[
  {
    "path": ".editorconfig",
    "content": "root = true\n\n[*]\ncharset = utf-8\nend_of_line = lf\nindent_size = 4\nindent_style = space\ninsert_final_newline = false\nmax_line_length = 120\ntab_width = 4\nij_continuation_indent_size = 8\nij_formatter_off_tag = @formatter:off\nij_formatter_on_tag = @formatter:on\nij_formatter_tags_enabled = false\nij_smart_tabs = false\nij_wrap_on_typing = false\n\n[*.java]\nij_java_align_consecutive_assignments = false\nij_java_align_consecutive_variable_declarations = false\nij_java_align_group_field_declarations = false\nij_java_align_multiline_annotation_parameters = false\nij_java_align_multiline_array_initializer_expression = false\nij_java_align_multiline_assignment = false\nij_java_align_multiline_binary_operation = false\nij_java_align_multiline_chained_methods = false\nij_java_align_multiline_extends_list = false\nij_java_align_multiline_for = true\nij_java_align_multiline_method_parentheses = false\nij_java_align_multiline_parameters = true\nij_java_align_multiline_parameters_in_calls = false\nij_java_align_multiline_parenthesized_expression = false\nij_java_align_multiline_records = true\nij_java_align_multiline_resources = true\nij_java_align_multiline_ternary_operation = false\nij_java_align_multiline_text_blocks = false\nij_java_align_multiline_throws_list = false\nij_java_align_subsequent_simple_methods = false\nij_java_align_throws_keyword = false\nij_java_annotation_parameter_wrap = off\nij_java_array_initializer_new_line_after_left_brace = false\nij_java_array_initializer_right_brace_on_new_line = false\nij_java_array_initializer_wrap = off\nij_java_assert_statement_colon_on_next_line = false\nij_java_assert_statement_wrap = off\nij_java_assignment_wrap = off\nij_java_binary_operation_sign_on_next_line = false\nij_java_binary_operation_wrap = off\nij_java_blank_lines_after_anonymous_class_header = 0\nij_java_blank_lines_after_class_header = 0\nij_java_blank_lines_after_imports = 1\nij_java_blank_lines_after_package = 1\nij_java_blank_lines_around_class = 1\nij_java_blank_lines_around_field = 0\nij_java_blank_lines_around_field_in_interface = 0\nij_java_blank_lines_around_initializer = 1\nij_java_blank_lines_around_method = 1\nij_java_blank_lines_around_method_in_interface = 1\nij_java_blank_lines_before_class_end = 0\nij_java_blank_lines_before_imports = 1\nij_java_blank_lines_before_method_body = 0\nij_java_blank_lines_before_package = 0\nij_java_block_brace_style = end_of_line\nij_java_block_comment_at_first_column = true\nij_java_call_parameters_new_line_after_left_paren = false\nij_java_call_parameters_right_paren_on_new_line = false\nij_java_call_parameters_wrap = off\nij_java_case_statement_on_separate_line = true\nij_java_catch_on_new_line = false\nij_java_class_annotation_wrap = split_into_lines\nij_java_class_brace_style = end_of_line\nij_java_class_count_to_use_import_on_demand = 5\nij_java_class_names_in_javadoc = 1\nij_java_do_not_indent_top_level_class_members = false\nij_java_do_not_wrap_after_single_annotation = false\nij_java_do_while_brace_force = never\nij_java_doc_add_blank_line_after_description = true\nij_java_doc_add_blank_line_after_param_comments = false\nij_java_doc_add_blank_line_after_return = false\nij_java_doc_add_p_tag_on_empty_lines = true\nij_java_doc_align_exception_comments = true\nij_java_doc_align_param_comments = true\nij_java_doc_do_not_wrap_if_one_line = false\nij_java_doc_enable_formatting = true\nij_java_doc_enable_leading_asterisks = true\nij_java_doc_indent_on_continuation = false\nij_java_doc_keep_empty_lines = true\nij_java_doc_keep_empty_parameter_tag = true\nij_java_doc_keep_empty_return_tag = true\nij_java_doc_keep_empty_throws_tag = true\nij_java_doc_keep_invalid_tags = true\nij_java_doc_param_description_on_new_line = false\nij_java_doc_preserve_line_breaks = false\nij_java_doc_use_throws_not_exception_tag = true\nij_java_else_on_new_line = false\nij_java_entity_dd_suffix = EJB\nij_java_entity_eb_suffix = Bean\nij_java_entity_hi_suffix = Home\nij_java_entity_lhi_prefix = Local\nij_java_entity_lhi_suffix = Home\nij_java_entity_li_prefix = Local\nij_java_entity_pk_class = java.lang.String\nij_java_entity_vo_suffix = VO\nij_java_enum_constants_wrap = off\nij_java_extends_keyword_wrap = off\nij_java_extends_list_wrap = off\nij_java_field_annotation_wrap = split_into_lines\nij_java_finally_on_new_line = false\nij_java_for_brace_force = never\nij_java_for_statement_new_line_after_left_paren = false\nij_java_for_statement_right_paren_on_new_line = false\nij_java_for_statement_wrap = off\nij_java_generate_final_locals = false\nij_java_generate_final_parameters = false\nij_java_if_brace_force = never\nij_java_imports_layout = *,|,javax.**,java.**,|,$*\nij_java_indent_case_from_switch = true\nij_java_insert_inner_class_imports = false\nij_java_insert_override_annotation = true\nij_java_keep_blank_lines_before_right_brace = 2\nij_java_keep_blank_lines_between_package_declaration_and_header = 2\nij_java_keep_blank_lines_in_code = 2\nij_java_keep_blank_lines_in_declarations = 2\nij_java_keep_control_statement_in_one_line = true\nij_java_keep_first_column_comment = true\nij_java_keep_indents_on_empty_lines = false\nij_java_keep_line_breaks = true\nij_java_keep_multiple_expressions_in_one_line = false\nij_java_keep_simple_blocks_in_one_line = false\nij_java_keep_simple_classes_in_one_line = false\nij_java_keep_simple_lambdas_in_one_line = false\nij_java_keep_simple_methods_in_one_line = false\nij_java_label_indent_absolute = false\nij_java_label_indent_size = 0\nij_java_lambda_brace_style = end_of_line\nij_java_layout_static_imports_separately = true\nij_java_line_comment_add_space = false\nij_java_line_comment_at_first_column = true\nij_java_message_dd_suffix = EJB\nij_java_message_eb_suffix = Bean\nij_java_method_annotation_wrap = split_into_lines\nij_java_method_brace_style = end_of_line\nij_java_method_call_chain_wrap = off\nij_java_method_parameters_new_line_after_left_paren = false\nij_java_method_parameters_right_paren_on_new_line = false\nij_java_method_parameters_wrap = off\nij_java_modifier_list_wrap = false\nij_java_names_count_to_use_import_on_demand = 3\nij_java_new_line_after_lparen_in_record_header = false\nij_java_packages_to_use_import_on_demand = java.awt.*,javax.swing.*\nij_java_parameter_annotation_wrap = off\nij_java_parentheses_expression_new_line_after_left_paren = false\nij_java_parentheses_expression_right_paren_on_new_line = false\nij_java_place_assignment_sign_on_next_line = false\nij_java_prefer_longer_names = true\nij_java_prefer_parameters_wrap = false\nij_java_record_components_wrap = normal\nij_java_repeat_synchronized = true\nij_java_replace_instanceof_and_cast = false\nij_java_replace_null_check = true\nij_java_replace_sum_lambda_with_method_ref = true\nij_java_resource_list_new_line_after_left_paren = false\nij_java_resource_list_right_paren_on_new_line = false\nij_java_resource_list_wrap = off\nij_java_rparen_on_new_line_in_record_header = false\nij_java_session_dd_suffix = EJB\nij_java_session_eb_suffix = Bean\nij_java_session_hi_suffix = Home\nij_java_session_lhi_prefix = Local\nij_java_session_lhi_suffix = Home\nij_java_session_li_prefix = Local\nij_java_session_si_suffix = Service\nij_java_space_after_closing_angle_bracket_in_type_argument = false\nij_java_space_after_colon = true\nij_java_space_after_comma = true\nij_java_space_after_comma_in_type_arguments = true\nij_java_space_after_for_semicolon = true\nij_java_space_after_quest = true\nij_java_space_after_type_cast = true\nij_java_space_before_annotation_array_initializer_left_brace = false\nij_java_space_before_annotation_parameter_list = false\nij_java_space_before_array_initializer_left_brace = false\nij_java_space_before_catch_keyword = true\nij_java_space_before_catch_left_brace = true\nij_java_space_before_catch_parentheses = true\nij_java_space_before_class_left_brace = true\nij_java_space_before_colon = true\nij_java_space_before_colon_in_foreach = true\nij_java_space_before_comma = false\nij_java_space_before_do_left_brace = true\nij_java_space_before_else_keyword = true\nij_java_space_before_else_left_brace = true\nij_java_space_before_finally_keyword = true\nij_java_space_before_finally_left_brace = true\nij_java_space_before_for_left_brace = true\nij_java_space_before_for_parentheses = true\nij_java_space_before_for_semicolon = false\nij_java_space_before_if_left_brace = true\nij_java_space_before_if_parentheses = true\nij_java_space_before_method_call_parentheses = false\nij_java_space_before_method_left_brace = true\nij_java_space_before_method_parentheses = false\nij_java_space_before_opening_angle_bracket_in_type_parameter = false\nij_java_space_before_quest = true\nij_java_space_before_switch_left_brace = true\nij_java_space_before_switch_parentheses = true\nij_java_space_before_synchronized_left_brace = true\nij_java_space_before_synchronized_parentheses = true\nij_java_space_before_try_left_brace = true\nij_java_space_before_try_parentheses = true\nij_java_space_before_type_parameter_list = false\nij_java_space_before_while_keyword = true\nij_java_space_before_while_left_brace = true\nij_java_space_before_while_parentheses = true\nij_java_space_inside_one_line_enum_braces = false\nij_java_space_within_empty_array_initializer_braces = false\nij_java_space_within_empty_method_call_parentheses = false\nij_java_space_within_empty_method_parentheses = false\nij_java_spaces_around_additive_operators = true\nij_java_spaces_around_assignment_operators = true\nij_java_spaces_around_bitwise_operators = true\nij_java_spaces_around_equality_operators = true\nij_java_spaces_around_lambda_arrow = true\nij_java_spaces_around_logical_operators = true\nij_java_spaces_around_method_ref_dbl_colon = false\nij_java_spaces_around_multiplicative_operators = true\nij_java_spaces_around_relational_operators = true\nij_java_spaces_around_shift_operators = true\nij_java_spaces_around_type_bounds_in_type_parameters = true\nij_java_spaces_around_unary_operator = false\nij_java_spaces_within_angle_brackets = false\nij_java_spaces_within_annotation_parentheses = false\nij_java_spaces_within_array_initializer_braces = false\nij_java_spaces_within_braces = false\nij_java_spaces_within_brackets = false\nij_java_spaces_within_cast_parentheses = false\nij_java_spaces_within_catch_parentheses = false\nij_java_spaces_within_for_parentheses = false\nij_java_spaces_within_if_parentheses = false\nij_java_spaces_within_method_call_parentheses = false\nij_java_spaces_within_method_parentheses = false\nij_java_spaces_within_parentheses = false\nij_java_spaces_within_switch_parentheses = false\nij_java_spaces_within_synchronized_parentheses = false\nij_java_spaces_within_try_parentheses = false\nij_java_spaces_within_while_parentheses = false\nij_java_special_else_if_treatment = true\nij_java_subclass_name_suffix = Impl\nij_java_ternary_operation_signs_on_next_line = false\nij_java_ternary_operation_wrap = off\nij_java_test_name_suffix = Test\nij_java_throws_keyword_wrap = off\nij_java_throws_list_wrap = off\nij_java_use_external_annotations = false\nij_java_use_fq_class_names = false\nij_java_use_relative_indents = false\nij_java_use_single_class_imports = true\nij_java_variable_annotation_wrap = off\nij_java_visibility = public\nij_java_while_brace_force = never\nij_java_while_on_new_line = false\nij_java_wrap_comments = false\nij_java_wrap_first_method_in_call_chain = false\nij_java_wrap_long_lines = false\n"
  },
  {
    "path": ".gitignore",
    "content": "# Compiled class file\n*.class\n\n# Gradle\n.gradle/\nbuild/\n\n# Eclipse\n.setup/\nbin/\n.classpath\n.project\n\n# IntelliJ\n*.iml\n.idea/\nout/\n\n# VS Code\n.settings/\n\n# Radon\nradon.log\nradon.log.lck\n"
  },
  {
    "path": ".travis.yml",
    "content": "language: java\ninstall: true\ndist: trusty\n\njdk:\n  - oraclejdk11\n\nscript:\n  - ./gradlew build\n"
  },
  {
    "path": "CONTRIBUTING.md",
    "content": "# Radon Contribution Guide\n\n## Table of Contents\n* [GitHub](#github)\n    * [Issue Reports](#issue-reports)\n    * [Pull Requests](#pull-requests)\n* [Styleguides](#styleguides)\n    * [Git Commit Messages](#git-commit-messages)\n    * [Java Styleguide](#java-styleguide)\n    * [Transformer Documentation](#transformer-documentation)\n\n## GitHub\n### Issue Reports\nFound an issue with Radon? Awesome. Make sure you read the following before reporting it:\n\n#### Before Submitting an Issue Report\n* **Check the FAQ in the readme**. Radon has had numerous \"bugs/errors/issues\" reported which were completely\npreventable due to configuration.\n* **Check if the issue has already been reported**. Should said issue already exist, add a comment on the issue rather\nthan starting a new one.\n* **Check if you made a YAML error**. You can use an online YAML verifier like\n[this one](http://www.yamllint.com/) to catch errors quickly.\n* **If possible, please spend a little time debugging before reporting the issue!** This could save a ton of time for\nyou and anyone who decides to fix the bug. If you are able to locate the precise issue in Radon's codebase, chances are \na fix can be implemented much sooner.\n\n#### Submitting an Issue Report as a Bug\nAll bugs are tracked as GitHub issues for organizational purposes. For that reason, please do not report bugs in the\nDiscord and expect a fix as I am prone to forgetfulness.\n\nWhen opening a bug report, please make sure to follow the below:\n* **Use a clear and descriptive title**.\n    * Example of a **good** title: \"Using the FastInvokedynamic transformer on any Spigot plugin results in NPE from\n      radon\"\n    * Example of a **good** title: \"Adding an exclusion hangs the renamer\"\n    * Example of a **bad** title: \"Adding an exclusions causes bug\"\n    * Example of a **bad** title: \"Radon bug\"\n* **Be as specific and descriptive as possible when describing the issue**. It really annoys me and other people when\nyour description is vague. I should be able to understand exactly what the issue is with no questions asked.\n* **Be as detailed as you can when describing the expected behavior.** Same reason as above.\n* **Provide the git commit hash you build Radon from.** This allows me or anyone investigating the issue to instantly\nfind the version of Radon you are using. Saying \"latest\" or similar will result in an instant close of your issue with\nno help provided. If you're not going to make an effort to make a proper report, then I'm not going to make an effort to\nhelp.\n* **Provide the exact configuration used in code blocks**. This means no blanking out lines and no screenshots. I\napologize in advance if privacy is desired, but issues that could have been solved in 5 seconds have lasted multiple\nhours because people hid parts of their configuration while requesting help.\n* **Provide the relevant errors and exceptions in code blocks.** Please do not put screenshots here and make sure to put\neach error in its own markdown code block. Also, please make sure you specify when the error happens.\n* **Be as specific and detailed as possible when doing reproduction steps**. This is where some of the worst\nmiscommunications have happened which resulted in a ton of wasted time. Please just put in a little effort so that I\nknow *exactly* what you did.\n* **Attach / link what you attempted to obfuscate**. This is a mandatory for all software problems created by the\nobfuscation. If you are unable to attach or link the software you obfuscated, attach a proof-of-concept JAR which also\ncauses the same issue to happen. If possible, please also provide the obfuscated output.\n\nExtra: [this video](https://www.youtube.com/watch?v=53zkBvL4ZB4&vl=en) by\n[LiveOverflow](https://github.com/LiveOverflow) and this [webpage](http://www.catb.org/esr/faqs/smart-questions.html)\nare good references for properly asking a question.\n\n#### Submitting an Issue Report as an Enhancement / Feature Request\nAll enhancements and feature requests are tracked as GitHub issues for organizational purposes.\n\nWhen opening an enhancement / feature request, please make sure to follow the below:\n* **Use a clear and descriptive title**. Please also prefix the title with [Enhancement/FR] so there's no room for\nconfusion.\n    * Example of a **good** title: \"[Enhancement] Use dynamic decryption methods for XXXX instead of YYYY\"\n    * Example of a **good** title: \"[Feature Request] Transformer to flatten the CFG\"\n    * Example of a **bad** title: \"suggestion\"\n    * Example of a **bad** title: \"thing to make radon better\"\n* **Provide an in-depth description of what the feature should do.** You need to be as descriptive as possible to the\npoint where people shouldn't have to ask question to understand what the feature/enhancement will do.\n\n#### Pull Requests\nPull requests should fulfill one of the following:\n* Spelling / grammatical errors in documentation, Javadocs, or markdown files.\n* Fix issues reported on the issue tracker.\n* Implement an enhancement / feature request on the issue tracker.\n    * If a transformer is implemented, it needs to be added as an enum field to\n        1. `xyz.itzsomebody.radon.transformers.Transformers` and\n        2. (Optional) Be documented accordingly.\n* Update code or documentation to adhere to the specified style guides.\n* Replace poorly-written or spaghetti code with properly-written and thought-out code.\n\nThe rules for guidelines are pretty simple:\n* Follow the style guides.\n* Fix your commits should status checks fail.\n* If the PR adds features / code, make sure you also appropriately document said additions.\n* No need to squash commits -- I will personally do that if I think it's necessary.\n\n## Style guides\n#### Git Commit Messages\n* Use present tense.\n* Use the imperative mood.\n\n#### Java\nAll Java code should adhere to the provided EditorConfig file. Even though the column limit is set to 120, feel free to\nignore that.\n\n#### Markdown\nAll markdown files are required to be hard-wrapped at 120 characters. The only exceptions are extremely long URLs and\ncode snippets.\n"
  },
  {
    "path": "LICENSE",
    "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 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 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 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 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 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 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 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": "README.md",
    "content": "# [Abandoned] Radon Java Bytecode Obfuscator\n\n## Radon is no longer maintained\n\nIt's important to note that Radon is intended for __***experimentation only***__. If your software breaks in production\nbecause you protected it with Radon then that is completely on you.\n\nIf you have a quick question about how something works, you can join my [Discord](https://discord.gg/RfuxTea)\nserver and ask.\n\nThis project is **not** likely to be production-safe nor bug free. If you would\nlike some pointers to production-safe (more or less) and less buggy Java\nbytecode obfuscators that are properly maintained, I would suggest one of these:\n* [Proguard](https://www.guardsquare.com/en/products/proguard) (mostly only\nclass/method/field name obfuscation)\n* [Skidfuscator](https://github.com/terminalsin/skidfuscator-java-obfuscator) - [Discord](https://discord.gg/QJC9g8fBU9)\n* [Zelix KlassMaster](http://www.zelix.com/)\n\nSince we're on the topic of obfuscation, consider taking a look at\n[Recaf](https://github.com/Col-E/Recaf) ([Discord](https://discord.gg/Bya5HaA))\nif you have not already. Recaf is actively maintained by the contributers to\nstay on top of a variety obfuscation techniques found in the wild. I would\nhighly recommend learning to use Recaf for those who are into Java reverse-engineering.\n\n[Skidfuscator](https://github.com/terminalsin/skidfuscator-java-obfuscator) is probably\none of the most promising Java bytecode obfuscation projects I have seen and has a much\nmore sanely-managed codebase than most obfuscators do (including Radon). I would recommend\nanyone trying to get into Java obfuscation to spend time learning how Skidfuscator works.\n\nAnother resource (slightly dated, but still a good amount of information) is\nGenericException's [SkidSuite](https://github.com/GenericException/SkidSuite) repo.\nSome common cheap obfuscation techniques that have become more common in the last \nfew years are documented there which anyone who is interested in Java reverse-engineering\nshould know.\n\nAdditionally, here are some other obfuscators/protectors for Java that you could\ncheck out for fun or learning (though not necessarily I would recommend using are):\n* [Allatori](http://www.allatori.com/) - Commericial. Somewhat popular choice in industry.\n* [avaj](https://github.com/cg-dot/avaj) - FOSS. Has a nice way of generating decryption subroutines on string constants. Also has some CFG flattening which is always nice to see.\n* [BisGuard](http://www.bisguard.com/) - Commercial. Relies entirely on class encryption (last time I checked, at least) so protection has quite a bit of room for improvement.\n* [Bozar](https://github.com/vimasig/Bozar) - Points for FOSS. Has some cheap tricks that I have seen being used in the Minecraft community.\n* [Branchlock](https://branchlock.net/) - Commercial. Shows up a bit in the Minecraft community.\n* [Caesium](https://github.com/sim0n/Caesium) - FOSS. Has a transformer that implements a well-known HTML injection into any Java reverse-engineering tool that parses HTML tags. \n* [ClassGuard](https://zenofx.com/classguard/) - Commercial. Relies mostly on class encryption with hardcoded AES keys in native libs. Pretty easy IDA/Binary Ninja/Ghidra exercise if you want to flex on your blog on something. \n* [DashO](https://www.preemptive.com/products/dasho/overview) - Commercial. Shows up a bit in industry and has some interesting ideas (albeit probably outdated) in flow obfuscation.\n* [JBCO](http://www.sable.mcgill.ca/JBCO/) - FOSS. Some interesting flow obfuscation techniques that still work in modern Java. Based on the [Soot](https://github.com/soot-oss/soot) library which is also something worthwhile checking out.\n* [JObf](https://github.com/superblaubeere27/obfuscator) - FOSS. Pretty outdated. Some of the transformations done show up in the Minecraft community so it can be worthwhile spending a bit of time takinng a look at this.\n* [JObfuscator](https://www.pelock.com/products/jobfuscator) - Commericial. Never seen this used before so I cannot really give any comments.\n* [NeonObf](https://github.com/MoofMonkey/NeonObf) - Mostly points for FOSS.  Made up of the easier to defeat obfuscation techniques.  NeonObf is also the name inspiration for Radon.\n* [Obzcure](https://obzcu.re/) [Discord](https://discordapp.com/invite/fUCPxq8) (Dead) - Commericial. Web-based obfuscation service with some inspiration taken from Radon and [SkidSuite2](https://github.com/GenericException/SkidSuite/tree/master/archive/skidsuite-2). Used to go by the name \"SpigotProtect\" so you might see some Spigot plugins using the obfuscation from this product if you look around hard enough.\n* [Paramorphism](https://paramorphism.serenity.enterprises/) - [Discord](https://discordapp.com/invite/k9DPvEy) (Dead) - Commerical. Was one of the most unusual and unique obfuscators at the time it was an active project in that relied a lot more on the JVM's unusual way of loading JAR archives including zip entries with duplicated names and the [fake directory trick](https://github.com/x4e/fakedirectory). Used to be more commonly used before people started ripping ideas from Paramorphism.\n* [qProtect](https://mdma.dev/) - Commericial. Implements a lot of the more common obfuscation techiques into a single tool. Shows up a bit in the Minecraft community.\n* [Sandmark](http://sandmark.cs.arizona.edu) - FOSS. Really old obfuscator research project led by Christian Collberg at the University of Arizona. Some interesting ideas in watermarking are here and some of the flow obfuscation ideas are good.\n* [SkidSuite2](https://github.com/GenericException/SkidSuite/tree/master/archive/skidsuite-2) - FOSS. Some pretty basic obfuscation techniques, nothing too special.\n* [Stringer](https://jfxstore.com/stringer/) - Commercial. Pretty infamous for its complicated AES-based encryption/decryption routines and price. Does not really offer a whole lot of protection, but sometimes does show up in industry.  \n* [yGuard](https://www.yworks.com/products/yguard) - FOSS. Functionally equivalent to ProGuard as far as I can tell.\n* [zProtect](https://zprotect.dev/) - [Discord](https://discord.com/invite/dnGKGuwvGH) - Commercial. Newer obfuscator. I have not seen any samples from it so I do not have an opinion on it.\n\n## Build Instructions\n\nRun the following (and hope nothing breaks):\n```\n./gradlew build\n```\nOr if you're on Windows:\n```\ngradlew.bat build\n```\n\nShould that somehow not work, use the following instead:\n```\n./gradlew clean shadowJar\n```\n\nP.S. For those wondering why there aren't any prebuilt releases, if you can't figure out how to use Gradle, should you really be using an obfuscator? ;) [end of snarkiness]\n\n## FAQ\n\n* **Q: Is this uncrackable/undeobfuscatable?**  \n*A: No. Nothing is impossible to deobfuscate or reverse-engineer. Furthermore, Radon is far from being hard to \n  deobfuscate. On a scale of 1 to 10 on how hard Radon is to deobfuscate, I'd say 2 in the best possible scenario.*\n  \n* **Q: Why is this open-sourced?**  \n*A: I made Radon as a way to experiment with obfuscation and to become familiar with the JVM bytecode instruction set \n  and as a codebase if anyone wants to mess around. Furthermore, I strongly support the FOSS ideology.*\n  \n* **Q: Doesn't Radon being open-sourced make it easier to deobfuscate?**  \n*A: Probably.*\n  \n* **Q: Can Spring apps be obfuscated with this?**  \n*A: Out of the box, no. Starting from Radon 3, I will never add support for Spring or multiversion JARs.*\n  \n* **Q: What does '... \"org/somelib/TableFactoryBuilder\" not found in classpath' mean?**  \n*A: Radon internally determines how to construct certain entities in the classfile based on the class hierarchy of the \n  JAR being obfuscated. For this reason, Radon needs access to library classes used by the project. Make sure you add \n  the appropriate libraries so this doesn't show up.*\n  \n* **Q: Can I use all transformers for maximum protection?**  \n*A: You could, but you should note that it's very likely that the program will break and/or there will be a large \n  overhead in file size and/or performance.*\n  \n* **Q: Why do certain combinations of transformers break the program?**  \n*A: Radon is intended to be an experimental project, not a commercial product protector. Not all features are meant to \n  work together.*\n  \n* **Q: What version of Java is required to run Radon 3?**  \n*A: Java 11+.*\n  \n* **Q: What version of Java is my software required to written in to work with Radon?**  \n*A: Radon can theoretically obfuscate software written in any Java version provided that the `asm` library is compatible\n  with the classfile version.*\n  \n* **Q: Does Radon support Android?**  \n*A: While the answer is technically yes, I will not provide support for issues pertaining to Android apps.*\n  \n* **Q: Does Radon have Gradle, Maven, or Ant integration?**  \n*A: No. You are more than welcome to make a PR to add such functionality if desired.*\n  \n* **Q: Will there be a GUI for Radon 3?**  \n*A: Yes, however, a GUI is very low on my priority list, so it might be awhile before one is actually made.*\n\n* **Q: Will there be a Radon 4?**  \n*A: Probably not.*\n\n## License\n\nGNU General Public License v3.0 (The cancer license)\n"
  },
  {
    "path": "build.gradle",
    "content": "/*\n * Radon - An open-source Java obfuscator\n * Copyright (C) 2021 ItzSomebody\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, either version 3 of the License, or\n * (at your option) any later version.\n *\n * This program is distributed in the hope that it will be 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.  If not, see <http://www.gnu.org/licenses/>\n */\n\nplugins {\n    id 'com.github.johnrengelman.shadow' version '5.1.0'\n}\n\ndefaultTasks 'clean', 'test', 'build'\n\next {\n    // ASM\n    asmVer = '9.4'\n    asm = 'org.ow2.asm:asm:' + asmVer\n    asmAnalysis = 'org.ow2.asm:asm-analysis:' + asmVer\n    asmCommons = 'org.ow2.asm:asm-commons:' + asmVer\n    asmTree = 'org.ow2.asm:asm-tree:' + asmVer\n    asmUtil = 'org.ow2.asm:asm-util:' + asmVer\n\n    // junit\n    junit = 'junit:junit:4.12'\n\n    // Annotations\n    annotations = 'org.jetbrains:annotations:20.1.0'\n\n    // Jackson\n    jackson = 'com.fasterxml.jackson.core:jackson-databind:2.12.2'\n\n    // Java version\n    javaVer = 11\n}\n\nallprojects {\n    // Project group and version\n    group 'xyz.itzsomebody'\n    version '3.0.0-SNAPSHOT'\n\n    // Compile using UTF-8 encoding\n    tasks.withType(JavaCompile) {\n        options.encoding = 'UTF-8'\n    }\n\n    repositories {\n        mavenCentral()\n    }\n}\n\n"
  },
  {
    "path": "docs/changelog.md",
    "content": "# Changelog\n\n## 3.0.0 - Full rewrite\nThere are multiple turning points with the release of Radon 3.0.0 compared to all previous versions of Radon.\n\n### Differences between Radon 3 and previous versions\n* Radon 3 is written in Java 11. Every previous version of Radon was written in Java 8.\n* Some of Radon 3's features are not portable to different JVMs whereas every previous version of Radon was intended for\nHotSpot.\n* Radon 3 removes all \"optimizers\" from Radon 2. If you need some kind of optimization done, use ProGuard instead.\n* Compared to Radon 2, Radon 3 can be significantly more risky in how it performs transformations on bytecode.\n* Radon 2 uses the GitHub wiki for documentation of transformers and usage. Radon 3 has no usage guide and uses GitHub\npages for documentation of transformers (however, the wiki will not be removed for ease of reference).\n* Radon 3 removes delegation for \"shrinking\" transformers via the above point.\n* Radon 3 adheres to a style guide (sort of) whereas no previous version of Radon has.\n* Radon 3 reimplements the exclusion system in a much more efficient matter.\n* Radon 3 introduces a high-level code generator to remove some reliance on ASMifier generated code.\n"
  },
  {
    "path": "docs/exclusions.md",
    "content": "# Exclusions\n\n**Note: You will need a basic understanding of internal class/method/field names to understand how Radon processes \nexclusions.**\n\nExclusions in Radon are regex-based and are matched using the code below:\n\n```java\npublic boolean matches(String other, ExclusionType type) {\n    if (type == ExclusionType.GLOBAL || type == exclusionType) {\n        return true;\n    }\n\n    return invert != matcher.reset(other).matches();\n}\n```\n\n**The use of `java.util.regex.Matcher#matches()` is intentional and should be considered whilst creating an exclusion.**\n\n* When **classes** are checked for exclusion, the internal name is passed into `other`. e.g.\n```java\n// Check for java.lang.Object and java.lang.String\nExclusion exclusion = new Exclusion(\"java/lang/(Object|String)\");\n\nSystem.out.println(exclusion.matches(\"java/lang/Object\")); // true\nSystem.out.println(exclusion.matches(\"java/lang/String\")); // true\nSystem.out.println(exclusion.matches(\"java/lang/String isEmpty()Z\")); // false\nSystem.out.println(exclusion.matches(\"java/lang/Number\")); // false\n```\n```java\n// Check for all classes that start with \"java.lang\" in their internal name\nExclusion exclusion = new Exclusion(\"java/lang.*\");\n\nSystem.out.println(exclusion.matches(\"java/lang/Object\")); // true\nSystem.out.println(exclusion.matches(\"java/lang/String\")); // true\nSystem.out.println(exclusion.matches(\"java/lang/String isEmpty()Z\")); // true - be careful when playing with \".*\"\nSystem.out.println(exclusion.matches(\"java/lang/Number\")); // true\n```\n\n* When **methods** are checked for exclusion, `<internal owner name> <method name><internal method description>` is\npassed into `other`. e.g.\n```java\n// Check for java.lang.String.isEmpty()\nExclusion exclusion = new Exclusion(\"java/lang/String isEmpty\\\\(\\\\)Z\");\n\nSystem.out.println(exclusion.matches(\"java/lang/String isEmpty()Z\")); // true\nSystem.out.println(exclusion.matches(\"java/lang/String toCharArray()[C\")); // false\n```\n* When **fields** are checked for exclusion, `<internal owner name> <field name> <internal field description>` is\npassed into `other`. e.g.\n```java\n// Check for java.lang.System.out\nExclusion exclusion = new Exclusion(\"java/lang/System out Ljava/io/PrintStream;\");\n\nSystem.out.println(exclusion.matches(\"java/lang/System out Ljava/lang/PrintStream;\")); // true\nSystem.out.println(exclusion.matches(\"java/lang/System err Ljava/lang/PrintStream;\")); // false\n```\n"
  },
  {
    "path": "docs/index.md",
    "content": "# Radon Java Obfuscator [![Build Status](https://travis-ci.org/ItzSomebody/Radon.svg?branch=master)](https://travis-ci.org/ItzSomebody/Radon)\n\nWelcome to the documentation page for the Radon Java bytecode obfuscator! Here you can find the documentation and\nvarious parts of stuff put into Radon's internals and transformers.\n\n* [Changelog](changelog.md)\n* [Exclusions](exclusions.md)\n* Transformers\n    * TODO\n"
  },
  {
    "path": "gradle/wrapper/gradle-wrapper.properties",
    "content": "distributionBase=GRADLE_USER_HOME\ndistributionPath=wrapper/dists\ndistributionUrl=https\\://services.gradle.org/distributions/gradle-7.5.1-bin.zip\nzipStoreBase=GRADLE_USER_HOME\nzipStorePath=wrapper/dists\n"
  },
  {
    "path": "gradlew",
    "content": "#!/usr/bin/env sh\n\n#\n# Copyright 2015 the original author or authors.\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#      https://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\n##############################################################################\n##\n##  Gradle start up script for UN*X\n##\n##############################################################################\n\n# Attempt to set APP_HOME\n# Resolve links: $0 may be a link\nPRG=\"$0\"\n# Need this for relative symlinks.\nwhile [ -h \"$PRG\" ] ; do\n    ls=`ls -ld \"$PRG\"`\n    link=`expr \"$ls\" : '.*-> \\(.*\\)$'`\n    if expr \"$link\" : '/.*' > /dev/null; then\n        PRG=\"$link\"\n    else\n        PRG=`dirname \"$PRG\"`\"/$link\"\n    fi\ndone\nSAVED=\"`pwd`\"\ncd \"`dirname \\\"$PRG\\\"`/\" >/dev/null\nAPP_HOME=\"`pwd -P`\"\ncd \"$SAVED\" >/dev/null\n\nAPP_NAME=\"Gradle\"\nAPP_BASE_NAME=`basename \"$0\"`\n\n# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.\nDEFAULT_JVM_OPTS='\"-Xmx64m\" \"-Xms64m\"'\n\n# Use the maximum available, or set MAX_FD != -1 to use that value.\nMAX_FD=\"maximum\"\n\nwarn () {\n    echo \"$*\"\n}\n\ndie () {\n    echo\n    echo \"$*\"\n    echo\n    exit 1\n}\n\n# OS specific support (must be 'true' or 'false').\ncygwin=false\nmsys=false\ndarwin=false\nnonstop=false\ncase \"`uname`\" in\n  CYGWIN* )\n    cygwin=true\n    ;;\n  Darwin* )\n    darwin=true\n    ;;\n  MINGW* )\n    msys=true\n    ;;\n  NONSTOP* )\n    nonstop=true\n    ;;\nesac\n\nCLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar\n\n\n# Determine the Java command to use to start the JVM.\nif [ -n \"$JAVA_HOME\" ] ; then\n    if [ -x \"$JAVA_HOME/jre/sh/java\" ] ; then\n        # IBM's JDK on AIX uses strange locations for the executables\n        JAVACMD=\"$JAVA_HOME/jre/sh/java\"\n    else\n        JAVACMD=\"$JAVA_HOME/bin/java\"\n    fi\n    if [ ! -x \"$JAVACMD\" ] ; then\n        die \"ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME\n\nPlease set the JAVA_HOME variable in your environment to match the\nlocation of your Java installation.\"\n    fi\nelse\n    JAVACMD=\"java\"\n    which java >/dev/null 2>&1 || die \"ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.\n\nPlease set the JAVA_HOME variable in your environment to match the\nlocation of your Java installation.\"\nfi\n\n# Increase the maximum file descriptors if we can.\nif [ \"$cygwin\" = \"false\" -a \"$darwin\" = \"false\" -a \"$nonstop\" = \"false\" ] ; then\n    MAX_FD_LIMIT=`ulimit -H -n`\n    if [ $? -eq 0 ] ; then\n        if [ \"$MAX_FD\" = \"maximum\" -o \"$MAX_FD\" = \"max\" ] ; then\n            MAX_FD=\"$MAX_FD_LIMIT\"\n        fi\n        ulimit -n $MAX_FD\n        if [ $? -ne 0 ] ; then\n            warn \"Could not set maximum file descriptor limit: $MAX_FD\"\n        fi\n    else\n        warn \"Could not query maximum file descriptor limit: $MAX_FD_LIMIT\"\n    fi\nfi\n\n# For Darwin, add options to specify how the application appears in the dock\nif $darwin; then\n    GRADLE_OPTS=\"$GRADLE_OPTS \\\"-Xdock:name=$APP_NAME\\\" \\\"-Xdock:icon=$APP_HOME/media/gradle.icns\\\"\"\nfi\n\n# For Cygwin or MSYS, switch paths to Windows format before running java\nif [ \"$cygwin\" = \"true\" -o \"$msys\" = \"true\" ] ; then\n    APP_HOME=`cygpath --path --mixed \"$APP_HOME\"`\n    CLASSPATH=`cygpath --path --mixed \"$CLASSPATH\"`\n    \n    JAVACMD=`cygpath --unix \"$JAVACMD\"`\n\n    # We build the pattern for arguments to be converted via cygpath\n    ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`\n    SEP=\"\"\n    for dir in $ROOTDIRSRAW ; do\n        ROOTDIRS=\"$ROOTDIRS$SEP$dir\"\n        SEP=\"|\"\n    done\n    OURCYGPATTERN=\"(^($ROOTDIRS))\"\n    # Add a user-defined pattern to the cygpath arguments\n    if [ \"$GRADLE_CYGPATTERN\" != \"\" ] ; then\n        OURCYGPATTERN=\"$OURCYGPATTERN|($GRADLE_CYGPATTERN)\"\n    fi\n    # Now convert the arguments - kludge to limit ourselves to /bin/sh\n    i=0\n    for arg in \"$@\" ; do\n        CHECK=`echo \"$arg\"|egrep -c \"$OURCYGPATTERN\" -`\n        CHECK2=`echo \"$arg\"|egrep -c \"^-\"`                                 ### Determine if an option\n\n        if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then                    ### Added a condition\n            eval `echo args$i`=`cygpath --path --ignore --mixed \"$arg\"`\n        else\n            eval `echo args$i`=\"\\\"$arg\\\"\"\n        fi\n        i=`expr $i + 1`\n    done\n    case $i in\n        0) set -- ;;\n        1) set -- \"$args0\" ;;\n        2) set -- \"$args0\" \"$args1\" ;;\n        3) set -- \"$args0\" \"$args1\" \"$args2\" ;;\n        4) set -- \"$args0\" \"$args1\" \"$args2\" \"$args3\" ;;\n        5) set -- \"$args0\" \"$args1\" \"$args2\" \"$args3\" \"$args4\" ;;\n        6) set -- \"$args0\" \"$args1\" \"$args2\" \"$args3\" \"$args4\" \"$args5\" ;;\n        7) set -- \"$args0\" \"$args1\" \"$args2\" \"$args3\" \"$args4\" \"$args5\" \"$args6\" ;;\n        8) set -- \"$args0\" \"$args1\" \"$args2\" \"$args3\" \"$args4\" \"$args5\" \"$args6\" \"$args7\" ;;\n        9) set -- \"$args0\" \"$args1\" \"$args2\" \"$args3\" \"$args4\" \"$args5\" \"$args6\" \"$args7\" \"$args8\" ;;\n    esac\nfi\n\n# Escape application args\nsave () {\n    for i do printf %s\\\\n \"$i\" | sed \"s/'/'\\\\\\\\''/g;1s/^/'/;\\$s/\\$/' \\\\\\\\/\" ; done\n    echo \" \"\n}\nAPP_ARGS=`save \"$@\"`\n\n# Collect all arguments for the java command, following the shell quoting and substitution rules\neval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS \"\\\"-Dorg.gradle.appname=$APP_BASE_NAME\\\"\" -classpath \"\\\"$CLASSPATH\\\"\" org.gradle.wrapper.GradleWrapperMain \"$APP_ARGS\"\n\nexec \"$JAVACMD\" \"$@\"\n"
  },
  {
    "path": "gradlew.bat",
    "content": "@rem\r\n@rem Copyright 2015 the original author or authors.\r\n@rem\r\n@rem Licensed under the Apache License, Version 2.0 (the \"License\");\r\n@rem you may not use this file except in compliance with the License.\r\n@rem You may obtain a copy of the License at\r\n@rem\r\n@rem      https://www.apache.org/licenses/LICENSE-2.0\r\n@rem\r\n@rem Unless required by applicable law or agreed to in writing, software\r\n@rem distributed under the License is distributed on an \"AS IS\" BASIS,\r\n@rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r\n@rem See the License for the specific language governing permissions and\r\n@rem limitations under the License.\r\n@rem\r\n\r\n@if \"%DEBUG%\" == \"\" @echo off\r\n@rem ##########################################################################\r\n@rem\r\n@rem  Gradle startup script for Windows\r\n@rem\r\n@rem ##########################################################################\r\n\r\n@rem Set local scope for the variables with windows NT shell\r\nif \"%OS%\"==\"Windows_NT\" setlocal\r\n\r\nset DIRNAME=%~dp0\r\nif \"%DIRNAME%\" == \"\" set DIRNAME=.\r\nset APP_BASE_NAME=%~n0\r\nset APP_HOME=%DIRNAME%\r\n\r\n@rem Resolve any \".\" and \"..\" in APP_HOME to make it shorter.\r\nfor %%i in (\"%APP_HOME%\") do set APP_HOME=%%~fi\r\n\r\n@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.\r\nset DEFAULT_JVM_OPTS=\"-Xmx64m\" \"-Xms64m\"\r\n\r\n@rem Find java.exe\r\nif defined JAVA_HOME goto findJavaFromJavaHome\r\n\r\nset JAVA_EXE=java.exe\r\n%JAVA_EXE% -version >NUL 2>&1\r\nif \"%ERRORLEVEL%\" == \"0\" goto init\r\n\r\necho.\r\necho ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.\r\necho.\r\necho Please set the JAVA_HOME variable in your environment to match the\r\necho location of your Java installation.\r\n\r\ngoto fail\r\n\r\n:findJavaFromJavaHome\r\nset JAVA_HOME=%JAVA_HOME:\"=%\r\nset JAVA_EXE=%JAVA_HOME%/bin/java.exe\r\n\r\nif exist \"%JAVA_EXE%\" goto init\r\n\r\necho.\r\necho ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%\r\necho.\r\necho Please set the JAVA_HOME variable in your environment to match the\r\necho location of your Java installation.\r\n\r\ngoto fail\r\n\r\n:init\r\n@rem Get command-line arguments, handling Windows variants\r\n\r\nif not \"%OS%\" == \"Windows_NT\" goto win9xME_args\r\n\r\n:win9xME_args\r\n@rem Slurp the command line arguments.\r\nset CMD_LINE_ARGS=\r\nset _SKIP=2\r\n\r\n:win9xME_args_slurp\r\nif \"x%~1\" == \"x\" goto execute\r\n\r\nset CMD_LINE_ARGS=%*\r\n\r\n:execute\r\n@rem Setup the command line\r\n\r\nset CLASSPATH=%APP_HOME%\\gradle\\wrapper\\gradle-wrapper.jar\r\n\r\n\r\n@rem Execute Gradle\r\n\"%JAVA_EXE%\" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% \"-Dorg.gradle.appname=%APP_BASE_NAME%\" -classpath \"%CLASSPATH%\" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS%\r\n\r\n:end\r\n@rem End local scope for the variables with windows NT shell\r\nif \"%ERRORLEVEL%\"==\"0\" goto mainEnd\r\n\r\n:fail\r\nrem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of\r\nrem the _cmd.exe /c_ return code!\r\nif  not \"\" == \"%GRADLE_EXIT_CONSOLE%\" exit 1\r\nexit /b 1\r\n\r\n:mainEnd\r\nif \"%OS%\"==\"Windows_NT\" endlocal\r\n\r\n:omega\r\n"
  },
  {
    "path": "settings.gradle",
    "content": "/*\n * Radon - An open-source Java obfuscator\n * Copyright (C) 2020 ItzSomebody\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, either version 3 of the License, or\n * (at your option) any later version.\n *\n * This program is distributed in the hope that it will be 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.  If not, see <http://www.gnu.org/licenses/>\n */\n\nrootProject.name = 'radon'\ninclude 'xyz.itzsomebody.codegen'\ninclude 'xyz.itzsomebody.radon'\ninclude 'xyz.itzsomebody.commons'\ninclude 'xyz.itzsomebody.radon.template'\n\n"
  },
  {
    "path": "xyz.itzsomebody.codegen/README.md",
    "content": "# CodeGen\n\nThis module contains radon's bytecode code generation utility. This is intended to reduce some of the heavy reliance\non the asm-tree API and ASMifier, and is based on the airlift bytecode generation library.\n"
  },
  {
    "path": "xyz.itzsomebody.codegen/build.gradle",
    "content": "/*\n * Radon - An open-source Java obfuscator\n * Copyright (C) 2021 ItzSomebody\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, either version 3 of the License, or\n * (at your option) any later version.\n *\n * This program is distributed in the hope that it will be 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.  If not, see <http://www.gnu.org/licenses/>\n */\n\nplugins {\n    id 'java'\n}\n\nsourceCompatibility = javaVer\n\ndependencies {\n    implementation annotations\n    implementation asm\n    implementation asmTree\n    testImplementation junit\n}\n"
  },
  {
    "path": "xyz.itzsomebody.codegen/src/main/java/xyz/itzsomebody/codegen/BytecodeBlock.java",
    "content": "/*\n * Radon - An open-source Java obfuscator\n * Copyright (C) 2021 ItzSomebody\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, either version 3 of the License, or\n * (at your option) any later version.\n *\n * This program is distributed in the hope that it will be 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.  If not, see <http://www.gnu.org/licenses/>\n */\n\npackage xyz.itzsomebody.codegen;\n\nimport org.objectweb.asm.tree.InsnList;\nimport xyz.itzsomebody.codegen.expressions.predefined.IRReturnExpression;\nimport xyz.itzsomebody.codegen.instructions.CompilableNode;\nimport xyz.itzsomebody.codegen.instructions.SimpleNode;\n\nimport java.util.ArrayList;\nimport java.util.List;\n\npublic class BytecodeBlock {\n    private final List<CompilableNode> nodes = new ArrayList<>();\n\n    public BytecodeBlock append(BytecodeBlock block) {\n        nodes.addAll(block.nodes);\n        return this;\n    }\n\n    public BytecodeBlock append(CompilableNode node) {\n        nodes.add(node);\n        return this;\n    }\n\n    public InsnList compile() {\n        var insns = new InsnList();\n        nodes.forEach(node -> insns.add(node.getNode()));\n        return insns;\n    }\n\n    public BytecodeBlock voidReturn(){\n        nodes.add(SimpleNode.RETURN_VOID);\n        return this;\n    }\n\n    public List<CompilableNode> getNodes() {\n        return nodes;\n    }\n}\n"
  },
  {
    "path": "xyz.itzsomebody.codegen/src/main/java/xyz/itzsomebody/codegen/GenerationContext.java",
    "content": "/*\n * Radon - An open-source Java obfuscator\n * Copyright (C) 2021 ItzSomebody\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, either version 3 of the License, or\n * (at your option) any later version.\n *\n * This program is distributed in the hope that it will be 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.  If not, see <http://www.gnu.org/licenses/>\n */\n\npackage xyz.itzsomebody.codegen;\n\nimport xyz.itzsomebody.codegen.expressions.IRVariable;\n\npublic class GenerationContext {\n    private int slotOffset = 0;\n\n    public void setSlotOffset(int slotOffset) {\n        this.slotOffset = slotOffset;\n    }\n\n    public IRVariable newVariable(WrappedType type) {\n        var variable = new IRVariable(type, slotOffset);\n        slotOffset += type.getType().getSize();\n        return variable;\n    }\n\n    public IRVariable newVariable(Class<?> clazz) {\n        return newVariable(WrappedType.from(clazz));\n    }\n}\n"
  },
  {
    "path": "xyz.itzsomebody.codegen/src/main/java/xyz/itzsomebody/codegen/Utils.java",
    "content": "/*\n * Radon - An open-source Java obfuscator\n * Copyright (C) 2021 ItzSomebody\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, either version 3 of the License, or\n * (at your option) any later version.\n *\n * This program is distributed in the hope that it will be 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.  If not, see <http://www.gnu.org/licenses/>\n */\n\npackage xyz.itzsomebody.codegen;\n\nimport org.objectweb.asm.Type;\nimport org.objectweb.asm.tree.LabelNode;\nimport org.objectweb.asm.tree.MethodNode;\nimport xyz.itzsomebody.codegen.instructions.BytecodeLabel;\nimport xyz.itzsomebody.codegen.instructions.ConstantNode;\n\nimport java.lang.reflect.Constructor;\nimport java.lang.reflect.Method;\nimport java.util.ArrayList;\nimport java.util.List;\n\npublic class Utils {\n    public static List<WrappedType> wrapMethodNodeParameters(MethodNode methodNode) {\n        var wrappedTypes = new ArrayList<WrappedType>();\n        List.of(Type.getArgumentTypes(methodNode.desc)).forEach(type -> wrappedTypes.add(new WrappedType(type)));\n        return wrappedTypes;\n    }\n\n    public static List<WrappedType> wrapMethodParameters(Method method) {\n        var wrappedTypes = new ArrayList<WrappedType>();\n        List.of(method.getParameterTypes()).forEach(clazz -> wrappedTypes.add(WrappedType.from(clazz)));\n        return wrappedTypes;\n    }\n\n    public static List<WrappedType> wrapConstructorParameters(Constructor<?> constructor) {\n        var wrappedTypes = new ArrayList<WrappedType>();\n        List.of(constructor.getParameterTypes()).forEach(clazz -> wrappedTypes.add(WrappedType.from(clazz)));\n        return wrappedTypes;\n    }\n\n    public static String unwrapMethodDescriptor(List<WrappedType> parameterTypes, WrappedType returnType) {\n        var sb = new StringBuilder(\"(\");\n        parameterTypes.forEach(type -> sb.append(type.unwrap()));\n        sb.append(')').append(returnType.unwrap());\n        return sb.toString();\n    }\n\n    public static ArrayList<LabelNode> unwrapLabels(List<BytecodeLabel> wrappedLabels) {\n        var unwrappedLabels = new ArrayList<LabelNode>(wrappedLabels.size());\n        wrappedLabels.forEach(wrappedLabel -> unwrappedLabels.add(wrappedLabel.getLabel()));\n        return unwrappedLabels;\n    }\n\n    public static Object[] unpackConstants(List<ConstantNode> constants) {\n        var unpacked = new Object[constants.size()];\n        for (var i = 0; i < unpacked.length; i++) {\n            unpacked[i] = constants.get(i).getValue();\n        }\n        return unpacked;\n    }\n\n    public static WrappedType box(WrappedType primitive) {\n        if (!primitive.isPrimitive()) {\n            throw new IllegalArgumentException(\"Attempted to box non-primitive type: \" + primitive);\n        }\n\n        switch (primitive.getSort()) {\n            case Type.BOOLEAN:\n                return WrappedType.from(Boolean.class);\n            case Type.CHAR:\n                return WrappedType.from(Character.class);\n            case Type.BYTE:\n                return WrappedType.from(Byte.class);\n            case Type.SHORT:\n                return WrappedType.from(Short.class);\n            case Type.INT:\n                return WrappedType.from(Integer.class);\n            case Type.LONG:\n                return WrappedType.from(Long.class);\n            case Type.FLOAT:\n                return WrappedType.from(Float.class);\n            case Type.DOUBLE:\n                return WrappedType.from(Double.class);\n            default:\n                throw new IllegalArgumentException(\"Unknown primitive type: \" + primitive);\n        }\n    }\n}\n"
  },
  {
    "path": "xyz.itzsomebody.codegen/src/main/java/xyz/itzsomebody/codegen/WrappedHandle.java",
    "content": "/*\n * Radon - An open-source Java obfuscator\n * Copyright (C) 2021 ItzSomebody\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, either version 3 of the License, or\n * (at your option) any later version.\n *\n * This program is distributed in the hope that it will be 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.  If not, see <http://www.gnu.org/licenses/>\n */\n\npackage xyz.itzsomebody.codegen;\n\nimport org.objectweb.asm.Handle;\nimport org.objectweb.asm.Opcodes;\n\nimport java.lang.reflect.Field;\nimport java.lang.reflect.Method;\nimport java.util.Collections;\nimport java.util.List;\n\npublic class WrappedHandle {\n    private final int tag;\n    private final WrappedType owner;\n    private final String name;\n    private final List<WrappedType> parameterTypes;\n    private final WrappedType returnType;\n\n    public WrappedHandle(int tag, WrappedType owner, String name, List<WrappedType> parameterTypes, WrappedType returnType) {\n        this.tag = tag;\n        this.owner = owner;\n        this.name = name;\n        this.parameterTypes = parameterTypes;\n        this.returnType = returnType;\n    }\n\n    public int getTag() {\n        return tag;\n    }\n\n    public WrappedType getOwner() {\n        return owner;\n    }\n\n    public String getName() {\n        return name;\n    }\n\n    public List<WrappedType> getParameterTypes() {\n        return parameterTypes;\n    }\n\n    public WrappedType getReturnType() {\n        return returnType;\n    }\n\n    public Handle constructHandle() {\n        return new Handle(tag, owner.getInternalName(), name, Utils.unwrapMethodDescriptor(parameterTypes, returnType), owner.isInterface());\n    }\n\n    // Fields\n\n    public static WrappedHandle getFieldHandle(WrappedType owner, String name, WrappedType type) {\n        return new WrappedHandle(Opcodes.H_GETFIELD, owner, name, Collections.emptyList(), type);\n    }\n\n    public static WrappedHandle getFieldHandle(Field field) {\n        return getFieldHandle(WrappedType.from(field.getDeclaringClass()), field.getName(), WrappedType.from(field.getType()));\n    }\n\n    public static WrappedHandle getStaticHandle(WrappedType owner, String name, WrappedType type) {\n        return new WrappedHandle(Opcodes.H_GETSTATIC, owner, name, Collections.emptyList(), type);\n    }\n\n    public static WrappedHandle getStaticHandle(Field field) {\n        return getFieldHandle(WrappedType.from(field.getDeclaringClass()), field.getName(), WrappedType.from(field.getType()));\n    }\n\n    public static WrappedHandle putFieldHandle(WrappedType owner, String name, WrappedType type) {\n        return new WrappedHandle(Opcodes.H_PUTFIELD, owner, name, Collections.emptyList(), type);\n    }\n\n    public static WrappedHandle putFieldHandle(Field field) {\n        return getFieldHandle(WrappedType.from(field.getDeclaringClass()), field.getName(), WrappedType.from(field.getType()));\n    }\n\n    public static WrappedHandle putStaticHandle(WrappedType owner, String name, WrappedType type) {\n        return new WrappedHandle(Opcodes.H_PUTSTATIC, owner, name, Collections.emptyList(), type);\n    }\n\n    public static WrappedHandle putStaticHandle(Field field) {\n        return getFieldHandle(WrappedType.from(field.getDeclaringClass()), field.getName(), WrappedType.from(field.getType()));\n    }\n\n    // Methods\n\n    public static WrappedHandle getInvokeVirtualHandle(WrappedType owner, String name, List<WrappedType> parameterTypes, WrappedType returnType) {\n        return new WrappedHandle(Opcodes.H_INVOKEVIRTUAL, owner, name, parameterTypes, returnType);\n    }\n\n    public static WrappedHandle getInvokeVirtualHandle(Method method) {\n        return getInvokeVirtualHandle(WrappedType.from(method.getDeclaringClass()), method.getName(), Utils.wrapMethodParameters(method), WrappedType.from(method.getReturnType()));\n    }\n\n    public static WrappedHandle getInvokeStaticHandle(WrappedType owner, String name, List<WrappedType> parameterTypes, WrappedType returnType) {\n        return new WrappedHandle(Opcodes.H_INVOKESTATIC, owner, name, parameterTypes, returnType);\n    }\n\n    public static WrappedHandle getInvokeStaticHandle(Method method) {\n        return getInvokeStaticHandle(WrappedType.from(method.getDeclaringClass()), method.getName(), Utils.wrapMethodParameters(method), WrappedType.from(method.getReturnType()));\n    }\n\n    public static WrappedHandle getInvokeSpecialHandle(WrappedType owner, String name, List<WrappedType> parameterTypes, WrappedType returnType) {\n        return new WrappedHandle(Opcodes.H_INVOKESPECIAL, owner, name, parameterTypes, returnType);\n    }\n\n    public static WrappedHandle getInvokeSpecialHandle(Method method) {\n        return getInvokeSpecialHandle(WrappedType.from(method.getDeclaringClass()), method.getName(), Utils.wrapMethodParameters(method), WrappedType.from(method.getReturnType()));\n    }\n\n    public static WrappedHandle getNewInvokeSpecialHandle(WrappedType owner, String name, List<WrappedType> parameterTypes, WrappedType returnType) {\n        return new WrappedHandle(Opcodes.H_NEWINVOKESPECIAL, owner, name, parameterTypes, returnType);\n    }\n\n    public static WrappedHandle getNewInvokeSpecialHandle(Method method) {\n        return getNewInvokeSpecialHandle(WrappedType.from(method.getDeclaringClass()), method.getName(), Utils.wrapMethodParameters(method), WrappedType.from(method.getReturnType()));\n    }\n\n    public static WrappedHandle getInvokeInterfaceHandle(WrappedType owner, String name, List<WrappedType> parameterTypes, WrappedType returnType) {\n        return new WrappedHandle(Opcodes.H_INVOKEVIRTUAL, owner, name, parameterTypes, returnType);\n    }\n\n    public static WrappedHandle getInvokeInterfaceHandle(Method method) {\n        return getInvokeInterfaceHandle(WrappedType.from(method.getDeclaringClass()), method.getName(), Utils.wrapMethodParameters(method), WrappedType.from(method.getReturnType()));\n    }\n}\n"
  },
  {
    "path": "xyz.itzsomebody.codegen/src/main/java/xyz/itzsomebody/codegen/WrappedType.java",
    "content": "/*\n * Radon - An open-source Java obfuscator\n * Copyright (C) 2021 ItzSomebody\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, either version 3 of the License, or\n * (at your option) any later version.\n *\n * This program is distributed in the hope that it will be 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.  If not, see <http://www.gnu.org/licenses/>\n */\n\npackage xyz.itzsomebody.codegen;\n\nimport org.objectweb.asm.Opcodes;\nimport org.objectweb.asm.Type;\nimport org.objectweb.asm.tree.ClassNode;\nimport xyz.itzsomebody.codegen.exceptions.UncompilableNodeException;\n\nimport java.util.HashMap;\nimport java.util.Map;\n\npublic class WrappedType {\n    private static final Map<String, Class<?>> BOXED_TYPES = new HashMap<>() {\n        {\n            put(Type.getInternalName(Boolean.class), boolean.class);\n            put(Type.getInternalName(Character.class), char.class);\n            put(Type.getInternalName(Byte.class), byte.class);\n            put(Type.getInternalName(Short.class), short.class);\n            put(Type.getInternalName(Integer.class), int.class);\n            put(Type.getInternalName(Float.class), float.class);\n            put(Type.getInternalName(Long.class), long.class);\n            put(Type.getInternalName(Double.class), double.class);\n        }\n    };\n    private static AbsentWrappedType absent;\n    private final Type type;\n    private final boolean isInterface;\n\n    public WrappedType(Type type) {\n        this.type = type;\n        this.isInterface = false;\n    }\n\n    public WrappedType(Type type, boolean isInterface) {\n        this.type = type;\n        this.isInterface = isInterface;\n    }\n\n    public static AbsentWrappedType getAbsent() {\n        if (absent == null) {\n            absent = new AbsentWrappedType();\n        }\n\n        return absent;\n    }\n\n    public Type getType() {\n        return type;\n    }\n\n    public boolean isInterface() {\n        return isInterface;\n    }\n\n    public int getSort() {\n        return type.getSort();\n    }\n\n    /**\n     * For NEWARRAY instructions\n     */\n    public int getNewArraySort() {\n        switch (type.getSort()) {\n            case Type.BOOLEAN:\n                return Opcodes.T_BOOLEAN;\n            case Type.CHAR:\n                return Opcodes.T_CHAR;\n            case Type.FLOAT:\n                return Opcodes.T_FLOAT;\n            case Type.DOUBLE:\n                return Opcodes.T_DOUBLE;\n            case Type.BYTE:\n                return Opcodes.T_BYTE;\n            case Type.SHORT:\n                return Opcodes.T_SHORT;\n            case Type.INT:\n                return Opcodes.T_INT;\n            case Type.LONG:\n                return Opcodes.T_LONG;\n            default:\n                throw new UncompilableNodeException(\"Attempted to get primitive array type of \" + this);\n        }\n    }\n\n    public boolean isPrimitive() {\n        switch (type.getSort()) {\n            case Type.BOOLEAN:\n            case Type.CHAR:\n            case Type.BYTE:\n            case Type.SHORT:\n            case Type.INT:\n            case Type.FLOAT:\n            case Type.LONG:\n            case Type.DOUBLE:\n                return true;\n            default:\n                return false;\n        }\n    }\n\n    public WrappedType getPrimitiveType() {\n        var primitiveClass = BOXED_TYPES.get(getInternalName());\n        if (primitiveClass == null) {\n            throw new UncompilableNodeException(\"Attempted to get primitive type of \" + this);\n        }\n\n        return WrappedType.from(primitiveClass);\n    }\n\n    public boolean isBoxed() {\n        return BOXED_TYPES.containsKey(getInternalName());\n    }\n\n    public boolean isArray() {\n        return type.getSort() == Type.ARRAY;\n    }\n\n    public boolean isIntType() {\n        var sort = getSort();\n        return (sort == Type.BOOLEAN)\n                || (sort == Type.CHAR)\n                || (sort == Type.BYTE)\n                || (sort == Type.SHORT)\n                || (sort == Type.INT);\n    }\n\n    public String unwrap() {\n        if (type.getSort() == Type.OBJECT) {\n            return 'L' + type.getInternalName() + ';';\n        } else {\n            return type.getInternalName();\n        }\n    }\n\n    public String getInternalName() {\n        return type.getInternalName();\n    }\n\n    public String getClassName() {\n        return type.getClassName();\n    }\n\n    public static WrappedType fromClassName(String className, boolean isInterface) {\n        StringBuilder internalName = new StringBuilder();\n\n        if (className.endsWith(\"[]\")) {\n            className = className.substring(0, className.length() - 2);\n            internalName.append('[');\n        }\n        switch (className) {\n            case \"int\":\n                internalName.append(\"I\");\n                break;\n            case \"long\":\n                internalName.append(\"J\");\n                break;\n            case \"float\":\n                internalName.append(\"F\");\n                break;\n            case \"double\":\n                internalName.append(\"D\");\n                break;\n            case \"boolean\":\n                internalName.append(\"Z\");\n                break;\n            case \"byte\":\n                internalName.append(\"B\");\n                break;\n            case \"short\":\n                internalName.append(\"S\");\n                break;\n            case \"char\":\n                internalName.append(\"C\");\n                break;\n            default:\n                internalName.append('L').append(className.replace('.', '/')).append(';');\n        }\n\n        return new WrappedType(Type.getType(internalName.toString()), isInterface);\n    }\n\n    public static WrappedType fromInternalName(String internalName, boolean isInterface) {\n        if (\"ZBCSIJFDV\".contains(internalName) || internalName.startsWith(\"[\")) {\n            return new WrappedType(Type.getType(internalName), isInterface);\n        } else {\n            return new WrappedType(Type.getType(\"L\" + internalName + \";\"), isInterface);\n        }\n    }\n\n    public static WrappedType from(Class<?> clazz) {\n        return new WrappedType(Type.getType(clazz), clazz.isInterface());\n    }\n\n    public static WrappedType from(ClassNode classNode) {\n        return new WrappedType(Type.getType(\"L\" + classNode.name + \";\"), (classNode.access & Opcodes.ACC_INTERFACE) != 0);\n    }\n\n    @Override\n    public String toString() {\n        return \"WrappedType{\" +\n                \"type=\" + type +\n                \", isInterface=\" + isInterface +\n                '}';\n    }\n\n    @Override\n    public boolean equals(Object other) {\n        if (!(other instanceof WrappedType)) {\n            return false;\n        }\n\n        return getType().equals(((WrappedType) other).getType());\n    }\n\n    static class AbsentWrappedType extends WrappedType {\n        private AbsentWrappedType() {\n            super(null);\n        }\n\n        @Override\n        public Type getType() {\n            throw new UncompilableNodeException(\"Attempted to get type of AbsentWrappedType\");\n        }\n\n        @Override\n        public boolean isInterface() {\n            throw new UncompilableNodeException(\"Attempted to determine interface flag of AbsentWrappedType\");\n        }\n\n        @Override\n        public int getSort() {\n            throw new UncompilableNodeException(\"Attempted to get sort of AbsentWrappedType\");\n        }\n\n        @Override\n        public boolean isPrimitive() {\n            throw new UncompilableNodeException(\"Attempted to determine primitive flag of AbsentWrappedType\");\n        }\n\n        @Override\n        public boolean isBoxed() {\n            throw new UncompilableNodeException(\"Attempted to determine boxed flag of AbsentWrappedType\");\n        }\n\n        @Override\n        public boolean isArray() {\n            throw new UncompilableNodeException(\"Attempted to determine array flag of AbsentWrappedType\");\n        }\n\n        @Override\n        public boolean isIntType() {\n            throw new UncompilableNodeException(\"Attempted to determine isIntType flag of AbsentWrappedType\");\n        }\n\n        @Override\n        public String unwrap() {\n            throw new UncompilableNodeException(\"Attempted to unwrap AbsentWrappedType\");\n        }\n\n        @Override\n        public String getInternalName() {\n            throw new UncompilableNodeException(\"Attempted to get internal name of AbsentWrappedType\");\n        }\n\n        @Override\n        public String getClassName() {\n            throw new UncompilableNodeException(\"Attempted to get class name of AbsentWrappedType\");\n        }\n    }\n}\n"
  },
  {
    "path": "xyz.itzsomebody.codegen/src/main/java/xyz/itzsomebody/codegen/exceptions/UncompilableNodeException.java",
    "content": "/*\n * Radon - An open-source Java obfuscator\n * Copyright (C) 2020 ItzSomebody\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, either version 3 of the License, or\n * (at your option) any later version.\n *\n * This program is distributed in the hope that it will be 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.  If not, see <http://www.gnu.org/licenses/>\n */\n\npackage xyz.itzsomebody.codegen.exceptions;\n\npublic class UncompilableNodeException extends RuntimeException {\n    public UncompilableNodeException() {\n        super();\n    }\n\n    public UncompilableNodeException(String msg) {\n        super(msg);\n    }\n}\n"
  },
  {
    "path": "xyz.itzsomebody.codegen/src/main/java/xyz/itzsomebody/codegen/expressions/IRExpression.java",
    "content": "/*\n * Radon - An open-source Java obfuscator\n * Copyright (C) 2021 ItzSomebody\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, either version 3 of the License, or\n * (at your option) any later version.\n *\n * This program is distributed in the hope that it will be 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.  If not, see <http://www.gnu.org/licenses/>\n */\n\npackage xyz.itzsomebody.codegen.expressions;\n\nimport org.objectweb.asm.Type;\nimport org.objectweb.asm.tree.ClassNode;\nimport org.objectweb.asm.tree.FieldNode;\nimport org.objectweb.asm.tree.MethodNode;\nimport xyz.itzsomebody.codegen.BytecodeBlock;\nimport xyz.itzsomebody.codegen.Utils;\nimport xyz.itzsomebody.codegen.WrappedType;\nimport xyz.itzsomebody.codegen.expressions.predefined.*;\n\nimport java.lang.reflect.Field;\nimport java.lang.reflect.Method;\nimport java.util.List;\n\npublic abstract class IRExpression {\n    private final WrappedType type;\n\n    public IRExpression(WrappedType type) {\n        this.type = type;\n    }\n\n    public WrappedType getType() {\n        return type;\n    }\n\n    public abstract BytecodeBlock getInstructions();\n\n    public IRExpression arrayLength() {\n        return new IRArrayLengthExpression(this);\n    }\n\n    public IRExpression getArrayElement(int index) {\n        return new IRGetArrayElementExpression(this, IRExpressions.intConst(index));\n    }\n\n    public IRExpression getArrayElement(IRExpression index) {\n        return new IRGetArrayElementExpression(this, index);\n    }\n\n    public IRExpression setArrayElement(int index, IRExpression value) {\n        return new IRSetArrayElementExpression(this, IRExpressions.intConst(index), value);\n    }\n\n    public IRExpression setArrayElement(IRExpression index, IRExpression value) {\n        return new IRSetArrayElementExpression(this, index, value);\n    }\n\n    public IRExpression cast(ClassNode target) {\n        return new IRCastExpression(this, WrappedType.from(target));\n    }\n\n    public IRExpression cast(Class<?> target) {\n        return new IRCastExpression(this, WrappedType.from(target));\n    }\n\n    public IRExpression cast(String target) {\n        return new IRCastExpression(this, WrappedType.fromInternalName(target, false));\n    }\n\n    public IRExpression cast(WrappedType type) {\n        return new IRCastExpression(this, type);\n    }\n\n    public IRExpression instanceOf(ClassNode target) {\n        return new IRInstanceOfExpression(this, WrappedType.from(target));\n    }\n\n    public IRExpression instanceOf(Class<?> target) {\n        return new IRInstanceOfExpression(this, WrappedType.from(target));\n    }\n\n    public IRExpression instanceOf(String target) {\n        return new IRInstanceOfExpression(this, WrappedType.fromInternalName(target, false));\n    }\n\n    public IRExpression instanceOf(WrappedType type) {\n        return new IRInstanceOfExpression(this, type);\n    }\n\n    public IRExpression getField(String name, Class<?> type) {\n        return new IRGetFieldExpression(this, getType(), name, WrappedType.from(type));\n    }\n\n    public IRExpression getField(String name, WrappedType type) {\n        return new IRGetFieldExpression(this, getType(), name, type);\n    }\n\n    public IRExpression getField(FieldNode fieldNode) {\n        return new IRGetFieldExpression(this, getType(), fieldNode.name, WrappedType.fromInternalName(fieldNode.desc, false));\n    }\n\n    public IRExpression getField(Field field) {\n        return new IRGetFieldExpression(this, getType(), field.getName(), WrappedType.from(field.getType()));\n    }\n\n    public IRExpression setField(String name, Class<?> type, IRExpression value) {\n        return new IRSetFieldExpression(this, value, getType(), name, WrappedType.from(type));\n    }\n\n    public IRExpression setField(String name, WrappedType type, IRExpression value) {\n        return new IRSetFieldExpression(this, value, getType(), name, type);\n    }\n\n    public IRExpression setField(FieldNode fieldNode, IRExpression value) {\n        return new IRSetFieldExpression(this, value, getType(), fieldNode.name, WrappedType.fromInternalName(fieldNode.desc, false));\n    }\n\n    public IRExpression setField(Field field, IRExpression value) {\n        return new IRSetFieldExpression(this, value, getType(), field.getName(), WrappedType.from(field.getType()));\n    }\n\n    public IRExpression invoke(MethodNode methodNode, IRExpression... arguments) {\n        return new IRInvocationExpression(this, getType(), methodNode.name, List.of(arguments), Utils.wrapMethodNodeParameters(methodNode), new WrappedType(Type.getReturnType(methodNode.desc)));\n    }\n\n    public IRExpression invoke(Method method, IRExpression... arguments) {\n        return new IRInvocationExpression(this, getType(), method.getName(), List.of(arguments), Utils.wrapMethodParameters(method), WrappedType.from(method.getReturnType()));\n    }\n\n    public IRExpression invoke(String name, List<WrappedType> parameterTypes, WrappedType returnType, IRExpression... arguments) {\n        return new IRInvocationExpression(this, getType(), name, List.of(arguments), parameterTypes, returnType);\n    }\n\n    public IRExpression ret() {\n        return new IRReturnExpression(this);\n    }\n\n    public IRExpression throwMe() {\n        return new IRThrowExceptionExpression(this);\n    }\n}\n"
  },
  {
    "path": "xyz.itzsomebody.codegen/src/main/java/xyz/itzsomebody/codegen/expressions/IRExpressions.java",
    "content": "/*\n * Radon - An open-source Java obfuscator\n * Copyright (C) 2021 ItzSomebody\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, either version 3 of the License, or\n * (at your option) any later version.\n *\n * This program is distributed in the hope that it will be 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.  If not, see <http://www.gnu.org/licenses/>\n */\n\npackage xyz.itzsomebody.codegen.expressions;\n\nimport org.objectweb.asm.Type;\nimport org.objectweb.asm.tree.ClassNode;\nimport org.objectweb.asm.tree.MethodNode;\nimport xyz.itzsomebody.codegen.BytecodeBlock;\nimport xyz.itzsomebody.codegen.Utils;\nimport xyz.itzsomebody.codegen.WrappedHandle;\nimport xyz.itzsomebody.codegen.WrappedType;\nimport xyz.itzsomebody.codegen.expressions.flow.*;\nimport xyz.itzsomebody.codegen.expressions.predefined.*;\nimport xyz.itzsomebody.codegen.instructions.ConstantNode;\nimport xyz.itzsomebody.codegen.instructions.SimpleNode;\n\nimport java.lang.reflect.Constructor;\nimport java.lang.reflect.Field;\nimport java.lang.reflect.Method;\nimport java.util.ArrayList;\nimport java.util.List;\n\npublic class IRExpressions {\n    // ARITHMETIC\n\n    public static IRExpression intAdd(IRExpression left, IRExpression right) {\n        return new IRArithmeticExpression(SimpleNode.INT_ADD, left, right);\n    }\n\n    public static IRExpression intSub(IRExpression left, IRExpression right) {\n        return new IRArithmeticExpression(SimpleNode.INT_SUB, left, right);\n    }\n\n    public static IRExpression intMul(IRExpression left, IRExpression right) {\n        return new IRArithmeticExpression(SimpleNode.INT_MUL, left, right);\n    }\n\n    public static IRExpression intDiv(IRExpression left, IRExpression right) {\n        return new IRArithmeticExpression(SimpleNode.INT_DIV, left, right);\n    }\n\n    public static IRExpression intMod(IRExpression left, IRExpression right) {\n        return new IRArithmeticExpression(SimpleNode.INT_MOD, left, right);\n    }\n\n    public static IRExpression intShiftLeft(IRExpression left, IRExpression right) {\n        return new IRArithmeticExpression(SimpleNode.INT_SHIFT_LEFT, left, right);\n    }\n\n    public static IRExpression intShiftRight(IRExpression left, IRExpression right) {\n        return new IRArithmeticExpression(SimpleNode.INT_SHIFT_RIGHT, left, right);\n    }\n\n    public static IRExpression intUnsignedShiftRight(IRExpression left, IRExpression right) {\n        return new IRArithmeticExpression(SimpleNode.INT_UNSIGNED_SHIFT_RIGHT, left, right);\n    }\n\n    public static IRExpression intAnd(IRExpression left, IRExpression right) {\n        return new IRArithmeticExpression(SimpleNode.INT_AND, left, right);\n    }\n\n    public static IRExpression intOr(IRExpression left, IRExpression right) {\n        return new IRArithmeticExpression(SimpleNode.INT_OR, left, right);\n    }\n\n    public static IRExpression intXor(IRExpression left, IRExpression right) {\n        return new IRArithmeticExpression(SimpleNode.INT_XOR, left, right);\n    }\n\n    public static IRExpression longAdd(IRExpression left, IRExpression right) {\n        return new IRArithmeticExpression(SimpleNode.LONG_ADD, left, right);\n    }\n\n    public static IRExpression longSub(IRExpression left, IRExpression right) {\n        return new IRArithmeticExpression(SimpleNode.LONG_SUB, left, right);\n    }\n\n    public static IRExpression longMul(IRExpression left, IRExpression right) {\n        return new IRArithmeticExpression(SimpleNode.LONG_MUL, left, right);\n    }\n\n    public static IRExpression longDiv(IRExpression left, IRExpression right) {\n        return new IRArithmeticExpression(SimpleNode.LONG_DIV, left, right);\n    }\n\n    public static IRExpression longMod(IRExpression left, IRExpression right) {\n        return new IRArithmeticExpression(SimpleNode.LONG_MOD, left, right);\n    }\n\n    public static IRExpression longShiftLeft(IRExpression left, IRExpression right) {\n        return new IRArithmeticExpression(SimpleNode.LONG_SHIFT_LEFT, left, right);\n    }\n\n    public static IRExpression longShiftRight(IRExpression left, IRExpression right) {\n        return new IRArithmeticExpression(SimpleNode.LONG_SHIFT_RIGHT, left, right);\n    }\n\n    public static IRExpression longUnsignedShiftRight(IRExpression left, IRExpression right) {\n        return new IRArithmeticExpression(SimpleNode.LONG_UNSIGNED_SHIFT_RIGHT, left, right);\n    }\n\n    public static IRExpression longAnd(IRExpression left, IRExpression right) {\n        return new IRArithmeticExpression(SimpleNode.LONG_AND, left, right);\n    }\n\n    public static IRExpression longOr(IRExpression left, IRExpression right) {\n        return new IRArithmeticExpression(SimpleNode.LONG_OR, left, right);\n    }\n\n    public static IRExpression longXor(IRExpression left, IRExpression right) {\n        return new IRArithmeticExpression(SimpleNode.LONG_XOR, left, right);\n    }\n\n    public static IRExpression floatAdd(IRExpression left, IRExpression right) {\n        return new IRArithmeticExpression(SimpleNode.FLOAT_ADD, left, right);\n    }\n\n    public static IRExpression floatSub(IRExpression left, IRExpression right) {\n        return new IRArithmeticExpression(SimpleNode.FLOAT_SUB, left, right);\n    }\n\n    public static IRExpression floatMul(IRExpression left, IRExpression right) {\n        return new IRArithmeticExpression(SimpleNode.FLOAT_MUL, left, right);\n    }\n\n    public static IRExpression floatDiv(IRExpression left, IRExpression right) {\n        return new IRArithmeticExpression(SimpleNode.FLOAT_DIV, left, right);\n    }\n\n    public static IRExpression floatMod(IRExpression left, IRExpression right) {\n        return new IRArithmeticExpression(SimpleNode.FLOAT_MOD, left, right);\n    }\n\n    public static IRExpression doubleAdd(IRExpression left, IRExpression right) {\n        return new IRArithmeticExpression(SimpleNode.DOUBLE_ADD, left, right);\n    }\n\n    public static IRExpression doubleSub(IRExpression left, IRExpression right) {\n        return new IRArithmeticExpression(SimpleNode.DOUBLE_SUB, left, right);\n    }\n\n    public static IRExpression doubleMul(IRExpression left, IRExpression right) {\n        return new IRArithmeticExpression(SimpleNode.DOUBLE_MUL, left, right);\n    }\n\n    public static IRExpression doubleDiv(IRExpression left, IRExpression right) {\n        return new IRArithmeticExpression(SimpleNode.DOUBLE_DIV, left, right);\n    }\n\n    public static IRExpression doubleMod(IRExpression left, IRExpression right) {\n        return new IRArithmeticExpression(SimpleNode.DOUBLE_MOD, left, right);\n    }\n\n    // ARRAYLENGTH\n\n    public static IRExpression arrayLength(IRExpression array) {\n        return new IRArrayLengthExpression(array);\n    }\n\n    // CAST\n\n    public static IRExpression cast(IRExpression source, WrappedType targetType) {\n        return new IRCastExpression(source, targetType);\n    }\n\n    // CONSTANT DYNAMIC\n\n    public static IRExpression dynamicConst(String name, WrappedType type, WrappedHandle bootstrapMethod, List<ConstantNode> bootstrapArgs) {\n        return new IRConstantExpression(ConstantNode.dynamicConst(name, type, bootstrapMethod, bootstrapArgs), type);\n    }\n\n    public static IRExpression dynamicConst(String name, WrappedType type, Method bootstrap, List<ConstantNode> bootstrapArgs) {\n        return new IRConstantExpression(ConstantNode.dynamicConst(name, type, bootstrap, bootstrapArgs), type);\n    }\n\n    // CONSTANTS\n\n    public static IRExpression nullConst(Class<?> type) {\n        return new IRConstantExpression(ConstantNode.nullConst(), WrappedType.from(type));\n    }\n\n    public static IRExpression nullConst(ClassNode type) {\n        return new IRConstantExpression(ConstantNode.nullConst(), WrappedType.from(type));\n    }\n\n    public static IRExpression nullConst(WrappedType type) {\n        return new IRConstantExpression(ConstantNode.nullConst(), type);\n    }\n\n    public static IRExpression booleanConst(boolean z) {\n        return new IRConstantExpression(ConstantNode.booleanConst(z), WrappedType.from(boolean.class));\n    }\n\n    public static IRExpression trueConst() {\n        return booleanConst(true);\n    }\n\n    public static IRExpression falseConst() {\n        return booleanConst(false);\n    }\n\n    public static IRExpression intConst(int i) {\n        return new IRConstantExpression(ConstantNode.intConst(i), WrappedType.from(int.class));\n    }\n\n    public static IRExpression longConst(long j) {\n        return new IRConstantExpression(ConstantNode.longConst(j), WrappedType.from(long.class));\n    }\n\n    public static IRExpression floatConst(float f) {\n        return new IRConstantExpression(ConstantNode.floatConst(f), WrappedType.from(float.class));\n    }\n\n    public static IRExpression doubleConst(double d) {\n        return new IRConstantExpression(ConstantNode.doubleConst(d), WrappedType.from(double.class));\n    }\n\n    public static IRExpression stringConst(String str) {\n        return new IRConstantExpression(ConstantNode.stringConst(str), WrappedType.from(String.class));\n    }\n\n    public static IRExpression classConst(Class<?> clazz) {\n        return new IRConstantExpression(ConstantNode.classConst(WrappedType.from(clazz)), WrappedType.from(Class.class));\n    }\n\n    public static IRExpression classConst(WrappedType type) {\n        return new IRConstantExpression(ConstantNode.classConst(type), WrappedType.from(Class.class));\n    }\n\n    // GET ARRAY ELEMENT\n\n    public static IRExpression getArrayElement(IRExpression array, int index) {\n        return new IRGetArrayElementExpression(array, intConst(index));\n    }\n\n    public static IRExpression getArrayElement(IRExpression array, IRExpression index) {\n        return new IRGetArrayElementExpression(array, index);\n    }\n\n    // GET FIELD\n\n    public static IRExpression getField(IRExpression instance, Field field) {\n        return new IRGetFieldExpression(instance, field);\n    }\n\n    public static IRExpression getField(IRExpression instance, Class<?> owner, String name, Class<?> type) {\n        return new IRGetFieldExpression(instance, WrappedType.from(owner), name, WrappedType.from(type));\n    }\n\n    public static IRExpression getField(IRExpression instance, WrappedType owner, String name, WrappedType type) {\n        return new IRGetFieldExpression(instance, owner, name, type);\n    }\n\n    public static IRExpression getStatic(Field field) {\n        return new IRGetFieldExpression(null, field);\n    }\n\n    public static IRExpression getStatic(Class<?> owner, String name, Class<?> type) {\n        return new IRGetFieldExpression(null, WrappedType.from(owner), name, WrappedType.from(type));\n    }\n\n    public static IRExpression getStatic(WrappedType owner, String name, WrappedType type) {\n        return new IRGetFieldExpression(null, owner, name, type);\n    }\n\n    // INSTANCE OF\n\n    public static IRExpression instanceOf(IRExpression instance, Class<?> type) {\n        return new IRInstanceOfExpression(instance, WrappedType.from(type));\n    }\n\n    public static IRExpression instanceOf(IRExpression instance, WrappedType type) {\n        return new IRInstanceOfExpression(instance, type);\n    }\n\n    // INVOCATIONS\n\n    public static IRExpression invokeVirtual(IRExpression instance, Method method, IRExpression... args) {\n        return new IRInvocationExpression(instance, method, List.of(args));\n    }\n\n    public static IRExpression invokeVirtual(IRExpression instance, MethodNode methodNode, IRExpression... arguments) {\n        return new IRInvocationExpression(instance, instance.getType(), methodNode.name, List.of(arguments), Utils.wrapMethodNodeParameters(methodNode), new WrappedType(Type.getReturnType(methodNode.desc)));\n    }\n\n    public static IRExpression invokeVirtual(IRExpression instance, String name, List<WrappedType> parameterTypes, WrappedType returnType, IRExpression... arguments) {\n        return new IRInvocationExpression(instance, instance.getType(), name, List.of(arguments), parameterTypes, returnType);\n    }\n\n    public static IRExpression invokeVirtual(IRExpression instance, WrappedType owner, String name, List<IRExpression> args, List<WrappedType> argTypes, WrappedType returnType) {\n        return new IRInvocationExpression(instance, owner, name, args, argTypes, returnType);\n    }\n\n    public static IRExpression invokeStatic(Method method, IRExpression... args) {\n        return new IRInvocationExpression(null, method, List.of(args));\n    }\n\n    public static IRExpression invokeStatic(ClassNode owner, MethodNode methodNode, IRExpression... arguments) {\n        return new IRInvocationExpression(null, WrappedType.from(owner), methodNode.name, List.of(arguments), Utils.wrapMethodNodeParameters(methodNode), new WrappedType(Type.getReturnType(methodNode.desc)));\n    }\n\n    public static IRExpression invokeStatic(String owner, String name, List<WrappedType> parameterTypes, WrappedType returnType, IRExpression... arguments) {\n        return new IRInvocationExpression(null, WrappedType.fromInternalName(owner, false), name, List.of(arguments), parameterTypes, returnType);\n    }\n\n    public static IRExpression invokeStatic(WrappedType owner, String name, List<IRExpression> args, List<WrappedType> argTypes, WrappedType returnType) {\n        return new IRInvocationExpression(null, owner, name, args, argTypes, returnType);\n    }\n\n    // INVOKE DYNAMIC\n\n    public static IRExpression invokeDynamic(String name, List<IRExpression> args, List<WrappedType> argTypes, WrappedType returnType, Method bootstrap, List<ConstantNode> bootstrapArgs) {\n        return new IRInvokeDynamicExpression(name, args, argTypes, returnType, WrappedHandle.getInvokeStaticHandle(bootstrap), bootstrapArgs);\n    }\n\n    public static IRExpression invokeDynamic(String name, List<IRExpression> args, List<WrappedType> argTypes, WrappedType returnType, WrappedHandle bootstrap, List<ConstantNode> bootstrapArgs) {\n        return new IRInvokeDynamicExpression(name, args, argTypes, returnType, bootstrap, bootstrapArgs);\n    }\n\n    // NEGATIONS\n\n    public static IRExpression negate(IRExpression operand) {\n        return new IRNegateExpression(operand);\n    }\n\n    // NEW ARRAY\n\n    public static IRExpression newArray(Class<?> type, IRExpression... elements) {\n        return new IRNewArrayExpression(intConst(elements.length), WrappedType.from(type), elements);\n    }\n\n    public static IRExpression newArray(WrappedType type, IRExpression... elements) {\n        return new IRNewArrayExpression(intConst(elements.length), type, elements);\n    }\n\n    public static IRExpression newArray(int length, Class<?> type, IRExpression... elements) {\n        return new IRNewArrayExpression(intConst(length), WrappedType.from(type), elements);\n    }\n\n    public static IRExpression newArray(int length, WrappedType type, IRExpression... elements) {\n        return new IRNewArrayExpression(intConst(length), type, elements);\n    }\n\n    public static IRExpression newArray(IRExpression length, Class<?> type, IRExpression... elements) {\n        return new IRNewArrayExpression(length, WrappedType.from(type), elements);\n    }\n\n    public static IRExpression newArray(IRExpression length, WrappedType type, IRExpression... elements) {\n        return new IRNewArrayExpression(length, type, elements);\n    }\n\n    // NEW INSTANCE (CONSTRUCTOR INVOCATIONS)\n\n    public static IRExpression newInstance(Constructor<?> constructor, IRExpression... args) {\n        return new IRNewInstanceExpression(WrappedType.from(constructor.getDeclaringClass()), Utils.wrapConstructorParameters(constructor), List.of(args));\n    }\n\n    public static IRExpression newInstance(WrappedType type, List<WrappedType> argumentTypes, List<IRExpression> arguments) {\n        return new IRNewInstanceExpression(type, argumentTypes, arguments);\n    }\n\n    // RETURNS\n\n    public static IRExpression returnMe(IRExpression operand) {\n        return new IRReturnExpression(operand);\n    }\n\n    // SET ARRAY ELEMENT\n\n    public static IRExpression setArrayElement(IRExpression array, int index, IRExpression value) {\n        return new IRSetArrayElementExpression(array, intConst(index), value);\n    }\n\n    public static IRExpression setArrayElement(IRExpression array, IRExpression index, IRExpression value) {\n        return new IRSetArrayElementExpression(array, index, value);\n    }\n\n    // SET FIELD\n\n    public static IRExpression setField(IRExpression instance, Field field, IRExpression value) {\n        return new IRSetFieldExpression(instance, value, field);\n    }\n\n    public static IRExpression setField(IRExpression instance, Class<?> owner, String name, Class<?> type, IRExpression value) {\n        return new IRSetFieldExpression(instance, value, WrappedType.from(owner), name, WrappedType.from(type));\n    }\n\n    public static IRExpression setField(IRExpression instance, WrappedType owner, String name, WrappedType type, IRExpression value) {\n        return new IRSetFieldExpression(instance, value, owner, name, type);\n    }\n\n    public static IRExpression setStatic(Field field, IRExpression value) {\n        return new IRSetFieldExpression(null, value, field);\n    }\n\n    public static IRExpression setStatic(Class<?> owner, String name, Class<?> type, IRExpression value) {\n        return new IRSetFieldExpression(null, value, WrappedType.from(owner), name, WrappedType.from(type));\n    }\n\n    public static IRExpression setStatic(WrappedType owner, String name, WrappedType type, IRExpression value) {\n        return new IRSetFieldExpression(null, value, owner, name, type);\n    }\n\n    public static IRExpression throwException(IRExpression exception) {\n        return new IRThrowExceptionExpression(exception);\n    }\n\n    // FLOW STRUCTURES\n\n    public static IRFlowStructure forLoop(BytecodeBlock initializer, BytecodeBlock condition, BytecodeBlock updater, BytecodeBlock body) {\n        return new IRForStructure(initializer, condition, updater, body);\n    }\n\n    public static IRFlowStructure ifBlock(BytecodeBlock condition, BytecodeBlock ifTrue, BytecodeBlock ifFalse) {\n        return new IRIfStructure(condition, ifTrue, ifFalse);\n    }\n\n    public static IRFlowStructure switchStatement(IRExpression operand, ArrayList<Integer> keys, ArrayList<BytecodeBlock> cases, BytecodeBlock defaultBody) {\n        return new IRSwitchStructure(operand, keys, cases, defaultBody);\n    }\n\n    public static IRFlowStructure synchronizedBlock(IRExpression instance, BytecodeBlock body) {\n        return new IRSynchronizedStructure(instance, body);\n    }\n\n    public static IRFlowStructure tryCatch(BytecodeBlock tryBody, BytecodeBlock catchBody, WrappedType exceptionType) {\n        return new IRTryCatchStructure(tryBody, catchBody, exceptionType);\n    }\n\n    public static IRFlowStructure whileLoop(BytecodeBlock condition, BytecodeBlock body) {\n        return new IRWhileStructure(condition, body);\n    }\n}\n"
  },
  {
    "path": "xyz.itzsomebody.codegen/src/main/java/xyz/itzsomebody/codegen/expressions/IRVariable.java",
    "content": "/*\n * Radon - An open-source Java obfuscator\n * Copyright (C) 2021 ItzSomebody\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, either version 3 of the License, or\n * (at your option) any later version.\n *\n * This program is distributed in the hope that it will be 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.  If not, see <http://www.gnu.org/licenses/>\n */\n\npackage xyz.itzsomebody.codegen.expressions;\n\nimport xyz.itzsomebody.codegen.BytecodeBlock;\nimport xyz.itzsomebody.codegen.WrappedType;\nimport xyz.itzsomebody.codegen.expressions.predefined.IRSetVariableExpression;\nimport xyz.itzsomebody.codegen.instructions.RegisterNode;\n\npublic class IRVariable extends IRExpression {\n    private final WrappedType wrappedType;\n    private final int slot;\n\n    public IRVariable(WrappedType wrappedType, int slot) {\n        super(wrappedType);\n        this.wrappedType = wrappedType;\n        this.slot = slot;\n    }\n\n    @Override\n    public BytecodeBlock getInstructions() {\n        return new BytecodeBlock().append(RegisterNode.loadVar(this));\n    }\n\n    public WrappedType getWrappedType() {\n        return wrappedType;\n    }\n\n    public int getSlot() {\n        return slot;\n    }\n\n    public IRExpression set(IRExpression expression) {\n        return new IRSetVariableExpression(this, expression);\n    }\n}\n"
  },
  {
    "path": "xyz.itzsomebody.codegen/src/main/java/xyz/itzsomebody/codegen/expressions/flow/IRFlowStructure.java",
    "content": "/*\n * Radon - An open-source Java obfuscator\n * Copyright (C) 2021 ItzSomebody\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, either version 3 of the License, or\n * (at your option) any later version.\n *\n * This program is distributed in the hope that it will be 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.  If not, see <http://www.gnu.org/licenses/>\n */\n\npackage xyz.itzsomebody.codegen.expressions.flow;\n\nimport xyz.itzsomebody.codegen.WrappedType;\nimport xyz.itzsomebody.codegen.expressions.IRExpression;\n\npublic abstract class IRFlowStructure extends IRExpression {\n    public IRFlowStructure() {\n        super(WrappedType.getAbsent());\n    }\n}\n"
  },
  {
    "path": "xyz.itzsomebody.codegen/src/main/java/xyz/itzsomebody/codegen/expressions/flow/IRForStructure.java",
    "content": "/*\n * Radon - An open-source Java obfuscator\n * Copyright (C) 2021 ItzSomebody\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, either version 3 of the License, or\n * (at your option) any later version.\n *\n * This program is distributed in the hope that it will be 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.  If not, see <http://www.gnu.org/licenses/>\n */\n\npackage xyz.itzsomebody.codegen.expressions.flow;\n\nimport xyz.itzsomebody.codegen.BytecodeBlock;\nimport xyz.itzsomebody.codegen.instructions.BytecodeLabel;\nimport xyz.itzsomebody.codegen.instructions.JumpNode;\n\npublic class IRForStructure extends IRFlowStructure {\n    private final BytecodeBlock initializer;\n    private final BytecodeBlock condition;\n    private final BytecodeBlock updater;\n    private final BytecodeBlock body;\n    private final BytecodeLabel continueLabel = new BytecodeLabel();\n    private final BytecodeLabel exitLabel = new BytecodeLabel();\n\n    public IRForStructure(BytecodeBlock initializer, BytecodeBlock condition, BytecodeBlock updater, BytecodeBlock body) {\n        this.initializer = initializer;\n        this.condition = condition;\n        this.updater = updater;\n        this.body = body;\n    }\n\n    @Override\n    public BytecodeBlock getInstructions() {\n        return new BytecodeBlock()\n                // Initializer\n                .append(initializer)\n\n                // Condition\n                .append(continueLabel)\n                .append(condition)\n                .append(JumpNode.jumpIfZero(exitLabel)) // Exit if false\n\n                // Updater\n                .append(updater)\n\n                // Body\n                .append(body)\n                .append(JumpNode.jumpUnconditionally(continueLabel)) // Next iteration\n                .append(exitLabel);\n    }\n\n    public BytecodeLabel getContinueLabel() {\n        return continueLabel;\n    }\n\n    public BytecodeLabel getExitLabel() {\n        return exitLabel;\n    }\n}\n"
  },
  {
    "path": "xyz.itzsomebody.codegen/src/main/java/xyz/itzsomebody/codegen/expressions/flow/IRIfStructure.java",
    "content": "/*\n * Radon - An open-source Java obfuscator\n * Copyright (C) 2021 ItzSomebody\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, either version 3 of the License, or\n * (at your option) any later version.\n *\n * This program is distributed in the hope that it will be 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.  If not, see <http://www.gnu.org/licenses/>\n */\n\npackage xyz.itzsomebody.codegen.expressions.flow;\n\nimport xyz.itzsomebody.codegen.BytecodeBlock;\nimport xyz.itzsomebody.codegen.instructions.BytecodeLabel;\nimport xyz.itzsomebody.codegen.instructions.JumpNode;\n\npublic class IRIfStructure extends IRFlowStructure {\n    private final BytecodeBlock condition;\n    private final BytecodeBlock ifTrue;\n    private final BytecodeBlock ifFalse;\n    private final BytecodeLabel trueLabel = new BytecodeLabel();\n    private final BytecodeLabel exitLabel = new BytecodeLabel();\n\n    public IRIfStructure(BytecodeBlock condition, BytecodeBlock ifTrue, BytecodeBlock ifFalse) {\n        this.condition = condition;\n        this.ifTrue = ifTrue;\n        this.ifFalse = ifFalse;\n    }\n\n    @Override\n    public BytecodeBlock getInstructions() {\n        return new BytecodeBlock()\n                // Condition\n                .append(condition)\n                .append(JumpNode.jumpIfNotZero(trueLabel))\n\n                // Execute this if false\n                .append(ifFalse)\n                .append(JumpNode.jumpUnconditionally(exitLabel)) // Don't execute the ifTrue block\n\n                // Execute this if true\n                .append(trueLabel)\n                .append(ifTrue)\n\n                // Exit\n                .append(exitLabel);\n\n    }\n\n    public BytecodeLabel getTrueLabel() {\n        return trueLabel;\n    }\n\n    public BytecodeLabel getExitLabel() {\n        return exitLabel;\n    }\n}\n"
  },
  {
    "path": "xyz.itzsomebody.codegen/src/main/java/xyz/itzsomebody/codegen/expressions/flow/IRSwitchStructure.java",
    "content": "/*\n * Radon - An open-source Java obfuscator\n * Copyright (C) 2021 ItzSomebody\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, either version 3 of the License, or\n * (at your option) any later version.\n *\n * This program is distributed in the hope that it will be 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.  If not, see <http://www.gnu.org/licenses/>\n */\n\npackage xyz.itzsomebody.codegen.expressions.flow;\n\nimport org.jetbrains.annotations.NotNull;\nimport xyz.itzsomebody.codegen.BytecodeBlock;\nimport xyz.itzsomebody.codegen.expressions.IRExpression;\nimport xyz.itzsomebody.codegen.instructions.BytecodeLabel;\nimport xyz.itzsomebody.codegen.instructions.JumpNode;\nimport xyz.itzsomebody.codegen.instructions.SwitchNode;\n\nimport java.util.ArrayList;\nimport java.util.SortedSet;\nimport java.util.TreeSet;\nimport java.util.stream.Collectors;\nimport java.util.stream.IntStream;\n\npublic class IRSwitchStructure extends IRFlowStructure {\n    private final IRExpression operand;\n    private final SortedSet<IRCaseStructure> cases = new TreeSet<>();\n    private final BytecodeBlock defaultBody;\n    private final ArrayList<BytecodeLabel> caseLabels = new ArrayList<>();\n    private final BytecodeLabel defaultLabel = new BytecodeLabel();\n    private final BytecodeLabel exitLabel = new BytecodeLabel();\n\n    public IRSwitchStructure(IRExpression operand, ArrayList<Integer> keys, ArrayList<BytecodeBlock> caseBodies, BytecodeBlock defaultBody) {\n        this.operand = operand;\n        this.defaultBody = defaultBody;\n\n        IntStream.range(0, keys.size()).forEach(index -> cases.add(new IRCaseStructure(keys.get(index), caseBodies.get(index))));\n    }\n\n    @Override\n    public BytecodeBlock getInstructions() {\n        var block = new BytecodeBlock()\n                .append(operand.getInstructions())\n                .append(new SwitchNode(cases.stream().map(IRCaseStructure::getKey).collect(Collectors.toList()), caseLabels, defaultLabel));\n\n        // Cases\n        cases.forEach(caseStructure -> {\n            var caseLabel = new BytecodeLabel();\n            block.append(caseLabel)\n                    .append(caseStructure.getBody())\n                    .append(JumpNode.jumpUnconditionally(exitLabel));\n            caseLabels.add(caseLabel);\n        });\n\n        // Default\n        block.append(defaultLabel)\n                .append(defaultBody);\n\n        // Exit\n        block.append(exitLabel);\n        return block;\n    }\n\n    public ArrayList<BytecodeLabel> getCaseLabels() {\n        return caseLabels;\n    }\n\n    public BytecodeLabel getDefaultLabel() {\n        return defaultLabel;\n    }\n\n    public BytecodeLabel getExitLabel() {\n        return exitLabel;\n    }\n\n    static class IRCaseStructure implements Comparable<IRCaseStructure> {\n        private final int key;\n        private final BytecodeBlock body;\n\n        IRCaseStructure(int key, BytecodeBlock body) {\n            this.key = key;\n            this.body = body;\n        }\n\n        public int getKey() {\n            return key;\n        }\n\n        public BytecodeBlock getBody() {\n            return body;\n        }\n\n        @Override\n        public int compareTo(@NotNull IRSwitchStructure.IRCaseStructure other) {\n            return Integer.compare(key, other.key);\n        }\n    }\n}\n"
  },
  {
    "path": "xyz.itzsomebody.codegen/src/main/java/xyz/itzsomebody/codegen/expressions/flow/IRSynchronizedStructure.java",
    "content": "/*\n * Radon - An open-source Java obfuscator\n * Copyright (C) 2021 ItzSomebody\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, either version 3 of the License, or\n * (at your option) any later version.\n *\n * This program is distributed in the hope that it will be 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.  If not, see <http://www.gnu.org/licenses/>\n */\n\npackage xyz.itzsomebody.codegen.expressions.flow;\n\nimport xyz.itzsomebody.codegen.BytecodeBlock;\nimport xyz.itzsomebody.codegen.expressions.IRExpression;\nimport xyz.itzsomebody.codegen.instructions.SimpleNode;\n\npublic class IRSynchronizedStructure extends IRFlowStructure {\n    private final IRExpression instance;\n    private final BytecodeBlock body;\n\n    public IRSynchronizedStructure(IRExpression instance, BytecodeBlock body) {\n        this.instance = instance;\n        this.body = body;\n    }\n\n    @Override\n    public BytecodeBlock getInstructions() {\n        return new BytecodeBlock()\n                .append(instance.getInstructions())\n                .append(SimpleNode.ENTER_MONITOR)\n                .append(body)\n                .append(instance.getInstructions())\n                .append(SimpleNode.EXIT_MONITOR);\n    }\n}\n"
  },
  {
    "path": "xyz.itzsomebody.codegen/src/main/java/xyz/itzsomebody/codegen/expressions/flow/IRTryCatchStructure.java",
    "content": "/*\n * Radon - An open-source Java obfuscator\n * Copyright (C) 2021 ItzSomebody\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, either version 3 of the License, or\n * (at your option) any later version.\n *\n * This program is distributed in the hope that it will be 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.  If not, see <http://www.gnu.org/licenses/>\n */\n\npackage xyz.itzsomebody.codegen.expressions.flow;\n\nimport org.objectweb.asm.tree.TryCatchBlockNode;\nimport xyz.itzsomebody.codegen.BytecodeBlock;\nimport xyz.itzsomebody.codegen.WrappedType;\nimport xyz.itzsomebody.codegen.instructions.BytecodeLabel;\nimport xyz.itzsomebody.codegen.instructions.JumpNode;\n\npublic class IRTryCatchStructure extends IRFlowStructure {\n    private final BytecodeBlock trapRange;\n    private final BytecodeBlock handler;\n    private final WrappedType exceptionType;\n    private final BytecodeLabel trapStartLabel = new BytecodeLabel();\n    private final BytecodeLabel trapEndLabel = new BytecodeLabel();\n    private final BytecodeLabel handlerLabel = new BytecodeLabel();\n    private final BytecodeLabel exitLabel = new BytecodeLabel();\n\n    public IRTryCatchStructure(BytecodeBlock trapRange, BytecodeBlock handler, WrappedType exceptionType) {\n        this.trapRange = trapRange;\n        this.handler = handler;\n        this.exceptionType = exceptionType;\n    }\n\n    public TryCatchBlockNode getTryCatchBlocKNode() {\n        return new TryCatchBlockNode(trapStartLabel.getLabel(), trapEndLabel.getLabel(), handlerLabel.getLabel(), exceptionType.getInternalName());\n    }\n\n    @Override\n    public BytecodeBlock getInstructions() {\n        return new BytecodeBlock()\n                // Try block\n                .append(trapStartLabel)\n                .append(trapRange)\n                .append(trapEndLabel)\n                .append(JumpNode.jumpUnconditionally(exitLabel)) // No exception has been thrown so skip the handler\n\n                // Catch block\n                .append(handlerLabel)\n                .append(handler)\n\n                // Exit\n                .append(exitLabel);\n    }\n\n    public BytecodeLabel getTrapStartLabel() {\n        return trapStartLabel;\n    }\n\n    public BytecodeLabel getTrapEndLabel() {\n        return trapEndLabel;\n    }\n\n    public BytecodeLabel getHandlerLabel() {\n        return handlerLabel;\n    }\n\n    public BytecodeLabel getExitLabel() {\n        return exitLabel;\n    }\n}\n"
  },
  {
    "path": "xyz.itzsomebody.codegen/src/main/java/xyz/itzsomebody/codegen/expressions/flow/IRWhileStructure.java",
    "content": "/*\n * Radon - An open-source Java obfuscator\n * Copyright (C) 2021 ItzSomebody\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, either version 3 of the License, or\n * (at your option) any later version.\n *\n * This program is distributed in the hope that it will be 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.  If not, see <http://www.gnu.org/licenses/>\n */\n\npackage xyz.itzsomebody.codegen.expressions.flow;\n\nimport xyz.itzsomebody.codegen.BytecodeBlock;\nimport xyz.itzsomebody.codegen.instructions.BytecodeLabel;\nimport xyz.itzsomebody.codegen.instructions.JumpNode;\n\npublic class IRWhileStructure extends IRFlowStructure {\n    private final BytecodeBlock condition;\n    private final BytecodeBlock body;\n    private final BytecodeLabel continueLabel = new BytecodeLabel();\n    private final BytecodeLabel exitLabel = new BytecodeLabel();\n\n    public IRWhileStructure(BytecodeBlock condition, BytecodeBlock body) {\n        this.condition = condition;\n        this.body = body;\n    }\n\n    @Override\n    public BytecodeBlock getInstructions() {\n        return new BytecodeBlock()\n                // Condition\n                .append(continueLabel)\n                .append(condition)\n                .append(JumpNode.jumpIfZero(exitLabel)) // Exit if false\n\n                // Body\n                .append(body)\n                .append(JumpNode.jumpUnconditionally(continueLabel)) // Next iteration\n\n                // Exit\n                .append(exitLabel);\n    }\n\n    public BytecodeLabel getContinueLabel() {\n        return continueLabel;\n    }\n\n    public BytecodeLabel getExitLabel() {\n        return exitLabel;\n    }\n}\n"
  },
  {
    "path": "xyz.itzsomebody.codegen/src/main/java/xyz/itzsomebody/codegen/expressions/predefined/IRArithmeticExpression.java",
    "content": "/*\n * Radon - An open-source Java obfuscator\n * Copyright (C) 2021 ItzSomebody\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, either version 3 of the License, or\n * (at your option) any later version.\n *\n * This program is distributed in the hope that it will be 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.  If not, see <http://www.gnu.org/licenses/>\n */\n\npackage xyz.itzsomebody.codegen.expressions.predefined;\n\nimport xyz.itzsomebody.codegen.BytecodeBlock;\nimport xyz.itzsomebody.codegen.expressions.IRExpression;\nimport xyz.itzsomebody.codegen.instructions.SimpleNode;\n\npublic class IRArithmeticExpression extends IRExpression {\n    private final SimpleNode operation;\n    private final IRExpression left;\n    private final IRExpression right;\n\n    public IRArithmeticExpression(SimpleNode operation, IRExpression left, IRExpression right) {\n        super(left.getType()); // Left expression should ALWAYS be the resultant type (i.e. LSHL/LSHR/LUSHR)\n        this.operation = operation;\n        this.left = left;\n        this.right = right;\n    }\n\n    @Override\n    public BytecodeBlock getInstructions() {\n        return new BytecodeBlock()\n                .append(left.getInstructions())\n                .append(right.getInstructions())\n                .append(operation);\n\n    }\n}\n"
  },
  {
    "path": "xyz.itzsomebody.codegen/src/main/java/xyz/itzsomebody/codegen/expressions/predefined/IRArrayLengthExpression.java",
    "content": "/*\n * Radon - An open-source Java obfuscator\n * Copyright (C) 2021 ItzSomebody\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, either version 3 of the License, or\n * (at your option) any later version.\n *\n * This program is distributed in the hope that it will be 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.  If not, see <http://www.gnu.org/licenses/>\n */\n\npackage xyz.itzsomebody.codegen.expressions.predefined;\n\nimport xyz.itzsomebody.codegen.BytecodeBlock;\nimport xyz.itzsomebody.codegen.WrappedType;\nimport xyz.itzsomebody.codegen.expressions.IRExpression;\nimport xyz.itzsomebody.codegen.instructions.SimpleNode;\n\npublic class IRArrayLengthExpression extends IRExpression {\n    private final IRExpression array;\n\n    public IRArrayLengthExpression(IRExpression array) {\n        super(WrappedType.from(int.class));\n        this.array = array;\n    }\n\n    @Override\n    public BytecodeBlock getInstructions() {\n        return new BytecodeBlock()\n                .append(array.getInstructions())\n                .append(SimpleNode.ARRAY_LENGTH);\n    }\n}\n"
  },
  {
    "path": "xyz.itzsomebody.codegen/src/main/java/xyz/itzsomebody/codegen/expressions/predefined/IRCastExpression.java",
    "content": "/*\n * Radon - An open-source Java obfuscator\n * Copyright (C) 2021 ItzSomebody\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, either version 3 of the License, or\n * (at your option) any later version.\n *\n * This program is distributed in the hope that it will be 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.  If not, see <http://www.gnu.org/licenses/>\n */\n\npackage xyz.itzsomebody.codegen.expressions.predefined;\n\nimport org.objectweb.asm.Type;\nimport xyz.itzsomebody.codegen.BytecodeBlock;\nimport xyz.itzsomebody.codegen.Utils;\nimport xyz.itzsomebody.codegen.WrappedType;\nimport xyz.itzsomebody.codegen.exceptions.UncompilableNodeException;\nimport xyz.itzsomebody.codegen.expressions.IRExpression;\nimport xyz.itzsomebody.codegen.instructions.InvokeNode;\nimport xyz.itzsomebody.codegen.instructions.SimpleNode;\nimport xyz.itzsomebody.codegen.instructions.TypeNode;\n\nimport java.util.Collections;\nimport java.util.List;\n\npublic class IRCastExpression extends IRExpression {\n    private final IRExpression castMe;\n\n    public IRCastExpression(IRExpression castMe, WrappedType castType) {\n        super(castType);\n        this.castMe = castMe;\n    }\n\n    @Override\n    public BytecodeBlock getInstructions() {\n        var block = new BytecodeBlock().append(castMe.getInstructions());\n        var currentType = castMe.getType();\n        var targetType = getType();\n\n        if (currentType.equals(targetType)) {\n            return block;\n        }\n\n        if (currentType.isPrimitive()) {\n            if (targetType.isPrimitive()) {\n                castPrimitives(block, currentType, targetType);\n            } else if (targetType.isBoxed()) {\n                block.append(InvokeNode.invokeStatic(targetType, \"valueOf\", List.of(currentType), targetType));\n            } else {\n                block.append(InvokeNode.invokeStatic(Utils.box(currentType), \"valueOf\", List.of(currentType), Utils.box(currentType)))\n                        .append(TypeNode.cast(targetType));\n            }\n        } else if (currentType.isBoxed()) {\n            if (targetType.isPrimitive()) {\n                var primitiveType = currentType.getPrimitiveType();\n                block.append(InvokeNode.invokeVirtual(currentType, primitiveType.getClassName() + \"Value\", Collections.emptyList(), primitiveType));\n                castPrimitives(block, primitiveType, targetType);\n            } else {\n                block.append(TypeNode.cast(targetType));\n            }\n        } else {\n            if (targetType.isPrimitive()) {\n                var primitiveType = targetType.getPrimitiveType();\n                block.append(TypeNode.cast(Utils.box(targetType)))\n                        .append(InvokeNode.invokeVirtual(targetType, primitiveType.getClassName() + \"Value\", Collections.emptyList(), primitiveType));\n            } else {\n                block.append(TypeNode.cast(targetType));\n            }\n        }\n\n        return block;\n    }\n\n    @SuppressWarnings(\"Duplicates\")\n    private static void castPrimitives(BytecodeBlock block, WrappedType source, WrappedType target) {\n        var sourceSort = source.getSort();\n        var targetSort = target.getSort();\n\n        if (sourceSort == targetSort) {\n            return; // Casting primitive to same primitive type = redundant\n        }\n\n        if (sourceSort == Type.BOOLEAN || sourceSort == Type.BYTE) {\n            if (target.isIntType()) {\n                return;\n            }\n            if (targetSort == Type.FLOAT) {\n                block.append(SimpleNode.CAST_INT_TO_FLOAT);\n                return;\n            } else if (targetSort == Type.LONG) {\n                block.append(SimpleNode.CAST_INT_TO_LONG);\n                return;\n            } else if (targetSort == Type.DOUBLE) {\n                block.append(SimpleNode.CAST_INT_TO_DOUBLE);\n                return;\n            }\n        } else if (sourceSort == Type.CHAR) {\n            if (targetSort == Type.BYTE) {\n                block.append(SimpleNode.CAST_INT_TO_BYTE);\n                return;\n            }\n            if (target.isIntType()) { // Non-byte integer\n                return;\n            }\n            if (targetSort == Type.FLOAT) {\n                block.append(SimpleNode.CAST_INT_TO_FLOAT);\n                return;\n            } else if (targetSort == Type.LONG) {\n                block.append(SimpleNode.CAST_INT_TO_LONG);\n                return;\n            } else if (targetSort == Type.DOUBLE) {\n                block.append(SimpleNode.CAST_INT_TO_DOUBLE);\n                return;\n            }\n        } else if (sourceSort == Type.SHORT) {\n            if (targetSort == Type.BYTE) {\n                block.append(SimpleNode.CAST_INT_TO_BYTE);\n                return;\n            }\n            if (targetSort == Type.CHAR) {\n                block.append(SimpleNode.CAST_INT_TO_CHAR);\n                return;\n            }\n            if (target.isIntType()) { // Non-byte integer\n                return;\n            }\n            if (targetSort == Type.FLOAT) {\n                block.append(SimpleNode.CAST_INT_TO_FLOAT);\n                return;\n            } else if (targetSort == Type.LONG) {\n                block.append(SimpleNode.CAST_INT_TO_LONG);\n                return;\n            } else if (targetSort == Type.DOUBLE) {\n                block.append(SimpleNode.CAST_INT_TO_DOUBLE);\n                return;\n            }\n        } else if (sourceSort == Type.INT) {\n            if (targetSort == Type.BYTE) {\n                block.append(SimpleNode.CAST_INT_TO_BYTE);\n                return;\n            } else if (targetSort == Type.CHAR) {\n                block.append(SimpleNode.CAST_INT_TO_CHAR);\n                return;\n            } else if (targetSort == Type.SHORT) {\n                block.append(SimpleNode.CAST_INT_TO_SHORT);\n                return;\n            } else if (targetSort == Type.FLOAT) {\n                block.append(SimpleNode.CAST_INT_TO_FLOAT);\n                return;\n            } else if (targetSort == Type.LONG) {\n                block.append(SimpleNode.CAST_INT_TO_LONG);\n                return;\n            } else if (targetSort == Type.DOUBLE) {\n                block.append(SimpleNode.CAST_INT_TO_DOUBLE);\n                return;\n            }\n        } else if (sourceSort == Type.LONG) {\n            if (target.isIntType()) {\n                block.append(SimpleNode.CAST_LONG_TO_INT);\n                if (targetSort == Type.BYTE) {\n                    block.append(SimpleNode.CAST_INT_TO_BYTE);\n                } else if (targetSort == Type.CHAR) {\n                    block.append(SimpleNode.CAST_INT_TO_CHAR);\n                } else if (targetSort == Type.SHORT) {\n                    block.append(SimpleNode.CAST_INT_TO_SHORT);\n                }\n                return;\n            } else if (targetSort == Type.FLOAT) {\n                block.append(SimpleNode.CAST_LONG_TO_FLOAT);\n                return;\n            } else if (targetSort == Type.DOUBLE) {\n                block.append(SimpleNode.CAST_LONG_TO_DOUBLE);\n                return;\n            }\n        } else if (sourceSort == Type.FLOAT) {\n            if (target.isIntType()) {\n                block.append(SimpleNode.CAST_FLOAT_TO_INT);\n                if (targetSort == Type.BYTE) {\n                    block.append(SimpleNode.CAST_INT_TO_BYTE);\n                } else if (targetSort == Type.CHAR) {\n                    block.append(SimpleNode.CAST_INT_TO_CHAR);\n                } else if (targetSort == Type.SHORT) {\n                    block.append(SimpleNode.CAST_INT_TO_SHORT);\n                }\n                return;\n            } else if (targetSort == Type.LONG) {\n                block.append(SimpleNode.CAST_FLOAT_TO_LONG);\n                return;\n            } else if (targetSort == Type.DOUBLE) {\n                block.append(SimpleNode.CAST_FLOAT_TO_DOUBLE);\n                return;\n            }\n        } else if (sourceSort == Type.DOUBLE) {\n            if (target.isIntType()) {\n                block.append(SimpleNode.CAST_DOUBLE_TO_INT);\n                if (targetSort == Type.BYTE) {\n                    block.append(SimpleNode.CAST_INT_TO_BYTE);\n                } else if (targetSort == Type.CHAR) {\n                    block.append(SimpleNode.CAST_INT_TO_CHAR);\n                } else if (targetSort == Type.SHORT) {\n                    block.append(SimpleNode.CAST_INT_TO_SHORT);\n                }\n                return;\n            } else if (targetSort == Type.FLOAT) {\n                block.append(SimpleNode.CAST_DOUBLE_TO_FLOAT);\n                return;\n            } else if (targetSort == Type.LONG) {\n                block.append(SimpleNode.CAST_DOUBLE_TO_LONG);\n                return;\n            }\n        }\n        throw new UncompilableNodeException(\"Cannot cast \" + source + \" to \" + target);\n    }\n}\n"
  },
  {
    "path": "xyz.itzsomebody.codegen/src/main/java/xyz/itzsomebody/codegen/expressions/predefined/IRConstantExpression.java",
    "content": "/*\n * Radon - An open-source Java obfuscator\n * Copyright (C) 2021 ItzSomebody\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, either version 3 of the License, or\n * (at your option) any later version.\n *\n * This program is distributed in the hope that it will be 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.  If not, see <http://www.gnu.org/licenses/>\n */\n\npackage xyz.itzsomebody.codegen.expressions.predefined;\n\nimport xyz.itzsomebody.codegen.BytecodeBlock;\nimport xyz.itzsomebody.codegen.WrappedType;\nimport xyz.itzsomebody.codegen.expressions.IRExpression;\nimport xyz.itzsomebody.codegen.instructions.ConstantNode;\n\npublic class IRConstantExpression extends IRExpression {\n    private final ConstantNode cst;\n\n    public IRConstantExpression(ConstantNode cst, WrappedType type) {\n        super(type);\n        this.cst = cst;\n    }\n\n    @Override\n    public BytecodeBlock getInstructions() {\n        return new BytecodeBlock().append(cst);\n    }\n}\n"
  },
  {
    "path": "xyz.itzsomebody.codegen/src/main/java/xyz/itzsomebody/codegen/expressions/predefined/IRGetArrayElementExpression.java",
    "content": "/*\n * Radon - An open-source Java obfuscator\n * Copyright (C) 2021 ItzSomebody\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, either version 3 of the License, or\n * (at your option) any later version.\n *\n * This program is distributed in the hope that it will be 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.  If not, see <http://www.gnu.org/licenses/>\n */\n\npackage xyz.itzsomebody.codegen.expressions.predefined;\n\nimport xyz.itzsomebody.codegen.BytecodeBlock;\nimport xyz.itzsomebody.codegen.expressions.IRExpression;\nimport xyz.itzsomebody.codegen.instructions.SimpleNode;\n\npublic class IRGetArrayElementExpression extends IRExpression {\n    private final IRExpression array;\n    private final IRExpression index;\n\n    public IRGetArrayElementExpression(IRExpression array, IRExpression index) {\n        super(array.getType());\n        this.array = array;\n        this.index = index;\n    }\n\n    @Override\n    public BytecodeBlock getInstructions() {\n        return new BytecodeBlock()\n                .append(array.getInstructions())\n                .append(index.getInstructions())\n                .append(SimpleNode.getArrayLoadOp(getType()));\n    }\n}\n"
  },
  {
    "path": "xyz.itzsomebody.codegen/src/main/java/xyz/itzsomebody/codegen/expressions/predefined/IRGetFieldExpression.java",
    "content": "/*\n * Radon - An open-source Java obfuscator\n * Copyright (C) 2021 ItzSomebody\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, either version 3 of the License, or\n * (at your option) any later version.\n *\n * This program is distributed in the hope that it will be 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.  If not, see <http://www.gnu.org/licenses/>\n */\n\npackage xyz.itzsomebody.codegen.expressions.predefined;\n\nimport xyz.itzsomebody.codegen.BytecodeBlock;\nimport xyz.itzsomebody.codegen.WrappedType;\nimport xyz.itzsomebody.codegen.expressions.IRExpression;\nimport xyz.itzsomebody.codegen.instructions.FieldAccessNode;\n\nimport java.lang.reflect.Field;\n\npublic class IRGetFieldExpression extends IRExpression {\n    private final IRExpression instance;\n    private final WrappedType owner;\n    private final String name;\n\n    public IRGetFieldExpression(IRExpression instance, WrappedType owner, String name, WrappedType type) {\n        super(type);\n        this.instance = instance;\n        this.owner = owner;\n        this.name = name;\n    }\n\n    public IRGetFieldExpression(IRExpression instance, Field field) {\n        this(instance, WrappedType.from(field.getDeclaringClass()), field.getName(), WrappedType.from(field.getType()));\n    }\n\n    @Override\n    public BytecodeBlock getInstructions() {\n        if (instance == null) {\n            return new BytecodeBlock().append(FieldAccessNode.getStatic(owner, name, getType()));\n        } else {\n            return new BytecodeBlock()\n                    .append(instance.getInstructions())\n                    .append(FieldAccessNode.getField(owner, name, getType()));\n        }\n    }\n}\n"
  },
  {
    "path": "xyz.itzsomebody.codegen/src/main/java/xyz/itzsomebody/codegen/expressions/predefined/IRInstanceOfExpression.java",
    "content": "/*\n * Radon - An open-source Java obfuscator\n * Copyright (C) 2021 ItzSomebody\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, either version 3 of the License, or\n * (at your option) any later version.\n *\n * This program is distributed in the hope that it will be 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.  If not, see <http://www.gnu.org/licenses/>\n */\n\npackage xyz.itzsomebody.codegen.expressions.predefined;\n\nimport xyz.itzsomebody.codegen.BytecodeBlock;\nimport xyz.itzsomebody.codegen.WrappedType;\nimport xyz.itzsomebody.codegen.expressions.IRExpression;\nimport xyz.itzsomebody.codegen.instructions.TypeNode;\n\npublic class IRInstanceOfExpression extends IRExpression {\n    private final IRExpression instance;\n    private final WrappedType type;\n\n    public IRInstanceOfExpression(IRExpression instance, WrappedType type) {\n        super(WrappedType.from(boolean.class));\n        this.instance = instance;\n        this.type = type;\n    }\n\n    @Override\n    public BytecodeBlock getInstructions() {\n        return new BytecodeBlock()\n                .append(instance.getInstructions())\n                .append(TypeNode.instanceOf(type));\n    }\n}\n"
  },
  {
    "path": "xyz.itzsomebody.codegen/src/main/java/xyz/itzsomebody/codegen/expressions/predefined/IRInvocationExpression.java",
    "content": "/*\n * Radon - An open-source Java obfuscator\n * Copyright (C) 2021 ItzSomebody\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, either version 3 of the License, or\n * (at your option) any later version.\n *\n * This program is distributed in the hope that it will be 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.  If not, see <http://www.gnu.org/licenses/>\n */\n\npackage xyz.itzsomebody.codegen.expressions.predefined;\n\nimport xyz.itzsomebody.codegen.BytecodeBlock;\nimport xyz.itzsomebody.codegen.Utils;\nimport xyz.itzsomebody.codegen.WrappedType;\nimport xyz.itzsomebody.codegen.expressions.IRExpression;\nimport xyz.itzsomebody.codegen.instructions.InvokeNode;\n\nimport java.lang.reflect.Method;\nimport java.util.List;\n\npublic class IRInvocationExpression extends IRExpression {\n    private final IRExpression instance;\n    private final WrappedType owner;\n    private final String name;\n    private final List<IRExpression> args;\n    private final List<WrappedType> argTypes;\n\n    public IRInvocationExpression(IRExpression instance, WrappedType owner, String name, List<IRExpression> args, List<WrappedType> argTypes, WrappedType returnType) {\n        super(returnType);\n        this.instance = instance;\n        this.owner = owner;\n        this.name = name;\n        this.args = args;\n        this.argTypes = argTypes;\n    }\n\n    public IRInvocationExpression(IRExpression instance, Method method, List<IRExpression> args) {\n        this(instance, WrappedType.from(method.getDeclaringClass()), method.getName(), args, Utils.wrapMethodParameters(method), WrappedType.from(method.getReturnType()));\n    }\n\n    @Override\n    public BytecodeBlock getInstructions() {\n        var block = new BytecodeBlock();\n\n        if (instance != null) {\n            block.append(instance.getInstructions());\n        }\n\n        args.forEach(arg -> block.append(arg.getInstructions()));\n\n        if (instance == null) {\n            block.append(InvokeNode.invokeStatic(owner, name, argTypes, getType()));\n        } else if (owner.isInterface()) {\n            block.append(InvokeNode.invokeInterface(owner, name, argTypes, getType()));\n        } else {\n            block.append(InvokeNode.invokeVirtual(owner, name, argTypes, getType()));\n        }\n\n        return block;\n    }\n}\n"
  },
  {
    "path": "xyz.itzsomebody.codegen/src/main/java/xyz/itzsomebody/codegen/expressions/predefined/IRInvokeDynamicExpression.java",
    "content": "/*\n * Radon - An open-source Java obfuscator\n * Copyright (C) 2021 ItzSomebody\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, either version 3 of the License, or\n * (at your option) any later version.\n *\n * This program is distributed in the hope that it will be 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.  If not, see <http://www.gnu.org/licenses/>\n */\n\npackage xyz.itzsomebody.codegen.expressions.predefined;\n\nimport xyz.itzsomebody.codegen.BytecodeBlock;\nimport xyz.itzsomebody.codegen.WrappedHandle;\nimport xyz.itzsomebody.codegen.WrappedType;\nimport xyz.itzsomebody.codegen.expressions.IRExpression;\nimport xyz.itzsomebody.codegen.instructions.ConstantNode;\nimport xyz.itzsomebody.codegen.instructions.InvokeDynamicNode;\n\nimport java.util.List;\n\npublic class IRInvokeDynamicExpression extends IRExpression {\n    private final String name;\n    private final List<IRExpression> args;\n    private final List<WrappedType> argTypes;\n    private final WrappedHandle bootstrap;\n    private final List<ConstantNode> bootstrapArgs;\n\n    public IRInvokeDynamicExpression(String name, List<IRExpression> args, List<WrappedType> argTypes, WrappedType returnType, WrappedHandle bootstrap, List<ConstantNode> bootstrapArgs) {\n        super(returnType);\n        this.name = name;\n        this.args = args;\n        this.argTypes = argTypes;\n        this.bootstrap = bootstrap;\n        this.bootstrapArgs = bootstrapArgs;\n    }\n\n    @Override\n    public BytecodeBlock getInstructions() {\n        var block = new BytecodeBlock();\n        args.forEach(arg -> block.append(arg.getInstructions()));\n        block.append(InvokeDynamicNode.invokeDynamic(name, argTypes, getType(), bootstrap, bootstrapArgs));\n        return block;\n    }\n}\n"
  },
  {
    "path": "xyz.itzsomebody.codegen/src/main/java/xyz/itzsomebody/codegen/expressions/predefined/IRNegateExpression.java",
    "content": "/*\n * Radon - An open-source Java obfuscator\n * Copyright (C) 2021 ItzSomebody\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, either version 3 of the License, or\n * (at your option) any later version.\n *\n * This program is distributed in the hope that it will be 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.  If not, see <http://www.gnu.org/licenses/>\n */\n\npackage xyz.itzsomebody.codegen.expressions.predefined;\n\nimport xyz.itzsomebody.codegen.BytecodeBlock;\nimport xyz.itzsomebody.codegen.expressions.IRExpression;\nimport xyz.itzsomebody.codegen.instructions.SimpleNode;\n\npublic class IRNegateExpression extends IRExpression {\n    private final IRExpression operand;\n\n    public IRNegateExpression(IRExpression operand) {\n        super(operand.getType());\n        this.operand = operand;\n    }\n\n    @Override\n    public BytecodeBlock getInstructions() {\n        return new BytecodeBlock()\n                .append(operand.getInstructions())\n                .append(SimpleNode.negateOpcodeFor(operand.getType()));\n    }\n}\n"
  },
  {
    "path": "xyz.itzsomebody.codegen/src/main/java/xyz/itzsomebody/codegen/expressions/predefined/IRNewArrayExpression.java",
    "content": "/*\n * Radon - An open-source Java obfuscator\n * Copyright (C) 2021 ItzSomebody\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, either version 3 of the License, or\n * (at your option) any later version.\n *\n * This program is distributed in the hope that it will be 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.  If not, see <http://www.gnu.org/licenses/>\n */\n\npackage xyz.itzsomebody.codegen.expressions.predefined;\n\nimport xyz.itzsomebody.codegen.BytecodeBlock;\nimport xyz.itzsomebody.codegen.WrappedType;\nimport xyz.itzsomebody.codegen.expressions.IRExpression;\nimport xyz.itzsomebody.codegen.instructions.ConstantNode;\nimport xyz.itzsomebody.codegen.instructions.NewArrayNode;\nimport xyz.itzsomebody.codegen.instructions.SimpleNode;\n\npublic class IRNewArrayExpression extends IRExpression {\n    private final IRExpression length;\n    private final WrappedType type;\n    private final IRExpression[] elements;\n\n    public IRNewArrayExpression(IRExpression length, WrappedType type, IRExpression[] elements) {\n        super(type);\n        this.length = length;\n        this.type = type;\n        this.elements = elements;\n    }\n\n    @Override\n    public BytecodeBlock getInstructions() {\n        BytecodeBlock block = new BytecodeBlock()\n                .append(length.getInstructions())\n                .append(new NewArrayNode(type));\n        for (int i = 0; i < elements.length; i++) {\n            IRExpression element = elements[i];\n            block.append(SimpleNode.DUP)\n                    .append(ConstantNode.intConst(i))\n                    .append(element.getInstructions())\n                    .append(SimpleNode.getArrayStoreOp(type));\n        }\n        return block;\n    }\n}\n"
  },
  {
    "path": "xyz.itzsomebody.codegen/src/main/java/xyz/itzsomebody/codegen/expressions/predefined/IRNewInstanceExpression.java",
    "content": "/*\n * Radon - An open-source Java obfuscator\n * Copyright (C) 2021 ItzSomebody\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, either version 3 of the License, or\n * (at your option) any later version.\n *\n * This program is distributed in the hope that it will be 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.  If not, see <http://www.gnu.org/licenses/>\n */\n\npackage xyz.itzsomebody.codegen.expressions.predefined;\n\nimport xyz.itzsomebody.codegen.BytecodeBlock;\nimport xyz.itzsomebody.codegen.WrappedType;\nimport xyz.itzsomebody.codegen.expressions.IRExpression;\nimport xyz.itzsomebody.codegen.instructions.InvokeNode;\nimport xyz.itzsomebody.codegen.instructions.SimpleNode;\nimport xyz.itzsomebody.codegen.instructions.TypeNode;\n\nimport java.util.List;\n\npublic class IRNewInstanceExpression extends IRExpression {\n    private final List<WrappedType> argumentTypes;\n    private final List<IRExpression> arguments;\n\n    public IRNewInstanceExpression(WrappedType type, List<WrappedType> argumentTypes, List<IRExpression> arguments) {\n        super(type);\n        this.argumentTypes = argumentTypes;\n        this.arguments = arguments;\n    }\n\n    @Override\n    public BytecodeBlock getInstructions() {\n        var block = new BytecodeBlock()\n                .append(TypeNode.newInstance(getType()))\n                .append(SimpleNode.DUP);\n        for (var expr : arguments) {\n            block.append(expr.getInstructions());\n        }\n        block.append(InvokeNode.invokeConstructor(getType(), argumentTypes));\n        return block;\n    }\n}\n"
  },
  {
    "path": "xyz.itzsomebody.codegen/src/main/java/xyz/itzsomebody/codegen/expressions/predefined/IRReturnExpression.java",
    "content": "/*\n * Radon - An open-source Java obfuscator\n * Copyright (C) 2021 ItzSomebody\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, either version 3 of the License, or\n * (at your option) any later version.\n *\n * This program is distributed in the hope that it will be 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.  If not, see <http://www.gnu.org/licenses/>\n */\n\npackage xyz.itzsomebody.codegen.expressions.predefined;\n\nimport org.objectweb.asm.Type;\nimport xyz.itzsomebody.codegen.BytecodeBlock;\nimport xyz.itzsomebody.codegen.WrappedType;\nimport xyz.itzsomebody.codegen.expressions.IRExpression;\nimport xyz.itzsomebody.codegen.instructions.SimpleNode;\n\npublic class IRReturnExpression extends IRExpression {\n    private final IRExpression target;\n\n    public IRReturnExpression(IRExpression target) {\n        super(WrappedType.getAbsent());\n        this.target = target;\n    }\n\n    @Override\n    public BytecodeBlock getInstructions() {\n        if (target == null) {\n            return new BytecodeBlock().append(SimpleNode.RETURN_VOID);\n        }\n\n        var block = new BytecodeBlock().append(target.getInstructions());\n        var type = target.getType();\n\n        switch (type.getSort()) {\n            case Type.VOID:\n                block.append(SimpleNode.RETURN_VOID);\n                break;\n            case Type.BOOLEAN:\n            case Type.CHAR:\n            case Type.BYTE:\n            case Type.SHORT:\n            case Type.INT:\n                block.append(SimpleNode.RETURN_INT);\n                break;\n            case Type.FLOAT:\n                block.append(SimpleNode.RETURN_FLOAT);\n                break;\n            case Type.LONG:\n                block.append(SimpleNode.RETURN_LONG);\n                break;\n            case Type.DOUBLE:\n                block.append(SimpleNode.RETURN_DOUBLE);\n                break;\n            default:\n                block.append(SimpleNode.RETURN_OBJECT);\n        }\n        return block;\n    }\n}\n"
  },
  {
    "path": "xyz.itzsomebody.codegen/src/main/java/xyz/itzsomebody/codegen/expressions/predefined/IRSetArrayElementExpression.java",
    "content": "/*\n * Radon - An open-source Java obfuscator\n * Copyright (C) 2021 ItzSomebody\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, either version 3 of the License, or\n * (at your option) any later version.\n *\n * This program is distributed in the hope that it will be 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.  If not, see <http://www.gnu.org/licenses/>\n */\n\npackage xyz.itzsomebody.codegen.expressions.predefined;\n\nimport xyz.itzsomebody.codegen.BytecodeBlock;\nimport xyz.itzsomebody.codegen.WrappedType;\nimport xyz.itzsomebody.codegen.expressions.IRExpression;\nimport xyz.itzsomebody.codegen.instructions.SimpleNode;\n\npublic class IRSetArrayElementExpression extends IRExpression {\n    private final IRExpression array;\n    private final IRExpression index;\n    private final IRExpression value;\n\n    public IRSetArrayElementExpression(IRExpression array, IRExpression index, IRExpression value) {\n        super(WrappedType.getAbsent());\n        this.array = array;\n        this.index = index;\n        this.value = value;\n    }\n\n    @Override\n    public BytecodeBlock getInstructions() {\n        return new BytecodeBlock()\n                .append(array.getInstructions())\n                .append(index.getInstructions())\n                .append(value.getInstructions())\n                .append(SimpleNode.getArrayStoreOp(array.getType()));\n    }\n}\n"
  },
  {
    "path": "xyz.itzsomebody.codegen/src/main/java/xyz/itzsomebody/codegen/expressions/predefined/IRSetFieldExpression.java",
    "content": "/*\n * Radon - An open-source Java obfuscator\n * Copyright (C) 2021 ItzSomebody\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, either version 3 of the License, or\n * (at your option) any later version.\n *\n * This program is distributed in the hope that it will be 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.  If not, see <http://www.gnu.org/licenses/>\n */\n\npackage xyz.itzsomebody.codegen.expressions.predefined;\n\nimport xyz.itzsomebody.codegen.BytecodeBlock;\nimport xyz.itzsomebody.codegen.WrappedType;\nimport xyz.itzsomebody.codegen.expressions.IRExpression;\nimport xyz.itzsomebody.codegen.instructions.FieldAccessNode;\n\nimport java.lang.reflect.Field;\n\npublic class IRSetFieldExpression extends IRExpression {\n    private final IRExpression instance;\n    private final IRExpression value;\n    private final WrappedType owner;\n    private final String name;\n\n    public IRSetFieldExpression(IRExpression instance, IRExpression value, WrappedType owner, String name, WrappedType type) {\n        super(type);\n        this.instance = instance;\n        this.value = value;\n        this.owner = owner;\n        this.name = name;\n    }\n\n    public IRSetFieldExpression(IRExpression instance, IRExpression value, Field field) {\n        this(instance, value, WrappedType.from(field.getDeclaringClass()), field.getName(), WrappedType.from(field.getType()));\n    }\n\n    @Override\n    public BytecodeBlock getInstructions() {\n        if (instance == null) {\n            return new BytecodeBlock()\n                    .append(value.getInstructions())\n                    .append(FieldAccessNode.putStatic(owner, name, getType()));\n        } else {\n            return new BytecodeBlock()\n                    .append(instance.getInstructions())\n                    .append(value.getInstructions())\n                    .append(FieldAccessNode.putField(owner, name, getType()));\n        }\n    }\n}\n"
  },
  {
    "path": "xyz.itzsomebody.codegen/src/main/java/xyz/itzsomebody/codegen/expressions/predefined/IRSetVariableExpression.java",
    "content": "/*\n * Radon - An open-source Java obfuscator\n * Copyright (C) 2021 ItzSomebody\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, either version 3 of the License, or\n * (at your option) any later version.\n *\n * This program is distributed in the hope that it will be 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.  If not, see <http://www.gnu.org/licenses/>\n */\n\npackage xyz.itzsomebody.codegen.expressions.predefined;\n\nimport xyz.itzsomebody.codegen.BytecodeBlock;\nimport xyz.itzsomebody.codegen.WrappedType;\nimport xyz.itzsomebody.codegen.expressions.IRExpression;\nimport xyz.itzsomebody.codegen.expressions.IRVariable;\nimport xyz.itzsomebody.codegen.instructions.RegisterNode;\n\npublic class IRSetVariableExpression extends IRExpression {\n    private final IRVariable variable;\n    private final IRExpression expression;\n\n    public IRSetVariableExpression(IRVariable variable, IRExpression expression) {\n        super(WrappedType.getAbsent());\n        this.variable = variable;\n        this.expression = expression;\n    }\n\n    @Override\n    public BytecodeBlock getInstructions() {\n        return new BytecodeBlock()\n                .append(expression.getInstructions())\n                .append(RegisterNode.storeVar(variable));\n    }\n}\n"
  },
  {
    "path": "xyz.itzsomebody.codegen/src/main/java/xyz/itzsomebody/codegen/expressions/predefined/IRThrowExceptionExpression.java",
    "content": "/*\n * Radon - An open-source Java obfuscator\n * Copyright (C) 2021 ItzSomebody\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, either version 3 of the License, or\n * (at your option) any later version.\n *\n * This program is distributed in the hope that it will be 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.  If not, see <http://www.gnu.org/licenses/>\n */\n\npackage xyz.itzsomebody.codegen.expressions.predefined;\n\nimport xyz.itzsomebody.codegen.BytecodeBlock;\nimport xyz.itzsomebody.codegen.WrappedType;\nimport xyz.itzsomebody.codegen.expressions.IRExpression;\nimport xyz.itzsomebody.codegen.instructions.SimpleNode;\n\npublic class IRThrowExceptionExpression extends IRExpression {\n    private final IRExpression exception;\n\n    public IRThrowExceptionExpression(IRExpression exception) {\n        super(WrappedType.getAbsent());\n        this.exception = exception;\n    }\n\n    @Override\n    public BytecodeBlock getInstructions() {\n        return new BytecodeBlock()\n                .append(exception.getInstructions())\n                .append(SimpleNode.THROW_EXCEPTION);\n    }\n}\n"
  },
  {
    "path": "xyz.itzsomebody.codegen/src/main/java/xyz/itzsomebody/codegen/instructions/BytecodeLabel.java",
    "content": "/*\n * Radon - An open-source Java obfuscator\n * Copyright (C) 2020 ItzSomebody\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, either version 3 of the License, or\n * (at your option) any later version.\n *\n * This program is distributed in the hope that it will be 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.  If not, see <http://www.gnu.org/licenses/>\n */\n\npackage xyz.itzsomebody.codegen.instructions;\n\nimport org.objectweb.asm.tree.AbstractInsnNode;\nimport org.objectweb.asm.tree.LabelNode;\n\npublic class BytecodeLabel implements CompilableNode {\n    private final LabelNode label;\n\n    public BytecodeLabel() {\n        this.label = new LabelNode();\n    }\n\n    public BytecodeLabel(LabelNode label) {\n        this.label = label;\n    }\n\n    @Override\n    public AbstractInsnNode getNode() {\n        return label;\n    }\n\n    public LabelNode getLabel() {\n        return label;\n    }\n}\n"
  },
  {
    "path": "xyz.itzsomebody.codegen/src/main/java/xyz/itzsomebody/codegen/instructions/CompilableNode.java",
    "content": "/*\n * Radon - An open-source Java obfuscator\n * Copyright (C) 2020 ItzSomebody\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, either version 3 of the License, or\n * (at your option) any later version.\n *\n * This program is distributed in the hope that it will be 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.  If not, see <http://www.gnu.org/licenses/>\n */\n\npackage xyz.itzsomebody.codegen.instructions;\n\nimport org.objectweb.asm.tree.AbstractInsnNode;\n\npublic interface CompilableNode {\n    AbstractInsnNode getNode();\n}\n"
  },
  {
    "path": "xyz.itzsomebody.codegen/src/main/java/xyz/itzsomebody/codegen/instructions/ConstantNode.java",
    "content": "/*\n * Radon - An open-source Java obfuscator\n * Copyright (C) 2021 ItzSomebody\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, either version 3 of the License, or\n * (at your option) any later version.\n *\n * This program is distributed in the hope that it will be 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.  If not, see <http://www.gnu.org/licenses/>\n */\n\npackage xyz.itzsomebody.codegen.instructions;\n\nimport org.objectweb.asm.ConstantDynamic;\nimport org.objectweb.asm.Opcodes;\nimport org.objectweb.asm.tree.AbstractInsnNode;\nimport org.objectweb.asm.tree.InsnNode;\nimport org.objectweb.asm.tree.IntInsnNode;\nimport org.objectweb.asm.tree.LdcInsnNode;\nimport xyz.itzsomebody.codegen.Utils;\nimport xyz.itzsomebody.codegen.WrappedHandle;\nimport xyz.itzsomebody.codegen.WrappedType;\nimport xyz.itzsomebody.codegen.exceptions.UncompilableNodeException;\n\nimport java.lang.reflect.Method;\nimport java.util.List;\n\npublic abstract class ConstantNode implements CompilableNode { // todo: constants of type Handle\n    public abstract Object getValue();\n\n    public static ConstantNode nullConst() {\n        return new NullConst();\n    }\n\n    public static ConstantNode booleanConst(boolean z) {\n        return new BooleanConst(z);\n    }\n\n    public static ConstantNode intConst(int i) {\n        return new IntConst(i);\n    }\n\n    public static ConstantNode floatConst(float f) {\n        return new FloatConst(f);\n    }\n\n    public static ConstantNode longConst(long j) {\n        return new LongConst(j);\n    }\n\n    public static ConstantNode doubleConst(double d) {\n        return new DoubleConst(d);\n    }\n\n    public static ConstantNode stringConst(String s) {\n        return new StringConst(s);\n    }\n\n    public static ConstantNode classConst(WrappedType type) {\n        return new ClassConst(type);\n    }\n\n    public static ConstantNode dynamicConst(String name, WrappedType type, WrappedHandle bootstrapMethod, List<ConstantNode> bootstrapArgs) {\n        return new DynamicConst(name, type, bootstrapMethod, bootstrapArgs);\n    }\n\n    public static ConstantNode dynamicConst(String name, WrappedType type, Method bootstrap, List<ConstantNode> bootstrapArgs) {\n        return dynamicConst(name, type, WrappedHandle.getInvokeStaticHandle(bootstrap), bootstrapArgs);\n    }\n\n    public static class NullConst extends ConstantNode {\n        @Override\n        public Object getValue() {\n            return null;\n        }\n\n        @Override\n        public AbstractInsnNode getNode() {\n            return new InsnNode(Opcodes.ACONST_NULL);\n        }\n    }\n\n    public static class BooleanConst extends ConstantNode {\n        private final boolean value;\n\n        public BooleanConst(boolean value) {\n            this.value = value;\n        }\n\n        @Override\n        public Boolean getValue() {\n            return value;\n        }\n\n        @Override\n        public AbstractInsnNode getNode() {\n            if (value) {\n                return new InsnNode(Opcodes.ICONST_1);\n            } else {\n                return new InsnNode(Opcodes.ICONST_0);\n            }\n        }\n    }\n\n    public static class IntConst extends ConstantNode {\n        private final int value;\n\n        public IntConst(int value) {\n            this.value = value;\n        }\n\n        @Override\n        public Integer getValue() {\n            return value;\n        }\n\n        @Override\n        public AbstractInsnNode getNode() {\n            if (value >= -1 && value <= 5) {\n                return new InsnNode(value + 3);\n            } else if (value >= Byte.MIN_VALUE && value <= Byte.MAX_VALUE) {\n                return new IntInsnNode(Opcodes.BIPUSH, value);\n            } else if (value >= Short.MIN_VALUE && value <= Short.MAX_VALUE) {\n                return new IntInsnNode(Opcodes.SIPUSH, value);\n            } else {\n                return new LdcInsnNode(value);\n            }\n        }\n    }\n\n    public static class FloatConst extends ConstantNode {\n        private final float value;\n\n        public FloatConst(float value) {\n            this.value = value;\n        }\n\n        @Override\n        public Float getValue() {\n            return value;\n        }\n\n        @Override\n        public AbstractInsnNode getNode() {\n            if (value == 0F || value == 1F || value == 2F) {\n                return new InsnNode((int) value + 11);\n            } else {\n                return new LdcInsnNode(value);\n            }\n        }\n    }\n\n    public static class LongConst extends ConstantNode {\n        private final long value;\n\n        public LongConst(long value) {\n            this.value = value;\n        }\n\n        @Override\n        public Long getValue() {\n            return value;\n        }\n\n        @Override\n        public AbstractInsnNode getNode() {\n            if (value == 0L || value == 1L) {\n                return new InsnNode((int) value + 9);\n            } else {\n                return new LdcInsnNode(value);\n            }\n        }\n    }\n\n    public static class DoubleConst extends ConstantNode {\n        private final double value;\n\n        public DoubleConst(double value) {\n            this.value = value;\n        }\n\n        @Override\n        public Double getValue() {\n            return value;\n        }\n\n        @Override\n        public AbstractInsnNode getNode() {\n            if (value == 0D || value == 1D) {\n                return new InsnNode((int) value + 14);\n            } else {\n                return new LdcInsnNode(value);\n            }\n        }\n    }\n\n    public static class StringConst extends ConstantNode {\n        private final String value;\n\n        public StringConst(String value) {\n            this.value = value;\n        }\n\n        @Override\n        public String getValue() {\n            return value;\n        }\n\n        @Override\n        public AbstractInsnNode getNode() {\n            return new LdcInsnNode(value);\n        }\n    }\n\n    public static class ClassConst extends ConstantNode {\n        private final WrappedType type;\n\n        public ClassConst(WrappedType type) {\n            this.type = type;\n        }\n\n        @Override\n        public Object getValue() {\n            return type;\n        }\n\n        @Override\n        public AbstractInsnNode getNode() {\n            return new LdcInsnNode(type.getType());\n        }\n    }\n\n    public static class DynamicConst extends ConstantNode {\n        private final String name;\n        private final WrappedType type;\n        private final WrappedHandle bootstrapMethod;\n        private final List<ConstantNode> bootstrapArgs;\n\n        public DynamicConst(String name, WrappedType type, WrappedHandle bootstrapMethod, List<ConstantNode> bootstrapArgs) {\n            this.name = name;\n            this.type = type;\n            this.bootstrapMethod = bootstrapMethod;\n            this.bootstrapArgs = bootstrapArgs;\n        }\n\n        @Override\n        public AbstractInsnNode getNode() {\n            return new LdcInsnNode(new ConstantDynamic(name, type.unwrap(), bootstrapMethod.constructHandle(), Utils.unpackConstants(bootstrapArgs)));\n        }\n\n        @Override\n        public Object getValue() {\n            return new UncompilableNodeException(\"Attempted to get value of dynamic constant\");\n        }\n    }\n}\n"
  },
  {
    "path": "xyz.itzsomebody.codegen/src/main/java/xyz/itzsomebody/codegen/instructions/FieldAccessNode.java",
    "content": "/*\n * Radon - An open-source Java obfuscator\n * Copyright (C) 2021 ItzSomebody\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, either version 3 of the License, or\n * (at your option) any later version.\n *\n * This program is distributed in the hope that it will be 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.  If not, see <http://www.gnu.org/licenses/>\n */\n\npackage xyz.itzsomebody.codegen.instructions;\n\nimport org.objectweb.asm.Opcodes;\nimport org.objectweb.asm.tree.AbstractInsnNode;\nimport org.objectweb.asm.tree.FieldInsnNode;\nimport xyz.itzsomebody.codegen.WrappedType;\n\npublic class FieldAccessNode implements CompilableNode {\n    private final int opcode;\n    private final WrappedType owner;\n    private final String name;\n    private final WrappedType type;\n\n    public FieldAccessNode(int opcode, WrappedType owner, String name, WrappedType type) {\n        this.opcode = opcode;\n        this.owner = owner;\n        this.name = name;\n        this.type = type;\n    }\n\n    @Override\n    public AbstractInsnNode getNode() {\n        return new FieldInsnNode(opcode, owner.getInternalName(), name, type.unwrap());\n    }\n\n    public static FieldAccessNode getStatic(WrappedType owner, String name, WrappedType type) {\n        return new FieldAccessNode(Opcodes.GETSTATIC, owner, name, type);\n    }\n\n    public static FieldAccessNode putStatic(WrappedType owner, String name, WrappedType type) {\n        return new FieldAccessNode(Opcodes.PUTSTATIC, owner, name, type);\n    }\n\n    public static FieldAccessNode getField(WrappedType owner, String name, WrappedType type) {\n        return new FieldAccessNode(Opcodes.GETFIELD, owner, name, type);\n    }\n\n    public static FieldAccessNode putField(WrappedType owner, String name, WrappedType type) {\n        return new FieldAccessNode(Opcodes.PUTFIELD, owner, name, type);\n    }\n}\n"
  },
  {
    "path": "xyz.itzsomebody.codegen/src/main/java/xyz/itzsomebody/codegen/instructions/InvokeDynamicNode.java",
    "content": "/*\n * Radon - An open-source Java obfuscator\n * Copyright (C) 2021 ItzSomebody\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, either version 3 of the License, or\n * (at your option) any later version.\n *\n * This program is distributed in the hope that it will be 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.  If not, see <http://www.gnu.org/licenses/>\n */\n\npackage xyz.itzsomebody.codegen.instructions;\n\nimport org.objectweb.asm.tree.AbstractInsnNode;\nimport org.objectweb.asm.tree.InvokeDynamicInsnNode;\nimport xyz.itzsomebody.codegen.Utils;\nimport xyz.itzsomebody.codegen.WrappedHandle;\nimport xyz.itzsomebody.codegen.WrappedType;\n\nimport java.lang.reflect.Method;\nimport java.util.List;\n\npublic class InvokeDynamicNode implements CompilableNode {\n    private final String name;\n    private final List<WrappedType> parameterTypes;\n    private final WrappedType returnType;\n    private final WrappedHandle bootstrapMethod;\n    private final List<ConstantNode> bootstrapArgs;\n\n    public InvokeDynamicNode(String name, List<WrappedType> parameterTypes, WrappedType returnType, WrappedHandle bootstrapMethod, List<ConstantNode> bootstrapArgs) {\n        this.name = name;\n        this.parameterTypes = parameterTypes;\n        this.returnType = returnType;\n        this.bootstrapMethod = bootstrapMethod;\n        this.bootstrapArgs = bootstrapArgs;\n    }\n\n    @Override\n    public AbstractInsnNode getNode() {\n        return new InvokeDynamicInsnNode(name, Utils.unwrapMethodDescriptor(parameterTypes, returnType), bootstrapMethod.constructHandle(), Utils.unpackConstants(bootstrapArgs));\n    }\n\n    public static InvokeDynamicNode invokeDynamic(String name, List<WrappedType> parameterTypes, WrappedType returnType, WrappedHandle bootstrapMethod, List<ConstantNode> bootstrapArgs) {\n        return new InvokeDynamicNode(name, parameterTypes, returnType, bootstrapMethod, bootstrapArgs);\n    }\n\n    public static InvokeDynamicNode invokeDynamic(String name, List<WrappedType> parameterTypes, WrappedType returnType, Method bootstrap, List<ConstantNode> bootstrapArgs) {\n        return invokeDynamic(name, parameterTypes, returnType, WrappedHandle.getInvokeStaticHandle(bootstrap), bootstrapArgs);\n    }\n}\n"
  },
  {
    "path": "xyz.itzsomebody.codegen/src/main/java/xyz/itzsomebody/codegen/instructions/InvokeNode.java",
    "content": "/*\n * Radon - An open-source Java obfuscator\n * Copyright (C) 2021 ItzSomebody\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, either version 3 of the License, or\n * (at your option) any later version.\n *\n * This program is distributed in the hope that it will be 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.  If not, see <http://www.gnu.org/licenses/>\n */\n\npackage xyz.itzsomebody.codegen.instructions;\n\nimport org.objectweb.asm.Opcodes;\nimport org.objectweb.asm.tree.AbstractInsnNode;\nimport org.objectweb.asm.tree.MethodInsnNode;\nimport xyz.itzsomebody.codegen.Utils;\nimport xyz.itzsomebody.codegen.WrappedType;\n\nimport java.util.List;\n\npublic class InvokeNode implements CompilableNode {\n    private final int opcode;\n    private final WrappedType owner;\n    private final String name;\n    private final List<WrappedType> parameterTypes;\n    private final WrappedType returnType;\n\n    public InvokeNode(int opcode, WrappedType owner, String name, List<WrappedType> parameterTypes, WrappedType returnType) {\n        this.opcode = opcode;\n        this.owner = owner;\n        this.name = name;\n        this.parameterTypes = parameterTypes;\n        this.returnType = returnType;\n    }\n\n    @Override\n    public AbstractInsnNode getNode() {\n        return new MethodInsnNode(opcode, owner.getInternalName(), name, Utils.unwrapMethodDescriptor(parameterTypes, returnType), owner.isInterface());\n    }\n\n    public static InvokeNode invokeStatic(WrappedType owner, String name, List<WrappedType> parameterTypes, WrappedType returnType) {\n        return new InvokeNode(Opcodes.INVOKESTATIC, owner, name, parameterTypes, returnType);\n    }\n\n    public static InvokeNode invokeVirtual(WrappedType owner, String name, List<WrappedType> parameterTypes, WrappedType returnType) {\n        return new InvokeNode(Opcodes.INVOKEVIRTUAL, owner, name, parameterTypes, returnType);\n    }\n\n    public static InvokeNode invokeInterface(WrappedType owner, String name, List<WrappedType> parameterTypes, WrappedType returnType) {\n        return new InvokeNode(Opcodes.INVOKEINTERFACE, owner, name, parameterTypes, returnType);\n    }\n\n    public static InvokeNode invokeSpecial(WrappedType owner, String name, List<WrappedType> parameterTypes, WrappedType returnType) {\n        return new InvokeNode(Opcodes.INVOKESPECIAL, owner, name, parameterTypes, returnType);\n    }\n\n    public static InvokeNode invokeConstructor(WrappedType owner, List<WrappedType> parameterTypes) {\n        return new InvokeNode(Opcodes.INVOKESPECIAL, owner, \"<init>\", parameterTypes, WrappedType.from(void.class));\n    }\n}\n"
  },
  {
    "path": "xyz.itzsomebody.codegen/src/main/java/xyz/itzsomebody/codegen/instructions/JumpNode.java",
    "content": "/*\n * Radon - An open-source Java obfuscator\n * Copyright (C) 2020 ItzSomebody\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, either version 3 of the License, or\n * (at your option) any later version.\n *\n * This program is distributed in the hope that it will be 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.  If not, see <http://www.gnu.org/licenses/>\n */\n\npackage xyz.itzsomebody.codegen.instructions;\n\nimport org.objectweb.asm.Opcodes;\nimport org.objectweb.asm.tree.AbstractInsnNode;\nimport org.objectweb.asm.tree.JumpInsnNode;\n\npublic class JumpNode implements CompilableNode {\n    private final int opcode;\n    private final BytecodeLabel target;\n\n    public JumpNode(int opcode, BytecodeLabel target) {\n        this.opcode = opcode;\n        this.target = target;\n    }\n\n    @Override\n    public AbstractInsnNode getNode() {\n        return new JumpInsnNode(opcode, target.getLabel());\n    }\n\n    public static JumpNode jumpIfZero(BytecodeLabel target) {\n        return new JumpNode(Opcodes.IFEQ, target);\n    }\n\n    public static JumpNode jumpIfNotZero(BytecodeLabel target) {\n        return new JumpNode(Opcodes.IFNE, target);\n    }\n\n    public static JumpNode jumpIfLessThanZero(BytecodeLabel target) {\n        return new JumpNode(Opcodes.IFLT, target);\n    }\n\n    public static JumpNode jumpIfLessThanOrEqualToZero(BytecodeLabel target) {\n        return new JumpNode(Opcodes.IFLE, target);\n    }\n\n    public static JumpNode jumpIfGreaterThanZero(BytecodeLabel target) {\n        return new JumpNode(Opcodes.IFGT, target);\n    }\n\n    public static JumpNode jumpIfGreaterThanOrEqualToZero(BytecodeLabel target) {\n        return new JumpNode(Opcodes.IFGE, target);\n    }\n\n    public static JumpNode jumpIfIntEqual(BytecodeLabel target) {\n        return new JumpNode(Opcodes.IF_ICMPEQ, target);\n    }\n\n    public static JumpNode jumpIfIntNotEqual(BytecodeLabel target) {\n        return new JumpNode(Opcodes.IF_ICMPNE, target);\n    }\n\n    public static JumpNode jumpIfIntLessThan(BytecodeLabel target) {\n        return new JumpNode(Opcodes.IF_ICMPLT, target);\n    }\n\n    public static JumpNode jumpIfIntLessThanOrEqualToZero(BytecodeLabel target) {\n        return new JumpNode(Opcodes.IF_ICMPLE, target);\n    }\n\n    public static JumpNode jumpIfIntGreaterThan(BytecodeLabel target) {\n        return new JumpNode(Opcodes.IF_ICMPGT, target);\n    }\n\n    public static JumpNode jumpIfIntGreaterThanOrEqualToZero(BytecodeLabel target) {\n        return new JumpNode(Opcodes.IF_ICMPGE, target);\n    }\n\n    public static JumpNode jumpIfObjectEqual(BytecodeLabel target) {\n        return new JumpNode(Opcodes.IF_ACMPEQ, target);\n    }\n\n    public static JumpNode jumpIfObjectNotEqual(BytecodeLabel target) {\n        return new JumpNode(Opcodes.IF_ACMPNE, target);\n    }\n\n    public static JumpNode jumpUnconditionally(BytecodeLabel target) {\n        return new JumpNode(Opcodes.GOTO, target);\n    }\n\n    public static JumpNode jsr(BytecodeLabel target) {\n        return new JumpNode(Opcodes.JSR, target);\n    }\n\n    public static JumpNode jumpIfNull(BytecodeLabel target) {\n        return new JumpNode(Opcodes.IFNULL, target);\n    }\n\n    public static JumpNode jumpIfNotNull(BytecodeLabel target) {\n        return new JumpNode(Opcodes.IFNONNULL, target);\n    }\n}\n"
  },
  {
    "path": "xyz.itzsomebody.codegen/src/main/java/xyz/itzsomebody/codegen/instructions/NewArrayNode.java",
    "content": "/*\n * Radon - An open-source Java obfuscator\n * Copyright (C) 2021 ItzSomebody\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, either version 3 of the License, or\n * (at your option) any later version.\n *\n * This program is distributed in the hope that it will be 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.  If not, see <http://www.gnu.org/licenses/>\n */\n\npackage xyz.itzsomebody.codegen.instructions;\n\nimport org.objectweb.asm.Opcodes;\nimport org.objectweb.asm.tree.AbstractInsnNode;\nimport org.objectweb.asm.tree.IntInsnNode;\nimport org.objectweb.asm.tree.TypeInsnNode;\nimport xyz.itzsomebody.codegen.WrappedType;\n\npublic class NewArrayNode implements CompilableNode {\n    private final WrappedType wrappedType;\n\n    public NewArrayNode(WrappedType wrappedType) {\n        this.wrappedType = wrappedType;\n    }\n\n    @Override\n    public AbstractInsnNode getNode() {\n        if (wrappedType.isPrimitive()) {\n            return new IntInsnNode(Opcodes.NEWARRAY, wrappedType.getNewArraySort());\n        } else {\n            return new TypeInsnNode(Opcodes.ANEWARRAY, wrappedType.getInternalName());\n        }\n    }\n}\n"
  },
  {
    "path": "xyz.itzsomebody.codegen/src/main/java/xyz/itzsomebody/codegen/instructions/RegisterNode.java",
    "content": "/*\n * Radon - An open-source Java obfuscator\n * Copyright (C) 2020 ItzSomebody\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, either version 3 of the License, or\n * (at your option) any later version.\n *\n * This program is distributed in the hope that it will be 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.  If not, see <http://www.gnu.org/licenses/>\n */\n\npackage xyz.itzsomebody.codegen.instructions;\n\nimport org.objectweb.asm.Opcodes;\nimport org.objectweb.asm.Type;\nimport org.objectweb.asm.tree.AbstractInsnNode;\nimport org.objectweb.asm.tree.VarInsnNode;\nimport xyz.itzsomebody.codegen.exceptions.UncompilableNodeException;\nimport xyz.itzsomebody.codegen.expressions.IRVariable;\n\npublic class RegisterNode implements CompilableNode {\n    private final int opcode;\n    private final int slot;\n\n    public RegisterNode(int opcode, int slot) {\n        this.opcode = opcode;\n        this.slot = slot;\n    }\n\n    @Override\n    public AbstractInsnNode getNode() {\n        return new VarInsnNode(opcode, slot);\n    }\n\n    public static RegisterNode loadInt(int slot) {\n        return new RegisterNode(Opcodes.ILOAD, slot);\n    }\n\n    public static RegisterNode loadLong(int slot) {\n        return new RegisterNode(Opcodes.LLOAD, slot);\n    }\n\n    public static RegisterNode loadFloat(int slot) {\n        return new RegisterNode(Opcodes.FLOAD, slot);\n    }\n\n    public static RegisterNode loadDouble(int slot) {\n        return new RegisterNode(Opcodes.DLOAD, slot);\n    }\n\n    public static RegisterNode loadObject(int slot) {\n        return new RegisterNode(Opcodes.ALOAD, slot);\n    }\n\n    public static RegisterNode storeInt(int slot) {\n        return new RegisterNode(Opcodes.ISTORE, slot);\n    }\n\n    public static RegisterNode storeLong(int slot) {\n        return new RegisterNode(Opcodes.LSTORE, slot);\n    }\n\n    public static RegisterNode storeFloat(int slot) {\n        return new RegisterNode(Opcodes.FSTORE, slot);\n    }\n\n    public static RegisterNode storeDouble(int slot) {\n        return new RegisterNode(Opcodes.DSTORE, slot);\n    }\n\n    public static RegisterNode storeObject(int slot) {\n        return new RegisterNode(Opcodes.ASTORE, slot);\n    }\n\n    public static RegisterNode ret(int slot) {\n        return new RegisterNode(Opcodes.RET, slot);\n    } // todo: add jsr support to troll cooker\n\n    public static RegisterNode loadVar(IRVariable variable) {\n        switch (variable.getWrappedType().getSort()) {\n            case Type.BOOLEAN:\n            case Type.CHAR:\n            case Type.BYTE:\n            case Type.SHORT:\n            case Type.INT:\n                return loadInt(variable.getSlot());\n            case Type.FLOAT:\n                return loadFloat(variable.getSlot());\n            case Type.LONG:\n                return loadLong(variable.getSlot());\n            case Type.DOUBLE:\n                return loadDouble(variable.getSlot());\n            case Type.ARRAY:\n            case Type.OBJECT:\n                return loadObject(variable.getSlot());\n            default:\n                throw new UncompilableNodeException(\"Attempted to load variable of type \" + variable.getWrappedType());\n        }\n    }\n\n    public static RegisterNode storeVar(IRVariable variable) {\n        switch (variable.getWrappedType().getSort()) {\n            case Type.BOOLEAN:\n            case Type.CHAR:\n            case Type.BYTE:\n            case Type.SHORT:\n            case Type.INT:\n                return storeInt(variable.getSlot());\n            case Type.FLOAT:\n                return storeFloat(variable.getSlot());\n            case Type.LONG:\n                return storeLong(variable.getSlot());\n            case Type.DOUBLE:\n                return storeDouble(variable.getSlot());\n            case Type.ARRAY:\n            case Type.OBJECT:\n                return storeObject(variable.getSlot());\n            default:\n                throw new UncompilableNodeException(\"Attempted to store variable of type \" + variable.getWrappedType());\n        }\n    }\n}\n"
  },
  {
    "path": "xyz.itzsomebody.codegen/src/main/java/xyz/itzsomebody/codegen/instructions/SimpleNode.java",
    "content": "/*\n * Radon - An open-source Java obfuscator\n * Copyright (C) 2020 ItzSomebody\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, either version 3 of the License, or\n * (at your option) any later version.\n *\n * This program is distributed in the hope that it will be 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.  If not, see <http://www.gnu.org/licenses/>\n */\n\npackage xyz.itzsomebody.codegen.instructions;\n\nimport org.objectweb.asm.Opcodes;\nimport org.objectweb.asm.Type;\nimport org.objectweb.asm.tree.AbstractInsnNode;\nimport org.objectweb.asm.tree.InsnNode;\nimport xyz.itzsomebody.codegen.WrappedType;\nimport xyz.itzsomebody.codegen.exceptions.UncompilableNodeException;\n\npublic enum SimpleNode implements CompilableNode {\n    // Tux, will you nop sled with me?\n    NOP(Opcodes.NOP),\n\n    // Null push\n    PUSH_NULL(Opcodes.ACONST_NULL),\n\n    // Integer pushes\n    PUSH_M1I(Opcodes.ICONST_M1),\n    PUSH_0I(Opcodes.ICONST_0),\n    PUSH_1I(Opcodes.ICONST_1),\n    PUSH_2I(Opcodes.ICONST_2),\n    PUSH_3I(Opcodes.ICONST_3),\n    PUSH_4I(Opcodes.ICONST_4),\n    PUSH_5I(Opcodes.ICONST_5),\n\n    // Long pushes\n    PUSH_0L(Opcodes.LCONST_0),\n    PUSH_1L(Opcodes.LCONST_1),\n\n    // Float pushes\n    PUSH_0F(Opcodes.FCONST_0),\n    PUSH_1F(Opcodes.FCONST_1),\n    PUSH_2F(Opcodes.FCONST_2),\n\n    // Double pushes\n    PUSH_0D(Opcodes.DCONST_0),\n    PUSH_1D(Opcodes.DCONST_1),\n\n    // Array loads\n    INT_ARRAY_LOAD(Opcodes.IALOAD),\n    LONG_ARRAY_LOAD(Opcodes.LALOAD),\n    FLOAT_ARRAY_LOAD(Opcodes.FALOAD),\n    DOUBLE_ARRAY_LOAD(Opcodes.DALOAD),\n    OBJECT_ARRAY_LOAD(Opcodes.AALOAD),\n    BYTE_ARRAY_LOAD(Opcodes.BALOAD),\n    CHAR_ARRAY_LOAD(Opcodes.CALOAD),\n    SHORT_ARRAY_LOAD(Opcodes.SALOAD),\n\n    // Array stores\n    INT_ARRAY_STORE(Opcodes.IASTORE),\n    LONG_ARRAY_STORE(Opcodes.LASTORE),\n    FLOAT_ARRAY_STORE(Opcodes.FASTORE),\n    DOUBLE_ARRAY_STORE(Opcodes.DASTORE),\n    OBJECT_ARRAY_STORE(Opcodes.AASTORE),\n    BYTE_ARRAY_STORE(Opcodes.BASTORE),\n    CHAR_ARRAY_STORE(Opcodes.CASTORE),\n    SHORT_ARRAY_STORE(Opcodes.SASTORE),\n\n    // Stack stuff\n    POP(Opcodes.POP),\n    POP2(Opcodes.POP2),\n    DUP(Opcodes.DUP),\n    DUP_X1(Opcodes.DUP_X1),\n    DUP_X2(Opcodes.DUP_X2),\n    DUP2(Opcodes.DUP2),\n    DUP2_X1(Opcodes.DUP2_X1),\n    DUP2_X2(Opcodes.DUP2_X2),\n    SWAP(Opcodes.SWAP),\n\n    // Int math\n    INT_ADD(Opcodes.IADD),\n    INT_SUB(Opcodes.ISUB),\n    INT_MUL(Opcodes.IMUL),\n    INT_DIV(Opcodes.IDIV),\n    INT_MOD(Opcodes.IREM),\n    INT_NEG(Opcodes.INEG),\n    INT_SHIFT_LEFT(Opcodes.ISHL),\n    INT_SHIFT_RIGHT(Opcodes.ISHR),\n    INT_UNSIGNED_SHIFT_RIGHT(Opcodes.IUSHR),\n    INT_AND(Opcodes.IAND),\n    INT_OR(Opcodes.IOR),\n    INT_XOR(Opcodes.IXOR),\n\n    // Long math\n    LONG_ADD(Opcodes.LADD),\n    LONG_SUB(Opcodes.LSUB),\n    LONG_MUL(Opcodes.LMUL),\n    LONG_DIV(Opcodes.LDIV),\n    LONG_MOD(Opcodes.LREM),\n    LONG_NEG(Opcodes.LNEG),\n    LONG_SHIFT_LEFT(Opcodes.LSHL),\n    LONG_SHIFT_RIGHT(Opcodes.LSHR),\n    LONG_UNSIGNED_SHIFT_RIGHT(Opcodes.LUSHR),\n    LONG_AND(Opcodes.LAND),\n    LONG_OR(Opcodes.LOR),\n    LONG_XOR(Opcodes.LXOR),\n\n    // Float math\n    FLOAT_ADD(Opcodes.FADD),\n    FLOAT_SUB(Opcodes.FSUB),\n    FLOAT_MUL(Opcodes.FMUL),\n    FLOAT_DIV(Opcodes.FDIV),\n    FLOAT_MOD(Opcodes.FREM),\n    FLOAT_NEG(Opcodes.FNEG),\n\n    // Double math\n    DOUBLE_ADD(Opcodes.DADD),\n    DOUBLE_SUB(Opcodes.DSUB),\n    DOUBLE_MUL(Opcodes.DMUL),\n    DOUBLE_DIV(Opcodes.DDIV),\n    DOUBLE_MOD(Opcodes.DREM),\n    DOUBLE_NEG(Opcodes.DNEG),\n\n    // Int 2 XXX casts\n    CAST_INT_TO_LONG(Opcodes.I2L),\n    CAST_INT_TO_FLOAT(Opcodes.I2F),\n    CAST_INT_TO_DOUBLE(Opcodes.I2D),\n    CAST_INT_TO_BYTE(Opcodes.I2B),\n    CAST_INT_TO_CHAR(Opcodes.I2C),\n    CAST_INT_TO_SHORT(Opcodes.I2S),\n\n    // Long 2 XXX casts\n    CAST_LONG_TO_INT(Opcodes.L2I),\n    CAST_LONG_TO_FLOAT(Opcodes.L2F),\n    CAST_LONG_TO_DOUBLE(Opcodes.L2D),\n\n    // Float 2 XXX casts\n    CAST_FLOAT_TO_INT(Opcodes.F2I),\n    CAST_FLOAT_TO_LONG(Opcodes.F2L),\n    CAST_FLOAT_TO_DOUBLE(Opcodes.F2D),\n\n    // Double 2 XXX casts\n    CAST_DOUBLE_TO_INT(Opcodes.D2I),\n    CAST_DOUBLE_TO_LONG(Opcodes.D2L),\n    CAST_DOUBLE_TO_FLOAT(Opcodes.D2F),\n\n    // Long.compare(first, second)\n    COMPARE_LONGS(Opcodes.LCMP),\n\n    // Float.compare(first, second)\n    COMPARE_FLOAT_OR_M1I(Opcodes.FCMPL), // pushes -1 if 'first' or 'second' are NaN\n    COMPARE_FLOAT_OR_1I(Opcodes.FCMPG), // pushes 1 if 'first' or 'second' are NaN\n\n    // Double.compare(first, second)\n    COMPARE_DOUBLE_OR_M1I(Opcodes.DCMPL), // pushes -1 if 'first' or 'second' are NaN\n    COMPARE_DOUBLE_OR_1I(Opcodes.DCMPG), // pushes 1 if 'first' or 'second' are NaN\n\n    // Returns\n    RETURN_INT(Opcodes.IRETURN),\n    RETURN_LONG(Opcodes.LRETURN),\n    RETURN_FLOAT(Opcodes.FRETURN),\n    RETURN_DOUBLE(Opcodes.DRETURN),\n    RETURN_OBJECT(Opcodes.ARETURN),\n    RETURN_VOID(Opcodes.RETURN),\n\n    // array.length\n    ARRAY_LENGTH(Opcodes.ARRAYLENGTH),\n\n    // throw exceptionInstance\n    THROW_EXCEPTION(Opcodes.ATHROW),\n\n    // Monitor enter/exit\n    ENTER_MONITOR(Opcodes.MONITORENTER),\n    EXIT_MONITOR(Opcodes.MONITOREXIT);\n\n    private int opcode;\n\n    SimpleNode(int opcode) {\n        this.opcode = opcode;\n    }\n\n    @Override\n    public AbstractInsnNode getNode() {\n        return new InsnNode(opcode);\n    }\n\n    public static SimpleNode getArrayStoreOp(WrappedType type) { // fixme maybe move to Utils?\n        switch (type.getSort()) {\n            case Type.BOOLEAN:\n            case Type.INT:\n                return INT_ARRAY_STORE;\n            case Type.CHAR:\n                return CHAR_ARRAY_STORE;\n            case Type.BYTE:\n                return BYTE_ARRAY_STORE;\n            case Type.SHORT:\n                return SHORT_ARRAY_STORE;\n            case Type.FLOAT:\n                return FLOAT_ARRAY_STORE;\n            case Type.LONG:\n                return LONG_ARRAY_STORE;\n            case Type.DOUBLE:\n                return DOUBLE_ARRAY_STORE;\n            case Type.ARRAY:\n            case Type.OBJECT:\n                return OBJECT_ARRAY_STORE;\n            default:\n                throw new UncompilableNodeException(\"Attempted to get array store opcode for \" + type);\n        }\n    }\n\n    public static SimpleNode getArrayLoadOp(WrappedType type) {\n        switch (type.getSort()) {\n            case Type.BOOLEAN:\n            case Type.INT:\n                return INT_ARRAY_LOAD;\n            case Type.CHAR:\n                return CHAR_ARRAY_LOAD;\n            case Type.BYTE:\n                return BYTE_ARRAY_LOAD;\n            case Type.SHORT:\n                return SHORT_ARRAY_LOAD;\n            case Type.FLOAT:\n                return FLOAT_ARRAY_LOAD;\n            case Type.LONG:\n                return LONG_ARRAY_LOAD;\n            case Type.DOUBLE:\n                return DOUBLE_ARRAY_LOAD;\n            case Type.ARRAY:\n            case Type.OBJECT:\n                return OBJECT_ARRAY_LOAD;\n            default:\n                throw new UncompilableNodeException(\"Attempted to get array load opcode for \" + type);\n        }\n    }\n\n    public static SimpleNode negateOpcodeFor(WrappedType type) {\n        switch (type.getSort()) {\n            case Type.BOOLEAN:\n            case Type.CHAR:\n            case Type.BYTE:\n            case Type.SHORT:\n            case Type.INT:\n                return INT_NEG;\n            case Type.FLOAT:\n                return FLOAT_NEG;\n            case Type.LONG:\n                return LONG_NEG;\n            case Type.DOUBLE:\n                return DOUBLE_NEG;\n            default:\n                throw new UncompilableNodeException(\"Attempted to get negate opcode for \" + type);\n        }\n    }\n}\n"
  },
  {
    "path": "xyz.itzsomebody.codegen/src/main/java/xyz/itzsomebody/codegen/instructions/SwitchNode.java",
    "content": "/*\n * Radon - An open-source Java obfuscator\n * Copyright (C) 2021 ItzSomebody\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, either version 3 of the License, or\n * (at your option) any later version.\n *\n * This program is distributed in the hope that it will be 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.  If not, see <http://www.gnu.org/licenses/>\n */\n\npackage xyz.itzsomebody.codegen.instructions;\n\nimport org.objectweb.asm.tree.AbstractInsnNode;\nimport org.objectweb.asm.tree.LabelNode;\nimport org.objectweb.asm.tree.LookupSwitchInsnNode;\nimport xyz.itzsomebody.codegen.Utils;\n\nimport java.util.List;\n\npublic class SwitchNode implements CompilableNode {\n    private final List<Integer> keys;\n    private final List<BytecodeLabel> labels;\n    private final BytecodeLabel defaultLabel;\n\n    public SwitchNode(List<Integer> keys, List<BytecodeLabel> labels, BytecodeLabel defaultLabel) {\n        this.keys = keys;\n        this.labels = labels;\n        this.defaultLabel = defaultLabel;\n    }\n\n    @Override\n    public AbstractInsnNode getNode() {\n        return new LookupSwitchInsnNode(defaultLabel.getLabel(), keys.stream().mapToInt(i -> i).toArray(), Utils.unwrapLabels(labels).toArray(new LabelNode[0]));\n    }\n}\n"
  },
  {
    "path": "xyz.itzsomebody.codegen/src/main/java/xyz/itzsomebody/codegen/instructions/TypeNode.java",
    "content": "/*\n * Radon - An open-source Java obfuscator\n * Copyright (C) 2021 ItzSomebody\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, either version 3 of the License, or\n * (at your option) any later version.\n *\n * This program is distributed in the hope that it will be 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.  If not, see <http://www.gnu.org/licenses/>\n */\n\npackage xyz.itzsomebody.codegen.instructions;\n\nimport org.objectweb.asm.Opcodes;\nimport org.objectweb.asm.tree.AbstractInsnNode;\nimport org.objectweb.asm.tree.TypeInsnNode;\nimport xyz.itzsomebody.codegen.WrappedType;\n\npublic class TypeNode implements CompilableNode {\n    private final int opcode;\n    private final WrappedType type;\n\n    public TypeNode(int opcode, WrappedType type) {\n        this.opcode = opcode;\n        this.type = type;\n    }\n\n    @Override\n    public AbstractInsnNode getNode() {\n        return new TypeInsnNode(opcode, type.getInternalName());\n    }\n\n    public static TypeNode newInstance(WrappedType type) {\n        return new TypeNode(Opcodes.NEW, type);\n    }\n\n    public static TypeNode cast(WrappedType type) {\n        return new TypeNode(Opcodes.CHECKCAST, type);\n    }\n\n    public static TypeNode instanceOf(WrappedType type) {\n        return new TypeNode(Opcodes.INSTANCEOF, type);\n    }\n}\n"
  },
  {
    "path": "xyz.itzsomebody.codegen/src/test/java/xyz/itzsomebody/codegen/UtilsTester.java",
    "content": "/*\n * Radon - An open-source Java obfuscator\n * Copyright (C) 2021 ItzSomebody\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, either version 3 of the License, or\n * (at your option) any later version.\n *\n * This program is distributed in the hope that it will be 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.  If not, see <http://www.gnu.org/licenses/>\n */\n\npackage xyz.itzsomebody.codegen;\n\nimport org.junit.Assert;\nimport org.junit.Test;\nimport org.objectweb.asm.tree.MethodNode;\nimport xyz.itzsomebody.codegen.instructions.ConstantNode;\n\nimport java.util.List;\n\npublic class UtilsTester {\n    @Test\n    public void testWrapMethodNodeParameters() {\n        var dummyMethodNode = new MethodNode();\n        dummyMethodNode.desc = \"(Ljava/lang/String;ZBCSIJFD)V\";\n\n        List<WrappedType> wrappedTypes = Utils.wrapMethodNodeParameters(dummyMethodNode);\n        List<WrappedType> expected = List.of(\n                WrappedType.from(String.class),\n                WrappedType.from(boolean.class),\n                WrappedType.from(byte.class),\n                WrappedType.from(char.class),\n                WrappedType.from(short.class),\n                WrappedType.from(int.class),\n                WrappedType.from(long.class),\n                WrappedType.from(float.class),\n                WrappedType.from(double.class)\n        );\n\n        Assert.assertEquals(expected, wrappedTypes);\n    }\n\n    @Test\n    public void testWrapMethodParameters() throws Exception {\n        var method = String.class.getMethod(\"getBytes\", int.class, int.class, byte[].class, int.class);\n\n        List<WrappedType> wrappedTypes = Utils.wrapMethodParameters(method);\n        List<WrappedType> expected = List.of(\n                WrappedType.from(int.class),\n                WrappedType.from(int.class),\n                WrappedType.from(byte[].class),\n                WrappedType.from(int.class)\n        );\n\n        Assert.assertEquals(expected, wrappedTypes);\n    }\n\n    @Test\n    public void testWrapConstructorParameters() throws Exception {\n        var constructor = String.class.getConstructor(byte[].class, String.class);\n\n        List<WrappedType> wrappedTypes = Utils.wrapConstructorParameters(constructor);\n        List<WrappedType> expected = List.of(\n                WrappedType.from(byte[].class),\n                WrappedType.from(String.class)\n        );\n\n        Assert.assertEquals(expected, wrappedTypes);\n    }\n\n    @Test\n    public void testUnwrapMethodDescriptor() {\n        var expected = \"(Ljava/lang/String;ZBCSIJFD)V\";\n        var actual = Utils.unwrapMethodDescriptor(List.of(\n                WrappedType.from(String.class),\n                WrappedType.from(boolean.class),\n                WrappedType.from(byte.class),\n                WrappedType.from(char.class),\n                WrappedType.from(short.class),\n                WrappedType.from(int.class),\n                WrappedType.from(long.class),\n                WrappedType.from(float.class),\n                WrappedType.from(double.class)), WrappedType.from(void.class)\n        );\n\n        Assert.assertEquals(expected, actual);\n    }\n\n    @Test\n    public void testUnpackConstants() {\n        var expected = new Object[]{null, \"test\", false, 0, 0L, 0F, 0D, WrappedType.from(String.class)};\n        var actual = Utils.unpackConstants(List.of(\n                ConstantNode.nullConst(),\n                ConstantNode.stringConst(\"test\"),\n                ConstantNode.booleanConst(false),\n                ConstantNode.intConst(0),\n                ConstantNode.longConst(0L),\n                ConstantNode.floatConst(0F),\n                ConstantNode.doubleConst(0D),\n                ConstantNode.classConst(WrappedType.from(String.class))\n        ));\n\n        Assert.assertArrayEquals(expected, actual);\n    }\n\n    @Test\n    public void testBoxForPrimitives() { // Test all primitive boxings\n        Assert.assertEquals(WrappedType.from(Boolean.class), Utils.box(WrappedType.from(boolean.class)));\n        Assert.assertEquals(WrappedType.from(Character.class), Utils.box(WrappedType.from(char.class)));\n        Assert.assertEquals(WrappedType.from(Byte.class), Utils.box(WrappedType.from(byte.class)));\n        Assert.assertEquals(WrappedType.from(Short.class), Utils.box(WrappedType.from(short.class)));\n        Assert.assertEquals(WrappedType.from(Integer.class), Utils.box(WrappedType.from(int.class)));\n        Assert.assertEquals(WrappedType.from(Long.class), Utils.box(WrappedType.from(long.class)));\n        Assert.assertEquals(WrappedType.from(Float.class), Utils.box(WrappedType.from(float.class)));\n        Assert.assertEquals(WrappedType.from(Double.class), Utils.box(WrappedType.from(double.class)));\n    }\n\n    @Test(expected = IllegalArgumentException.class)\n    public void testBoxForNonPrimitive() { // Ensure exception is thrown when boxing non-primitive\n        Utils.box(WrappedType.from(String.class));\n    }\n}\n"
  },
  {
    "path": "xyz.itzsomebody.codegen/src/test/java/xyz/itzsomebody/codegen/WrappedTypeTester.java",
    "content": "/*\n * Radon - An open-source Java obfuscator\n * Copyright (C) 2021 ItzSomebody\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, either version 3 of the License, or\n * (at your option) any later version.\n *\n * This program is distributed in the hope that it will be 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.  If not, see <http://www.gnu.org/licenses/>\n */\n\npackage xyz.itzsomebody.codegen;\n\nimport org.junit.Assert;\nimport org.junit.Test;\nimport org.objectweb.asm.Opcodes;\nimport org.objectweb.asm.tree.ClassNode;\nimport xyz.itzsomebody.codegen.exceptions.UncompilableNodeException;\n\npublic class WrappedTypeTester {\n    @Test\n    public void testGetAbsent() {\n        Assert.assertNotNull(WrappedType.getAbsent());\n    }\n\n    @Test\n    public void testIsInterface() {\n        Assert.assertTrue(WrappedType.from(Dummy.class).isInterface());\n        Assert.assertFalse(WrappedType.from(int.class).isInterface());\n        Assert.assertFalse(WrappedType.from(String.class).isInterface());\n    }\n\n    @Test\n    public void testIsPrimitive() {\n        Assert.assertTrue(WrappedType.from(boolean.class).isPrimitive());\n        Assert.assertTrue(WrappedType.from(char.class).isPrimitive());\n        Assert.assertTrue(WrappedType.from(byte.class).isPrimitive());\n        Assert.assertTrue(WrappedType.from(short.class).isPrimitive());\n        Assert.assertTrue(WrappedType.from(int.class).isPrimitive());\n        Assert.assertTrue(WrappedType.from(float.class).isPrimitive());\n        Assert.assertTrue(WrappedType.from(long.class).isPrimitive());\n        Assert.assertTrue(WrappedType.from(double.class).isPrimitive());\n\n        Assert.assertFalse(WrappedType.from(int[].class).isPrimitive());\n        Assert.assertFalse(WrappedType.from(String.class).isPrimitive());\n        Assert.assertFalse(WrappedType.from(Integer.class).isPrimitive());\n    }\n\n    @Test\n    public void testGetPrimitiveTypeForBoxedPrimitive() {\n        Assert.assertEquals(WrappedType.from(boolean.class), WrappedType.from(Boolean.class).getPrimitiveType());\n        Assert.assertEquals(WrappedType.from(char.class), WrappedType.from(Character.class).getPrimitiveType());\n        Assert.assertEquals(WrappedType.from(byte.class), WrappedType.from(Byte.class).getPrimitiveType());\n        Assert.assertEquals(WrappedType.from(short.class), WrappedType.from(Short.class).getPrimitiveType());\n        Assert.assertEquals(WrappedType.from(int.class), WrappedType.from(Integer.class).getPrimitiveType());\n        Assert.assertEquals(WrappedType.from(float.class), WrappedType.from(Float.class).getPrimitiveType());\n        Assert.assertEquals(WrappedType.from(long.class), WrappedType.from(Long.class).getPrimitiveType());\n        Assert.assertEquals(WrappedType.from(double.class), WrappedType.from(Double.class).getPrimitiveType());\n    }\n\n    @Test(expected = UncompilableNodeException.class)\n    public void testGetPrimitiveTypeForNonBoxedPrimitive() {\n        WrappedType.from(int.class).getPrimitiveType();\n    }\n\n    @Test\n    public void testIsBoxed() {\n        Assert.assertTrue(WrappedType.from(Boolean.class).isBoxed());\n        Assert.assertTrue(WrappedType.from(Character.class).isBoxed());\n        Assert.assertTrue(WrappedType.from(Byte.class).isBoxed());\n        Assert.assertTrue(WrappedType.from(Short.class).isBoxed());\n        Assert.assertTrue(WrappedType.from(Integer.class).isBoxed());\n        Assert.assertTrue(WrappedType.from(Float.class).isBoxed());\n        Assert.assertTrue(WrappedType.from(Long.class).isBoxed());\n        Assert.assertTrue(WrappedType.from(Double.class).isBoxed());\n\n        Assert.assertFalse(WrappedType.from(Integer[].class).isBoxed());\n        Assert.assertFalse(WrappedType.from(int.class).isBoxed());\n        Assert.assertFalse(WrappedType.from(String.class).isBoxed());\n    }\n\n    @Test\n    public void testIsArray() {\n        Assert.assertTrue(WrappedType.from(int[].class).isArray());\n        Assert.assertTrue(WrappedType.from(String[].class).isArray());\n\n        Assert.assertFalse(WrappedType.from(int.class).isArray());\n        Assert.assertFalse(WrappedType.from(String.class).isArray());\n    }\n\n    @Test\n    public void testIsIntType() {\n        Assert.assertTrue(WrappedType.from(boolean.class).isIntType());\n        Assert.assertTrue(WrappedType.from(char.class).isIntType());\n        Assert.assertTrue(WrappedType.from(byte.class).isIntType());\n        Assert.assertTrue(WrappedType.from(short.class).isIntType());\n        Assert.assertTrue(WrappedType.from(int.class).isIntType());\n\n        Assert.assertFalse(WrappedType.from(float.class).isIntType());\n        Assert.assertFalse(WrappedType.from(long.class).isIntType());\n        Assert.assertFalse(WrappedType.from(double.class).isIntType());\n        Assert.assertFalse(WrappedType.from(int[].class).isPrimitive());\n        Assert.assertFalse(WrappedType.from(String.class).isPrimitive());\n        Assert.assertFalse(WrappedType.from(Integer.class).isPrimitive());\n    }\n\n    @Test\n    public void testUnwrap() {\n        Assert.assertEquals(\"Z\", WrappedType.from(boolean.class).unwrap());\n        Assert.assertEquals(\"C\", WrappedType.from(char.class).unwrap());\n        Assert.assertEquals(\"S\", WrappedType.from(short.class).unwrap());\n        Assert.assertEquals(\"B\", WrappedType.from(byte.class).unwrap());\n        Assert.assertEquals(\"I\", WrappedType.from(int.class).unwrap());\n        Assert.assertEquals(\"J\", WrappedType.from(long.class).unwrap());\n        Assert.assertEquals(\"F\", WrappedType.from(float.class).unwrap());\n        Assert.assertEquals(\"D\", WrappedType.from(double.class).unwrap());\n        Assert.assertEquals(\"Ljava/lang/String;\", WrappedType.from(String.class).unwrap());\n        Assert.assertEquals(\"[Ljava/lang/String;\", WrappedType.from(String[].class).unwrap());\n        Assert.assertEquals(\"[I\", WrappedType.from(int[].class).unwrap());\n    }\n\n    @Test\n    public void testFromClassName() {\n        Assert.assertEquals(WrappedType.from(boolean.class), WrappedType.fromClassName(\"boolean\", false));\n        Assert.assertEquals(WrappedType.from(char.class), WrappedType.fromClassName(\"char\", false));\n        Assert.assertEquals(WrappedType.from(short.class), WrappedType.fromClassName(\"short\", false));\n        Assert.assertEquals(WrappedType.from(byte.class), WrappedType.fromClassName(\"byte\", false));\n        Assert.assertEquals(WrappedType.from(int.class), WrappedType.fromClassName(\"int\", false));\n        Assert.assertEquals(WrappedType.from(long.class), WrappedType.fromClassName(\"long\", false));\n        Assert.assertEquals(WrappedType.from(float.class), WrappedType.fromClassName(\"float\", false));\n        Assert.assertEquals(WrappedType.from(double.class), WrappedType.fromClassName(\"double\", false));\n        Assert.assertEquals(WrappedType.from(String.class), WrappedType.fromClassName(\"java.lang.String\", false));\n        Assert.assertEquals(WrappedType.from(String[].class), WrappedType.fromClassName(\"java.lang.String[]\", false));\n    }\n\n    @Test\n    public void testFromInternalName() {\n        Assert.assertEquals(WrappedType.from(boolean.class), WrappedType.fromInternalName(\"Z\", false));\n        Assert.assertEquals(WrappedType.from(char.class), WrappedType.fromInternalName(\"C\", false));\n        Assert.assertEquals(WrappedType.from(short.class), WrappedType.fromInternalName(\"S\", false));\n        Assert.assertEquals(WrappedType.from(byte.class), WrappedType.fromInternalName(\"B\", false));\n        Assert.assertEquals(WrappedType.from(int.class), WrappedType.fromInternalName(\"I\", false));\n        Assert.assertEquals(WrappedType.from(long.class), WrappedType.fromInternalName(\"J\", false));\n        Assert.assertEquals(WrappedType.from(float.class), WrappedType.fromInternalName(\"F\", false));\n        Assert.assertEquals(WrappedType.from(double.class), WrappedType.fromInternalName(\"D\", false));\n        Assert.assertEquals(WrappedType.from(String.class), WrappedType.fromInternalName(\"java/lang/String\", false));\n        Assert.assertEquals(WrappedType.from(String[].class), WrappedType.fromInternalName(\"[Ljava/lang/String;\", false));\n    }\n\n    @Test\n    public void testFromClassNode() {\n        var dummyClassNode = new ClassNode();\n        dummyClassNode.name = \"xyz/itzsomebody/codegen/WrappedTypeTester$Dummy\";\n        dummyClassNode.access = Opcodes.ACC_INTERFACE;\n        Assert.assertEquals(WrappedType.from(Dummy.class), WrappedType.from(dummyClassNode));\n    }\n\n    private interface Dummy {\n    }\n}\n"
  },
  {
    "path": "xyz.itzsomebody.codegen/src/test/java/xyz/itzsomebody/codegen/expressions/IRVariableTester.java",
    "content": "/*\n * Radon - An open-source Java obfuscator\n * Copyright (C) 2021 ItzSomebody\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, either version 3 of the License, or\n * (at your option) any later version.\n *\n * This program is distributed in the hope that it will be 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.  If not, see <http://www.gnu.org/licenses/>\n */\n\npackage xyz.itzsomebody.codegen.expressions;\n\nimport org.junit.Assert;\nimport org.junit.Test;\nimport org.objectweb.asm.Opcodes;\nimport xyz.itzsomebody.codegen.GenerationContext;\n\npublic class IRVariableTester {\n    @Test\n    public void testGetIntTypeVariable() {\n        var context = new GenerationContext();\n        var insns = context.newVariable(byte.class).getInstructions().compile();\n        Assert.assertEquals(Opcodes.ILOAD, insns.get(0).getOpcode());\n    }\n\n    @Test\n    public void testGetLongVariable() {\n        var context = new GenerationContext();\n        var insns = context.newVariable(long.class).getInstructions().compile();\n        Assert.assertEquals(Opcodes.LLOAD, insns.get(0).getOpcode());\n    }\n\n    @Test\n    public void testGetFloatVariable() {\n        var context = new GenerationContext();\n        var insns = context.newVariable(float.class).getInstructions().compile();\n        Assert.assertEquals(Opcodes.FLOAD, insns.get(0).getOpcode());\n    }\n\n    @Test\n    public void testGetDoubleVariable() {\n        var context = new GenerationContext();\n        var insns = context.newVariable(double.class).getInstructions().compile();\n        Assert.assertEquals(Opcodes.DLOAD, insns.get(0).getOpcode());\n    }\n\n    @Test\n    public void testGetObjectVariable() {\n        var context = new GenerationContext();\n        var insns = context.newVariable(String.class).getInstructions().compile();\n        Assert.assertEquals(Opcodes.ALOAD, insns.get(0).getOpcode());\n    }\n}\n"
  },
  {
    "path": "xyz.itzsomebody.codegen/src/test/java/xyz/itzsomebody/codegen/expressions/predefined/IRArithmeticExpressionTester.java",
    "content": "/*\n * Radon - An open-source Java obfuscator\n * Copyright (C) 2021 ItzSomebody\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, either version 3 of the License, or\n * (at your option) any later version.\n *\n * This program is distributed in the hope that it will be 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.  If not, see <http://www.gnu.org/licenses/>\n */\n\npackage xyz.itzsomebody.codegen.expressions.predefined;\n\nimport org.junit.Assert;\nimport org.junit.Test;\nimport org.objectweb.asm.Opcodes;\n\nimport static xyz.itzsomebody.codegen.expressions.IRExpressions.*;\n\npublic class IRArithmeticExpressionTester {\n    @Test\n    public void testIntMathGeneration() {\n        var block = intAdd(intConst(5), intConst(-3)).getInstructions();\n        var insns = block.compile();\n\n        Assert.assertEquals(Opcodes.ICONST_5, insns.get(0).getOpcode());\n        Assert.assertEquals(Opcodes.BIPUSH, insns.get(1).getOpcode());\n        Assert.assertEquals(Opcodes.IADD, insns.get(2).getOpcode());\n    }\n\n    @Test\n    public void testLongMathGeneration() {\n        var block = longMod(longConst(11), longConst(1)).getInstructions();\n        var insns = block.compile();\n\n        Assert.assertEquals(Opcodes.LDC, insns.get(0).getOpcode());\n        Assert.assertEquals(Opcodes.LCONST_1, insns.get(1).getOpcode());\n        Assert.assertEquals(Opcodes.LREM, insns.get(2).getOpcode());\n    }\n\n    @Test\n    public void testFloatMathGeneration() {\n        var block = floatMul(floatConst(0F), floatConst(2.1f)).getInstructions();\n        var insns = block.compile();\n\n        Assert.assertEquals(Opcodes.FCONST_0, insns.get(0).getOpcode());\n        Assert.assertEquals(Opcodes.LDC, insns.get(1).getOpcode());\n        Assert.assertEquals(Opcodes.FMUL, insns.get(2).getOpcode());\n    }\n\n    @Test\n    public void testDoubleMathGeneration() {\n        var block = doubleSub(doubleConst(1D), doubleConst(8.9999D)).getInstructions();\n        var insns = block.compile();\n\n        Assert.assertEquals(Opcodes.DCONST_1, insns.get(0).getOpcode());\n        Assert.assertEquals(Opcodes.LDC, insns.get(1).getOpcode());\n        Assert.assertEquals(Opcodes.DSUB, insns.get(2).getOpcode());\n    }\n}\n"
  },
  {
    "path": "xyz.itzsomebody.codegen/src/test/java/xyz/itzsomebody/codegen/expressions/predefined/IRArrayLengthTester.java",
    "content": "/*\n * Radon - An open-source Java obfuscator\n * Copyright (C) 2021 ItzSomebody\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, either version 3 of the License, or\n * (at your option) any later version.\n *\n * This program is distributed in the hope that it will be 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.  If not, see <http://www.gnu.org/licenses/>\n */\n\npackage xyz.itzsomebody.codegen.expressions.predefined;\n\nimport org.junit.Assert;\nimport org.junit.Test;\nimport org.objectweb.asm.Opcodes;\n\nimport java.util.stream.IntStream;\n\nimport static xyz.itzsomebody.codegen.expressions.IRExpressions.*;\n\npublic class IRArrayLengthTester {\n    @Test\n    public void testForPrimitiveArray() {\n        var block = arrayLength(newArray(int.class, intConst(0), intConst(1))).getInstructions();\n        var insns = block.compile();\n        var expectedOpcodes = new int[]{\n                Opcodes.ICONST_2,\n                Opcodes.NEWARRAY,\n                Opcodes.DUP,\n                Opcodes.ICONST_0,\n                Opcodes.ICONST_0,\n                Opcodes.IASTORE,\n                Opcodes.DUP,\n                Opcodes.ICONST_1,\n                Opcodes.ICONST_1,\n                Opcodes.IASTORE,\n                Opcodes.ARRAYLENGTH\n        };\n\n        IntStream.range(0, insns.size()).forEach(i -> Assert.assertEquals(expectedOpcodes[i], insns.get(i).getOpcode()));\n    }\n\n    @Test\n    public void testForStringArray() {\n        var block = arrayLength(newArray(String.class, stringConst(\"tux\"), stringConst(\"tucks\"))).getInstructions();\n        var insns = block.compile();\n        var expectedOpcodes = new int[]{\n                Opcodes.ICONST_2,\n                Opcodes.ANEWARRAY,\n                Opcodes.DUP,\n                Opcodes.ICONST_0,\n                Opcodes.LDC,\n                Opcodes.AASTORE,\n                Opcodes.DUP,\n                Opcodes.ICONST_1,\n                Opcodes.LDC,\n                Opcodes.AASTORE,\n                Opcodes.ARRAYLENGTH\n        };\n\n        IntStream.range(0, insns.size()).forEach(i -> Assert.assertEquals(expectedOpcodes[i], insns.get(i).getOpcode()));\n    }\n}\n"
  },
  {
    "path": "xyz.itzsomebody.codegen/src/test/java/xyz/itzsomebody/codegen/expressions/predefined/IRCastExpressionTester.java",
    "content": "/*\n * Radon - An open-source Java obfuscator\n * Copyright (C) 2021 ItzSomebody\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, either version 3 of the License, or\n * (at your option) any later version.\n *\n * This program is distributed in the hope that it will be 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.  If not, see <http://www.gnu.org/licenses/>\n */\n\npackage xyz.itzsomebody.codegen.expressions.predefined;\n\nimport org.junit.Assert;\nimport org.junit.Test;\nimport org.objectweb.asm.Opcodes;\nimport org.objectweb.asm.tree.LdcInsnNode;\nimport org.objectweb.asm.tree.MethodInsnNode;\nimport org.objectweb.asm.tree.TypeInsnNode;\nimport xyz.itzsomebody.codegen.WrappedType;\n\nimport static xyz.itzsomebody.codegen.expressions.IRExpressions.*;\n\npublic class IRCastExpressionTester {\n    @Test\n    public void testCastBooleanToShort() {\n        var block = cast(booleanConst(false), WrappedType.from(short.class)).getInstructions();\n        var insns = block.compile();\n\n        Assert.assertEquals(Opcodes.ICONST_0, insns.get(0).getOpcode());\n    }\n\n    @Test\n    public void testCastDoubleToShort() {\n        var block = cast(doubleConst(99.9999D), WrappedType.from(short.class)).getInstructions();\n        var insns = block.compile();\n\n        Assert.assertEquals(Opcodes.LDC, insns.get(0).getOpcode());\n        Assert.assertEquals(Opcodes.D2I, insns.get(1).getOpcode());\n        Assert.assertEquals(Opcodes.I2S, insns.get(2).getOpcode());\n\n        var ldc = (LdcInsnNode) insns.get(0);\n        Assert.assertEquals(99.9999D, ldc.cst);\n    }\n\n    @Test\n    public void testCastPrimitiveToEquivalentBoxedPrimitive() {\n        var block = cast(booleanConst(false), WrappedType.from(Boolean.class)).getInstructions();\n        var insns = block.compile();\n\n        Assert.assertEquals(Opcodes.ICONST_0, insns.get(0).getOpcode());\n        Assert.assertEquals(Opcodes.INVOKESTATIC, insns.get(1).getOpcode());\n\n        var invoke = (MethodInsnNode) insns.get(1);\n        Assert.assertEquals(\"java/lang/Boolean\", invoke.owner);\n        Assert.assertEquals(\"valueOf\", invoke.name);\n        Assert.assertEquals(\"(Z)Ljava/lang/Boolean;\", invoke.desc);\n    }\n\n    @Test\n    public void testCastPrimitiveToNonPrimitive() {\n        var block = cast(intConst(5), WrappedType.from(Number.class)).getInstructions();\n        var insns = block.compile();\n\n        Assert.assertEquals(Opcodes.ICONST_5, insns.get(0).getOpcode());\n        Assert.assertEquals(Opcodes.INVOKESTATIC, insns.get(1).getOpcode());\n        Assert.assertEquals(Opcodes.CHECKCAST, insns.get(2).getOpcode());\n\n        var invoke = (MethodInsnNode) insns.get(1);\n        Assert.assertEquals(\"java/lang/Integer\", invoke.owner);\n        Assert.assertEquals(\"valueOf\", invoke.name);\n        Assert.assertEquals(\"(I)Ljava/lang/Integer;\", invoke.desc);\n\n        var cast = (TypeInsnNode) insns.get(2);\n        Assert.assertEquals(\"java/lang/Number\", cast.desc);\n    }\n\n    @Test\n    public void testCastBoxedPrimitiveToPrimitive() {\n        var block = cast(cast(intConst(5), WrappedType.from(Integer.class)), WrappedType.from(long.class)).getInstructions();\n        var insns = block.compile();\n\n        Assert.assertEquals(Opcodes.ICONST_5, insns.get(0).getOpcode());\n        Assert.assertEquals(Opcodes.INVOKESTATIC, insns.get(1).getOpcode());\n        Assert.assertEquals(Opcodes.INVOKEVIRTUAL, insns.get(2).getOpcode());\n        Assert.assertEquals(Opcodes.I2L, insns.get(3).getOpcode());\n\n        var invoke1 = (MethodInsnNode) insns.get(1);\n        Assert.assertEquals(\"java/lang/Integer\", invoke1.owner);\n        Assert.assertEquals(\"valueOf\", invoke1.name);\n        Assert.assertEquals(\"(I)Ljava/lang/Integer;\", invoke1.desc);\n\n        var invoke2 = (MethodInsnNode) insns.get(2);\n        Assert.assertEquals(\"java/lang/Integer\", invoke2.owner);\n        Assert.assertEquals(\"intValue\", invoke2.name);\n        Assert.assertEquals(\"()I\", invoke2.desc);\n    }\n\n    @Test\n    public void testCastBoxedPrimitiveToNonPrimitive() {\n        var block = cast(cast(intConst(5), WrappedType.from(Integer.class)), WrappedType.from(Number.class)).getInstructions();\n        var insns = block.compile();\n\n        Assert.assertEquals(Opcodes.ICONST_5, insns.get(0).getOpcode());\n        Assert.assertEquals(Opcodes.INVOKESTATIC, insns.get(1).getOpcode());\n        Assert.assertEquals(Opcodes.CHECKCAST, insns.get(2).getOpcode());\n\n        var invoke = (MethodInsnNode) insns.get(1);\n        Assert.assertEquals(\"java/lang/Integer\", invoke.owner);\n        Assert.assertEquals(\"valueOf\", invoke.name);\n        Assert.assertEquals(\"(I)Ljava/lang/Integer;\", invoke.desc);\n\n        var cast = (TypeInsnNode) insns.get(2);\n        Assert.assertEquals(\"java/lang/Number\", cast.desc);\n    }\n\n    @Test\n    public void testCastNonPrimitiveToPrimitive() {\n        // Don't try this at home lol\n        var block = cast(cast(nullConst(Number.class), WrappedType.from(Integer.class)), WrappedType.from(long.class)).getInstructions();\n        var insns = block.compile();\n\n        Assert.assertEquals(Opcodes.ACONST_NULL, insns.get(0).getOpcode());\n        Assert.assertEquals(Opcodes.CHECKCAST, insns.get(1).getOpcode());\n        Assert.assertEquals(Opcodes.INVOKEVIRTUAL, insns.get(2).getOpcode());\n        Assert.assertEquals(Opcodes.I2L, insns.get(3).getOpcode());\n\n        var cast = (TypeInsnNode) insns.get(1);\n        Assert.assertEquals(\"java/lang/Integer\", cast.desc);\n\n        var invoke = (MethodInsnNode) insns.get(2);\n        Assert.assertEquals(\"java/lang/Integer\", invoke.owner);\n        Assert.assertEquals(\"intValue\", invoke.name);\n        Assert.assertEquals(\"()I\", invoke.desc);\n    }\n\n    @Test\n    public void testCastNonPrimitiveToNonPrimitive() {\n        var block = cast(nullConst(String.class), WrappedType.from(CharSequence.class)).getInstructions();\n        var insns = block.compile();\n\n        Assert.assertEquals(Opcodes.ACONST_NULL, insns.get(0).getOpcode());\n        Assert.assertEquals(Opcodes.CHECKCAST, insns.get(1).getOpcode());\n\n        var cast = (TypeInsnNode) insns.get(1);\n        Assert.assertEquals(\"java/lang/CharSequence\", cast.desc);\n    }\n}\n"
  },
  {
    "path": "xyz.itzsomebody.codegen/src/test/java/xyz/itzsomebody/codegen/expressions/predefined/IRConstantTester.java",
    "content": "/*\n * Radon - An open-source Java obfuscator\n * Copyright (C) 2021 ItzSomebody\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, either version 3 of the License, or\n * (at your option) any later version.\n *\n * This program is distributed in the hope that it will be 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.  If not, see <http://www.gnu.org/licenses/>\n */\n\npackage xyz.itzsomebody.codegen.expressions.predefined;\n\nimport org.junit.Assert;\nimport org.junit.Test;\nimport org.objectweb.asm.ConstantDynamic;\nimport org.objectweb.asm.Opcodes;\nimport org.objectweb.asm.Type;\nimport org.objectweb.asm.tree.IntInsnNode;\nimport org.objectweb.asm.tree.LdcInsnNode;\nimport xyz.itzsomebody.codegen.WrappedHandle;\nimport xyz.itzsomebody.codegen.WrappedType;\n\nimport java.lang.invoke.MethodHandles;\nimport java.util.Collections;\n\nimport static xyz.itzsomebody.codegen.expressions.IRExpressions.*;\n\npublic class IRConstantTester {\n    @Test\n    public void testDynamicConst() throws Exception {\n        var block = dynamicConst(\"tux\", WrappedType.from(String.class), WrappedHandle.getInvokeStaticHandle(IRConstantTester.class.getMethod(\"dynamicTester\", MethodHandles.Lookup.class, String.class, Class.class)), Collections.emptyList()).getInstructions();\n        var insn = block.compile().getFirst();\n\n        Assert.assertTrue(insn instanceof LdcInsnNode && ((LdcInsnNode) insn).cst instanceof ConstantDynamic);\n\n        var dynamic = (ConstantDynamic) ((LdcInsnNode) insn).cst;\n        var handle = dynamic.getBootstrapMethod();\n\n        Assert.assertEquals(Type.getInternalName(IRConstantTester.class), handle.getOwner());\n        Assert.assertEquals(\"dynamicTester\", handle.getName());\n        Assert.assertEquals(\"(Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/Class;)Ljava/lang/String;\", handle.getDesc());\n        Assert.assertEquals(\"tux\", dynamic.getName());\n        Assert.assertEquals(\"Ljava/lang/String;\", dynamic.getDescriptor());\n    }\n\n    @Test\n    public void testNullConst() {\n        var block = nullConst(String.class).getInstructions();\n        var insns = block.compile();\n\n        Assert.assertEquals(Opcodes.ACONST_NULL, insns.get(0).getOpcode());\n    }\n\n    @Test\n    public void testIntConst() {\n        Assert.assertEquals(Opcodes.ICONST_0, intConst(0).getInstructions().compile().get(0).getOpcode());\n        Assert.assertEquals(Opcodes.BIPUSH, intConst(Byte.MAX_VALUE).getInstructions().compile().get(0).getOpcode());\n        Assert.assertEquals(Byte.MAX_VALUE, ((IntInsnNode) intConst(Byte.MAX_VALUE).getInstructions().compile().get(0)).operand);\n        Assert.assertEquals(Opcodes.SIPUSH, intConst(Short.MAX_VALUE).getInstructions().compile().get(0).getOpcode());\n        Assert.assertEquals(Short.MAX_VALUE, ((IntInsnNode) intConst(Short.MAX_VALUE).getInstructions().compile().get(0)).operand);\n        Assert.assertEquals(Opcodes.LDC, intConst(Integer.MAX_VALUE).getInstructions().compile().get(0).getOpcode());\n        Assert.assertEquals(Integer.MAX_VALUE, ((LdcInsnNode) intConst(Integer.MAX_VALUE).getInstructions().compile().get(0)).cst);\n    }\n\n    @Test\n    public void testLongConst() {\n        Assert.assertEquals(Opcodes.LCONST_0, longConst(0L).getInstructions().compile().get(0).getOpcode());\n        Assert.assertEquals(Opcodes.LDC, longConst(Long.MAX_VALUE).getInstructions().compile().get(0).getOpcode());\n        Assert.assertEquals(Long.MAX_VALUE, ((LdcInsnNode) longConst(Long.MAX_VALUE).getInstructions().compile().get(0)).cst);\n    }\n\n    @Test\n    public void testFloatConst() {\n        Assert.assertEquals(Opcodes.FCONST_0, floatConst(0F).getInstructions().compile().get(0).getOpcode());\n        Assert.assertEquals(Opcodes.LDC, floatConst(Float.MAX_VALUE).getInstructions().compile().get(0).getOpcode());\n        Assert.assertEquals(Float.MAX_VALUE, ((LdcInsnNode) floatConst(Float.MAX_VALUE).getInstructions().compile().get(0)).cst);\n    }\n\n    @Test\n    public void testDoubleConst() {\n        Assert.assertEquals(Opcodes.DCONST_0, doubleConst(0D).getInstructions().compile().get(0).getOpcode());\n        Assert.assertEquals(Opcodes.LDC, doubleConst(Double.MAX_VALUE).getInstructions().compile().get(0).getOpcode());\n        Assert.assertEquals(Double.MAX_VALUE, ((LdcInsnNode) doubleConst(Double.MAX_VALUE).getInstructions().compile().get(0)).cst);\n    }\n\n    @Test\n    public void testStringConst() {\n        Assert.assertEquals(Opcodes.LDC, stringConst(\"tux\").getInstructions().compile().get(0).getOpcode());\n        Assert.assertEquals(\"tux\", ((LdcInsnNode) stringConst(\"tux\").getInstructions().compile().get(0)).cst);\n    }\n\n    @Test\n    public void testClassConst() {\n        Assert.assertEquals(Opcodes.LDC, classConst(String.class).getInstructions().compile().get(0).getOpcode());\n        Assert.assertEquals(Type.getType(String.class), ((LdcInsnNode) classConst(String.class).getInstructions().compile().get(0)).cst);\n    }\n\n    public static String dynamicTester(MethodHandles.Lookup lookup, String name, Class<?> type) {\n        return \"test\";\n    }\n}\n"
  },
  {
    "path": "xyz.itzsomebody.codegen/src/test/java/xyz/itzsomebody/codegen/expressions/predefined/IRGetArrayElementExpressionTester.java",
    "content": "/*\n * Radon - An open-source Java obfuscator\n * Copyright (C) 2021 ItzSomebody\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, either version 3 of the License, or\n * (at your option) any later version.\n *\n * This program is distributed in the hope that it will be 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.  If not, see <http://www.gnu.org/licenses/>\n */\n\npackage xyz.itzsomebody.codegen.expressions.predefined;\n\nimport org.junit.Assert;\nimport org.junit.Test;\nimport org.objectweb.asm.Opcodes;\n\nimport static xyz.itzsomebody.codegen.expressions.IRExpressions.*;\n\npublic class IRGetArrayElementExpressionTester {\n    @Test\n    public void testLoadBooleanElement() {\n        var block = getArrayElement(nullConst(boolean.class), intConst(0)).getInstructions();\n        var insns = block.compile();\n\n        Assert.assertEquals(Opcodes.ACONST_NULL, insns.get(0).getOpcode());\n        Assert.assertEquals(Opcodes.ICONST_0, insns.get(1).getOpcode());\n        Assert.assertEquals(Opcodes.IALOAD, insns.get(2).getOpcode());\n    }\n\n    @Test\n    public void testLoadByteElement() {\n        var block = getArrayElement(nullConst(byte.class), intConst(0)).getInstructions();\n        var insns = block.compile();\n\n        Assert.assertEquals(Opcodes.ACONST_NULL, insns.get(0).getOpcode());\n        Assert.assertEquals(Opcodes.ICONST_0, insns.get(1).getOpcode());\n        Assert.assertEquals(Opcodes.BALOAD, insns.get(2).getOpcode());\n    }\n\n    @Test\n    public void testLoadShortElement() {\n        var block = getArrayElement(nullConst(short.class), intConst(0)).getInstructions();\n        var insns = block.compile();\n\n        Assert.assertEquals(Opcodes.ACONST_NULL, insns.get(0).getOpcode());\n        Assert.assertEquals(Opcodes.ICONST_0, insns.get(1).getOpcode());\n        Assert.assertEquals(Opcodes.SALOAD, insns.get(2).getOpcode());\n    }\n\n    @Test\n    public void testLoadCharElement() {\n        var block = getArrayElement(nullConst(char.class), intConst(0)).getInstructions();\n        var insns = block.compile();\n\n        Assert.assertEquals(Opcodes.ACONST_NULL, insns.get(0).getOpcode());\n        Assert.assertEquals(Opcodes.ICONST_0, insns.get(1).getOpcode());\n        Assert.assertEquals(Opcodes.CALOAD, insns.get(2).getOpcode());\n    }\n\n    @Test\n    public void testLoadIntElement() {\n        var block = getArrayElement(nullConst(int.class), intConst(0)).getInstructions();\n        var insns = block.compile();\n\n        Assert.assertEquals(Opcodes.ACONST_NULL, insns.get(0).getOpcode());\n        Assert.assertEquals(Opcodes.ICONST_0, insns.get(1).getOpcode());\n        Assert.assertEquals(Opcodes.IALOAD, insns.get(2).getOpcode());\n    }\n\n    @Test\n    public void testLoadLongElement() {\n        var block = getArrayElement(nullConst(long.class), intConst(0)).getInstructions();\n        var insns = block.compile();\n\n        Assert.assertEquals(Opcodes.ACONST_NULL, insns.get(0).getOpcode());\n        Assert.assertEquals(Opcodes.ICONST_0, insns.get(1).getOpcode());\n        Assert.assertEquals(Opcodes.LALOAD, insns.get(2).getOpcode());\n    }\n\n    @Test\n    public void testLoadFloatElement() {\n        var block = getArrayElement(nullConst(float.class), intConst(0)).getInstructions();\n        var insns = block.compile();\n\n        Assert.assertEquals(Opcodes.ACONST_NULL, insns.get(0).getOpcode());\n        Assert.assertEquals(Opcodes.ICONST_0, insns.get(1).getOpcode());\n        Assert.assertEquals(Opcodes.FALOAD, insns.get(2).getOpcode());\n    }\n\n    @Test\n    public void testLoadDoubleElement() {\n        var block = getArrayElement(nullConst(double.class), intConst(0)).getInstructions();\n        var insns = block.compile();\n\n        Assert.assertEquals(Opcodes.ACONST_NULL, insns.get(0).getOpcode());\n        Assert.assertEquals(Opcodes.ICONST_0, insns.get(1).getOpcode());\n        Assert.assertEquals(Opcodes.DALOAD, insns.get(2).getOpcode());\n    }\n\n    @Test\n    public void testLoadObjectElement() {\n        var block = getArrayElement(nullConst(String.class), intConst(0)).getInstructions();\n        var insns = block.compile();\n\n        Assert.assertEquals(Opcodes.ACONST_NULL, insns.get(0).getOpcode());\n        Assert.assertEquals(Opcodes.ICONST_0, insns.get(1).getOpcode());\n        Assert.assertEquals(Opcodes.AALOAD, insns.get(2).getOpcode());\n    }\n}\n"
  },
  {
    "path": "xyz.itzsomebody.codegen/src/test/java/xyz/itzsomebody/codegen/expressions/predefined/IRGetFieldExpressionTester.java",
    "content": "/*\n * Radon - An open-source Java obfuscator\n * Copyright (C) 2021 ItzSomebody\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, either version 3 of the License, or\n * (at your option) any later version.\n *\n * This program is distributed in the hope that it will be 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.  If not, see <http://www.gnu.org/licenses/>\n */\n\npackage xyz.itzsomebody.codegen.expressions.predefined;\n\nimport org.junit.Assert;\nimport org.junit.Test;\nimport org.objectweb.asm.Opcodes;\nimport org.objectweb.asm.Type;\nimport org.objectweb.asm.tree.FieldInsnNode;\nimport xyz.itzsomebody.codegen.WrappedType;\n\nimport static xyz.itzsomebody.codegen.expressions.IRExpressions.*;\n\npublic class IRGetFieldExpressionTester {\n    @Test\n    public void testGetObjectField() throws Exception {\n        var fin = (FieldInsnNode) getField(nullConst(WrappedType.from(TestClass.class)), TestClass.class.getField(\"exampleField\")).getInstructions().compile().get(1);\n        Assert.assertEquals(Opcodes.GETFIELD, fin.getOpcode());\n        Assert.assertEquals(Type.getInternalName(TestClass.class), fin.owner);\n        Assert.assertEquals(\"exampleField\", fin.name);\n        Assert.assertEquals(\"Ljava/lang/String;\", fin.desc);\n    }\n\n    @Test\n    public void testGetPrimitiveField() throws Exception {\n        var fin = (FieldInsnNode) getField(nullConst(WrappedType.from(TestClass.class)), TestClass.class.getField(\"examplePrimitiveField\")).getInstructions().compile().get(1);\n        Assert.assertEquals(Opcodes.GETFIELD, fin.getOpcode());\n        Assert.assertEquals(Type.getInternalName(TestClass.class), fin.owner);\n        Assert.assertEquals(\"examplePrimitiveField\", fin.name);\n        Assert.assertEquals(\"B\", fin.desc);\n    }\n\n    @Test\n    public void testGetObjectStatic() throws Exception {\n        var fin = (FieldInsnNode) getStatic(TestClass.class.getField(\"exampleStaticField\")).getInstructions().compile().get(0);\n        Assert.assertEquals(Opcodes.GETSTATIC, fin.getOpcode());\n        Assert.assertEquals(Type.getInternalName(TestClass.class), fin.owner);\n        Assert.assertEquals(\"exampleStaticField\", fin.name);\n        Assert.assertEquals(\"Ljava/lang/String;\", fin.desc);\n    }\n\n    @Test\n    public void testGetPrimitiveStatic() throws Exception {\n        var fin = (FieldInsnNode) getStatic(TestClass.class.getField(\"exampleStaticPrimitiveField\")).getInstructions().compile().get(0);\n        Assert.assertEquals(Opcodes.GETSTATIC, fin.getOpcode());\n        Assert.assertEquals(Type.getInternalName(TestClass.class), fin.owner);\n        Assert.assertEquals(\"exampleStaticPrimitiveField\", fin.name);\n        Assert.assertEquals(\"B\", fin.desc);\n    }\n\n    public static class TestClass {\n        public String exampleField;\n        public byte examplePrimitiveField;\n        public static String exampleStaticField;\n        public static byte exampleStaticPrimitiveField;\n    }\n}\n"
  },
  {
    "path": "xyz.itzsomebody.codegen/src/test/java/xyz/itzsomebody/codegen/expressions/predefined/IRInstanceOfExpressionTester.java",
    "content": "/*\n * Radon - An open-source Java obfuscator\n * Copyright (C) 2021 ItzSomebody\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, either version 3 of the License, or\n * (at your option) any later version.\n *\n * This program is distributed in the hope that it will be 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.  If not, see <http://www.gnu.org/licenses/>\n */\n\npackage xyz.itzsomebody.codegen.expressions.predefined;\n\nimport org.junit.Assert;\nimport org.junit.Test;\nimport org.objectweb.asm.tree.TypeInsnNode;\nimport xyz.itzsomebody.codegen.WrappedType;\n\nimport static xyz.itzsomebody.codegen.expressions.IRExpressions.instanceOf;\nimport static xyz.itzsomebody.codegen.expressions.IRExpressions.nullConst;\n\npublic class IRInstanceOfExpressionTester {\n    @Test\n    public void testInstanceOfClass() {\n        var tin = (TypeInsnNode) instanceOf(nullConst(Integer.class), Number.class).getInstructions().compile().get(1);\n        Assert.assertEquals(\"java/lang/Number\", tin.desc);\n    }\n\n    @Test\n    public void testInstanceOfWrappedType() {\n        var tin = (TypeInsnNode) instanceOf(nullConst(Integer.class), WrappedType.from(Number.class)).getInstructions().compile().get(1);\n        Assert.assertEquals(\"java/lang/Number\", tin.desc);\n    }\n}\n"
  },
  {
    "path": "xyz.itzsomebody.codegen/src/test/java/xyz/itzsomebody/codegen/expressions/predefined/IRInvocationExpressionTester.java",
    "content": "/*\n * Radon - An open-source Java obfuscator\n * Copyright (C) 2021 ItzSomebody\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, either version 3 of the License, or\n * (at your option) any later version.\n *\n * This program is distributed in the hope that it will be 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.  If not, see <http://www.gnu.org/licenses/>\n */\n\npackage xyz.itzsomebody.codegen.expressions.predefined;\n\nimport org.junit.Assert;\nimport org.junit.Test;\nimport org.objectweb.asm.Opcodes;\nimport org.objectweb.asm.Type;\nimport org.objectweb.asm.tree.MethodInsnNode;\n\nimport static xyz.itzsomebody.codegen.expressions.IRExpressions.*;\n\npublic class IRInvocationExpressionTester {\n    @Test\n    public void testInvokeStatic() throws Exception {\n        var min = (MethodInsnNode) invokeStatic(DummyClass.class.getMethod(\"dummyStatic\", String.class, int[].class)).getInstructions().compile().get(0);\n        Assert.assertEquals(Opcodes.INVOKESTATIC, min.getOpcode());\n        Assert.assertEquals(Type.getInternalName(DummyClass.class), min.owner);\n        Assert.assertEquals(\"dummyStatic\", min.name);\n        Assert.assertEquals(\"(Ljava/lang/String;[I)V\", min.desc);\n    }\n\n    @Test\n    public void testInvokeVirtual() throws Exception {\n        var min = (MethodInsnNode) invokeVirtual(nullConst(DummyClass.class), DummyClass.class.getMethod(\"dummyMethod\", String.class, byte.class)).getInstructions().compile().get(1);\n        Assert.assertEquals(Opcodes.INVOKEVIRTUAL, min.getOpcode());\n        Assert.assertEquals(Type.getInternalName(DummyClass.class), min.owner);\n        Assert.assertEquals(\"dummyMethod\", min.name);\n        Assert.assertEquals(\"(Ljava/lang/String;B)V\", min.desc);\n    }\n\n    @Test\n    public void testInvokeInterface() throws Exception {\n        var min = (MethodInsnNode) invokeVirtual(nullConst(DummyInterface.class), DummyInterface.class.getMethod(\"dummyInterfaceMethod\", String.class, boolean.class)).getInstructions().compile().get(1);\n        Assert.assertEquals(Opcodes.INVOKEINTERFACE, min.getOpcode());\n        Assert.assertEquals(Type.getInternalName(DummyInterface.class), min.owner);\n        Assert.assertEquals(\"dummyInterfaceMethod\", min.name);\n        Assert.assertEquals(\"(Ljava/lang/String;Z)V\", min.desc);\n    }\n\n    public interface DummyInterface {\n        void dummyInterfaceMethod(String tux, boolean tucks);\n    }\n\n    public static class DummyClass implements DummyInterface {\n        public void dummyMethod(String tux, byte tucks) {\n        }\n\n        public static void dummyStatic(String tux, int[] tucks) {\n        }\n\n        @Override\n        public void dummyInterfaceMethod(String tux, boolean tucks) {\n        }\n    }\n}\n"
  },
  {
    "path": "xyz.itzsomebody.codegen/src/test/java/xyz/itzsomebody/codegen/expressions/predefined/IRInvokeDynamicExpressionTester.java",
    "content": "/*\n * Radon - An open-source Java obfuscator\n * Copyright (C) 2021 ItzSomebody\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, either version 3 of the License, or\n * (at your option) any later version.\n *\n * This program is distributed in the hope that it will be 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.  If not, see <http://www.gnu.org/licenses/>\n */\n\npackage xyz.itzsomebody.codegen.expressions.predefined;\n\nimport org.junit.Assert;\nimport org.junit.Test;\nimport org.objectweb.asm.Opcodes;\nimport org.objectweb.asm.Type;\nimport org.objectweb.asm.tree.InvokeDynamicInsnNode;\nimport org.objectweb.asm.tree.LdcInsnNode;\nimport xyz.itzsomebody.codegen.WrappedHandle;\nimport xyz.itzsomebody.codegen.WrappedType;\n\nimport java.lang.invoke.CallSite;\nimport java.lang.invoke.MethodHandles;\nimport java.lang.invoke.MethodType;\nimport java.util.Collections;\nimport java.util.List;\n\nimport static xyz.itzsomebody.codegen.expressions.IRExpressions.invokeDynamic;\nimport static xyz.itzsomebody.codegen.expressions.IRExpressions.stringConst;\n\npublic class IRInvokeDynamicExpressionTester {\n    @Test\n    public void testInvokeDynamicWithMethodBootstrap() throws Exception {\n        var method = IRInvokeDynamicExpressionTester.class.getMethod(\"dummyBootstrap\", MethodHandles.Lookup.class, String.class, MethodType.class);\n        var block = invokeDynamic(\n                \"tucks\",\n                List.of(stringConst(\"tux\"), stringConst(\"tuks\")),\n                List.of(WrappedType.from(String.class), WrappedType.from(String.class)),\n                WrappedType.from(String.class),\n                method,\n                Collections.emptyList()\n        ).getInstructions();\n        var insns = block.compile();\n\n        Assert.assertEquals(\"tux\", ((LdcInsnNode) insns.get(0)).cst);\n        Assert.assertEquals(\"tuks\", ((LdcInsnNode) insns.get(1)).cst);\n        Assert.assertEquals(Opcodes.INVOKEDYNAMIC, insns.get(2).getOpcode());\n\n        var indy = (InvokeDynamicInsnNode) insns.get(2);\n        var handle = indy.bsm;\n        Assert.assertEquals(\"tucks\", indy.name);\n        Assert.assertEquals(\"(Ljava/lang/String;Ljava/lang/String;)Ljava/lang/String;\", indy.desc);\n        Assert.assertEquals(Type.getInternalName(IRInvokeDynamicExpressionTester.class), handle.getOwner());\n        Assert.assertEquals(\"dummyBootstrap\", handle.getName());\n        Assert.assertEquals(\"(Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;)Ljava/lang/invoke/CallSite;\", handle.getDesc());\n    }\n\n    @Test\n    public void testInvokeDynamicWithWrappedHandleBootstrap() throws Exception {\n        var method = IRInvokeDynamicExpressionTester.class.getMethod(\"dummyBootstrap\", MethodHandles.Lookup.class, String.class, MethodType.class);\n        var block = invokeDynamic(\n                \"tucks\",\n                List.of(stringConst(\"tux\"), stringConst(\"tuks\")),\n                List.of(WrappedType.from(String.class), WrappedType.from(String.class)),\n                WrappedType.from(String.class),\n                WrappedHandle.getInvokeStaticHandle(method),\n                Collections.emptyList()\n        ).getInstructions();\n        var insns = block.compile();\n\n        Assert.assertEquals(\"tux\", ((LdcInsnNode) insns.get(0)).cst);\n        Assert.assertEquals(\"tuks\", ((LdcInsnNode) insns.get(1)).cst);\n        Assert.assertEquals(Opcodes.INVOKEDYNAMIC, insns.get(2).getOpcode());\n\n        var indy = (InvokeDynamicInsnNode) insns.get(2);\n        var handle = indy.bsm;\n        Assert.assertEquals(\"tucks\", indy.name);\n        Assert.assertEquals(\"(Ljava/lang/String;Ljava/lang/String;)Ljava/lang/String;\", indy.desc);\n        Assert.assertEquals(Type.getInternalName(IRInvokeDynamicExpressionTester.class), handle.getOwner());\n        Assert.assertEquals(\"dummyBootstrap\", handle.getName());\n        Assert.assertEquals(\"(Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;)Ljava/lang/invoke/CallSite;\", handle.getDesc());\n    }\n\n    public static CallSite dummyBootstrap(MethodHandles.Lookup lookup, String name, MethodType type) {\n        return null;\n    }\n}\n"
  },
  {
    "path": "xyz.itzsomebody.codegen/src/test/java/xyz/itzsomebody/codegen/expressions/predefined/IRNegateExpressionTester.java",
    "content": "/*\n * Radon - An open-source Java obfuscator\n * Copyright (C) 2021 ItzSomebody\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, either version 3 of the License, or\n * (at your option) any later version.\n *\n * This program is distributed in the hope that it will be 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.  If not, see <http://www.gnu.org/licenses/>\n */\n\npackage xyz.itzsomebody.codegen.expressions.predefined;\n\nimport org.junit.Assert;\nimport org.junit.Test;\nimport org.objectweb.asm.Opcodes;\nimport org.objectweb.asm.tree.InsnNode;\nimport xyz.itzsomebody.codegen.exceptions.UncompilableNodeException;\n\nimport static xyz.itzsomebody.codegen.expressions.IRExpressions.*;\n\npublic class IRNegateExpressionTester {\n    @Test\n    public void testNegateBoolean() {\n        var insn = (InsnNode) negate(booleanConst(false)).getInstructions().compile().get(1);\n        Assert.assertEquals(Opcodes.INEG, insn.getOpcode());\n    }\n\n    @Test\n    public void testNegateInt() {\n        var insn = (InsnNode) negate(intConst(0)).getInstructions().compile().get(1);\n        Assert.assertEquals(Opcodes.INEG, insn.getOpcode());\n    }\n\n    @Test\n    public void testNegateLong() {\n        var insn = (InsnNode) negate(longConst(0L)).getInstructions().compile().get(1);\n        Assert.assertEquals(Opcodes.LNEG, insn.getOpcode());\n    }\n\n    @Test\n    public void testNegateFloat() {\n        var insn = (InsnNode) negate(floatConst(0F)).getInstructions().compile().get(1);\n        Assert.assertEquals(Opcodes.FNEG, insn.getOpcode());\n    }\n\n    @Test\n    public void testNegateDouble() {\n        var insn = (InsnNode) negate(doubleConst(0D)).getInstructions().compile().get(1);\n        Assert.assertEquals(Opcodes.DNEG, insn.getOpcode());\n    }\n\n    @Test(expected = UncompilableNodeException.class)\n    public void ensureExceptionThrownOnNonNegatableOperand() {\n        negate(nullConst(String.class)).getInstructions();\n    }\n}\n"
  },
  {
    "path": "xyz.itzsomebody.codegen/src/test/java/xyz/itzsomebody/codegen/expressions/predefined/IRNewArrayExpressionTester.java",
    "content": "/*\n * Radon - An open-source Java obfuscator\n * Copyright (C) 2021 ItzSomebody\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, either version 3 of the License, or\n * (at your option) any later version.\n *\n * This program is distributed in the hope that it will be 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.  If not, see <http://www.gnu.org/licenses/>\n */\n\npackage xyz.itzsomebody.codegen.expressions.predefined;\n\nimport org.junit.Assert;\nimport org.junit.Test;\nimport org.objectweb.asm.Opcodes;\nimport org.objectweb.asm.tree.IntInsnNode;\n\nimport java.util.stream.IntStream;\n\nimport static xyz.itzsomebody.codegen.expressions.IRExpressions.*;\n\npublic class IRNewArrayExpressionTester {\n    @Test\n    public void testForPrimitiveArray() {\n        var block = newArray(int.class, intConst(0), intConst(1)).getInstructions();\n        var insns = block.compile();\n        var expectedOpcodes = new int[]{\n                Opcodes.ICONST_2,\n                Opcodes.NEWARRAY,\n                Opcodes.DUP,\n                Opcodes.ICONST_0,\n                Opcodes.ICONST_0,\n                Opcodes.IASTORE,\n                Opcodes.DUP,\n                Opcodes.ICONST_1,\n                Opcodes.ICONST_1,\n                Opcodes.IASTORE,\n        };\n\n        IntStream.range(0, insns.size()).forEach(i -> Assert.assertEquals(expectedOpcodes[i], insns.get(i).getOpcode()));\n        Assert.assertEquals(Opcodes.T_INT, ((IntInsnNode) insns.get(1)).operand);\n    }\n\n    @Test\n    public void testForStringArray() {\n        var block = newArray(String.class, stringConst(\"tux\"), stringConst(\"tucks\")).getInstructions();\n        var insns = block.compile();\n        var expectedOpcodes = new int[]{\n                Opcodes.ICONST_2,\n                Opcodes.ANEWARRAY,\n                Opcodes.DUP,\n                Opcodes.ICONST_0,\n                Opcodes.LDC,\n                Opcodes.AASTORE,\n                Opcodes.DUP,\n                Opcodes.ICONST_1,\n                Opcodes.LDC,\n                Opcodes.AASTORE,\n        };\n\n        IntStream.range(0, insns.size()).forEach(i -> Assert.assertEquals(expectedOpcodes[i], insns.get(i).getOpcode()));\n    }\n}\n"
  },
  {
    "path": "xyz.itzsomebody.codegen/src/test/java/xyz/itzsomebody/codegen/expressions/predefined/IRNewInstanceExpressionTester.java",
    "content": "/*\n * Radon - An open-source Java obfuscator\n * Copyright (C) 2021 ItzSomebody\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, either version 3 of the License, or\n * (at your option) any later version.\n *\n * This program is distributed in the hope that it will be 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.  If not, see <http://www.gnu.org/licenses/>\n */\n\npackage xyz.itzsomebody.codegen.expressions.predefined;\n\nimport org.junit.Assert;\nimport org.junit.Test;\nimport org.objectweb.asm.Opcodes;\nimport org.objectweb.asm.tree.MethodInsnNode;\nimport org.objectweb.asm.tree.TypeInsnNode;\nimport xyz.itzsomebody.codegen.WrappedType;\n\nimport java.util.Collections;\n\nimport static xyz.itzsomebody.codegen.expressions.IRExpressions.newInstance;\n\npublic class IRNewInstanceExpressionTester {\n    @Test\n    public void testNewInstanceViaConstructor() throws Exception {\n        var insns = newInstance(String.class.getConstructor()).getInstructions().compile();\n        var newOp = (TypeInsnNode) insns.get(0);\n        Assert.assertEquals(\"java/lang/String\", newOp.desc);\n        Assert.assertEquals(Opcodes.DUP, insns.get(1).getOpcode());\n        var invoke = (MethodInsnNode) insns.get(2);\n        Assert.assertEquals(\"java/lang/String\", invoke.owner);\n        Assert.assertEquals(\"<init>\", invoke.name);\n        Assert.assertEquals(\"()V\", invoke.desc);\n    }\n\n    @Test\n    public void testNewInstanceViaWrappedType() throws Exception {\n        var insns = newInstance(WrappedType.from(String.class), Collections.emptyList(), Collections.emptyList()).getInstructions().compile();\n        var newOp = (TypeInsnNode) insns.get(0);\n        Assert.assertEquals(\"java/lang/String\", newOp.desc);\n        Assert.assertEquals(Opcodes.DUP, insns.get(1).getOpcode());\n        var invoke = (MethodInsnNode) insns.get(2);\n        Assert.assertEquals(\"java/lang/String\", invoke.owner);\n        Assert.assertEquals(\"<init>\", invoke.name);\n        Assert.assertEquals(\"()V\", invoke.desc);\n    }\n}\n"
  },
  {
    "path": "xyz.itzsomebody.codegen/src/test/java/xyz/itzsomebody/codegen/expressions/predefined/IRReturnExpressionTester.java",
    "content": "/*\n * Radon - An open-source Java obfuscator\n * Copyright (C) 2021 ItzSomebody\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, either version 3 of the License, or\n * (at your option) any later version.\n *\n * This program is distributed in the hope that it will be 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.  If not, see <http://www.gnu.org/licenses/>\n */\n\npackage xyz.itzsomebody.codegen.expressions.predefined;\n\nimport org.junit.Assert;\nimport org.junit.Test;\nimport org.objectweb.asm.Opcodes;\n\nimport static xyz.itzsomebody.codegen.expressions.IRExpressions.*;\n\npublic class IRReturnExpressionTester {\n    @Test\n    public void testReturnBoolean() {\n        Assert.assertEquals(Opcodes.IRETURN, returnMe(booleanConst(false)).getInstructions().compile().get(1).getOpcode());\n    }\n\n    @Test\n    public void testReturnInt() {\n        Assert.assertEquals(Opcodes.IRETURN, returnMe(intConst(0)).getInstructions().compile().get(1).getOpcode());\n    }\n\n    @Test\n    public void testReturnLong() {\n        Assert.assertEquals(Opcodes.LRETURN, returnMe(longConst(0L)).getInstructions().compile().get(1).getOpcode());\n    }\n\n    @Test\n    public void testReturnFloat() {\n        Assert.assertEquals(Opcodes.FRETURN, returnMe(floatConst(0F)).getInstructions().compile().get(1).getOpcode());\n    }\n\n    @Test\n    public void testReturnDouble() {\n        Assert.assertEquals(Opcodes.DRETURN, returnMe(doubleConst(0D)).getInstructions().compile().get(1).getOpcode());\n    }\n\n    @Test\n    public void testReturnObject() {\n        Assert.assertEquals(Opcodes.ARETURN, returnMe(nullConst(String.class)).getInstructions().compile().get(1).getOpcode());\n    }\n\n    @Test\n    public void testReturnNothing() {\n        Assert.assertEquals(Opcodes.RETURN, returnMe(null).getInstructions().compile().get(0).getOpcode());\n    }\n}\n"
  },
  {
    "path": "xyz.itzsomebody.codegen/src/test/java/xyz/itzsomebody/codegen/expressions/predefined/IRSetArrayElementExpressionTester.java",
    "content": "package xyz.itzsomebody.codegen.expressions.predefined;\n\nimport org.junit.Assert;\nimport org.junit.Test;\nimport org.objectweb.asm.Opcodes;\n\nimport static xyz.itzsomebody.codegen.expressions.IRExpressions.*;\n\npublic class IRSetArrayElementExpressionTester {\n    @Test\n    public void testStoreBooleanElement() {\n        var block = setArrayElement(nullConst(boolean.class), intConst(0), booleanConst(false)).getInstructions();\n        var insns = block.compile();\n\n        Assert.assertEquals(Opcodes.ACONST_NULL, insns.get(0).getOpcode());\n        Assert.assertEquals(Opcodes.ICONST_0, insns.get(1).getOpcode());\n        Assert.assertEquals(Opcodes.ICONST_0, insns.get(2).getOpcode());\n        Assert.assertEquals(Opcodes.IASTORE, insns.get(3).getOpcode());\n    }\n\n    @Test\n    public void testStoreByteElement() {\n        var block = setArrayElement(nullConst(byte.class), intConst(0), intConst(0)).getInstructions();\n        var insns = block.compile();\n\n        Assert.assertEquals(Opcodes.ACONST_NULL, insns.get(0).getOpcode());\n        Assert.assertEquals(Opcodes.ICONST_0, insns.get(1).getOpcode());\n        Assert.assertEquals(Opcodes.ICONST_0, insns.get(2).getOpcode());\n        Assert.assertEquals(Opcodes.BASTORE, insns.get(3).getOpcode());\n    }\n\n    @Test\n    public void testStoreShortElement() {\n        var block = setArrayElement(nullConst(short.class), intConst(0), intConst(0)).getInstructions();\n        var insns = block.compile();\n\n        Assert.assertEquals(Opcodes.ACONST_NULL, insns.get(0).getOpcode());\n        Assert.assertEquals(Opcodes.ICONST_0, insns.get(1).getOpcode());\n        Assert.assertEquals(Opcodes.ICONST_0, insns.get(2).getOpcode());\n        Assert.assertEquals(Opcodes.SASTORE, insns.get(3).getOpcode());\n    }\n\n    @Test\n    public void testStoreCharElement() {\n        var block = setArrayElement(nullConst(char.class), intConst(0), intConst(0)).getInstructions();\n        var insns = block.compile();\n\n        Assert.assertEquals(Opcodes.ACONST_NULL, insns.get(0).getOpcode());\n        Assert.assertEquals(Opcodes.ICONST_0, insns.get(1).getOpcode());\n        Assert.assertEquals(Opcodes.ICONST_0, insns.get(2).getOpcode());\n        Assert.assertEquals(Opcodes.CASTORE, insns.get(3).getOpcode());\n    }\n\n    @Test\n    public void testStoreIntElement() {\n        var block = setArrayElement(nullConst(int.class), intConst(0), intConst(0)).getInstructions();\n        var insns = block.compile();\n\n        Assert.assertEquals(Opcodes.ACONST_NULL, insns.get(0).getOpcode());\n        Assert.assertEquals(Opcodes.ICONST_0, insns.get(1).getOpcode());\n        Assert.assertEquals(Opcodes.ICONST_0, insns.get(2).getOpcode());\n        Assert.assertEquals(Opcodes.IASTORE, insns.get(3).getOpcode());\n    }\n\n    @Test\n    public void testStoreLongElement() {\n        var block = setArrayElement(nullConst(long.class), intConst(0), longConst(0L)).getInstructions();\n        var insns = block.compile();\n\n        Assert.assertEquals(Opcodes.ACONST_NULL, insns.get(0).getOpcode());\n        Assert.assertEquals(Opcodes.ICONST_0, insns.get(1).getOpcode());\n        Assert.assertEquals(Opcodes.LCONST_0, insns.get(2).getOpcode());\n        Assert.assertEquals(Opcodes.LASTORE, insns.get(3).getOpcode());\n    }\n\n    @Test\n    public void testStoreFloatElement() {\n        var block = setArrayElement(nullConst(float.class), intConst(0), floatConst(0F)).getInstructions();\n        var insns = block.compile();\n\n        Assert.assertEquals(Opcodes.ACONST_NULL, insns.get(0).getOpcode());\n        Assert.assertEquals(Opcodes.ICONST_0, insns.get(1).getOpcode());\n        Assert.assertEquals(Opcodes.FCONST_0, insns.get(2).getOpcode());\n        Assert.assertEquals(Opcodes.FASTORE, insns.get(3).getOpcode());\n    }\n\n    @Test\n    public void testStoreDoubleElement() {\n        var block = setArrayElement(nullConst(double.class), intConst(0), doubleConst(0D)).getInstructions();\n        var insns = block.compile();\n\n        Assert.assertEquals(Opcodes.ACONST_NULL, insns.get(0).getOpcode());\n        Assert.assertEquals(Opcodes.ICONST_0, insns.get(1).getOpcode());\n        Assert.assertEquals(Opcodes.DCONST_0, insns.get(2).getOpcode());\n        Assert.assertEquals(Opcodes.DASTORE, insns.get(3).getOpcode());\n    }\n\n    @Test\n    public void testStoreObjectElement() {\n        var block = setArrayElement(nullConst(String.class), intConst(0), nullConst(String.class)).getInstructions();\n        var insns = block.compile();\n\n        Assert.assertEquals(Opcodes.ACONST_NULL, insns.get(0).getOpcode());\n        Assert.assertEquals(Opcodes.ICONST_0, insns.get(1).getOpcode());\n        Assert.assertEquals(Opcodes.ACONST_NULL, insns.get(2).getOpcode());\n        Assert.assertEquals(Opcodes.AASTORE, insns.get(3).getOpcode());\n    }\n}\n"
  },
  {
    "path": "xyz.itzsomebody.codegen/src/test/java/xyz/itzsomebody/codegen/expressions/predefined/IRSetFieldExpressionTester.java",
    "content": "/*\n * Radon - An open-source Java obfuscator\n * Copyright (C) 2021 ItzSomebody\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, either version 3 of the License, or\n * (at your option) any later version.\n *\n * This program is distributed in the hope that it will be 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.  If not, see <http://www.gnu.org/licenses/>\n */\n\npackage xyz.itzsomebody.codegen.expressions.predefined;\n\nimport org.junit.Assert;\nimport org.junit.Test;\nimport org.objectweb.asm.Opcodes;\nimport org.objectweb.asm.Type;\nimport org.objectweb.asm.tree.FieldInsnNode;\nimport xyz.itzsomebody.codegen.WrappedType;\n\nimport static xyz.itzsomebody.codegen.expressions.IRExpressions.*;\n\npublic class IRSetFieldExpressionTester {\n    @Test\n    public void testSetObjectField() throws Exception {\n        var fin = (FieldInsnNode) setField(nullConst(WrappedType.from(IRSetFieldExpressionTester.TestClass.class)), IRSetFieldExpressionTester.TestClass.class.getField(\"exampleField\"), nullConst(String.class)).getInstructions().compile().get(2);\n        Assert.assertEquals(Opcodes.PUTFIELD, fin.getOpcode());\n        Assert.assertEquals(Type.getInternalName(IRSetFieldExpressionTester.TestClass.class), fin.owner);\n        Assert.assertEquals(\"exampleField\", fin.name);\n        Assert.assertEquals(\"Ljava/lang/String;\", fin.desc);\n    }\n\n    @Test\n    public void testSetPrimitiveField() throws Exception {\n        var fin = (FieldInsnNode) setField(nullConst(WrappedType.from(IRSetFieldExpressionTester.TestClass.class)), IRSetFieldExpressionTester.TestClass.class.getField(\"examplePrimitiveField\"), intConst(0)).getInstructions().compile().get(2);\n        Assert.assertEquals(Opcodes.PUTFIELD, fin.getOpcode());\n        Assert.assertEquals(Type.getInternalName(IRSetFieldExpressionTester.TestClass.class), fin.owner);\n        Assert.assertEquals(\"examplePrimitiveField\", fin.name);\n        Assert.assertEquals(\"B\", fin.desc);\n    }\n\n    @Test\n    public void testSetObjectStatic() throws Exception {\n        var fin = (FieldInsnNode) setStatic(IRSetFieldExpressionTester.TestClass.class.getField(\"exampleStaticField\"), nullConst(String.class)).getInstructions().compile().get(1);\n        Assert.assertEquals(Opcodes.PUTSTATIC, fin.getOpcode());\n        Assert.assertEquals(Type.getInternalName(IRSetFieldExpressionTester.TestClass.class), fin.owner);\n        Assert.assertEquals(\"exampleStaticField\", fin.name);\n        Assert.assertEquals(\"Ljava/lang/String;\", fin.desc);\n    }\n\n    @Test\n    public void testSetPrimitiveStatic() throws Exception {\n        var fin = (FieldInsnNode) setStatic(IRSetFieldExpressionTester.TestClass.class.getField(\"exampleStaticPrimitiveField\"), intConst(0)).getInstructions().compile().get(1);\n        Assert.assertEquals(Opcodes.PUTSTATIC, fin.getOpcode());\n        Assert.assertEquals(Type.getInternalName(IRSetFieldExpressionTester.TestClass.class), fin.owner);\n        Assert.assertEquals(\"exampleStaticPrimitiveField\", fin.name);\n        Assert.assertEquals(\"B\", fin.desc);\n    }\n\n    public static class TestClass {\n        public String exampleField;\n        public byte examplePrimitiveField;\n        public static String exampleStaticField;\n        public static byte exampleStaticPrimitiveField;\n    }\n}\n"
  },
  {
    "path": "xyz.itzsomebody.codegen/src/test/java/xyz/itzsomebody/codegen/expressions/predefined/IRSetVariableExpressionTester.java",
    "content": "/*\n * Radon - An open-source Java obfuscator\n * Copyright (C) 2021 ItzSomebody\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, either version 3 of the License, or\n * (at your option) any later version.\n *\n * This program is distributed in the hope that it will be 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.  If not, see <http://www.gnu.org/licenses/>\n */\n\npackage xyz.itzsomebody.codegen.expressions.predefined;\n\nimport org.junit.Assert;\nimport org.junit.Test;\nimport org.objectweb.asm.Opcodes;\nimport xyz.itzsomebody.codegen.GenerationContext;\n\nimport static xyz.itzsomebody.codegen.expressions.IRExpressions.*;\n\npublic class IRSetVariableExpressionTester {\n    @Test\n    public void testSetIntTypeVariable() {\n        var context = new GenerationContext();\n        var insns = context.newVariable(byte.class).set(intConst(0)).getInstructions().compile();\n        Assert.assertEquals(Opcodes.ICONST_0, insns.get(0).getOpcode());\n        Assert.assertEquals(Opcodes.ISTORE, insns.get(1).getOpcode());\n    }\n\n    @Test\n    public void testSetLongVariable() {\n        var context = new GenerationContext();\n        var insns = context.newVariable(long.class).set(longConst(0L)).getInstructions().compile();\n        Assert.assertEquals(Opcodes.LCONST_0, insns.get(0).getOpcode());\n        Assert.assertEquals(Opcodes.LSTORE, insns.get(1).getOpcode());\n    }\n\n    @Test\n    public void testSetFloatVariable() {\n        var context = new GenerationContext();\n        var insns = context.newVariable(float.class).set(floatConst(0F)).getInstructions().compile();\n        Assert.assertEquals(Opcodes.FCONST_0, insns.get(0).getOpcode());\n        Assert.assertEquals(Opcodes.FSTORE, insns.get(1).getOpcode());\n    }\n\n    @Test\n    public void testSetDoubleVariable() {\n        var context = new GenerationContext();\n        var insns = context.newVariable(double.class).set(doubleConst(0)).getInstructions().compile();\n        Assert.assertEquals(Opcodes.DCONST_0, insns.get(0).getOpcode());\n        Assert.assertEquals(Opcodes.DSTORE, insns.get(1).getOpcode());\n    }\n\n    @Test\n    public void testSetObjectVariable() {\n        var context = new GenerationContext();\n        var insns = context.newVariable(String.class).set(stringConst(\"tucks\")).getInstructions().compile();\n        Assert.assertEquals(Opcodes.LDC, insns.get(0).getOpcode());\n        Assert.assertEquals(Opcodes.ASTORE, insns.get(1).getOpcode());\n    }\n}\n"
  },
  {
    "path": "xyz.itzsomebody.codegen/src/test/java/xyz/itzsomebody/codegen/instructions/BytecodeLabelTester.java",
    "content": "/*\n * Radon - An open-source Java obfuscator\n * Copyright (C) 2021 ItzSomebody\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, either version 3 of the License, or\n * (at your option) any later version.\n *\n * This program is distributed in the hope that it will be 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.  If not, see <http://www.gnu.org/licenses/>\n */\n\npackage xyz.itzsomebody.codegen.instructions;\n\nimport org.junit.Assert;\nimport org.junit.Test;\n\npublic class BytecodeLabelTester {\n    @Test\n    public void ensureCreatedLabelsAreUnique() {\n        Assert.assertNotEquals(new BytecodeLabel().getLabel(), new BytecodeLabel().getLabel());\n    }\n}\n"
  },
  {
    "path": "xyz.itzsomebody.codegen/src/test/java/xyz/itzsomebody/codegen/instructions/ConstantNodeTester.java",
    "content": "/*\n * Radon - An open-source Java obfuscator\n * Copyright (C) 2021 ItzSomebody\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, either version 3 of the License, or\n * (at your option) any later version.\n *\n * This program is distributed in the hope that it will be 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.  If not, see <http://www.gnu.org/licenses/>\n */\n\npackage xyz.itzsomebody.codegen.instructions;\n\nimport org.junit.Assert;\nimport org.junit.Test;\nimport org.objectweb.asm.Opcodes;\nimport xyz.itzsomebody.codegen.WrappedType;\n\npublic class ConstantNodeTester {\n    @Test\n    public void testNullConst() {\n        Assert.assertNull(ConstantNode.nullConst().getValue());\n        Assert.assertEquals(Opcodes.ACONST_NULL, ConstantNode.nullConst().getNode().getOpcode());\n    }\n\n    @Test\n    public void testBooleanConst() {\n        Assert.assertTrue((Boolean) ConstantNode.booleanConst(true).getValue());\n        Assert.assertNotEquals(Opcodes.ICONST_0, ConstantNode.booleanConst(true).getNode().getOpcode());\n        Assert.assertFalse((Boolean) ConstantNode.booleanConst(false).getValue());\n        Assert.assertEquals(Opcodes.ICONST_0, ConstantNode.booleanConst(false).getNode().getOpcode());\n    }\n\n    @Test\n    public void testIntConst() {\n        Assert.assertEquals(Integer.MIN_VALUE, ConstantNode.intConst(Integer.MIN_VALUE).getValue());\n        Assert.assertEquals(Opcodes.LDC, ConstantNode.intConst(Integer.MIN_VALUE).getNode().getOpcode());\n        Assert.assertEquals(Opcodes.SIPUSH, ConstantNode.intConst(Short.MIN_VALUE).getNode().getOpcode());\n        Assert.assertEquals(Opcodes.BIPUSH, ConstantNode.intConst(Byte.MIN_VALUE).getNode().getOpcode());\n        Assert.assertEquals(Opcodes.ICONST_M1, ConstantNode.intConst(-1).getNode().getOpcode());\n    }\n\n    @Test\n    public void testFloatConst() {\n        Assert.assertEquals(Float.MIN_VALUE, ConstantNode.floatConst(Float.MIN_VALUE).getValue());\n        Assert.assertEquals(Opcodes.LDC, ConstantNode.floatConst(Float.MIN_VALUE).getNode().getOpcode());\n        Assert.assertEquals(Opcodes.FCONST_0, ConstantNode.floatConst(0F).getNode().getOpcode());\n    }\n\n    @Test\n    public void testDoubleConst() {\n        Assert.assertEquals(Double.MIN_VALUE, ConstantNode.doubleConst(Double.MIN_VALUE).getValue());\n        Assert.assertEquals(Opcodes.LDC, ConstantNode.doubleConst(Double.MIN_VALUE).getNode().getOpcode());\n        Assert.assertEquals(Opcodes.DCONST_0, ConstantNode.doubleConst(0D).getNode().getOpcode());\n    }\n\n    @Test\n    public void testStringConst() {\n        Assert.assertEquals(\"tucks\", ConstantNode.stringConst(\"tucks\").getValue());\n        Assert.assertEquals(Opcodes.LDC, ConstantNode.stringConst(\"tux\").getNode().getOpcode());\n    }\n\n    @Test\n    public void testClassConst() {\n        Assert.assertEquals(WrappedType.from(String.class), ConstantNode.classConst(WrappedType.from(String.class)).getValue());\n    }\n}\n"
  },
  {
    "path": "xyz.itzsomebody.codegen/src/test/java/xyz/itzsomebody/codegen/instructions/FieldAccessNodeTester.java",
    "content": "/*\n * Radon - An open-source Java obfuscator\n * Copyright (C) 2021 ItzSomebody\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, either version 3 of the License, or\n * (at your option) any later version.\n *\n * This program is distributed in the hope that it will be 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.  If not, see <http://www.gnu.org/licenses/>\n */\n\npackage xyz.itzsomebody.codegen.instructions;\n\nimport org.junit.Assert;\nimport org.junit.Test;\nimport org.objectweb.asm.Opcodes;\nimport org.objectweb.asm.tree.FieldInsnNode;\nimport xyz.itzsomebody.codegen.WrappedType;\n\npublic class FieldAccessNodeTester {\n    @Test\n    public void testGetStatic() {\n        var getStatic = (FieldInsnNode) FieldAccessNode.getStatic(WrappedType.from(Integer.class), \"TYPE\", WrappedType.from(Class.class)).getNode();\n        Assert.assertEquals(Opcodes.GETSTATIC, getStatic.getOpcode());\n        Assert.assertEquals(\"java/lang/Integer\", getStatic.owner);\n        Assert.assertEquals(\"TYPE\", getStatic.name);\n        Assert.assertEquals(\"Ljava/lang/Class;\", getStatic.desc);\n    }\n\n    @Test\n    public void testPutStatic() {\n        var putStatic = (FieldInsnNode) FieldAccessNode.putStatic(WrappedType.from(String.class), \"hash\", WrappedType.from(int.class)).getNode();\n        Assert.assertEquals(Opcodes.PUTSTATIC, putStatic.getOpcode());\n        Assert.assertEquals(\"java/lang/String\", putStatic.owner);\n        Assert.assertEquals(\"hash\", putStatic.name);\n        Assert.assertEquals(\"I\", putStatic.desc);\n    }\n\n    @Test\n    public void testGetField() {\n        var getField = (FieldInsnNode) FieldAccessNode.getField(WrappedType.from(Integer.class), \"value\", WrappedType.from(int.class)).getNode();\n        Assert.assertEquals(Opcodes.GETFIELD, getField.getOpcode());\n        Assert.assertEquals(\"java/lang/Integer\", getField.owner);\n        Assert.assertEquals(\"value\", getField.name);\n        Assert.assertEquals(\"I\", getField.desc);\n    }\n\n    @Test\n    public void testPutField() {\n        var putField = (FieldInsnNode) FieldAccessNode.putField(WrappedType.from(String.class), \"value\", WrappedType.from(byte[].class)).getNode();\n        Assert.assertEquals(Opcodes.PUTFIELD, putField.getOpcode());\n        Assert.assertEquals(\"java/lang/String\", putField.owner);\n        Assert.assertEquals(\"value\", putField.name);\n        Assert.assertEquals(\"[B\", putField.desc);\n    }\n}\n"
  },
  {
    "path": "xyz.itzsomebody.codegen/src/test/java/xyz/itzsomebody/codegen/instructions/InvokeDynamicNodeTester.java",
    "content": "/*\n * Radon - An open-source Java obfuscator\n * Copyright (C) 2021 ItzSomebody\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, either version 3 of the License, or\n * (at your option) any later version.\n *\n * This program is distributed in the hope that it will be 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.  If not, see <http://www.gnu.org/licenses/>\n */\n\npackage xyz.itzsomebody.codegen.instructions;\n\nimport org.junit.Assert;\nimport org.junit.Test;\nimport org.objectweb.asm.Type;\nimport org.objectweb.asm.tree.InvokeDynamicInsnNode;\nimport xyz.itzsomebody.codegen.WrappedHandle;\nimport xyz.itzsomebody.codegen.WrappedType;\n\nimport java.lang.invoke.CallSite;\nimport java.lang.invoke.MethodHandles;\nimport java.lang.invoke.MethodType;\nimport java.util.Collections;\nimport java.util.List;\n\npublic class InvokeDynamicNodeTester {\n    @Test\n    public void testInvokeDynamicWithMethod() throws Exception {\n        var method = InvokeDynamicNodeTester.class.getMethod(\"testBootstrap\", MethodHandles.Lookup.class, String.class, MethodType.class);\n        var invoke = (InvokeDynamicInsnNode) InvokeDynamicNode.invokeDynamic(\"tux\", List.of(WrappedType.from(String.class)), WrappedType.from(void.class), method, Collections.emptyList()).getNode();\n        Assert.assertEquals(\"tux\", invoke.name);\n        Assert.assertEquals(\"(Ljava/lang/String;)V\", invoke.desc);\n        var handle = invoke.bsm;\n        Assert.assertEquals(Type.getInternalName(InvokeDynamicNodeTester.class), handle.getOwner());\n        Assert.assertEquals(\"testBootstrap\", handle.getName());\n        Assert.assertEquals(\"(Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;)Ljava/lang/invoke/CallSite;\", handle.getDesc());\n    }\n\n    @Test\n    public void testInvokeDynamicWithWrappedHandle() throws Exception {\n        var invoke = (InvokeDynamicInsnNode) InvokeDynamicNode.invokeDynamic(\"tux\", List.of(WrappedType.from(String.class)), WrappedType.from(void.class), WrappedHandle.getInvokeStaticHandle(InvokeDynamicNodeTester.class.getMethod(\"testBootstrap\", MethodHandles.Lookup.class, String.class, MethodType.class)), Collections.emptyList()).getNode();\n        Assert.assertEquals(\"tux\", invoke.name);\n        Assert.assertEquals(\"(Ljava/lang/String;)V\", invoke.desc);\n        var handle = invoke.bsm;\n        Assert.assertEquals(Type.getInternalName(InvokeDynamicNodeTester.class), handle.getOwner());\n        Assert.assertEquals(\"testBootstrap\", handle.getName());\n        Assert.assertEquals(\"(Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;)Ljava/lang/invoke/CallSite;\", handle.getDesc());\n    }\n\n    public static CallSite testBootstrap(MethodHandles.Lookup lookup, String name, MethodType methodType) {\n        return null;\n    }\n}\n"
  },
  {
    "path": "xyz.itzsomebody.codegen/src/test/java/xyz/itzsomebody/codegen/instructions/InvokeNodeTester.java",
    "content": "/*\n * Radon - An open-source Java obfuscator\n * Copyright (C) 2021 ItzSomebody\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, either version 3 of the License, or\n * (at your option) any later version.\n *\n * This program is distributed in the hope that it will be 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.  If not, see <http://www.gnu.org/licenses/>\n */\n\npackage xyz.itzsomebody.codegen.instructions;\n\nimport org.junit.Assert;\nimport org.junit.Test;\nimport org.objectweb.asm.Opcodes;\nimport org.objectweb.asm.tree.MethodInsnNode;\nimport xyz.itzsomebody.codegen.WrappedType;\n\nimport java.nio.charset.Charset;\nimport java.util.Collections;\nimport java.util.List;\n\npublic class InvokeNodeTester {\n    @Test\n    public void testInvokeStatic() {\n        var invokeStatic = (MethodInsnNode) InvokeNode.invokeStatic(WrappedType.from(String.class), \"valueOf\", List.of(WrappedType.from(int.class)), WrappedType.from(String.class)).getNode();\n        Assert.assertEquals(Opcodes.INVOKESTATIC, invokeStatic.getOpcode());\n        Assert.assertEquals(\"java/lang/String\", invokeStatic.owner);\n        Assert.assertEquals(\"valueOf\", invokeStatic.name);\n        Assert.assertEquals(\"(I)Ljava/lang/String;\", invokeStatic.desc);\n    }\n\n    @Test\n    public void testInvokeVirtual() {\n        var invokeVirtual = (MethodInsnNode) InvokeNode.invokeVirtual(WrappedType.from(String.class), \"hashCode\", Collections.emptyList(), WrappedType.from(int.class)).getNode();\n        Assert.assertEquals(Opcodes.INVOKEVIRTUAL, invokeVirtual.getOpcode());\n        Assert.assertEquals(\"java/lang/String\", invokeVirtual.owner);\n        Assert.assertEquals(\"hashCode\", invokeVirtual.name);\n        Assert.assertEquals(\"()I\", invokeVirtual.desc);\n    }\n\n    @Test\n    public void testInvokeInterface() {\n        var invokeInterface = (MethodInsnNode) InvokeNode.invokeInterface(WrappedType.from(CharSequence.class), \"length\", Collections.emptyList(), WrappedType.from(int.class)).getNode();\n        Assert.assertEquals(Opcodes.INVOKEINTERFACE, invokeInterface.getOpcode());\n        Assert.assertEquals(\"java/lang/CharSequence\", invokeInterface.owner);\n        Assert.assertEquals(\"length\", invokeInterface.name);\n        Assert.assertEquals(\"()I\", invokeInterface.desc);\n    }\n\n    @Test\n    public void testInvokeSpecials() {\n        var invokeSpecial = (MethodInsnNode) InvokeNode.invokeSpecial(WrappedType.from(String.class), \"valueOf\", List.of(WrappedType.from(int.class)), WrappedType.from(String.class)).getNode();\n        Assert.assertEquals(Opcodes.INVOKESPECIAL, invokeSpecial.getOpcode());\n        Assert.assertEquals(\"java/lang/String\", invokeSpecial.owner);\n        Assert.assertEquals(\"valueOf\", invokeSpecial.name);\n        Assert.assertEquals(\"(I)Ljava/lang/String;\", invokeSpecial.desc);\n    }\n\n    @Test\n    public void testInvokeConstructor() {\n        var invokeConstructor = (MethodInsnNode) InvokeNode.invokeConstructor(WrappedType.from(String.class), List.of(WrappedType.from(byte[].class), WrappedType.from(Charset.class))).getNode();\n        Assert.assertEquals(Opcodes.INVOKESPECIAL, invokeConstructor.getOpcode());\n        Assert.assertEquals(\"java/lang/String\", invokeConstructor.owner);\n        Assert.assertEquals(\"<init>\", invokeConstructor.name);\n        Assert.assertEquals(\"([BLjava/nio/charset/Charset;)V\", invokeConstructor.desc);\n    }\n}\n"
  },
  {
    "path": "xyz.itzsomebody.codegen/src/test/java/xyz/itzsomebody/codegen/instructions/NewArrayNodeTester.java",
    "content": "/*\n * Radon - An open-source Java obfuscator\n * Copyright (C) 2021 ItzSomebody\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, either version 3 of the License, or\n * (at your option) any later version.\n *\n * This program is distributed in the hope that it will be 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.  If not, see <http://www.gnu.org/licenses/>\n */\n\npackage xyz.itzsomebody.codegen.instructions;\n\nimport org.junit.Assert;\nimport org.junit.Test;\nimport org.objectweb.asm.Opcodes;\nimport org.objectweb.asm.Type;\nimport org.objectweb.asm.tree.IntInsnNode;\nimport org.objectweb.asm.tree.TypeInsnNode;\nimport xyz.itzsomebody.codegen.WrappedType;\n\npublic class NewArrayNodeTester {\n    @Test\n    public void testPrimitiveArrayType() {\n        Assert.assertEquals(Opcodes.NEWARRAY, new NewArrayNode(WrappedType.from(boolean.class)).getNode().getOpcode());\n        Assert.assertEquals(Opcodes.T_BOOLEAN, ((IntInsnNode) new NewArrayNode(WrappedType.from(boolean.class)).getNode()).operand);\n\n        Assert.assertEquals(Opcodes.NEWARRAY, new NewArrayNode(WrappedType.from(char.class)).getNode().getOpcode());\n        Assert.assertEquals(Opcodes.T_CHAR, ((IntInsnNode) new NewArrayNode(WrappedType.from(char.class)).getNode()).operand);\n\n        Assert.assertEquals(Opcodes.NEWARRAY, new NewArrayNode(WrappedType.from(byte.class)).getNode().getOpcode());\n        Assert.assertEquals(Opcodes.T_BYTE, ((IntInsnNode) new NewArrayNode(WrappedType.from(byte.class)).getNode()).operand);\n\n        Assert.assertEquals(Opcodes.NEWARRAY, new NewArrayNode(WrappedType.from(short.class)).getNode().getOpcode());\n        Assert.assertEquals(Opcodes.T_SHORT, ((IntInsnNode) new NewArrayNode(WrappedType.from(short.class)).getNode()).operand);\n\n        Assert.assertEquals(Opcodes.NEWARRAY, new NewArrayNode(WrappedType.from(int.class)).getNode().getOpcode());\n        Assert.assertEquals(Opcodes.T_INT, ((IntInsnNode) new NewArrayNode(WrappedType.from(int.class)).getNode()).operand);\n\n        Assert.assertEquals(Opcodes.NEWARRAY, new NewArrayNode(WrappedType.from(long.class)).getNode().getOpcode());\n        Assert.assertEquals(Opcodes.T_LONG, ((IntInsnNode) new NewArrayNode(WrappedType.from(long.class)).getNode()).operand);\n\n        Assert.assertEquals(Opcodes.NEWARRAY, new NewArrayNode(WrappedType.from(float.class)).getNode().getOpcode());\n        Assert.assertEquals(Opcodes.T_FLOAT, ((IntInsnNode) new NewArrayNode(WrappedType.from(float.class)).getNode()).operand);\n\n        Assert.assertEquals(Opcodes.NEWARRAY, new NewArrayNode(WrappedType.from(double.class)).getNode().getOpcode());\n        Assert.assertEquals(Opcodes.T_DOUBLE, ((IntInsnNode) new NewArrayNode(WrappedType.from(double.class)).getNode()).operand);\n    }\n\n    @Test\n    public void testNonPrimitiveArrayType() {\n        Assert.assertEquals(Opcodes.ANEWARRAY, new NewArrayNode(WrappedType.from(String.class)).getNode().getOpcode());\n        Assert.assertEquals(\"java/lang/String\", ((TypeInsnNode) new NewArrayNode(WrappedType.from(String.class)).getNode()).desc);\n\n        Assert.assertEquals(Opcodes.ANEWARRAY, new NewArrayNode(WrappedType.from(Integer.class)).getNode().getOpcode());\n        Assert.assertEquals(\"java/lang/Integer\", ((TypeInsnNode) new NewArrayNode(WrappedType.from(Integer.class)).getNode()).desc);\n    }\n}\n"
  },
  {
    "path": "xyz.itzsomebody.codegen/src/test/java/xyz/itzsomebody/codegen/instructions/TypeNodeTester.java",
    "content": "/*\n * Radon - An open-source Java obfuscator\n * Copyright (C) 2021 ItzSomebody\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, either version 3 of the License, or\n * (at your option) any later version.\n *\n * This program is distributed in the hope that it will be 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.  If not, see <http://www.gnu.org/licenses/>\n */\n\npackage xyz.itzsomebody.codegen.instructions;\n\nimport org.junit.Assert;\nimport org.junit.Test;\nimport org.objectweb.asm.Opcodes;\nimport org.objectweb.asm.tree.TypeInsnNode;\nimport xyz.itzsomebody.codegen.WrappedType;\n\npublic class TypeNodeTester {\n    @Test\n    public void testNewInstanceForCorrectOpcode() {\n        Assert.assertEquals(Opcodes.NEW, TypeNode.newInstance(WrappedType.from(String.class)).getNode().getOpcode());\n    }\n\n    @Test\n    public void testNewInstanceForValidType() {\n        Assert.assertEquals(\"java/lang/String\", ((TypeInsnNode) TypeNode.newInstance(WrappedType.from(String.class)).getNode()).desc);\n    }\n}\n"
  },
  {
    "path": "xyz.itzsomebody.commons/README.md",
    "content": "# Commons\n\nTODO: put analyzers and instruction matcher here\n"
  },
  {
    "path": "xyz.itzsomebody.commons/build.gradle",
    "content": "/*\n * Radon - An open-source Java obfuscator\n * Copyright (C) 2021 ItzSomebody\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, either version 3 of the License, or\n * (at your option) any later version.\n *\n * This program is distributed in the hope that it will be 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.  If not, see <http://www.gnu.org/licenses/>\n */\n\nplugins {\n    id 'java'\n}\n\nsourceCompatibility = javaVer\n\ndependencies {\n    implementation annotations\n    implementation asm\n    implementation asmTree\n    implementation asmAnalysis\n    testImplementation junit\n}\n"
  },
  {
    "path": "xyz.itzsomebody.commons/src/main/java/xyz/itzsomebody/commons/InsnListModifier.java",
    "content": "/*\n * Radon - An open-source Java obfuscator\n * Copyright (C) 2021 ItzSomebody\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, either version 3 of the License, or\n * (at your option) any later version.\n *\n * This program is distributed in the hope that it will be 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.  If not, see <http://www.gnu.org/licenses/>\n */\n\npackage xyz.itzsomebody.commons;\n\nimport org.jetbrains.annotations.NotNull;\nimport org.objectweb.asm.tree.AbstractInsnNode;\nimport org.objectweb.asm.tree.InsnList;\nimport org.objectweb.asm.tree.MethodNode;\n\nimport java.util.ArrayList;\nimport java.util.HashMap;\nimport java.util.List;\nimport java.util.Map;\n\n/**\n * This class allows for easy modifications of {@link org.objectweb.asm.tree.InsnList}s. This is identical in idea to\n * the \"InstructionModifier\" in java-deobfuscator. The idea of this modifier is to make it easier to modify instruction\n * lists while iterating over them.\n */\npublic class InsnListModifier {\n    private final List<InsnList> appends = new ArrayList<>();\n    private final List<InsnList> prepends = new ArrayList<>();\n    private final Map<AbstractInsnNode, InsnList> inserts = new HashMap<>();\n    private final Map<AbstractInsnNode, InsnList> insertBefores = new HashMap<>();\n    private final Map<AbstractInsnNode, InsnList> replacements = new HashMap<>();\n    private final List<AbstractInsnNode> removals = new ArrayList<>();\n\n    public InsnListModifier append(InsnList insns) {\n        appends.add(insns);\n        return this;\n    }\n\n    public InsnListModifier append(@NotNull AbstractInsnNode... insns) {\n        var list = new InsnList();\n        List.of(insns).forEach(list::add);\n        appends.add(list);\n        return this;\n    }\n\n    public InsnListModifier prepend(InsnList insns) {\n        prepends.add(insns);\n        return this;\n    }\n\n    public InsnListModifier prepend(@NotNull AbstractInsnNode... insns) {\n        var list = new InsnList();\n        List.of(insns).forEach(list::add);\n        prepends.add(list);\n        return this;\n    }\n\n    public InsnListModifier insert(AbstractInsnNode previous, InsnList insns) {\n        inserts.put(previous, insns);\n        return this;\n    }\n\n    public InsnListModifier insert(AbstractInsnNode previous, @NotNull AbstractInsnNode... insns) {\n        var list = new InsnList();\n        List.of(insns).forEach(list::add);\n        inserts.put(previous, list);\n        return this;\n    }\n\n    public InsnListModifier insertBefore(AbstractInsnNode next, InsnList insns) {\n        insertBefores.put(next, insns);\n        return this;\n    }\n\n    public InsnListModifier insertBefore(AbstractInsnNode next, @NotNull AbstractInsnNode... insns) {\n        var list = new InsnList();\n        List.of(insns).forEach(list::add);\n        insertBefores.put(next, list);\n        return this;\n    }\n\n    public InsnListModifier replace(AbstractInsnNode old, InsnList replacement) {\n        replacements.put(old, replacement);\n        return this;\n    }\n\n    public InsnListModifier replace(AbstractInsnNode old, @NotNull AbstractInsnNode... insns) {\n        var list = new InsnList();\n        List.of(insns).forEach(list::add);\n        replacements.put(old, list);\n        return this;\n    }\n\n    public InsnListModifier remove(AbstractInsnNode insn) {\n        removals.add(insn);\n        return this;\n    }\n\n    public InsnListModifier remove(@NotNull AbstractInsnNode... insns) {\n        List.of(insns).forEach(this::remove);\n        return this;\n    }\n\n    public InsnListModifier remove(Iterable<? extends AbstractInsnNode> iterable) {\n        iterable.forEach(this::remove);\n        return this;\n    }\n\n    public void apply(InsnList insns) {\n        appends.forEach(insns::add);\n        prepends.forEach(insns::insert);\n        inserts.forEach(insns::insert);\n        insertBefores.forEach(insns::insertBefore);\n        replacements.forEach((old, replacement) -> {\n            insns.insert(old, replacement);\n            insns.remove(old);\n        });\n        removals.forEach(insns::remove);\n    }\n\n    public void apply(MethodNode node) {\n        apply(node.instructions);\n    }\n}\n"
  },
  {
    "path": "xyz.itzsomebody.commons/src/main/java/xyz/itzsomebody/commons/MaxLocalsUpdater.java",
    "content": "/*\n * Radon - An open-source Java obfuscator\n * Copyright (C) 2021 ItzSomebody\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, either version 3 of the License, or\n * (at your option) any later version.\n *\n * This program is distributed in the hope that it will be 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.  If not, see <http://www.gnu.org/licenses/>\n */\n\npackage xyz.itzsomebody.commons;\n\nimport org.objectweb.asm.MethodVisitor;\nimport org.objectweb.asm.Opcodes;\nimport org.objectweb.asm.Type;\nimport org.objectweb.asm.tree.MethodNode;\n\n/**\n * Determines the numbers of locals slots being used by a method based on the variable instructions within the method.\n *\n * @author itzsomebody\n */\npublic class MaxLocalsUpdater {\n    private final MethodNode methodNode;\n\n    private MaxLocalsUpdater(MethodNode methodNode) {\n        this.methodNode = methodNode;\n    }\n\n    private int computeMaxs() {\n        int size = 0;\n        if ((methodNode.access & Opcodes.ACC_STATIC) == 0) {\n            size += 1; // Non-static implicitly declares variable 0 as \"this\"\n        }\n        for (var type : Type.getArgumentTypes(methodNode.desc)) {\n            size += type.getSize();\n        }\n        var visitor = new MaxLocalsVisitor(size);\n        methodNode.accept(visitor);\n        return visitor.getSize(); // Quality code /s\n    }\n\n    public static void update(MethodNode methodNode) {\n        methodNode.visitMaxs(methodNode.maxStack, new MaxLocalsUpdater(methodNode).computeMaxs());\n    }\n\n    class MaxLocalsVisitor extends MethodVisitor {\n        private int size;\n\n        public MaxLocalsVisitor(int initialSize) {\n            super(/* latest api */ Opcodes.ASM9, null);\n            this.size = initialSize;\n        }\n\n        @Override\n        public void visitVarInsn(int opcode, int var) {\n            if (var >= size) {\n                size = var + 1;\n                if (opcode == Opcodes.LLOAD\n                        || opcode == Opcodes.DLOAD\n                        || opcode == Opcodes.LSTORE\n                        || opcode == Opcodes.DSTORE) {\n                    size += 1;\n                }\n            }\n        }\n\n        @Override\n        public void visitIincInsn(int var, int increment) {\n            if (var >= size) {\n                size = var + 1;\n            }\n        }\n\n        public int getSize() {\n            return size;\n        }\n    }\n}\n"
  },
  {
    "path": "xyz.itzsomebody.commons/src/main/java/xyz/itzsomebody/commons/analysis/callgraph/CallGraphAnalyzer.java",
    "content": "package xyz.itzsomebody.commons.analysis.callgraph;\n\npublic class CallGraphAnalyzer {\n    // TODO\n}\n"
  },
  {
    "path": "xyz.itzsomebody.commons/src/main/java/xyz/itzsomebody/commons/analysis/cfg/CFGAnalyzer.java",
    "content": "package xyz.itzsomebody.commons.analysis.cfg;\n\npublic class CFGAnalyzer {\n    // TODO\n}\n"
  },
  {
    "path": "xyz.itzsomebody.commons/src/main/java/xyz/itzsomebody/commons/analysis/frame/FrameAnalyzer.java",
    "content": "package xyz.itzsomebody.commons.analysis.frame;\n\npublic class FrameAnalyzer {\n    // tODO\n}\n"
  },
  {
    "path": "xyz.itzsomebody.commons/src/main/java/xyz/itzsomebody/commons/matcher/InstructionMatcher.java",
    "content": "/*\n * Radon - An open-source Java obfuscator\n * Copyright (C) 2021 ItzSomebody\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, either version 3 of the License, or\n * (at your option) any later version.\n *\n * This program is distributed in the hope that it will be 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.  If not, see <http://www.gnu.org/licenses/>\n */\n\npackage xyz.itzsomebody.commons.matcher;\n\nimport org.objectweb.asm.tree.AbstractInsnNode;\n\nimport java.util.ArrayList;\nimport java.util.List;\n\npublic class InstructionMatcher {\n    private final InstructionPattern pattern;\n    private final AbstractInsnNode start;\n    private final List<List<AbstractInsnNode>> captured = new ArrayList<>();\n\n    public InstructionMatcher(InstructionPattern pattern, AbstractInsnNode start) {\n        this.pattern = pattern;\n        this.start = start;\n    }\n\n    public boolean matches() {\n        var rules = pattern.getRules();\n        if (rules.size() == 0) {\n            return false;\n        }\n\n        var current = start;\n        ArrayList<AbstractInsnNode> possibleMatch = new ArrayList<>();\n        for (var rule : rules) {\n            if (current == null || !rule.matches(this, current)) {\n                return false;\n            }\n            possibleMatch.add(current);\n            current = current.getNext();\n        }\n        if (current != null) {\n            return false;\n        }\n        captured.add(possibleMatch);\n        return true;\n    }\n\n    public boolean find() { // This is a good example of why you shouldn't let me algorithmic programming\n        var rules = pattern.getRules();\n        if (rules.size() == 0) {\n            return false;\n        }\n        var initialSize = captured.size();\n        ArrayList<AbstractInsnNode> possibleMatch = new ArrayList<>();\n        var current = start;\n        int currentRuleIndex = 0;\n\n        while (current != null) {\n            if (rules.get(currentRuleIndex).matches(this, current)) {\n                possibleMatch.add(current);\n                if (++currentRuleIndex == rules.size()) {\n                    captured.add(possibleMatch);\n                    currentRuleIndex = 0;\n                    possibleMatch = new ArrayList<>();\n                }\n            } else {\n                currentRuleIndex = 0;\n                possibleMatch.clear();\n            }\n            current = current.getNext();\n        }\n\n        return captured.size() - initialSize != 0;\n    }\n\n    public List<AbstractInsnNode> getCaptured(int which) {\n        return captured.get(which);\n    }\n\n    public List<List<AbstractInsnNode>> getAllCaptured() {\n        return captured;\n    }\n}\n"
  },
  {
    "path": "xyz.itzsomebody.commons/src/main/java/xyz/itzsomebody/commons/matcher/InstructionPattern.java",
    "content": "/*\n * Radon - An open-source Java obfuscator\n * Copyright (C) 2021 ItzSomebody\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, either version 3 of the License, or\n * (at your option) any later version.\n *\n * This program is distributed in the hope that it will be 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.  If not, see <http://www.gnu.org/licenses/>\n */\n\npackage xyz.itzsomebody.commons.matcher;\n\nimport org.jetbrains.annotations.NotNull;\nimport org.objectweb.asm.tree.AbstractInsnNode;\nimport xyz.itzsomebody.commons.matcher.rules.InstructionRule;\n\nimport java.util.List;\n\npublic class InstructionPattern {\n    private final List<InstructionRule> rules;\n\n    public InstructionPattern(@NotNull InstructionRule... rules) {\n        this.rules = List.of(rules);\n    }\n\n    public List<InstructionRule> getRules() {\n        return rules;\n    }\n\n    public InstructionMatcher matcher(AbstractInsnNode start) {\n        return new InstructionMatcher(this, start);\n    }\n}\n"
  },
  {
    "path": "xyz.itzsomebody.commons/src/main/java/xyz/itzsomebody/commons/matcher/rules/AccessFieldRule.java",
    "content": "/*\n * Radon - An open-source Java obfuscator\n * Copyright (C) 2021 ItzSomebody\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, either version 3 of the License, or\n * (at your option) any later version.\n *\n * This program is distributed in the hope that it will be 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.  If not, see <http://www.gnu.org/licenses/>\n */\n\npackage xyz.itzsomebody.commons.matcher.rules;\n\nimport org.objectweb.asm.Opcodes;\nimport org.objectweb.asm.tree.AbstractInsnNode;\nimport org.objectweb.asm.tree.FieldInsnNode;\nimport xyz.itzsomebody.commons.matcher.InstructionMatcher;\n\nimport java.util.function.Function;\n\npublic class AccessFieldRule extends OpcodeRule {\n    private final int opcode;\n    private final String owner;\n    private final String name;\n    private final String description;\n\n    public AccessFieldRule(Function<AbstractInsnNode, Boolean> rule, int opcode, String owner, String name, String description) {\n        super(rule, Opcodes.GETFIELD, Opcodes.GETSTATIC, Opcodes.PUTFIELD, Opcodes.PUTSTATIC);\n        this.opcode = opcode;\n        this.owner = owner;\n        this.name = name;\n        this.description = description;\n    }\n\n    public AccessFieldRule(int opcode, String owner, String name, String description) {\n        super(null, Opcodes.GETFIELD, Opcodes.GETSTATIC, Opcodes.PUTFIELD, Opcodes.PUTSTATIC);\n        this.opcode = opcode;\n        this.owner = owner;\n        this.name = name;\n        this.description = description;\n    }\n\n    @Override\n    public boolean matches(InstructionMatcher matcher, AbstractInsnNode current) {\n        if (current.getOpcode() == opcode && current instanceof FieldInsnNode) {\n            var casted = (FieldInsnNode) current;\n            return (owner == null || owner.equals(casted.owner))\n                    && (name == null || name.equals(casted.name))\n                    && (description == null || description.equals(casted.desc));\n        }\n        return false;\n    }\n}\n"
  },
  {
    "path": "xyz.itzsomebody.commons/src/main/java/xyz/itzsomebody/commons/matcher/rules/DoubleConstRule.java",
    "content": "/*\n * Radon - An open-source Java obfuscator\n * Copyright (C) 2021 ItzSomebody\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, either version 3 of the License, or\n * (at your option) any later version.\n *\n * This program is distributed in the hope that it will be 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.  If not, see <http://www.gnu.org/licenses/>\n */\n\npackage xyz.itzsomebody.commons.matcher.rules;\n\nimport org.objectweb.asm.Opcodes;\nimport org.objectweb.asm.tree.LdcInsnNode;\n\npublic class DoubleConstRule extends OpcodeRule {\n    public DoubleConstRule() {\n        super(current -> {\n                    if (current instanceof LdcInsnNode && !(((LdcInsnNode) current).cst instanceof Double)) {\n                        return false;\n                    }\n                    return true;\n                }, Opcodes.DCONST_0,\n                Opcodes.DCONST_1,\n                Opcodes.LDC\n        );\n    }\n}\n"
  },
  {
    "path": "xyz.itzsomebody.commons/src/main/java/xyz/itzsomebody/commons/matcher/rules/FloatConstRule.java",
    "content": "/*\n * Radon - An open-source Java obfuscator\n * Copyright (C) 2021 ItzSomebody\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, either version 3 of the License, or\n * (at your option) any later version.\n *\n * This program is distributed in the hope that it will be 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.  If not, see <http://www.gnu.org/licenses/>\n */\n\npackage xyz.itzsomebody.commons.matcher.rules;\n\nimport org.objectweb.asm.Opcodes;\nimport org.objectweb.asm.tree.LdcInsnNode;\n\npublic class FloatConstRule extends OpcodeRule {\n    public FloatConstRule() {\n        super(current -> {\n                    if (current instanceof LdcInsnNode && !(((LdcInsnNode) current).cst instanceof Float)) {\n                        return false;\n                    }\n                    return true;\n                }, Opcodes.FCONST_0,\n                Opcodes.FCONST_1,\n                Opcodes.FCONST_2,\n                Opcodes.LDC\n        );\n    }\n}\n"
  },
  {
    "path": "xyz.itzsomebody.commons/src/main/java/xyz/itzsomebody/commons/matcher/rules/InstructionRule.java",
    "content": "/*\n * Radon - An open-source Java obfuscator\n * Copyright (C) 2021 ItzSomebody\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, either version 3 of the License, or\n * (at your option) any later version.\n *\n * This program is distributed in the hope that it will be 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.  If not, see <http://www.gnu.org/licenses/>\n */\n\npackage xyz.itzsomebody.commons.matcher.rules;\n\nimport org.objectweb.asm.tree.AbstractInsnNode;\nimport xyz.itzsomebody.commons.matcher.InstructionMatcher;\n\npublic interface InstructionRule {\n    boolean matches(InstructionMatcher matcher, AbstractInsnNode current);\n}\n"
  },
  {
    "path": "xyz.itzsomebody.commons/src/main/java/xyz/itzsomebody/commons/matcher/rules/IntConstRule.java",
    "content": "/*\n * Radon - An open-source Java obfuscator\n * Copyright (C) 2021 ItzSomebody\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, either version 3 of the License, or\n * (at your option) any later version.\n *\n * This program is distributed in the hope that it will be 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.  If not, see <http://www.gnu.org/licenses/>\n */\n\npackage xyz.itzsomebody.commons.matcher.rules;\n\nimport org.objectweb.asm.Opcodes;\nimport org.objectweb.asm.tree.LdcInsnNode;\n\npublic class IntConstRule extends OpcodeRule {\n    public IntConstRule() {\n        super(current -> {\n                    if (current instanceof LdcInsnNode && !(((LdcInsnNode) current).cst instanceof Integer)) {\n                        return false;\n                    }\n                    return true;\n                }, Opcodes.ICONST_M1,\n                Opcodes.ICONST_0,\n                Opcodes.ICONST_1,\n                Opcodes.ICONST_2,\n                Opcodes.ICONST_3,\n                Opcodes.ICONST_4,\n                Opcodes.ICONST_5,\n                Opcodes.BIPUSH,\n                Opcodes.SIPUSH,\n                Opcodes.LDC\n        );\n    }\n}\n"
  },
  {
    "path": "xyz.itzsomebody.commons/src/main/java/xyz/itzsomebody/commons/matcher/rules/InvocationRule.java",
    "content": "/*\n * Radon - An open-source Java obfuscator\n * Copyright (C) 2021 ItzSomebody\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, either version 3 of the License, or\n * (at your option) any later version.\n *\n * This program is distributed in the hope that it will be 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.  If not, see <http://www.gnu.org/licenses/>\n */\n\npackage xyz.itzsomebody.commons.matcher.rules;\n\nimport org.objectweb.asm.Opcodes;\nimport org.objectweb.asm.tree.AbstractInsnNode;\nimport org.objectweb.asm.tree.MethodInsnNode;\nimport xyz.itzsomebody.commons.matcher.InstructionMatcher;\n\nimport java.util.function.Function;\n\npublic class InvocationRule extends OpcodeRule {\n    private final int opcode;\n    private final String owner;\n    private final String name;\n    private final String description;\n\n    public InvocationRule(Function<AbstractInsnNode, Boolean> rule, int opcode, String owner, String name, String description) {\n        super(rule, Opcodes.INVOKEVIRTUAL, Opcodes.INVOKESPECIAL, Opcodes.INVOKESTATIC, Opcodes.INVOKEINTERFACE);\n        this.opcode = opcode;\n        this.owner = owner;\n        this.name = name;\n        this.description = description;\n    }\n\n    public InvocationRule(int opcode, String owner, String name, String description) {\n        super(null, Opcodes.INVOKEVIRTUAL, Opcodes.INVOKESPECIAL, Opcodes.INVOKESTATIC, Opcodes.INVOKEINTERFACE);\n        this.opcode = opcode;\n        this.owner = owner;\n        this.name = name;\n        this.description = description;\n    }\n\n    @Override\n    public boolean matches(InstructionMatcher matcher, AbstractInsnNode current) {\n        if (current.getOpcode() == opcode && current instanceof MethodInsnNode) {\n            var casted = (MethodInsnNode) current;\n            return (owner == null || owner.equals(casted.owner))\n                    && (name == null || name.equals(casted.name))\n                    && (description == null || description.equals(casted.desc));\n        }\n        return false;\n    }\n}\n"
  },
  {
    "path": "xyz.itzsomebody.commons/src/main/java/xyz/itzsomebody/commons/matcher/rules/LongConstRule.java",
    "content": "/*\n * Radon - An open-source Java obfuscator\n * Copyright (C) 2021 ItzSomebody\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, either version 3 of the License, or\n * (at your option) any later version.\n *\n * This program is distributed in the hope that it will be 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.  If not, see <http://www.gnu.org/licenses/>\n */\n\npackage xyz.itzsomebody.commons.matcher.rules;\n\nimport org.objectweb.asm.Opcodes;\nimport org.objectweb.asm.tree.LdcInsnNode;\n\npublic class LongConstRule extends OpcodeRule {\n    public LongConstRule() {\n        super(current -> {\n                    if (current instanceof LdcInsnNode && !(((LdcInsnNode) current).cst instanceof Long)) {\n                        return false;\n                    }\n                    return true;\n                }, Opcodes.LCONST_0,\n                Opcodes.LCONST_1,\n                Opcodes.LDC\n        );\n    }\n}\n"
  },
  {
    "path": "xyz.itzsomebody.commons/src/main/java/xyz/itzsomebody/commons/matcher/rules/OpcodeRule.java",
    "content": "/*\n * Radon - An open-source Java obfuscator\n * Copyright (C) 2021 ItzSomebody\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, either version 3 of the License, or\n * (at your option) any later version.\n *\n * This program is distributed in the hope that it will be 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.  If not, see <http://www.gnu.org/licenses/>\n */\n\npackage xyz.itzsomebody.commons.matcher.rules;\n\nimport org.objectweb.asm.tree.AbstractInsnNode;\nimport xyz.itzsomebody.commons.matcher.InstructionMatcher;\n\nimport java.util.Arrays;\nimport java.util.List;\nimport java.util.function.Function;\nimport java.util.stream.Collectors;\n\npublic class OpcodeRule implements InstructionRule {\n    private final Function<AbstractInsnNode, Boolean> rule;\n    private final List<Integer> wantedOpcodes;\n\n    public OpcodeRule(Function<AbstractInsnNode, Boolean> rule, int... opcodes) {\n        this.rule = rule;\n        this.wantedOpcodes = Arrays.stream(opcodes).boxed().collect(Collectors.toList());\n    }\n\n    public OpcodeRule(int... opcodes) {\n        this.rule = null;\n        this.wantedOpcodes = Arrays.stream(opcodes).boxed().collect(Collectors.toList());\n    }\n\n    @Override\n    public boolean matches(InstructionMatcher matcher, AbstractInsnNode current) {\n        return wantedOpcodes.contains(current.getOpcode()) && (rule == null || rule.apply(current));\n    }\n}\n"
  },
  {
    "path": "xyz.itzsomebody.commons/src/main/java/xyz/itzsomebody/commons/matcher/rules/WildcardRule.java",
    "content": "/*\n * Radon - An open-source Java obfuscator\n * Copyright (C) 2021 ItzSomebody\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, either version 3 of the License, or\n * (at your option) any later version.\n *\n * This program is distributed in the hope that it will be 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.  If not, see <http://www.gnu.org/licenses/>\n */\n\npackage xyz.itzsomebody.commons.matcher.rules;\n\nimport org.objectweb.asm.tree.AbstractInsnNode;\nimport xyz.itzsomebody.commons.matcher.InstructionMatcher;\n\npublic class WildcardRule extends OpcodeRule {\n    public WildcardRule(){\n        super(null);\n    }\n\n    @Override\n    public boolean matches(InstructionMatcher matcher, AbstractInsnNode current) {\n        return true;\n    }\n}\n"
  },
  {
    "path": "xyz.itzsomebody.commons/src/test/java/xyz/itzsomebody/commons/InsnListModifierTester.java",
    "content": "/*\n * Radon - An open-source Java obfuscator\n * Copyright (C) 2021 ItzSomebody\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, either version 3 of the License, or\n * (at your option) any later version.\n *\n * This program is distributed in the hope that it will be 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.  If not, see <http://www.gnu.org/licenses/>\n */\n\npackage xyz.itzsomebody.commons;\n\nimport org.junit.Assert;\nimport org.junit.Test;\nimport org.objectweb.asm.Opcodes;\nimport org.objectweb.asm.tree.InsnList;\nimport org.objectweb.asm.tree.InsnNode;\n\nimport java.util.stream.IntStream;\n\npublic class InsnListModifierTester {\n    @Test\n    public void testAppending() {\n        var insns = new InsnList();\n        var addMe = new InsnList();\n        addMe.add(new InsnNode(Opcodes.ACONST_NULL));\n        addMe.add(new InsnNode(Opcodes.ARETURN));\n        var modifier = new InsnListModifier();\n        modifier.append(addMe);\n        modifier.apply(insns);\n        IntStream.range(0, addMe.size()).forEach(i -> Assert.assertEquals(addMe.get(i), insns.get(i)));\n    }\n\n    @Test\n    public void testPrepending() {\n        var insns = new InsnList();\n        insns.add(new InsnNode(Opcodes.ICONST_1));\n        insns.add(new InsnNode(Opcodes.POP));\n        var addMe = new InsnList();\n        addMe.add(new InsnNode(Opcodes.ACONST_NULL));\n        addMe.add(new InsnNode(Opcodes.ARETURN));\n        var modifier = new InsnListModifier();\n        modifier.prepend(addMe);\n        modifier.apply(insns);\n        IntStream.range(0, addMe.size()).forEach(i -> Assert.assertEquals(addMe.get(i), insns.get(i)));\n    }\n\n    @Test\n    public void testInsertion() {\n        var insns = new InsnList();\n        insns.add(new InsnNode(Opcodes.ICONST_1));\n        insns.add(new InsnNode(Opcodes.POP));\n        var addMe = new InsnList();\n        addMe.add(new InsnNode(Opcodes.ACONST_NULL));\n        addMe.add(new InsnNode(Opcodes.ARETURN));\n        var modifier = new InsnListModifier();\n        modifier.insert(insns.getLast(), addMe);\n        modifier.apply(insns);\n        insns.remove(insns.getFirst());\n        insns.remove(insns.getFirst());\n        IntStream.range(0, addMe.size()).forEach(i -> Assert.assertEquals(addMe.get(i), insns.get(i)));\n    }\n\n    @Test\n    public void testInsertionBefore() {\n        var insns = new InsnList();\n        insns.add(new InsnNode(Opcodes.ACONST_NULL));\n        insns.add(new InsnNode(Opcodes.ARETURN));\n        var addMe = new InsnList();\n        addMe.add(new InsnNode(Opcodes.ICONST_1));\n        addMe.add(new InsnNode(Opcodes.POP));\n\n        var modifier = new InsnListModifier();\n        modifier.insertBefore(insns.getFirst(), addMe);\n        modifier.apply(insns);\n        insns.remove(insns.getLast());\n        insns.remove(insns.getLast());\n        IntStream.range(0, addMe.size()).forEach(i -> Assert.assertEquals(addMe.get(i), insns.get(i)));\n    }\n}\n"
  },
  {
    "path": "xyz.itzsomebody.commons/src/test/java/xyz/itzsomebody/commons/MaxLocalsUpdaterTester.java",
    "content": "/*\n * Radon - An open-source Java obfuscator\n * Copyright (C) 2021 ItzSomebody\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, either version 3 of the License, or\n * (at your option) any later version.\n *\n * This program is distributed in the hope that it will be 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.  If not, see <http://www.gnu.org/licenses/>\n */\n\npackage xyz.itzsomebody.commons;\n\nimport org.junit.Assert;\nimport org.junit.Test;\nimport org.objectweb.asm.Opcodes;\nimport org.objectweb.asm.tree.InsnNode;\nimport org.objectweb.asm.tree.MethodNode;\nimport org.objectweb.asm.tree.VarInsnNode;\n\npublic class MaxLocalsUpdaterTester {\n    @Test\n    public void testParameterSizeEvaluation() {\n        var node = new MethodNode();\n        node.desc = \"(IIIJD)V\";\n        node.access = Opcodes.ACC_STATIC;\n\n        MaxLocalsUpdater.update(node);\n        Assert.assertEquals(1 + 1 + 1 + 2 + 2, node.maxLocals);\n    }\n\n    @Test\n    public void testEvaluationByBytecodeStatic1() {\n        var node = new MethodNode();\n        node.desc = \"(IIIJD)V\";\n        node.access = Opcodes.ACC_STATIC;\n        node.instructions.add(new InsnNode(Opcodes.ICONST_0));\n        node.instructions.add(new VarInsnNode(Opcodes.ISTORE, 69));\n\n        MaxLocalsUpdater.update(node);\n        Assert.assertEquals(69 + 1, node.maxLocals);\n    }\n\n    @Test\n    public void testEvaluationByBytecodeStatic2() {\n        var node = new MethodNode();\n        node.desc = \"(IIIJD)V\";\n        node.access = Opcodes.ACC_STATIC;\n        node.instructions.add(new InsnNode(Opcodes.LCONST_0));\n        node.instructions.add(new VarInsnNode(Opcodes.LSTORE, 69));\n\n        MaxLocalsUpdater.update(node);\n        Assert.assertEquals(69 + 2, node.maxLocals);\n    }\n\n    @Test\n    public void testEvaluationByBytecodeVirtual1() {\n        var node = new MethodNode();\n        node.desc = \"(IIIJD)V\";\n\n        MaxLocalsUpdater.update(node);\n        Assert.assertEquals(1 + 1 + 1 + 1 + 2 + 2, node.maxLocals);\n    }\n\n    @Test\n    public void testEvaluationByBytecodeVirtual2() {\n        var node = new MethodNode();\n        node.desc = \"(IIIJD)V\";\n        node.instructions.add(new InsnNode(Opcodes.FCONST_0));\n        node.instructions.add(new VarInsnNode(Opcodes.FSTORE, 69));\n\n        MaxLocalsUpdater.update(node);\n        Assert.assertEquals(69 + 1, node.maxLocals);\n    }\n}\n"
  },
  {
    "path": "xyz.itzsomebody.commons/src/test/java/xyz/itzsomebody/commons/TestingUtils.java",
    "content": "/*\n * Radon - An open-source Java obfuscator\n * Copyright (C) 2021 ItzSomebody\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, either version 3 of the License, or\n * (at your option) any later version.\n *\n * This program is distributed in the hope that it will be 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.  If not, see <http://www.gnu.org/licenses/>\n */\n\npackage xyz.itzsomebody.commons;\n\nimport org.objectweb.asm.Opcodes;\nimport org.objectweb.asm.tree.AbstractInsnNode;\nimport org.objectweb.asm.tree.InsnNode;\nimport org.objectweb.asm.tree.IntInsnNode;\nimport org.objectweb.asm.tree.LdcInsnNode;\n\npublic class TestingUtils {\n    public static AbstractInsnNode loadInt(int i) {\n        if (i >= -1 && i <= 5) {\n            return new InsnNode(i + 3);\n        } else if (i >= Byte.MIN_VALUE && i <= Byte.MAX_VALUE) {\n            return new IntInsnNode(Opcodes.BIPUSH, i);\n        } else if (i >= Short.MIN_VALUE && i <= Short.MAX_VALUE) {\n            return new IntInsnNode(Opcodes.SIPUSH, i);\n        } else {\n            return new LdcInsnNode(i);\n        }\n    }\n\n    public static AbstractInsnNode loadLong(long j) {\n        if (j == 0L || j == 1L) {\n            return new InsnNode((int) j + 9);\n        } else {\n            return new LdcInsnNode(j);\n        }\n    }\n\n    public static AbstractInsnNode loadFloat(float f) {\n        if (f == 0F || f == 1F || f == 2F) {\n            return new InsnNode((int) f + 11);\n        } else {\n            return new LdcInsnNode(f);\n        }\n    }\n\n    public static AbstractInsnNode loadDouble(double d) {\n        if (d == 0D || d == 1D) {\n            return new InsnNode((int) d + 14);\n        } else {\n            return new LdcInsnNode(d);\n        }\n    }\n}\n"
  },
  {
    "path": "xyz.itzsomebody.commons/src/test/java/xyz/itzsomebody/commons/matcher/InstructionMatcherTester.java",
    "content": "/*\n * Radon - An open-source Java obfuscator\n * Copyright (C) 2021 ItzSomebody\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, either version 3 of the License, or\n * (at your option) any later version.\n *\n * This program is distributed in the hope that it will be 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.  If not, see <http://www.gnu.org/licenses/>\n */\n\npackage xyz.itzsomebody.commons.matcher;\n\nimport org.junit.Assert;\nimport org.junit.Test;\nimport org.objectweb.asm.Opcodes;\nimport org.objectweb.asm.Type;\nimport org.objectweb.asm.tree.InsnList;\nimport org.objectweb.asm.tree.InsnNode;\nimport org.objectweb.asm.tree.LdcInsnNode;\nimport org.objectweb.asm.tree.MethodInsnNode;\nimport xyz.itzsomebody.commons.matcher.rules.InvocationRule;\nimport xyz.itzsomebody.commons.matcher.rules.OpcodeRule;\n\nimport java.nio.charset.Charset;\n\npublic class InstructionMatcherTester {\n    @Test\n    public void testMatchMethodInvocationAndArgs() {\n        var insns = new InsnList();\n        insns.add(new LdcInsnNode(\"tucks\"));\n        insns.add(new LdcInsnNode(\"tux\"));\n        insns.add(new InsnNode(Opcodes.ACONST_NULL));\n        insns.add(new MethodInsnNode(Opcodes.INVOKEVIRTUAL, \"java/lang/String\", \"getBytes\", Type.getInternalName(Charset.class), false));\n\n        var pattern = new InstructionPattern(\n                new OpcodeRule((node) -> node instanceof LdcInsnNode && ((LdcInsnNode) node).cst.equals(\"tux\"), Opcodes.LDC),\n                new OpcodeRule(Opcodes.ACONST_NULL),\n                new InvocationRule(Opcodes.INVOKEVIRTUAL, \"java/lang/String\", \"getBytes\", Type.getInternalName(Charset.class))\n        );\n        var matcher = pattern.matcher(insns.getFirst());\n        Assert.assertFalse(matcher.matches());\n        Assert.assertTrue(matcher.find());\n\n        var captured = matcher.getCaptured(0);\n        insns.remove(insns.getFirst());\n        for (var i = 0; i < insns.size(); i++) {\n            Assert.assertEquals(insns.get(i), captured.get(i));\n        }\n    }\n}\n"
  },
  {
    "path": "xyz.itzsomebody.commons/src/test/java/xyz/itzsomebody/commons/matcher/rules/AccessFieldRuleTester.java",
    "content": "/*\n * Radon - An open-source Java obfuscator\n * Copyright (C) 2021 ItzSomebody\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, either version 3 of the License, or\n * (at your option) any later version.\n *\n * This program is distributed in the hope that it will be 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.  If not, see <http://www.gnu.org/licenses/>\n */\n\npackage xyz.itzsomebody.commons.matcher.rules;\n\nimport org.junit.Assert;\nimport org.junit.Test;\nimport org.objectweb.asm.Opcodes;\nimport org.objectweb.asm.tree.FieldInsnNode;\nimport xyz.itzsomebody.commons.matcher.InstructionPattern;\n\npublic class AccessFieldRuleTester {\n    @Test\n    public void testMatch() {\n        var pattern = new InstructionPattern(new AccessFieldRule(Opcodes.GETSTATIC, null, null, \"I\"));\n        var matcher = pattern.matcher(new FieldInsnNode(Opcodes.GETSTATIC, \"tucks/Tux\", \"tucks\", \"I\"));\n        Assert.assertTrue(matcher.matches());\n        Assert.assertTrue(matcher.find());\n    }\n}\n"
  },
  {
    "path": "xyz.itzsomebody.commons/src/test/java/xyz/itzsomebody/commons/matcher/rules/DoubleConstRuleTester.java",
    "content": "/*\n * Radon - An open-source Java obfuscator\n * Copyright (C) 2021 ItzSomebody\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, either version 3 of the License, or\n * (at your option) any later version.\n *\n * This program is distributed in the hope that it will be 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.  If not, see <http://www.gnu.org/licenses/>\n */\n\npackage xyz.itzsomebody.commons.matcher.rules;\n\nimport org.junit.Assert;\nimport org.junit.Test;\nimport xyz.itzsomebody.commons.TestingUtils;\nimport xyz.itzsomebody.commons.matcher.InstructionPattern;\n\nimport java.util.concurrent.ThreadLocalRandom;\n\npublic class DoubleConstRuleTester {\n    @Test\n    public void testMatch() {\n        var examples = new double[]{\n                0D,\n                1D,\n                ThreadLocalRandom.current().nextDouble()\n        };\n\n        for (var example : examples) {\n            var pattern = new InstructionPattern(new DoubleConstRule());\n            var matcher = pattern.matcher(TestingUtils.loadDouble(example));\n            Assert.assertTrue(matcher.matches());\n            Assert.assertTrue(matcher.find());\n        }\n    }\n}\n"
  },
  {
    "path": "xyz.itzsomebody.commons/src/test/java/xyz/itzsomebody/commons/matcher/rules/FloatConstRuleTester.java",
    "content": "/*\n * Radon - An open-source Java obfuscator\n * Copyright (C) 2021 ItzSomebody\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, either version 3 of the License, or\n * (at your option) any later version.\n *\n * This program is distributed in the hope that it will be 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.  If not, see <http://www.gnu.org/licenses/>\n */\n\npackage xyz.itzsomebody.commons.matcher.rules;\n\nimport org.junit.Assert;\nimport org.junit.Test;\nimport xyz.itzsomebody.commons.TestingUtils;\nimport xyz.itzsomebody.commons.matcher.InstructionPattern;\n\nimport java.util.concurrent.ThreadLocalRandom;\n\npublic class FloatConstRuleTester {\n    @Test\n    public void testMatch() {\n        var examples = new float[]{\n                0F,\n                1F,\n                2F,\n                ThreadLocalRandom.current().nextFloat()\n        };\n\n        for (var example : examples) {\n            var pattern = new InstructionPattern(new FloatConstRule());\n            var matcher = pattern.matcher(TestingUtils.loadFloat(example));\n            Assert.assertTrue(matcher.matches());\n            Assert.assertTrue(matcher.find());\n        }\n    }\n}\n"
  },
  {
    "path": "xyz.itzsomebody.commons/src/test/java/xyz/itzsomebody/commons/matcher/rules/IntConstRuleTester.java",
    "content": "/*\n * Radon - An open-source Java obfuscator\n * Copyright (C) 2021 ItzSomebody\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, either version 3 of the License, or\n * (at your option) any later version.\n *\n * This program is distributed in the hope that it will be 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.  If not, see <http://www.gnu.org/licenses/>\n */\n\npackage xyz.itzsomebody.commons.matcher.rules;\n\nimport org.junit.Assert;\nimport org.junit.Test;\nimport xyz.itzsomebody.commons.TestingUtils;\nimport xyz.itzsomebody.commons.matcher.InstructionPattern;\n\nimport java.util.concurrent.ThreadLocalRandom;\n\npublic class IntConstRuleTester {\n    @Test\n    public void testMatch() {\n        var examples = new int[]{\n                -1,\n                0,\n                1,\n                2,\n                3,\n                4,\n                5,\n                ThreadLocalRandom.current().nextInt(5, Byte.MAX_VALUE),\n                ThreadLocalRandom.current().nextInt(Byte.MAX_VALUE + 1, Short.MAX_VALUE),\n                ThreadLocalRandom.current().nextInt(Short.MAX_VALUE + 1, Integer.MAX_VALUE)\n        };\n\n        for (var example : examples) {\n            var pattern = new InstructionPattern(new IntConstRule());\n            var matcher = pattern.matcher(TestingUtils.loadInt(example));\n            Assert.assertTrue(matcher.matches());\n            Assert.assertTrue(matcher.find());\n        }\n    }\n}\n"
  },
  {
    "path": "xyz.itzsomebody.commons/src/test/java/xyz/itzsomebody/commons/matcher/rules/InvocationRuleTester.java",
    "content": "/*\n * Radon - An open-source Java obfuscator\n * Copyright (C) 2021 ItzSomebody\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, either version 3 of the License, or\n * (at your option) any later version.\n *\n * This program is distributed in the hope that it will be 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.  If not, see <http://www.gnu.org/licenses/>\n */\n\npackage xyz.itzsomebody.commons.matcher.rules;\n\nimport org.junit.Assert;\nimport org.junit.Test;\nimport org.objectweb.asm.Opcodes;\nimport org.objectweb.asm.tree.MethodInsnNode;\nimport xyz.itzsomebody.commons.matcher.InstructionPattern;\n\npublic class InvocationRuleTester {\n    @Test\n    public void testMatch() {\n        var pattern = new InstructionPattern(new InvocationRule(Opcodes.INVOKESTATIC, null, null, \"()I\"));\n        var matcher = pattern.matcher(new MethodInsnNode(Opcodes.INVOKESTATIC, \"tucks/Tux\", \"tucks\", \"()I\"));\n        Assert.assertTrue(matcher.matches());\n        Assert.assertTrue(matcher.find());\n    }\n}\n"
  },
  {
    "path": "xyz.itzsomebody.commons/src/test/java/xyz/itzsomebody/commons/matcher/rules/LongConstRuleTester.java",
    "content": "/*\n * Radon - An open-source Java obfuscator\n * Copyright (C) 2021 ItzSomebody\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, either version 3 of the License, or\n * (at your option) any later version.\n *\n * This program is distributed in the hope that it will be 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.  If not, see <http://www.gnu.org/licenses/>\n */\n\npackage xyz.itzsomebody.commons.matcher.rules;\n\nimport org.junit.Assert;\nimport org.junit.Test;\nimport xyz.itzsomebody.commons.TestingUtils;\nimport xyz.itzsomebody.commons.matcher.InstructionPattern;\n\nimport java.util.concurrent.ThreadLocalRandom;\n\npublic class LongConstRuleTester {\n    @Test\n    public void testMatch() {\n        var examples = new long[]{\n                0L,\n                1L,\n                ThreadLocalRandom.current().nextLong()\n        };\n\n        for (var example : examples) {\n            var pattern = new InstructionPattern(new LongConstRule());\n            var matcher = pattern.matcher(TestingUtils.loadLong(example));\n            Assert.assertTrue(matcher.matches());\n            Assert.assertTrue(matcher.find());\n        }\n    }\n}\n"
  },
  {
    "path": "xyz.itzsomebody.radon/build.gradle",
    "content": "/*\n * Radon - An open-source Java obfuscator\n * Copyright (C) 2021 ItzSomebody\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, either version 3 of the License, or\n * (at your option) any later version.\n *\n * This program is distributed in the hope that it will be 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.  If not, see <http://www.gnu.org/licenses/>\n */\n\nimport org.apache.tools.ant.filters.ReplaceTokens\n\nplugins {\n    id 'com.github.johnrengelman.shadow'\n    id 'java'\n}\n\n// So people stop asking why 'gradle build' doesn't work. Lmao I'm lazy\nbuild.dependsOn 'shadowJar'\nsourceCompatibility = javaVer\n\n// Main class\ndef mainClass = 'xyz.itzsomebody.radon.RadonMain'\n\n// Function to grab the git commit hash of HEAD\ndef getCommitHash = { ->\n    def stdout = new ByteArrayOutputStream()\n    exec {\n        commandLine 'git', 'rev-parse', 'HEAD'\n        standardOutput = stdout\n    }\n    return stdout.toString().trim()\n}\n\n// Search for and replace project version and commit hash placeholders in the source code\ntask processSource(type: Sync) {\n    from sourceSets.main.java\n    filter(ReplaceTokens, tokens: [VERSION: version, COMMITHASH: getCommitHash()])\n    into \"$buildDir/src\"\n}\n\ncompileJava {\n    source = processSource.outputs\n}\n\n// Creates a fat jar\nshadowJar() {\n    archiveClassifier.set(null)\n\n    // Relocate lib classes\n    relocate 'org.objectweb.asm', 'xyz.itzsomebody.radon.lib.org.objectweb.asm'\n    relocate 'com.fasterxml.jackson', 'xyz.itzsomebody.radon.lib.com.fasterxml.jackson'\n    exclude 'module-info.class'\n\n    manifest { attributes 'Main-Class': mainClass }\n}\n\ndependencies {\n    implementation project(':xyz.itzsomebody.codegen')\n    implementation project(':xyz.itzsomebody.commons')\n    implementation annotations\n    implementation jackson\n    implementation asm\n    implementation asmAnalysis\n    implementation asmCommons\n    implementation asmTree\n    implementation asmUtil\n    testImplementation junit\n}\n"
  },
  {
    "path": "xyz.itzsomebody.radon/src/main/java/xyz/itzsomebody/radon/Radon.java",
    "content": "/*\n * Radon - An open-source Java obfuscator\n * Copyright (C) 2020 ItzSomebody\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, either version 3 of the License, or\n * (at your option) any later version.\n *\n * This program is distributed in the hope that it will be 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.  If not, see <http://www.gnu.org/licenses/>\n */\n\npackage xyz.itzsomebody.radon;\n\nimport xyz.itzsomebody.radon.config.ObfConfig;\nimport xyz.itzsomebody.radon.exceptions.MissingClassException;\nimport xyz.itzsomebody.radon.exceptions.MissingResourceException;\nimport xyz.itzsomebody.radon.exclusions.ExclusionManager;\nimport xyz.itzsomebody.radon.utils.JarLoader;\nimport xyz.itzsomebody.radon.utils.JarWriter;\nimport xyz.itzsomebody.radon.utils.asm.ClassWrapper;\nimport xyz.itzsomebody.radon.utils.logging.RadonLogger;\n\nimport java.util.HashSet;\nimport java.util.Map;\nimport java.util.Objects;\nimport java.util.Set;\n\npublic class Radon {\n    private static Radon radon;\n\n    private final ExclusionManager exclusionManager;\n    public final ObfConfig config;\n\n    private Map<String, ClassWrapper> classes;\n    private Map<String, ClassWrapper> classpath;\n    private Map<String, byte[]> resources;\n\n    public Radon(ObfConfig config) {\n        this.config = config;\n        this.exclusionManager = config.exclusions;\n        radon = this;\n    }\n\n    public void run() {\n        // ========================== Load input & libs\n        var loader = new JarLoader();\n        loader.loadAsInput(config.input); // Load input\n        this.config.libraries.forEach(loader::loadAsLib); // Load libs\n        this.classes = loader.getClasses();\n        this.classpath = loader.getClasspath();\n        this.resources = loader.getResources();\n\n        // ========================== Transformation\n        var transformers = config.transformers;\n\n        // Run 'em all\n        // re nonNull: check fix-me in TransformerDeserializer\n        transformers.stream().filter(Objects::nonNull).forEach(transformer -> {\n            RadonLogger.info(\"[Transformers] Executing: \" + transformer.getName() + \" (\" + transformer.getConfigName() + \")\");\n            transformer.init(this);\n\n            // Quality way of measuring execution time /sarcasm\n            long before = System.currentTimeMillis();\n            transformer.transform();\n            long after = System.currentTimeMillis();\n\n            RadonLogger.info(\"[Transformers] Finished executing: \" + transformer.getName() + \" [\" + (after - before) + \"ms]\");\n        });\n\n        // ========================== Write output\n        var writer = new JarWriter();\n        writer.write(config.output);\n    }\n\n    private void buildHierarchy(ClassWrapper wrapper, ClassWrapper sub, Set<String> visited) {\n        if (visited.add(wrapper.getName())) {\n            if (wrapper.getSuperName() != null) {\n                var superParent = getClasspathWrapper(wrapper.getSuperName());\n                wrapper.getParents().add(superParent);\n                buildHierarchy(superParent, wrapper, visited);\n            }\n            if (wrapper.getInterfaceNames() != null) {\n                wrapper.getInterfaceNames().forEach(interfaceName -> {\n                    var interfaceParent = getClasspathWrapper(interfaceName);\n                    wrapper.getParents().add(interfaceParent);\n                    buildHierarchy(interfaceParent, wrapper, visited);\n                });\n            }\n        }\n        if (sub != null) {\n            wrapper.getChildren().add(sub);\n        }\n    }\n\n    public void buildHierarchyGraph() {\n        HashSet<String> visited = new HashSet<>();\n        classes.values().forEach(wrapper -> buildHierarchy(wrapper, null, visited));\n    }\n\n    public static Radon getInstance() {\n        return radon;\n    }\n\n    public ClassWrapper getClassWrapper(String name) {\n        var wrapper = classes.get(name);\n\n        if (wrapper == null) {\n            throw MissingClassException.forInputClass(name);\n        }\n\n        return wrapper;\n    }\n\n    public Map<String, ClassWrapper> getClasses() {\n        return classes;\n    }\n\n    public void setClasses(Map<String, ClassWrapper> classes) {\n        this.classes = classes;\n    }\n\n    public ClassWrapper getClasspathWrapper(String name) {\n        var wrapper = classpath.get(name);\n\n        if (wrapper == null) {\n            throw MissingClassException.forLibraryClass(name);\n        }\n\n        return wrapper;\n    }\n\n    public Map<String, ClassWrapper> getClasspath() {\n        return classpath;\n    }\n\n    public void setClasspath(Map<String, ClassWrapper> classpath) {\n        this.classpath = classpath;\n    }\n\n    public byte[] getResource(String name) {\n        var resource = resources.get(name);\n\n        if (resource == null) {\n            throw new MissingResourceException(name);\n        }\n\n        return resource;\n    }\n\n    public void setResources(Map<String, byte[]> resources) {\n        this.resources = resources;\n    }\n\n    public Map<String, byte[]> getResources() {\n        return resources;\n    }\n\n    public ExclusionManager getExclusionManager() {\n        return exclusionManager;\n    }\n}\n"
  },
  {
    "path": "xyz.itzsomebody.radon/src/main/java/xyz/itzsomebody/radon/RadonConstants.java",
    "content": "/*\n * Radon - An open-source Java obfuscator\n * Copyright (C) 2020 ItzSomebody\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, either version 3 of the License, or\n * (at your option) any later version.\n *\n * This program is distributed in the hope that it will be 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.  If not, see <http://www.gnu.org/licenses/>\n */\n\npackage xyz.itzsomebody.radon;\n\n/**\n * Various constants used throughout the obfuscator.\n *\n * @author itzsomebody\n */\npublic interface RadonConstants {\n    String VERSION = \"@VERSION@\";\n    String GIT_HASH = \"@COMMITHASH@\";\n    String LOG_TIMESTAMP_FORMAT = \"dd/MM/yyyy-hh:mm:ss\";\n    String DEFAULT_ZIP_COMMENT = \"Radon is a free and open-source Java bytecode obfuscator released under GPLv3\\nhttps://github.com/ItzSomebody/radon\";\n    boolean VERBOSE = true; // Because spamming the console is fun\n}\n"
  },
  {
    "path": "xyz.itzsomebody.radon/src/main/java/xyz/itzsomebody/radon/RadonMain.java",
    "content": "/*\n * Radon - An open-source Java obfuscator\n * Copyright (C) 2020 ItzSomebody\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, either version 3 of the License, or\n * (at your option) any later version.\n *\n * This program is distributed in the hope that it will be 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.  If not, see <http://www.gnu.org/licenses/>\n */\n\npackage xyz.itzsomebody.radon;\n\nimport xyz.itzsomebody.radon.cli.CmdArgsParser;\nimport xyz.itzsomebody.radon.config.ConfigurationParser;\nimport xyz.itzsomebody.radon.config.ObfConfig;\nimport xyz.itzsomebody.radon.exceptions.FatalRadonException;\nimport xyz.itzsomebody.radon.exceptions.PreventableRadonException;\nimport xyz.itzsomebody.radon.transformers.misc.Watermarker;\nimport xyz.itzsomebody.radon.utils.IOUtils;\nimport xyz.itzsomebody.radon.utils.logging.RadonLogger;\n\nimport java.io.File;\nimport java.io.FileInputStream;\nimport java.io.FileNotFoundException;\nimport java.io.IOException;\nimport java.nio.charset.StandardCharsets;\nimport java.util.zip.ZipFile;\n\n/**\n * Entry point for the Radon Java bytecode obfuscator.\n *\n * @author itzsomebody\n */\npublic class RadonMain {\n    /**\n     * Underlying implementation of {@link RadonMain#bootstrap(boolean)}.\n     *\n     * @param cliMode Determines if the obfuscator should initialize {@link CmdArgsParser}.\n     */\n    @SuppressWarnings(\"SameParameterValue\")\n    private static void bootstrap0(final boolean cliMode) {\n        // RadonLogger\n        try {\n            // Throws from static initializer if some random thing should go rip\n            RadonLogger.info(\"Finished setting up RadonLogger\");\n        } catch (Throwable t) {\n            System.out.println(\"Some random error happened while bootstrapping logger D:\");\n            t.printStackTrace(System.out);\n            System.exit(-1);\n        }\n\n        // CLI stuff\n        // For console-application usage\n        if (cliMode) {\n            CmdArgsParser.registerSwitch(\"help\", 0);\n            CmdArgsParser.registerSwitch(\"license\", 0); // not that anybody cares abt this one\n            CmdArgsParser.registerSwitch(\"config\", 1);\n            CmdArgsParser.registerSwitch(\"extract\", 2);\n            RadonLogger.info(\"Finished setting up command line parser\");\n        }\n    }\n\n    /**\n     * Initializes the {@link RadonLogger}. Also initializes {@link CmdArgsParser} if the obfuscator is being run\n     * from the console.\n     *\n     * @param cliMode Determines if the obfuscator should initialize {@link CmdArgsParser}.\n     */\n    public static void bootstrap(boolean cliMode) {\n        bootstrap0(cliMode);\n        RadonLogger.info(\"Finished bootstrap phase\");\n        RadonLogger.info(\"Radon: A free and open-source experimental JVM bytecode obfuscator\");\n        RadonLogger.info(String.format(\"Version: %s (commit hash: %s)\", RadonConstants.VERSION, RadonConstants.GIT_HASH));\n        RadonLogger.info(\"Repository: https://github.com/ItzSomebody/radon\");\n    }\n\n    private static int cliThing(String[] args) {\n        // Parse all the args off the command line\n        var parser = new CmdArgsParser();\n        parser.parse(args);\n\n        // Do stuff based on whatever was thrown in\n        if (parser.containsSwitch(\"help\")) {\n            var programName = new File(RadonMain.class.getProtectionDomain().getCodeSource().getLocation().getPath()).getName();\n\n            RadonLogger.info(String.format(\"Extractor: %5s java -jar %s --extract example.jar\", \"\", programName));\n            RadonLogger.info(String.format(\"CLI Usage: %5s java -jar %s --config example.yml\", \"\", programName));\n            RadonLogger.info(String.format(\"Help Menu: %5s java -jar %s --config example.yml\", \"\", programName));\n            RadonLogger.info(String.format(\"License: %5s java -jar %s --config example.yml\", \"\", programName));\n        } else if (parser.containsSwitch(\"license\")) {\n            try {\n                RadonLogger.info(new String(IOUtils.toByteArray(RadonMain.class.getResourceAsStream(\"/radon-license.txt\")), StandardCharsets.UTF_8));\n            } catch (IOException ioe) {\n                RadonLogger.severe(\"Unable to load the license file\");\n                ioe.printStackTrace(System.out);\n            }\n        } else if (parser.containsSwitch(\"config\")) {\n            var configPath = parser.getArgsFor(\"config\")[0];\n            var configFile = new File(configPath);\n            if (!configFile.exists()) {\n                RadonLogger.severe(String.format(\"Could not find specified config file \\\"%s\\\"\", configFile.getAbsolutePath()));\n            }\n            if (!configFile.canRead()) {\n                RadonLogger.severe(String.format(\"Cannot not read specified config file \\\"%s\\\"\", configFile.getAbsolutePath()));\n            }\n            if (!configFile.isFile()) {\n                RadonLogger.severe(String.format(\"Specified config file \\\"%s\\\" is not a file\", configFile.getAbsolutePath()));\n            }\n\n            ConfigurationParser config;\n            try {\n                config = new ConfigurationParser(new FileInputStream(configFile));\n            } catch (FileNotFoundException e) {\n                RadonLogger.severe(\"Unknown IO error happened: \" + e.getMessage());\n\n                if (RadonConstants.VERBOSE) {\n                    e.printStackTrace();\n                }\n                return -1;\n            }\n\n            try {\n                var radon = new Radon(config.parseConfig());\n                radon.run();\n            } catch (FatalRadonException e) {\n                RadonLogger.severe(\"A fatal exception was thrown: \" + e.getMessage());\n\n                if (RadonConstants.VERBOSE) {\n                    e.printStackTrace(System.out);\n                }\n                return -1;\n            } catch (PreventableRadonException e) {\n                RadonLogger.severe(\"A preventable exception was thrown: \" + e.getMessage());\n\n                if (RadonConstants.VERBOSE) {\n                    e.printStackTrace(System.out);\n                }\n                return 1;\n            } catch (Throwable t) {\n                RadonLogger.severe(\"An unknown error was throw: \" + t.getMessage());\n\n                if (RadonConstants.VERBOSE) {\n                    t.printStackTrace(System.out);\n                }\n                return -1;\n            }\n        } else if (parser.containsSwitch(\"extract\")) {\n            // At this point I was too lazy to write proper code -- I don't think anyone uses this anyways lmao\n            var switchArgs = parser.getArgsFor(\"extract\");\n\n            File leaked = new File(switchArgs[0]);\n            if (!leaked.exists()) {\n                RadonLogger.severe(\"Input file not found\");\n                return -1;\n            }\n\n            try {\n                var extractor = new Watermarker.Extractor(new ZipFile(leaked), switchArgs[1]);\n                RadonLogger.info(extractor.extractId());\n            } catch (FatalRadonException e) {\n                RadonLogger.severe(\"A fatal exception was thrown: \" + e.getMessage());\n\n                if (RadonConstants.VERBOSE) {\n                    e.printStackTrace(System.out);\n                }\n                return -1;\n            } catch (PreventableRadonException e) {\n                RadonLogger.severe(\"A preventable exception was thrown: \" + e.getMessage());\n\n                if (RadonConstants.VERBOSE) {\n                    e.printStackTrace(System.out);\n                }\n                return 1;\n            } catch (Throwable t) {\n                RadonLogger.severe(\"An unknown error was throw: \" + t.getMessage());\n\n                if (RadonConstants.VERBOSE) {\n                    t.printStackTrace(System.out);\n                }\n                return -1;\n            }\n        } else {\n            RadonLogger.info(\"Unknown operation: perhaps try viewing the results of --help?\");\n        }\n\n        // Thank the Lord\n        RadonLogger.info(\"Exiting gracefully\");\n        return 0;\n    }\n\n    /**\n     * Entry point to the obfuscator.\n     */\n    public static void main(String[] args) {\n        // Bootstrap to init stuffs\n        bootstrap(true);\n\n        // Run the stuff\n        System.exit(cliThing(args));\n    }\n}\n"
  },
  {
    "path": "xyz.itzsomebody.radon/src/main/java/xyz/itzsomebody/radon/cli/CmdArgsParser.java",
    "content": "/*\n * Radon - An open-source Java obfuscator\n * Copyright (C) 2020 ItzSomebody\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, either version 3 of the License, or\n * (at your option) any later version.\n *\n * This program is distributed in the hope that it will be 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.  If not, see <http://www.gnu.org/licenses/>\n */\n\npackage xyz.itzsomebody.radon.cli;\n\nimport xyz.itzsomebody.radon.exceptions.PreventableRadonException;\n\nimport java.util.HashMap;\nimport java.util.HashSet;\nimport java.util.Map;\nimport java.util.Set;\nimport java.util.stream.Stream;\n\npublic class CmdArgsParser {\n    private final static String[] SWITCH_PREFIXES = {\"--\", \"-\", \"/\"};\n    private final static Set<CmdSwitch> SWITCHES = new HashSet<>();\n    private final Map<String, String[]> argMap = new HashMap<>();\n\n    private String getSwitchIdOrThrow(String arg) {\n        return arg.substring(Stream.of(SWITCH_PREFIXES)\n                .filter(arg::startsWith)\n                .findFirst()\n                .orElseThrow(() -> new PreventableRadonException(\"Unexpected command argument: \\\"\" + arg + \"\\\"\"))\n                .length());\n    }\n\n    public void parse(String[] args) {\n        for (var cliArgIndex = 0; cliArgIndex < args.length; cliArgIndex++) {\n            final var switchId = getSwitchIdOrThrow(args[cliArgIndex]);\n\n            var knownSwitch = false;\n            for (var cmdSwitch : SWITCHES) {\n                if (cmdSwitch.id.equals(switchId)) {\n                    String[] switchArgs = new String[cmdSwitch.expectedArgs];\n\n                    for (var switchArgIndex = 0; switchArgIndex < cmdSwitch.expectedArgs; switchArgIndex++) {\n                        try {\n                            switchArgs[switchArgIndex] = args[++cliArgIndex];\n                        } catch (ArrayIndexOutOfBoundsException e) {\n                            throw new PreventableRadonException(String.format(\"Command switch \\\"%s\\\" expected %d argument(s), got %d instead.\",\n                                    switchId,\n                                    cmdSwitch.expectedArgs,\n                                    switchArgIndex\n                            ));\n                        }\n                    }\n\n                    argMap.put(switchId, switchArgs);\n                    knownSwitch = true;\n                    break;\n                }\n            }\n\n            if (!knownSwitch) {\n                throw new PreventableRadonException(\"Unknown command switch: \\\"\" + switchId + \"\\\"\");\n            }\n        }\n    }\n\n    public static void registerSwitch(String id, int expectedArgs) {\n        registerSwitch(new CmdSwitch(id, expectedArgs));\n    }\n\n    public static void registerSwitch(CmdSwitch cmdSwitch) {\n        SWITCHES.add(cmdSwitch);\n    }\n\n    public boolean containsSwitch(String id) {\n        return argMap.containsKey(id);\n    }\n\n    public String[] getArgsFor(String id) {\n        return argMap.get(id);\n    }\n}\n"
  },
  {
    "path": "xyz.itzsomebody.radon/src/main/java/xyz/itzsomebody/radon/cli/CmdSwitch.java",
    "content": "/*\n * Radon - An open-source Java obfuscator\n * Copyright (C) 2020 ItzSomebody\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, either version 3 of the License, or\n * (at your option) any later version.\n *\n * This program is distributed in the hope that it will be 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.  If not, see <http://www.gnu.org/licenses/>\n */\n\npackage xyz.itzsomebody.radon.cli;\n\nimport java.util.Objects;\n\npublic class CmdSwitch {\n    public final String id;\n    public final int expectedArgs;\n\n    public CmdSwitch(String id, int expectedArgs) {\n        this.id = id;\n        this.expectedArgs = expectedArgs;\n    }\n\n    @Override\n    public boolean equals(final Object o) {\n        if (this == o) {\n            return true;\n        }\n        if (o instanceof CmdSwitch) {\n            var other = (CmdSwitch) o;\n            return (this.expectedArgs == other.expectedArgs) && (Objects.equals(this.id, other.id));\n        }\n\n        return true;\n    }\n}"
  },
  {
    "path": "xyz.itzsomebody.radon/src/main/java/xyz/itzsomebody/radon/config/ConfigurationParser.java",
    "content": "/*\n * Radon - An open-source Java obfuscator\n * Copyright (C) 2020 ItzSomebody\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, either version 3 of the License, or\n * (at your option) any later version.\n *\n * This program is distributed in the hope that it will be 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.  If not, see <http://www.gnu.org/licenses/>\n */\n\npackage xyz.itzsomebody.radon.config;\n\nimport com.fasterxml.jackson.databind.ObjectMapper;\nimport com.fasterxml.jackson.databind.module.SimpleModule;\nimport xyz.itzsomebody.radon.exclusions.ExclusionManager;\nimport xyz.itzsomebody.radon.transformers.Transformer;\n\nimport java.io.IOException;\nimport java.io.InputStream;\n\n/**\n * Parser for the config\n *\n * @author itzsomebody\n */\npublic class ConfigurationParser extends ObjectMapper {\n    private final InputStream configStream;\n\n    public ConfigurationParser(InputStream configStream) {\n        super();\n        registerModule(new SimpleModule()\n                .addDeserializer(Transformer.class, new TransformerDeserializer())\n                .addDeserializer(ExclusionManager.class, new ExclusionsDeserializer())\n        );\n        this.configStream = configStream;\n    }\n\n    public ObfConfig parseConfig() throws IOException {\n        return readValue(configStream, ObfConfig.class);\n    }\n}\n"
  },
  {
    "path": "xyz.itzsomebody.radon/src/main/java/xyz/itzsomebody/radon/config/DictionaryDeserializer.java",
    "content": "/*\n * Radon - An open-source Java obfuscator\n * Copyright (C) 2021 ItzSomebody\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, either version 3 of the License, or\n * (at your option) any later version.\n *\n * This program is distributed in the hope that it will be 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.  If not, see <http://www.gnu.org/licenses/>\n */\n\npackage xyz.itzsomebody.radon.config;\n\nimport com.fasterxml.jackson.core.JsonParser;\nimport com.fasterxml.jackson.databind.DeserializationContext;\nimport com.fasterxml.jackson.databind.JsonDeserializer;\nimport xyz.itzsomebody.radon.dictionaries.Dictionary;\nimport xyz.itzsomebody.radon.dictionaries.DictionaryFactory;\n\nimport java.io.IOException;\n\npublic class DictionaryDeserializer extends JsonDeserializer<Dictionary> {\n    @Override\n    public Dictionary deserialize(JsonParser p, DeserializationContext ctxt) throws IOException {\n        var dictionaryName = p.readValueAs(String.class);\n        return DictionaryFactory.forName(dictionaryName);\n    }\n}\n"
  },
  {
    "path": "xyz.itzsomebody.radon/src/main/java/xyz/itzsomebody/radon/config/ExclusionsDeserializer.java",
    "content": "/*\n * Radon - An open-source Java obfuscator\n * Copyright (C) 2021 ItzSomebody\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, either version 3 of the License, or\n * (at your option) any later version.\n *\n * This program is distributed in the hope that it will be 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.  If not, see <http://www.gnu.org/licenses/>\n */\n\npackage xyz.itzsomebody.radon.config;\n\nimport com.fasterxml.jackson.core.JsonParser;\nimport com.fasterxml.jackson.databind.DeserializationContext;\nimport com.fasterxml.jackson.databind.JsonDeserializer;\nimport com.fasterxml.jackson.databind.JsonNode;\nimport xyz.itzsomebody.radon.exclusions.ExclusionManager;\n\nimport java.io.IOException;\nimport java.util.HashMap;\n\npublic class ExclusionsDeserializer extends JsonDeserializer<ExclusionManager> {\n    @Override\n    public ExclusionManager deserialize(JsonParser p, DeserializationContext ctxt) throws IOException {\n        JsonNode node = p.getCodec().readTree(p);\n        var map = new HashMap<String, String>();\n        node.fields().forEachRemaining(entry -> map.put(entry.getKey(), entry.getValue().asText()));\n        return new ExclusionManager(map);\n    }\n}\n"
  },
  {
    "path": "xyz.itzsomebody.radon/src/main/java/xyz/itzsomebody/radon/config/ObfConfig.java",
    "content": "/*\n * Radon - An open-source Java obfuscator\n * Copyright (C) 2020 ItzSomebody\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, either version 3 of the License, or\n * (at your option) any later version.\n *\n * This program is distributed in the hope that it will be 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.  If not, see <http://www.gnu.org/licenses/>\n */\n\npackage xyz.itzsomebody.radon.config;\n\nimport com.fasterxml.jackson.annotation.JsonProperty;\nimport xyz.itzsomebody.radon.RadonConstants;\nimport xyz.itzsomebody.radon.exclusions.ExclusionManager;\nimport xyz.itzsomebody.radon.transformers.Transformer;\n\nimport java.util.Collections;\nimport java.util.List;\nimport java.util.zip.Deflater;\n\n/**\n * Provides all of the information needed for Radon to do its job.\n *\n * @author itzsomebody\n */\npublic class ObfConfig {\n    @JsonProperty(\"input\")\n    public String input;\n\n    @JsonProperty(\"output\")\n    public String output;\n\n    @JsonProperty(\"libraries\")\n    public List<String> libraries;\n\n    @JsonProperty(\"exclusions\")\n    public ExclusionManager exclusions = new ExclusionManager(Collections.emptyMap());\n\n    @JsonProperty(\"transformers\")\n    public List<Transformer> transformers;\n\n    @JsonProperty(\"use_store\")\n    public boolean useStore;\n\n    @JsonProperty(\"compression_level\")\n    public int compressionLevel = Deflater.BEST_COMPRESSION;\n\n    @JsonProperty(\"zip_comment\")\n    public String zipComment = RadonConstants.DEFAULT_ZIP_COMMENT;\n\n    @JsonProperty(\"verify\")\n    public boolean verify;\n\n    @JsonProperty(\"fake_duplicate_entries\")\n    public int fakeDuplicateEntries;\n\n    @JsonProperty(\"corrupt_crcs\")\n    public boolean corruptCrcs;\n\n    @JsonProperty(\"anti_extraction\")\n    public boolean antiExtraction;\n\n    @JsonProperty(\"attempt_compute_maxs\")\n    public boolean attemptComputeMaxs;\n}\n"
  },
  {
    "path": "xyz.itzsomebody.radon/src/main/java/xyz/itzsomebody/radon/config/TransformerDeserializer.java",
    "content": "/*\n * Radon - An open-source Java obfuscator\n * Copyright (C) 2020 ItzSomebody\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, either version 3 of the License, or\n * (at your option) any later version.\n *\n * This program is distributed in the hope that it will be 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.  If not, see <http://www.gnu.org/licenses/>\n */\n\npackage xyz.itzsomebody.radon.config;\n\nimport com.fasterxml.jackson.core.JsonFactory;\nimport com.fasterxml.jackson.core.JsonParser;\nimport com.fasterxml.jackson.databind.DeserializationContext;\nimport com.fasterxml.jackson.databind.JsonDeserializer;\nimport com.fasterxml.jackson.databind.JsonNode;\nimport com.fasterxml.jackson.databind.ObjectMapper;\nimport com.fasterxml.jackson.databind.module.SimpleModule;\nimport xyz.itzsomebody.radon.dictionaries.Dictionary;\nimport xyz.itzsomebody.radon.exceptions.FatalRadonException;\nimport xyz.itzsomebody.radon.exceptions.PreventableRadonException;\nimport xyz.itzsomebody.radon.transformers.Transformer;\nimport xyz.itzsomebody.radon.transformers.Transformers;\n\nimport java.io.IOException;\nimport java.lang.reflect.InvocationTargetException;\n\n/**\n * Deseralizer for transformers\n *\n * @author itzsomebody\n */\npublic class TransformerDeserializer extends JsonDeserializer<Transformer> {\n    private static Transformer transformerFor(String name) {\n        try {\n            var transformerEnum = Transformers.valueOf(name.toUpperCase());\n            var clazz = transformerEnum.getTransformerClass();\n            var cnstr = clazz.getConstructor();\n            cnstr.setAccessible(true);\n            return cnstr.newInstance();\n        } catch (IllegalArgumentException e) {\n            throw new PreventableRadonException(\"Transformer \\\"\" + name + \"\\\" is an unknown transformer\");\n        } catch (NoSuchMethodException | InstantiationException | IllegalAccessException e) {\n            throw new FatalRadonException(e);\n        } catch (InvocationTargetException e) {\n            throw new FatalRadonException(e.getTargetException());\n        }\n    }\n\n    @Override\n    public Transformer deserialize(JsonParser jp, DeserializationContext ctxt) throws IOException {\n        JsonNode node = jp.getCodec().readTree(jp);\n        var entry = node.fields().next();\n        var transformer = transformerFor(entry.getKey());\n        if (entry.getValue().isBoolean()) {\n            if (entry.getValue().asBoolean()) {\n                return transformer;\n            } else {\n                return null; // fixme: don't caboose null\n            }\n        } else {\n            var mapper = new ObjectMapper(new JsonFactory());\n            mapper.registerModule(new SimpleModule().addDeserializer(Dictionary.class, new DictionaryDeserializer()));\n            return mapper.readerForUpdating(transformer).readValue(entry.getValue());\n        }\n    }\n}\n"
  },
  {
    "path": "xyz.itzsomebody.radon/src/main/java/xyz/itzsomebody/radon/dictionaries/Dictionary.java",
    "content": "/*\n * Radon - An open-source Java obfuscator\n * Copyright (C) 2020 ItzSomebody\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, either version 3 of the License, or\n * (at your option) any later version.\n *\n * This program is distributed in the hope that it will be 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.  If not, see <http://www.gnu.org/licenses/>\n */\n\npackage xyz.itzsomebody.radon.dictionaries;\n\nimport xyz.itzsomebody.radon.utils.RandomUtils;\n\npublic interface Dictionary {\n    String next();\n\n    String randomStr(int length);\n\n    String configName();\n\n    Dictionary copy();\n\n    // https://en.wikipedia.org/wiki/Bijective_numeration\n    static String toBijectiveBase(char[] charset, int decimal) {\n        var sb = new StringBuilder();\n        while (decimal-- > 0) {\n            sb.insert(0, charset[decimal % charset.length]);\n            decimal /= charset.length;\n        }\n        return sb.toString();\n    }\n\n    static String randomString(char[] charset, int length) {\n        var charsetLength = charset.length;\n        var buf = new char[length];\n\n        for (int i = 0; i < length; i++) {\n            buf[i] = charset[RandomUtils.randomInt(charsetLength)];\n        }\n\n        return new String(buf);\n    }\n}\n"
  },
  {
    "path": "xyz.itzsomebody.radon/src/main/java/xyz/itzsomebody/radon/dictionaries/DictionaryFactory.java",
    "content": "/*\n * Radon - An open-source Java obfuscator\n * Copyright (C) 2021 ItzSomebody\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, either version 3 of the License, or\n * (at your option) any later version.\n *\n * This program is distributed in the hope that it will be 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.  If not, see <http://www.gnu.org/licenses/>\n */\n\npackage xyz.itzsomebody.radon.dictionaries;\n\nimport xyz.itzsomebody.radon.dictionaries.defined.*;\nimport xyz.itzsomebody.radon.utils.logging.RadonLogger;\n\nimport java.util.List;\n\npublic class DictionaryFactory {\n    private static final Dictionary[] DEFINED = {\n            new AlphabeticalDictionary(),\n            new AlphaNumericDictionary(),\n            new RandomUnicodeDictionary(),\n            new SpacesDictionary(),\n            new UnrecognizedDictionary()\n    };\n\n    public static Dictionary forName(String name) {\n        return List.of(DEFINED).stream()\n                .filter(dictionary -> name.equalsIgnoreCase(dictionary.configName()))\n                .findFirst()\n                .orElseGet(() -> {\n                    RadonLogger.info(\"Unknown dictionary \\\"\" + name + \"\\\" -- treating as user-defined charset dictionary\");\n                    return new CustomCharsetDictionary(name);\n                });\n    }\n\n    public static Dictionary defaultDictionary() {\n        return new AlphabeticalDictionary();\n    }\n}\n"
  },
  {
    "path": "xyz.itzsomebody.radon/src/main/java/xyz/itzsomebody/radon/dictionaries/defined/AlphaNumericDictionary.java",
    "content": "/*\n * Radon - An open-source Java obfuscator\n * Copyright (C) 2021 ItzSomebody\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, either version 3 of the License, or\n * (at your option) any later version.\n *\n * This program is distributed in the hope that it will be 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.  If not, see <http://www.gnu.org/licenses/>\n */\n\npackage xyz.itzsomebody.radon.dictionaries.defined;\n\nimport xyz.itzsomebody.radon.dictionaries.Dictionary;\nimport xyz.itzsomebody.radon.utils.RandomUtils;\n\npublic class AlphaNumericDictionary implements Dictionary {\n    private static final char[] CHARSET = \"1234567890ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz\".toCharArray();\n    private int index = 1;\n\n    @Override\n    public String next() {\n        return Dictionary.toBijectiveBase(CHARSET, index++);\n    }\n\n    @Override\n    public String randomStr(int length) {\n        return Dictionary.randomString(CHARSET, length);\n    }\n\n    @Override\n    public String configName() {\n        return \"alphanumeric\";\n    }\n\n    @Override\n    public Dictionary copy() {\n        return new AlphaNumericDictionary();\n    }\n}\n"
  },
  {
    "path": "xyz.itzsomebody.radon/src/main/java/xyz/itzsomebody/radon/dictionaries/defined/AlphabeticalDictionary.java",
    "content": "/*\n * Radon - An open-source Java obfuscator\n * Copyright (C) 2020 ItzSomebody\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, either version 3 of the License, or\n * (at your option) any later version.\n *\n * This program is distributed in the hope that it will be 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.  If not, see <http://www.gnu.org/licenses/>\n */\n\npackage xyz.itzsomebody.radon.dictionaries.defined;\n\nimport xyz.itzsomebody.radon.dictionaries.Dictionary;\n\npublic class AlphabeticalDictionary implements Dictionary {\n    private static final char[] CHARSET = \"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz\".toCharArray();\n    private int index = 1;\n\n    @Override\n    public String next() {\n        return Dictionary.toBijectiveBase(CHARSET, index++);\n    }\n\n    @Override\n    public String randomStr(int length) {\n        return Dictionary.randomString(CHARSET, length);\n    }\n\n    @Override\n    public String configName() {\n        return \"alphabetical\";\n    }\n\n    @Override\n    public Dictionary copy() {\n        return new AlphabeticalDictionary();\n    }\n}\n"
  },
  {
    "path": "xyz.itzsomebody.radon/src/main/java/xyz/itzsomebody/radon/dictionaries/defined/CustomCharsetDictionary.java",
    "content": "/*\n * Radon - An open-source Java obfuscator\n * Copyright (C) 2021 ItzSomebody\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, either version 3 of the License, or\n * (at your option) any later version.\n *\n * This program is distributed in the hope that it will be 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.  If not, see <http://www.gnu.org/licenses/>\n */\n\npackage xyz.itzsomebody.radon.dictionaries.defined;\n\nimport xyz.itzsomebody.radon.dictionaries.Dictionary;\n\npublic class CustomCharsetDictionary implements Dictionary {\n    private final char[] charset;\n    private int index = 1;\n\n    public CustomCharsetDictionary(String charsetString) {\n        charset = charsetString.toCharArray();\n    }\n\n    @Override\n    public String next() {\n        return Dictionary.toBijectiveBase(charset, index++);\n    }\n\n    @Override\n    public String randomStr(int length) {\n        return Dictionary.randomString(charset, length);\n    }\n\n    @Override\n    public String configName() {\n        // This is intentional\n        return null;\n    }\n\n    @Override\n    public Dictionary copy() {\n        return new AlphaNumericDictionary();\n    }\n}\n"
  },
  {
    "path": "xyz.itzsomebody.radon/src/main/java/xyz/itzsomebody/radon/dictionaries/defined/RandomUnicodeDictionary.java",
    "content": "/*\n * Radon - An open-source Java obfuscator\n * Copyright (C) 2021 ItzSomebody\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, either version 3 of the License, or\n * (at your option) any later version.\n *\n * This program is distributed in the hope that it will be 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.  If not, see <http://www.gnu.org/licenses/>\n */\n\npackage xyz.itzsomebody.radon.dictionaries.defined;\n\nimport xyz.itzsomebody.radon.dictionaries.Dictionary;\nimport xyz.itzsomebody.radon.utils.RandomUtils;\n\npublic class RandomUnicodeDictionary implements Dictionary {\n    private static final char[] CHARSET = new char[25];\n    private int index = 1;\n\n    static {\n        for (int i = 0; i < CHARSET.length; i++) {\n            CHARSET[i] = (char) RandomUtils.randomInt('\\u2000', '\\uFFFF');\n        }\n    }\n\n    @Override\n    public String next() {\n        return Dictionary.toBijectiveBase(CHARSET, index++);\n    }\n\n    @Override\n    public String randomStr(int length) {\n        return Dictionary.randomString(CHARSET, length);\n    }\n\n    @Override\n    public String configName() {\n        return \"random_unicode\";\n    }\n\n    @Override\n    public Dictionary copy() {\n        return new RandomUnicodeDictionary();\n    }\n}\n"
  },
  {
    "path": "xyz.itzsomebody.radon/src/main/java/xyz/itzsomebody/radon/dictionaries/defined/SpacesDictionary.java",
    "content": "/*\n * Radon - An open-source Java obfuscator\n * Copyright (C) 2021 ItzSomebody\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, either version 3 of the License, or\n * (at your option) any later version.\n *\n * This program is distributed in the hope that it will be 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.  If not, see <http://www.gnu.org/licenses/>\n */\n\npackage xyz.itzsomebody.radon.dictionaries.defined;\n\nimport xyz.itzsomebody.radon.dictionaries.Dictionary;\n\npublic class SpacesDictionary implements Dictionary {\n    private static final char[] CHARSET = new char[0xF + 1];\n    private int index = 1;\n\n    static {\n        for (int i = 0; i < CHARSET.length; i++) {\n            CHARSET[i] = (char) ('\\u2000' + i);\n        }\n    }\n\n    @Override\n    public String next() {\n        return Dictionary.toBijectiveBase(CHARSET, index++);\n    }\n\n    @Override\n    public String randomStr(int length) {\n        return Dictionary.randomString(CHARSET, length);\n    }\n\n    @Override\n    public String configName() {\n        return \"spaces\";\n    }\n\n    @Override\n    public Dictionary copy() {\n        return new SpacesDictionary();\n    }\n}\n"
  },
  {
    "path": "xyz.itzsomebody.radon/src/main/java/xyz/itzsomebody/radon/dictionaries/defined/UnrecognizedDictionary.java",
    "content": "/*\n * Radon - An open-source Java obfuscator\n * Copyright (C) 2021 ItzSomebody\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, either version 3 of the License, or\n * (at your option) any later version.\n *\n * This program is distributed in the hope that it will be 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.  If not, see <http://www.gnu.org/licenses/>\n */\n\npackage xyz.itzsomebody.radon.dictionaries.defined;\n\nimport xyz.itzsomebody.radon.dictionaries.Dictionary;\n\npublic class UnrecognizedDictionary implements Dictionary {\n    private static final char[] CHARSET = new char[33];\n    private int index = 1;\n\n    static {\n        for (int i = 0; i < CHARSET.length; i++) {\n            CHARSET[i] = (char) ('\\ua6ac' + i);\n        }\n    }\n\n    @Override\n    public String next() {\n        return Dictionary.toBijectiveBase(CHARSET, index++);\n    }\n\n    @Override\n    public String randomStr(int length) {\n        return Dictionary.randomString(CHARSET, length);\n    }\n\n    @Override\n    public String configName() {\n        return \"unrecognized\";\n    }\n\n    @Override\n    public Dictionary copy() {\n        return new UnrecognizedDictionary();\n    }\n}\n"
  },
  {
    "path": "xyz.itzsomebody.radon/src/main/java/xyz/itzsomebody/radon/exceptions/FatalRadonException.java",
    "content": "/*\n * Radon - An open-source Java obfuscator\n * Copyright (C) 2020 ItzSomebody\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, either version 3 of the License, or\n * (at your option) any later version.\n *\n * This program is distributed in the hope that it will be 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.  If not, see <http://www.gnu.org/licenses/>\n */\n\npackage xyz.itzsomebody.radon.exceptions;\n\n/**\n * A subclass of {@link RuntimeException} that should only be thrown on non-user-preventable exceptions (e.g.\n * programmatic or logic errors).\n *\n * @author itzsomebody\n */\npublic class FatalRadonException extends RuntimeException {\n    public FatalRadonException() {\n        super();\n    }\n\n    public FatalRadonException(String msg) {\n        super(msg);\n    }\n\n    public FatalRadonException(Throwable t) {\n        super(t);\n    }\n}\n"
  },
  {
    "path": "xyz.itzsomebody.radon/src/main/java/xyz/itzsomebody/radon/exceptions/MissingClassException.java",
    "content": "/*\n * Radon - An open-source Java obfuscator\n * Copyright (C) 2020 ItzSomebody\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, either version 3 of the License, or\n * (at your option) any later version.\n *\n * This program is distributed in the hope that it will be 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.  If not, see <http://www.gnu.org/licenses/>\n */\n\npackage xyz.itzsomebody.radon.exceptions;\n\n/**\n * Subclass of {@link PreventableRadonException} which is thrown when Radon is unable to find classes that should have\n * been in either the input JAR or in one of the user-provided libraries in the config.\n *\n * @author itzsomebody\n */\npublic class MissingClassException extends PreventableRadonException {\n    private MissingClassException(String className, boolean library) {\n        super(\"Do NOT report this as an issue unless you have ensured the supposedly missing class is actually in at \" +\n                \"least one of the provided libraries in your config.\\n\" + String.format(\n                \"Could not find \\\"%s\\\" in the %s.\", className, library ? \"classpath\" : \"input JAR classes\"));\n    }\n\n    public static MissingClassException forInputClass(String className) {\n        return new MissingClassException(className, false);\n    }\n\n    public static MissingClassException forLibraryClass(String className) {\n        return new MissingClassException(className, true);\n    }\n}\n"
  },
  {
    "path": "xyz.itzsomebody.radon/src/main/java/xyz/itzsomebody/radon/exceptions/MissingResourceException.java",
    "content": "/*\n * Radon - An open-source Java obfuscator\n * Copyright (C) 2020 ItzSomebody\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, either version 3 of the License, or\n * (at your option) any later version.\n *\n * This program is distributed in the hope that it will be 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.  If not, see <http://www.gnu.org/licenses/>\n */\n\npackage xyz.itzsomebody.radon.exceptions;\n\npublic class MissingResourceException extends PreventableRadonException {\n    public MissingResourceException(String resourceName) {\n        super(\"Do NOT report this as an issue unless you have ensured the supposedly missing resource is actually in\" +\n                \"the input jar.\\n\" + String.format(\"Could not find \\\"%s\\\" in the input JAR.\", resourceName));\n    }\n}\n"
  },
  {
    "path": "xyz.itzsomebody.radon/src/main/java/xyz/itzsomebody/radon/exceptions/PreventableRadonException.java",
    "content": "/*\n * Radon - An open-source Java obfuscator\n * Copyright (C) 2020 ItzSomebody\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, either version 3 of the License, or\n * (at your option) any later version.\n *\n * This program is distributed in the hope that it will be 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.  If not, see <http://www.gnu.org/licenses/>\n */\n\npackage xyz.itzsomebody.radon.exceptions;\n\n/**\n * A subclass of {@link RuntimeException} that should only be thrown on user-preventable exceptions\n * (e.g. certain OOM errors).\n *\n * @author itzsomebody\n */\npublic class PreventableRadonException extends RuntimeException {\n    public PreventableRadonException() {\n        super();\n    }\n\n    public PreventableRadonException(String msg) {\n        super(msg);\n    }\n\n    public PreventableRadonException(Throwable t) {\n        super(t);\n    }\n}\n"
  },
  {
    "path": "xyz.itzsomebody.radon/src/main/java/xyz/itzsomebody/radon/exclusions/Exclusion.java",
    "content": "/*\n * Radon - An open-source Java obfuscator\n * Copyright (C) 2020 ItzSomebody\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, either version 3 of the License, or\n * (at your option) any later version.\n *\n * This program is distributed in the hope that it will be 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.  If not, see <http://www.gnu.org/licenses/>\n */\n\npackage xyz.itzsomebody.radon.exclusions;\n\nimport java.util.Objects;\nimport java.util.regex.Matcher;\nimport java.util.regex.Pattern;\n\npublic class Exclusion {\n    private final Matcher matcher;\n    private final String rawPattern;\n    private final boolean invert;\n    private final ExclusionType exclusionType;\n\n    public Exclusion(String pattern) {\n        this(pattern, false);\n    }\n\n    public Exclusion(String pattern, boolean invert) {\n        this(pattern, ExclusionType.GLOBAL, invert);\n    }\n\n    public Exclusion(String pattern, ExclusionType exclusionType, boolean invert) {\n        this.matcher = Pattern.compile(pattern).matcher(\"\");\n        this.rawPattern = pattern;\n        this.invert = invert;\n        this.exclusionType = exclusionType;\n    }\n\n    public boolean matches(String other, ExclusionType type) {\n        if (type == ExclusionType.GLOBAL || type == exclusionType) {\n            return true;\n        }\n\n        return invert != matcher.reset(other).matches();\n    }\n\n    @Override\n    public boolean equals(Object o) {\n        if (o instanceof Exclusion) {\n            return Objects.equals(rawPattern, ((Exclusion) o).rawPattern);\n        }\n\n        return false;\n    }\n\n    @Override\n    public int hashCode() {\n        return Objects.hash(rawPattern);\n    }\n\n    public enum ExclusionType {\n        GLOBAL,\n        OPTIMIZER,\n        SHRINKER,\n        ADD_BRIDGE_ACCESS_FLAG,\n        ADD_DEPRECATED_ACCESS_FLAG,\n        ADD_SYNTHETIC_ACCESS_FLAG,\n        ADD_TRASH_CLASSES,\n        RENAMER,\n        RESOURCE_RENAMER,\n        SCRAMBLE_LINE_NUMBERS,\n        STRING_OBFUSCATION,\n        REFERENCE_OBFUSCATION,\n        NUMBER_OBFUSCATION,\n        FLOW_OBFUSCATION,\n        ANTI_TAMPER,\n        INJECT_ANTI_DEBUGGER,\n        INJECT_EXPIRATION_KILL_SWITCH,\n        ANTI_MEMORY_DUMP,\n        VIRTUALIZER,\n        PACKER,\n        WATERMARK,\n        SHUFFLE_MEMBERS; // fixme\n\n        public static ExclusionType forIdentifier(String identifier) {\n            // This is O(n), but should be fine since this is run only during config load\n            for (var type : values()) {\n                if (type.name().equalsIgnoreCase(identifier)) {\n                    return type;\n                }\n            }\n\n            return GLOBAL;\n        }\n    }\n}\n"
  },
  {
    "path": "xyz.itzsomebody.radon/src/main/java/xyz/itzsomebody/radon/exclusions/ExclusionManager.java",
    "content": "/*\n * Radon - An open-source Java obfuscator\n * Copyright (C) 2020 ItzSomebody\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, either version 3 of the License, or\n * (at your option) any later version.\n *\n * This program is distributed in the hope that it will be 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.  If not, see <http://www.gnu.org/licenses/>\n */\n\npackage xyz.itzsomebody.radon.exclusions;\n\nimport java.util.HashMap;\nimport java.util.HashSet;\nimport java.util.Map;\nimport java.util.Set;\n\npublic class ExclusionManager {\n    private final Set<Exclusion> exclusions;\n    private final Map<String, Boolean> cache;\n\n    public ExclusionManager(Map<String, String> patterns) {\n        this.exclusions = new HashSet<>(patterns.size());\n        this.cache = new HashMap<>();\n\n        patterns.forEach((k, v) -> {\n            var invert = false;\n\n            if (k.startsWith(\"!\")) {\n                invert = true;\n                k = k.substring(1);\n            }\n\n            exclusions.add(new Exclusion(v, Exclusion.ExclusionType.forIdentifier(k), invert));\n        });\n    }\n\n    public boolean find(String other, Exclusion.ExclusionType exclusionType) {\n        // fixme: flawed cache logic\n        if (cache.containsKey(other)) {\n            return cache.get(other);\n        }\n\n        var result = exclusions.stream().anyMatch(exclusion -> exclusion.matches(other, exclusionType));\n        cache.put(other, result);\n        return result;\n    }\n}\n"
  },
  {
    "path": "xyz.itzsomebody.radon/src/main/java/xyz/itzsomebody/radon/transformers/Transformer.java",
    "content": "/*\n * Radon - An open-source Java obfuscator\n * Copyright (C) 2020 ItzSomebody\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, either version 3 of the License, or\n * (at your option) any later version.\n *\n * This program is distributed in the hope that it will be 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.  If not, see <http://www.gnu.org/licenses/>\n */\n\npackage xyz.itzsomebody.radon.transformers;\n\nimport org.objectweb.asm.Opcodes;\nimport org.objectweb.asm.tree.ClassNode;\nimport xyz.itzsomebody.radon.Radon;\nimport xyz.itzsomebody.radon.config.ConfigurationParser;\nimport xyz.itzsomebody.radon.config.ObfConfig;\nimport xyz.itzsomebody.radon.exclusions.Exclusion;\nimport xyz.itzsomebody.radon.utils.RandomUtils;\nimport xyz.itzsomebody.radon.utils.asm.ClassWrapper;\nimport xyz.itzsomebody.radon.utils.asm.FieldWrapper;\nimport xyz.itzsomebody.radon.utils.asm.MethodWrapper;\n\nimport java.util.ArrayList;\nimport java.util.Collection;\nimport java.util.Map;\nimport java.util.stream.Stream;\n\npublic abstract class Transformer implements Opcodes {\n    private Radon radon;\n\n    public void init(Radon radon) {\n        this.radon = radon;\n    }\n\n    protected Collection<ClassWrapper> classes() {\n        return radon.getClasses().values();\n    }\n\n    protected Stream<ClassWrapper> classStream() {\n        return classes().stream();\n    }\n\n    protected Map<String, ClassWrapper> classMap() {\n        return radon.getClasses();\n    }\n\n    protected Map<String, ClassWrapper> classPathMap() {\n        return radon.getClasspath();\n    }\n\n    protected Map<String, byte[]> resourceMap() {\n        return radon.getResources();\n    }\n\n    protected boolean notExcluded(ClassWrapper wrapper) {\n        return notExcluded(wrapper.getOriginalName());\n    }\n\n    protected boolean notExcluded(MethodWrapper wrapper) {\n        return notExcluded(wrapper.getOwner().getOriginalName() + ' ' + wrapper.getOriginalName() + wrapper.getOriginalDescriptor());\n    }\n\n    protected boolean notExcluded(FieldWrapper wrapper) {\n        return notExcluded(wrapper.getOwner().getOriginalName() + ' ' + wrapper.getOriginalName() + ' ' + wrapper.getOriginalType());\n    }\n\n    protected boolean notExcluded(String checkThis) {\n        return !radon.getExclusionManager().find(checkThis, getExclusionType());\n    }\n\n    protected void addClass(ClassWrapper classWrapper) {\n        radon.getClasses().put(classWrapper.getName(), classWrapper);\n        radon.getClasspath().put(classWrapper.getName(), classWrapper);\n    }\n\n    protected void addClass(ClassNode classNode) {\n        addClass(new ClassWrapper(classNode, false));\n        addClass(new ClassWrapper(classNode, false));\n    }\n\n    protected ClassWrapper randomClass() {\n        var list = new ArrayList<>(classMap().values());\n        return list.get(RandomUtils.randomInt(list.size()));\n    }\n\n    protected String fakeSubClass() {\n        var list = new ArrayList<>(classMap().keySet());\n        var base = list.get(RandomUtils.randomInt(list.size()));\n        var sub = list.get(RandomUtils.randomInt(list.size()));\n\n        return base + '$' + sub.substring(sub.lastIndexOf('/') + 1);\n    }\n\n    public String getName() {\n        return getClass().getName();\n    }\n\n    public abstract void transform();\n\n    public abstract Exclusion.ExclusionType getExclusionType();\n\n    public abstract String getConfigName();\n}\n"
  },
  {
    "path": "xyz.itzsomebody.radon/src/main/java/xyz/itzsomebody/radon/transformers/Transformers.java",
    "content": "/*\n * Radon - An open-source Java obfuscator\n * Copyright (C) 2020 ItzSomebody\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, either version 3 of the License, or\n * (at your option) any later version.\n *\n * This program is distributed in the hope that it will be 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.  If not, see <http://www.gnu.org/licenses/>\n */\n\npackage xyz.itzsomebody.radon.transformers;\n\nimport xyz.itzsomebody.radon.transformers.misc.*;\nimport xyz.itzsomebody.radon.transformers.strings.AESPCBCStringEncryption;\nimport xyz.itzsomebody.radon.transformers.strings.StaticFieldStrPool;\nimport xyz.itzsomebody.radon.transformers.strings.Str2Base64Encoding;\n\npublic enum Transformers {\n    // Misc.\n    ADD_BRIDGE_ACCESS_FLAG(AddBridgeAccess.class),\n    ADD_DEPRECATED_ACCESS_FLAG(AddDeprecatedAccess.class),\n    ADD_SYNTHETIC_ACCESS_FLAG(AddSyntheticAccess.class),\n    ADD_TRASH_CLASSES(AddTrashClasses.class),\n    INJECT_ANTI_DEBUGGER(AntiDebugger.class),\n    INJECT_EXPIRATION_KILL_SWITCH(ExpirationKillSwitch.class),\n    RENAMER(Renamer.class),\n    RESOURCE_RENAMER(ResourceRenamer.class),\n    SCRAMBLE_LINE_NUMBERS(ScrambleLineNumbers.class),\n    SHUFFLE_MEMBERS(ShuffleMembers.class),\n    WATERMARK(Watermarker.class),\n\n    // String encryption/encoding\n    STRING_TO_BASE64_ENCODING(Str2Base64Encoding.class),\n    POOL_STRINGS_TO_STATIC_FIELD(StaticFieldStrPool.class),\n    AES_PCBC_STRING_ENCRYPTION(AESPCBCStringEncryption.class),\n\n    ;//TODO\n\n    private final Class<? extends Transformer> transformerClass;\n\n    Transformers(Class<? extends Transformer> transformerClass) {\n        this.transformerClass = transformerClass;\n    }\n\n    public Class<? extends Transformer> getTransformerClass() {\n        return transformerClass;\n    }\n\n    public String getConfigName() {\n        return name().toLowerCase();\n    }\n}\n"
  },
  {
    "path": "xyz.itzsomebody.radon/src/main/java/xyz/itzsomebody/radon/transformers/exploiter/ExploiterTransformer.java",
    "content": "package xyz.itzsomebody.radon.transformers.exploiter;\n\npublic class ExploiterTransformer {\n}\n"
  },
  {
    "path": "xyz.itzsomebody.radon/src/main/java/xyz/itzsomebody/radon/transformers/flow/FlowTransformer.java",
    "content": "package xyz.itzsomebody.radon.transformers.flow;\n\npublic class FlowTransformer {\n}\n"
  },
  {
    "path": "xyz.itzsomebody.radon/src/main/java/xyz/itzsomebody/radon/transformers/math/NumberTransformer.java",
    "content": "package xyz.itzsomebody.radon.transformers.math;\n\npublic class NumberTransformer {\n}\n"
  },
  {
    "path": "xyz.itzsomebody.radon/src/main/java/xyz/itzsomebody/radon/transformers/misc/AddBridgeAccess.java",
    "content": "/*\n * Radon - An open-source Java obfuscator\n * Copyright (C) 2021 ItzSomebody\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, either version 3 of the License, or\n * (at your option) any later version.\n *\n * This program is distributed in the hope that it will be 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.  If not, see <http://www.gnu.org/licenses/>\n */\n\npackage xyz.itzsomebody.radon.transformers.misc;\n\nimport org.objectweb.asm.Opcodes;\nimport xyz.itzsomebody.radon.config.ConfigurationParser;\nimport xyz.itzsomebody.radon.exclusions.Exclusion;\nimport xyz.itzsomebody.radon.transformers.Transformer;\nimport xyz.itzsomebody.radon.transformers.Transformers;\nimport xyz.itzsomebody.radon.utils.logging.RadonLogger;\n\nimport java.util.concurrent.atomic.AtomicInteger;\n\npublic class AddBridgeAccess extends Transformer {\n    @Override\n    public void transform() {\n        var count = new AtomicInteger();\n        classes().stream().filter(this::notExcluded).forEach(cw -> {\n            cw.methodStream().filter(mw -> notExcluded(mw) && !mw.hasVisibleAnnotations()).forEach(mw -> {\n                // Adding ACC_BRIDGE to init / clinit is e-legal\n                if (!mw.getMethodNode().name.startsWith(\"<\") && !mw.isBridge()) {\n                    mw.addAccessFlags(Opcodes.ACC_BRIDGE);\n                    count.incrementAndGet();\n                }\n            });\n        });\n        RadonLogger.info(\"Added bridge access flags to \" + count.get() + \" methods\");\n    }\n\n    @Override\n    public Exclusion.ExclusionType getExclusionType() {\n        return Exclusion.ExclusionType.ADD_BRIDGE_ACCESS_FLAG;\n    }\n\n    @Override\n    public String getConfigName() {\n        return Transformers.ADD_BRIDGE_ACCESS_FLAG.getConfigName();\n    }\n}\n"
  },
  {
    "path": "xyz.itzsomebody.radon/src/main/java/xyz/itzsomebody/radon/transformers/misc/AddDeprecatedAccess.java",
    "content": "/*\n * Radon - An open-source Java obfuscator\n * Copyright (C) 2021 ItzSomebody\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, either version 3 of the License, or\n * (at your option) any later version.\n *\n * This program is distributed in the hope that it will be 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.  If not, see <http://www.gnu.org/licenses/>\n */\n\npackage xyz.itzsomebody.radon.transformers.misc;\n\nimport com.fasterxml.jackson.annotation.JsonProperty;\nimport org.objectweb.asm.Opcodes;\nimport xyz.itzsomebody.radon.config.ConfigurationParser;\nimport xyz.itzsomebody.radon.exclusions.Exclusion;\nimport xyz.itzsomebody.radon.transformers.Transformer;\nimport xyz.itzsomebody.radon.transformers.Transformers;\nimport xyz.itzsomebody.radon.utils.logging.RadonLogger;\n\nimport java.util.concurrent.atomic.AtomicInteger;\n\npublic class AddDeprecatedAccess extends Transformer {\n    @JsonProperty(\"add_to_classes\")\n    private boolean doClasses;\n\n    @JsonProperty(\"add_to_methods\")\n    private boolean doMethods;\n\n    @JsonProperty(\"add_to_fields\")\n    private boolean doFields;\n\n    @Override\n    public void transform() {\n        var classCount = new AtomicInteger();\n        var methodCount = new AtomicInteger();\n        var fieldCount = new AtomicInteger();\n        if (doClasses || doFields || doMethods) {\n            classes().stream().filter(this::notExcluded).forEach(cw -> {\n                if (doFields) {\n                    cw.fieldStream().filter(this::notExcluded).forEach(fw -> {\n                        if (!fw.isDeprecated()) {\n                            fw.addAccessFlags(Opcodes.ACC_DEPRECATED);\n                            fieldCount.incrementAndGet();\n                        }\n                    });\n                }\n                if (doMethods) {\n                    cw.methodStream().filter(this::notExcluded).forEach(mw -> {\n                        if (!mw.isDeprecated()) {\n                            mw.addAccessFlags(Opcodes.ACC_DEPRECATED);\n                            methodCount.incrementAndGet();\n                        }\n                    });\n                }\n                if (doClasses) {\n                    if (!cw.isDeprecated()) {\n                        cw.addAccessFlags(Opcodes.ACC_DEPRECATED);\n                        classCount.incrementAndGet();\n                    }\n                }\n            });\n        }\n        RadonLogger.info(String.format(\"Added deprecated access flags to %d classes, %d methods, and %d fields\", classCount.get(), methodCount.get(), fieldCount.get()));\n    }\n\n    @Override\n    public Exclusion.ExclusionType getExclusionType() {\n        return Exclusion.ExclusionType.ADD_DEPRECATED_ACCESS_FLAG;\n    }\n\n    @Override\n    public String getConfigName() {\n        return Transformers.ADD_DEPRECATED_ACCESS_FLAG.getConfigName();\n    }\n}\n"
  },
  {
    "path": "xyz.itzsomebody.radon/src/main/java/xyz/itzsomebody/radon/transformers/misc/AddSyntheticAccess.java",
    "content": "/*\n * Radon - An open-source Java obfuscator\n * Copyright (C) 2021 ItzSomebody\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, either version 3 of the License, or\n * (at your option) any later version.\n *\n * This program is distributed in the hope that it will be 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.  If not, see <http://www.gnu.org/licenses/>\n */\n\npackage xyz.itzsomebody.radon.transformers.misc;\n\nimport com.fasterxml.jackson.annotation.JsonProperty;\nimport org.objectweb.asm.Opcodes;\nimport xyz.itzsomebody.radon.exclusions.Exclusion;\nimport xyz.itzsomebody.radon.transformers.Transformer;\nimport xyz.itzsomebody.radon.transformers.Transformers;\nimport xyz.itzsomebody.radon.utils.logging.RadonLogger;\n\nimport java.util.concurrent.atomic.AtomicInteger;\n\npublic class AddSyntheticAccess extends Transformer {\n    @JsonProperty(\"add_to_classes\")\n    private boolean doClasses;\n\n    @JsonProperty(\"add_to_methods\")\n    private boolean doMethods;\n\n    @JsonProperty(\"add_to_fields\")\n    private boolean doFields;\n\n    @Override\n    public void transform() {\n        var classCount = new AtomicInteger();\n        var methodCount = new AtomicInteger();\n        var fieldCount = new AtomicInteger();\n        if (doClasses || doFields || doMethods) {\n            classes().stream().filter(this::notExcluded).forEach(cw -> {\n                if (doFields) {\n                    cw.fieldStream().filter(fw -> notExcluded(fw) && fw.hasVisibleAnnotations()).forEach(fw -> {\n                        if (!fw.isSynthetic()) {\n                            fw.addAccessFlags(Opcodes.ACC_SYNTHETIC);\n                            fieldCount.incrementAndGet();\n                        }\n                    });\n                }\n                if (doMethods) {\n                    cw.methodStream().filter(mw -> notExcluded(mw) && !mw.hasVisibleAnnotations()).forEach(mw -> {\n                        if (!mw.isSynthetic()) {\n                            mw.addAccessFlags(Opcodes.ACC_SYNTHETIC);\n                            methodCount.incrementAndGet();\n                        }\n                    });\n                }\n                if (doClasses) {\n                    if (!cw.hasVisibleAnnotations() && !cw.isSynthetic()) {\n                        cw.addAccessFlags(Opcodes.ACC_SYNTHETIC);\n                        classCount.incrementAndGet();\n                    }\n                }\n            });\n        }\n        RadonLogger.info(String.format(\"Added synthetic access flags to %d classes, %d methods, and %d fields\", classCount.get(), methodCount.get(), fieldCount.get()));\n    }\n\n    @Override\n    public Exclusion.ExclusionType getExclusionType() {\n        return Exclusion.ExclusionType.ADD_SYNTHETIC_ACCESS_FLAG;\n    }\n\n    @Override\n    public String getConfigName() {\n        return Transformers.ADD_SYNTHETIC_ACCESS_FLAG.getConfigName();\n    }\n}\n"
  },
  {
    "path": "xyz.itzsomebody.radon/src/main/java/xyz/itzsomebody/radon/transformers/misc/AddTrashClasses.java",
    "content": "/*\n * Radon - An open-source Java obfuscator\n * Copyright (C) 2021 ItzSomebody\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, either version 3 of the License, or\n * (at your option) any later version.\n *\n * This program is distributed in the hope that it will be 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.  If not, see <http://www.gnu.org/licenses/>\n */\n\npackage xyz.itzsomebody.radon.transformers.misc;\n\nimport com.fasterxml.jackson.annotation.JsonProperty;\nimport org.objectweb.asm.ClassWriter;\nimport org.objectweb.asm.Handle;\nimport org.objectweb.asm.Type;\nimport org.objectweb.asm.tree.*;\nimport xyz.itzsomebody.radon.RadonConstants;\nimport xyz.itzsomebody.radon.dictionaries.Dictionary;\nimport xyz.itzsomebody.radon.dictionaries.DictionaryFactory;\nimport xyz.itzsomebody.radon.exclusions.Exclusion;\nimport xyz.itzsomebody.radon.transformers.Transformer;\nimport xyz.itzsomebody.radon.transformers.Transformers;\nimport xyz.itzsomebody.radon.utils.RandomUtils;\nimport xyz.itzsomebody.radon.utils.asm.ASMUtils;\nimport xyz.itzsomebody.radon.utils.logging.RadonLogger;\n\nimport java.util.ArrayList;\n\n/**\n * Not really a transformer. This \"transformer\" generates unused classes full\n * of random bytecode. This is copy-pasted from radon 2 -- no need to rewrite.\n *\n * @author ItzSomebody\n */\npublic class AddTrashClasses extends Transformer {\n    private static ArrayList<String> DESCRIPTORS = new ArrayList<>();\n\n    @JsonProperty(\"dictionary\")\n    private Dictionary dictionary = DictionaryFactory.defaultDictionary();\n\n    @JsonProperty(\"number_of_trash_classes\")\n    private int nTrashClasses;\n\n    static {\n        DESCRIPTORS.add(\"Z\");\n        DESCRIPTORS.add(\"C\");\n        DESCRIPTORS.add(\"B\");\n        DESCRIPTORS.add(\"S\");\n        DESCRIPTORS.add(\"I\");\n        DESCRIPTORS.add(\"F\");\n        DESCRIPTORS.add(\"J\");\n        DESCRIPTORS.add(\"D\");\n        DESCRIPTORS.add(\"V\");\n    }\n\n    @Override\n    public void transform() {\n        ArrayList<String> classNames = new ArrayList<>(classPathMap().keySet());\n        for (int i = 0; i < classNames.size() % 20; i++) {\n            DESCRIPTORS.add(\"L\" + classNames.get(RandomUtils.randomInt(classNames.size())) + \";\");\n        }\n\n        for (int i = 0; i < nTrashClasses; i++) {\n            var classNode = generateClass();\n            var cw = new ClassWriter(0);\n            cw.newUTF8(\"RADON\" + RadonConstants.VERSION);\n            classNode.accept(cw);\n\n            resourceMap().put(classNode.name + \".class\", cw.toByteArray());\n        }\n\n        RadonLogger.info(String.format(\"Generated %d trash classes.\", nTrashClasses));\n    }\n\n    private ClassNode generateClass() {\n        ClassNode classNode = createClass(fakeSubClass());\n        int methodsToGenerate = RandomUtils.randomInt(3) + 2;\n\n        for (int i = 0; i < methodsToGenerate; i++)\n            classNode.methods.add(methodGen());\n\n        return classNode;\n    }\n\n    private ClassNode createClass(String className) {\n        ClassNode classNode = new ClassNode();\n        classNode.visit(49, ACC_SUPER + ACC_PUBLIC, className, null, \"java/lang/Object\", null);\n\n        var mv = classNode.visitMethod(ACC_PUBLIC, \"<init>\", \"()V\", null, null);\n        mv.visitCode();\n        mv.visitVarInsn(ALOAD, 0);\n        mv.visitMethodInsn(INVOKESPECIAL, \"java/lang/Object\", \"<init>\", \"()V\", false);\n        mv.visitInsn(RETURN);\n        mv.visitMaxs(1, 1);\n        mv.visitEnd();\n\n        classNode.visitEnd();\n\n        return classNode;\n    }\n\n    private MethodNode methodGen() {\n        String randDesc = descGen();\n        MethodNode method = new MethodNode(ACC_STATIC + ACC_PRIVATE, dictionary.next(), randDesc, null, null);\n        int instructions = RandomUtils.randomInt(30) + 30;\n\n        InsnList insns = new InsnList();\n\n        for (int i = 0; i < instructions; ++i) {\n            insns.add(junkInstructions());\n        }\n\n        Type returnType = Type.getReturnType(randDesc);\n        switch (returnType.getSort()) {\n            case Type.VOID:\n                insns.add(new InsnNode(RETURN));\n                break;\n            case Type.BOOLEAN:\n            case Type.CHAR:\n            case Type.BYTE:\n            case Type.SHORT:\n            case Type.INT:\n                if (RandomUtils.randomInt(10) % 2 == 1)\n                    insns.add(new InsnNode(ICONST_0));\n                else\n                    insns.add(new InsnNode(ICONST_1));\n\n                insns.add(new InsnNode(IRETURN));\n                break;\n            case Type.FLOAT:\n                insns.add(ASMUtils.getNumberInsn(RandomUtils.randomFloat()));\n                insns.add(new InsnNode(FRETURN));\n                break;\n            case Type.LONG:\n                insns.add(ASMUtils.getNumberInsn(RandomUtils.randomLong()));\n                insns.add(new InsnNode(LRETURN));\n                break;\n            case Type.DOUBLE:\n                insns.add(ASMUtils.getNumberInsn(RandomUtils.randomDouble()));\n                insns.add(new InsnNode(DRETURN));\n                break;\n            default:\n                insns.add(new VarInsnNode(ALOAD, RandomUtils.randomInt(30)));\n                insns.add(new InsnNode(ARETURN));\n                break;\n        }\n\n        method.instructions = insns;\n        return method;\n    }\n\n    private String descGen() {\n        StringBuilder sb = new StringBuilder(\"(\");\n\n        for (int i = 0; i < RandomUtils.randomInt(7); i++)\n            sb.append(DESCRIPTORS.get(RandomUtils.randomInt(DESCRIPTORS.size())));\n\n        sb.append(\")\");\n        sb.append(DESCRIPTORS.get(RandomUtils.randomInt(DESCRIPTORS.size())));\n\n        return sb.toString();\n    }\n\n    private AbstractInsnNode junkInstructions() {\n        int index = RandomUtils.randomInt(20);\n        switch (index) {\n            case 0:\n                return new MethodInsnNode(INVOKESTATIC, dictionary.next(), dictionary.next(), \"(Ljava/lang/String;)V\", false);\n            case 1:\n                return new FieldInsnNode(GETFIELD, dictionary.next(), dictionary.next(), \"I\");\n            case 2:\n                return new InsnNode(RandomUtils.randomInt(16));\n            case 3:\n                return new VarInsnNode(ALOAD, RandomUtils.randomInt(30));\n            case 4:\n                return new IntInsnNode(BIPUSH, RandomUtils.randomInt(255));\n            case 5:\n                return new IntInsnNode(SIPUSH, RandomUtils.randomInt(25565));\n            case 6:\n            case 7:\n            case 8:\n                return new InsnNode(RandomUtils.randomInt(5));\n            case 9:\n                return new LdcInsnNode(dictionary.next());\n            case 10:\n                return new IincInsnNode(RandomUtils.randomInt(16), RandomUtils.randomInt(16));\n            case 11:\n                return new MethodInsnNode(INVOKESPECIAL, dictionary.next(), dictionary.next(), \"()V\", false);\n            case 12:\n                return new MethodInsnNode(INVOKEVIRTUAL, dictionary.next(), dictionary.next(), \"(Ljava/lang/Object;)Ljava/lang/Object;\", false);\n            case 13:\n                return new VarInsnNode(ILOAD, RandomUtils.randomInt(30));\n            case 14:\n                return new InsnNode(ATHROW);\n            case 15:\n                return new MethodInsnNode(INVOKEINTERFACE, dictionary.next(), dictionary.next(), \"(I)I\", false);\n            case 16:\n                Handle handle = new Handle(6, dictionary.next(), dictionary.next(), dictionary.next(), false);\n                return new InvokeDynamicInsnNode(dictionary.next(), dictionary.next(), handle, RandomUtils.randomInt(5), RandomUtils.randomInt(5), RandomUtils.randomInt(5), RandomUtils.randomInt(5), RandomUtils.randomInt(5));\n            case 17:\n                return new IntInsnNode(ANEWARRAY, RandomUtils.randomInt(30));\n            case 18:\n                return new VarInsnNode(ASTORE, RandomUtils.randomInt(30));\n            case 19:\n            default:\n                return new VarInsnNode(ISTORE, RandomUtils.randomInt(30));\n        }\n    }\n\n    @Override\n    public Exclusion.ExclusionType getExclusionType() {\n        return Exclusion.ExclusionType.ADD_TRASH_CLASSES;\n    }\n\n    @Override\n    public String getConfigName() {\n        return Transformers.ADD_TRASH_CLASSES.getConfigName();\n    }\n}\n"
  },
  {
    "path": "xyz.itzsomebody.radon/src/main/java/xyz/itzsomebody/radon/transformers/misc/AntiDebugger.java",
    "content": "/*\n * Radon - An open-source Java obfuscator\n * Copyright (C) 2021 ItzSomebody\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, either version 3 of the License, or\n * (at your option) any later version.\n *\n * This program is distributed in the hope that it will be 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.  If not, see <http://www.gnu.org/licenses/>\n */\n\npackage xyz.itzsomebody.radon.transformers.misc;\n\nimport com.fasterxml.jackson.annotation.JsonProperty;\nimport org.objectweb.asm.tree.InsnList;\nimport org.objectweb.asm.tree.MethodNode;\nimport xyz.itzsomebody.codegen.BytecodeBlock;\nimport xyz.itzsomebody.codegen.WrappedType;\nimport xyz.itzsomebody.codegen.expressions.IRExpression;\nimport xyz.itzsomebody.radon.exclusions.Exclusion;\nimport xyz.itzsomebody.radon.transformers.Transformer;\nimport xyz.itzsomebody.radon.transformers.Transformers;\nimport xyz.itzsomebody.radon.utils.RandomUtils;\nimport xyz.itzsomebody.radon.utils.logging.RadonLogger;\n\nimport java.io.PrintStream;\nimport java.lang.management.ManagementFactory;\nimport java.lang.management.RuntimeMXBean;\nimport java.util.Collections;\nimport java.util.List;\nimport java.util.concurrent.atomic.AtomicInteger;\n\nimport static xyz.itzsomebody.codegen.expressions.IRExpressions.*;\n\n/**\n * Blocks debugging options on the commandline.\n *\n * @author vovanre\n * @author itzsomebody\n */\n/*\n * Note from itzsomebody: this is *really, really* easy to remove and/or bypass; however, I don't really want to\n * vest much time in anti-debugging. So as a result, I turned this into a production test of the codegen. :PP\n */\npublic class AntiDebugger extends Transformer {\n    private static final String[] DEBUG_OPTIONS = new String[]{\"-agentlib:jdwp\", \"-Xdebug\", \"-Xrunjdwp:\", \"-javaagent:\"};\n    @JsonProperty(\"message\")\n    private String message = \"java.lang.NullPointerException\"; // lul\n    private AtomicInteger debugOptionIndex;\n\n    @Override\n    public void transform() {\n        var counter = new AtomicInteger();\n        debugOptionIndex = new AtomicInteger();\n\n        classes().stream().filter(cw -> !cw.isInterface() && notExcluded(cw)).forEach(cw -> {\n            var clinit = cw.getMethodNode(\"<clinit>\", \"()V\");\n            if (clinit == null) {\n                clinit = new MethodNode(ACC_PRIVATE | ACC_STATIC, \"<clinit>\", \"()V\", null, null);\n                clinit.visitInsn(RETURN);\n                cw.addMethod(clinit);\n            }\n\n            var checkCount = RandomUtils.randomInt(1, DEBUG_OPTIONS.length);\n            for (int i = 0; i < checkCount; i++) {\n                clinit.instructions.insert(generateCheck());\n                counter.incrementAndGet();\n            }\n        });\n\n        RadonLogger.info(\"Injected \" + counter.get() + \" anti-debugger checks\");\n    }\n\n    private InsnList generateCheck() {\n        var trueBlock = new BytecodeBlock();\n        if (RandomUtils.randomBoolean()) {\n            trueBlock.append(getStatic(\n                    WrappedType.from(System.class),\n                    \"out\",\n                    WrappedType.from(PrintStream.class)\n            ).invoke(\n                    \"println\",\n                    List.of(WrappedType.from(String.class)),\n                    WrappedType.from(void.class),\n                    stringConst(message)\n            ).getInstructions());\n            if (RandomUtils.randomBoolean()) {\n                trueBlock.append(invokeStatic(\n                        WrappedType.from(System.class),\n                        \"exit\",\n                        List.of(intConst(RandomUtils.randomInt())),\n                        List.of(WrappedType.from(int.class)),\n                        WrappedType.from(void.class)\n                ).getInstructions());\n            } else {\n                trueBlock.append(invokeStatic(\n                        WrappedType.from(Runtime.class),\n                        \"getRuntime\",\n                        Collections.emptyList(),\n                        Collections.emptyList(),\n                        WrappedType.from(Runtime.class)\n                ).invoke(\n                        \"halt\",\n                        List.of(WrappedType.from(int.class)),\n                        WrappedType.from(void.class),\n                        intConst(RandomUtils.randomInt())\n                ).getInstructions());\n            }\n        } else {\n            trueBlock.append(newInstance(\n                    WrappedType.from(RuntimeException.class),\n                    List.of(WrappedType.from(String.class)),\n                    List.of(stringConst(message))\n            ).throwMe().getInstructions());\n        }\n\n        return ifBlock(\n                isDebugExpression().getInstructions(),\n                trueBlock,\n                new BytecodeBlock()\n        ).getInstructions().compile();\n    }\n\n    private IRExpression isDebugExpression() {\n        var isUpper = RandomUtils.randomBoolean();\n        var argument = DEBUG_OPTIONS[debugOptionIndex.incrementAndGet() % DEBUG_OPTIONS.length];\n        argument = isUpper ? argument.toUpperCase() : argument.toLowerCase();\n\n        var getArguments = invokeVirtual(\n                invokeVirtual(\n                        invokeVirtual(\n                                invokeStatic(WrappedType.from(ManagementFactory.class), \"getRuntimeMXBean\", Collections.emptyList(), Collections.emptyList(), WrappedType.from(RuntimeMXBean.class)),\n                                WrappedType.from(RuntimeMXBean.class),\n                                \"getInputArguments\",\n                                Collections.emptyList(),\n                                Collections.emptyList(),\n                                WrappedType.from(List.class)\n                        ),\n                        WrappedType.from(Object.class),\n                        \"toString\",\n                        Collections.emptyList(),\n                        Collections.emptyList(),\n                        WrappedType.from(String.class)\n                ),\n                WrappedType.from(String.class),\n                isUpper ? \"toUpperCase\" : \"toLowerCase\",\n                Collections.emptyList(),\n                Collections.emptyList(),\n                WrappedType.from(String.class)\n        );\n        return invokeVirtual(\n                getArguments,\n                WrappedType.from(String.class),\n                \"contains\",\n                List.of(stringConst(argument)),\n                List.of(WrappedType.from(CharSequence.class)),\n                WrappedType.from(boolean.class)\n        );\n    }\n\n    @Override\n    public Exclusion.ExclusionType getExclusionType() {\n        return Exclusion.ExclusionType.INJECT_ANTI_DEBUGGER;\n    }\n\n    @Override\n    public String getConfigName() {\n        return Transformers.INJECT_ANTI_DEBUGGER.getConfigName();\n    }\n}\n"
  },
  {
    "path": "xyz.itzsomebody.radon/src/main/java/xyz/itzsomebody/radon/transformers/misc/ExpirationKillSwitch.java",
    "content": "/*\n * Radon - An open-source Java obfuscator\n * Copyright (C) 2021 ItzSomebody\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, either version 3 of the License, or\n * (at your option) any later version.\n *\n * This program is distributed in the hope that it will be 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.  If not, see <http://www.gnu.org/licenses/>\n */\n\npackage xyz.itzsomebody.radon.transformers.misc;\n\nimport com.fasterxml.jackson.annotation.JsonProperty;\nimport org.objectweb.asm.tree.InsnList;\nimport xyz.itzsomebody.codegen.BytecodeBlock;\nimport xyz.itzsomebody.codegen.WrappedType;\nimport xyz.itzsomebody.radon.exceptions.PreventableRadonException;\nimport xyz.itzsomebody.radon.exclusions.Exclusion;\nimport xyz.itzsomebody.radon.transformers.Transformer;\nimport xyz.itzsomebody.radon.transformers.Transformers;\nimport xyz.itzsomebody.radon.utils.RandomUtils;\nimport xyz.itzsomebody.radon.utils.logging.RadonLogger;\n\nimport javax.swing.*;\nimport java.awt.*;\nimport java.text.ParseException;\nimport java.text.SimpleDateFormat;\nimport java.util.Collections;\nimport java.util.Date;\nimport java.util.List;\nimport java.util.concurrent.atomic.AtomicInteger;\n\nimport static xyz.itzsomebody.codegen.expressions.IRExpressions.*;\n\n/**\n * Inserts an expiration block of instructions in each constructor method.\n *\n * @author itzsomebody\n */\n/*\n * Another really easy thing to patch out. So I also turned this into a production test of codegen.\n */\npublic class ExpirationKillSwitch extends Transformer {\n    private static final Class<?>[] EXCEPTIONS = {\n            Throwable.class,\n            Exception.class,\n            RuntimeException.class,\n            NullPointerException.class,\n            IllegalArgumentException.class,\n            IllegalStateException.class\n    };\n\n    @JsonProperty(\"message\")\n    private String message = \"tucks\";\n\n    private long expirationTime;\n\n    @JsonProperty(\"inject_joption_pane\")\n    private boolean injectJOptionPane;\n\n    @JsonProperty(\"expiration_time\")\n    public void setExpirationTime(String date) {\n        try {\n            expirationTime = new SimpleDateFormat(\"MM/dd/yyyy\").parse(date).getTime();\n        } catch (ParseException e) {\n            throw new PreventableRadonException(\"Error parsing \" + date + \" into format MM/dd/yyyy: (\" + e.getMessage() + \", offset=\" + e.getErrorOffset() + \")\");\n        }\n    }\n\n    @Override\n    public void transform() {\n        var counter = new AtomicInteger();\n        classes().stream().filter(this::notExcluded).forEach(cw -> {\n            cw.methodStream().filter(mw -> notExcluded(mw) && mw.getMethodNode().name.startsWith(\"<\")).forEach(mw -> {\n                mw.getMethodNode().instructions.insert(generateExpirationCode());\n                counter.incrementAndGet();\n            });\n        });\n        RadonLogger.info(\"Added \" + counter.get() + \" expiration code blocks\");\n    }\n\n    // For reference\n    private static void example() {\n        // replace 0L with time and \"tucks\" with message\n        if (new Date().after(new Date(0L))) {\n            JOptionPane.showMessageDialog(null, \"tucks\");\n            throw new RuntimeException(\"tucks\");\n        }\n    }\n\n    private InsnList generateExpirationCode() {\n        var condition = new BytecodeBlock()\n                .append(\n                        newInstance(\n                                WrappedType.from(Date.class),\n                                Collections.emptyList(),\n                                Collections.emptyList()\n                        ).invoke(\n                                \"after\",\n                                List.of(WrappedType.from(Date.class)),\n                                WrappedType.from(boolean.class),\n                                newInstance(\n                                        WrappedType.from(Date.class),\n                                        List.of(WrappedType.from(long.class)),\n                                        List.of(longConst(expirationTime))\n                                )\n                        ).getInstructions()\n                );\n\n        var trueBlock = new BytecodeBlock();\n        if (injectJOptionPane) {\n            trueBlock.append(invokeStatic(\n                    WrappedType.from(JOptionPane.class),\n                    \"showMessageDialog\",\n                    List.of(nullConst(Component.class), stringConst(message)),\n                    List.of(WrappedType.from(Component.class), WrappedType.from(Object.class)),\n                    WrappedType.from(void.class)\n            ).getInstructions());\n        }\n        trueBlock.append(newInstance(\n                WrappedType.from(EXCEPTIONS[RandomUtils.randomInt(EXCEPTIONS.length)]),\n                List.of(WrappedType.from(String.class)),\n                List.of(stringConst(message))\n        ).throwMe().getInstructions());\n\n        return ifBlock(condition, trueBlock, new BytecodeBlock()).getInstructions().compile();\n    }\n\n    @Override\n    public Exclusion.ExclusionType getExclusionType() {\n        return Exclusion.ExclusionType.INJECT_EXPIRATION_KILL_SWITCH;\n    }\n\n    @Override\n    public String getConfigName() {\n        return Transformers.INJECT_EXPIRATION_KILL_SWITCH.getConfigName();\n    }\n}\n"
  },
  {
    "path": "xyz.itzsomebody.radon/src/main/java/xyz/itzsomebody/radon/transformers/misc/Packer.java",
    "content": "/*\n * Radon - An open-source Java obfuscator\n * Copyright (C) 2021 ItzSomebody\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, either version 3 of the License, or\n * (at your option) any later version.\n *\n * This program is distributed in the hope that it will be 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.  If not, see <http://www.gnu.org/licenses/>\n */\n\npackage xyz.itzsomebody.radon.transformers.misc;\n\npublic class Packer {\n}\n"
  },
  {
    "path": "xyz.itzsomebody.radon/src/main/java/xyz/itzsomebody/radon/transformers/misc/Renamer.java",
    "content": "/*\n * Radon - An open-source Java obfuscator\n * Copyright (C) 2021 ItzSomebody\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, either version 3 of the License, or\n * (at your option) any later version.\n *\n * This program is distributed in the hope that it will be 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.  If not, see <http://www.gnu.org/licenses/>\n */\n\npackage xyz.itzsomebody.radon.transformers.misc;\n\nimport com.fasterxml.jackson.annotation.JsonProperty;\nimport org.objectweb.asm.commons.ClassRemapper;\nimport org.objectweb.asm.tree.ClassNode;\nimport xyz.itzsomebody.radon.Radon;\nimport xyz.itzsomebody.radon.RadonConstants;\nimport xyz.itzsomebody.radon.config.ConfigurationParser;\nimport xyz.itzsomebody.radon.dictionaries.Dictionary;\nimport xyz.itzsomebody.radon.dictionaries.DictionaryFactory;\nimport xyz.itzsomebody.radon.exclusions.Exclusion;\nimport xyz.itzsomebody.radon.transformers.Transformer;\nimport xyz.itzsomebody.radon.transformers.Transformers;\nimport xyz.itzsomebody.radon.utils.IOUtils;\nimport xyz.itzsomebody.radon.utils.RandomUtils;\nimport xyz.itzsomebody.radon.utils.asm.ClassWrapper;\nimport xyz.itzsomebody.radon.utils.asm.FieldWrapper;\nimport xyz.itzsomebody.radon.utils.asm.MethodWrapper;\nimport xyz.itzsomebody.radon.utils.asm.RadonRemapper;\nimport xyz.itzsomebody.radon.utils.logging.RadonLogger;\n\nimport java.io.BufferedWriter;\nimport java.io.File;\nimport java.io.FileWriter;\nimport java.io.IOException;\nimport java.nio.charset.StandardCharsets;\nimport java.util.*;\nimport java.util.stream.IntStream;\n\npublic class Renamer extends Transformer {\n    @JsonProperty(\"resources_to_adapt\")\n    private List<String> resourceToAdapt = Collections.emptyList();\n\n    @JsonProperty(\"dump_mappings\")\n    private boolean dumpMappings;\n\n    @JsonProperty(\"repackaging_prefix\")\n    private String repackagingPrefix;\n\n    @JsonProperty(\"class_name_dictionary\")\n    private Dictionary classNameDictionary = DictionaryFactory.defaultDictionary();\n\n    @JsonProperty(\"method_name_dictionary\")\n    private Dictionary methodNameDictionary = DictionaryFactory.defaultDictionary();\n\n    @JsonProperty(\"field_name_dictionary\")\n    private Dictionary fieldNameDictionary = DictionaryFactory.defaultDictionary();\n    private final Map<String, String> mappings = new HashMap<>();\n\n    @Override\n    public void transform() {\n        RadonLogger.info(\"Building inheritance hierarchy graph\");\n        long current = System.currentTimeMillis();\n        Radon.getInstance().buildHierarchyGraph();\n        RadonLogger.info(String.format(\"Finished building inheritance graph [%dms]\", (System.currentTimeMillis() - current)));\n\n        RadonLogger.info(\"Generating mappings\");\n        current = System.currentTimeMillis();\n        generateMappings();\n        RadonLogger.info(String.format(\"Finished generating mappings [%dms]\", (System.currentTimeMillis() - current)));\n\n        RadonLogger.info(\"Applying mappings\");\n        current = System.currentTimeMillis();\n        applyMappings();\n        RadonLogger.info(String.format(\"Finished applying mappings [%dms]\", (System.currentTimeMillis() - current)));\n\n        RadonLogger.info(\"Adapting resources\");\n        current = System.currentTimeMillis();\n        adaptResources();\n        RadonLogger.info(String.format(\"Finished adapting resources [%dms]\", (System.currentTimeMillis() - current)));\n\n        if (dumpMappings) {\n            RadonLogger.info(\"Dumping mappings\");\n            dumpMappings();\n        }\n    }\n\n    private void generateMappings() {\n        classes().forEach(classWrapper -> {\n            classWrapper.methodStream().filter(methodWrapped -> !cannotRenameMethod(classWrapper, methodWrapped, new HashSet<>())).forEach(methodWrapper -> {\n                String newName;\n                do {\n                    newName = methodNameDictionary.next();\n                } while (mappings.containsKey(classWrapper.getOriginalName() + '.' + methodWrapper.getOriginalName() + methodWrapper.getOriginalDescriptor())\n                        && mappings.get(classWrapper.getOriginalName() + '.' + methodWrapper.getOriginalName() + methodWrapper.getOriginalDescriptor()).equals(newName));\n\n\n                generateMethodMappings(classWrapper, methodWrapper, newName);\n                for (var mapping : mappings.keySet()) {\n                    if (mapping.startsWith(\"java/util/List.size\") && mappings.get(mapping).contains(\"Cx\")) {\n                        System.out.println(\"Working on \" + classWrapper.getName() + '.' + methodWrapper.getOriginalName() + methodWrapper.getOriginalDescriptor() + \": \" + mapping + \" -> \" + mappings.get(mapping));\n                        break;\n                    }\n                }\n            });\n            classWrapper.fieldStream().filter(fieldWrapper -> !cannotRenameField(classWrapper, fieldWrapper)).forEach(fieldWrapper -> {\n                String newName;\n                do {\n                    newName = fieldNameDictionary.next();\n                } while (mappings.containsKey(classWrapper.getOriginalName() + '.' + fieldWrapper.getOriginalName() + ' ' + fieldWrapper.getOriginalType())\n                        && mappings.get(classWrapper.getOriginalName() + '.' + fieldWrapper.getOriginalName() + ' ' + fieldWrapper.getOriginalType()).equals(newName));\n\n\n                generateFieldMappings(classWrapper, fieldWrapper, newName);\n            });\n\n            if (notExcluded(classWrapper)) {\n                if (repackagingPrefix == null) {\n                    repackagingPrefix = classNameDictionary.copy().randomStr(RandomUtils.randomInt(0xF));\n                }\n\n                var newName = repackagingPrefix;\n                if (!newName.isEmpty()) {\n                    newName += '/';\n                }\n                String temp;\n                do {\n                    temp = newName + classNameDictionary.next();\n                } while (classPathMap().containsKey(temp)); // Important to check classpath instead of input classes\n                newName = temp;\n\n                mappings.put(classWrapper.getOriginalName(), newName);\n            }\n        });\n    }\n\n    private boolean cannotRenameMethod(ClassWrapper classWrapper, MethodWrapper wrapper, Set<ClassWrapper> visited) {\n        // Already visited so don't check\n        if (!visited.add(classWrapper)) {\n            return false;\n        }\n\n        // If excluded, we don't want to rename.\n        // If we already mapped the tree, we don't want to waste time doing it again.\n        if (!notExcluded(classWrapper.getOriginalName() + '.' + wrapper.getOriginalName() + wrapper.getOriginalDescriptor()) || mappings.containsKey(classWrapper.getOriginalName() + '.' + wrapper.getOriginalName() + wrapper.getOriginalDescriptor())) {\n            return true;\n        }\n\n        // Native and main/premain methods should not be renamed\n        // Init and clinit methods should also not be renamed (otherwise the jvm will get mad)\n        if (wrapper.isNative() || wrapper.getOriginalName().equals(\"main\") || wrapper.getOriginalName().equals(\"premain\") || wrapper.getOriginalName().startsWith(\"<\")) {\n            return true;\n        }\n\n        // Static methods are never inherited\n        if (wrapper.isStatic()) {\n            // Renaming these particular enum methods will cause problems\n            return classWrapper.isEnum()\n                    && (wrapper.getOriginalName().equals(\"valueOf\") || wrapper.getOriginalName().equals(\"values\"));\n        } else {\n            if (classWrapper.getOriginalName().startsWith(\"java/util\")) {\n                System.out.println(\"Checking \" + classWrapper.getOriginalName() + '.' + wrapper.getOriginalName() + wrapper.getOriginalDescriptor());\n            }\n            // Methods which override or inherit from external libs cannot be renamed\n            if (classWrapper != wrapper.getOwner() && classWrapper.isLibraryNode()\n                    && classWrapper.methodStream().anyMatch(other -> other.getOriginalName().equals(wrapper.getOriginalName())\n                    && other.getOriginalDescriptor().equals(wrapper.getOriginalDescriptor()))) {\n                return true;\n            }\n\n            // Children are checked for exclusions\n            // Parents are checked for exclusions and if they are library nodes\n            return classWrapper.getParents().stream().anyMatch(parent -> cannotRenameMethod(parent, wrapper, visited))\n                    || classWrapper.getChildren().stream().anyMatch(child -> cannotRenameMethod(child, wrapper, visited));\n        }\n    }\n\n    private void generateMethodMappings(ClassWrapper owner, MethodWrapper wrapper, String newName) {\n        String key = owner.getOriginalName() + '.' + wrapper.getOriginalName() + wrapper.getOriginalDescriptor();\n\n        // This (supposedly) will prevent an infinite recursion because the tree was already renamed\n        if (mappings.containsKey(key)) {\n            return;\n        }\n        mappings.put(key, newName);\n\n        if (!wrapper.isStatic()) { //  Static methods cannot be overriden\n            owner.getParents().forEach(parent -> generateMethodMappings(parent, wrapper, newName));\n            owner.getChildren().forEach(child -> generateMethodMappings(child, wrapper, newName));\n        }\n    }\n\n    private boolean cannotRenameField(ClassWrapper classWrapper, FieldWrapper wrapper) {\n        if (!notExcluded(wrapper) || mappings.containsKey(classWrapper.getOriginalName() + '.' + wrapper.getOriginalName() + ' ' + wrapper.getOriginalType())) {\n            return true;\n        }\n\n        return classWrapper.isEnum(); // Todo: enums are a pain to handle\n    }\n\n    private void generateFieldMappings(ClassWrapper owner, FieldWrapper wrapper, String newName) {\n        String key = owner.getOriginalName() + '.' + wrapper.getOriginalName() + ' ' + wrapper.getOriginalType();\n\n        // This (supposedly) will prevent an infinite recursion because the tree was already renamed\n        if (mappings.containsKey(key)) {\n            return;\n        }\n        mappings.put(key, newName);\n\n        if (!wrapper.isStatic()) { //  Static fields cannot be inherited\n            owner.getParents().forEach(parent -> generateFieldMappings(parent, wrapper, newName));\n            owner.getChildren().forEach(child -> generateFieldMappings(child, wrapper, newName));\n        }\n    }\n\n    private void applyMappings() {\n        var remapper = new RadonRemapper(mappings);\n        new ArrayList<>(classes()).forEach(classWrapper -> {\n            var classNode = classWrapper.getClassNode();\n            var copy = new ClassNode();\n            classNode.accept(new ClassRemapper(copy, remapper));\n\n            // In order to preserve the original names to prevent exclusions from breaking,\n            // we update the MethodNode/FieldNode/ClassNode each wrapper wraps instead.\n            IntStream.range(0, copy.methods.size()).forEach(i -> {\n                classWrapper.getMethods().get(i).setMethodNode(copy.methods.get(i));\n            });\n            IntStream.range(0, copy.fields.size()).forEach(i -> {\n                classWrapper.getFields().get(i).setFieldNode(copy.fields.get(i));\n            });\n            classWrapper.setClassNode(copy);\n\n            // Fix input/classpath classnames\n            classMap().remove(classWrapper.getOriginalName());\n            classPathMap().remove(classWrapper.getOriginalName());\n            classMap().put(copy.name, classWrapper);\n            classPathMap().put(copy.name, classWrapper);\n        });\n    }\n\n    private void adaptResources() {\n        resourceToAdapt.forEach(resourceName -> {\n            var resourceBytes = resourceMap().get(resourceName);\n            if (resourceBytes == null) {\n                RadonLogger.warn(\"Attempted to adapt nonexistent resource: \" + resourceName);\n            }\n\n            var stringVer = new String(resourceBytes, StandardCharsets.UTF_8);\n            for (var original : mappings.keySet()) {\n                if (stringVer.contains(original.replace(\"/\", \".\"))) {\n                    if (resourceName.equals(\"META-INF/MANIFEST.MF\")\n                            || resourceName.equals(\"plugin.yml\")\n                            || resourceName.equals(\"bungee.yml\")) {\n                        stringVer = stringVer.replaceAll(\"(?<=[: ])\" + original.replace(\"/\", \".\"), mappings.get(original)).replace(\"/\", \".\");\n                    } else {\n                        stringVer = stringVer.replace(original.replace(\"/\", \".\"), mappings.get(original)).replace(\"/\", \".\");\n                    }\n                }\n            }\n            resourceMap().put(resourceName, stringVer.getBytes(StandardCharsets.UTF_8));\n        });\n    }\n\n    private void dumpMappings() {\n        var file = new File(\"mappings.txt\");\n        if (file.exists()) {\n            IOUtils.renameExistingFile(file);\n        }\n\n        try {\n            file.createNewFile();\n            var bw = new BufferedWriter(new FileWriter(file));\n            mappings.forEach((oldName, newName) -> {\n                try {\n                    bw.append(oldName).append(\" -> \").append(newName).append(\"\\n\");\n                } catch (IOException ioe) {\n                    RadonLogger.warn(String.format(\"Caught IOException while attempting to write line \\\"%s -> %s\\\"\", oldName, newName));\n                    if (RadonConstants.VERBOSE) {\n                        ioe.printStackTrace(System.out);\n                    }\n                }\n            });\n        } catch (Throwable t) {\n            RadonLogger.warn(\"Captured throwable upon attempting to generate mappings file: \" + t.getMessage());\n            if (RadonConstants.VERBOSE) {\n                t.printStackTrace(System.out);\n            }\n        }\n    }\n\n    @Override\n    public Exclusion.ExclusionType getExclusionType() {\n        return Exclusion.ExclusionType.RENAMER;\n    }\n\n    @Override\n    public String getConfigName() {\n        return Transformers.RENAMER.getConfigName();\n    }\n}\n"
  },
  {
    "path": "xyz.itzsomebody.radon/src/main/java/xyz/itzsomebody/radon/transformers/misc/ResourceRenamer.java",
    "content": "/*\n * Radon - An open-source Java obfuscator\n * Copyright (C) 2021 ItzSomebody\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, either version 3 of the License, or\n * (at your option) any later version.\n *\n * This program is distributed in the hope that it will be 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.  If not, see <http://www.gnu.org/licenses/>\n */\n\npackage xyz.itzsomebody.radon.transformers.misc;\n\nimport com.fasterxml.jackson.annotation.JsonProperty;\nimport org.objectweb.asm.tree.ClassNode;\nimport xyz.itzsomebody.radon.config.ConfigurationParser;\nimport xyz.itzsomebody.radon.dictionaries.Dictionary;\nimport xyz.itzsomebody.radon.dictionaries.DictionaryFactory;\nimport xyz.itzsomebody.radon.exclusions.Exclusion;\nimport xyz.itzsomebody.radon.transformers.Transformer;\nimport xyz.itzsomebody.radon.transformers.Transformers;\nimport xyz.itzsomebody.radon.utils.asm.ResourceNameRemapper;\nimport xyz.itzsomebody.radon.utils.logging.RadonLogger;\n\nimport java.util.ArrayList;\nimport java.util.HashMap;\nimport java.util.Map;\n\npublic class ResourceRenamer extends Transformer {\n    private final Map<String, String> mappings = new HashMap<>();\n\n    @JsonProperty\n    private Dictionary dictionary = DictionaryFactory.defaultDictionary();\n\n    @Override\n    public void transform() {\n        RadonLogger.info(\"Generating mappings\");\n        long current = System.currentTimeMillis();\n        generateMappings();\n        RadonLogger.info(String.format(\"Finished generating mappings [%dms]\", (System.currentTimeMillis() - current)));\n\n        RadonLogger.info(\"Applying mappings\");\n        current = System.currentTimeMillis();\n        applyMappings();\n        RadonLogger.info(String.format(\"Finished applying mappings [%dms]\", (System.currentTimeMillis() - current)));\n    }\n\n    private void generateMappings() {\n        resourceMap().keySet().stream().filter(this::notExcluded).forEach(resourceName -> {\n            String newName;\n            do {\n                newName = dictionary.next();\n            } while (resourceMap().containsKey(newName));\n\n            mappings.put(resourceName, newName);\n        });\n    }\n\n    private void applyMappings() {\n        new ArrayList<>(classes()).forEach(classWrapper -> {\n            var classNode = classWrapper.getClassNode();\n            var copy = new ClassNode();\n            classNode.accept(new ResourceNameRemapper(copy, mappings, classWrapper.getName()));\n            classWrapper.setClassNode(copy);\n        });\n    }\n\n    @Override\n    public Exclusion.ExclusionType getExclusionType() {\n        return Exclusion.ExclusionType.RESOURCE_RENAMER;\n    }\n\n    @Override\n    public String getConfigName() {\n        return Transformers.RESOURCE_RENAMER.getConfigName();\n    }\n}\n"
  },
  {
    "path": "xyz.itzsomebody.radon/src/main/java/xyz/itzsomebody/radon/transformers/misc/ScrambleLineNumbers.java",
    "content": "/*\n * Radon - An open-source Java obfuscator\n * Copyright (C) 2021 ItzSomebody\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, either version 3 of the License, or\n * (at your option) any later version.\n *\n * This program is distributed in the hope that it will be 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.  If not, see <http://www.gnu.org/licenses/>\n */\n\npackage xyz.itzsomebody.radon.transformers.misc;\n\nimport com.fasterxml.jackson.annotation.JsonProperty;\nimport org.objectweb.asm.tree.LineNumberNode;\nimport xyz.itzsomebody.radon.exclusions.Exclusion;\nimport xyz.itzsomebody.radon.transformers.Transformer;\nimport xyz.itzsomebody.radon.transformers.Transformers;\nimport xyz.itzsomebody.radon.utils.RandomUtils;\nimport xyz.itzsomebody.radon.utils.logging.RadonLogger;\n\nimport java.util.concurrent.atomic.AtomicInteger;\n\npublic class ScrambleLineNumbers extends Transformer {\n    @JsonProperty(\"random_origin\")\n    private int origin;\n\n    @JsonProperty(\"random_bound\")\n    private int bound;\n\n    @Override\n    public void transform() {\n        var count = new AtomicInteger();\n        classes().stream().filter(this::notExcluded).forEach(cw -> {\n            cw.methodStream().filter(this::notExcluded).forEach(mw -> {\n                mw.getMethodNode().instructions.forEach(insn -> {\n                    if (insn instanceof LineNumberNode) {\n                        ((LineNumberNode) insn).line = RandomUtils.randomInt(origin, bound);\n                        count.incrementAndGet();\n                    }\n                });\n            });\n        });\n        RadonLogger.info(\"Scrambled \" + count.get() + \" lines\");\n    }\n\n    @Override\n    public Exclusion.ExclusionType getExclusionType() {\n        return Exclusion.ExclusionType.SCRAMBLE_LINE_NUMBERS;\n    }\n\n    @Override\n    public String getConfigName() {\n        return Transformers.SCRAMBLE_LINE_NUMBERS.getConfigName();\n    }\n}\n"
  },
  {
    "path": "xyz.itzsomebody.radon/src/main/java/xyz/itzsomebody/radon/transformers/misc/ShuffleMembers.java",
    "content": "/*\n * Radon - An open-source Java obfuscator\n * Copyright (C) 2021 ItzSomebody\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, either version 3 of the License, or\n * (at your option) any later version.\n *\n * This program is distributed in the hope that it will be 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.  If not, see <http://www.gnu.org/licenses/>\n */\n\npackage xyz.itzsomebody.radon.transformers.misc;\n\nimport com.fasterxml.jackson.annotation.JsonProperty;\nimport xyz.itzsomebody.radon.exclusions.Exclusion;\nimport xyz.itzsomebody.radon.transformers.Transformer;\nimport xyz.itzsomebody.radon.transformers.Transformers;\nimport xyz.itzsomebody.radon.utils.logging.RadonLogger;\n\nimport java.util.Collections;\nimport java.util.concurrent.atomic.AtomicInteger;\n\npublic class ShuffleMembers extends Transformer {\n    @JsonProperty(\"shuffle_methods\")\n    private boolean shuffleMethods;\n\n    @JsonProperty(\"shuffle_fields\")\n    private boolean shuffleFields;\n\n    @Override\n    public void transform() {\n        if (shuffleFields || shuffleMethods) {\n            var count = new AtomicInteger();\n            classes().stream().filter(this::notExcluded).forEach(cw -> {\n                // FIXME: Also update list of method/field wrappers\n                if (shuffleMethods) {\n                    Collections.shuffle(cw.getClassNode().methods);\n                    count.addAndGet(cw.getMethods().size());\n                }\n                if (shuffleFields) {\n                    Collections.shuffle(cw.getClassNode().fields);\n                    count.addAndGet(cw.getFields().size());\n                }\n            });\n            RadonLogger.info(\"Shuffled \" + count.get() + \" members\");\n        }\n    }\n\n    @Override\n    public Exclusion.ExclusionType getExclusionType() {\n        return Exclusion.ExclusionType.SHUFFLE_MEMBERS;\n    }\n\n    @Override\n    public String getConfigName() {\n        return Transformers.SHUFFLE_MEMBERS.getConfigName();\n    }\n}\n"
  },
  {
    "path": "xyz.itzsomebody.radon/src/main/java/xyz/itzsomebody/radon/transformers/misc/Watermarker.java",
    "content": "/*\n * Radon - An open-source Java obfuscator\n * Copyright (C) 2021 ItzSomebody\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, either version 3 of the License, or\n * (at your option) any later version.\n *\n * This program is distributed in the hope that it will be 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.  If not, see <http://www.gnu.org/licenses/>\n */\n\npackage xyz.itzsomebody.radon.transformers.misc;\n\nimport com.fasterxml.jackson.annotation.JsonProperty;\nimport org.objectweb.asm.ClassReader;\nimport org.objectweb.asm.tree.ClassNode;\nimport org.objectweb.asm.tree.InsnList;\nimport org.objectweb.asm.tree.VarInsnNode;\nimport xyz.itzsomebody.commons.MaxLocalsUpdater;\nimport xyz.itzsomebody.commons.matcher.InstructionPattern;\nimport xyz.itzsomebody.commons.matcher.rules.IntConstRule;\nimport xyz.itzsomebody.commons.matcher.rules.OpcodeRule;\nimport xyz.itzsomebody.radon.exceptions.FatalRadonException;\nimport xyz.itzsomebody.radon.exclusions.Exclusion;\nimport xyz.itzsomebody.radon.transformers.Transformer;\nimport xyz.itzsomebody.radon.transformers.Transformers;\nimport xyz.itzsomebody.radon.utils.RandomUtils;\nimport xyz.itzsomebody.radon.utils.asm.ASMUtils;\nimport xyz.itzsomebody.radon.utils.asm.ClassWrapper;\nimport xyz.itzsomebody.radon.utils.asm.MethodWrapper;\nimport xyz.itzsomebody.radon.utils.logging.RadonLogger;\n\nimport java.util.*;\nimport java.util.zip.ZipFile;\n\npublic class Watermarker extends Transformer {\n    @JsonProperty\n    private String message = \"tucks\";\n\n    @JsonProperty\n    private String key = \"ginkoid\";\n\n    @JsonProperty\n    private int copies = 3;\n\n    @Override\n    public void transform() {\n        ArrayList<ClassWrapper> wrappersList = new ArrayList<>(classes());\n\n        for (int i = 0; i < copies; i++) {\n            Deque<Character> cipheredCharacters = cipheredWatermark();\n            while (!cipheredCharacters.isEmpty()) {\n                MethodWrapper wrapper = getInjectableMethod(wrappersList);\n                MaxLocalsUpdater.update(wrapper.getMethodNode());\n\n                wrapper.getMethodNode().instructions.insert(createInstructions(cipheredCharacters, wrapper.getMethodNode().maxLocals));\n                wrapper.getMethodNode().maxLocals += 4;\n            }\n        }\n\n        RadonLogger.info(\"Successfully injected watermark\");\n    }\n\n    private MethodWrapper getInjectableMethod(ArrayList<ClassWrapper> wrappersList) {\n        var missCount = 0;\n        for (; missCount < 20; missCount++) {\n            var wrapper = wrappersList.get(RandomUtils.randomInt(wrappersList.size()));\n\n            if (!wrapper.getMethods().isEmpty()) {\n                var method = wrapper.getMethods().get(RandomUtils.randomInt(wrapper.getMethods().size()));\n\n                if (method.hasInstructions()) {\n                    return method;\n                }\n            }\n        }\n        throw new FatalRadonException(\"Could not find a suitable method to inject watermark into after \" + missCount + \" tries\");\n    }\n\n    private InsnList createInstructions(Deque<Character> ciphered, int offset) {\n        var charXorKey = RandomUtils.randomInt(Character.MAX_VALUE);\n        var xorChar = ciphered.pop() ^ charXorKey;\n        var indexXorKey = RandomUtils.randomInt(Short.MIN_VALUE, Short.MAX_VALUE);\n        var xorIndex = ciphered.size() ^ indexXorKey;\n\n        InsnList instructions = new InsnList();\n        instructions.add(ASMUtils.getNumberInsn(charXorKey));\n        instructions.add(ASMUtils.getNumberInsn(xorChar));\n        instructions.add(ASMUtils.getNumberInsn(indexXorKey));\n        instructions.add(ASMUtils.getNumberInsn(xorIndex));\n\n        instructions.add(new VarInsnNode(ISTORE, offset + 1));\n        instructions.add(new VarInsnNode(ISTORE, offset + 2));\n        instructions.add(new VarInsnNode(ISTORE, offset + 3));\n        instructions.add(new VarInsnNode(ISTORE, offset + 4));\n\n        return instructions;\n    }\n\n    private Deque<Character> cipheredWatermark() {\n        var ciphered = new ArrayDeque<Character>();\n        for (int i = 0; i < message.length(); i++) {\n            ciphered.push((char) (message.charAt(i) ^ key.charAt(i % key.length())));\n        }\n        return ciphered;\n    }\n\n    @Override\n    public Exclusion.ExclusionType getExclusionType() {\n        return Exclusion.ExclusionType.WATERMARK;\n    }\n\n    @Override\n    public String getConfigName() {\n        return Transformers.WATERMARK.getConfigName();\n    }\n\n    public static class Extractor {\n        private static final InstructionPattern PATTERN = new InstructionPattern(\n                new IntConstRule(),\n                new IntConstRule(),\n                new IntConstRule(),\n                new IntConstRule(),\n                new OpcodeRule(ISTORE),\n                new OpcodeRule(ISTORE),\n                new OpcodeRule(ISTORE),\n                new OpcodeRule(ISTORE)\n        );\n        private final ZipFile file;\n        private final String key;\n\n        public Extractor(ZipFile file, String key) {\n            this.file = file;\n            this.key = key;\n        }\n\n        private boolean enoughInfo(Map<Integer, Character> charMap) {\n            if (charMap.size() < 1) {\n                return false;\n            }\n\n            for (var i = 0; i < charMap.size(); i++) {\n                if (!charMap.containsKey(i)) {\n                    return false;\n                }\n            }\n\n            return true;\n        }\n\n        private String constructString(Map<Integer, Character> embedMap) {\n            var sb = new StringBuilder();\n            for (var i = 0; i < embedMap.size(); i++) {\n                sb.append((char) embedMap.get(i));\n            }\n            return sb.toString();\n        }\n\n        private String decrypt(String enc, String key) {\n            var messageChars = enc.toCharArray();\n            var keyChars = key.toCharArray();\n            var sb = new StringBuilder();\n\n            for (var i = 0; i < messageChars.length; i++) {\n                sb.append((char) (messageChars[i] ^ keyChars[i % keyChars.length]));\n            }\n\n            return sb.toString();\n        }\n\n        private void attemptExtract(ClassNode classNode, Map<Integer, Character> map) {\n            classNode.methods.forEach(methodNode -> {\n                if (methodNode.instructions.size() > 0) {\n                    var matcher = PATTERN.matcher(methodNode.instructions.getFirst());\n\n                    if (matcher.find()) {\n                        matcher.getAllCaptured().forEach(captured -> {\n                            char character = (char) (\n                                    ASMUtils.getIntegerFromInsn(captured.get(0)) ^ ASMUtils.getIntegerFromInsn(captured.get(1))\n                            );\n                            int index = (\n                                    ASMUtils.getIntegerFromInsn(captured.get(2)) ^ ASMUtils.getIntegerFromInsn(captured.get(3))\n                            );\n                            map.put(index, character);\n                        });\n                    }\n                }\n            });\n        }\n\n        public String extractId() {\n            Map<Integer, Character> map = new HashMap<>();\n            var entries = file.entries();\n            while (entries.hasMoreElements()) {\n                var entry = entries.nextElement();\n                if (!entry.isDirectory() && entry.getName().endsWith(\".class\")) {\n                    try {\n                        var node = new ClassNode();\n                        var reader = new ClassReader(file.getInputStream(entry));\n                        reader.accept(node, ClassReader.SKIP_DEBUG | ClassReader.SKIP_FRAMES);\n                        attemptExtract(node, map);\n                    } catch (Throwable ignored) {\n                    }\n                }\n            }\n            if (enoughInfo(map)) {\n                return \"Found watermark: \" + decrypt(constructString(map), key);\n            }\n            return \"Unable to extract watermarked id (does it exist?)\";\n        }\n    }\n}\n"
  },
  {
    "path": "xyz.itzsomebody.radon/src/main/java/xyz/itzsomebody/radon/transformers/references/ReferenceTransformer.java",
    "content": "package xyz.itzsomebody.radon.transformers.references;\n\npublic class ReferenceTransformer {\n}\n"
  },
  {
    "path": "xyz.itzsomebody.radon/src/main/java/xyz/itzsomebody/radon/transformers/shrinker/RemoveDeprecatedAccess.java",
    "content": "package xyz.itzsomebody.radon.transformers.shrinker;\n\npublic class RemoveDeprecatedAccess {\n}\n"
  },
  {
    "path": "xyz.itzsomebody.radon/src/main/java/xyz/itzsomebody/radon/transformers/shrinker/RemoveInnerClassesAttribute.java",
    "content": "package xyz.itzsomebody.radon.transformers.shrinker;\n\npublic class RemoveInnerClassesAttribute {\n}\n"
  },
  {
    "path": "xyz.itzsomebody.radon/src/main/java/xyz/itzsomebody/radon/transformers/shrinker/RemoveInvisibleAnnotations.java",
    "content": "package xyz.itzsomebody.radon.transformers.shrinker;\n\npublic class RemoveInvisibleAnnotations {\n}\n"
  },
  {
    "path": "xyz.itzsomebody.radon/src/main/java/xyz/itzsomebody/radon/transformers/shrinker/RemoveInvisibleParameterAnnotations.java",
    "content": "package xyz.itzsomebody.radon.transformers.shrinker;\n\npublic class RemoveInvisibleParameterAnnotations {\n}\n"
  },
  {
    "path": "xyz.itzsomebody.radon/src/main/java/xyz/itzsomebody/radon/transformers/shrinker/RemoveInvisibleTypeAnnotations.java",
    "content": "package xyz.itzsomebody.radon.transformers.shrinker;\n\npublic class RemoveInvisibleTypeAnnotations {\n}\n"
  },
  {
    "path": "xyz.itzsomebody.radon/src/main/java/xyz/itzsomebody/radon/transformers/shrinker/RemoveLineNumbers.java",
    "content": "package xyz.itzsomebody.radon.transformers.shrinker;\n\npublic class RemoveLineNumbers {\n}\n"
  },
  {
    "path": "xyz.itzsomebody.radon/src/main/java/xyz/itzsomebody/radon/transformers/shrinker/RemoveLocalVariableTable.java",
    "content": "package xyz.itzsomebody.radon.transformers.shrinker;\n\npublic class RemoveLocalVariableTable {\n}\n"
  },
  {
    "path": "xyz.itzsomebody.radon/src/main/java/xyz/itzsomebody/radon/transformers/shrinker/RemoveOuterMethodAttribute.java",
    "content": "package xyz.itzsomebody.radon.transformers.shrinker;\n\npublic class RemoveOuterMethodAttribute {\n}\n"
  },
  {
    "path": "xyz.itzsomebody.radon/src/main/java/xyz/itzsomebody/radon/transformers/shrinker/RemoveSignatureAttribute.java",
    "content": "package xyz.itzsomebody.radon.transformers.shrinker;\n\npublic class RemoveSignatureAttribute {\n}\n"
  },
  {
    "path": "xyz.itzsomebody.radon/src/main/java/xyz/itzsomebody/radon/transformers/shrinker/RemoveSourceDebugAttribute.java",
    "content": "package xyz.itzsomebody.radon.transformers.shrinker;\n\npublic class RemoveSourceDebugAttribute {\n}\n"
  },
  {
    "path": "xyz.itzsomebody.radon/src/main/java/xyz/itzsomebody/radon/transformers/shrinker/RemoveSourceFileAttribute.java",
    "content": "package xyz.itzsomebody.radon.transformers.shrinker;\n\npublic class RemoveSourceFileAttribute {\n}\n"
  },
  {
    "path": "xyz.itzsomebody.radon/src/main/java/xyz/itzsomebody/radon/transformers/shrinker/RemoveSyntheticAccessAttribute.java",
    "content": "package xyz.itzsomebody.radon.transformers.shrinker;\n\npublic class RemoveSyntheticAccessAttribute {\n}\n"
  },
  {
    "path": "xyz.itzsomebody.radon/src/main/java/xyz/itzsomebody/radon/transformers/shrinker/RemoveUnknownAttributes.java",
    "content": "package xyz.itzsomebody.radon.transformers.shrinker;\n\npublic class RemoveUnknownAttributes {\n}\n"
  },
  {
    "path": "xyz.itzsomebody.radon/src/main/java/xyz/itzsomebody/radon/transformers/shrinker/RemoveVisibleAnnotations.java",
    "content": "package xyz.itzsomebody.radon.transformers.shrinker;\n\npublic class RemoveVisibleAnnotations {\n}\n"
  },
  {
    "path": "xyz.itzsomebody.radon/src/main/java/xyz/itzsomebody/radon/transformers/shrinker/RemoveVisibleParameterAnnotations.java",
    "content": "package xyz.itzsomebody.radon.transformers.shrinker;\n\npublic class RemoveVisibleParameterAnnotations {\n}\n"
  },
  {
    "path": "xyz.itzsomebody.radon/src/main/java/xyz/itzsomebody/radon/transformers/shrinker/RemoveVisibleTypeAnnotations.java",
    "content": "package xyz.itzsomebody.radon.transformers.shrinker;\n\npublic class RemoveVisibleTypeAnnotations {\n}\n"
  },
  {
    "path": "xyz.itzsomebody.radon/src/main/java/xyz/itzsomebody/radon/transformers/shrinker/ShrinkerTransformer.java",
    "content": "package xyz.itzsomebody.radon.transformers.shrinker;\n\npublic class ShrinkerTransformer {\n}\n"
  },
  {
    "path": "xyz.itzsomebody.radon/src/main/java/xyz/itzsomebody/radon/transformers/strings/AESPCBCEncryptor.java",
    "content": "package xyz.itzsomebody.radon.transformers.strings;\n\nimport java.nio.charset.StandardCharsets;\nimport java.util.Arrays;\nimport java.util.Base64;\n\npublic class AESPCBCEncryptor {\n    private static int[][] sbox; // lookup table for SBox\n    private static int[][] mcTables; // lookup tables for MixColumns\n    private static int[] rcon; // round constants\n    private static int[] W; // expanded key\n\n    static {\n        initMultLookups();\n        initSBox();\n        initRcon();\n    }\n\n    private static void initSBox() {\n        sbox = new int[0x10][0x10];\n        int p = 1;\n        int q = 1;\n\n        // See https://crypto.stackexchange.com/questions/85670/need-help-understanding-math-behind-rijndael-s-box\n        // for an explanation of how 3 generates GF[2^8]\n        do {\n            p = gfMult(0x3, p);\n            q = gfMult(0xF6, q);\n\n            int trans = q; // Affine transformation\n            trans ^= ((q << 1) | (q >>> (8 - 1))) & 0xFF;\n            trans ^= ((q << 2) | (q >>> (8 - 2))) & 0xFF;\n            trans ^= ((q << 3) | (q >>> (8 - 3))) & 0xFF;\n            trans ^= ((q << 4) | (q >>> (8 - 4))) & 0xFF;\n            sbox[p / 16][p % 16] = (trans ^ 0x63) & 0xFF;\n        } while (p != 1);\n\n        sbox[0][0] = 0x63; // 0 is never invertible so set manually\n    }\n\n    // Multiply in GF[2^8]\n    private static int gfMult(int mult, int b) {\n        int result = 0;\n        for (int i = 0; i < 8; i++) {\n            if ((mult & 0x1) != 0) {\n                result ^= b;\n            }\n            mult >>= 1;\n            int mod = 0;\n            if ((b & 0x80) != 0) {\n                mod = 0x11B;\n            }\n            b = (b << 1) ^ mod;\n        }\n        return result;\n    }\n\n    private static void initMultLookups() {\n        mcTables = new int[0xF][];\n        mcTables[0x1] = new int[0x100];\n        mcTables[0x2] = new int[0x100];\n        mcTables[0x3] = new int[0x100];\n\n        for (int mult = 0; mult < mcTables.length; mult++) {\n            if (mcTables[mult] != null) {\n                int[] table = mcTables[mult];\n\n                for (int n = 0; n < table.length; n++) {\n                    table[n] = gfMult(mult, n);\n                }\n            }\n        }\n    }\n\n    private static void initRcon() {\n        rcon = new int[10];\n        for (int i = 0; i < rcon.length; i++) {\n            if (i == 0) {\n                rcon[i] = 1;\n            } else if (rcon[i - 1] < 0x80) {\n                rcon[i] = 2 * rcon[i - 1];\n            } else if (rcon[i - 1] >= 0x80) {\n                rcon[i] = (2 * rcon[i - 1]) ^ 0x11B;\n            } else {\n                throw new RuntimeException(\"?\");\n            }\n        }\n        for (int i = 0; i < rcon.length; i++) {\n            rcon[i] <<= 24;\n        }\n    }\n\n    private static void cipher(int[][] state) {\n        int round = 0;\n\n        addRoundKey(state, round);\n\n        for (round = 1; round < 10; round++) {\n            subBytes(state);\n            shiftRows(state);\n            mixColumns(state);\n            addRoundKey(state, round);\n        }\n\n        subBytes(state);\n        shiftRows(state);\n        addRoundKey(state, round);\n    }\n\n    private static int[] pad(int[] arr) {\n        int bytesNeeded = 16 - arr.length % 16;\n        int[] paddedArr = new int[arr.length + bytesNeeded];\n        System.arraycopy(arr, 0, paddedArr, 0, arr.length);\n        for (int i = 0; i < bytesNeeded; i++) {\n            paddedArr[arr.length + i] = bytesNeeded;\n        }\n        return paddedArr;\n    }\n\n    private static int[] design(byte[] arr) {\n        int[] designed = new int[arr.length];\n        for (int i = 0; i < arr.length; i++) {\n            designed[i] = arr[i] & 0xFF;\n        }\n        return designed;\n    }\n\n    private static byte[] sign(int[] arr) {\n        byte[] signed = new byte[arr.length];\n        for (int i = 0; i < arr.length; i++) {\n            signed[i] = (byte) arr[i];\n        }\n        return signed;\n    }\n\n    public static String encrypt(String input, int[] key, long[] ivInts) {\n        // Key stuff\n        keySchedule(key);\n\n        // Convert IV to correct format\n        int[] ivBytes = new int[0x10];\n        for (int i = 0; i < ivInts.length; i++) {\n            for (int j = 0; j < 8; j++) {\n                ivBytes[i * 8 + j] = (int) ((ivInts[i] >>> (56 - j * 8)) & 0xFF);\n            }\n        }\n        int[][] iv = create_state(ivBytes);\n\n        // Pad and create state block\n        int[] paddedArr = pad(design(input.getBytes(StandardCharsets.UTF_8)));\n        int[][][] states = new int[paddedArr.length / 16][][];\n        for (int i = 0; i < states.length; i++) {\n            int[] subarray = Arrays.copyOfRange(paddedArr, i * 16, (i + 1) * 16);\n            states[i] = create_state(subarray);\n        }\n\n        // PCBC encryption algorithm\n        int[][] blockCopy = copyBlock(states[0]); // plaintext here\n        for (int row = 0; row < states[0].length; row++) {\n            for (int col = 0; col < states[0][0].length; col++) {\n                states[0][row][col] ^= iv[row][col];\n            }\n        }\n        cipher(states[0]);\n        for (int row = 0; row < states[0].length; row++) {\n            for (int col = 0; col < states[0][0].length; col++) {\n                blockCopy[row][col] ^= states[0][row][col]; // states[0] is ciphered here\n            }\n        }\n\n        for (int i = 1; i < states.length; i++) {\n            int[][] blockCopy2 = copyBlock(states[i]);\n            int[][] state = states[i];\n            for (int row = 0; row < state.length; row++) {\n                for (int col = 0; col < state[0].length; col++) {\n                    state[row][col] ^= blockCopy[row][col];\n                }\n            }\n            cipher(states[i]);\n            for (int row = 0; row < state.length; row++) {\n                for (int col = 0; col < state[0].length; col++) {\n                    blockCopy2[row][col] ^= state[row][col]; // state is ciphered here\n                }\n            }\n            blockCopy = blockCopy2;\n        }\n\n        // Convert state to single-dimension array\n        byte[] processed = new byte[paddedArr.length];\n        for (int i = 0; i < states.length; i++) {\n            int[] vector = new int[0x10];\n            for (int col = 0; col < states[0].length; col++) {\n                for (int row = 0; row < states[0][0].length; row++) {\n                    vector[col * 4 + row] = states[i][row][col];\n                }\n            }\n            System.arraycopy(sign(vector), 0, processed, i * 16, vector.length);\n        }\n\n        // Encode with B64 (prevents String UTF8 encoding/decoding messing the bytes up)\n        // You could also just encode the bytes into a char if you want weird unprintable characters\n        return Base64.getEncoder().encodeToString(processed);\n    }\n\n    public static int[][] copyBlock(int[][] block) {\n        int[][] copy = new int[block.length][block[0].length];\n        for (int row = 0; row < block.length; row++) {\n            for (int col = 0; col < block[0].length; col++) {\n                copy[row][col] = block[row][col];\n            }\n        }\n        return copy;\n    }\n\n    public static int[][] create_state(int[] bytes) {\n        int[][] state = new int[4][4];\n        for (int i = 0; i < bytes.length; i++) {\n            state[i % 4][i / 4] = bytes[i];\n        }\n        return state;\n    }\n\n    public static void subBytes(int[][] state) {\n        for (int row = 0; row < state.length; row++) {\n            for (int col = 0; col < state[row].length; col++) {\n                int s = state[row][col];\n                int upper = s >> 4;\n                int lower = s & 0xF;\n                state[row][col] = sbox[upper][lower];\n            }\n        }\n    }\n\n    public static void shiftRows(int[][] state) {\n        for (int offset = 0; offset < state.length; offset++) {\n            int[] row = state[offset];\n            int[] shifted = new int[row.length];\n            for (int i = 0; i < row.length; i++) {\n                shifted[i] = row[(i + offset) % 4];\n            }\n            state[offset] = shifted;\n        }\n    }\n\n    public static void mixColumns(int[][] state) {\n        for (int col = 0; col < state[0].length; col++) {\n            int s1 = mcTables[0x2][state[0][col]] ^ mcTables[0x3][state[1][col]] ^ mcTables[0x1][state[2][col]] ^ mcTables[0x1][state[3][col]];\n            int s2 = mcTables[0x1][state[0][col]] ^ mcTables[0x2][state[1][col]] ^ mcTables[0x3][state[2][col]] ^ mcTables[0x1][state[3][col]];\n            int s3 = mcTables[0x1][state[0][col]] ^ mcTables[0x1][state[1][col]] ^ mcTables[0x2][state[2][col]] ^ mcTables[0x3][state[3][col]];\n            int s4 = mcTables[0x3][state[0][col]] ^ mcTables[0x1][state[1][col]] ^ mcTables[0x1][state[2][col]] ^ mcTables[0x2][state[3][col]];\n\n            state[0][col] = s1;\n            state[1][col] = s2;\n            state[2][col] = s3;\n            state[3][col] = s4;\n        }\n    }\n\n    public static int subWord(int word) {\n        int b0 = (word >> (8 * 3)) & 0xFF;\n        int b1 = (word >> (8 * 2)) & 0xFF;\n        int b2 = (word >> 8) & 0xFF;\n        int b3 = word & 0xFF;\n\n        return (sbox[b0 >> 4][b0 & 0xF] << 8*3)\n                | (sbox[b1 >> 4][b1 & 0xF] << 8*2)\n                | (sbox[b2 >> 4][b2 & 0xF] << 8)\n                | (sbox[b3 >> 4][b3 & 0xF]);\n    }\n\n    public static void keySchedule(int[] key) {\n        // AES-128 has 11 round keys\n        int R = 11;\n        W = new int[4*R];\n\n        for (int i = 0; i < W.length; i++) {\n            if (i < key.length) {\n                W[i] = key[i];\n            } else if (i % key.length == 0) {\n                int b = (W[i - 1] << 8) | (W[i - 1] >>> (32 - 8));\n                W[i] = W[i - key.length];\n                W[i] ^= subWord(b);\n                W[i] ^= rcon[i / key.length - 1];\n            } else {\n                W[i] = W[i - key.length] ^ W[i - 1];\n            }\n        }\n    }\n\n    public static void addRoundKey(int[][] state, int round) {\n        for (int row = 0; row < state.length; row++) {\n            for (int col = 0; col < state[0].length; col++) {\n                int rkey = W[round*state[0].length + col];\n                int xbyte = (rkey >> (8*(state.length - 1) - 8*row)) & 0xFF;\n                state[row][col] ^= xbyte;\n            }\n        }\n    }\n}\n"
  },
  {
    "path": "xyz.itzsomebody.radon/src/main/java/xyz/itzsomebody/radon/transformers/strings/AESPCBCStringEncryption.java",
    "content": "package xyz.itzsomebody.radon.transformers.strings;\n\nimport org.objectweb.asm.FieldVisitor;\nimport org.objectweb.asm.Label;\nimport org.objectweb.asm.MethodVisitor;\nimport org.objectweb.asm.Opcodes;\nimport org.objectweb.asm.tree.ClassNode;\nimport org.objectweb.asm.tree.InsnList;\nimport org.objectweb.asm.tree.LdcInsnNode;\nimport xyz.itzsomebody.codegen.WrappedType;\nimport xyz.itzsomebody.commons.InsnListModifier;\nimport xyz.itzsomebody.radon.transformers.Transformers;\nimport xyz.itzsomebody.radon.utils.RandomUtils;\nimport xyz.itzsomebody.radon.utils.asm.ClassWrapper;\nimport xyz.itzsomebody.radon.utils.asm.MethodWrapper;\nimport xyz.itzsomebody.radon.utils.logging.RadonLogger;\n\nimport java.util.List;\nimport java.util.concurrent.atomic.AtomicInteger;\n\nimport static xyz.itzsomebody.codegen.expressions.IRExpressions.*;\nimport static xyz.itzsomebody.codegen.expressions.IRExpressions.longConst;\n\n/**\n * I made this transformer as a project for my cryptography class.\n * This is an implementation of AES in the PCBC mode with 128 bit keys from (mostly) scratch.\n * <p>\n * For AES read <a href=\"https://nvlpubs.nist.gov/nistpubs/fips/nist.fips.197.pdf\">this</a>\n * </p>\n * <p>\n * For PCBC read <a href=\"https://en.wikipedia.org/wiki/Block_cipher_mode_of_operation#Propagating_cipher_block_chaining_(PCBC)\">this</a>\n * </p>\n * @author ItzSomebody\n */\npublic class AESPCBCStringEncryption extends StringTransformer {\n    @Override\n    public void transform() {\n        var stringsEncrypted = new AtomicInteger();\n        var memberNames = new DecryptionMemberNames();\n\n        classStream().filter(this::notExcluded).forEach(cw -> {\n            cw.methodStream().filter(mw -> notExcluded(mw) && mw.hasInstructions()).forEach(mw -> {\n                if (mw.getLeewaySize() <= allowedLeeway) {\n                    return;\n                }\n\n                var methodNode = mw.getMethodNode();\n                var modifier = new InsnListModifier();\n\n                methodNode.instructions.forEach(ain -> {\n                    if (ain instanceof LdcInsnNode && ((LdcInsnNode) ain).cst instanceof String) {\n                        String str = (String) ((LdcInsnNode) ain).cst;\n                        modifier.replace(ain, generateInsnBlock(str, cw, mw, memberNames));\n                        stringsEncrypted.incrementAndGet();\n                    }\n                });\n\n                modifier.apply(methodNode);\n            });\n        });\n\n        if (stringsEncrypted.get() > 0) {\n            addClass(generateDecryptionClass(memberNames));\n            RadonLogger.info(\"Encrypted \" + stringsEncrypted.get() + \" strings\");\n        }\n    }\n\n    @Override\n    public String getConfigName() {\n        return Transformers.AES_PCBC_STRING_ENCRYPTION.getConfigName();\n    }\n\n    private InsnList generateInsnBlock(String str, ClassWrapper cw, MethodWrapper mw, DecryptionMemberNames memberNames) {\n        int[] key = {\n                memberNames.decryptorClassName.replace('/','.').hashCode(),\n                memberNames.decryptMethodName.hashCode(),\n                cw.getName().replace('/','.').hashCode(),\n                mw.getMethodNode().name.replace('/','.').hashCode(),\n        };\n        long[] ivInts = {\n                RandomUtils.randomLong(),\n                RandomUtils.randomLong()\n        };\n\n        return invokeStatic(\n                WrappedType.fromInternalName(memberNames.decryptorClassName, false), // Owner\n                memberNames.decryptMethodName, // Method name\n                List.of(\n                        stringConst(AESPCBCEncryptor.encrypt(str, key, ivInts)),\n                        newArray(long.class, longConst(ivInts[0]), longConst(ivInts[1]))\n                ), // Args\n                List.of(\n                        WrappedType.from(String.class),\n                        WrappedType.from(long[].class)\n                ), // Arg types\n                WrappedType.from(String.class) // Return type\n        ).getInstructions().compile();\n    }\n\n    private class DecryptionMemberNames {\n        // Class name\n        private String decryptorClassName = fakeSubClass();\n\n        // Field names\n        private String sboxFieldName = dictionary.next();\n        private String invSBoxFieldName = dictionary.next();\n        private String rconFieldName = dictionary.next();\n        private String expandedKeyFieldName = dictionary.next();\n        private String mcTablesFieldName = dictionary.next();\n\n        // Method names\n        private String subWordMethodName = dictionary.next();\n        private String keyScheduleMethodName = dictionary.next();\n        private String addRoundKeyMethodName = dictionary.next();\n        private String invShiftRowsMethodName = dictionary.next();\n        private String invSubBytesMethodName = dictionary.next();\n        private String gfMultMethodName = dictionary.next();\n        private String invMixColumnsMethodName = dictionary.next();\n        private String invCipherMethodName = dictionary.next();\n        private String decryptMethodName = dictionary.next();\n        private String copyBlockMethodName = dictionary.next();\n        private String designMethodName = dictionary.next();\n        private String resignMethodName = dictionary.next();\n        private String createStateMethodName = dictionary.next();\n    }\n\n    private ClassNode generateDecryptionClass(DecryptionMemberNames memberNames) {\n        ClassNode classWriter = new ClassNode();\n        FieldVisitor fieldVisitor;\n        MethodVisitor methodVisitor;\n\n        classWriter.visit(Opcodes.V11, ACC_PUBLIC | ACC_SUPER, memberNames.decryptorClassName, null, \"java/lang/Object\", null);\n\n        classWriter.visitInnerClass(\"java/util/Base64$Decoder\", \"java/util/Base64\", \"Decoder\", ACC_PUBLIC | ACC_STATIC);\n\n        {\n            fieldVisitor = classWriter.visitField(ACC_PUBLIC | ACC_STATIC, memberNames.sboxFieldName, \"[[I\", null, null);\n            fieldVisitor.visitEnd();\n        }\n        {\n            fieldVisitor = classWriter.visitField(ACC_PUBLIC | ACC_STATIC, memberNames.invSBoxFieldName, \"[[I\", null, null);\n            fieldVisitor.visitEnd();\n        }\n        {\n            fieldVisitor = classWriter.visitField(ACC_PUBLIC | ACC_STATIC, memberNames.rconFieldName, \"[I\", null, null);\n            fieldVisitor.visitEnd();\n        }\n        {\n            fieldVisitor = classWriter.visitField(ACC_PUBLIC | ACC_STATIC, memberNames.expandedKeyFieldName, \"[I\", null, null);\n            fieldVisitor.visitEnd();\n        }\n        {\n            fieldVisitor = classWriter.visitField(ACC_PUBLIC | ACC_STATIC, memberNames.mcTablesFieldName, \"[[I\", null, null);\n            fieldVisitor.visitEnd();\n        }\n        {\n            methodVisitor = classWriter.visitMethod(ACC_PUBLIC, \"<init>\", \"()V\", null, null);\n            methodVisitor.visitCode();\n            methodVisitor.visitVarInsn(ALOAD, 0);\n            methodVisitor.visitMethodInsn(INVOKESPECIAL, \"java/lang/Object\", \"<init>\", \"()V\", false);\n            methodVisitor.visitInsn(RETURN);\n            methodVisitor.visitMaxs(1, 1);\n            methodVisitor.visitEnd();\n        }\n        {\n            methodVisitor = classWriter.visitMethod(ACC_PUBLIC | ACC_STATIC, memberNames.subWordMethodName, \"(I)I\", null, null);\n            methodVisitor.visitCode();\n            methodVisitor.visitVarInsn(ILOAD, 0);\n            methodVisitor.visitIntInsn(BIPUSH, 24);\n            methodVisitor.visitInsn(ISHR);\n            methodVisitor.visitIntInsn(SIPUSH, 255);\n            methodVisitor.visitInsn(IAND);\n            methodVisitor.visitVarInsn(ISTORE, 1);\n            methodVisitor.visitVarInsn(ILOAD, 0);\n            methodVisitor.visitIntInsn(BIPUSH, 16);\n            methodVisitor.visitInsn(ISHR);\n            methodVisitor.visitIntInsn(SIPUSH, 255);\n            methodVisitor.visitInsn(IAND);\n            methodVisitor.visitVarInsn(ISTORE, 2);\n            methodVisitor.visitVarInsn(ILOAD, 0);\n            methodVisitor.visitIntInsn(BIPUSH, 8);\n            methodVisitor.visitInsn(ISHR);\n            methodVisitor.visitIntInsn(SIPUSH, 255);\n            methodVisitor.visitInsn(IAND);\n            methodVisitor.visitVarInsn(ISTORE, 3);\n            methodVisitor.visitVarInsn(ILOAD, 0);\n            methodVisitor.visitIntInsn(SIPUSH, 255);\n            methodVisitor.visitInsn(IAND);\n            methodVisitor.visitVarInsn(ISTORE, 4);\n            methodVisitor.visitFieldInsn(GETSTATIC, memberNames.decryptorClassName, memberNames.sboxFieldName, \"[[I\");\n            methodVisitor.visitVarInsn(ILOAD, 1);\n            methodVisitor.visitInsn(ICONST_4);\n            methodVisitor.visitInsn(ISHR);\n            methodVisitor.visitInsn(AALOAD);\n            methodVisitor.visitVarInsn(ILOAD, 1);\n            methodVisitor.visitIntInsn(BIPUSH, 15);\n            methodVisitor.visitInsn(IAND);\n            methodVisitor.visitInsn(IALOAD);\n            methodVisitor.visitIntInsn(BIPUSH, 24);\n            methodVisitor.visitInsn(ISHL);\n            methodVisitor.visitFieldInsn(GETSTATIC, memberNames.decryptorClassName, memberNames.sboxFieldName, \"[[I\");\n            methodVisitor.visitVarInsn(ILOAD, 2);\n            methodVisitor.visitInsn(ICONST_4);\n            methodVisitor.visitInsn(ISHR);\n            methodVisitor.visitInsn(AALOAD);\n            methodVisitor.visitVarInsn(ILOAD, 2);\n            methodVisitor.visitIntInsn(BIPUSH, 15);\n            methodVisitor.visitInsn(IAND);\n            methodVisitor.visitInsn(IALOAD);\n            methodVisitor.visitIntInsn(BIPUSH, 16);\n            methodVisitor.visitInsn(ISHL);\n            methodVisitor.visitInsn(IOR);\n            methodVisitor.visitFieldInsn(GETSTATIC, memberNames.decryptorClassName, memberNames.sboxFieldName, \"[[I\");\n            methodVisitor.visitVarInsn(ILOAD, 3);\n            methodVisitor.visitInsn(ICONST_4);\n            methodVisitor.visitInsn(ISHR);\n            methodVisitor.visitInsn(AALOAD);\n            methodVisitor.visitVarInsn(ILOAD, 3);\n            methodVisitor.visitIntInsn(BIPUSH, 15);\n            methodVisitor.visitInsn(IAND);\n            methodVisitor.visitInsn(IALOAD);\n            methodVisitor.visitIntInsn(BIPUSH, 8);\n            methodVisitor.visitInsn(ISHL);\n            methodVisitor.visitInsn(IOR);\n            methodVisitor.visitFieldInsn(GETSTATIC, memberNames.decryptorClassName, memberNames.sboxFieldName, \"[[I\");\n            methodVisitor.visitVarInsn(ILOAD, 4);\n            methodVisitor.visitInsn(ICONST_4);\n            methodVisitor.visitInsn(ISHR);\n            methodVisitor.visitInsn(AALOAD);\n            methodVisitor.visitVarInsn(ILOAD, 4);\n            methodVisitor.visitIntInsn(BIPUSH, 15);\n            methodVisitor.visitInsn(IAND);\n            methodVisitor.visitInsn(IALOAD);\n            methodVisitor.visitInsn(IOR);\n            methodVisitor.visitInsn(IRETURN);\n            methodVisitor.visitMaxs(4, 5);\n            methodVisitor.visitEnd();\n        }\n        {\n            methodVisitor = classWriter.visitMethod(ACC_PUBLIC | ACC_STATIC, memberNames.keyScheduleMethodName, \"([I)V\", null, null);\n            methodVisitor.visitCode();\n            methodVisitor.visitIntInsn(BIPUSH, 11);\n            methodVisitor.visitVarInsn(ISTORE, 1);\n            methodVisitor.visitInsn(ICONST_4);\n            methodVisitor.visitVarInsn(ILOAD, 1);\n            methodVisitor.visitInsn(IMUL);\n            methodVisitor.visitIntInsn(NEWARRAY, T_INT);\n            methodVisitor.visitFieldInsn(PUTSTATIC, memberNames.decryptorClassName, memberNames.expandedKeyFieldName, \"[I\");\n            methodVisitor.visitInsn(ICONST_0);\n            methodVisitor.visitVarInsn(ISTORE, 2);\n            Label label0 = new Label();\n            methodVisitor.visitLabel(label0);\n            methodVisitor.visitVarInsn(ILOAD, 2);\n            methodVisitor.visitFieldInsn(GETSTATIC, memberNames.decryptorClassName, memberNames.expandedKeyFieldName, \"[I\");\n            methodVisitor.visitInsn(ARRAYLENGTH);\n            Label label1 = new Label();\n            methodVisitor.visitJumpInsn(IF_ICMPGE, label1);\n            methodVisitor.visitVarInsn(ILOAD, 2);\n            methodVisitor.visitVarInsn(ALOAD, 0);\n            methodVisitor.visitInsn(ARRAYLENGTH);\n            Label label2 = new Label();\n            methodVisitor.visitJumpInsn(IF_ICMPGE, label2);\n            methodVisitor.visitFieldInsn(GETSTATIC, memberNames.decryptorClassName, memberNames.expandedKeyFieldName, \"[I\");\n            methodVisitor.visitVarInsn(ILOAD, 2);\n            methodVisitor.visitVarInsn(ALOAD, 0);\n            methodVisitor.visitVarInsn(ILOAD, 2);\n            methodVisitor.visitInsn(IALOAD);\n            methodVisitor.visitInsn(IASTORE);\n            Label label3 = new Label();\n            methodVisitor.visitJumpInsn(GOTO, label3);\n            methodVisitor.visitLabel(label2);\n            methodVisitor.visitVarInsn(ILOAD, 2);\n            methodVisitor.visitVarInsn(ALOAD, 0);\n            methodVisitor.visitInsn(ARRAYLENGTH);\n            methodVisitor.visitInsn(IREM);\n            Label label4 = new Label();\n            methodVisitor.visitJumpInsn(IFNE, label4);\n            methodVisitor.visitFieldInsn(GETSTATIC, memberNames.decryptorClassName, memberNames.expandedKeyFieldName, \"[I\");\n            methodVisitor.visitVarInsn(ILOAD, 2);\n            methodVisitor.visitInsn(ICONST_1);\n            methodVisitor.visitInsn(ISUB);\n            methodVisitor.visitInsn(IALOAD);\n            methodVisitor.visitIntInsn(BIPUSH, 8);\n            methodVisitor.visitInsn(ISHL);\n            methodVisitor.visitFieldInsn(GETSTATIC, memberNames.decryptorClassName, memberNames.expandedKeyFieldName, \"[I\");\n            methodVisitor.visitVarInsn(ILOAD, 2);\n            methodVisitor.visitInsn(ICONST_1);\n            methodVisitor.visitInsn(ISUB);\n            methodVisitor.visitInsn(IALOAD);\n            methodVisitor.visitIntInsn(BIPUSH, 24);\n            methodVisitor.visitInsn(IUSHR);\n            methodVisitor.visitInsn(IOR);\n            methodVisitor.visitVarInsn(ISTORE, 3);\n            methodVisitor.visitFieldInsn(GETSTATIC, memberNames.decryptorClassName, memberNames.expandedKeyFieldName, \"[I\");\n            methodVisitor.visitVarInsn(ILOAD, 2);\n            methodVisitor.visitFieldInsn(GETSTATIC, memberNames.decryptorClassName, memberNames.expandedKeyFieldName, \"[I\");\n            methodVisitor.visitVarInsn(ILOAD, 2);\n            methodVisitor.visitVarInsn(ALOAD, 0);\n            methodVisitor.visitInsn(ARRAYLENGTH);\n            methodVisitor.visitInsn(ISUB);\n            methodVisitor.visitInsn(IALOAD);\n            methodVisitor.visitInsn(IASTORE);\n            methodVisitor.visitFieldInsn(GETSTATIC, memberNames.decryptorClassName, memberNames.expandedKeyFieldName, \"[I\");\n            methodVisitor.visitVarInsn(ILOAD, 2);\n            methodVisitor.visitInsn(DUP2);\n            methodVisitor.visitInsn(IALOAD);\n            methodVisitor.visitVarInsn(ILOAD, 3);\n            methodVisitor.visitMethodInsn(INVOKESTATIC, memberNames.decryptorClassName, memberNames.subWordMethodName, \"(I)I\", false);\n            methodVisitor.visitInsn(IXOR);\n            methodVisitor.visitInsn(IASTORE);\n            methodVisitor.visitFieldInsn(GETSTATIC, memberNames.decryptorClassName, memberNames.expandedKeyFieldName, \"[I\");\n            methodVisitor.visitVarInsn(ILOAD, 2);\n            methodVisitor.visitInsn(DUP2);\n            methodVisitor.visitInsn(IALOAD);\n            methodVisitor.visitFieldInsn(GETSTATIC, memberNames.decryptorClassName, memberNames.rconFieldName, \"[I\");\n            methodVisitor.visitVarInsn(ILOAD, 2);\n            methodVisitor.visitVarInsn(ALOAD, 0);\n            methodVisitor.visitInsn(ARRAYLENGTH);\n            methodVisitor.visitInsn(IDIV);\n            methodVisitor.visitInsn(ICONST_1);\n            methodVisitor.visitInsn(ISUB);\n            methodVisitor.visitInsn(IALOAD);\n            methodVisitor.visitInsn(IXOR);\n            methodVisitor.visitInsn(IASTORE);\n            methodVisitor.visitJumpInsn(GOTO, label3);\n            methodVisitor.visitLabel(label4);\n            methodVisitor.visitFieldInsn(GETSTATIC, memberNames.decryptorClassName, memberNames.expandedKeyFieldName, \"[I\");\n            methodVisitor.visitVarInsn(ILOAD, 2);\n            methodVisitor.visitFieldInsn(GETSTATIC, memberNames.decryptorClassName, memberNames.expandedKeyFieldName, \"[I\");\n            methodVisitor.visitVarInsn(ILOAD, 2);\n            methodVisitor.visitVarInsn(ALOAD, 0);\n            methodVisitor.visitInsn(ARRAYLENGTH);\n            methodVisitor.visitInsn(ISUB);\n            methodVisitor.visitInsn(IALOAD);\n            methodVisitor.visitFieldInsn(GETSTATIC, memberNames.decryptorClassName, memberNames.expandedKeyFieldName, \"[I\");\n            methodVisitor.visitVarInsn(ILOAD, 2);\n            methodVisitor.visitInsn(ICONST_1);\n            methodVisitor.visitInsn(ISUB);\n            methodVisitor.visitInsn(IALOAD);\n            methodVisitor.visitInsn(IXOR);\n            methodVisitor.visitInsn(IASTORE);\n            methodVisitor.visitLabel(label3);\n            methodVisitor.visitIincInsn(2, 1);\n            methodVisitor.visitJumpInsn(GOTO, label0);\n            methodVisitor.visitLabel(label1);\n            methodVisitor.visitInsn(RETURN);\n            methodVisitor.visitMaxs(6, 4);\n            methodVisitor.visitEnd();\n        }\n        {\n            methodVisitor = classWriter.visitMethod(ACC_PUBLIC | ACC_STATIC, memberNames.addRoundKeyMethodName, \"([[II)V\", null, null);\n            methodVisitor.visitCode();\n            methodVisitor.visitInsn(ICONST_0);\n            methodVisitor.visitVarInsn(ISTORE, 2);\n            Label label0 = new Label();\n            methodVisitor.visitLabel(label0);\n            methodVisitor.visitVarInsn(ILOAD, 2);\n            methodVisitor.visitVarInsn(ALOAD, 0);\n            methodVisitor.visitInsn(ARRAYLENGTH);\n            Label label1 = new Label();\n            methodVisitor.visitJumpInsn(IF_ICMPGE, label1);\n            methodVisitor.visitInsn(ICONST_0);\n            methodVisitor.visitVarInsn(ISTORE, 3);\n            Label label2 = new Label();\n            methodVisitor.visitLabel(label2);\n            methodVisitor.visitVarInsn(ILOAD, 3);\n            methodVisitor.visitVarInsn(ALOAD, 0);\n            methodVisitor.visitInsn(ICONST_0);\n            methodVisitor.visitInsn(AALOAD);\n            methodVisitor.visitInsn(ARRAYLENGTH);\n            Label label3 = new Label();\n            methodVisitor.visitJumpInsn(IF_ICMPGE, label3);\n            methodVisitor.visitFieldInsn(GETSTATIC, memberNames.decryptorClassName, memberNames.expandedKeyFieldName, \"[I\");\n            methodVisitor.visitVarInsn(ILOAD, 1);\n            methodVisitor.visitVarInsn(ALOAD, 0);\n            methodVisitor.visitInsn(ICONST_0);\n            methodVisitor.visitInsn(AALOAD);\n            methodVisitor.visitInsn(ARRAYLENGTH);\n            methodVisitor.visitInsn(IMUL);\n            methodVisitor.visitVarInsn(ILOAD, 3);\n            methodVisitor.visitInsn(IADD);\n            methodVisitor.visitInsn(IALOAD);\n            methodVisitor.visitVarInsn(ISTORE, 4);\n            methodVisitor.visitVarInsn(ILOAD, 4);\n            methodVisitor.visitIntInsn(BIPUSH, 8);\n            methodVisitor.visitVarInsn(ALOAD, 0);\n            methodVisitor.visitInsn(ARRAYLENGTH);\n            methodVisitor.visitInsn(ICONST_1);\n            methodVisitor.visitInsn(ISUB);\n            methodVisitor.visitInsn(IMUL);\n            methodVisitor.visitIntInsn(BIPUSH, 8);\n            methodVisitor.visitVarInsn(ILOAD, 2);\n            methodVisitor.visitInsn(IMUL);\n            methodVisitor.visitInsn(ISUB);\n            methodVisitor.visitInsn(ISHR);\n            methodVisitor.visitIntInsn(SIPUSH, 255);\n            methodVisitor.visitInsn(IAND);\n            methodVisitor.visitVarInsn(ISTORE, 5);\n            methodVisitor.visitVarInsn(ALOAD, 0);\n            methodVisitor.visitVarInsn(ILOAD, 2);\n            methodVisitor.visitInsn(AALOAD);\n            methodVisitor.visitVarInsn(ILOAD, 3);\n            methodVisitor.visitInsn(DUP2);\n            methodVisitor.visitInsn(IALOAD);\n            methodVisitor.visitVarInsn(ILOAD, 5);\n            methodVisitor.visitInsn(IXOR);\n            methodVisitor.visitInsn(IASTORE);\n            methodVisitor.visitIincInsn(3, 1);\n            methodVisitor.visitJumpInsn(GOTO, label2);\n            methodVisitor.visitLabel(label3);\n            methodVisitor.visitIincInsn(2, 1);\n            methodVisitor.visitJumpInsn(GOTO, label0);\n            methodVisitor.visitLabel(label1);\n            methodVisitor.visitInsn(RETURN);\n            methodVisitor.visitMaxs(4, 6);\n            methodVisitor.visitEnd();\n        }\n        {\n            methodVisitor = classWriter.visitMethod(ACC_PUBLIC | ACC_STATIC, memberNames.invShiftRowsMethodName, \"([[I)V\", null, null);\n            methodVisitor.visitCode();\n            methodVisitor.visitInsn(ICONST_0);\n            methodVisitor.visitVarInsn(ISTORE, 1);\n            Label label0 = new Label();\n            methodVisitor.visitLabel(label0);\n            methodVisitor.visitVarInsn(ILOAD, 1);\n            methodVisitor.visitVarInsn(ALOAD, 0);\n            methodVisitor.visitInsn(ARRAYLENGTH);\n            Label label1 = new Label();\n            methodVisitor.visitJumpInsn(IF_ICMPGE, label1);\n            methodVisitor.visitVarInsn(ALOAD, 0);\n            methodVisitor.visitVarInsn(ILOAD, 1);\n            methodVisitor.visitInsn(AALOAD);\n            methodVisitor.visitVarInsn(ASTORE, 2);\n            methodVisitor.visitVarInsn(ALOAD, 2);\n            methodVisitor.visitInsn(ARRAYLENGTH);\n            methodVisitor.visitIntInsn(NEWARRAY, T_INT);\n            methodVisitor.visitVarInsn(ASTORE, 3);\n            methodVisitor.visitInsn(ICONST_0);\n            methodVisitor.visitVarInsn(ISTORE, 4);\n            Label label2 = new Label();\n            methodVisitor.visitLabel(label2);\n            methodVisitor.visitVarInsn(ILOAD, 4);\n            methodVisitor.visitVarInsn(ALOAD, 2);\n            methodVisitor.visitInsn(ARRAYLENGTH);\n            Label label3 = new Label();\n            methodVisitor.visitJumpInsn(IF_ICMPGE, label3);\n            methodVisitor.visitVarInsn(ALOAD, 3);\n            methodVisitor.visitVarInsn(ILOAD, 4);\n            methodVisitor.visitVarInsn(ILOAD, 1);\n            methodVisitor.visitInsn(IADD);\n            methodVisitor.visitInsn(ICONST_4);\n            methodVisitor.visitInsn(IREM);\n            methodVisitor.visitVarInsn(ALOAD, 2);\n            methodVisitor.visitVarInsn(ILOAD, 4);\n            methodVisitor.visitInsn(IALOAD);\n            methodVisitor.visitInsn(IASTORE);\n            methodVisitor.visitIincInsn(4, 1);\n            methodVisitor.visitJumpInsn(GOTO, label2);\n            methodVisitor.visitLabel(label3);\n            methodVisitor.visitVarInsn(ALOAD, 0);\n            methodVisitor.visitVarInsn(ILOAD, 1);\n            methodVisitor.visitVarInsn(ALOAD, 3);\n            methodVisitor.visitInsn(AASTORE);\n            methodVisitor.visitIincInsn(1, 1);\n            methodVisitor.visitJumpInsn(GOTO, label0);\n            methodVisitor.visitLabel(label1);\n            methodVisitor.visitInsn(RETURN);\n            methodVisitor.visitMaxs(4, 5);\n            methodVisitor.visitEnd();\n        }\n        {\n            methodVisitor = classWriter.visitMethod(ACC_PUBLIC | ACC_STATIC, memberNames.invSubBytesMethodName, \"([[I)V\", null, null);\n            methodVisitor.visitCode();\n            methodVisitor.visitInsn(ICONST_0);\n            methodVisitor.visitVarInsn(ISTORE, 1);\n            Label label0 = new Label();\n            methodVisitor.visitLabel(label0);\n            methodVisitor.visitVarInsn(ILOAD, 1);\n            methodVisitor.visitVarInsn(ALOAD, 0);\n            methodVisitor.visitInsn(ARRAYLENGTH);\n            Label label1 = new Label();\n            methodVisitor.visitJumpInsn(IF_ICMPGE, label1);\n            methodVisitor.visitInsn(ICONST_0);\n            methodVisitor.visitVarInsn(ISTORE, 2);\n            Label label2 = new Label();\n            methodVisitor.visitLabel(label2);\n            methodVisitor.visitVarInsn(ILOAD, 2);\n            methodVisitor.visitVarInsn(ALOAD, 0);\n            methodVisitor.visitVarInsn(ILOAD, 1);\n            methodVisitor.visitInsn(AALOAD);\n            methodVisitor.visitInsn(ARRAYLENGTH);\n            Label label3 = new Label();\n            methodVisitor.visitJumpInsn(IF_ICMPGE, label3);\n            methodVisitor.visitVarInsn(ALOAD, 0);\n            methodVisitor.visitVarInsn(ILOAD, 1);\n            methodVisitor.visitInsn(AALOAD);\n            methodVisitor.visitVarInsn(ILOAD, 2);\n            methodVisitor.visitInsn(IALOAD);\n            methodVisitor.visitVarInsn(ISTORE, 3);\n            methodVisitor.visitVarInsn(ILOAD, 3);\n            methodVisitor.visitInsn(ICONST_4);\n            methodVisitor.visitInsn(ISHR);\n            methodVisitor.visitVarInsn(ISTORE, 4);\n            methodVisitor.visitVarInsn(ILOAD, 3);\n            methodVisitor.visitIntInsn(BIPUSH, 15);\n            methodVisitor.visitInsn(IAND);\n            methodVisitor.visitVarInsn(ISTORE, 5);\n            methodVisitor.visitVarInsn(ALOAD, 0);\n            methodVisitor.visitVarInsn(ILOAD, 1);\n            methodVisitor.visitInsn(AALOAD);\n            methodVisitor.visitVarInsn(ILOAD, 2);\n            methodVisitor.visitFieldInsn(GETSTATIC, memberNames.decryptorClassName, memberNames.invSBoxFieldName, \"[[I\");\n            methodVisitor.visitVarInsn(ILOAD, 4);\n            methodVisitor.visitInsn(AALOAD);\n            methodVisitor.visitVarInsn(ILOAD, 5);\n            methodVisitor.visitInsn(IALOAD);\n            methodVisitor.visitInsn(IASTORE);\n            methodVisitor.visitIincInsn(2, 1);\n            methodVisitor.visitJumpInsn(GOTO, label2);\n            methodVisitor.visitLabel(label3);\n            methodVisitor.visitIincInsn(1, 1);\n            methodVisitor.visitJumpInsn(GOTO, label0);\n            methodVisitor.visitLabel(label1);\n            methodVisitor.visitInsn(RETURN);\n            methodVisitor.visitMaxs(4, 6);\n            methodVisitor.visitEnd();\n        }\n        {\n            methodVisitor = classWriter.visitMethod(ACC_PUBLIC | ACC_STATIC, memberNames.gfMultMethodName, \"(II)I\", null, null);\n            methodVisitor.visitCode();\n            methodVisitor.visitInsn(ICONST_0);\n            methodVisitor.visitVarInsn(ISTORE, 2);\n            methodVisitor.visitInsn(ICONST_0);\n            methodVisitor.visitVarInsn(ISTORE, 3);\n            Label label0 = new Label();\n            methodVisitor.visitLabel(label0);\n            methodVisitor.visitVarInsn(ILOAD, 3);\n            methodVisitor.visitIntInsn(BIPUSH, 8);\n            Label label1 = new Label();\n            methodVisitor.visitJumpInsn(IF_ICMPGE, label1);\n            methodVisitor.visitVarInsn(ILOAD, 0);\n            methodVisitor.visitInsn(ICONST_1);\n            methodVisitor.visitInsn(IAND);\n            Label label2 = new Label();\n            methodVisitor.visitJumpInsn(IFEQ, label2);\n            methodVisitor.visitVarInsn(ILOAD, 2);\n            methodVisitor.visitVarInsn(ILOAD, 1);\n            methodVisitor.visitInsn(IXOR);\n            methodVisitor.visitVarInsn(ISTORE, 2);\n            methodVisitor.visitLabel(label2);\n            methodVisitor.visitVarInsn(ILOAD, 0);\n            methodVisitor.visitInsn(ICONST_1);\n            methodVisitor.visitInsn(ISHR);\n            methodVisitor.visitVarInsn(ISTORE, 0);\n            methodVisitor.visitInsn(ICONST_0);\n            methodVisitor.visitVarInsn(ISTORE, 4);\n            methodVisitor.visitVarInsn(ILOAD, 1);\n            methodVisitor.visitIntInsn(SIPUSH, 128);\n            methodVisitor.visitInsn(IAND);\n            Label label3 = new Label();\n            methodVisitor.visitJumpInsn(IFEQ, label3);\n            methodVisitor.visitIntInsn(SIPUSH, 283);\n            methodVisitor.visitVarInsn(ISTORE, 4);\n            methodVisitor.visitLabel(label3);\n            methodVisitor.visitVarInsn(ILOAD, 1);\n            methodVisitor.visitInsn(ICONST_1);\n            methodVisitor.visitInsn(ISHL);\n            methodVisitor.visitVarInsn(ILOAD, 4);\n            methodVisitor.visitInsn(IXOR);\n            methodVisitor.visitVarInsn(ISTORE, 1);\n            methodVisitor.visitIincInsn(3, 1);\n            methodVisitor.visitJumpInsn(GOTO, label0);\n            methodVisitor.visitLabel(label1);\n            methodVisitor.visitVarInsn(ILOAD, 2);\n            methodVisitor.visitInsn(IRETURN);\n            methodVisitor.visitMaxs(2, 5);\n            methodVisitor.visitEnd();\n        }\n        {\n            methodVisitor = classWriter.visitMethod(ACC_PUBLIC | ACC_STATIC, memberNames.invMixColumnsMethodName, \"([[I)V\", null, null);\n            methodVisitor.visitCode();\n            methodVisitor.visitInsn(ICONST_0);\n            methodVisitor.visitVarInsn(ISTORE, 1);\n            Label label0 = new Label();\n            methodVisitor.visitLabel(label0);\n            methodVisitor.visitVarInsn(ILOAD, 1);\n            methodVisitor.visitVarInsn(ALOAD, 0);\n            methodVisitor.visitInsn(ICONST_0);\n            methodVisitor.visitInsn(AALOAD);\n            methodVisitor.visitInsn(ARRAYLENGTH);\n            Label label1 = new Label();\n            methodVisitor.visitJumpInsn(IF_ICMPGE, label1);\n            methodVisitor.visitFieldInsn(GETSTATIC, memberNames.decryptorClassName, memberNames.mcTablesFieldName, \"[[I\");\n            methodVisitor.visitIntInsn(BIPUSH, 14);\n            methodVisitor.visitInsn(AALOAD);\n            methodVisitor.visitVarInsn(ALOAD, 0);\n            methodVisitor.visitInsn(ICONST_0);\n            methodVisitor.visitInsn(AALOAD);\n            methodVisitor.visitVarInsn(ILOAD, 1);\n            methodVisitor.visitInsn(IALOAD);\n            methodVisitor.visitInsn(IALOAD);\n            methodVisitor.visitFieldInsn(GETSTATIC, memberNames.decryptorClassName, memberNames.mcTablesFieldName, \"[[I\");\n            methodVisitor.visitIntInsn(BIPUSH, 11);\n            methodVisitor.visitInsn(AALOAD);\n            methodVisitor.visitVarInsn(ALOAD, 0);\n            methodVisitor.visitInsn(ICONST_1);\n            methodVisitor.visitInsn(AALOAD);\n            methodVisitor.visitVarInsn(ILOAD, 1);\n            methodVisitor.visitInsn(IALOAD);\n            methodVisitor.visitInsn(IALOAD);\n            methodVisitor.visitInsn(IXOR);\n            methodVisitor.visitFieldInsn(GETSTATIC, memberNames.decryptorClassName, memberNames.mcTablesFieldName, \"[[I\");\n            methodVisitor.visitIntInsn(BIPUSH, 13);\n            methodVisitor.visitInsn(AALOAD);\n            methodVisitor.visitVarInsn(ALOAD, 0);\n            methodVisitor.visitInsn(ICONST_2);\n            methodVisitor.visitInsn(AALOAD);\n            methodVisitor.visitVarInsn(ILOAD, 1);\n            methodVisitor.visitInsn(IALOAD);\n            methodVisitor.visitInsn(IALOAD);\n            methodVisitor.visitInsn(IXOR);\n            methodVisitor.visitFieldInsn(GETSTATIC, memberNames.decryptorClassName, memberNames.mcTablesFieldName, \"[[I\");\n            methodVisitor.visitIntInsn(BIPUSH, 9);\n            methodVisitor.visitInsn(AALOAD);\n            methodVisitor.visitVarInsn(ALOAD, 0);\n            methodVisitor.visitInsn(ICONST_3);\n            methodVisitor.visitInsn(AALOAD);\n            methodVisitor.visitVarInsn(ILOAD, 1);\n            methodVisitor.visitInsn(IALOAD);\n            methodVisitor.visitInsn(IALOAD);\n            methodVisitor.visitInsn(IXOR);\n            methodVisitor.visitVarInsn(ISTORE, 2);\n            methodVisitor.visitFieldInsn(GETSTATIC, memberNames.decryptorClassName, memberNames.mcTablesFieldName, \"[[I\");\n            methodVisitor.visitIntInsn(BIPUSH, 9);\n            methodVisitor.visitInsn(AALOAD);\n            methodVisitor.visitVarInsn(ALOAD, 0);\n            methodVisitor.visitInsn(ICONST_0);\n            methodVisitor.visitInsn(AALOAD);\n            methodVisitor.visitVarInsn(ILOAD, 1);\n            methodVisitor.visitInsn(IALOAD);\n            methodVisitor.visitInsn(IALOAD);\n            methodVisitor.visitFieldInsn(GETSTATIC, memberNames.decryptorClassName, memberNames.mcTablesFieldName, \"[[I\");\n            methodVisitor.visitIntInsn(BIPUSH, 14);\n            methodVisitor.visitInsn(AALOAD);\n            methodVisitor.visitVarInsn(ALOAD, 0);\n            methodVisitor.visitInsn(ICONST_1);\n            methodVisitor.visitInsn(AALOAD);\n            methodVisitor.visitVarInsn(ILOAD, 1);\n            methodVisitor.visitInsn(IALOAD);\n            methodVisitor.visitInsn(IALOAD);\n            methodVisitor.visitInsn(IXOR);\n            methodVisitor.visitFieldInsn(GETSTATIC, memberNames.decryptorClassName, memberNames.mcTablesFieldName, \"[[I\");\n            methodVisitor.visitIntInsn(BIPUSH, 11);\n            methodVisitor.visitInsn(AALOAD);\n            methodVisitor.visitVarInsn(ALOAD, 0);\n            methodVisitor.visitInsn(ICONST_2);\n            methodVisitor.visitInsn(AALOAD);\n            methodVisitor.visitVarInsn(ILOAD, 1);\n            methodVisitor.visitInsn(IALOAD);\n            methodVisitor.visitInsn(IALOAD);\n            methodVisitor.visitInsn(IXOR);\n            methodVisitor.visitFieldInsn(GETSTATIC, memberNames.decryptorClassName, memberNames.mcTablesFieldName, \"[[I\");\n            methodVisitor.visitIntInsn(BIPUSH, 13);\n            methodVisitor.visitInsn(AALOAD);\n            methodVisitor.visitVarInsn(ALOAD, 0);\n            methodVisitor.visitInsn(ICONST_3);\n            methodVisitor.visitInsn(AALOAD);\n            methodVisitor.visitVarInsn(ILOAD, 1);\n            methodVisitor.visitInsn(IALOAD);\n            methodVisitor.visitInsn(IALOAD);\n            methodVisitor.visitInsn(IXOR);\n            methodVisitor.visitVarInsn(ISTORE, 3);\n            methodVisitor.visitFieldInsn(GETSTATIC, memberNames.decryptorClassName, memberNames.mcTablesFieldName, \"[[I\");\n            methodVisitor.visitIntInsn(BIPUSH, 13);\n            methodVisitor.visitInsn(AALOAD);\n            methodVisitor.visitVarInsn(ALOAD, 0);\n            methodVisitor.visitInsn(ICONST_0);\n            methodVisitor.visitInsn(AALOAD);\n            methodVisitor.visitVarInsn(ILOAD, 1);\n            methodVisitor.visitInsn(IALOAD);\n            methodVisitor.visitInsn(IALOAD);\n            methodVisitor.visitFieldInsn(GETSTATIC, memberNames.decryptorClassName, memberNames.mcTablesFieldName, \"[[I\");\n            methodVisitor.visitIntInsn(BIPUSH, 9);\n            methodVisitor.visitInsn(AALOAD);\n            methodVisitor.visitVarInsn(ALOAD, 0);\n            methodVisitor.visitInsn(ICONST_1);\n            methodVisitor.visitInsn(AALOAD);\n            methodVisitor.visitVarInsn(ILOAD, 1);\n            methodVisitor.visitInsn(IALOAD);\n            methodVisitor.visitInsn(IALOAD);\n            methodVisitor.visitInsn(IXOR);\n            methodVisitor.visitFieldInsn(GETSTATIC, memberNames.decryptorClassName, memberNames.mcTablesFieldName, \"[[I\");\n            methodVisitor.visitIntInsn(BIPUSH, 14);\n            methodVisitor.visitInsn(AALOAD);\n            methodVisitor.visitVarInsn(ALOAD, 0);\n            methodVisitor.visitInsn(ICONST_2);\n            methodVisitor.visitInsn(AALOAD);\n            methodVisitor.visitVarInsn(ILOAD, 1);\n            methodVisitor.visitInsn(IALOAD);\n            methodVisitor.visitInsn(IALOAD);\n            methodVisitor.visitInsn(IXOR);\n            methodVisitor.visitFieldInsn(GETSTATIC, memberNames.decryptorClassName, memberNames.mcTablesFieldName, \"[[I\");\n            methodVisitor.visitIntInsn(BIPUSH, 11);\n            methodVisitor.visitInsn(AALOAD);\n            methodVisitor.visitVarInsn(ALOAD, 0);\n            methodVisitor.visitInsn(ICONST_3);\n            methodVisitor.visitInsn(AALOAD);\n            methodVisitor.visitVarInsn(ILOAD, 1);\n            methodVisitor.visitInsn(IALOAD);\n            methodVisitor.visitInsn(IALOAD);\n            methodVisitor.visitInsn(IXOR);\n            methodVisitor.visitVarInsn(ISTORE, 4);\n            methodVisitor.visitFieldInsn(GETSTATIC, memberNames.decryptorClassName, memberNames.mcTablesFieldName, \"[[I\");\n            methodVisitor.visitIntInsn(BIPUSH, 11);\n            methodVisitor.visitInsn(AALOAD);\n            methodVisitor.visitVarInsn(ALOAD, 0);\n            methodVisitor.visitInsn(ICONST_0);\n            methodVisitor.visitInsn(AALOAD);\n            methodVisitor.visitVarInsn(ILOAD, 1);\n            methodVisitor.visitInsn(IALOAD);\n            methodVisitor.visitInsn(IALOAD);\n            methodVisitor.visitFieldInsn(GETSTATIC, memberNames.decryptorClassName, memberNames.mcTablesFieldName, \"[[I\");\n            methodVisitor.visitIntInsn(BIPUSH, 13);\n            methodVisitor.visitInsn(AALOAD);\n            methodVisitor.visitVarInsn(ALOAD, 0);\n            methodVisitor.visitInsn(ICONST_1);\n            methodVisitor.visitInsn(AALOAD);\n            methodVisitor.visitVarInsn(ILOAD, 1);\n            methodVisitor.visitInsn(IALOAD);\n            methodVisitor.visitInsn(IALOAD);\n            methodVisitor.visitInsn(IXOR);\n            methodVisitor.visitFieldInsn(GETSTATIC, memberNames.decryptorClassName, memberNames.mcTablesFieldName, \"[[I\");\n            methodVisitor.visitIntInsn(BIPUSH, 9);\n            methodVisitor.visitInsn(AALOAD);\n            methodVisitor.visitVarInsn(ALOAD, 0);\n            methodVisitor.visitInsn(ICONST_2);\n            methodVisitor.visitInsn(AALOAD);\n            methodVisitor.visitVarInsn(ILOAD, 1);\n            methodVisitor.visitInsn(IALOAD);\n            methodVisitor.visitInsn(IALOAD);\n            methodVisitor.visitInsn(IXOR);\n            methodVisitor.visitFieldInsn(GETSTATIC, memberNames.decryptorClassName, memberNames.mcTablesFieldName, \"[[I\");\n            methodVisitor.visitIntInsn(BIPUSH, 14);\n            methodVisitor.visitInsn(AALOAD);\n            methodVisitor.visitVarInsn(ALOAD, 0);\n            methodVisitor.visitInsn(ICONST_3);\n            methodVisitor.visitInsn(AALOAD);\n            methodVisitor.visitVarInsn(ILOAD, 1);\n            methodVisitor.visitInsn(IALOAD);\n            methodVisitor.visitInsn(IALOAD);\n            methodVisitor.visitInsn(IXOR);\n            methodVisitor.visitVarInsn(ISTORE, 5);\n            methodVisitor.visitVarInsn(ALOAD, 0);\n            methodVisitor.visitInsn(ICONST_0);\n            methodVisitor.visitInsn(AALOAD);\n            methodVisitor.visitVarInsn(ILOAD, 1);\n            methodVisitor.visitVarInsn(ILOAD, 2);\n            methodVisitor.visitInsn(IASTORE);\n            methodVisitor.visitVarInsn(ALOAD, 0);\n            methodVisitor.visitInsn(ICONST_1);\n            methodVisitor.visitInsn(AALOAD);\n            methodVisitor.visitVarInsn(ILOAD, 1);\n            methodVisitor.visitVarInsn(ILOAD, 3);\n            methodVisitor.visitInsn(IASTORE);\n            methodVisitor.visitVarInsn(ALOAD, 0);\n            methodVisitor.visitInsn(ICONST_2);\n            methodVisitor.visitInsn(AALOAD);\n            methodVisitor.visitVarInsn(ILOAD, 1);\n            methodVisitor.visitVarInsn(ILOAD, 4);\n            methodVisitor.visitInsn(IASTORE);\n            methodVisitor.visitVarInsn(ALOAD, 0);\n            methodVisitor.visitInsn(ICONST_3);\n            methodVisitor.visitInsn(AALOAD);\n            methodVisitor.visitVarInsn(ILOAD, 1);\n            methodVisitor.visitVarInsn(ILOAD, 5);\n            methodVisitor.visitInsn(IASTORE);\n            methodVisitor.visitIincInsn(1, 1);\n            methodVisitor.visitJumpInsn(GOTO, label0);\n            methodVisitor.visitLabel(label1);\n            methodVisitor.visitInsn(RETURN);\n            methodVisitor.visitMaxs(4, 6);\n            methodVisitor.visitEnd();\n        }\n        {\n            methodVisitor = classWriter.visitMethod(ACC_PUBLIC | ACC_STATIC, memberNames.invCipherMethodName, \"([[I)V\", null, null);\n            methodVisitor.visitCode();\n            methodVisitor.visitIntInsn(BIPUSH, 10);\n            methodVisitor.visitVarInsn(ISTORE, 1);\n            methodVisitor.visitVarInsn(ALOAD, 0);\n            methodVisitor.visitVarInsn(ILOAD, 1);\n            methodVisitor.visitMethodInsn(INVOKESTATIC, memberNames.decryptorClassName, memberNames.addRoundKeyMethodName, \"([[II)V\", false);\n            methodVisitor.visitIntInsn(BIPUSH, 9);\n            methodVisitor.visitVarInsn(ISTORE, 1);\n            Label label0 = new Label();\n            methodVisitor.visitLabel(label0);\n            methodVisitor.visitVarInsn(ILOAD, 1);\n            Label label1 = new Label();\n            methodVisitor.visitJumpInsn(IFLE, label1);\n            methodVisitor.visitVarInsn(ALOAD, 0);\n            methodVisitor.visitMethodInsn(INVOKESTATIC, memberNames.decryptorClassName, memberNames.invShiftRowsMethodName, \"([[I)V\", false);\n            methodVisitor.visitVarInsn(ALOAD, 0);\n            methodVisitor.visitMethodInsn(INVOKESTATIC, memberNames.decryptorClassName, memberNames.invSubBytesMethodName, \"([[I)V\", false);\n            methodVisitor.visitVarInsn(ALOAD, 0);\n            methodVisitor.visitVarInsn(ILOAD, 1);\n            methodVisitor.visitMethodInsn(INVOKESTATIC, memberNames.decryptorClassName, memberNames.addRoundKeyMethodName, \"([[II)V\", false);\n            methodVisitor.visitVarInsn(ALOAD, 0);\n            methodVisitor.visitMethodInsn(INVOKESTATIC, memberNames.decryptorClassName, memberNames.invMixColumnsMethodName, \"([[I)V\", false);\n            methodVisitor.visitIincInsn(1, -1);\n            methodVisitor.visitJumpInsn(GOTO, label0);\n            methodVisitor.visitLabel(label1);\n            methodVisitor.visitVarInsn(ALOAD, 0);\n            methodVisitor.visitMethodInsn(INVOKESTATIC, memberNames.decryptorClassName, memberNames.invSubBytesMethodName, \"([[I)V\", false);\n            methodVisitor.visitVarInsn(ALOAD, 0);\n            methodVisitor.visitMethodInsn(INVOKESTATIC, memberNames.decryptorClassName, memberNames.invShiftRowsMethodName, \"([[I)V\", false);\n            methodVisitor.visitVarInsn(ALOAD, 0);\n            methodVisitor.visitVarInsn(ILOAD, 1);\n            methodVisitor.visitMethodInsn(INVOKESTATIC, memberNames.decryptorClassName, memberNames.addRoundKeyMethodName, \"([[II)V\", false);\n            methodVisitor.visitInsn(RETURN);\n            methodVisitor.visitMaxs(2, 2);\n            methodVisitor.visitEnd();\n        }\n        {\n            methodVisitor = classWriter.visitMethod(ACC_PUBLIC | ACC_STATIC, memberNames.decryptMethodName, \"(Ljava/lang/String;[J)Ljava/lang/String;\", null, null);\n            methodVisitor.visitCode();\n            methodVisitor.visitMethodInsn(INVOKESTATIC, \"java/lang/Thread\", \"currentThread\", \"()Ljava/lang/Thread;\", false);\n            methodVisitor.visitMethodInsn(INVOKEVIRTUAL, \"java/lang/Thread\", \"getStackTrace\", \"()[Ljava/lang/StackTraceElement;\", false);\n            methodVisitor.visitVarInsn(ASTORE, 2);\n            methodVisitor.visitInsn(ICONST_4);\n            methodVisitor.visitIntInsn(NEWARRAY, T_INT);\n            methodVisitor.visitInsn(DUP);\n            methodVisitor.visitInsn(ICONST_0);\n            methodVisitor.visitVarInsn(ALOAD, 2);\n            methodVisitor.visitInsn(ICONST_1);\n            methodVisitor.visitInsn(AALOAD);\n            methodVisitor.visitMethodInsn(INVOKEVIRTUAL, \"java/lang/StackTraceElement\", \"getClassName\", \"()Ljava/lang/String;\", false);\n            methodVisitor.visitMethodInsn(INVOKEVIRTUAL, \"java/lang/String\", \"hashCode\", \"()I\", false);\n            methodVisitor.visitInsn(IASTORE);\n            methodVisitor.visitInsn(DUP);\n            methodVisitor.visitInsn(ICONST_1);\n            methodVisitor.visitVarInsn(ALOAD, 2);\n            methodVisitor.visitInsn(ICONST_1);\n            methodVisitor.visitInsn(AALOAD);\n            methodVisitor.visitMethodInsn(INVOKEVIRTUAL, \"java/lang/StackTraceElement\", \"getMethodName\", \"()Ljava/lang/String;\", false);\n            methodVisitor.visitMethodInsn(INVOKEVIRTUAL, \"java/lang/String\", \"hashCode\", \"()I\", false);\n            methodVisitor.visitInsn(IASTORE);\n            methodVisitor.visitInsn(DUP);\n            methodVisitor.visitInsn(ICONST_2);\n            methodVisitor.visitVarInsn(ALOAD, 2);\n            methodVisitor.visitInsn(ICONST_2);\n            methodVisitor.visitInsn(AALOAD);\n            methodVisitor.visitMethodInsn(INVOKEVIRTUAL, \"java/lang/StackTraceElement\", \"getClassName\", \"()Ljava/lang/String;\", false);\n            methodVisitor.visitMethodInsn(INVOKEVIRTUAL, \"java/lang/String\", \"hashCode\", \"()I\", false);\n            methodVisitor.visitInsn(IASTORE);\n            methodVisitor.visitInsn(DUP);\n            methodVisitor.visitInsn(ICONST_3);\n            methodVisitor.visitVarInsn(ALOAD, 2);\n            methodVisitor.visitInsn(ICONST_2);\n            methodVisitor.visitInsn(AALOAD);\n            methodVisitor.visitMethodInsn(INVOKEVIRTUAL, \"java/lang/StackTraceElement\", \"getMethodName\", \"()Ljava/lang/String;\", false);\n            methodVisitor.visitMethodInsn(INVOKEVIRTUAL, \"java/lang/String\", \"hashCode\", \"()I\", false);\n            methodVisitor.visitInsn(IASTORE);\n            methodVisitor.visitVarInsn(ASTORE, 3);\n            methodVisitor.visitVarInsn(ALOAD, 3);\n            methodVisitor.visitMethodInsn(INVOKESTATIC, memberNames.decryptorClassName, memberNames.keyScheduleMethodName, \"([I)V\", false);\n            methodVisitor.visitIntInsn(BIPUSH, 16);\n            methodVisitor.visitIntInsn(NEWARRAY, T_INT);\n            methodVisitor.visitVarInsn(ASTORE, 4);\n            methodVisitor.visitInsn(ICONST_0);\n            methodVisitor.visitVarInsn(ISTORE, 5);\n            Label label0 = new Label();\n            methodVisitor.visitLabel(label0);\n            methodVisitor.visitVarInsn(ILOAD, 5);\n            methodVisitor.visitVarInsn(ALOAD, 1);\n            methodVisitor.visitInsn(ARRAYLENGTH);\n            Label label1 = new Label();\n            methodVisitor.visitJumpInsn(IF_ICMPGE, label1);\n            methodVisitor.visitInsn(ICONST_0);\n            methodVisitor.visitVarInsn(ISTORE, 6);\n            Label label2 = new Label();\n            methodVisitor.visitLabel(label2);\n            methodVisitor.visitVarInsn(ILOAD, 6);\n            methodVisitor.visitIntInsn(BIPUSH, 8);\n            Label label3 = new Label();\n            methodVisitor.visitJumpInsn(IF_ICMPGE, label3);\n            methodVisitor.visitVarInsn(ALOAD, 4);\n            methodVisitor.visitVarInsn(ILOAD, 5);\n            methodVisitor.visitIntInsn(BIPUSH, 8);\n            methodVisitor.visitInsn(IMUL);\n            methodVisitor.visitVarInsn(ILOAD, 6);\n            methodVisitor.visitInsn(IADD);\n            methodVisitor.visitVarInsn(ALOAD, 1);\n            methodVisitor.visitVarInsn(ILOAD, 5);\n            methodVisitor.visitInsn(LALOAD);\n            methodVisitor.visitIntInsn(BIPUSH, 56);\n            methodVisitor.visitVarInsn(ILOAD, 6);\n            methodVisitor.visitIntInsn(BIPUSH, 8);\n            methodVisitor.visitInsn(IMUL);\n            methodVisitor.visitInsn(ISUB);\n            methodVisitor.visitInsn(LUSHR);\n            methodVisitor.visitLdcInsn(255L);\n            methodVisitor.visitInsn(LAND);\n            methodVisitor.visitInsn(L2I);\n            methodVisitor.visitInsn(IASTORE);\n            methodVisitor.visitIincInsn(6, 1);\n            methodVisitor.visitJumpInsn(GOTO, label2);\n            methodVisitor.visitLabel(label3);\n            methodVisitor.visitIincInsn(5, 1);\n            methodVisitor.visitJumpInsn(GOTO, label0);\n            methodVisitor.visitLabel(label1);\n            methodVisitor.visitVarInsn(ALOAD, 4);\n            methodVisitor.visitMethodInsn(INVOKESTATIC, memberNames.decryptorClassName, memberNames.createStateMethodName, \"([I)[[I\", false);\n            methodVisitor.visitVarInsn(ASTORE, 5);\n            methodVisitor.visitMethodInsn(INVOKESTATIC, \"java/util/Base64\", \"getDecoder\", \"()Ljava/util/Base64$Decoder;\", false);\n            methodVisitor.visitVarInsn(ALOAD, 0);\n            methodVisitor.visitMethodInsn(INVOKEVIRTUAL, \"java/util/Base64$Decoder\", \"decode\", \"(Ljava/lang/String;)[B\", false);\n            methodVisitor.visitMethodInsn(INVOKESTATIC, memberNames.decryptorClassName, memberNames.designMethodName, \"([B)[I\", false);\n            methodVisitor.visitVarInsn(ASTORE, 6);\n            methodVisitor.visitVarInsn(ALOAD, 6);\n            methodVisitor.visitInsn(ARRAYLENGTH);\n            methodVisitor.visitIntInsn(BIPUSH, 16);\n            methodVisitor.visitInsn(IDIV);\n            methodVisitor.visitTypeInsn(ANEWARRAY, \"[[I\");\n            methodVisitor.visitVarInsn(ASTORE, 7);\n            methodVisitor.visitInsn(ICONST_0);\n            methodVisitor.visitVarInsn(ISTORE, 8);\n            Label label4 = new Label();\n            methodVisitor.visitLabel(label4);\n            methodVisitor.visitVarInsn(ILOAD, 8);\n            methodVisitor.visitVarInsn(ALOAD, 7);\n            methodVisitor.visitInsn(ARRAYLENGTH);\n            Label label5 = new Label();\n            methodVisitor.visitJumpInsn(IF_ICMPGE, label5);\n            methodVisitor.visitVarInsn(ALOAD, 6);\n            methodVisitor.visitVarInsn(ILOAD, 8);\n            methodVisitor.visitIntInsn(BIPUSH, 16);\n            methodVisitor.visitInsn(IMUL);\n            methodVisitor.visitVarInsn(ILOAD, 8);\n            methodVisitor.visitInsn(ICONST_1);\n            methodVisitor.visitInsn(IADD);\n            methodVisitor.visitIntInsn(BIPUSH, 16);\n            methodVisitor.visitInsn(IMUL);\n            methodVisitor.visitMethodInsn(INVOKESTATIC, \"java/util/Arrays\", \"copyOfRange\", \"([III)[I\", false);\n            methodVisitor.visitVarInsn(ASTORE, 9);\n            methodVisitor.visitVarInsn(ALOAD, 7);\n            methodVisitor.visitVarInsn(ILOAD, 8);\n            methodVisitor.visitVarInsn(ALOAD, 9);\n            methodVisitor.visitMethodInsn(INVOKESTATIC, memberNames.decryptorClassName, memberNames.createStateMethodName, \"([I)[[I\", false);\n            methodVisitor.visitInsn(AASTORE);\n            methodVisitor.visitIincInsn(8, 1);\n            methodVisitor.visitJumpInsn(GOTO, label4);\n            methodVisitor.visitLabel(label5);\n            methodVisitor.visitVarInsn(ALOAD, 7);\n            methodVisitor.visitInsn(ICONST_0);\n            methodVisitor.visitInsn(AALOAD);\n            methodVisitor.visitMethodInsn(INVOKESTATIC, memberNames.decryptorClassName, memberNames.copyBlockMethodName, \"([[I)[[I\", false);\n            methodVisitor.visitVarInsn(ASTORE, 8);\n            methodVisitor.visitVarInsn(ALOAD, 7);\n            methodVisitor.visitInsn(ICONST_0);\n            methodVisitor.visitInsn(AALOAD);\n            methodVisitor.visitMethodInsn(INVOKESTATIC, memberNames.decryptorClassName, memberNames.invCipherMethodName, \"([[I)V\", false);\n            methodVisitor.visitInsn(ICONST_0);\n            methodVisitor.visitVarInsn(ISTORE, 9);\n            Label label6 = new Label();\n            methodVisitor.visitLabel(label6);\n            methodVisitor.visitVarInsn(ILOAD, 9);\n            methodVisitor.visitVarInsn(ALOAD, 7);\n            methodVisitor.visitInsn(ICONST_0);\n            methodVisitor.visitInsn(AALOAD);\n            methodVisitor.visitInsn(ARRAYLENGTH);\n            Label label7 = new Label();\n            methodVisitor.visitJumpInsn(IF_ICMPGE, label7);\n            methodVisitor.visitInsn(ICONST_0);\n            methodVisitor.visitVarInsn(ISTORE, 10);\n            Label label8 = new Label();\n            methodVisitor.visitLabel(label8);\n            methodVisitor.visitVarInsn(ILOAD, 10);\n            methodVisitor.visitVarInsn(ALOAD, 7);\n            methodVisitor.visitInsn(ICONST_0);\n            methodVisitor.visitInsn(AALOAD);\n            methodVisitor.visitInsn(ICONST_0);\n            methodVisitor.visitInsn(AALOAD);\n            methodVisitor.visitInsn(ARRAYLENGTH);\n            Label label9 = new Label();\n            methodVisitor.visitJumpInsn(IF_ICMPGE, label9);\n            methodVisitor.visitVarInsn(ALOAD, 7);\n            methodVisitor.visitInsn(ICONST_0);\n            methodVisitor.visitInsn(AALOAD);\n            methodVisitor.visitVarInsn(ILOAD, 9);\n            methodVisitor.visitInsn(AALOAD);\n            methodVisitor.visitVarInsn(ILOAD, 10);\n            methodVisitor.visitInsn(DUP2);\n            methodVisitor.visitInsn(IALOAD);\n            methodVisitor.visitVarInsn(ALOAD, 5);\n            methodVisitor.visitVarInsn(ILOAD, 9);\n            methodVisitor.visitInsn(AALOAD);\n            methodVisitor.visitVarInsn(ILOAD, 10);\n            methodVisitor.visitInsn(IALOAD);\n            methodVisitor.visitInsn(IXOR);\n            methodVisitor.visitInsn(IASTORE);\n            methodVisitor.visitVarInsn(ALOAD, 8);\n            methodVisitor.visitVarInsn(ILOAD, 9);\n            methodVisitor.visitInsn(AALOAD);\n            methodVisitor.visitVarInsn(ILOAD, 10);\n            methodVisitor.visitInsn(DUP2);\n            methodVisitor.visitInsn(IALOAD);\n            methodVisitor.visitVarInsn(ALOAD, 7);\n            methodVisitor.visitInsn(ICONST_0);\n            methodVisitor.visitInsn(AALOAD);\n            methodVisitor.visitVarInsn(ILOAD, 9);\n            methodVisitor.visitInsn(AALOAD);\n            methodVisitor.visitVarInsn(ILOAD, 10);\n            methodVisitor.visitInsn(IALOAD);\n            methodVisitor.visitInsn(IXOR);\n            methodVisitor.visitInsn(IASTORE);\n            methodVisitor.visitIincInsn(10, 1);\n            methodVisitor.visitJumpInsn(GOTO, label8);\n            methodVisitor.visitLabel(label9);\n            methodVisitor.visitIincInsn(9, 1);\n            methodVisitor.visitJumpInsn(GOTO, label6);\n            methodVisitor.visitLabel(label7);\n            methodVisitor.visitInsn(ICONST_1);\n            methodVisitor.visitVarInsn(ISTORE, 9);\n            Label label10 = new Label();\n            methodVisitor.visitLabel(label10);\n            methodVisitor.visitVarInsn(ILOAD, 9);\n            methodVisitor.visitVarInsn(ALOAD, 7);\n            methodVisitor.visitInsn(ARRAYLENGTH);\n            Label label11 = new Label();\n            methodVisitor.visitJumpInsn(IF_ICMPGE, label11);\n            methodVisitor.visitVarInsn(ALOAD, 7);\n            methodVisitor.visitVarInsn(ILOAD, 9);\n            methodVisitor.visitInsn(AALOAD);\n            methodVisitor.visitMethodInsn(INVOKESTATIC, memberNames.decryptorClassName, memberNames.copyBlockMethodName, \"([[I)[[I\", false);\n            methodVisitor.visitVarInsn(ASTORE, 10);\n            methodVisitor.visitVarInsn(ALOAD, 7);\n            methodVisitor.visitVarInsn(ILOAD, 9);\n            methodVisitor.visitInsn(AALOAD);\n            methodVisitor.visitMethodInsn(INVOKESTATIC, memberNames.decryptorClassName, memberNames.invCipherMethodName, \"([[I)V\", false);\n            methodVisitor.visitVarInsn(ALOAD, 7);\n            methodVisitor.visitVarInsn(ILOAD, 9);\n            methodVisitor.visitInsn(AALOAD);\n            methodVisitor.visitVarInsn(ASTORE, 11);\n            methodVisitor.visitInsn(ICONST_0);\n            methodVisitor.visitVarInsn(ISTORE, 12);\n            Label label12 = new Label();\n            methodVisitor.visitLabel(label12);\n            methodVisitor.visitVarInsn(ILOAD, 12);\n            methodVisitor.visitVarInsn(ALOAD, 11);\n            methodVisitor.visitInsn(ARRAYLENGTH);\n            Label label13 = new Label();\n            methodVisitor.visitJumpInsn(IF_ICMPGE, label13);\n            methodVisitor.visitInsn(ICONST_0);\n            methodVisitor.visitVarInsn(ISTORE, 13);\n            Label label14 = new Label();\n            methodVisitor.visitLabel(label14);\n            methodVisitor.visitVarInsn(ILOAD, 13);\n            methodVisitor.visitVarInsn(ALOAD, 11);\n            methodVisitor.visitInsn(ICONST_0);\n            methodVisitor.visitInsn(AALOAD);\n            methodVisitor.visitInsn(ARRAYLENGTH);\n            Label label15 = new Label();\n            methodVisitor.visitJumpInsn(IF_ICMPGE, label15);\n            methodVisitor.visitVarInsn(ALOAD, 11);\n            methodVisitor.visitVarInsn(ILOAD, 12);\n            methodVisitor.visitInsn(AALOAD);\n            methodVisitor.visitVarInsn(ILOAD, 13);\n            methodVisitor.visitInsn(DUP2);\n            methodVisitor.visitInsn(IALOAD);\n            methodVisitor.visitVarInsn(ALOAD, 8);\n            methodVisitor.visitVarInsn(ILOAD, 12);\n            methodVisitor.visitInsn(AALOAD);\n            methodVisitor.visitVarInsn(ILOAD, 13);\n            methodVisitor.visitInsn(IALOAD);\n            methodVisitor.visitInsn(IXOR);\n            methodVisitor.visitInsn(IASTORE);\n            methodVisitor.visitVarInsn(ALOAD, 10);\n            methodVisitor.visitVarInsn(ILOAD, 12);\n            methodVisitor.visitInsn(AALOAD);\n            methodVisitor.visitVarInsn(ILOAD, 13);\n            methodVisitor.visitInsn(DUP2);\n            methodVisitor.visitInsn(IALOAD);\n            methodVisitor.visitVarInsn(ALOAD, 11);\n            methodVisitor.visitVarInsn(ILOAD, 12);\n            methodVisitor.visitInsn(AALOAD);\n            methodVisitor.visitVarInsn(ILOAD, 13);\n            methodVisitor.visitInsn(IALOAD);\n            methodVisitor.visitInsn(IXOR);\n            methodVisitor.visitInsn(IASTORE);\n            methodVisitor.visitIincInsn(13, 1);\n            methodVisitor.visitJumpInsn(GOTO, label14);\n            methodVisitor.visitLabel(label15);\n            methodVisitor.visitIincInsn(12, 1);\n            methodVisitor.visitJumpInsn(GOTO, label12);\n            methodVisitor.visitLabel(label13);\n            methodVisitor.visitVarInsn(ALOAD, 10);\n            methodVisitor.visitVarInsn(ASTORE, 8);\n            methodVisitor.visitIincInsn(9, 1);\n            methodVisitor.visitJumpInsn(GOTO, label10);\n            methodVisitor.visitLabel(label11);\n            methodVisitor.visitVarInsn(ALOAD, 6);\n            methodVisitor.visitInsn(ARRAYLENGTH);\n            methodVisitor.visitIntInsn(NEWARRAY, T_BYTE);\n            methodVisitor.visitVarInsn(ASTORE, 9);\n            methodVisitor.visitInsn(ICONST_0);\n            methodVisitor.visitVarInsn(ISTORE, 10);\n            Label label16 = new Label();\n            methodVisitor.visitLabel(label16);\n            methodVisitor.visitVarInsn(ILOAD, 10);\n            methodVisitor.visitVarInsn(ALOAD, 7);\n            methodVisitor.visitInsn(ARRAYLENGTH);\n            Label label17 = new Label();\n            methodVisitor.visitJumpInsn(IF_ICMPGE, label17);\n            methodVisitor.visitIntInsn(BIPUSH, 16);\n            methodVisitor.visitIntInsn(NEWARRAY, T_INT);\n            methodVisitor.visitVarInsn(ASTORE, 11);\n            methodVisitor.visitInsn(ICONST_0);\n            methodVisitor.visitVarInsn(ISTORE, 12);\n            Label label18 = new Label();\n            methodVisitor.visitLabel(label18);\n            methodVisitor.visitVarInsn(ILOAD, 12);\n            methodVisitor.visitVarInsn(ALOAD, 7);\n            methodVisitor.visitInsn(ICONST_0);\n            methodVisitor.visitInsn(AALOAD);\n            methodVisitor.visitInsn(ARRAYLENGTH);\n            Label label19 = new Label();\n            methodVisitor.visitJumpInsn(IF_ICMPGE, label19);\n            methodVisitor.visitInsn(ICONST_0);\n            methodVisitor.visitVarInsn(ISTORE, 13);\n            Label label20 = new Label();\n            methodVisitor.visitLabel(label20);\n            methodVisitor.visitVarInsn(ILOAD, 13);\n            methodVisitor.visitVarInsn(ALOAD, 7);\n            methodVisitor.visitInsn(ICONST_0);\n            methodVisitor.visitInsn(AALOAD);\n            methodVisitor.visitInsn(ICONST_0);\n            methodVisitor.visitInsn(AALOAD);\n            methodVisitor.visitInsn(ARRAYLENGTH);\n            Label label21 = new Label();\n            methodVisitor.visitJumpInsn(IF_ICMPGE, label21);\n            methodVisitor.visitVarInsn(ALOAD, 11);\n            methodVisitor.visitVarInsn(ILOAD, 12);\n            methodVisitor.visitInsn(ICONST_4);\n            methodVisitor.visitInsn(IMUL);\n            methodVisitor.visitVarInsn(ILOAD, 13);\n            methodVisitor.visitInsn(IADD);\n            methodVisitor.visitVarInsn(ALOAD, 7);\n            methodVisitor.visitVarInsn(ILOAD, 10);\n            methodVisitor.visitInsn(AALOAD);\n            methodVisitor.visitVarInsn(ILOAD, 13);\n            methodVisitor.visitInsn(AALOAD);\n            methodVisitor.visitVarInsn(ILOAD, 12);\n            methodVisitor.visitInsn(IALOAD);\n            methodVisitor.visitInsn(IASTORE);\n            methodVisitor.visitIincInsn(13, 1);\n            methodVisitor.visitJumpInsn(GOTO, label20);\n            methodVisitor.visitLabel(label21);\n            methodVisitor.visitIincInsn(12, 1);\n            methodVisitor.visitJumpInsn(GOTO, label18);\n            methodVisitor.visitLabel(label19);\n            methodVisitor.visitVarInsn(ALOAD, 11);\n            methodVisitor.visitMethodInsn(INVOKESTATIC, memberNames.decryptorClassName, memberNames.resignMethodName, \"([I)[B\", false);\n            methodVisitor.visitInsn(ICONST_0);\n            methodVisitor.visitVarInsn(ALOAD, 9);\n            methodVisitor.visitVarInsn(ILOAD, 10);\n            methodVisitor.visitIntInsn(BIPUSH, 16);\n            methodVisitor.visitInsn(IMUL);\n            methodVisitor.visitVarInsn(ALOAD, 11);\n            methodVisitor.visitInsn(ARRAYLENGTH);\n            methodVisitor.visitMethodInsn(INVOKESTATIC, \"java/lang/System\", \"arraycopy\", \"(Ljava/lang/Object;ILjava/lang/Object;II)V\", false);\n            methodVisitor.visitIincInsn(10, 1);\n            methodVisitor.visitJumpInsn(GOTO, label16);\n            methodVisitor.visitLabel(label17);\n            methodVisitor.visitVarInsn(ALOAD, 9);\n            methodVisitor.visitVarInsn(ALOAD, 9);\n            methodVisitor.visitInsn(ARRAYLENGTH);\n            methodVisitor.visitInsn(ICONST_1);\n            methodVisitor.visitInsn(ISUB);\n            methodVisitor.visitInsn(BALOAD);\n            methodVisitor.visitVarInsn(ISTORE, 10);\n            methodVisitor.visitVarInsn(ALOAD, 9);\n            methodVisitor.visitInsn(ARRAYLENGTH);\n            methodVisitor.visitVarInsn(ILOAD, 10);\n            methodVisitor.visitInsn(ISUB);\n            methodVisitor.visitIntInsn(NEWARRAY, T_BYTE);\n            methodVisitor.visitVarInsn(ASTORE, 11);\n            methodVisitor.visitVarInsn(ALOAD, 9);\n            methodVisitor.visitInsn(ICONST_0);\n            methodVisitor.visitVarInsn(ALOAD, 11);\n            methodVisitor.visitInsn(ICONST_0);\n            methodVisitor.visitVarInsn(ALOAD, 11);\n            methodVisitor.visitInsn(ARRAYLENGTH);\n            methodVisitor.visitMethodInsn(INVOKESTATIC, \"java/lang/System\", \"arraycopy\", \"(Ljava/lang/Object;ILjava/lang/Object;II)V\", false);\n            methodVisitor.visitTypeInsn(NEW, \"java/lang/String\");\n            methodVisitor.visitInsn(DUP);\n            methodVisitor.visitVarInsn(ALOAD, 11);\n            methodVisitor.visitFieldInsn(GETSTATIC, \"java/nio/charset/StandardCharsets\", \"UTF_8\", \"Ljava/nio/charset/Charset;\");\n            methodVisitor.visitMethodInsn(INVOKESPECIAL, \"java/lang/String\", \"<init>\", \"([BLjava/nio/charset/Charset;)V\", false);\n            methodVisitor.visitInsn(ARETURN);\n            methodVisitor.visitMaxs(7, 14);\n            methodVisitor.visitEnd();\n        }\n        {\n            methodVisitor = classWriter.visitMethod(ACC_PUBLIC | ACC_STATIC, memberNames.copyBlockMethodName, \"([[I)[[I\", null, null);\n            methodVisitor.visitCode();\n            methodVisitor.visitVarInsn(ALOAD, 0);\n            methodVisitor.visitInsn(ARRAYLENGTH);\n            methodVisitor.visitVarInsn(ALOAD, 0);\n            methodVisitor.visitInsn(ICONST_0);\n            methodVisitor.visitInsn(AALOAD);\n            methodVisitor.visitInsn(ARRAYLENGTH);\n            methodVisitor.visitMultiANewArrayInsn(\"[[I\", 2);\n            methodVisitor.visitVarInsn(ASTORE, 1);\n            methodVisitor.visitInsn(ICONST_0);\n            methodVisitor.visitVarInsn(ISTORE, 2);\n            Label label0 = new Label();\n            methodVisitor.visitLabel(label0);\n            methodVisitor.visitVarInsn(ILOAD, 2);\n            methodVisitor.visitVarInsn(ALOAD, 0);\n            methodVisitor.visitInsn(ARRAYLENGTH);\n            Label label1 = new Label();\n            methodVisitor.visitJumpInsn(IF_ICMPGE, label1);\n            methodVisitor.visitInsn(ICONST_0);\n            methodVisitor.visitVarInsn(ISTORE, 3);\n            Label label2 = new Label();\n            methodVisitor.visitLabel(label2);\n            methodVisitor.visitVarInsn(ILOAD, 3);\n            methodVisitor.visitVarInsn(ALOAD, 0);\n            methodVisitor.visitInsn(ICONST_0);\n            methodVisitor.visitInsn(AALOAD);\n            methodVisitor.visitInsn(ARRAYLENGTH);\n            Label label3 = new Label();\n            methodVisitor.visitJumpInsn(IF_ICMPGE, label3);\n            methodVisitor.visitVarInsn(ALOAD, 1);\n            methodVisitor.visitVarInsn(ILOAD, 2);\n            methodVisitor.visitInsn(AALOAD);\n            methodVisitor.visitVarInsn(ILOAD, 3);\n            methodVisitor.visitVarInsn(ALOAD, 0);\n            methodVisitor.visitVarInsn(ILOAD, 2);\n            methodVisitor.visitInsn(AALOAD);\n            methodVisitor.visitVarInsn(ILOAD, 3);\n            methodVisitor.visitInsn(IALOAD);\n            methodVisitor.visitInsn(IASTORE);\n            methodVisitor.visitIincInsn(3, 1);\n            methodVisitor.visitJumpInsn(GOTO, label2);\n            methodVisitor.visitLabel(label3);\n            methodVisitor.visitIincInsn(2, 1);\n            methodVisitor.visitJumpInsn(GOTO, label0);\n            methodVisitor.visitLabel(label1);\n            methodVisitor.visitVarInsn(ALOAD, 1);\n            methodVisitor.visitInsn(ARETURN);\n            methodVisitor.visitMaxs(4, 4);\n            methodVisitor.visitEnd();\n        }\n        {\n            methodVisitor = classWriter.visitMethod(ACC_PUBLIC | ACC_STATIC, memberNames.designMethodName, \"([B)[I\", null, null);\n            methodVisitor.visitCode();\n            methodVisitor.visitVarInsn(ALOAD, 0);\n            methodVisitor.visitInsn(ARRAYLENGTH);\n            methodVisitor.visitIntInsn(NEWARRAY, T_INT);\n            methodVisitor.visitVarInsn(ASTORE, 1);\n            methodVisitor.visitInsn(ICONST_0);\n            methodVisitor.visitVarInsn(ISTORE, 2);\n            Label label0 = new Label();\n            methodVisitor.visitLabel(label0);\n            methodVisitor.visitVarInsn(ILOAD, 2);\n            methodVisitor.visitVarInsn(ALOAD, 0);\n            methodVisitor.visitInsn(ARRAYLENGTH);\n            Label label1 = new Label();\n            methodVisitor.visitJumpInsn(IF_ICMPGE, label1);\n            methodVisitor.visitVarInsn(ALOAD, 1);\n            methodVisitor.visitVarInsn(ILOAD, 2);\n            methodVisitor.visitVarInsn(ALOAD, 0);\n            methodVisitor.visitVarInsn(ILOAD, 2);\n            methodVisitor.visitInsn(BALOAD);\n            methodVisitor.visitIntInsn(SIPUSH, 255);\n            methodVisitor.visitInsn(IAND);\n            methodVisitor.visitInsn(IASTORE);\n            methodVisitor.visitIincInsn(2, 1);\n            methodVisitor.visitJumpInsn(GOTO, label0);\n            methodVisitor.visitLabel(label1);\n            methodVisitor.visitVarInsn(ALOAD, 1);\n            methodVisitor.visitInsn(ARETURN);\n            methodVisitor.visitMaxs(4, 3);\n            methodVisitor.visitEnd();\n        }\n        {\n            methodVisitor = classWriter.visitMethod(ACC_PUBLIC | ACC_STATIC, memberNames.resignMethodName, \"([I)[B\", null, null);\n            methodVisitor.visitCode();\n            methodVisitor.visitVarInsn(ALOAD, 0);\n            methodVisitor.visitInsn(ARRAYLENGTH);\n            methodVisitor.visitIntInsn(NEWARRAY, T_BYTE);\n            methodVisitor.visitVarInsn(ASTORE, 1);\n            methodVisitor.visitInsn(ICONST_0);\n            methodVisitor.visitVarInsn(ISTORE, 2);\n            Label label0 = new Label();\n            methodVisitor.visitLabel(label0);\n            methodVisitor.visitVarInsn(ILOAD, 2);\n            methodVisitor.visitVarInsn(ALOAD, 0);\n            methodVisitor.visitInsn(ARRAYLENGTH);\n            Label label1 = new Label();\n            methodVisitor.visitJumpInsn(IF_ICMPGE, label1);\n            methodVisitor.visitVarInsn(ALOAD, 1);\n            methodVisitor.visitVarInsn(ILOAD, 2);\n            methodVisitor.visitVarInsn(ALOAD, 0);\n            methodVisitor.visitVarInsn(ILOAD, 2);\n            methodVisitor.visitInsn(IALOAD);\n            methodVisitor.visitInsn(I2B);\n            methodVisitor.visitInsn(BASTORE);\n            methodVisitor.visitIincInsn(2, 1);\n            methodVisitor.visitJumpInsn(GOTO, label0);\n            methodVisitor.visitLabel(label1);\n            methodVisitor.visitVarInsn(ALOAD, 1);\n            methodVisitor.visitInsn(ARETURN);\n            methodVisitor.visitMaxs(4, 3);\n            methodVisitor.visitEnd();\n        }\n        {\n            methodVisitor = classWriter.visitMethod(ACC_PUBLIC | ACC_STATIC, memberNames.createStateMethodName, \"([I)[[I\", null, null);\n            methodVisitor.visitCode();\n            methodVisitor.visitInsn(ICONST_4);\n            methodVisitor.visitInsn(ICONST_4);\n            methodVisitor.visitMultiANewArrayInsn(\"[[I\", 2);\n            methodVisitor.visitVarInsn(ASTORE, 1);\n            methodVisitor.visitInsn(ICONST_0);\n            methodVisitor.visitVarInsn(ISTORE, 2);\n            Label label0 = new Label();\n            methodVisitor.visitLabel(label0);\n            methodVisitor.visitVarInsn(ILOAD, 2);\n            methodVisitor.visitVarInsn(ALOAD, 0);\n            methodVisitor.visitInsn(ARRAYLENGTH);\n            Label label1 = new Label();\n            methodVisitor.visitJumpInsn(IF_ICMPGE, label1);\n            methodVisitor.visitVarInsn(ALOAD, 1);\n            methodVisitor.visitVarInsn(ILOAD, 2);\n            methodVisitor.visitInsn(ICONST_4);\n            methodVisitor.visitInsn(IREM);\n            methodVisitor.visitInsn(AALOAD);\n            methodVisitor.visitVarInsn(ILOAD, 2);\n            methodVisitor.visitInsn(ICONST_4);\n            methodVisitor.visitInsn(IDIV);\n            methodVisitor.visitVarInsn(ALOAD, 0);\n            methodVisitor.visitVarInsn(ILOAD, 2);\n            methodVisitor.visitInsn(IALOAD);\n            methodVisitor.visitInsn(IASTORE);\n            methodVisitor.visitIincInsn(2, 1);\n            methodVisitor.visitJumpInsn(GOTO, label0);\n            methodVisitor.visitLabel(label1);\n            methodVisitor.visitVarInsn(ALOAD, 1);\n            methodVisitor.visitInsn(ARETURN);\n            methodVisitor.visitMaxs(4, 3);\n            methodVisitor.visitEnd();\n        }\n        {\n            methodVisitor = classWriter.visitMethod(ACC_STATIC, \"<clinit>\", \"()V\", null, null);\n            methodVisitor.visitCode();\n            methodVisitor.visitIntInsn(BIPUSH, 16);\n            methodVisitor.visitIntInsn(BIPUSH, 16);\n            methodVisitor.visitMultiANewArrayInsn(\"[[I\", 2);\n            methodVisitor.visitFieldInsn(PUTSTATIC, memberNames.decryptorClassName, memberNames.sboxFieldName, \"[[I\");\n            methodVisitor.visitInsn(ICONST_1);\n            methodVisitor.visitVarInsn(ISTORE, 0);\n            methodVisitor.visitInsn(ICONST_1);\n            methodVisitor.visitVarInsn(ISTORE, 1);\n            Label label0 = new Label();\n            methodVisitor.visitLabel(label0);\n            methodVisitor.visitInsn(ICONST_3);\n            methodVisitor.visitVarInsn(ILOAD, 0);\n            methodVisitor.visitMethodInsn(INVOKESTATIC, memberNames.decryptorClassName, memberNames.gfMultMethodName, \"(II)I\", false);\n            methodVisitor.visitVarInsn(ISTORE, 0);\n            methodVisitor.visitIntInsn(SIPUSH, 246);\n            methodVisitor.visitVarInsn(ILOAD, 1);\n            methodVisitor.visitMethodInsn(INVOKESTATIC, memberNames.decryptorClassName, memberNames.gfMultMethodName, \"(II)I\", false);\n            methodVisitor.visitVarInsn(ISTORE, 1);\n            methodVisitor.visitVarInsn(ILOAD, 1);\n            methodVisitor.visitVarInsn(ISTORE, 2);\n            methodVisitor.visitVarInsn(ILOAD, 2);\n            methodVisitor.visitVarInsn(ILOAD, 1);\n            methodVisitor.visitInsn(ICONST_1);\n            methodVisitor.visitInsn(ISHL);\n            methodVisitor.visitVarInsn(ILOAD, 1);\n            methodVisitor.visitIntInsn(BIPUSH, 7);\n            methodVisitor.visitInsn(IUSHR);\n            methodVisitor.visitInsn(IOR);\n            methodVisitor.visitIntInsn(SIPUSH, 255);\n            methodVisitor.visitInsn(IAND);\n            methodVisitor.visitInsn(IXOR);\n            methodVisitor.visitVarInsn(ISTORE, 2);\n            methodVisitor.visitVarInsn(ILOAD, 2);\n            methodVisitor.visitVarInsn(ILOAD, 1);\n            methodVisitor.visitInsn(ICONST_2);\n            methodVisitor.visitInsn(ISHL);\n            methodVisitor.visitVarInsn(ILOAD, 1);\n            methodVisitor.visitIntInsn(BIPUSH, 6);\n            methodVisitor.visitInsn(IUSHR);\n            methodVisitor.visitInsn(IOR);\n            methodVisitor.visitIntInsn(SIPUSH, 255);\n            methodVisitor.visitInsn(IAND);\n            methodVisitor.visitInsn(IXOR);\n            methodVisitor.visitVarInsn(ISTORE, 2);\n            methodVisitor.visitVarInsn(ILOAD, 2);\n            methodVisitor.visitVarInsn(ILOAD, 1);\n            methodVisitor.visitInsn(ICONST_3);\n            methodVisitor.visitInsn(ISHL);\n            methodVisitor.visitVarInsn(ILOAD, 1);\n            methodVisitor.visitInsn(ICONST_5);\n            methodVisitor.visitInsn(IUSHR);\n            methodVisitor.visitInsn(IOR);\n            methodVisitor.visitIntInsn(SIPUSH, 255);\n            methodVisitor.visitInsn(IAND);\n            methodVisitor.visitInsn(IXOR);\n            methodVisitor.visitVarInsn(ISTORE, 2);\n            methodVisitor.visitVarInsn(ILOAD, 2);\n            methodVisitor.visitVarInsn(ILOAD, 1);\n            methodVisitor.visitInsn(ICONST_4);\n            methodVisitor.visitInsn(ISHL);\n            methodVisitor.visitVarInsn(ILOAD, 1);\n            methodVisitor.visitInsn(ICONST_4);\n            methodVisitor.visitInsn(IUSHR);\n            methodVisitor.visitInsn(IOR);\n            methodVisitor.visitIntInsn(SIPUSH, 255);\n            methodVisitor.visitInsn(IAND);\n            methodVisitor.visitInsn(IXOR);\n            methodVisitor.visitVarInsn(ISTORE, 2);\n            methodVisitor.visitFieldInsn(GETSTATIC, memberNames.decryptorClassName, memberNames.sboxFieldName, \"[[I\");\n            methodVisitor.visitVarInsn(ILOAD, 0);\n            methodVisitor.visitIntInsn(BIPUSH, 16);\n            methodVisitor.visitInsn(IDIV);\n            methodVisitor.visitInsn(AALOAD);\n            methodVisitor.visitVarInsn(ILOAD, 0);\n            methodVisitor.visitIntInsn(BIPUSH, 16);\n            methodVisitor.visitInsn(IREM);\n            methodVisitor.visitVarInsn(ILOAD, 2);\n            methodVisitor.visitIntInsn(BIPUSH, 99);\n            methodVisitor.visitInsn(IXOR);\n            methodVisitor.visitIntInsn(SIPUSH, 255);\n            methodVisitor.visitInsn(IAND);\n            methodVisitor.visitInsn(IASTORE);\n            methodVisitor.visitVarInsn(ILOAD, 0);\n            methodVisitor.visitInsn(ICONST_1);\n            methodVisitor.visitJumpInsn(IF_ICMPNE, label0);\n            methodVisitor.visitFieldInsn(GETSTATIC, memberNames.decryptorClassName, memberNames.sboxFieldName, \"[[I\");\n            methodVisitor.visitInsn(ICONST_0);\n            methodVisitor.visitInsn(AALOAD);\n            methodVisitor.visitInsn(ICONST_0);\n            methodVisitor.visitIntInsn(BIPUSH, 99);\n            methodVisitor.visitInsn(IASTORE);\n            methodVisitor.visitFieldInsn(GETSTATIC, memberNames.decryptorClassName, memberNames.sboxFieldName, \"[[I\");\n            methodVisitor.visitInsn(ARRAYLENGTH);\n            methodVisitor.visitFieldInsn(GETSTATIC, memberNames.decryptorClassName, memberNames.sboxFieldName, \"[[I\");\n            methodVisitor.visitInsn(ARRAYLENGTH);\n            methodVisitor.visitMultiANewArrayInsn(\"[[I\", 2);\n            methodVisitor.visitFieldInsn(PUTSTATIC, memberNames.decryptorClassName, memberNames.invSBoxFieldName, \"[[I\");\n            methodVisitor.visitInsn(ICONST_0);\n            methodVisitor.visitVarInsn(ISTORE, 2);\n            Label label1 = new Label();\n            methodVisitor.visitLabel(label1);\n            methodVisitor.visitVarInsn(ILOAD, 2);\n            methodVisitor.visitFieldInsn(GETSTATIC, memberNames.decryptorClassName, memberNames.sboxFieldName, \"[[I\");\n            methodVisitor.visitInsn(ARRAYLENGTH);\n            Label label2 = new Label();\n            methodVisitor.visitJumpInsn(IF_ICMPGE, label2);\n            methodVisitor.visitInsn(ICONST_0);\n            methodVisitor.visitVarInsn(ISTORE, 3);\n            Label label3 = new Label();\n            methodVisitor.visitLabel(label3);\n            methodVisitor.visitVarInsn(ILOAD, 3);\n            methodVisitor.visitFieldInsn(GETSTATIC, memberNames.decryptorClassName, memberNames.sboxFieldName, \"[[I\");\n            methodVisitor.visitInsn(ICONST_0);\n            methodVisitor.visitInsn(AALOAD);\n            methodVisitor.visitInsn(ARRAYLENGTH);\n            Label label4 = new Label();\n            methodVisitor.visitJumpInsn(IF_ICMPGE, label4);\n            methodVisitor.visitFieldInsn(GETSTATIC, memberNames.decryptorClassName, memberNames.sboxFieldName, \"[[I\");\n            methodVisitor.visitVarInsn(ILOAD, 2);\n            methodVisitor.visitInsn(AALOAD);\n            methodVisitor.visitVarInsn(ILOAD, 3);\n            methodVisitor.visitInsn(IALOAD);\n            methodVisitor.visitVarInsn(ISTORE, 4);\n            methodVisitor.visitFieldInsn(GETSTATIC, memberNames.decryptorClassName, memberNames.invSBoxFieldName, \"[[I\");\n            methodVisitor.visitVarInsn(ILOAD, 4);\n            methodVisitor.visitInsn(ICONST_4);\n            methodVisitor.visitInsn(ISHR);\n            methodVisitor.visitInsn(AALOAD);\n            methodVisitor.visitVarInsn(ILOAD, 4);\n            methodVisitor.visitIntInsn(BIPUSH, 15);\n            methodVisitor.visitInsn(IAND);\n            methodVisitor.visitVarInsn(ILOAD, 2);\n            methodVisitor.visitInsn(ICONST_4);\n            methodVisitor.visitInsn(ISHL);\n            methodVisitor.visitVarInsn(ILOAD, 3);\n            methodVisitor.visitInsn(IOR);\n            methodVisitor.visitInsn(IASTORE);\n            methodVisitor.visitIincInsn(3, 1);\n            methodVisitor.visitJumpInsn(GOTO, label3);\n            methodVisitor.visitLabel(label4);\n            methodVisitor.visitIincInsn(2, 1);\n            methodVisitor.visitJumpInsn(GOTO, label1);\n            methodVisitor.visitLabel(label2);\n            methodVisitor.visitIntInsn(BIPUSH, 10);\n            methodVisitor.visitIntInsn(NEWARRAY, T_INT);\n            methodVisitor.visitFieldInsn(PUTSTATIC, memberNames.decryptorClassName, memberNames.rconFieldName, \"[I\");\n            methodVisitor.visitInsn(ICONST_0);\n            methodVisitor.visitVarInsn(ISTORE, 2);\n            Label label5 = new Label();\n            methodVisitor.visitLabel(label5);\n            methodVisitor.visitVarInsn(ILOAD, 2);\n            methodVisitor.visitFieldInsn(GETSTATIC, memberNames.decryptorClassName, memberNames.rconFieldName, \"[I\");\n            methodVisitor.visitInsn(ARRAYLENGTH);\n            Label label6 = new Label();\n            methodVisitor.visitJumpInsn(IF_ICMPGE, label6);\n            methodVisitor.visitVarInsn(ILOAD, 2);\n            Label label7 = new Label();\n            methodVisitor.visitJumpInsn(IFNE, label7);\n            methodVisitor.visitFieldInsn(GETSTATIC, memberNames.decryptorClassName, memberNames.rconFieldName, \"[I\");\n            methodVisitor.visitVarInsn(ILOAD, 2);\n            methodVisitor.visitInsn(ICONST_1);\n            methodVisitor.visitInsn(IASTORE);\n            Label label8 = new Label();\n            methodVisitor.visitJumpInsn(GOTO, label8);\n            methodVisitor.visitLabel(label7);\n            methodVisitor.visitFieldInsn(GETSTATIC, memberNames.decryptorClassName, memberNames.rconFieldName, \"[I\");\n            methodVisitor.visitVarInsn(ILOAD, 2);\n            methodVisitor.visitInsn(ICONST_1);\n            methodVisitor.visitInsn(ISUB);\n            methodVisitor.visitInsn(IALOAD);\n            methodVisitor.visitIntInsn(SIPUSH, 128);\n            Label label9 = new Label();\n            methodVisitor.visitJumpInsn(IF_ICMPGE, label9);\n            methodVisitor.visitFieldInsn(GETSTATIC, memberNames.decryptorClassName, memberNames.rconFieldName, \"[I\");\n            methodVisitor.visitVarInsn(ILOAD, 2);\n            methodVisitor.visitInsn(ICONST_2);\n            methodVisitor.visitFieldInsn(GETSTATIC, memberNames.decryptorClassName, memberNames.rconFieldName, \"[I\");\n            methodVisitor.visitVarInsn(ILOAD, 2);\n            methodVisitor.visitInsn(ICONST_1);\n            methodVisitor.visitInsn(ISUB);\n            methodVisitor.visitInsn(IALOAD);\n            methodVisitor.visitInsn(IMUL);\n            methodVisitor.visitInsn(IASTORE);\n            methodVisitor.visitJumpInsn(GOTO, label8);\n            methodVisitor.visitLabel(label9);\n            methodVisitor.visitFieldInsn(GETSTATIC, memberNames.decryptorClassName, memberNames.rconFieldName, \"[I\");\n            methodVisitor.visitVarInsn(ILOAD, 2);\n            methodVisitor.visitInsn(ICONST_1);\n            methodVisitor.visitInsn(ISUB);\n            methodVisitor.visitInsn(IALOAD);\n            methodVisitor.visitIntInsn(SIPUSH, 128);\n            methodVisitor.visitJumpInsn(IF_ICMPLT, label8);\n            methodVisitor.visitFieldInsn(GETSTATIC, memberNames.decryptorClassName, memberNames.rconFieldName, \"[I\");\n            methodVisitor.visitVarInsn(ILOAD, 2);\n            methodVisitor.visitInsn(ICONST_2);\n            methodVisitor.visitFieldInsn(GETSTATIC, memberNames.decryptorClassName, memberNames.rconFieldName, \"[I\");\n            methodVisitor.visitVarInsn(ILOAD, 2);\n            methodVisitor.visitInsn(ICONST_1);\n            methodVisitor.visitInsn(ISUB);\n            methodVisitor.visitInsn(IALOAD);\n            methodVisitor.visitInsn(IMUL);\n            methodVisitor.visitIntInsn(SIPUSH, 283);\n            methodVisitor.visitInsn(IXOR);\n            methodVisitor.visitInsn(IASTORE);\n            methodVisitor.visitLabel(label8);\n            methodVisitor.visitIincInsn(2, 1);\n            methodVisitor.visitJumpInsn(GOTO, label5);\n            methodVisitor.visitLabel(label6);\n            methodVisitor.visitInsn(ICONST_0);\n            methodVisitor.visitVarInsn(ISTORE, 2);\n            Label label10 = new Label();\n            methodVisitor.visitLabel(label10);\n            methodVisitor.visitVarInsn(ILOAD, 2);\n            methodVisitor.visitFieldInsn(GETSTATIC, memberNames.decryptorClassName, memberNames.rconFieldName, \"[I\");\n            methodVisitor.visitInsn(ARRAYLENGTH);\n            Label label11 = new Label();\n            methodVisitor.visitJumpInsn(IF_ICMPGE, label11);\n            methodVisitor.visitFieldInsn(GETSTATIC, memberNames.decryptorClassName, memberNames.rconFieldName, \"[I\");\n            methodVisitor.visitVarInsn(ILOAD, 2);\n            methodVisitor.visitInsn(DUP2);\n            methodVisitor.visitInsn(IALOAD);\n            methodVisitor.visitIntInsn(BIPUSH, 24);\n            methodVisitor.visitInsn(ISHL);\n            methodVisitor.visitInsn(IASTORE);\n            methodVisitor.visitIincInsn(2, 1);\n            methodVisitor.visitJumpInsn(GOTO, label10);\n            methodVisitor.visitLabel(label11);\n            methodVisitor.visitIntInsn(BIPUSH, 15);\n            methodVisitor.visitTypeInsn(ANEWARRAY, \"[I\");\n            methodVisitor.visitFieldInsn(PUTSTATIC, memberNames.decryptorClassName, memberNames.mcTablesFieldName, \"[[I\");\n            methodVisitor.visitFieldInsn(GETSTATIC, memberNames.decryptorClassName, memberNames.mcTablesFieldName, \"[[I\");\n            methodVisitor.visitIntInsn(BIPUSH, 14);\n            methodVisitor.visitIntInsn(SIPUSH, 256);\n            methodVisitor.visitIntInsn(NEWARRAY, T_INT);\n            methodVisitor.visitInsn(AASTORE);\n            methodVisitor.visitFieldInsn(GETSTATIC, memberNames.decryptorClassName, memberNames.mcTablesFieldName, \"[[I\");\n            methodVisitor.visitIntInsn(BIPUSH, 11);\n            methodVisitor.visitIntInsn(SIPUSH, 256);\n            methodVisitor.visitIntInsn(NEWARRAY, T_INT);\n            methodVisitor.visitInsn(AASTORE);\n            methodVisitor.visitFieldInsn(GETSTATIC, memberNames.decryptorClassName, memberNames.mcTablesFieldName, \"[[I\");\n            methodVisitor.visitIntInsn(BIPUSH, 13);\n            methodVisitor.visitIntInsn(SIPUSH, 256);\n            methodVisitor.visitIntInsn(NEWARRAY, T_INT);\n            methodVisitor.visitInsn(AASTORE);\n            methodVisitor.visitFieldInsn(GETSTATIC, memberNames.decryptorClassName, memberNames.mcTablesFieldName, \"[[I\");\n            methodVisitor.visitIntInsn(BIPUSH, 9);\n            methodVisitor.visitIntInsn(SIPUSH, 256);\n            methodVisitor.visitIntInsn(NEWARRAY, T_INT);\n            methodVisitor.visitInsn(AASTORE);\n            methodVisitor.visitInsn(ICONST_0);\n            methodVisitor.visitVarInsn(ISTORE, 2);\n            Label label12 = new Label();\n            methodVisitor.visitLabel(label12);\n            methodVisitor.visitVarInsn(ILOAD, 2);\n            methodVisitor.visitFieldInsn(GETSTATIC, memberNames.decryptorClassName, memberNames.mcTablesFieldName, \"[[I\");\n            methodVisitor.visitInsn(ARRAYLENGTH);\n            Label label13 = new Label();\n            methodVisitor.visitJumpInsn(IF_ICMPGE, label13);\n            methodVisitor.visitFieldInsn(GETSTATIC, memberNames.decryptorClassName, memberNames.mcTablesFieldName, \"[[I\");\n            methodVisitor.visitVarInsn(ILOAD, 2);\n            methodVisitor.visitInsn(AALOAD);\n            Label label14 = new Label();\n            methodVisitor.visitJumpInsn(IFNULL, label14);\n            methodVisitor.visitFieldInsn(GETSTATIC, memberNames.decryptorClassName, memberNames.mcTablesFieldName, \"[[I\");\n            methodVisitor.visitVarInsn(ILOAD, 2);\n            methodVisitor.visitInsn(AALOAD);\n            methodVisitor.visitVarInsn(ASTORE, 3);\n            methodVisitor.visitInsn(ICONST_0);\n            methodVisitor.visitVarInsn(ISTORE, 4);\n            Label label15 = new Label();\n            methodVisitor.visitLabel(label15);\n            methodVisitor.visitVarInsn(ILOAD, 4);\n            methodVisitor.visitVarInsn(ALOAD, 3);\n            methodVisitor.visitInsn(ARRAYLENGTH);\n            methodVisitor.visitJumpInsn(IF_ICMPGE, label14);\n            methodVisitor.visitVarInsn(ALOAD, 3);\n            methodVisitor.visitVarInsn(ILOAD, 4);\n            methodVisitor.visitVarInsn(ILOAD, 2);\n            methodVisitor.visitVarInsn(ILOAD, 4);\n            methodVisitor.visitMethodInsn(INVOKESTATIC, memberNames.decryptorClassName, memberNames.gfMultMethodName, \"(II)I\", false);\n            methodVisitor.visitInsn(IASTORE);\n            methodVisitor.visitIincInsn(4, 1);\n            methodVisitor.visitJumpInsn(GOTO, label15);\n            methodVisitor.visitLabel(label14);\n            methodVisitor.visitIincInsn(2, 1);\n            methodVisitor.visitJumpInsn(GOTO, label12);\n            methodVisitor.visitLabel(label13);\n            methodVisitor.visitInsn(RETURN);\n            methodVisitor.visitMaxs(6, 5);\n            methodVisitor.visitEnd();\n        }\n        classWriter.visitEnd();\n\n        return classWriter;\n    }\n}\n"
  },
  {
    "path": "xyz.itzsomebody.radon/src/main/java/xyz/itzsomebody/radon/transformers/strings/StaticFieldStrPool.java",
    "content": "package xyz.itzsomebody.radon.transformers.strings;\n\nimport org.objectweb.asm.tree.FieldNode;\nimport org.objectweb.asm.tree.LdcInsnNode;\nimport org.objectweb.asm.tree.MethodInsnNode;\nimport org.objectweb.asm.tree.MethodNode;\nimport xyz.itzsomebody.codegen.WrappedType;\nimport xyz.itzsomebody.codegen.expressions.IRExpression;\nimport xyz.itzsomebody.codegen.expressions.IRExpressions;\nimport xyz.itzsomebody.commons.InsnListModifier;\nimport xyz.itzsomebody.radon.transformers.Transformers;\nimport xyz.itzsomebody.radon.utils.asm.ClassWrapper;\nimport xyz.itzsomebody.radon.utils.logging.RadonLogger;\n\nimport java.util.ArrayList;\nimport java.util.concurrent.atomic.AtomicInteger;\n\nimport static xyz.itzsomebody.codegen.expressions.IRExpressions.*;\n\n/**\n * Takes all the strings in a class and stuffs them into a method which initializes a static field when\n * <clinit> is invoked.\n *\n * @author itzsomebody\n */\npublic class StaticFieldStrPool extends StringTransformer {\n    @Override\n    public void transform() {\n        var count = new AtomicInteger();\n        classStream().filter(this::notExcluded).forEach(classWrapper -> {\n            var strList = new ArrayList<String>();\n            var stringPoolInitMethodName = classWrapper.generateNextAllowedMethodName(dictionary.copy(), \"()V\");\n            var stringPoolFieldName = classWrapper.generateNextAllowedFieldName(dictionary.copy(), \"[Ljava/lang/String;\");\n            classWrapper.methodStream().filter(mw -> notExcluded(mw) && mw.hasInstructions()).forEach(methodWrapper -> {\n                if (methodWrapper.getLeewaySize() > allowedLeeway) {\n                    var methodNode = methodWrapper.getMethodNode();\n                    var modifier = new InsnListModifier();\n                    methodNode.instructions.forEach(insn -> {\n                        if (insn instanceof LdcInsnNode && ((LdcInsnNode) insn).cst instanceof String) {\n                            var str = (String) ((LdcInsnNode) insn).cst;\n\n                            if (!isExcludedString(str)) {\n                                modifier.replace(insn, getArrayElement(\n                                        getStatic(WrappedType.fromInternalName(classWrapper.getName(), classWrapper.isInterface()), stringPoolFieldName, WrappedType.from(String[].class)),\n                                        intConst(strList.size())\n                                ).getInstructions().compile());\n                                strList.add(str);\n                                count.incrementAndGet();\n                            }\n                        }\n                    });\n                    modifier.apply(methodNode.instructions);\n                }\n            });\n\n            if (strList.size() != 0) {\n                classWrapper.addMethod(createStringPoolInitializer(classWrapper, stringPoolInitMethodName, stringPoolFieldName, strList));\n\n                var clinit = classWrapper.getMethodNode(\"<clinit>\", \"()V\");\n                if (clinit == null) {\n                    clinit = new MethodNode(ACC_PRIVATE | ACC_STATIC, \"<clinit>\", \"()V\", null, null);\n                    clinit.visitMethodInsn(INVOKESTATIC, classWrapper.getName(), stringPoolInitMethodName, \"()V\", false);\n                    clinit.visitInsn(RETURN);\n                    classWrapper.addMethod(clinit);\n                } else {\n                    clinit.instructions.insert(new MethodInsnNode(INVOKESTATIC, classWrapper.getName(), stringPoolInitMethodName, \"()V\", false));\n                }\n\n                classWrapper.addField(new FieldNode(ACC_PRIVATE | ACC_STATIC | ACC_SYNTHETIC, stringPoolFieldName, \"[Ljava/lang/String;\", null, null));\n            }\n        });\n\n        RadonLogger.info(\"Pooled \" + count.get() + \" strings\");\n    }\n\n    @Override\n    public String getConfigName() {\n        return Transformers.POOL_STRINGS_TO_STATIC_FIELD.getConfigName();\n    }\n\n    private static MethodNode createStringPoolInitializer(ClassWrapper owner, String name, String stringPool, ArrayList<String> strings) {\n        var method = new MethodNode(ACC_PRIVATE | ACC_STATIC | ACC_SYNTHETIC | ACC_BRIDGE, name, \"()V\", null, null);\n        var createArrayExpr = newArray(String.class, strings.stream().map(IRExpressions::stringConst).toArray(IRExpression[]::new));\n        var putStaticExpr = setStatic(WrappedType.fromInternalName(owner.getName(), owner.isInterface()), stringPool, WrappedType.from(String[].class), createArrayExpr);\n        method.instructions = putStaticExpr.getInstructions().voidReturn().compile();\n        return method;\n    }\n}\n"
  },
  {
    "path": "xyz.itzsomebody.radon/src/main/java/xyz/itzsomebody/radon/transformers/strings/Str2Base64Encoding.java",
    "content": "/*\n * Radon - An open-source Java obfuscator\n * Copyright (C) 2020 ItzSomebody\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, either version 3 of the License, or\n * (at your option) any later version.\n *\n * This program is distributed in the hope that it will be 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.  If not, see <http://www.gnu.org/licenses/>\n */\n\npackage xyz.itzsomebody.radon.transformers.strings;\n\nimport com.fasterxml.jackson.annotation.JsonProperty;\nimport org.objectweb.asm.tree.ClassNode;\nimport org.objectweb.asm.tree.LdcInsnNode;\nimport org.objectweb.asm.tree.MethodInsnNode;\nimport org.objectweb.asm.tree.MethodNode;\nimport xyz.itzsomebody.commons.InsnListModifier;\nimport xyz.itzsomebody.radon.config.ConfigurationParser;\nimport xyz.itzsomebody.radon.transformers.Transformers;\nimport xyz.itzsomebody.radon.utils.asm.ClassWrapper;\nimport xyz.itzsomebody.radon.utils.logging.RadonLogger;\n\nimport java.nio.charset.StandardCharsets;\nimport java.util.Base64;\nimport java.util.concurrent.atomic.AtomicInteger;\n\n/**\n * Transformer which encodes Utf8 constants with Base64. This is here just so I can quickly test stuff.\n * Please don't use this and not expect your strings to get decoded, lol.\n *\n * @author itzsomebody\n */\npublic class Str2Base64Encoding extends StringTransformer {\n    @JsonProperty(\"decode_from_random_class\")\n    private boolean decodeFromRandomClass;\n\n    @Override\n    public void transform() {\n        ClassWrapper toInject;\n\n        if (decodeFromRandomClass) {\n            toInject = randomClass();\n        } else {\n            ClassNode cn = new ClassNode();\n            cn.version = V1_5;\n            cn.access = ACC_PUBLIC;\n            cn.name = fakeSubClass();\n            cn.superName = \"java/lang/Object\";\n\n            toInject = new ClassWrapper(cn, false);\n            addClass(toInject);\n        }\n\n        var decryptor = decryptorNode(toInject.generateNextAllowedMethodName(dictionary.copy(), \"(Ljava/lang/String;)Ljava/lang/String;\"));\n        toInject.addMethod(decryptor);\n\n        AtomicInteger count = new AtomicInteger();\n\n        classStream().filter(this::notExcluded).forEach(classWrapper -> {\n            classWrapper.methodStream().filter(mw -> notExcluded(mw) && mw.hasInstructions()).forEach(methodWrapper -> {\n                if (methodWrapper.getLeewaySize() > allowedLeeway) {\n                    var methodNode = methodWrapper.getMethodNode();\n                    var modifier = new InsnListModifier();\n                    methodNode.instructions.forEach(current -> {\n                        if (current instanceof LdcInsnNode && ((LdcInsnNode) current).cst instanceof String) {\n                            ((LdcInsnNode) current).cst = encodeString((String) ((LdcInsnNode) current).cst);\n                            modifier.insert(current, new MethodInsnNode(\n                                    INVOKESTATIC,\n                                    toInject.getName(),\n                                    decryptor.name,\n                                    decryptor.desc,\n                                    toInject.isInterface()\n                            ));\n                            count.incrementAndGet();\n                        }\n                    });\n                    modifier.apply(methodNode.instructions);\n                }\n            });\n        });\n\n        RadonLogger.info(\"Base64 encoded \" + count.get() + \" strings\");\n    }\n\n    @Override\n    public String getConfigName() {\n        return Transformers.STRING_TO_BASE64_ENCODING.getConfigName();\n    }\n\n    public static String encodeString(String s) {\n        // It's important to treat everything as UTF-8\n        return new String(Base64.getEncoder().encode(s.getBytes(StandardCharsets.UTF_8)), StandardCharsets.UTF_8);\n    }\n\n    /**\n     * Template for ASMifier.\n     */\n    public static String decodeString(String s) {\n        return new String(Base64.getDecoder().decode(s.getBytes(StandardCharsets.UTF_8)), StandardCharsets.UTF_8);\n    }\n\n    private MethodNode decryptorNode(String methodName) {\n        var mw = new MethodNode(ACC_PUBLIC | ACC_STATIC | ACC_SYNTHETIC | ACC_BRIDGE, methodName, \"(Ljava/lang/String;)Ljava/lang/String;\", null, null);\n        mw.visitCode();\n        mw.visitTypeInsn(NEW, \"java/lang/String\");\n        mw.visitInsn(DUP);\n        mw.visitMethodInsn(INVOKESTATIC, \"java/util/Base64\", \"getDecoder\", \"()Ljava/util/Base64$Decoder;\", false);\n        mw.visitVarInsn(ALOAD, 0);\n        mw.visitFieldInsn(GETSTATIC, \"java/nio/charset/StandardCharsets\", \"UTF_8\", \"Ljava/nio/charset/Charset;\");\n        mw.visitMethodInsn(INVOKEVIRTUAL, \"java/lang/String\", \"getBytes\", \"(Ljava/nio/charset/Charset;)[B\", false);\n        mw.visitMethodInsn(INVOKEVIRTUAL, \"java/util/Base64$Decoder\", \"decode\", \"([B)[B\", false);\n        mw.visitFieldInsn(GETSTATIC, \"java/nio/charset/StandardCharsets\", \"UTF_8\", \"Ljava/nio/charset/Charset;\");\n        mw.visitMethodInsn(INVOKESPECIAL, \"java/lang/String\", \"<init>\", \"([BLjava/nio/charset/Charset;)V\", false);\n        mw.visitInsn(ARETURN);\n        mw.visitMaxs(5, 2);\n        mw.visitEnd();\n        return mw;\n    }\n\n    enum Base64EncoderKey {\n        DECODE_FROM_RANDOM_CLASS;\n\n        public String getKey() {\n            return name().toLowerCase();\n        }\n    }\n}\n"
  },
  {
    "path": "xyz.itzsomebody.radon/src/main/java/xyz/itzsomebody/radon/transformers/strings/StringTransformer.java",
    "content": "/*\n * Radon - An open-source Java obfuscator\n * Copyright (C) 2020 ItzSomebody\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, either version 3 of the License, or\n * (at your option) any later version.\n *\n * This program is distributed in the hope that it will be 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.  If not, see <http://www.gnu.org/licenses/>\n */\n\npackage xyz.itzsomebody.radon.transformers.strings;\n\nimport com.fasterxml.jackson.annotation.JsonProperty;\nimport xyz.itzsomebody.radon.dictionaries.Dictionary;\nimport xyz.itzsomebody.radon.dictionaries.DictionaryFactory;\nimport xyz.itzsomebody.radon.exclusions.Exclusion;\nimport xyz.itzsomebody.radon.transformers.Transformer;\n\nimport java.util.Set;\n\npublic abstract class StringTransformer extends Transformer {\n    @JsonProperty(\"excluded_strings\")\n    private Set<String> excludedStrings;\n\n    @JsonProperty(\"dictionary\")\n    protected Dictionary dictionary = DictionaryFactory.defaultDictionary();\n\n    @JsonProperty(\"leeway\")\n    protected int allowedLeeway = 5000;\n\n    protected boolean isExcludedString(String s) {\n        return excludedStrings.contains(s);\n    }\n\n    @Override\n    public Exclusion.ExclusionType getExclusionType() {\n        return Exclusion.ExclusionType.STRING_OBFUSCATION;\n    }\n}\n"
  },
  {
    "path": "xyz.itzsomebody.radon/src/main/java/xyz/itzsomebody/radon/utils/IOUtils.java",
    "content": "/*\n * Radon - An open-source Java obfuscator\n * Copyright (C) 2020 ItzSomebody\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, either version 3 of the License, or\n * (at your option) any later version.\n *\n * This program is distributed in the hope that it will be 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.  If not, see <http://www.gnu.org/licenses/>\n */\n\npackage xyz.itzsomebody.radon.utils;\n\nimport xyz.itzsomebody.radon.exceptions.PreventableRadonException;\n\nimport java.io.ByteArrayOutputStream;\nimport java.io.File;\nimport java.io.IOException;\nimport java.io.InputStream;\n\n/**\n * Utility class for various I/O and File operations.\n *\n * @author itzsomebody\n */\npublic class IOUtils {\n    /**\n     * Return a given {@link InputStream} as a byte array.\n     *\n     * @return Byte array representation of provided {@link InputStream}.\n     */\n    public static byte[] toByteArray(final InputStream stream) throws IOException {\n        try (stream; var out = new ByteArrayOutputStream()) {\n            var buf = new byte[0x1000];\n            int bytesRead;\n            while ((bytesRead = stream.read(buf, 0, buf.length)) != -1) {\n                out.write(buf, 0, bytesRead);\n            }\n            out.flush();\n            return out.toByteArray();\n        }\n    }\n\n    /**\n     * Renames a {@link File} and returns the new name.\n     *\n     * @return The new {@link File} name.\n     */\n    public static String renameExistingFile(File existing) {\n        try {\n            var i = 0;\n            while (true) {\n                i++;\n                var newName = existing.getAbsolutePath() + \".BACKUP-\" + i;\n                var backUpName = new File(newName);\n                if (!backUpName.exists()) {\n                    existing.renameTo(backUpName);\n                    return newName;\n                }\n            }\n        } catch (Exception e) {\n            e.printStackTrace(System.out);\n            throw new PreventableRadonException(String.format(\"Could not backup \\\"%s\\\"\", existing.getAbsolutePath()));\n        }\n    }\n}\n"
  },
  {
    "path": "xyz.itzsomebody.radon/src/main/java/xyz/itzsomebody/radon/utils/JarLoader.java",
    "content": "/*\n * Radon - An open-source Java obfuscator\n * Copyright (C) 2020 ItzSomebody\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, either version 3 of the License, or\n * (at your option) any later version.\n *\n * This program is distributed in the hope that it will be 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.  If not, see <http://www.gnu.org/licenses/>\n */\n\npackage xyz.itzsomebody.radon.utils;\n\nimport org.objectweb.asm.ClassReader;\nimport xyz.itzsomebody.radon.RadonConstants;\nimport xyz.itzsomebody.radon.exceptions.FatalRadonException;\nimport xyz.itzsomebody.radon.exceptions.PreventableRadonException;\nimport xyz.itzsomebody.radon.utils.asm.ClassWrapper;\nimport xyz.itzsomebody.radon.utils.logging.RadonLogger;\n\nimport java.io.File;\nimport java.io.IOException;\nimport java.util.HashMap;\nimport java.util.Map;\nimport java.util.zip.ZipEntry;\nimport java.util.zip.ZipException;\nimport java.util.zip.ZipFile;\n\npublic class JarLoader {\n    private final Map<String, ClassWrapper> classes = new HashMap<>();\n    private final Map<String, ClassWrapper> classpath = new HashMap<>();\n    private final Map<String, byte[]> resources = new HashMap<>();\n\n    public void loadAsLib(String path) {\n        RadonLogger.info(\"Loading library \\\"\" + path + \"\\\"\");\n        var file = new File(path);\n\n        if (!file.exists()) {\n            RadonLogger.warn(\"Library \\\"\" + file.getAbsolutePath() + \"\\\" doesn't exist. Skipping\");\n        }\n        if (!file.canRead()) {\n            RadonLogger.warn(\"Library \\\"\" + file.getAbsolutePath() + \"\\\" doesn't have read permissions. Skipping\");\n        }\n        if (!file.isFile()) {\n            RadonLogger.warn(\"Library \\\"\" + file.getAbsolutePath() + \"\\\" isn't a file. Skipping\");\n        }\n\n        try {\n            var zipFile = new ZipFile(file);\n            var entries = zipFile.entries();\n\n            ZipEntry currentEntry;\n            while (entries.hasMoreElements()) {\n                currentEntry = entries.nextElement();\n\n                if (!currentEntry.isDirectory() && currentEntry.getName().endsWith(\".class\")) {\n                    try (var stream = zipFile.getInputStream(currentEntry)) {\n                        var wrapper = ClassWrapper.fromLib(new ClassReader(stream));\n                        classpath.put(wrapper.getName(), wrapper);\n                    } catch (Throwable t) {\n                        RadonLogger.warn(String.format(\"Error while loading library class: \\\"%s\\\"\", currentEntry.getName()));\n\n                        if (RadonConstants.VERBOSE) {\n                            t.printStackTrace();\n                        }\n                    }\n                }\n            }\n        } catch (ZipException e) {\n            RadonLogger.warn(\"Library \\\"\" + file.getAbsolutePath() + \"\\\" couldn't be loaded as a ZIP. Skipping\");\n\n            if (RadonConstants.VERBOSE) {\n                e.printStackTrace();\n            }\n        } catch (IOException e) {\n            RadonLogger.warn(\"Library \\\"\" + file.getAbsolutePath() + \"\\\" couldn't be loaded due to an IO error\" + e.getMessage());\n\n            if (RadonConstants.VERBOSE) {\n                e.printStackTrace();\n            }\n        }\n    }\n\n    public void loadAsInput(String path) {\n        RadonLogger.info(\"Loading input \\\"\" + path + \"\\\"\");\n        var file = new File(path);\n\n        if (!file.exists()) {\n            throw new PreventableRadonException(\"Input \\\"\" + file.getAbsolutePath() + \"\\\" doesn't exist\");\n        }\n        if (!file.canRead()) {\n            throw new PreventableRadonException(\"Input \\\"\" + file.getAbsolutePath() + \"\\\" doesn't have read permissions\");\n        }\n        if (!file.isFile()) {\n            throw new PreventableRadonException(\"Input \\\"\" + file.getAbsolutePath() + \"\\\" isn't a file\");\n        }\n\n        try {\n            var zipFile = new ZipFile(file);\n            var entries = zipFile.entries();\n\n            ZipEntry currentEntry;\n            while (entries.hasMoreElements()) {\n                currentEntry = entries.nextElement();\n\n                if (!currentEntry.isDirectory()) {\n                    try (var stream = zipFile.getInputStream(currentEntry)) {\n                        if (currentEntry.getName().endsWith(\".class\")) {\n                            try {\n                                var wrapper = ClassWrapper.from(new ClassReader(stream));\n                                classes.put(wrapper.getName(), wrapper);\n                                classpath.put(wrapper.getName(), wrapper);\n                            } catch (Throwable t) {\n                                RadonLogger.warn(String.format(\"Error while loading input class: \\\"%s\\\" (loading as resources instead)\", currentEntry.getName()));\n                                resources.put(currentEntry.getName(), IOUtils.toByteArray(stream));\n                            }\n                        } else {\n                            resources.put(currentEntry.getName(), IOUtils.toByteArray(stream));\n                        }\n                    }\n                }\n            }\n        } catch (ZipException e) {\n            throw new PreventableRadonException(\"Input \\\"\" + file.getAbsolutePath() + \"\\\" couldn't be loaded as a ZIP. (\" + e.getMessage() + \")\");\n        } catch (IOException e) {\n            throw new PreventableRadonException(\"Input \\\"\" + file.getAbsolutePath() + \"\\\" couldn't be due to an IO error. (\" + e.getMessage() + \")\");\n        }\n    }\n\n    public Map<String, ClassWrapper> getClasses() {\n        return classes;\n    }\n\n    public Map<String, ClassWrapper> getClasspath() {\n        return classpath;\n    }\n\n    public Map<String, byte[]> getResources() {\n        return resources;\n    }\n}\n"
  },
  {
    "path": "xyz.itzsomebody.radon/src/main/java/xyz/itzsomebody/radon/utils/JarWriter.java",
    "content": "/*\n * Radon - An open-source Java obfuscator\n * Copyright (C) 2020 ItzSomebody\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, either version 3 of the License, or\n * (at your option) any later version.\n *\n * This program is distributed in the hope that it will be 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.  If not, see <http://www.gnu.org/licenses/>\n */\n\npackage xyz.itzsomebody.radon.utils;\n\nimport xyz.itzsomebody.radon.Radon;\nimport xyz.itzsomebody.radon.RadonConstants;\nimport xyz.itzsomebody.radon.config.ObfConfig;\nimport xyz.itzsomebody.radon.exceptions.FatalRadonException;\nimport xyz.itzsomebody.radon.exceptions.PreventableRadonException;\nimport xyz.itzsomebody.radon.utils.logging.RadonLogger;\n\nimport java.io.File;\nimport java.io.FileOutputStream;\nimport java.io.IOException;\nimport java.nio.charset.StandardCharsets;\nimport java.util.HashSet;\nimport java.util.zip.CRC32;\nimport java.util.zip.Deflater;\nimport java.util.zip.ZipEntry;\nimport java.util.zip.ZipOutputStream;\n\npublic class JarWriter {\n    private int fakeIndex;\n\n    public void write(String path) {\n        var radon = Radon.getInstance();\n\n        var level = radon.config.compressionLevel;\n        var store = radon.config.useStore;\n        var corruptCrcs = radon.config.corruptCrcs;\n        var antiExtraction = radon.config.antiExtraction;\n        var fakeEntries = radon.config.fakeDuplicateEntries;\n\n        if (corruptCrcs && store) {\n            // fixme: maybe check this when loading config so people don't get annoyed that this wasn't checked until jar write\n            throw new PreventableRadonException(\"Cannot use store and corrupt_crcs together\");\n        }\n\n        var classes = radon.getClasses();\n        var resources = radon.getResources();\n\n        RadonLogger.info(String.format(\"Writing output to \\\"%s\\\"\", path));\n        var file = new File(path);\n\n        if (file.exists()) {\n            RadonLogger.info(String.format(\"Output already exists! Backed up to \\\"%s\\\"\", IOUtils.renameExistingFile(file)));\n        }\n\n        try {\n            var stream = new ZipOutputStream(new FileOutputStream(file));\n\n            stream.setLevel(level);\n            if (fakeEntries > 0) {\n                disableNameCache(stream);\n            }\n            if (store) {\n                stream.setMethod(ZipOutputStream.STORED);\n                stream.setLevel(Deflater.NO_COMPRESSION);\n            }\n            if (corruptCrcs) {\n                injectCrcCorrupter(stream);\n            }\n\n            classes.forEach(((name, wrapper) -> {\n                try {\n                    // The fact that this incredibly stupid but simple anti-extraction trick works simply blows my mind\n                    var entry = new ZipEntry(wrapper.getName() + \".class\" + (antiExtraction ? \"/\" : \"\"));\n                    var data = wrapper.toByteArray();\n                    writeEntry(stream, entry, data, store);\n                    if (antiExtraction) {\n                        writeAntiExtractionEntries(stream, entry.getName(), store);\n                    }\n\n                    if (fakeEntries > 0) {\n                        for (int i = 0; i < fakeEntries; i++) {\n                            var fakeEntry = new ZipEntry(entry.getName());\n                            var fakeData = RandomUtils.randomBytes();\n                            writeEntry(stream, fakeEntry, fakeData, store);\n\n                            if (antiExtraction) {\n                                writeAntiExtractionEntries(stream, fakeEntry.getName(), store);\n                            }\n                        }\n                    }\n                } catch (Throwable t) {\n                    RadonLogger.warn(String.format(\"An error happened while writing class \\\"%s\\\"\", name));\n\n                    if (RadonConstants.VERBOSE) {\n                        t.printStackTrace();\n                    }\n                }\n            }));\n\n            resources.forEach((name, data) -> {\n                try {\n                    writeEntry(stream, new ZipEntry(name), data, store);\n                } catch (IOException ioe) {\n                    RadonLogger.warn(String.format(\"An IO error happened while writing resource \\\"%s\\\"\", name));\n\n                    if (RadonConstants.VERBOSE) {\n                        ioe.printStackTrace();\n                    }\n                }\n            });\n\n            stream.setComment(radon.config.zipComment);\n            stream.close();\n        } catch (IOException ioe) {\n            if (RadonConstants.VERBOSE) {\n                ioe.printStackTrace();\n            }\n\n            throw new FatalRadonException(\"An IO error happened while writing output: \" + ioe.getMessage());\n        }\n    }\n\n    private void writeAntiExtractionEntries(ZipOutputStream stream, String name, boolean store) throws IOException {\n        // index entry\n        var localIndex = fakeIndex++;\n        var indexBytes = new byte[]{ // Completely unnecessary, but fun so why not lol\n                (byte) localIndex,\n                (byte) (localIndex >>> 8),\n                (byte) (localIndex >>> 16),\n                (byte) (localIndex >>> 24)\n        };\n        writeEntry(stream, new ZipEntry(name + \"index\"), indexBytes, store);\n\n        // name entry\n        writeEntry(stream, new ZipEntry(name + \"name\"), name.substring(0, name.length() - 1).getBytes(StandardCharsets.UTF_8), store);\n\n        // data_offset entry\n        var randomInt = RandomUtils.randomInt();\n        var randomIntBytes = new byte[]{ // lmao, here we go again\n                (byte) randomInt,\n                (byte) (randomInt >>> 8),\n                (byte) (randomInt >>> 16),\n                (byte) (randomInt >>> 24)\n        };\n        writeEntry(stream, new ZipEntry(name + \"data_offset\"), randomIntBytes, store);\n    }\n\n    private void writeEntry(ZipOutputStream stream, ZipEntry entry, byte[] data, boolean store) throws IOException {\n        if (store) {\n            populateStoredEntryInfo(entry, data);\n        }\n\n        stream.putNextEntry(entry);\n        stream.write(data);\n        stream.closeEntry();\n    }\n\n    private void disableNameCache(ZipOutputStream stream) {\n        // For reasons beyond my comprehension, this is 100% legal to do\n        try {\n            var clazz = ZipOutputStream.class;\n            var field = clazz.getDeclaredField(\"names\");\n            field.setAccessible(true);\n            field.set(stream, new HashSet<>(0) {\n                @Override\n                public boolean add(Object o) {\n                    // lol git rekt\n                    return true;\n                }\n            });\n        } catch (NoSuchFieldException | IllegalAccessException e) {\n            throw new FatalRadonException(\"Error while attempting to disable ZipOutputString name cache: \" + e.toString());\n        }\n    }\n\n    private void injectCrcCorrupter(ZipOutputStream stream) {\n        // tl;dr: \"oh man the zip format is really f***ed\"\n        // ~samczsun\n        try {\n            var clazz = ZipOutputStream.class;\n            var field = clazz.getDeclaredField(\"crc\");\n            field.setAccessible(true);\n            field.set(stream, new CRC32() {\n                @Override\n                public void update(byte[] b, int off, int len) {\n                    // Don't update the CRC\n                }\n\n                @Override\n                public long getValue() {\n                    return RandomUtils.randomLong(0xFFFFFFFFL);\n                }\n            });\n        } catch (NoSuchFieldException | IllegalAccessException e) {\n            throw new FatalRadonException(\"Error while attempting to inject CRC corrupter: \" + e.toString());\n        }\n    }\n\n    private void populateStoredEntryInfo(ZipEntry entry, byte[] data) {\n        var crc = new CRC32();\n        crc.update(data);\n\n        entry.setCrc(crc.getValue());\n        entry.setSize(data.length);\n        entry.setCompressedSize(data.length);\n    }\n}\n"
  },
  {
    "path": "xyz.itzsomebody.radon/src/main/java/xyz/itzsomebody/radon/utils/RandomUtils.java",
    "content": "/*\n * Radon - An open-source Java obfuscator\n * Copyright (C) 2020 ItzSomebody\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, either version 3 of the License, or\n * (at your option) any later version.\n *\n * This program is distributed in the hope that it will be 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.  If not, see <http://www.gnu.org/licenses/>\n */\n\npackage xyz.itzsomebody.radon.utils;\n\nimport java.util.concurrent.ThreadLocalRandom;\n\npublic class RandomUtils {\n    private static ThreadLocalRandom instance() {\n        return ThreadLocalRandom.current();\n    }\n\n    // --------\n    // Integers\n    // --------\n\n    public static int randomInt(int origin, int bound) {\n        return instance().nextInt(origin, bound);\n    }\n\n    public static int randomInt(int bound) {\n        return instance().nextInt(bound);\n    }\n\n    public static int randomInt() {\n        return instance().nextInt();\n    }\n\n    // -----\n    // Longs\n    // -----\n\n    public static long randomLong(long origin, long bound) {\n        return instance().nextLong(origin, bound);\n    }\n\n    public static long randomLong(long bound) {\n        return instance().nextLong(bound);\n    }\n\n    public static long randomLong() {\n        return instance().nextLong();\n    }\n\n    // ------\n    // Floats\n    // ------\n\n    public static float randomFloat(float origin, float bound) {\n        if (origin >= bound) {\n            throw new IllegalArgumentException(\"bound must be greater than origin\");\n        }\n\n        float r = (float)((randomInt()) >>> 8) * 5.9604645E-8F;\n        if (origin < bound) {\n            r = r * (bound - origin) + origin;\n            if (r >= bound) {\n                r = Float.intBitsToFloat(Float.floatToIntBits(bound) - 1);\n            }\n        }\n\n        return r;\n    }\n\n    public static float randomFloat(float bound) {\n        if (bound <= 0.0F) {\n            throw new IllegalArgumentException(\"bound must be positive\");\n        }\n\n        float r = (float)((randomInt()) >>> 8) * 5.9604645E-8F;\n        return r < bound ? r : Float.intBitsToFloat(Float.floatToIntBits(bound) - 1);\n    }\n\n    public static float randomFloat() {\n        return instance().nextFloat();\n    }\n\n    // --------\n    // Doubles\n    // --------\n\n    public static double randomDouble(double origin, double bound) {\n        return instance().nextDouble(origin, bound);\n    }\n\n    public static double randomDouble(double bound) {\n        return instance().nextDouble(bound);\n    }\n\n    public static double randomDouble() {\n        return instance().nextDouble();\n    }\n\n    // -----\n    // Misc.\n    // -----\n\n    public static boolean randomBoolean() {\n        return instance().nextBoolean();\n    }\n\n    public static byte[] randomBytes(int length) {\n        var arr = new byte[length];\n        instance().nextBytes(arr);\n        return arr;\n    }\n\n    public static byte[] randomBytes() {\n        var arr = new byte[randomInt(0xFFFF)];\n        instance().nextBytes(arr);\n        return arr;\n    }\n}\n"
  },
  {
    "path": "xyz.itzsomebody.radon/src/main/java/xyz/itzsomebody/radon/utils/asm/ASMUtils.java",
    "content": "/*\n * Radon - An open-source Java obfuscator\n * Copyright (C) 2021 ItzSomebody\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, either version 3 of the License, or\n * (at your option) any later version.\n *\n * This program is distributed in the hope that it will be 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.  If not, see <http://www.gnu.org/licenses/>\n */\n\npackage xyz.itzsomebody.radon.utils.asm;\n\nimport org.objectweb.asm.Opcodes;\nimport org.objectweb.asm.tree.AbstractInsnNode;\nimport org.objectweb.asm.tree.InsnNode;\nimport org.objectweb.asm.tree.IntInsnNode;\nimport org.objectweb.asm.tree.LdcInsnNode;\nimport xyz.itzsomebody.radon.exceptions.FatalRadonException;\n\npublic class ASMUtils {\n    public static AbstractInsnNode getNumberInsn(int number) {\n        if (number >= -1 && number <= 5)\n            return new InsnNode(number + 3);\n        else if (number >= -128 && number <= 127)\n            return new IntInsnNode(Opcodes.BIPUSH, number);\n        else if (number >= -32768 && number <= 32767)\n            return new IntInsnNode(Opcodes.SIPUSH, number);\n        else\n            return new LdcInsnNode(number);\n    }\n\n    public static AbstractInsnNode getNumberInsn(long number) {\n        if (number == 0L || number == 1L)\n            return new InsnNode((int) (number + 9));\n        else\n            return new LdcInsnNode(number);\n    }\n\n    public static AbstractInsnNode getNumberInsn(float number) {\n        if (number == 0F || number == 1F || number == 2F) {\n            return new InsnNode((int) (number + 11));\n        } else {\n            return new LdcInsnNode(number);\n        }\n    }\n\n    public static AbstractInsnNode getNumberInsn(double number) {\n        if (number == 0D || number == 1D)\n            return new InsnNode((int) (number + 14));\n        else\n            return new LdcInsnNode(number);\n    }\n\n    public static int getIntegerFromInsn(AbstractInsnNode insn) {\n        int opcode = insn.getOpcode();\n\n        if (opcode >= Opcodes.ICONST_M1 && opcode <= Opcodes.ICONST_5) {\n            return opcode - 3;\n        } else if (insn instanceof IntInsnNode && insn.getOpcode() != Opcodes.NEWARRAY) {\n            return ((IntInsnNode) insn).operand;\n        } else if (insn instanceof LdcInsnNode && ((LdcInsnNode) insn).cst instanceof Integer) {\n            return (Integer) ((LdcInsnNode) insn).cst;\n        }\n\n        throw new FatalRadonException(\"Attempted to get integer constant from \" + insn.getOpcode() + \" : \" + insn);\n    }\n}\n"
  },
  {
    "path": "xyz.itzsomebody.radon/src/main/java/xyz/itzsomebody/radon/utils/asm/ClassWrapper.java",
    "content": "/*\n * Radon - An open-source Java obfuscator\n * Copyright (C) 2020 ItzSomebody\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, either version 3 of the License, or\n * (at your option) any later version.\n *\n * This program is distributed in the hope that it will be 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.  If not, see <http://www.gnu.org/licenses/>\n */\n\npackage xyz.itzsomebody.radon.utils.asm;\n\nimport org.objectweb.asm.ClassReader;\nimport org.objectweb.asm.ClassWriter;\nimport org.objectweb.asm.Opcodes;\nimport org.objectweb.asm.tree.ClassNode;\nimport org.objectweb.asm.tree.FieldNode;\nimport org.objectweb.asm.tree.MethodNode;\nimport xyz.itzsomebody.radon.Radon;\nimport xyz.itzsomebody.radon.RadonConstants;\nimport xyz.itzsomebody.radon.config.ObfConfig;\nimport xyz.itzsomebody.radon.dictionaries.Dictionary;\nimport xyz.itzsomebody.radon.utils.logging.RadonLogger;\n\nimport java.util.ArrayList;\nimport java.util.List;\nimport java.util.stream.Stream;\n\n/**\n * Wrapper around {@link ClassNode}.\n *\n * @author itzsomebody\n */\npublic class ClassWrapper implements Opcodes {\n    private static final int LIB_READER_FLAGS = ClassReader.SKIP_FRAMES | ClassReader.SKIP_DEBUG | ClassReader.SKIP_CODE;\n    private static final int INPUT_READER_FLAGS = ClassReader.SKIP_FRAMES;\n    private static final int CP_COUNT_OFFSET = 0x4 + 0x2 + 0x2; // https://docs.oracle.com/javase/specs/jvms/se11/html/jvms-4.html#jvms-4.1\n\n    private ClassNode classNode;\n    private final String originalName;\n    private final boolean libraryNode;\n\n    private final List<MethodWrapper> methods;\n    private final List<FieldWrapper> fields;\n\n    private final List<ClassWrapper> parents = new ArrayList<>();\n    private final List<ClassWrapper> children = new ArrayList<>();\n\n    public List<String> utf8Consts = new ArrayList<>() {\n        {\n            add(\"RADON\" + RadonConstants.VERSION);\n        }\n    };\n\n    public ClassWrapper(ClassReader reader, boolean libraryNode) {\n        var classNode = new ClassNode();\n        reader.accept(classNode, libraryNode ? LIB_READER_FLAGS : INPUT_READER_FLAGS);\n\n        this.classNode = classNode;\n        this.originalName = classNode.name;\n        this.libraryNode = libraryNode;\n\n        this.methods = MethodWrappers.from(this);\n        this.fields = FieldWrappers.from(this);\n    }\n\n    public ClassWrapper(ClassNode classNode, boolean libraryNode) {\n        this.classNode = classNode;\n        this.originalName = classNode.name;\n        this.libraryNode = libraryNode;\n\n        this.methods = MethodWrappers.from(this);\n        this.fields = FieldWrappers.from(this);\n    }\n\n    // -----------------\n    // Getters / Setters\n    // -----------------\n\n    public ClassNode getClassNode() {\n        return classNode;\n    }\n\n    public void setClassNode(ClassNode classNode) {\n        this.classNode = classNode;\n    }\n\n    public String getName() {\n        return classNode.name;\n    }\n\n    public String getSuperName() {\n        return classNode.superName;\n    }\n\n    public List<String> getInterfaceNames() {\n        return classNode.interfaces;\n    }\n\n    public String getOriginalName() {\n        return originalName;\n    }\n\n    public boolean isLibraryNode() {\n        return libraryNode;\n    }\n\n    public List<MethodWrapper> getMethods() {\n        return methods;\n    }\n\n    public Stream<MethodWrapper> methodStream() {\n        return getMethods().stream();\n    }\n\n    public List<FieldWrapper> getFields() {\n        return fields;\n    }\n\n    public Stream<FieldWrapper> fieldStream() {\n        return getFields().stream();\n    }\n\n    public List<ClassWrapper> getParents() {\n        return parents;\n    }\n\n    public List<ClassWrapper> getChildren() {\n        return children;\n    }\n\n    // ------------\n    // Access stuff\n    // ------------\n\n    public void addAccessFlags(int flags) {\n        classNode.access |= flags;\n    }\n\n    public void removeAccessFlags(int flags) {\n        classNode.access &= ~flags;\n    }\n\n    public boolean isPublic() {\n        return (classNode.access & ACC_PUBLIC) != 0;\n    }\n\n    public boolean isPrivate() {\n        return (classNode.access & ACC_PRIVATE) != 0;\n    }\n\n    public boolean isProtected() {\n        return (classNode.access & ACC_PROTECTED) != 0;\n    }\n\n    public boolean isFinal() {\n        return (classNode.access & ACC_FINAL) != 0;\n    }\n\n    public boolean isSuper() {\n        return (classNode.access & ACC_SUPER) != 0;\n    }\n\n    public boolean isInterface() {\n        return (classNode.access & ACC_INTERFACE) != 0;\n    }\n\n    public boolean isAbstract() {\n        return (classNode.access & ACC_ABSTRACT) != 0;\n    }\n\n    public boolean isSynthetic() {\n        return (classNode.access & ACC_SYNTHETIC) != 0;\n    }\n\n    public boolean isAnnotation() {\n        return (classNode.access & ACC_ANNOTATION) != 0;\n    }\n\n    public boolean isEnum() {\n        return (classNode.access & ACC_ENUM) != 0;\n    }\n\n    public boolean isModule() {\n        return (classNode.access & ACC_MODULE) != 0;\n    }\n\n    public boolean isRecord() {\n        return (classNode.access & ACC_RECORD) != 0;\n    }\n\n    public boolean isDeprecated() {\n        return (classNode.access & ACC_DEPRECATED) != 0;\n    }\n\n    // -----\n    // Misc.\n    // -----\n\n    /**\n     * Adds a {@link MethodNode} to this {@link ClassWrapper}.\n     *\n     * @param methodNode {@link MethodNode} to add.\n     */\n    public void addMethod(MethodNode methodNode) {\n        classNode.methods.add(methodNode);\n        methods.add(MethodWrapper.from(methodNode, this));\n    }\n\n    /**\n     * Adds a {@link FieldNode} to this {@link ClassWrapper}.\n     *\n     * @param fieldNode {@link FieldNode} to add.\n     */\n    public void addField(FieldNode fieldNode) {\n        classNode.fields.add(fieldNode);\n        fields.add(FieldWrapper.from(fieldNode, this));\n    }\n\n    public MethodNode getMethodNode(String name, String desc) {\n        return classNode.methods.stream().filter(methodNode -> name.equals(methodNode.name) && desc.equals(methodNode.desc)).findAny().orElse(null);\n    }\n\n    public FieldNode getFieldNode(String name, String desc) {\n        return classNode.fields.stream().filter(fieldNode -> name.equals(fieldNode.name) && desc.equals(fieldNode.desc)).findAny().orElse(null);\n    }\n\n    public boolean containsMethodNode(String name, String desc) {\n        return classNode.methods.stream().anyMatch(methodNode -> name.equals(methodNode.name) && desc.equals(methodNode.desc));\n    }\n\n    public boolean containsFieldNode(String name, String desc) {\n        return classNode.fields.stream().anyMatch(fieldNode -> name.equals(fieldNode.name) && desc.equals(fieldNode.desc));\n    }\n\n    public String generateNextAllowedMethodName(Dictionary dictionary, String desc) {\n        String name = dictionary.next();\n        while (containsMethodNode(name, desc)) {\n            name = dictionary.next();\n        }\n        return name;\n    }\n\n    public String generateNextAllowedFieldName(Dictionary dictionary, String desc) {\n        String name = dictionary.next();\n        while (containsFieldNode(name, desc)) {\n            name = dictionary.next();\n        }\n        return name;\n    }\n\n    /**\n     * Returns true if the class allows dynamic constants (Java 11 and above).\n     */\n    public boolean allowsConstDy() {\n        return (classNode.version >= V11) && (classNode.version != V1_1);\n    }\n\n    /**\n     * Returns true if this class allows invokedynamic instructions (Java 7 and above).\n     */\n    public boolean allowsIndy() {\n        return (classNode.version >= V1_7) && (classNode.version != V1_1);\n    }\n\n    /**\n     * Returns true if this class allows JSR and RET instructions (Java 5 and below).\n     */\n    public boolean allowsJsr() {\n        return (classNode.version <= V1_5) || (classNode.version == V1_1);\n    }\n\n    public boolean hasVisibleAnnotations() {\n        return classNode.visibleAnnotations != null && classNode.visibleAnnotations.size() > 0;\n    }\n\n    /**\n     * Returns the count of the constant pool of the classfile this {@link ClassWrapper} represents.\n     * <p>\n     * This is done by writing the class bytes via {@link ClassWriter} with flags set to 0. The constant pool count is\n     * then manually constructed by directly accessing the relevant offsets. This is computationally expensive and should\n     * be done sparingly\n     */\n    public int computePoolCount() {\n        // Hopefully setting flags to 0 doesn't affect CP count\n        // If it does then pepega\n        var writer = new ClassWriter(0);\n        utf8Consts.forEach(writer::newUTF8);\n        classNode.accept(writer);\n\n        // Grab byte array\n        var bytes = writer.toByteArray();\n\n        // Construct unsigned short\n        // todo: check to make sure this isn't broken\n        return ((bytes[CP_COUNT_OFFSET] & 0xFF) << 8) | (bytes[CP_COUNT_OFFSET + 1] & 0xFF);\n    }\n\n    public void addUtf8Const(String s) {\n        utf8Consts.add(s);\n    }\n\n    /**\n     * Converts the class this {@link ClassWrapper} represents into a byte array.\n     */\n    public byte[] toByteArray() {\n        var attemptMaxs = Radon.getInstance().config.attemptComputeMaxs;\n        ClassWriter classWriter = new RadonClassWriter(ClassWriter.COMPUTE_FRAMES);\n\n        try {\n            // Write all non-essential (manually made) entries first\n            utf8Consts.forEach(classWriter::newUTF8);\n\n            // Do the rest\n            classNode.accept(classWriter);\n            return classWriter.toByteArray();\n        } catch (Throwable t) {\n            if (attemptMaxs) {\n                RadonLogger.warn(String.format(\"Error writing class %s. Skipping frames (might cause runtime errors).\", classNode.name + \".class\"));\n                t.printStackTrace(System.out);\n\n                classWriter = new ClassWriter(ClassWriter.COMPUTE_MAXS);\n\n                // Write all non-essential (manually inserted) utf8 entries first\n                utf8Consts.forEach(classWriter::newUTF8);\n\n                // Do the rest\n                classNode.accept(classWriter);\n                return classWriter.toByteArray();\n            } else {\n                throw t;\n            }\n        }\n    }\n\n    public static ClassWrapper from(ClassReader reader) {\n        return new ClassWrapper(reader, false);\n    }\n\n    public static ClassWrapper fromLib(ClassReader reader) {\n        return new ClassWrapper(reader, true);\n    }\n}\n"
  },
  {
    "path": "xyz.itzsomebody.radon/src/main/java/xyz/itzsomebody/radon/utils/asm/FieldWrapper.java",
    "content": "/*\n * Radon - An open-source Java obfuscator\n * Copyright (C) 2020 ItzSomebody\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, either version 3 of the License, or\n * (at your option) any later version.\n *\n * This program is distributed in the hope that it will be 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.  If not, see <http://www.gnu.org/licenses/>\n */\n\npackage xyz.itzsomebody.radon.utils.asm;\n\nimport org.objectweb.asm.Opcodes;\nimport org.objectweb.asm.tree.FieldNode;\n\n/**\n * Wrapper around {@link FieldNode}.\n *\n * @author itzsomebody\n */\npublic class FieldWrapper implements Opcodes {\n    private FieldNode fieldNode;\n    private final String originalName;\n    private final String originalType;\n    private final ClassWrapper owner;\n\n    public FieldWrapper(FieldNode fieldNode, ClassWrapper owner) {\n        this.fieldNode = fieldNode;\n        this.originalName = fieldNode.name;\n        this.originalType = fieldNode.desc;\n        this.owner = owner;\n    }\n\n    // -----------------\n    // Getters / Setters\n    // -----------------\n\n    public FieldNode getFieldNode() {\n        return fieldNode;\n    }\n\n    public void setFieldNode(FieldNode fieldNode) {\n        this.fieldNode = fieldNode;\n    }\n\n    public String getOriginalName() {\n        return originalName;\n    }\n\n    public String getOriginalType() {\n        return originalType;\n    }\n\n    public ClassWrapper getOwner() {\n        return owner;\n    }\n\n    // ------------\n    // Access stuff\n    // ------------\n\n    public void addAccessFlags(int flags) {\n        fieldNode.access |= flags;\n    }\n\n    public void removeAccessFlags(int flags) {\n        fieldNode.access &= ~flags;\n    }\n\n    public boolean isPublic() {\n        return (ACC_PUBLIC & fieldNode.access) != 0;\n    }\n\n    public boolean isPrivate() {\n        return (ACC_PRIVATE & fieldNode.access) != 0;\n    }\n\n    public boolean isProtected() {\n        return (ACC_PROTECTED & fieldNode.access) != 0;\n    }\n\n    public boolean isStatic() {\n        return (ACC_STATIC & fieldNode.access) != 0;\n    }\n\n    public boolean isFinal() {\n        return (ACC_FINAL & fieldNode.access) != 0;\n    }\n\n    public boolean isVolatile() {\n        return (ACC_PUBLIC & fieldNode.access) != 0;\n    }\n\n    public boolean isTransient() {\n        return (ACC_PUBLIC & fieldNode.access) != 0;\n    }\n\n    public boolean isSynthetic() {\n        return (ACC_SYNTHETIC & fieldNode.access) != 0;\n    }\n\n    public boolean isDeprecated() {\n        return (ACC_DEPRECATED & fieldNode.access) != 0;\n    }\n\n    // -----\n    // Misc.\n    // -----\n\n    public static FieldWrapper from(FieldNode FieldNode, ClassWrapper owner) {\n        return new FieldWrapper(FieldNode, owner);\n    }\n\n    public boolean hasVisibleAnnotations() {\n        return fieldNode.visibleAnnotations != null && fieldNode.visibleAnnotations.size() > 0;\n    }\n}\n"
  },
  {
    "path": "xyz.itzsomebody.radon/src/main/java/xyz/itzsomebody/radon/utils/asm/FieldWrappers.java",
    "content": "/*\n * Radon - An open-source Java obfuscator\n * Copyright (C) 2020 ItzSomebody\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, either version 3 of the License, or\n * (at your option) any later version.\n *\n * This program is distributed in the hope that it will be 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.  If not, see <http://www.gnu.org/licenses/>\n */\n\npackage xyz.itzsomebody.radon.utils.asm;\n\nimport java.util.ArrayList;\nimport java.util.List;\n\npublic class FieldWrappers {\n    public static List<FieldWrapper> from(ClassWrapper classWrapper) {\n        var classNode = classWrapper.getClassNode();\n        var fieldWrappers = new ArrayList<FieldWrapper>();\n        classNode.fields.forEach(fieldNode -> fieldWrappers.add(FieldWrapper.from(fieldNode, classWrapper)));\n\n        return fieldWrappers;\n    }\n}\n"
  },
  {
    "path": "xyz.itzsomebody.radon/src/main/java/xyz/itzsomebody/radon/utils/asm/MethodWrapper.java",
    "content": "/*\n * Radon - An open-source Java obfuscator\n * Copyright (C) 2020 ItzSomebody\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, either version 3 of the License, or\n * (at your option) any later version.\n *\n * This program is distributed in the hope that it will be 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.  If not, see <http://www.gnu.org/licenses/>\n */\n\npackage xyz.itzsomebody.radon.utils.asm;\n\nimport org.objectweb.asm.Opcodes;\nimport org.objectweb.asm.commons.CodeSizeEvaluator;\nimport org.objectweb.asm.tree.MethodNode;\n\n/**\n * Wrapper around {@link MethodNode}.\n *\n * @author itzsomebody\n */\npublic class MethodWrapper implements Opcodes {\n    /*\n     * From https://docs.oracle.com/javase/specs/jvms/se11/html/jvms-4.html#jvms-4.7.3\n     *\n     * Note that even though the specification lists an unsigned 32-bit integer size for code_length, the verifier gets\n     * mad if any method has a code_length > 0xFFFF\n     */\n    private static final int MAX_CODE_SIZE = 0xFFFF;\n\n    private MethodNode methodNode;\n    private final String originalName;\n    private final String originalDescriptor;\n    private final ClassWrapper owner;\n\n    public MethodWrapper(MethodNode methodNode, ClassWrapper owner) {\n        this.methodNode = methodNode;\n        this.originalName = methodNode.name;\n        this.originalDescriptor = methodNode.desc;\n        this.owner = owner;\n    }\n\n    // -----------------\n    // Getters / Setters\n    // -----------------\n\n    public MethodNode getMethodNode() {\n        return methodNode;\n    }\n\n    public void setMethodNode(MethodNode methodNode) {\n        this.methodNode = methodNode;\n    }\n\n    public String getOriginalName() {\n        return originalName;\n    }\n\n    public String getOriginalDescriptor() {\n        return originalDescriptor;\n    }\n\n    public ClassWrapper getOwner() {\n        return owner;\n    }\n\n    // ------------\n    // Access stuff\n    // ------------\n\n    public void addAccessFlags(int flags) {\n        methodNode.access |= flags;\n    }\n\n    public void removeAccessFlags(int flags) {\n        methodNode.access &= ~flags;\n    }\n\n    public boolean isPublic() {\n        return (ACC_PUBLIC & methodNode.access) != 0;\n    }\n\n    public boolean isPrivate() {\n        return (ACC_PRIVATE & methodNode.access) != 0;\n    }\n\n    public boolean isProtected() {\n        return (ACC_PROTECTED & methodNode.access) != 0;\n    }\n\n    public boolean isStatic() {\n        return (ACC_STATIC & methodNode.access) != 0;\n    }\n\n    public boolean isFinal() {\n        return (ACC_FINAL & methodNode.access) != 0;\n    }\n\n    public boolean isSynchronized() {\n        return (ACC_SYNCHRONIZED & methodNode.access) != 0;\n    }\n\n    public boolean isBridge() {\n        return (ACC_BRIDGE & methodNode.access) != 0;\n    }\n\n    public boolean isVarargs() {\n        return (ACC_VARARGS & methodNode.access) != 0;\n    }\n\n    public boolean isNative() {\n        return (ACC_NATIVE & methodNode.access) != 0;\n    }\n\n    public boolean isAbstract() {\n        return (ACC_ABSTRACT & methodNode.access) != 0;\n    }\n\n    public boolean isStrict() {\n        return (ACC_STRICT & methodNode.access) != 0;\n    }\n\n    public boolean isSynthetic() {\n        return (ACC_SYNTHETIC & methodNode.access) != 0;\n    }\n\n    public boolean isMandated() {\n        return (ACC_MANDATED & methodNode.access) != 0;\n    }\n\n    public boolean isDeprecated() {\n        return (ACC_DEPRECATED & methodNode.access) != 0;\n    }\n\n    // -----\n    // Misc.\n    // -----\n\n    public boolean hasInstructions() {\n        return methodNode.instructions.size() > 0;\n    }\n\n    public boolean hasVisibleAnnotations() {\n        return methodNode.visibleAnnotations != null && methodNode.visibleAnnotations.size() > 0;\n    }\n\n    public int getCodeSize() {\n        CodeSizeEvaluator evaluator = new CodeSizeEvaluator(null);\n        methodNode.accept(evaluator);\n        return evaluator.getMaxSize();\n    }\n\n    public int getLeewaySize() {\n        return MAX_CODE_SIZE - getCodeSize();\n    }\n\n    public int allocateLocalVar(boolean twoWords) {\n        methodNode.maxLocals += (twoWords ? 2 : 1);\n        return methodNode.maxLocals - 1;\n    }\n\n    public static MethodWrapper from(MethodNode methodNode, ClassWrapper owner) {\n        return new MethodWrapper(methodNode, owner);\n    }\n}\n"
  },
  {
    "path": "xyz.itzsomebody.radon/src/main/java/xyz/itzsomebody/radon/utils/asm/MethodWrappers.java",
    "content": "/*\n * Radon - An open-source Java obfuscator\n * Copyright (C) 2020 ItzSomebody\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, either version 3 of the License, or\n * (at your option) any later version.\n *\n * This program is distributed in the hope that it will be 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.  If not, see <http://www.gnu.org/licenses/>\n */\n\npackage xyz.itzsomebody.radon.utils.asm;\n\nimport java.util.ArrayList;\nimport java.util.List;\n\npublic class MethodWrappers {\n    public static List<MethodWrapper> from(ClassWrapper classWrapper) {\n        var classNode = classWrapper.getClassNode();\n        var methodWrappers = new ArrayList<MethodWrapper>();\n        classNode.methods.forEach(methodNode -> methodWrappers.add(MethodWrapper.from(methodNode, classWrapper)));\n\n        return methodWrappers;\n    }\n}\n"
  },
  {
    "path": "xyz.itzsomebody.radon/src/main/java/xyz/itzsomebody/radon/utils/asm/RadonClassWriter.java",
    "content": "/*\n * Radon - An open-source Java obfuscator\n * Copyright (C) 2020 ItzSomebody\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, either version 3 of the License, or\n * (at your option) any later version.\n *\n * This program is distributed in the hope that it will be 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.  If not, see <http://www.gnu.org/licenses/>\n */\n\npackage xyz.itzsomebody.radon.utils.asm;\n\nimport org.objectweb.asm.ClassWriter;\nimport xyz.itzsomebody.radon.Radon;\n\nimport java.util.ArrayDeque;\nimport java.util.HashSet;\n\n/**\n * Custom-implemented version of {@link ClassWriter} which doesn't use the internal JVM classpath when computing\n * stackmap frames.\n *\n * TODO: Perhaps consider creating fully-worked out hierarchies for JVM runtime classes so we don't have to keep checking huge jars\n * TODO: Implement shadow classes\n *\n * @author itzsomebody\n */\npublic class RadonClassWriter extends ClassWriter {\n    private static final Radon radon = Radon.getInstance();\n\n    public RadonClassWriter(int flags) {\n        super(flags);\n    }\n\n    @Override\n    protected String getCommonSuperClass(final String type1, final String type2) {\n        if (\"java/lang/Object\".equals(type1) || \"java/lang/Object\".equals(type2))\n            return \"java/lang/Object\";\n\n        String first = deriveCommonSuperName(type1, type2);\n        String second = deriveCommonSuperName(type2, type1);\n        if (!\"java/lang/Object\".equals(first)) {\n            return first;\n        }\n        if (!\"java/lang/Object\".equals(second)) {\n            return second;\n        }\n\n        return getCommonSuperClass(radon.getClasspathWrapper(type1).getSuperName(), radon.getClasspathWrapper(type2).getSuperName());\n    }\n\n    private String deriveCommonSuperName(final String type1, final String type2) {\n        ClassWrapper first = radon.getClasspathWrapper(type1);\n        ClassWrapper second = radon.getClasspathWrapper(type2);\n        if (isAssignableFrom(type1, type2)) {\n            return type1;\n        } else if (isAssignableFrom(type2, type1)) {\n            return type2;\n        } else if (first.isInterface() || second.isInterface()) {\n            return \"java/lang/Object\";\n        } else {\n            String temp;\n\n            do {\n                temp = first.getSuperName();\n                first = radon.getClasspathWrapper(temp);\n            } while (!isAssignableFrom(temp, type2));\n            return temp;\n        }\n    }\n\n    private boolean isAssignableFrom(String type1, String type2) {\n        if (\"java/lang/Object\".equals(type1)) {\n            return true;\n        }\n        if (type1.equals(type2)) {\n            return true;\n        }\n\n        ClassWrapper first = radon.getClasspathWrapper(type1);\n        radon.getClasspathWrapper(type2); // Ensure type2 was loaded at some point\n\n        var allChildren = new HashSet<String>();\n        var toProcess = new ArrayDeque<String>();\n        first.getChildren().forEach(child -> {\n            toProcess.add(child.getName());\n        });\n\n        while (!toProcess.isEmpty()) {\n            String next = toProcess.poll();\n\n            if (allChildren.add(next)) {\n                ClassWrapper temp = radon.getClasspathWrapper(next);\n                temp.getChildren().forEach(child -> {\n                    toProcess.add(child.getName());\n                });\n            }\n        }\n        return allChildren.contains(type2);\n    }\n}\n"
  },
  {
    "path": "xyz.itzsomebody.radon/src/main/java/xyz/itzsomebody/radon/utils/asm/RadonRemapper.java",
    "content": "/*\n * Radon - An open-source Java obfuscator\n * Copyright (C) 2021 ItzSomebody\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, either version 3 of the License, or\n * (at your option) any later version.\n *\n * This program is distributed in the hope that it will be 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.  If not, see <http://www.gnu.org/licenses/>\n */\n\npackage xyz.itzsomebody.radon.utils.asm;\n\nimport org.objectweb.asm.commons.SimpleRemapper;\n\nimport java.util.Map;\n\npublic class RadonRemapper extends SimpleRemapper {\n    public RadonRemapper(Map<String, String> mappings) {\n        super(mappings);\n    }\n\n    @Override\n    public String mapFieldName(String owner, String name, String descriptor) {\n        String remappedName = map(owner + '.' + name + ' ' + descriptor);\n        return (remappedName != null) ? remappedName : name;\n    }\n}\n"
  },
  {
    "path": "xyz.itzsomebody.radon/src/main/java/xyz/itzsomebody/radon/utils/asm/ResourceNameRemapper.java",
    "content": "/*\n * Radon - An open-source Java obfuscator\n * Copyright (C) 2021 ItzSomebody\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, either version 3 of the License, or\n * (at your option) any later version.\n *\n * This program is distributed in the hope that it will be 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.  If not, see <http://www.gnu.org/licenses/>\n */\n\npackage xyz.itzsomebody.radon.utils.asm;\n\nimport org.objectweb.asm.ClassVisitor;\nimport org.objectweb.asm.MethodVisitor;\nimport org.objectweb.asm.Opcodes;\n\nimport java.util.Map;\n\n// Stupid way remapping resource names, but works for the most part\n// If you want to do an *actual* job of this, you should use the SourceInterpreter to update strings arguments\n// to methods that grab resources by their name\npublic class ResourceNameRemapper extends ClassVisitor {\n    private final Map<String, String> mappings;\n    private final String internalName;\n\n    public ResourceNameRemapper(ClassVisitor visitor, Map<String, String> mappings, String internalName) {\n        this(/* latest api */ Opcodes.ASM9, visitor, mappings, internalName);\n    }\n\n    protected ResourceNameRemapper(int api, ClassVisitor visitor, Map<String, String> mappings, String internalName) {\n        super(api, visitor);\n        this.mappings = mappings;\n        this.internalName = internalName;\n    }\n\n    @Override\n    public MethodVisitor visitMethod(int access, String name, String descriptor, String signature, String[] exceptions) {\n        return new ResourceNameMethodRemapper(super.visitMethod(\n                access,\n                name,\n                descriptor,\n                signature,\n                exceptions\n        ));\n    }\n\n    class ResourceNameMethodRemapper extends MethodVisitor {\n        ResourceNameMethodRemapper(MethodVisitor visitor) {\n            this(/* latest api */ Opcodes.ASM9, visitor);\n        }\n\n        ResourceNameMethodRemapper(int api, MethodVisitor visitor) {\n            super(api, visitor);\n        }\n\n        @Override\n        public void visitLdcInsn(Object value) {\n            if (value instanceof String) {\n                String strValue = (String) value;\n                String fullResourcePath;\n\n                if (strValue.startsWith(\"/\")) { // JAR root case\n                    fullResourcePath = strValue.substring(1);\n                } else { // relative path case\n                    int index = internalName.lastIndexOf('/');\n                    if (index == -1) {\n                        fullResourcePath = \"\"; // Already at root\n                    } else {\n                        fullResourcePath = internalName.substring(0, index + 1) + strValue;\n                    }\n                }\n\n                if (mappings.containsKey(fullResourcePath)) {\n                    super.visitLdcInsn(mappings.get(fullResourcePath));\n                } else {\n                    super.visitLdcInsn(value);\n                }\n                return;\n            }\n            super.visitLdcInsn(value);\n        }\n    }\n}\n"
  },
  {
    "path": "xyz.itzsomebody.radon/src/main/java/xyz/itzsomebody/radon/utils/logging/RadonConsoleHandler.java",
    "content": "/*\n * Radon - An open-source Java obfuscator\n * Copyright (C) 2020 ItzSomebody\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, either version 3 of the License, or\n * (at your option) any later version.\n *\n * This program is distributed in the hope that it will be 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.  If not, see <http://www.gnu.org/licenses/>\n */\n\npackage xyz.itzsomebody.radon.utils.logging;\n\nimport xyz.itzsomebody.radon.RadonConstants;\n\nimport java.text.SimpleDateFormat;\nimport java.util.Date;\nimport java.util.logging.Formatter;\nimport java.util.logging.LogRecord;\nimport java.util.logging.StreamHandler;\n\n/**\n * A {@link StreamHandler} which outputs to stdout ({@link System#out}).\n *\n * @author itzsomebody\n */\npublic class RadonConsoleHandler extends StreamHandler {\n    /**\n     * Constructs a {@link StreamHandler} which outputs to stdout ({@link System#out}).\n     * <p>\n     * The {@link String} pushed into stdout is composed of a timestamp, level, and message.\n     */\n    public RadonConsoleHandler() {\n        super(System.out, new Formatter() {\n            @Override\n            public String format(final LogRecord record) {\n                var formatStr = \"[%s] %s: %s\\n\";\n                var dateStr = new SimpleDateFormat(RadonConstants.LOG_TIMESTAMP_FORMAT).format(new Date(record.getMillis()));\n                var levelName = record.getLevel().getName();\n                var formattedMsg = formatMessage(record);\n\n                return String.format(formatStr, dateStr, levelName, formattedMsg);\n            }\n        });\n    }\n}"
  },
  {
    "path": "xyz.itzsomebody.radon/src/main/java/xyz/itzsomebody/radon/utils/logging/RadonLogger.java",
    "content": "/*\n * Radon - An open-source Java obfuscator\n * Copyright (C) 2020 ItzSomebody\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, either version 3 of the License, or\n * (at your option) any later version.\n *\n * This program is distributed in the hope that it will be 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.  If not, see <http://www.gnu.org/licenses/>\n */\n\npackage xyz.itzsomebody.radon.utils.logging;\n\nimport xyz.itzsomebody.radon.RadonConstants;\nimport xyz.itzsomebody.radon.RadonMain;\n\nimport java.util.logging.Logger;\n\n/**\n * Wrapper around {@link Logger} to push messages into stdout ({@link System#out}). Parent handler inheritance is\n * switched off.\n *\n * @author itzsomebody\n */\npublic class RadonLogger {\n    /**\n     * Static instance of {@link Logger#getAnonymousLogger()}.\n     */\n    private static final Logger LOGGER;\n\n    static {\n        if (RadonConstants.VERBOSE) {\n            System.out.println(\"[RadonLogger] Bootstrapping logger\");\n        }\n\n        LOGGER = Logger.getLogger(\"RadonLogger\");\n        if (RadonConstants.VERBOSE) {\n            System.out.println(\"[RadonLogger] Created logger instance\");\n        }\n\n        LOGGER.setUseParentHandlers(false); // Avoid parent handler inheritance\n        if (RadonConstants.VERBOSE) {\n            System.out.println(\"[RadonLogger] Disabled parent handler inheritance\");\n        }\n\n        LOGGER.addHandler(new RadonConsoleHandler());\n        if (RadonConstants.VERBOSE) {\n            System.out.println(\"[RadonLogger] Registered console handler\");\n        }\n    }\n\n    /**\n     * Pushes provided message into stdout ({@link System#out}) via {@link Logger#info(String)}.\n     *\n     * @param msg Message to output into stdout ({@link System#out}).\n     */\n    public static void info(final String msg) {\n        LOGGER.info(msg);\n    }\n\n    /**\n     * Pushes provided message into stdout ({@link System#out}) via {@link Logger#warning(String)}.\n     *\n     * @param msg Message to output into stdout ({@link System#out}).\n     */\n    public static void warn(final String msg) {\n        LOGGER.warning(msg);\n    }\n\n    /**\n     * Pushes provided message into stdout ({@link System#out}) via {@link Logger#severe(String)}.\n     *\n     * @param msg Message to output into stdout ({@link System#out}).\n     */\n    public static void severe(final String msg) {\n        LOGGER.severe(msg);\n    }\n}\n"
  },
  {
    "path": "xyz.itzsomebody.radon/src/main/resources/asm-license.txt",
    "content": " ASM: a very small and fast Java bytecode manipulation framework\n Copyright (c) 2000-2011 INRIA, France Telecom\n All rights reserved.\n\n Redistribution and use in source and binary forms, with or without\n modification, are permitted provided that the following conditions\n are met:\n 1. Redistributions of source code must retain the above copyright\n    notice, this list of conditions and the following disclaimer.\n 2. Redistributions in binary form must reproduce the above copyright\n    notice, this list of conditions and the following disclaimer in the\n    documentation and/or other materials provided with the distribution.\n 3. Neither the name of the copyright holders nor the names of its\n    contributors may be used to endorse or promote products derived from\n    this software without specific prior written permission.\n\n THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\"\n AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\n IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE\n ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE\n LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR\n CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF\n SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS\n INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN\n CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)\n ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF\n THE POSSIBILITY OF SUCH DAMAGE.\n"
  },
  {
    "path": "xyz.itzsomebody.radon/src/main/resources/jackson-license.txt",
    "content": "\n                                 Apache License\n                           Version 2.0, January 2004\n                        http://www.apache.org/licenses/\n\n   TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION\n\n   1. Definitions.\n\n      \"License\" shall mean the terms and conditions for use, reproduction,\n      and distribution as defined by Sections 1 through 9 of this document.\n\n      \"Licensor\" shall mean the copyright owner or entity authorized by\n      the copyright owner that is granting the License.\n\n      \"Legal Entity\" shall mean the union of the acting entity and all\n      other entities that control, are controlled by, or are under common\n      control with that entity. For the purposes of this definition,\n      \"control\" means (i) the power, direct or indirect, to cause the\n      direction or management of such entity, whether by contract or\n      otherwise, or (ii) ownership of fifty percent (50%) or more of the\n      outstanding shares, or (iii) beneficial ownership of such entity.\n\n      \"You\" (or \"Your\") shall mean an individual or Legal Entity\n      exercising permissions granted by this License.\n\n      \"Source\" form shall mean the preferred form for making modifications,\n      including but not limited to software source code, documentation\n      source, and configuration files.\n\n      \"Object\" form shall mean any form resulting from mechanical\n      transformation or translation of a Source form, including but\n      not limited to compiled object code, generated documentation,\n      and conversions to other media types.\n\n      \"Work\" shall mean the work of authorship, whether in Source or\n      Object form, made available under the License, as indicated by a\n      copyright notice that is included in or attached to the work\n      (an example is provided in the Appendix below).\n\n      \"Derivative Works\" shall mean any work, whether in Source or Object\n      form, that is based on (or derived from) the Work and for which the\n      editorial revisions, annotations, elaborations, or other modifications\n      represent, as a whole, an original work of authorship. For the purposes\n      of this License, Derivative Works shall not include works that remain\n      separable from, or merely link (or bind by name) to the interfaces of,\n      the Work and Derivative Works thereof.\n\n      \"Contribution\" shall mean any work of authorship, including\n      the original version of the Work and any modifications or additions\n      to that Work or Derivative Works thereof, that is intentionally\n      submitted to Licensor for inclusion in the Work by the copyright owner\n      or by an individual or Legal Entity authorized to submit on behalf of\n      the copyright owner. For the purposes of this definition, \"submitted\"\n      means any form of electronic, verbal, or written communication sent\n      to the Licensor or its representatives, including but not limited to\n      communication on electronic mailing lists, source code control systems,\n      and issue tracking systems that are managed by, or on behalf of, the\n      Licensor for the purpose of discussing and improving the Work, but\n      excluding communication that is conspicuously marked or otherwise\n      designated in writing by the copyright owner as \"Not a Contribution.\"\n\n      \"Contributor\" shall mean Licensor and any individual or Legal Entity\n      on behalf of whom a Contribution has been received by Licensor and\n      subsequently incorporated within the Work.\n\n   2. Grant of Copyright License. Subject to the terms and conditions of\n      this License, each Contributor hereby grants to You a perpetual,\n      worldwide, non-exclusive, no-charge, royalty-free, irrevocable\n      copyright license to reproduce, prepare Derivative Works of,\n      publicly display, publicly perform, sublicense, and distribute the\n      Work and such Derivative Works in Source or Object form.\n\n   3. Grant of Patent License. Subject to the terms and conditions of\n      this License, each Contributor hereby grants to You a perpetual,\n      worldwide, non-exclusive, no-charge, royalty-free, irrevocable\n      (except as stated in this section) patent license to make, have made,\n      use, offer to sell, sell, import, and otherwise transfer the Work,\n      where such license applies only to those patent claims licensable\n      by such Contributor that are necessarily infringed by their\n      Contribution(s) alone or by combination of their Contribution(s)\n      with the Work to which such Contribution(s) was submitted. If You\n      institute patent litigation against any entity (including a\n      cross-claim or counterclaim in a lawsuit) alleging that the Work\n      or a Contribution incorporated within the Work constitutes direct\n      or contributory patent infringement, then any patent licenses\n      granted to You under this License for that Work shall terminate\n      as of the date such litigation is filed.\n\n   4. Redistribution. You may reproduce and distribute copies of the\n      Work or Derivative Works thereof in any medium, with or without\n      modifications, and in Source or Object form, provided that You\n      meet the following conditions:\n\n      (a) You must give any other recipients of the Work or\n          Derivative Works a copy of this License; and\n\n      (b) You must cause any modified files to carry prominent notices\n          stating that You changed the files; and\n\n      (c) You must retain, in the Source form of any Derivative Works\n          that You distribute, all copyright, patent, trademark, and\n          attribution notices from the Source form of the Work,\n          excluding those notices that do not pertain to any part of\n          the Derivative Works; and\n\n      (d) If the Work includes a \"NOTICE\" text file as part of its\n          distribution, then any Derivative Works that You distribute must\n          include a readable copy of the attribution notices contained\n          within such NOTICE file, excluding those notices that do not\n          pertain to any part of the Derivative Works, in at least one\n          of the following places: within a NOTICE text file distributed\n          as part of the Derivative Works; within the Source form or\n          documentation, if provided along with the Derivative Works; or,\n          within a display generated by the Derivative Works, if and\n          wherever such third-party notices normally appear. The contents\n          of the NOTICE file are for informational purposes only and\n          do not modify the License. You may add Your own attribution\n          notices within Derivative Works that You distribute, alongside\n          or as an addendum to the NOTICE text from the Work, provided\n          that such additional attribution notices cannot be construed\n          as modifying the License.\n\n      You may add Your own copyright statement to Your modifications and\n      may provide additional or different license terms and conditions\n      for use, reproduction, or distribution of Your modifications, or\n      for any such Derivative Works as a whole, provided Your use,\n      reproduction, and distribution of the Work otherwise complies with\n      the conditions stated in this License.\n\n   5. Submission of Contributions. Unless You explicitly state otherwise,\n      any Contribution intentionally submitted for inclusion in the Work\n      by You to the Licensor shall be under the terms and conditions of\n      this License, without any additional terms or conditions.\n      Notwithstanding the above, nothing herein shall supersede or modify\n      the terms of any separate license agreement you may have executed\n      with Licensor regarding such Contributions.\n\n   6. Trademarks. This License does not grant permission to use the trade\n      names, trademarks, service marks, or product names of the Licensor,\n      except as required for reasonable and customary use in describing the\n      origin of the Work and reproducing the content of the NOTICE file.\n\n   7. Disclaimer of Warranty. Unless required by applicable law or\n      agreed to in writing, Licensor provides the Work (and each\n      Contributor provides its Contributions) on an \"AS IS\" BASIS,\n      WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or\n      implied, including, without limitation, any warranties or conditions\n      of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A\n      PARTICULAR PURPOSE. You are solely responsible for determining the\n      appropriateness of using or redistributing the Work and assume any\n      risks associated with Your exercise of permissions under this License.\n\n   8. Limitation of Liability. In no event and under no legal theory,\n      whether in tort (including negligence), contract, or otherwise,\n      unless required by applicable law (such as deliberate and grossly\n      negligent acts) or agreed to in writing, shall any Contributor be\n      liable to You for damages, including any direct, indirect, special,\n      incidental, or consequential damages of any character arising as a\n      result of this License or out of the use or inability to use the\n      Work (including but not limited to damages for loss of goodwill,\n      work stoppage, computer failure or malfunction, or any and all\n      other commercial damages or losses), even if such Contributor\n      has been advised of the possibility of such damages.\n\n   9. Accepting Warranty or Additional Liability. While redistributing\n      the Work or Derivative Works thereof, You may choose to offer,\n      and charge a fee for, acceptance of support, warranty, indemnity,\n      or other liability obligations and/or rights consistent with this\n      License. However, in accepting such obligations, You may act only\n      on Your own behalf and on Your sole responsibility, not on behalf\n      of any other Contributor, and only if You agree to indemnify,\n      defend, and hold each Contributor harmless for any liability\n      incurred by, or claims asserted against, such Contributor by reason\n      of your accepting any such warranty or additional liability.\n\n   END OF TERMS AND CONDITIONS\n\n   APPENDIX: How to apply the Apache License to your work.\n\n      To apply the Apache License to your work, attach the following\n      boilerplate notice, with the fields enclosed by brackets \"[]\"\n      replaced with your own identifying information. (Don't include\n      the brackets!)  The text should be enclosed in the appropriate\n      comment syntax for the file format. We also recommend that a\n      file or class name and description of purpose be included on the\n      same \"printed page\" as the copyright notice for easier\n      identification within third-party archives.\n\n   Copyright [yyyy] [name of copyright owner]\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"
  },
  {
    "path": "xyz.itzsomebody.radon/src/main/resources/radon-license.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 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 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 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 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 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 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 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": "xyz.itzsomebody.radon/src/test/java/me/itzsomebody/radon/transformers/TransformersTest.java",
    "content": "package me.itzsomebody.radon.transformers;\n\nimport org.junit.Assert;\nimport org.junit.Test;\nimport xyz.itzsomebody.radon.exclusions.Exclusion;\nimport xyz.itzsomebody.radon.transformers.Transformers;\nimport xyz.itzsomebody.radon.transformers.strings.StringTransformer;\n\npublic class TransformersTest {\n    @Test\n    public void ensureTransformerExclusionTypeNonNull() throws Exception {\n        for (var transformerEnum : Transformers.values()) {\n            var transformerConstructor = transformerEnum.getTransformerClass().getConstructor();\n            transformerConstructor.setAccessible(true);\n            var transformerInstance = transformerConstructor.newInstance();\n\n            // Often I'm dumb and forget to put an exclusion type\n            Assert.assertNotNull(transformerInstance.getExclusionType());\n        }\n    }\n\n    @Test\n    public void ensureTransformerConfigNameNonNull() throws Exception{\n        for (var transformerEnum : Transformers.values()) {\n            var transformerConstructor = transformerEnum.getTransformerClass().getConstructor();\n            transformerConstructor.setAccessible(true);\n            var transformerInstance = transformerConstructor.newInstance();\n\n            Assert.assertNotNull(transformerInstance.getConfigName());\n        }\n    }\n\n    @Test\n    public void ensureTransformerExclusionTypeNameIsSameAsConfigName() throws Exception{\n        for (var transformerEnum : Transformers.values()) {\n            var transformerConstructor = transformerEnum.getTransformerClass().getConstructor();\n            transformerConstructor.setAccessible(true);\n            var transformerInstance = transformerConstructor.newInstance();\n\n            if (transformerInstance instanceof StringTransformer) {\n                // Skip -- mostly likely no problem here\n            } else {\n                Assert.assertEquals(transformerInstance.getConfigName(), transformerInstance.getExclusionType().name().toLowerCase());\n            }\n        }\n    }\n}\n"
  },
  {
    "path": "xyz.itzsomebody.radon.template/build.gradle",
    "content": "/*\n * Radon - An open-source Java obfuscator\n * Copyright (C) 2021 ItzSomebody\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, either version 3 of the License, or\n * (at your option) any later version.\n *\n * This program is distributed in the hope that it will be 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.  If not, see <http://www.gnu.org/licenses/>\n */\n\nplugins {\n    id 'java'\n}\n\nsourceCompatibility = javaVer\n\ndependencies {\n    testImplementation junit\n}\n"
  },
  {
    "path": "xyz.itzsomebody.radon.template/src/README.md",
    "content": "# Template\n\nThis module contains various template classes to use with ASMifier.\n"
  },
  {
    "path": "xyz.itzsomebody.radon.template/src/main/java/xyz/itzsomebody/radon/templates/string/AESPCBCDecryptor.java",
    "content": "package xyz.itzsomebody.radon.templates.string;\n\nimport java.nio.charset.StandardCharsets;\nimport java.util.Arrays;\nimport java.util.Base64;\n\npublic class AESPCBCDecryptor {\n    public static int[][] sbox;\n    public static int[][] invSbox;\n    public static int[] rcon; // round constants\n    public static int[] expandedKey; // expanded key\n    public static int[][] mcTables; // lookup tables for MixColumns\n\n    static {\n        // SBox\n        // See https://crypto.stackexchange.com/questions/85670/need-help-understanding-math-behind-rijndael-s-box\n        // for an explanation of how 3 generates GF[2^8]\n        sbox = new int[0x10][0x10];\n        int p = 1;\n        int q = 1;\n\n        do {\n            p = gfMult(3, p);\n            q = gfMult(0xF6, q);\n\n            int trans = q; // Affine transformation\n            trans ^= ((q << 1) | (q >>> (8 - 1))) & 0xFF;\n            trans ^= ((q << 2) | (q >>> (8 - 2))) & 0xFF;\n            trans ^= ((q << 3) | (q >>> (8 - 3))) & 0xFF;\n            trans ^= ((q << 4) | (q >>> (8 - 4))) & 0xFF;\n            sbox[p / 16][p % 16] = (trans ^ 0x63) & 0xFF;\n        } while (p != 1);\n\n        sbox[0][0] = 0x63; // 0 is never invertible so set manually\n\n        // InvSBox\n        invSbox = new int[sbox.length][sbox.length];\n        for (int row = 0; row < sbox.length; row++) {\n            for (int col = 0; col < sbox[0].length; col++) {\n                int b = sbox[row][col];\n                invSbox[b >> 4][b & 0xF] = (row << 4) | col;\n            }\n        }\n\n        // Round constants\n        rcon = new int[10];\n        for (int i = 0; i < rcon.length; i++) {\n            if (i == 0) {\n                rcon[i] = 1;\n            } else if (rcon[i - 1] < 0x80) {\n                rcon[i] = 2 * rcon[i - 1];\n            } else if (rcon[i - 1] >= 0x80) {\n                rcon[i] = (2 * rcon[i - 1]) ^ 0x11B;\n            }\n        }\n        for (int i = 0; i < rcon.length; i++) {\n            rcon[i] <<= 24;\n        }\n\n        // Multiplication tables for MixColumns\n        mcTables = new int[0xF][];\n        mcTables[0xE] = new int[0x100];\n        mcTables[0xB] = new int[0x100];\n        mcTables[0xD] = new int[0x100];\n        mcTables[0x9] = new int[0x100];\n\n        for (int mult = 0; mult < mcTables.length; mult++) {\n            if (mcTables[mult] != null) {\n                int[] table = mcTables[mult];\n\n                for (int n = 0; n < table.length; n++) {\n                    table[n] = gfMult(mult, n);\n                }\n            }\n        }\n    }\n\n    public static int subWord(int word) {\n        int b0 = (word >> (8 * 3)) & 0xFF;\n        int b1 = (word >> (8 * 2)) & 0xFF;\n        int b2 = (word >> 8) & 0xFF;\n        int b3 = word & 0xFF;\n\n        return (sbox[b0 >> 4][b0 & 0xF] << 8 * 3)\n                | (sbox[b1 >> 4][b1 & 0xF] << 8 * 2)\n                | (sbox[b2 >> 4][b2 & 0xF] << 8)\n                | (sbox[b3 >> 4][b3 & 0xF]);\n    }\n\n    public static void keySchedule(int[] key) {\n        // AES-128\n        int R = 11;\n        expandedKey = new int[4 * R];\n\n        for (int i = 0; i < expandedKey.length; i++) {\n            if (i < key.length) {\n                expandedKey[i] = key[i];\n            } else if (i % key.length == 0) {\n                int b = (expandedKey[i - 1] << 8) | (expandedKey[i - 1] >>> (32 - 8));\n                expandedKey[i] = expandedKey[i - key.length];\n                expandedKey[i] ^= subWord(b);\n                expandedKey[i] ^= rcon[i / key.length - 1];\n            } else {\n                expandedKey[i] = expandedKey[i - key.length] ^ expandedKey[i - 1];\n            }\n        }\n    }\n\n    public static void addRoundKey(int[][] state, int round) {\n        for (int row = 0; row < state.length; row++) {\n            for (int col = 0; col < state[0].length; col++) {\n                int rkey = expandedKey[round * state[0].length + col];\n                int xbyte = (rkey >> (8 * (state.length - 1) - 8 * row)) & 0xFF;\n                state[row][col] ^= xbyte;\n            }\n        }\n    }\n\n    public static void invShiftRows(int[][] state) {\n        for (int offset = 0; offset < state.length; offset++) {\n            int[] row = state[offset];\n            int[] shifted = new int[row.length];\n            for (int i = 0; i < row.length; i++) {\n                shifted[(i + offset) % 4] = row[i];\n            }\n            state[offset] = shifted;\n        }\n    }\n\n    public static void invSubBytes(int[][] state) {\n        for (int row = 0; row < state.length; row++) {\n            for (int col = 0; col < state[row].length; col++) {\n                int s = state[row][col];\n                int upper = s >> 4;\n                int lower = s & 0xF;\n                state[row][col] = invSbox[upper][lower];\n            }\n        }\n    }\n\n    // Multiply in GF[2^8]\n    public static int gfMult(int mult, int b) {\n        int result = 0;\n        for (int i = 0; i < 8; i++) {\n            if ((mult & 0x1) != 0) {\n                result ^= b;\n            }\n            mult >>= 1;\n            int mod = 0;\n            if ((b & 0x80) != 0) {\n                mod = 0x11B;\n            }\n            b = (b << 1) ^ mod;\n        }\n        return result;\n    }\n\n    public static void invMixColumns(int[][] state) {\n        for (int col = 0; col < state[0].length; col++) {\n            int s1 = mcTables[0xE][state[0][col]] ^ mcTables[0xB][state[1][col]] ^ mcTables[0xD][state[2][col]] ^ mcTables[0x9][state[3][col]];\n            int s2 = mcTables[0x9][state[0][col]] ^ mcTables[0xE][state[1][col]] ^ mcTables[0xB][state[2][col]] ^ mcTables[0xD][state[3][col]];\n            int s3 = mcTables[0xD][state[0][col]] ^ mcTables[0x9][state[1][col]] ^ mcTables[0xE][state[2][col]] ^ mcTables[0xB][state[3][col]];\n            int s4 = mcTables[0xB][state[0][col]] ^ mcTables[0xD][state[1][col]] ^ mcTables[0x9][state[2][col]] ^ mcTables[0xE][state[3][col]];\n\n            state[0][col] = s1;\n            state[1][col] = s2;\n            state[2][col] = s3;\n            state[3][col] = s4;\n        }\n    }\n\n    public static void invCipher(int[][] state) {\n        int round = 10;\n\n        addRoundKey(state, round);\n\n        for (round = 9; round > 0; round--) {\n            invShiftRows(state);\n            invSubBytes(state);\n            addRoundKey(state, round);\n            invMixColumns(state);\n        }\n\n        invSubBytes(state);\n        invShiftRows(state);\n        addRoundKey(state, round);\n    }\n\n    public static String decrypt(String input, long[] ivInts) {\n        // Compute key based on callstack (yes we're doing this meme again)\n        var callstack = Thread.currentThread().getStackTrace();\n        int[] key = new int[]{\n                callstack[1].getClassName().hashCode(),\n                callstack[1].getMethodName().hashCode(),\n                callstack[2].getClassName().hashCode(),\n                callstack[2].getMethodName().hashCode()\n        };\n        keySchedule(key);\n\n        // Convert IV to correct format\n        int[] ivBytes = new int[0x10];\n        for (int i = 0; i < ivInts.length; i++) {\n            for (int j = 0; j < 8; j++) {\n                ivBytes[i * 8 + j] = (int) ((ivInts[i] >>> (56 - j * 8)) & 0xFF);\n            }\n        }\n        int[][] iv = create_state(ivBytes);\n\n        // Input -> state for InvCipher\n        int[] cipherText = design(Base64.getDecoder().decode(input));\n        int[][][] states = new int[cipherText.length / 16][][];\n        for (int i = 0; i < states.length; i++) {\n            int[] subarray = Arrays.copyOfRange(cipherText, i * 16, (i + 1) * 16);\n            states[i] = create_state(subarray);\n        }\n\n        // PCBC decryption alg\n        int[][] previousBlock1 = copyBlock(states[0]);\n        invCipher(states[0]);\n        for (int row = 0; row < states[0].length; row++) {\n            for (int col = 0; col < states[0][0].length; col++) {\n                states[0][row][col] ^= iv[row][col];\n                previousBlock1[row][col] ^= states[0][row][col];\n            }\n        }\n\n        for (int i = 1; i < states.length; i++) {\n            int[][] previousBlock2 = copyBlock(states[i]);\n            invCipher(states[i]);\n            int[][] state = states[i];\n            for (int row = 0; row < state.length; row++) {\n                for (int col = 0; col < state[0].length; col++) {\n                    state[row][col] ^= previousBlock1[row][col];\n                    previousBlock2[row][col] ^= state[row][col];\n                }\n            }\n            previousBlock1 = previousBlock2;\n        }\n\n        // Reconstruct bytes\n        byte[] processed = new byte[cipherText.length];\n        for (int i = 0; i < states.length; i++) {\n            int[] vector = new int[0x10];\n            for (int col = 0; col < states[0].length; col++) {\n                for (int row = 0; row < states[0][0].length; row++) {\n                    vector[col * 4 + row] = states[i][row][col];\n                }\n            }\n            System.arraycopy(resign(vector), 0, processed, i * 16, vector.length);\n        }\n\n        // Remove padding\n        int nPadBytes = processed[processed.length - 1];\n        byte[] message = new byte[processed.length - nPadBytes];\n        System.arraycopy(processed, 0, message, 0, message.length);\n\n        return new String(message, StandardCharsets.UTF_8);\n    }\n\n    public static int[][] copyBlock(int[][] block) {\n        int[][] copy = new int[block.length][block[0].length];\n        for (int row = 0; row < block.length; row++) {\n            for (int col = 0; col < block[0].length; col++) {\n                copy[row][col] = block[row][col];\n            }\n        }\n        return copy;\n    }\n\n    public static int[] design(byte[] arr) {\n        int[] designed = new int[arr.length];\n        for (int i = 0; i < arr.length; i++) {\n            designed[i] = arr[i] & 0xFF;\n        }\n        return designed;\n    }\n\n    public static byte[] resign(int[] arr) {\n        byte[] signed = new byte[arr.length];\n        for (int i = 0; i < arr.length; i++) {\n            signed[i] = (byte) arr[i];\n        }\n        return signed;\n    }\n\n    public static int[][] create_state(int[] bytes) {\n        int[][] state = new int[4][4];\n        for (int i = 0; i < bytes.length; i++) {\n            state[i % 4][i / 4] = bytes[i];\n        }\n        return state;\n    }\n}\n"
  }
]