dynalang-0.4/0000755000175000017500000000000011425436177013122 5ustar twernertwernerdynalang-0.4/jython/0000755000175000017500000000000011425436176014434 5ustar twernertwernerdynalang-0.4/jython/.project0000644000175000017500000000056611011342427016074 0ustar twernertwerner Dynalang-Jython org.eclipse.jdt.core.javabuilder org.eclipse.jdt.core.javanature dynalang-0.4/jython/.settings/0000755000175000017500000000000011425436176016352 5ustar twernertwernerdynalang-0.4/jython/.settings/org.eclipse.jdt.ui.prefs0000644000175000017500000001330111011342427023001 0ustar twernertwerner#Fri Nov 09 11:23:08 CET 2007 eclipse.preferences.version=1 formatter_profile=org.eclipse.jdt.ui.default.sun_profile formatter_settings_version=11 internal.default.compliance=default org.eclipse.jdt.ui.text.custom_code_templates= dynalang-0.4/jython/.settings/org.eclipse.jdt.core.prefs0000644000175000017500000005516111011342427023326 0ustar twernertwerner#Fri Nov 09 11:23:22 CET 2007 eclipse.preferences.version=1 org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.5 org.eclipse.jdt.core.compiler.codegen.unusedLocal=preserve org.eclipse.jdt.core.compiler.compliance=1.5 org.eclipse.jdt.core.compiler.debug.lineNumber=generate org.eclipse.jdt.core.compiler.debug.localVariable=generate org.eclipse.jdt.core.compiler.debug.sourceFile=generate org.eclipse.jdt.core.compiler.doc.comment.support=enabled org.eclipse.jdt.core.compiler.problem.assertIdentifier=error org.eclipse.jdt.core.compiler.problem.enumIdentifier=error org.eclipse.jdt.core.compiler.problem.invalidJavadoc=warning org.eclipse.jdt.core.compiler.problem.invalidJavadocTags=enabled org.eclipse.jdt.core.compiler.problem.invalidJavadocTagsDeprecatedRef=enabled org.eclipse.jdt.core.compiler.problem.invalidJavadocTagsNotVisibleRef=enabled org.eclipse.jdt.core.compiler.problem.invalidJavadocTagsVisibility=protected org.eclipse.jdt.core.compiler.problem.missingJavadocComments=warning org.eclipse.jdt.core.compiler.problem.missingJavadocCommentsOverriding=disabled org.eclipse.jdt.core.compiler.problem.missingJavadocCommentsVisibility=protected org.eclipse.jdt.core.compiler.problem.missingJavadocTags=warning org.eclipse.jdt.core.compiler.problem.missingJavadocTagsOverriding=disabled org.eclipse.jdt.core.compiler.problem.missingJavadocTagsVisibility=protected org.eclipse.jdt.core.compiler.source=1.5 org.eclipse.jdt.core.formatter.align_type_members_on_columns=false org.eclipse.jdt.core.formatter.alignment_for_arguments_in_allocation_expression=16 org.eclipse.jdt.core.formatter.alignment_for_arguments_in_enum_constant=16 org.eclipse.jdt.core.formatter.alignment_for_arguments_in_explicit_constructor_call=16 org.eclipse.jdt.core.formatter.alignment_for_arguments_in_method_invocation=16 org.eclipse.jdt.core.formatter.alignment_for_arguments_in_qualified_allocation_expression=16 org.eclipse.jdt.core.formatter.alignment_for_assignment=0 org.eclipse.jdt.core.formatter.alignment_for_binary_expression=16 org.eclipse.jdt.core.formatter.alignment_for_compact_if=16 org.eclipse.jdt.core.formatter.alignment_for_conditional_expression=80 org.eclipse.jdt.core.formatter.alignment_for_enum_constants=0 org.eclipse.jdt.core.formatter.alignment_for_expressions_in_array_initializer=16 org.eclipse.jdt.core.formatter.alignment_for_multiple_fields=16 org.eclipse.jdt.core.formatter.alignment_for_parameters_in_constructor_declaration=16 org.eclipse.jdt.core.formatter.alignment_for_parameters_in_method_declaration=16 org.eclipse.jdt.core.formatter.alignment_for_selector_in_method_invocation=16 org.eclipse.jdt.core.formatter.alignment_for_superclass_in_type_declaration=16 org.eclipse.jdt.core.formatter.alignment_for_superinterfaces_in_enum_declaration=16 org.eclipse.jdt.core.formatter.alignment_for_superinterfaces_in_type_declaration=16 org.eclipse.jdt.core.formatter.alignment_for_throws_clause_in_constructor_declaration=16 org.eclipse.jdt.core.formatter.alignment_for_throws_clause_in_method_declaration=16 org.eclipse.jdt.core.formatter.blank_lines_after_imports=1 org.eclipse.jdt.core.formatter.blank_lines_after_package=1 org.eclipse.jdt.core.formatter.blank_lines_before_field=0 org.eclipse.jdt.core.formatter.blank_lines_before_first_class_body_declaration=0 org.eclipse.jdt.core.formatter.blank_lines_before_imports=1 org.eclipse.jdt.core.formatter.blank_lines_before_member_type=1 org.eclipse.jdt.core.formatter.blank_lines_before_method=1 org.eclipse.jdt.core.formatter.blank_lines_before_new_chunk=1 org.eclipse.jdt.core.formatter.blank_lines_before_package=0 org.eclipse.jdt.core.formatter.blank_lines_between_import_groups=1 org.eclipse.jdt.core.formatter.blank_lines_between_type_declarations=1 org.eclipse.jdt.core.formatter.brace_position_for_annotation_type_declaration=end_of_line org.eclipse.jdt.core.formatter.brace_position_for_anonymous_type_declaration=end_of_line org.eclipse.jdt.core.formatter.brace_position_for_array_initializer=end_of_line org.eclipse.jdt.core.formatter.brace_position_for_block=end_of_line org.eclipse.jdt.core.formatter.brace_position_for_block_in_case=end_of_line org.eclipse.jdt.core.formatter.brace_position_for_constructor_declaration=end_of_line org.eclipse.jdt.core.formatter.brace_position_for_enum_constant=end_of_line org.eclipse.jdt.core.formatter.brace_position_for_enum_declaration=end_of_line org.eclipse.jdt.core.formatter.brace_position_for_method_declaration=end_of_line org.eclipse.jdt.core.formatter.brace_position_for_switch=end_of_line org.eclipse.jdt.core.formatter.brace_position_for_type_declaration=end_of_line org.eclipse.jdt.core.formatter.comment.clear_blank_lines=false org.eclipse.jdt.core.formatter.comment.clear_blank_lines_in_block_comment=false org.eclipse.jdt.core.formatter.comment.clear_blank_lines_in_javadoc_comment=false org.eclipse.jdt.core.formatter.comment.format_block_comments=true org.eclipse.jdt.core.formatter.comment.format_comments=true org.eclipse.jdt.core.formatter.comment.format_header=false org.eclipse.jdt.core.formatter.comment.format_html=true org.eclipse.jdt.core.formatter.comment.format_javadoc_comments=true org.eclipse.jdt.core.formatter.comment.format_line_comments=true org.eclipse.jdt.core.formatter.comment.format_source_code=true org.eclipse.jdt.core.formatter.comment.indent_parameter_description=true org.eclipse.jdt.core.formatter.comment.indent_root_tags=true org.eclipse.jdt.core.formatter.comment.insert_new_line_before_root_tags=insert org.eclipse.jdt.core.formatter.comment.insert_new_line_for_parameter=insert org.eclipse.jdt.core.formatter.comment.line_length=80 org.eclipse.jdt.core.formatter.compact_else_if=true org.eclipse.jdt.core.formatter.continuation_indentation=2 org.eclipse.jdt.core.formatter.continuation_indentation_for_array_initializer=2 org.eclipse.jdt.core.formatter.format_guardian_clause_on_one_line=false org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_annotation_declaration_header=true org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_enum_constant_header=true org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_enum_declaration_header=true org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_type_header=true org.eclipse.jdt.core.formatter.indent_breaks_compare_to_cases=true org.eclipse.jdt.core.formatter.indent_empty_lines=false org.eclipse.jdt.core.formatter.indent_statements_compare_to_block=true org.eclipse.jdt.core.formatter.indent_statements_compare_to_body=true org.eclipse.jdt.core.formatter.indent_switchstatements_compare_to_cases=true org.eclipse.jdt.core.formatter.indent_switchstatements_compare_to_switch=false org.eclipse.jdt.core.formatter.indentation.size=4 org.eclipse.jdt.core.formatter.insert_new_line_after_annotation=insert org.eclipse.jdt.core.formatter.insert_new_line_after_opening_brace_in_array_initializer=do not insert org.eclipse.jdt.core.formatter.insert_new_line_at_end_of_file_if_missing=do not insert org.eclipse.jdt.core.formatter.insert_new_line_before_catch_in_try_statement=do not insert org.eclipse.jdt.core.formatter.insert_new_line_before_closing_brace_in_array_initializer=do not insert org.eclipse.jdt.core.formatter.insert_new_line_before_else_in_if_statement=do not insert org.eclipse.jdt.core.formatter.insert_new_line_before_finally_in_try_statement=do not insert org.eclipse.jdt.core.formatter.insert_new_line_before_while_in_do_statement=do not insert org.eclipse.jdt.core.formatter.insert_new_line_in_empty_annotation_declaration=insert org.eclipse.jdt.core.formatter.insert_new_line_in_empty_anonymous_type_declaration=insert org.eclipse.jdt.core.formatter.insert_new_line_in_empty_block=insert org.eclipse.jdt.core.formatter.insert_new_line_in_empty_enum_constant=insert org.eclipse.jdt.core.formatter.insert_new_line_in_empty_enum_declaration=insert org.eclipse.jdt.core.formatter.insert_new_line_in_empty_method_body=insert org.eclipse.jdt.core.formatter.insert_new_line_in_empty_type_declaration=insert org.eclipse.jdt.core.formatter.insert_space_after_and_in_type_parameter=insert org.eclipse.jdt.core.formatter.insert_space_after_assignment_operator=insert org.eclipse.jdt.core.formatter.insert_space_after_at_in_annotation=do not insert org.eclipse.jdt.core.formatter.insert_space_after_at_in_annotation_type_declaration=do not insert org.eclipse.jdt.core.formatter.insert_space_after_binary_operator=insert org.eclipse.jdt.core.formatter.insert_space_after_closing_angle_bracket_in_type_arguments=insert org.eclipse.jdt.core.formatter.insert_space_after_closing_angle_bracket_in_type_parameters=insert org.eclipse.jdt.core.formatter.insert_space_after_closing_brace_in_block=insert org.eclipse.jdt.core.formatter.insert_space_after_closing_paren_in_cast=insert org.eclipse.jdt.core.formatter.insert_space_after_colon_in_assert=insert org.eclipse.jdt.core.formatter.insert_space_after_colon_in_case=insert org.eclipse.jdt.core.formatter.insert_space_after_colon_in_conditional=insert org.eclipse.jdt.core.formatter.insert_space_after_colon_in_for=insert org.eclipse.jdt.core.formatter.insert_space_after_colon_in_labeled_statement=insert org.eclipse.jdt.core.formatter.insert_space_after_comma_in_allocation_expression=insert org.eclipse.jdt.core.formatter.insert_space_after_comma_in_annotation=insert org.eclipse.jdt.core.formatter.insert_space_after_comma_in_array_initializer=insert org.eclipse.jdt.core.formatter.insert_space_after_comma_in_constructor_declaration_parameters=insert org.eclipse.jdt.core.formatter.insert_space_after_comma_in_constructor_declaration_throws=insert org.eclipse.jdt.core.formatter.insert_space_after_comma_in_enum_constant_arguments=insert org.eclipse.jdt.core.formatter.insert_space_after_comma_in_enum_declarations=insert org.eclipse.jdt.core.formatter.insert_space_after_comma_in_explicitconstructorcall_arguments=insert org.eclipse.jdt.core.formatter.insert_space_after_comma_in_for_increments=insert org.eclipse.jdt.core.formatter.insert_space_after_comma_in_for_inits=insert org.eclipse.jdt.core.formatter.insert_space_after_comma_in_method_declaration_parameters=insert org.eclipse.jdt.core.formatter.insert_space_after_comma_in_method_declaration_throws=insert org.eclipse.jdt.core.formatter.insert_space_after_comma_in_method_invocation_arguments=insert org.eclipse.jdt.core.formatter.insert_space_after_comma_in_multiple_field_declarations=insert org.eclipse.jdt.core.formatter.insert_space_after_comma_in_multiple_local_declarations=insert org.eclipse.jdt.core.formatter.insert_space_after_comma_in_parameterized_type_reference=insert org.eclipse.jdt.core.formatter.insert_space_after_comma_in_superinterfaces=insert org.eclipse.jdt.core.formatter.insert_space_after_comma_in_type_arguments=insert org.eclipse.jdt.core.formatter.insert_space_after_comma_in_type_parameters=insert org.eclipse.jdt.core.formatter.insert_space_after_ellipsis=insert org.eclipse.jdt.core.formatter.insert_space_after_opening_angle_bracket_in_parameterized_type_reference=do not insert org.eclipse.jdt.core.formatter.insert_space_after_opening_angle_bracket_in_type_arguments=do not insert org.eclipse.jdt.core.formatter.insert_space_after_opening_angle_bracket_in_type_parameters=do not insert org.eclipse.jdt.core.formatter.insert_space_after_opening_brace_in_array_initializer=insert org.eclipse.jdt.core.formatter.insert_space_after_opening_bracket_in_array_allocation_expression=do not insert org.eclipse.jdt.core.formatter.insert_space_after_opening_bracket_in_array_reference=do not insert org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_annotation=do not insert org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_cast=do not insert org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_catch=do not insert org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_constructor_declaration=do not insert org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_enum_constant=do not insert org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_for=do not insert org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_if=do not insert org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_method_declaration=do not insert org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_method_invocation=do not insert org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_parenthesized_expression=do not insert org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_switch=do not insert org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_synchronized=do not insert org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_while=do not insert org.eclipse.jdt.core.formatter.insert_space_after_postfix_operator=do not insert org.eclipse.jdt.core.formatter.insert_space_after_prefix_operator=do not insert org.eclipse.jdt.core.formatter.insert_space_after_question_in_conditional=insert org.eclipse.jdt.core.formatter.insert_space_after_question_in_wildcard=do not insert org.eclipse.jdt.core.formatter.insert_space_after_semicolon_in_for=insert org.eclipse.jdt.core.formatter.insert_space_after_unary_operator=do not insert org.eclipse.jdt.core.formatter.insert_space_before_and_in_type_parameter=insert org.eclipse.jdt.core.formatter.insert_space_before_assignment_operator=insert org.eclipse.jdt.core.formatter.insert_space_before_at_in_annotation_type_declaration=insert org.eclipse.jdt.core.formatter.insert_space_before_binary_operator=insert org.eclipse.jdt.core.formatter.insert_space_before_closing_angle_bracket_in_parameterized_type_reference=do not insert org.eclipse.jdt.core.formatter.insert_space_before_closing_angle_bracket_in_type_arguments=do not insert org.eclipse.jdt.core.formatter.insert_space_before_closing_angle_bracket_in_type_parameters=do not insert org.eclipse.jdt.core.formatter.insert_space_before_closing_brace_in_array_initializer=insert org.eclipse.jdt.core.formatter.insert_space_before_closing_bracket_in_array_allocation_expression=do not insert org.eclipse.jdt.core.formatter.insert_space_before_closing_bracket_in_array_reference=do not insert org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_annotation=do not insert org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_cast=do not insert org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_catch=do not insert org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_constructor_declaration=do not insert org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_enum_constant=do not insert org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_for=do not insert org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_if=do not insert org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_method_declaration=do not insert org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_method_invocation=do not insert org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_parenthesized_expression=do not insert org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_switch=do not insert org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_synchronized=do not insert org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_while=do not insert org.eclipse.jdt.core.formatter.insert_space_before_colon_in_assert=insert org.eclipse.jdt.core.formatter.insert_space_before_colon_in_case=do not insert org.eclipse.jdt.core.formatter.insert_space_before_colon_in_conditional=insert org.eclipse.jdt.core.formatter.insert_space_before_colon_in_default=do not insert org.eclipse.jdt.core.formatter.insert_space_before_colon_in_for=insert org.eclipse.jdt.core.formatter.insert_space_before_colon_in_labeled_statement=do not insert org.eclipse.jdt.core.formatter.insert_space_before_comma_in_allocation_expression=do not insert org.eclipse.jdt.core.formatter.insert_space_before_comma_in_annotation=do not insert org.eclipse.jdt.core.formatter.insert_space_before_comma_in_array_initializer=do not insert org.eclipse.jdt.core.formatter.insert_space_before_comma_in_constructor_declaration_parameters=do not insert org.eclipse.jdt.core.formatter.insert_space_before_comma_in_constructor_declaration_throws=do not insert org.eclipse.jdt.core.formatter.insert_space_before_comma_in_enum_constant_arguments=do not insert org.eclipse.jdt.core.formatter.insert_space_before_comma_in_enum_declarations=do not insert org.eclipse.jdt.core.formatter.insert_space_before_comma_in_explicitconstructorcall_arguments=do not insert org.eclipse.jdt.core.formatter.insert_space_before_comma_in_for_increments=do not insert org.eclipse.jdt.core.formatter.insert_space_before_comma_in_for_inits=do not insert org.eclipse.jdt.core.formatter.insert_space_before_comma_in_method_declaration_parameters=do not insert org.eclipse.jdt.core.formatter.insert_space_before_comma_in_method_declaration_throws=do not insert org.eclipse.jdt.core.formatter.insert_space_before_comma_in_method_invocation_arguments=do not insert org.eclipse.jdt.core.formatter.insert_space_before_comma_in_multiple_field_declarations=do not insert org.eclipse.jdt.core.formatter.insert_space_before_comma_in_multiple_local_declarations=do not insert org.eclipse.jdt.core.formatter.insert_space_before_comma_in_parameterized_type_reference=do not insert org.eclipse.jdt.core.formatter.insert_space_before_comma_in_superinterfaces=do not insert org.eclipse.jdt.core.formatter.insert_space_before_comma_in_type_arguments=do not insert org.eclipse.jdt.core.formatter.insert_space_before_comma_in_type_parameters=do not insert org.eclipse.jdt.core.formatter.insert_space_before_ellipsis=do not insert org.eclipse.jdt.core.formatter.insert_space_before_opening_angle_bracket_in_parameterized_type_reference=do not insert org.eclipse.jdt.core.formatter.insert_space_before_opening_angle_bracket_in_type_arguments=do not insert org.eclipse.jdt.core.formatter.insert_space_before_opening_angle_bracket_in_type_parameters=do not insert org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_annotation_type_declaration=insert org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_anonymous_type_declaration=insert org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_array_initializer=insert org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_block=insert org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_constructor_declaration=insert org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_enum_constant=insert org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_enum_declaration=insert org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_method_declaration=insert org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_switch=insert org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_type_declaration=insert org.eclipse.jdt.core.formatter.insert_space_before_opening_bracket_in_array_allocation_expression=do not insert org.eclipse.jdt.core.formatter.insert_space_before_opening_bracket_in_array_reference=do not insert org.eclipse.jdt.core.formatter.insert_space_before_opening_bracket_in_array_type_reference=do not insert org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_annotation=do not insert org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_annotation_type_member_declaration=do not insert org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_catch=insert org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_constructor_declaration=do not insert org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_enum_constant=do not insert org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_for=insert org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_if=insert org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_method_declaration=do not insert org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_method_invocation=do not insert org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_parenthesized_expression=do not insert org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_switch=insert org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_synchronized=insert org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_while=insert org.eclipse.jdt.core.formatter.insert_space_before_parenthesized_expression_in_return=insert org.eclipse.jdt.core.formatter.insert_space_before_parenthesized_expression_in_throw=insert org.eclipse.jdt.core.formatter.insert_space_before_postfix_operator=do not insert org.eclipse.jdt.core.formatter.insert_space_before_prefix_operator=do not insert org.eclipse.jdt.core.formatter.insert_space_before_question_in_conditional=insert org.eclipse.jdt.core.formatter.insert_space_before_question_in_wildcard=do not insert org.eclipse.jdt.core.formatter.insert_space_before_semicolon=do not insert org.eclipse.jdt.core.formatter.insert_space_before_semicolon_in_for=do not insert org.eclipse.jdt.core.formatter.insert_space_before_unary_operator=do not insert org.eclipse.jdt.core.formatter.insert_space_between_brackets_in_array_type_reference=do not insert org.eclipse.jdt.core.formatter.insert_space_between_empty_braces_in_array_initializer=do not insert org.eclipse.jdt.core.formatter.insert_space_between_empty_brackets_in_array_allocation_expression=do not insert org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_annotation_type_member_declaration=do not insert org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_constructor_declaration=do not insert org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_enum_constant=do not insert org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_method_declaration=do not insert org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_method_invocation=do not insert org.eclipse.jdt.core.formatter.keep_else_statement_on_same_line=false org.eclipse.jdt.core.formatter.keep_empty_array_initializer_on_one_line=false org.eclipse.jdt.core.formatter.keep_imple_if_on_one_line=false org.eclipse.jdt.core.formatter.keep_then_statement_on_same_line=false org.eclipse.jdt.core.formatter.lineSplit=80 org.eclipse.jdt.core.formatter.never_indent_block_comments_on_first_column=false org.eclipse.jdt.core.formatter.never_indent_line_comments_on_first_column=false org.eclipse.jdt.core.formatter.number_of_blank_lines_at_beginning_of_method_body=0 org.eclipse.jdt.core.formatter.number_of_empty_lines_to_preserve=1 org.eclipse.jdt.core.formatter.put_empty_statement_on_new_line=true org.eclipse.jdt.core.formatter.tabulation.char=mixed org.eclipse.jdt.core.formatter.tabulation.size=8 org.eclipse.jdt.core.formatter.use_tabs_only_for_leading_indentations=false org.eclipse.jdt.core.formatter.wrap_before_binary_operator=true dynalang-0.4/jython/LICENSE.txt0000644000175000017500000002645011011342427016250 0ustar twernertwerner Apache License Version 2.0, January 2004 http://www.apache.org/licenses/ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 1. Definitions. "License" shall mean the terms and conditions for use, reproduction, and distribution as defined by Sections 1 through 9 of this document. "Licensor" shall mean the copyright owner or entity authorized by the copyright owner that is granting the License. "Legal Entity" shall mean the union of the acting entity and all other entities that control, are controlled by, or are under common control with that entity. For the purposes of this definition, "control" means (i) the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the outstanding shares, or (iii) beneficial ownership of such entity. "You" (or "Your") shall mean an individual or Legal Entity exercising permissions granted by this License. "Source" form shall mean the preferred form for making modifications, including but not limited to software source code, documentation source, and configuration files. "Object" form shall mean any form resulting from mechanical transformation or translation of a Source form, including but not limited to compiled object code, generated documentation, and conversions to other media types. "Work" shall mean the work of authorship, whether in Source or Object form, made available under the License, as indicated by a copyright notice that is included in or attached to the work (an example is provided in the Appendix below). "Derivative Works" shall mean any work, whether in Source or Object form, that is based on (or derived from) the Work and for which the editorial revisions, annotations, elaborations, or other modifications represent, as a whole, an original work of authorship. For the purposes of this License, Derivative Works shall not include works that remain separable from, or merely link (or bind by name) to the interfaces of, the Work and Derivative Works thereof. "Contribution" shall mean any work of authorship, including the original version of the Work and any modifications or additions to that Work or Derivative Works thereof, that is intentionally submitted to Licensor for inclusion in the Work by the copyright owner or by an individual or Legal Entity authorized to submit on behalf of the copyright owner. For the purposes of this definition, "submitted" means any form of electronic, verbal, or written communication sent to the Licensor or its representatives, including but not limited to communication on electronic mailing lists, source code control systems, and issue tracking systems that are managed by, or on behalf of, the Licensor for the purpose of discussing and improving the Work, but excluding communication that is conspicuously marked or otherwise designated in writing by the copyright owner as "Not a Contribution." "Contributor" shall mean Licensor and any individual or Legal Entity on behalf of whom a Contribution has been received by Licensor and subsequently incorporated within the Work. 2. Grant of Copyright License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable copyright license to reproduce, prepare Derivative Works of, publicly display, publicly perform, sublicense, and distribute the Work and such Derivative Works in Source or Object form. 3. Grant of Patent License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable (except as stated in this section) patent license to make, have made, use, offer to sell, sell, import, and otherwise transfer the Work, where such license applies only to those patent claims licensable by such Contributor that are necessarily infringed by their Contribution(s) alone or by combination of their Contribution(s) with the Work to which such Contribution(s) was submitted. If You institute patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Work or a Contribution incorporated within the Work constitutes direct or contributory patent infringement, then any patent licenses granted to You under this License for that Work shall terminate as of the date such litigation is filed. 4. Redistribution. You may reproduce and distribute copies of the Work or Derivative Works thereof in any medium, with or without modifications, and in Source or Object form, provided that You meet the following conditions: (a) You must give any other recipients of the Work or Derivative Works a copy of this License; and (b) You must cause any modified files to carry prominent notices stating that You changed the files; and (c) You must retain, in the Source form of any Derivative Works that You distribute, all copyright, patent, trademark, and attribution notices from the Source form of the Work, excluding those notices that do not pertain to any part of the Derivative Works; and (d) If the Work includes a "NOTICE" text file as part of its distribution, then any Derivative Works that You distribute must include a readable copy of the attribution notices contained within such NOTICE file, excluding those notices that do not pertain to any part of the Derivative Works, in at least one of the following places: within a NOTICE text file distributed as part of the Derivative Works; within the Source form or documentation, if provided along with the Derivative Works; or, within a display generated by the Derivative Works, if and wherever such third-party notices normally appear. The contents of the NOTICE file are for informational purposes only and do not modify the License. You may add Your own attribution notices within Derivative Works that You distribute, alongside or as an addendum to the NOTICE text from the Work, provided that such additional attribution notices cannot be construed as modifying the License. You may add Your own copyright statement to Your modifications and may provide additional or different license terms and conditions for use, reproduction, or distribution of Your modifications, or for any such Derivative Works as a whole, provided Your use, reproduction, and distribution of the Work otherwise complies with the conditions stated in this License. 5. Submission of Contributions. Unless You explicitly state otherwise, any Contribution intentionally submitted for inclusion in the Work by You to the Licensor shall be under the terms and conditions of this License, without any additional terms or conditions. Notwithstanding the above, nothing herein shall supersede or modify the terms of any separate license agreement you may have executed with Licensor regarding such Contributions. 6. Trademarks. This License does not grant permission to use the trade names, trademarks, service marks, or product names of the Licensor, except as required for reasonable and customary use in describing the origin of the Work and reproducing the content of the NOTICE file. 7. Disclaimer of Warranty. Unless required by applicable law or agreed to in writing, Licensor provides the Work (and each Contributor provides its Contributions) on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, including, without limitation, any warranties or conditions of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are solely responsible for determining the appropriateness of using or redistributing the Work and assume any risks associated with Your exercise of permissions under this License. 8. Limitation of Liability. In no event and under no legal theory, whether in tort (including negligence), contract, or otherwise, unless required by applicable law (such as deliberate and grossly negligent acts) or agreed to in writing, shall any Contributor be liable to You for damages, including any direct, indirect, special, incidental, or consequential damages of any character arising as a result of this License or out of the use or inability to use the Work (including but not limited to damages for loss of goodwill, work stoppage, computer failure or malfunction, or any and all other commercial damages or losses), even if such Contributor has been advised of the possibility of such damages. 9. Accepting Warranty or Additional Liability. While redistributing the Work or Derivative Works thereof, You may choose to offer, and charge a fee for, acceptance of support, warranty, indemnity, or other liability obligations and/or rights consistent with this License. However, in accepting such obligations, You may act only on Your own behalf and on Your sole responsibility, not on behalf of any other Contributor, and only if You agree to indemnify, defend, and hold each Contributor harmless for any liability incurred by, or claims asserted against, such Contributor by reason of your accepting any such warranty or additional liability. END OF TERMS AND CONDITIONS APPENDIX: How to apply the Apache License to your work. To apply the Apache License to your work, attach the following boilerplate notice, with the fields enclosed by brackets "[]" replaced with your own identifying information. (Don't include the brackets!) The text should be enclosed in the appropriate comment syntax for the file format. We also recommend that a file or class name and description of purpose be included on the same "printed page" as the copyright notice for easier identification within third-party archives. Copyright [yyyy] [name of copyright owner] Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. dynalang-0.4/jython/.classpath0000644000175000017500000000117211011342427016402 0ustar twernertwerner dynalang-0.4/jython/changelog.txt0000644000175000017500000000006311011342427017105 0ustar twernertwerner0.4 (2008.05.10) ================ Initial versiondynalang-0.4/jython/build.xml0000644000175000017500000001660611011557335016256 0ustar twernertwerner dynalang-0.4/jython/ivy.xml0000644000175000017500000000105511011557335015756 0ustar twernertwerner dynalang-0.4/jython/src/0000755000175000017500000000000011425436176015223 5ustar twernertwernerdynalang-0.4/jython/src/org/0000755000175000017500000000000011425436176016012 5ustar twernertwernerdynalang-0.4/jython/src/org/dynalang/0000755000175000017500000000000011425436176017607 5ustar twernertwernerdynalang-0.4/jython/src/org/dynalang/mop/0000755000175000017500000000000011425436176020402 5ustar twernertwernerdynalang-0.4/jython/src/org/dynalang/mop/jython/0000755000175000017500000000000011425436176021715 5ustar twernertwernerdynalang-0.4/jython/src/org/dynalang/mop/jython/JythonMetaobjectProtocol.java0000644000175000017500000001467211011342427027547 0ustar twernertwernerpackage org.dynalang.mop.jython; import java.util.Iterator; import java.util.Map; import java.util.NoSuchElementException; import java.util.Map.Entry; import org.dynalang.mop.CallProtocol; import org.dynalang.mop.ClassBasedMetaobjectProtocol; import org.dynalang.mop.impl.MetaobjectProtocolBase; import org.python.core.Py; import org.python.core.PyException; import org.python.core.PyObject; import org.python.core.PyString; /** * @author Attila Szegedi * @version $Id: $ */ public class JythonMetaobjectProtocol extends MetaobjectProtocolBase implements ClassBasedMetaobjectProtocol { public Result delete(Object target, Object propertyId) { String name = getInternedPropertyName(propertyId); if(name == null) { return Result.doesNotExist; } try { ((PyObject)target).__delattr__(name); return Result.ok; } catch(PyException e) { return pyExceptionToResult(e); } } public Boolean has(Object target, Object propertyId) { return get(target, propertyId) == null ? null : Boolean.TRUE; } @Override public Iterator propertyIds(Object target) { final PyObject pyTarget = (PyObject)target; final PyObject iter = pyTarget.__dir__().__iter__(); return new Iterator() { private PyObject next = iter.__iternext__(); private PyObject lastNext; public boolean hasNext() { return next != null; } public Object next() { if(next == null) { throw new NoSuchElementException(); } lastNext = next; next = iter.__iternext__(); return lastNext; } public void remove() { pyTarget.__delattr__(getInternedPropertyName(lastNext)); } }; } public Iterator properties(Object target) { final PyObject pyTarget = (PyObject)target; final Iterator keys = propertyIds(target); return new Iterator() { public boolean hasNext() { return keys.hasNext(); } public Entry next() { final PyObject key = (PyObject)keys.next(); return new Entry() { public Object getKey() { return key; } public Object getValue() { return pyTarget.__getattr__(getInternedPropertyName(key)); } public Object setValue(Object value) { String name = getInternedPropertyName(key); PyObject oldValue = pyTarget.__getattr__(name); pyTarget.__setattr__(name, (PyObject)representAs(value, PyObject.class)); return oldValue; } }; } public void remove() { keys.remove(); } }; } public Result put(Object target, Object propertyId, Object value, CallProtocol callProtocol) { String name = getInternedPropertyName(propertyId); if(name == null) { return Result.doesNotExist; } try { value = callProtocol.representAs(value, PyObject.class); if(value instanceof PyObject) { ((PyObject)target).__setattr__(name, (PyObject)value); return Result.ok; } return Result.noRepresentation; } catch(PyException e) { return pyExceptionToResult(e); } } public Object call(Object callable, CallProtocol callProtocol, Map args) { PyObject pyCallable = (PyObject)callable; if(!pyCallable.isCallable()) { return Result.notCallable; } String[] names = new String[args.size()]; PyObject[] values = new PyObject[args.size()]; int i = 0; for (Iterator it = args.entrySet().iterator(); it.hasNext();) { Map.Entry entry = it.next(); Object value = callProtocol.representAs(entry.getValue(), PyObject.class); if(value instanceof PyObject) { names[i] = String.valueOf(entry.getKey()); values[i++] = (PyObject)value; } else { return Result.noRepresentation; } } return pyCallable.__call__(values, names); } public Object call(Object callable, CallProtocol callProtocol, Object... args) { PyObject pyCallable = (PyObject)callable; if(!pyCallable.isCallable()) { return Result.notCallable; } // Use (theoretically) faster path for 0-2 arguments switch(args.length) { case 0: { return pyCallable.__call__(); } case 1: { Object arg0 = callProtocol.representAs(args[0], PyObject.class); if(arg0 instanceof PyObject) { return pyCallable.__call__((PyObject)arg0); } return Result.noRepresentation; } case 2: { Object arg0 = callProtocol.representAs(args[0], PyObject.class); if(arg0 instanceof PyObject) { Object arg1 = callProtocol.representAs(args[1], PyObject.class); if(arg1 instanceof PyObject) { return pyCallable.__call__((PyObject)arg0, (PyObject)arg1); } } return Result.noRepresentation; } default: { PyObject[] pyArgs = new PyObject[args.length]; for (int i = 0; i < args.length; i++) { Object arg = callProtocol.representAs(args[i], PyObject.class); if(!(arg instanceof PyObject)) { return Result.noRepresentation; } pyArgs[i] = (PyObject)arg; } return pyCallable.__call__(pyArgs); } } } public Object get(Object target, Object propertyId) { String name = getInternedPropertyName(propertyId); if(name == null) { return Result.doesNotExist; } Object value = ((PyObject)target).__findattr__(name); // TODO: what do we do with PyNone? return value == null ? Result.doesNotExist : value; } public Object representAs(Object object, Class targetClass) { if(object instanceof PyObject) { Object obj = ((PyObject)object).__tojava__(targetClass); return obj != Py.NoConversion ? obj : Result.noAuthority; } else if(targetClass == PyObject.class) { return Py.java2py(object); } return Result.noAuthority; } public boolean isAuthoritativeForClass(Class clazz) { return PyObject.class.isAssignableFrom(clazz); } private String getInternedPropertyName(Object propertyId) { if(propertyId instanceof PyString) { return ((PyString)propertyId).internedString(); } else if(propertyId instanceof String) { return ((String)propertyId).intern(); } return null; } private static Result pyExceptionToResult(PyException e) { if(e.type == Py.AttributeError) { String msg = e.getMessage(); if(msg.endsWith(" is read-only")) { return Result.notWritable; } else if(msg.lastIndexOf("has no attribute") != -1) { return Result.doesNotExist; } } throw e; } }dynalang-0.4/rhino/0000755000175000017500000000000011425436176014240 5ustar twernertwernerdynalang-0.4/rhino/.project0000644000175000017500000000056511011574340015700 0ustar twernertwerner Dynalang-Rhino org.eclipse.jdt.core.javabuilder org.eclipse.jdt.core.javanature dynalang-0.4/rhino/LICENSE.txt0000644000175000017500000002645011011574340016055 0ustar twernertwerner Apache License Version 2.0, January 2004 http://www.apache.org/licenses/ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 1. Definitions. "License" shall mean the terms and conditions for use, reproduction, and distribution as defined by Sections 1 through 9 of this document. "Licensor" shall mean the copyright owner or entity authorized by the copyright owner that is granting the License. "Legal Entity" shall mean the union of the acting entity and all other entities that control, are controlled by, or are under common control with that entity. For the purposes of this definition, "control" means (i) the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the outstanding shares, or (iii) beneficial ownership of such entity. "You" (or "Your") shall mean an individual or Legal Entity exercising permissions granted by this License. "Source" form shall mean the preferred form for making modifications, including but not limited to software source code, documentation source, and configuration files. "Object" form shall mean any form resulting from mechanical transformation or translation of a Source form, including but not limited to compiled object code, generated documentation, and conversions to other media types. "Work" shall mean the work of authorship, whether in Source or Object form, made available under the License, as indicated by a copyright notice that is included in or attached to the work (an example is provided in the Appendix below). "Derivative Works" shall mean any work, whether in Source or Object form, that is based on (or derived from) the Work and for which the editorial revisions, annotations, elaborations, or other modifications represent, as a whole, an original work of authorship. For the purposes of this License, Derivative Works shall not include works that remain separable from, or merely link (or bind by name) to the interfaces of, the Work and Derivative Works thereof. "Contribution" shall mean any work of authorship, including the original version of the Work and any modifications or additions to that Work or Derivative Works thereof, that is intentionally submitted to Licensor for inclusion in the Work by the copyright owner or by an individual or Legal Entity authorized to submit on behalf of the copyright owner. For the purposes of this definition, "submitted" means any form of electronic, verbal, or written communication sent to the Licensor or its representatives, including but not limited to communication on electronic mailing lists, source code control systems, and issue tracking systems that are managed by, or on behalf of, the Licensor for the purpose of discussing and improving the Work, but excluding communication that is conspicuously marked or otherwise designated in writing by the copyright owner as "Not a Contribution." "Contributor" shall mean Licensor and any individual or Legal Entity on behalf of whom a Contribution has been received by Licensor and subsequently incorporated within the Work. 2. Grant of Copyright License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable copyright license to reproduce, prepare Derivative Works of, publicly display, publicly perform, sublicense, and distribute the Work and such Derivative Works in Source or Object form. 3. Grant of Patent License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable (except as stated in this section) patent license to make, have made, use, offer to sell, sell, import, and otherwise transfer the Work, where such license applies only to those patent claims licensable by such Contributor that are necessarily infringed by their Contribution(s) alone or by combination of their Contribution(s) with the Work to which such Contribution(s) was submitted. If You institute patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Work or a Contribution incorporated within the Work constitutes direct or contributory patent infringement, then any patent licenses granted to You under this License for that Work shall terminate as of the date such litigation is filed. 4. Redistribution. You may reproduce and distribute copies of the Work or Derivative Works thereof in any medium, with or without modifications, and in Source or Object form, provided that You meet the following conditions: (a) You must give any other recipients of the Work or Derivative Works a copy of this License; and (b) You must cause any modified files to carry prominent notices stating that You changed the files; and (c) You must retain, in the Source form of any Derivative Works that You distribute, all copyright, patent, trademark, and attribution notices from the Source form of the Work, excluding those notices that do not pertain to any part of the Derivative Works; and (d) If the Work includes a "NOTICE" text file as part of its distribution, then any Derivative Works that You distribute must include a readable copy of the attribution notices contained within such NOTICE file, excluding those notices that do not pertain to any part of the Derivative Works, in at least one of the following places: within a NOTICE text file distributed as part of the Derivative Works; within the Source form or documentation, if provided along with the Derivative Works; or, within a display generated by the Derivative Works, if and wherever such third-party notices normally appear. The contents of the NOTICE file are for informational purposes only and do not modify the License. You may add Your own attribution notices within Derivative Works that You distribute, alongside or as an addendum to the NOTICE text from the Work, provided that such additional attribution notices cannot be construed as modifying the License. You may add Your own copyright statement to Your modifications and may provide additional or different license terms and conditions for use, reproduction, or distribution of Your modifications, or for any such Derivative Works as a whole, provided Your use, reproduction, and distribution of the Work otherwise complies with the conditions stated in this License. 5. Submission of Contributions. Unless You explicitly state otherwise, any Contribution intentionally submitted for inclusion in the Work by You to the Licensor shall be under the terms and conditions of this License, without any additional terms or conditions. Notwithstanding the above, nothing herein shall supersede or modify the terms of any separate license agreement you may have executed with Licensor regarding such Contributions. 6. Trademarks. This License does not grant permission to use the trade names, trademarks, service marks, or product names of the Licensor, except as required for reasonable and customary use in describing the origin of the Work and reproducing the content of the NOTICE file. 7. Disclaimer of Warranty. Unless required by applicable law or agreed to in writing, Licensor provides the Work (and each Contributor provides its Contributions) on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, including, without limitation, any warranties or conditions of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are solely responsible for determining the appropriateness of using or redistributing the Work and assume any risks associated with Your exercise of permissions under this License. 8. Limitation of Liability. In no event and under no legal theory, whether in tort (including negligence), contract, or otherwise, unless required by applicable law (such as deliberate and grossly negligent acts) or agreed to in writing, shall any Contributor be liable to You for damages, including any direct, indirect, special, incidental, or consequential damages of any character arising as a result of this License or out of the use or inability to use the Work (including but not limited to damages for loss of goodwill, work stoppage, computer failure or malfunction, or any and all other commercial damages or losses), even if such Contributor has been advised of the possibility of such damages. 9. Accepting Warranty or Additional Liability. While redistributing the Work or Derivative Works thereof, You may choose to offer, and charge a fee for, acceptance of support, warranty, indemnity, or other liability obligations and/or rights consistent with this License. However, in accepting such obligations, You may act only on Your own behalf and on Your sole responsibility, not on behalf of any other Contributor, and only if You agree to indemnify, defend, and hold each Contributor harmless for any liability incurred by, or claims asserted against, such Contributor by reason of your accepting any such warranty or additional liability. END OF TERMS AND CONDITIONS APPENDIX: How to apply the Apache License to your work. To apply the Apache License to your work, attach the following boilerplate notice, with the fields enclosed by brackets "[]" replaced with your own identifying information. (Don't include the brackets!) The text should be enclosed in the appropriate comment syntax for the file format. We also recommend that a file or class name and description of purpose be included on the same "printed page" as the copyright notice for easier identification within third-party archives. Copyright [yyyy] [name of copyright owner] Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. dynalang-0.4/rhino/.classpath0000644000175000017500000000121011011574340016200 0ustar twernertwerner dynalang-0.4/rhino/changelog.txt0000644000175000017500000000006311011574340016712 0ustar twernertwerner0.4 (2008.05.10) ================ Initial versiondynalang-0.4/rhino/build.xml0000644000175000017500000001661711011574340016057 0ustar twernertwerner dynalang-0.4/rhino/ivy.xml0000644000175000017500000000104311011574340015552 0ustar twernertwerner dynalang-0.4/mop/0000755000175000017500000000000011425436177013715 5ustar twernertwernerdynalang-0.4/mop/.project0000644000175000017500000000056310651477755015377 0ustar twernertwerner Dynalang-MOP org.eclipse.jdt.core.javabuilder org.eclipse.jdt.core.javanature dynalang-0.4/mop/.settings/0000755000175000017500000000000011425436177015633 5ustar twernertwernerdynalang-0.4/mop/.settings/org.eclipse.jdt.ui.prefs0000644000175000017500000001330110716322716022273 0ustar twernertwerner#Fri Nov 09 11:23:08 CET 2007 eclipse.preferences.version=1 formatter_profile=org.eclipse.jdt.ui.default.sun_profile formatter_settings_version=11 internal.default.compliance=default org.eclipse.jdt.ui.text.custom_code_templates= dynalang-0.4/mop/.settings/org.eclipse.jdt.core.prefs0000644000175000017500000005516110716322716022620 0ustar twernertwerner#Fri Nov 09 11:23:22 CET 2007 eclipse.preferences.version=1 org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.5 org.eclipse.jdt.core.compiler.codegen.unusedLocal=preserve org.eclipse.jdt.core.compiler.compliance=1.5 org.eclipse.jdt.core.compiler.debug.lineNumber=generate org.eclipse.jdt.core.compiler.debug.localVariable=generate org.eclipse.jdt.core.compiler.debug.sourceFile=generate org.eclipse.jdt.core.compiler.doc.comment.support=enabled org.eclipse.jdt.core.compiler.problem.assertIdentifier=error org.eclipse.jdt.core.compiler.problem.enumIdentifier=error org.eclipse.jdt.core.compiler.problem.invalidJavadoc=warning org.eclipse.jdt.core.compiler.problem.invalidJavadocTags=enabled org.eclipse.jdt.core.compiler.problem.invalidJavadocTagsDeprecatedRef=enabled org.eclipse.jdt.core.compiler.problem.invalidJavadocTagsNotVisibleRef=enabled org.eclipse.jdt.core.compiler.problem.invalidJavadocTagsVisibility=protected org.eclipse.jdt.core.compiler.problem.missingJavadocComments=warning org.eclipse.jdt.core.compiler.problem.missingJavadocCommentsOverriding=disabled org.eclipse.jdt.core.compiler.problem.missingJavadocCommentsVisibility=protected org.eclipse.jdt.core.compiler.problem.missingJavadocTags=warning org.eclipse.jdt.core.compiler.problem.missingJavadocTagsOverriding=disabled org.eclipse.jdt.core.compiler.problem.missingJavadocTagsVisibility=protected org.eclipse.jdt.core.compiler.source=1.5 org.eclipse.jdt.core.formatter.align_type_members_on_columns=false org.eclipse.jdt.core.formatter.alignment_for_arguments_in_allocation_expression=16 org.eclipse.jdt.core.formatter.alignment_for_arguments_in_enum_constant=16 org.eclipse.jdt.core.formatter.alignment_for_arguments_in_explicit_constructor_call=16 org.eclipse.jdt.core.formatter.alignment_for_arguments_in_method_invocation=16 org.eclipse.jdt.core.formatter.alignment_for_arguments_in_qualified_allocation_expression=16 org.eclipse.jdt.core.formatter.alignment_for_assignment=0 org.eclipse.jdt.core.formatter.alignment_for_binary_expression=16 org.eclipse.jdt.core.formatter.alignment_for_compact_if=16 org.eclipse.jdt.core.formatter.alignment_for_conditional_expression=80 org.eclipse.jdt.core.formatter.alignment_for_enum_constants=0 org.eclipse.jdt.core.formatter.alignment_for_expressions_in_array_initializer=16 org.eclipse.jdt.core.formatter.alignment_for_multiple_fields=16 org.eclipse.jdt.core.formatter.alignment_for_parameters_in_constructor_declaration=16 org.eclipse.jdt.core.formatter.alignment_for_parameters_in_method_declaration=16 org.eclipse.jdt.core.formatter.alignment_for_selector_in_method_invocation=16 org.eclipse.jdt.core.formatter.alignment_for_superclass_in_type_declaration=16 org.eclipse.jdt.core.formatter.alignment_for_superinterfaces_in_enum_declaration=16 org.eclipse.jdt.core.formatter.alignment_for_superinterfaces_in_type_declaration=16 org.eclipse.jdt.core.formatter.alignment_for_throws_clause_in_constructor_declaration=16 org.eclipse.jdt.core.formatter.alignment_for_throws_clause_in_method_declaration=16 org.eclipse.jdt.core.formatter.blank_lines_after_imports=1 org.eclipse.jdt.core.formatter.blank_lines_after_package=1 org.eclipse.jdt.core.formatter.blank_lines_before_field=0 org.eclipse.jdt.core.formatter.blank_lines_before_first_class_body_declaration=0 org.eclipse.jdt.core.formatter.blank_lines_before_imports=1 org.eclipse.jdt.core.formatter.blank_lines_before_member_type=1 org.eclipse.jdt.core.formatter.blank_lines_before_method=1 org.eclipse.jdt.core.formatter.blank_lines_before_new_chunk=1 org.eclipse.jdt.core.formatter.blank_lines_before_package=0 org.eclipse.jdt.core.formatter.blank_lines_between_import_groups=1 org.eclipse.jdt.core.formatter.blank_lines_between_type_declarations=1 org.eclipse.jdt.core.formatter.brace_position_for_annotation_type_declaration=end_of_line org.eclipse.jdt.core.formatter.brace_position_for_anonymous_type_declaration=end_of_line org.eclipse.jdt.core.formatter.brace_position_for_array_initializer=end_of_line org.eclipse.jdt.core.formatter.brace_position_for_block=end_of_line org.eclipse.jdt.core.formatter.brace_position_for_block_in_case=end_of_line org.eclipse.jdt.core.formatter.brace_position_for_constructor_declaration=end_of_line org.eclipse.jdt.core.formatter.brace_position_for_enum_constant=end_of_line org.eclipse.jdt.core.formatter.brace_position_for_enum_declaration=end_of_line org.eclipse.jdt.core.formatter.brace_position_for_method_declaration=end_of_line org.eclipse.jdt.core.formatter.brace_position_for_switch=end_of_line org.eclipse.jdt.core.formatter.brace_position_for_type_declaration=end_of_line org.eclipse.jdt.core.formatter.comment.clear_blank_lines=false org.eclipse.jdt.core.formatter.comment.clear_blank_lines_in_block_comment=false org.eclipse.jdt.core.formatter.comment.clear_blank_lines_in_javadoc_comment=false org.eclipse.jdt.core.formatter.comment.format_block_comments=true org.eclipse.jdt.core.formatter.comment.format_comments=true org.eclipse.jdt.core.formatter.comment.format_header=false org.eclipse.jdt.core.formatter.comment.format_html=true org.eclipse.jdt.core.formatter.comment.format_javadoc_comments=true org.eclipse.jdt.core.formatter.comment.format_line_comments=true org.eclipse.jdt.core.formatter.comment.format_source_code=true org.eclipse.jdt.core.formatter.comment.indent_parameter_description=true org.eclipse.jdt.core.formatter.comment.indent_root_tags=true org.eclipse.jdt.core.formatter.comment.insert_new_line_before_root_tags=insert org.eclipse.jdt.core.formatter.comment.insert_new_line_for_parameter=insert org.eclipse.jdt.core.formatter.comment.line_length=80 org.eclipse.jdt.core.formatter.compact_else_if=true org.eclipse.jdt.core.formatter.continuation_indentation=2 org.eclipse.jdt.core.formatter.continuation_indentation_for_array_initializer=2 org.eclipse.jdt.core.formatter.format_guardian_clause_on_one_line=false org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_annotation_declaration_header=true org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_enum_constant_header=true org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_enum_declaration_header=true org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_type_header=true org.eclipse.jdt.core.formatter.indent_breaks_compare_to_cases=true org.eclipse.jdt.core.formatter.indent_empty_lines=false org.eclipse.jdt.core.formatter.indent_statements_compare_to_block=true org.eclipse.jdt.core.formatter.indent_statements_compare_to_body=true org.eclipse.jdt.core.formatter.indent_switchstatements_compare_to_cases=true org.eclipse.jdt.core.formatter.indent_switchstatements_compare_to_switch=false org.eclipse.jdt.core.formatter.indentation.size=4 org.eclipse.jdt.core.formatter.insert_new_line_after_annotation=insert org.eclipse.jdt.core.formatter.insert_new_line_after_opening_brace_in_array_initializer=do not insert org.eclipse.jdt.core.formatter.insert_new_line_at_end_of_file_if_missing=do not insert org.eclipse.jdt.core.formatter.insert_new_line_before_catch_in_try_statement=do not insert org.eclipse.jdt.core.formatter.insert_new_line_before_closing_brace_in_array_initializer=do not insert org.eclipse.jdt.core.formatter.insert_new_line_before_else_in_if_statement=do not insert org.eclipse.jdt.core.formatter.insert_new_line_before_finally_in_try_statement=do not insert org.eclipse.jdt.core.formatter.insert_new_line_before_while_in_do_statement=do not insert org.eclipse.jdt.core.formatter.insert_new_line_in_empty_annotation_declaration=insert org.eclipse.jdt.core.formatter.insert_new_line_in_empty_anonymous_type_declaration=insert org.eclipse.jdt.core.formatter.insert_new_line_in_empty_block=insert org.eclipse.jdt.core.formatter.insert_new_line_in_empty_enum_constant=insert org.eclipse.jdt.core.formatter.insert_new_line_in_empty_enum_declaration=insert org.eclipse.jdt.core.formatter.insert_new_line_in_empty_method_body=insert org.eclipse.jdt.core.formatter.insert_new_line_in_empty_type_declaration=insert org.eclipse.jdt.core.formatter.insert_space_after_and_in_type_parameter=insert org.eclipse.jdt.core.formatter.insert_space_after_assignment_operator=insert org.eclipse.jdt.core.formatter.insert_space_after_at_in_annotation=do not insert org.eclipse.jdt.core.formatter.insert_space_after_at_in_annotation_type_declaration=do not insert org.eclipse.jdt.core.formatter.insert_space_after_binary_operator=insert org.eclipse.jdt.core.formatter.insert_space_after_closing_angle_bracket_in_type_arguments=insert org.eclipse.jdt.core.formatter.insert_space_after_closing_angle_bracket_in_type_parameters=insert org.eclipse.jdt.core.formatter.insert_space_after_closing_brace_in_block=insert org.eclipse.jdt.core.formatter.insert_space_after_closing_paren_in_cast=insert org.eclipse.jdt.core.formatter.insert_space_after_colon_in_assert=insert org.eclipse.jdt.core.formatter.insert_space_after_colon_in_case=insert org.eclipse.jdt.core.formatter.insert_space_after_colon_in_conditional=insert org.eclipse.jdt.core.formatter.insert_space_after_colon_in_for=insert org.eclipse.jdt.core.formatter.insert_space_after_colon_in_labeled_statement=insert org.eclipse.jdt.core.formatter.insert_space_after_comma_in_allocation_expression=insert org.eclipse.jdt.core.formatter.insert_space_after_comma_in_annotation=insert org.eclipse.jdt.core.formatter.insert_space_after_comma_in_array_initializer=insert org.eclipse.jdt.core.formatter.insert_space_after_comma_in_constructor_declaration_parameters=insert org.eclipse.jdt.core.formatter.insert_space_after_comma_in_constructor_declaration_throws=insert org.eclipse.jdt.core.formatter.insert_space_after_comma_in_enum_constant_arguments=insert org.eclipse.jdt.core.formatter.insert_space_after_comma_in_enum_declarations=insert org.eclipse.jdt.core.formatter.insert_space_after_comma_in_explicitconstructorcall_arguments=insert org.eclipse.jdt.core.formatter.insert_space_after_comma_in_for_increments=insert org.eclipse.jdt.core.formatter.insert_space_after_comma_in_for_inits=insert org.eclipse.jdt.core.formatter.insert_space_after_comma_in_method_declaration_parameters=insert org.eclipse.jdt.core.formatter.insert_space_after_comma_in_method_declaration_throws=insert org.eclipse.jdt.core.formatter.insert_space_after_comma_in_method_invocation_arguments=insert org.eclipse.jdt.core.formatter.insert_space_after_comma_in_multiple_field_declarations=insert org.eclipse.jdt.core.formatter.insert_space_after_comma_in_multiple_local_declarations=insert org.eclipse.jdt.core.formatter.insert_space_after_comma_in_parameterized_type_reference=insert org.eclipse.jdt.core.formatter.insert_space_after_comma_in_superinterfaces=insert org.eclipse.jdt.core.formatter.insert_space_after_comma_in_type_arguments=insert org.eclipse.jdt.core.formatter.insert_space_after_comma_in_type_parameters=insert org.eclipse.jdt.core.formatter.insert_space_after_ellipsis=insert org.eclipse.jdt.core.formatter.insert_space_after_opening_angle_bracket_in_parameterized_type_reference=do not insert org.eclipse.jdt.core.formatter.insert_space_after_opening_angle_bracket_in_type_arguments=do not insert org.eclipse.jdt.core.formatter.insert_space_after_opening_angle_bracket_in_type_parameters=do not insert org.eclipse.jdt.core.formatter.insert_space_after_opening_brace_in_array_initializer=insert org.eclipse.jdt.core.formatter.insert_space_after_opening_bracket_in_array_allocation_expression=do not insert org.eclipse.jdt.core.formatter.insert_space_after_opening_bracket_in_array_reference=do not insert org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_annotation=do not insert org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_cast=do not insert org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_catch=do not insert org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_constructor_declaration=do not insert org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_enum_constant=do not insert org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_for=do not insert org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_if=do not insert org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_method_declaration=do not insert org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_method_invocation=do not insert org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_parenthesized_expression=do not insert org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_switch=do not insert org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_synchronized=do not insert org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_while=do not insert org.eclipse.jdt.core.formatter.insert_space_after_postfix_operator=do not insert org.eclipse.jdt.core.formatter.insert_space_after_prefix_operator=do not insert org.eclipse.jdt.core.formatter.insert_space_after_question_in_conditional=insert org.eclipse.jdt.core.formatter.insert_space_after_question_in_wildcard=do not insert org.eclipse.jdt.core.formatter.insert_space_after_semicolon_in_for=insert org.eclipse.jdt.core.formatter.insert_space_after_unary_operator=do not insert org.eclipse.jdt.core.formatter.insert_space_before_and_in_type_parameter=insert org.eclipse.jdt.core.formatter.insert_space_before_assignment_operator=insert org.eclipse.jdt.core.formatter.insert_space_before_at_in_annotation_type_declaration=insert org.eclipse.jdt.core.formatter.insert_space_before_binary_operator=insert org.eclipse.jdt.core.formatter.insert_space_before_closing_angle_bracket_in_parameterized_type_reference=do not insert org.eclipse.jdt.core.formatter.insert_space_before_closing_angle_bracket_in_type_arguments=do not insert org.eclipse.jdt.core.formatter.insert_space_before_closing_angle_bracket_in_type_parameters=do not insert org.eclipse.jdt.core.formatter.insert_space_before_closing_brace_in_array_initializer=insert org.eclipse.jdt.core.formatter.insert_space_before_closing_bracket_in_array_allocation_expression=do not insert org.eclipse.jdt.core.formatter.insert_space_before_closing_bracket_in_array_reference=do not insert org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_annotation=do not insert org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_cast=do not insert org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_catch=do not insert org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_constructor_declaration=do not insert org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_enum_constant=do not insert org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_for=do not insert org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_if=do not insert org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_method_declaration=do not insert org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_method_invocation=do not insert org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_parenthesized_expression=do not insert org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_switch=do not insert org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_synchronized=do not insert org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_while=do not insert org.eclipse.jdt.core.formatter.insert_space_before_colon_in_assert=insert org.eclipse.jdt.core.formatter.insert_space_before_colon_in_case=do not insert org.eclipse.jdt.core.formatter.insert_space_before_colon_in_conditional=insert org.eclipse.jdt.core.formatter.insert_space_before_colon_in_default=do not insert org.eclipse.jdt.core.formatter.insert_space_before_colon_in_for=insert org.eclipse.jdt.core.formatter.insert_space_before_colon_in_labeled_statement=do not insert org.eclipse.jdt.core.formatter.insert_space_before_comma_in_allocation_expression=do not insert org.eclipse.jdt.core.formatter.insert_space_before_comma_in_annotation=do not insert org.eclipse.jdt.core.formatter.insert_space_before_comma_in_array_initializer=do not insert org.eclipse.jdt.core.formatter.insert_space_before_comma_in_constructor_declaration_parameters=do not insert org.eclipse.jdt.core.formatter.insert_space_before_comma_in_constructor_declaration_throws=do not insert org.eclipse.jdt.core.formatter.insert_space_before_comma_in_enum_constant_arguments=do not insert org.eclipse.jdt.core.formatter.insert_space_before_comma_in_enum_declarations=do not insert org.eclipse.jdt.core.formatter.insert_space_before_comma_in_explicitconstructorcall_arguments=do not insert org.eclipse.jdt.core.formatter.insert_space_before_comma_in_for_increments=do not insert org.eclipse.jdt.core.formatter.insert_space_before_comma_in_for_inits=do not insert org.eclipse.jdt.core.formatter.insert_space_before_comma_in_method_declaration_parameters=do not insert org.eclipse.jdt.core.formatter.insert_space_before_comma_in_method_declaration_throws=do not insert org.eclipse.jdt.core.formatter.insert_space_before_comma_in_method_invocation_arguments=do not insert org.eclipse.jdt.core.formatter.insert_space_before_comma_in_multiple_field_declarations=do not insert org.eclipse.jdt.core.formatter.insert_space_before_comma_in_multiple_local_declarations=do not insert org.eclipse.jdt.core.formatter.insert_space_before_comma_in_parameterized_type_reference=do not insert org.eclipse.jdt.core.formatter.insert_space_before_comma_in_superinterfaces=do not insert org.eclipse.jdt.core.formatter.insert_space_before_comma_in_type_arguments=do not insert org.eclipse.jdt.core.formatter.insert_space_before_comma_in_type_parameters=do not insert org.eclipse.jdt.core.formatter.insert_space_before_ellipsis=do not insert org.eclipse.jdt.core.formatter.insert_space_before_opening_angle_bracket_in_parameterized_type_reference=do not insert org.eclipse.jdt.core.formatter.insert_space_before_opening_angle_bracket_in_type_arguments=do not insert org.eclipse.jdt.core.formatter.insert_space_before_opening_angle_bracket_in_type_parameters=do not insert org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_annotation_type_declaration=insert org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_anonymous_type_declaration=insert org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_array_initializer=insert org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_block=insert org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_constructor_declaration=insert org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_enum_constant=insert org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_enum_declaration=insert org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_method_declaration=insert org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_switch=insert org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_type_declaration=insert org.eclipse.jdt.core.formatter.insert_space_before_opening_bracket_in_array_allocation_expression=do not insert org.eclipse.jdt.core.formatter.insert_space_before_opening_bracket_in_array_reference=do not insert org.eclipse.jdt.core.formatter.insert_space_before_opening_bracket_in_array_type_reference=do not insert org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_annotation=do not insert org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_annotation_type_member_declaration=do not insert org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_catch=insert org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_constructor_declaration=do not insert org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_enum_constant=do not insert org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_for=insert org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_if=insert org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_method_declaration=do not insert org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_method_invocation=do not insert org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_parenthesized_expression=do not insert org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_switch=insert org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_synchronized=insert org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_while=insert org.eclipse.jdt.core.formatter.insert_space_before_parenthesized_expression_in_return=insert org.eclipse.jdt.core.formatter.insert_space_before_parenthesized_expression_in_throw=insert org.eclipse.jdt.core.formatter.insert_space_before_postfix_operator=do not insert org.eclipse.jdt.core.formatter.insert_space_before_prefix_operator=do not insert org.eclipse.jdt.core.formatter.insert_space_before_question_in_conditional=insert org.eclipse.jdt.core.formatter.insert_space_before_question_in_wildcard=do not insert org.eclipse.jdt.core.formatter.insert_space_before_semicolon=do not insert org.eclipse.jdt.core.formatter.insert_space_before_semicolon_in_for=do not insert org.eclipse.jdt.core.formatter.insert_space_before_unary_operator=do not insert org.eclipse.jdt.core.formatter.insert_space_between_brackets_in_array_type_reference=do not insert org.eclipse.jdt.core.formatter.insert_space_between_empty_braces_in_array_initializer=do not insert org.eclipse.jdt.core.formatter.insert_space_between_empty_brackets_in_array_allocation_expression=do not insert org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_annotation_type_member_declaration=do not insert org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_constructor_declaration=do not insert org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_enum_constant=do not insert org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_method_declaration=do not insert org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_method_invocation=do not insert org.eclipse.jdt.core.formatter.keep_else_statement_on_same_line=false org.eclipse.jdt.core.formatter.keep_empty_array_initializer_on_one_line=false org.eclipse.jdt.core.formatter.keep_imple_if_on_one_line=false org.eclipse.jdt.core.formatter.keep_then_statement_on_same_line=false org.eclipse.jdt.core.formatter.lineSplit=80 org.eclipse.jdt.core.formatter.never_indent_block_comments_on_first_column=false org.eclipse.jdt.core.formatter.never_indent_line_comments_on_first_column=false org.eclipse.jdt.core.formatter.number_of_blank_lines_at_beginning_of_method_body=0 org.eclipse.jdt.core.formatter.number_of_empty_lines_to_preserve=1 org.eclipse.jdt.core.formatter.put_empty_statement_on_new_line=true org.eclipse.jdt.core.formatter.tabulation.char=mixed org.eclipse.jdt.core.formatter.tabulation.size=8 org.eclipse.jdt.core.formatter.use_tabs_only_for_leading_indentations=false org.eclipse.jdt.core.formatter.wrap_before_binary_operator=true dynalang-0.4/mop/LICENSE.txt0000644000175000017500000002645010651506721015540 0ustar twernertwerner Apache License Version 2.0, January 2004 http://www.apache.org/licenses/ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 1. Definitions. "License" shall mean the terms and conditions for use, reproduction, and distribution as defined by Sections 1 through 9 of this document. "Licensor" shall mean the copyright owner or entity authorized by the copyright owner that is granting the License. "Legal Entity" shall mean the union of the acting entity and all other entities that control, are controlled by, or are under common control with that entity. For the purposes of this definition, "control" means (i) the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the outstanding shares, or (iii) beneficial ownership of such entity. "You" (or "Your") shall mean an individual or Legal Entity exercising permissions granted by this License. "Source" form shall mean the preferred form for making modifications, including but not limited to software source code, documentation source, and configuration files. "Object" form shall mean any form resulting from mechanical transformation or translation of a Source form, including but not limited to compiled object code, generated documentation, and conversions to other media types. "Work" shall mean the work of authorship, whether in Source or Object form, made available under the License, as indicated by a copyright notice that is included in or attached to the work (an example is provided in the Appendix below). "Derivative Works" shall mean any work, whether in Source or Object form, that is based on (or derived from) the Work and for which the editorial revisions, annotations, elaborations, or other modifications represent, as a whole, an original work of authorship. For the purposes of this License, Derivative Works shall not include works that remain separable from, or merely link (or bind by name) to the interfaces of, the Work and Derivative Works thereof. "Contribution" shall mean any work of authorship, including the original version of the Work and any modifications or additions to that Work or Derivative Works thereof, that is intentionally submitted to Licensor for inclusion in the Work by the copyright owner or by an individual or Legal Entity authorized to submit on behalf of the copyright owner. For the purposes of this definition, "submitted" means any form of electronic, verbal, or written communication sent to the Licensor or its representatives, including but not limited to communication on electronic mailing lists, source code control systems, and issue tracking systems that are managed by, or on behalf of, the Licensor for the purpose of discussing and improving the Work, but excluding communication that is conspicuously marked or otherwise designated in writing by the copyright owner as "Not a Contribution." "Contributor" shall mean Licensor and any individual or Legal Entity on behalf of whom a Contribution has been received by Licensor and subsequently incorporated within the Work. 2. Grant of Copyright License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable copyright license to reproduce, prepare Derivative Works of, publicly display, publicly perform, sublicense, and distribute the Work and such Derivative Works in Source or Object form. 3. Grant of Patent License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable (except as stated in this section) patent license to make, have made, use, offer to sell, sell, import, and otherwise transfer the Work, where such license applies only to those patent claims licensable by such Contributor that are necessarily infringed by their Contribution(s) alone or by combination of their Contribution(s) with the Work to which such Contribution(s) was submitted. If You institute patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Work or a Contribution incorporated within the Work constitutes direct or contributory patent infringement, then any patent licenses granted to You under this License for that Work shall terminate as of the date such litigation is filed. 4. Redistribution. You may reproduce and distribute copies of the Work or Derivative Works thereof in any medium, with or without modifications, and in Source or Object form, provided that You meet the following conditions: (a) You must give any other recipients of the Work or Derivative Works a copy of this License; and (b) You must cause any modified files to carry prominent notices stating that You changed the files; and (c) You must retain, in the Source form of any Derivative Works that You distribute, all copyright, patent, trademark, and attribution notices from the Source form of the Work, excluding those notices that do not pertain to any part of the Derivative Works; and (d) If the Work includes a "NOTICE" text file as part of its distribution, then any Derivative Works that You distribute must include a readable copy of the attribution notices contained within such NOTICE file, excluding those notices that do not pertain to any part of the Derivative Works, in at least one of the following places: within a NOTICE text file distributed as part of the Derivative Works; within the Source form or documentation, if provided along with the Derivative Works; or, within a display generated by the Derivative Works, if and wherever such third-party notices normally appear. The contents of the NOTICE file are for informational purposes only and do not modify the License. You may add Your own attribution notices within Derivative Works that You distribute, alongside or as an addendum to the NOTICE text from the Work, provided that such additional attribution notices cannot be construed as modifying the License. You may add Your own copyright statement to Your modifications and may provide additional or different license terms and conditions for use, reproduction, or distribution of Your modifications, or for any such Derivative Works as a whole, provided Your use, reproduction, and distribution of the Work otherwise complies with the conditions stated in this License. 5. Submission of Contributions. Unless You explicitly state otherwise, any Contribution intentionally submitted for inclusion in the Work by You to the Licensor shall be under the terms and conditions of this License, without any additional terms or conditions. Notwithstanding the above, nothing herein shall supersede or modify the terms of any separate license agreement you may have executed with Licensor regarding such Contributions. 6. Trademarks. This License does not grant permission to use the trade names, trademarks, service marks, or product names of the Licensor, except as required for reasonable and customary use in describing the origin of the Work and reproducing the content of the NOTICE file. 7. Disclaimer of Warranty. Unless required by applicable law or agreed to in writing, Licensor provides the Work (and each Contributor provides its Contributions) on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, including, without limitation, any warranties or conditions of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are solely responsible for determining the appropriateness of using or redistributing the Work and assume any risks associated with Your exercise of permissions under this License. 8. Limitation of Liability. In no event and under no legal theory, whether in tort (including negligence), contract, or otherwise, unless required by applicable law (such as deliberate and grossly negligent acts) or agreed to in writing, shall any Contributor be liable to You for damages, including any direct, indirect, special, incidental, or consequential damages of any character arising as a result of this License or out of the use or inability to use the Work (including but not limited to damages for loss of goodwill, work stoppage, computer failure or malfunction, or any and all other commercial damages or losses), even if such Contributor has been advised of the possibility of such damages. 9. Accepting Warranty or Additional Liability. While redistributing the Work or Derivative Works thereof, You may choose to offer, and charge a fee for, acceptance of support, warranty, indemnity, or other liability obligations and/or rights consistent with this License. However, in accepting such obligations, You may act only on Your own behalf and on Your sole responsibility, not on behalf of any other Contributor, and only if You agree to indemnify, defend, and hold each Contributor harmless for any liability incurred by, or claims asserted against, such Contributor by reason of your accepting any such warranty or additional liability. END OF TERMS AND CONDITIONS APPENDIX: How to apply the Apache License to your work. To apply the Apache License to your work, attach the following boilerplate notice, with the fields enclosed by brackets "[]" replaced with your own identifying information. (Don't include the brackets!) The text should be enclosed in the appropriate comment syntax for the file format. We also recommend that a file or class name and description of purpose be included on the same "printed page" as the copyright notice for easier identification within third-party archives. Copyright [yyyy] [name of copyright owner] Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. dynalang-0.4/mop/.classpath0000644000175000017500000000066110751423660015675 0ustar twernertwerner dynalang-0.4/mop/testsrc/0000755000175000017500000000000011425436177015404 5ustar twernertwernerdynalang-0.4/mop/testsrc/META-INF/0000755000175000017500000000000011425436177016544 5ustar twernertwernerdynalang-0.4/mop/testsrc/META-INF/services/0000755000175000017500000000000011425436177020367 5ustar twernertwernerdynalang-0.4/mop/testsrc/META-INF/services/org.dynalang.mop.BaseMetaobjectProtocol0000644000175000017500000000016210716573340030053 0ustar twernertwerner# $Id: $ org.dynalang.mop.impl.test.DummyMetaobjectProtocol1 org.dynalang.mop.impl.test.DummyMetaobjectProtocol2dynalang-0.4/mop/testsrc/org/0000755000175000017500000000000011425436177016173 5ustar twernertwernerdynalang-0.4/mop/testsrc/org/dynalang/0000755000175000017500000000000011425436177017770 5ustar twernertwernerdynalang-0.4/mop/testsrc/org/dynalang/mop/0000755000175000017500000000000011425436177020563 5ustar twernertwernerdynalang-0.4/mop/testsrc/org/dynalang/mop/beans/0000755000175000017500000000000011425436177021653 5ustar twernertwernerdynalang-0.4/mop/testsrc/org/dynalang/mop/beans/TestArrays.java0000644000175000017500000001120510724016017024602 0ustar twernertwerner/* Copyright 2007 Attila Szegedi Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ package org.dynalang.mop.beans; import java.util.ArrayList; import java.util.Arrays; import java.util.Iterator; import java.util.List; import java.util.Map; import junit.framework.TestCase; import org.dynalang.mop.MetaobjectProtocol; import org.dynalang.mop.BaseMetaobjectProtocol.Result; /** * @author Attila Szegedi * @version $Id: $ */ public class TestArrays extends TestCase { private MetaobjectProtocol mop; @Override protected void setUp() throws Exception { mop = new BeansMetaobjectProtocol(true); } public TestArrays(String name) { super(name); } public void testLength() { int[] x = new int[5]; assertEquals(Integer.valueOf(5), mop.get(x, "length")); assertEquals(Boolean.TRUE, mop.has(x, "length")); assertEquals(Result.notWritable, mop.put(x, "length", 1, mop)); } public void testGet() { int[] x = new int[] {14, 11, 1974 }; assertEquals(Integer.valueOf(14), mop.get(x, Integer.valueOf(0))); assertEquals(Integer.valueOf(11), mop.get(x, 1L)); assertEquals(Integer.valueOf(1974), mop.get(x, Integer.valueOf(2))); assertEquals(Result.doesNotExist, mop.get(x, -1L)); assertEquals(Result.doesNotExist, mop.get(x, Integer.valueOf(3))); } public void testHas() { int[] x = new int[] {14, 11, 1974 }; assertEquals(Boolean.TRUE, mop.has(x, Integer.valueOf(0))); assertEquals(Boolean.TRUE, mop.has(x, 1)); assertEquals(Boolean.TRUE, mop.has(x, Integer.valueOf(2))); assertEquals(Boolean.FALSE, mop.has(x, -1)); assertEquals(Boolean.FALSE, mop.has(x, Integer.valueOf(3))); } public void testPut() { int[] x = new int[2]; assertEquals(Result.ok, mop.put(x, Integer.valueOf(0), Integer.valueOf(19), mop)); assertEquals(Result.ok, mop.put(x, Integer.valueOf(1), Integer.valueOf(6), mop)); assertEquals(Integer.valueOf(19), mop.get(x, Integer.valueOf(0))); assertEquals(Integer.valueOf(6), mop.get(x, Integer.valueOf(1))); assertEquals(19, x[0]); assertEquals(6, x[1]); assertEquals(Result.doesNotExist, mop.put(x, Integer.valueOf(2), Integer.valueOf(6), mop)); assertEquals(Result.noRepresentation, mop.put(x, Integer.valueOf(1), "xx", mop)); } public void testPropertyIds() { int[] x = new int[2]; Iterator it = mop.propertyIds(x); assertTrue(it.hasNext()); assertEquals(Integer.valueOf(0), it.next()); assertUnremovable(it); assertTrue(it.hasNext()); assertEquals(Integer.valueOf(1), it.next()); assertTrue(it.hasNext()); assertEquals("length", it.next()); assertUnremovable(it); List s = new ArrayList(); while(it.hasNext()) { s.add(it.next()); assertUnremovable(it); } assertEquals(Arrays.asList(new Object[] { "class", "equals", "getClass", "hashCode", "notify", "notifyAll", "toString", "wait" }), s); } public void testProperties() { int[] x = new int[] { 1999, 2001 }; Iterator it = mop.properties(x); Map.Entry e = it.next(); assertEquals(Integer.valueOf(0), e.getKey()); assertEquals(Integer.valueOf(1999), e.getValue()); e = it.next(); assertEquals(Integer.valueOf(1), e.getKey()); assertEquals(Integer.valueOf(2001), e.getValue()); // array elements can be set e.setValue(Integer.valueOf(2005)); assertEquals(2005, x[1]); e = it.next(); // non-writable properties can not be set assertEquals("length", e.getKey()); try { e.setValue("x"); } catch(UnsupportedOperationException ex) { // expected - can't set length } e = it.next(); assertEquals("class", e.getKey()); try { e.setValue("x"); } catch(UnsupportedOperationException ex) { // expected - can't set read-only property } e = it.next(); assertEquals("equals", e.getKey()); try { e.setValue("x"); } catch(UnsupportedOperationException ex) { // expected - can't set method } } private static void assertUnremovable(Iterator it) { try { it.remove(); fail(); } catch(UnsupportedOperationException e) { // expected } } } dynalang-0.4/mop/testsrc/org/dynalang/mop/beans/TestBeans.java0000644000175000017500000002465111063206304024377 0ustar twernertwerner/* Copyright 2007 Attila Szegedi Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ package org.dynalang.mop.beans; import java.util.Date; import junit.framework.TestCase; import org.dynalang.mop.BaseMetaobjectProtocol.Result; public class TestBeans extends TestCase { private BeansMetaobjectProtocol mop; private BeanForTest tb; public TestBeans(String name) { super(name); } @Override protected void setUp() throws Exception { mop = new BeansMetaobjectProtocol(true); tb = new BeanForTest(); } public void testPropertyExists() { assertTrue(mop.has(tb, "someBool")); } public void testBooleanPropertyGet() { assertEquals(mop.get(tb, "someBool"), Boolean.TRUE); } public void testBooleanPropertySet() { assertSame(mop.put(tb, "someBool", Boolean.FALSE, mop), Result.ok); assertEquals(mop.get(tb, "someBool"), Boolean.FALSE); } public void testAutomaticWideningAtPropertySet() { assertSame(mop.put(tb, "someDouble", Integer.valueOf(1), mop), Result.ok); assertEquals(mop.get(tb, "someDouble"), Double.valueOf(1.0d)); } public void testNoAutomaticNarrowingAtPropertySet() { assertSame(mop.put(tb, "someInteger", Double.valueOf(1.0), mop), Result.noRepresentation); // assert value hasn't changed assertEquals(mop.get(tb, "someInteger"), Integer.valueOf(0)); } public void testPropertyUnknownOnPut() { assertSame(mop.put(tb, "foo", null, null), Result.noAuthority); } public void testNumericPropertyUnknownOnPut() { assertSame(mop.put(tb, 1, null, null), Result.noAuthority); } public void testPropertyUnknownOnGet() { assertSame(mop.get(tb, "foo"), Result.noAuthority); } public void testNumericPropertyUnknownOnGet() { assertSame(mop.get(tb, 1), Result.noAuthority); } public void testPropertyUnknownOnHas() { assertNull(mop.has(tb, "foo")); } public void testNumericPropertyUnknownOnHas() { assertNull(mop.has(tb, 1)); } public void testSimpleFixArgMethodInvocation() { assertEquals(mop.call(tb, "simpleFixArgMethod", mop, "a", "b"), "a:b"); } public void testSimpleFixArgMethodInvocationThroughMember() { Object method = mop.get(tb, "simpleFixArgMethod"); assertNotNull(method); assertFalse(method instanceof Result); assertEquals(mop.call(method, mop, "a", "b"), "a:b"); } public void testSimpleVarArgMethodInvocation() { assertEquals(mop.call(tb, "simpleVarArgMethod", mop, 1, "a", "b", "c"), "1:[a, b, c]"); } public void testVarArgMethodInvocationWithZeroVarArg() { assertEquals(mop.call(tb, "simpleVarArgMethod", mop, 1), "1:[]"); } public void testVarArgMethodInvocationWithSingleVarArg() { assertEquals(mop.call(tb, "simpleVarArgMethod", mop, 1, "a"), "1:[a]"); } public void testVarArgMethodInvocationWithNullVarArg() { assertEquals(mop.call(tb, "simpleVarArgMethod", mop, 1, null), "1:null"); } public void testVarArgMethodInvocationWithExplicitArray() { assertEquals(mop.call(tb, "simpleVarArgMethod", mop, 1, new Object[] { "a", "b" }), "1:[a, b]"); } public void testVarArgMethodInvocationWithExplicitArrayPlusOne() { Object arr = new Object[] { "a", "b" }; assertEquals(mop.call(tb, "simpleVarArgMethod", mop, 1, arr, "c"), "1:[" + arr.toString() + ", c]"); } public void testVarArgMethodInvocationWithWideningPrimitiveConversion() { assertEquals(mop.call(tb, "simpleVarArgPrimitiveMethod", mop, new Object[] { Integer.valueOf(1), Byte.valueOf((byte)2), Short.valueOf((short)3), Character.valueOf('0'), Integer.valueOf(5) }), "1:[2, 3, 48, 5]"); } public void testVarArgMethodInvocationCantRepresent() { try { mop.call(tb, "simpleVarArgPrimitiveMethod", mop, new Date()); fail(); } catch(IllegalArgumentException e) { assertTrue(e.getMessage().startsWith("Can't represent")); } } public void testOverloadedMethodInvocationNoSuch() { try { mop.call(tb, "overloadedFixArgMethod", mop, new Date()); fail(); } catch(IllegalArgumentException e) { assertTrue(e.getMessage().startsWith("No signature")); } } public void testOverloadedMethodInvocationAmbiguous() { try { mop.call(tb, "overloadedAmbiguous", mop, ""); fail(); } catch(IllegalArgumentException e) { assertTrue(e.getMessage().startsWith("Multiple signatures")); } } public void testFixArgOverloadedMethod() { assertEquals(mop.call(tb, "overloadedFixArgMethod", mop, 2), "int:2"); assertEquals(mop.call(tb, "overloadedFixArgMethod", mop, "a"), "string:a"); assertEquals(mop.call(tb, "overloadedFixArgMethod", mop, "b", 3), "string/int:b3"); assertEquals(mop.call(tb, "overloadedFixArgMethod", mop, 4, "c"), "int/string:4c"); } public void testVarArgOverloadedMethod() { assertEquals(mop.call(tb, "overloadedVarArgMethod", mop, 2), "int/String...:2[]"); assertEquals(mop.call(tb, "overloadedVarArgMethod", mop, 2, "a"), "int/String...:2[a]"); assertEquals(mop.call(tb, "overloadedVarArgMethod", mop, 2, 3), "int/int/String...:23[]"); assertEquals(mop.call(tb, "overloadedVarArgMethod", mop, 2, 3, "a"), "int/int/String...:23[a]"); assertEquals(mop.call(tb, "overloadedVarArgMethod", mop, 2, "a", "b"), "int/String...:2[a, b]"); assertEquals(mop.call(tb, "varArgs", mop, 1, 2, 3), "varArgs-int..."); assertEquals(mop.call(tb, "varArgs", mop, 1, 2), "varArgs-int,int"); assertEquals(mop.call(tb, "varArgs", mop, 1), "varArgs-int..."); assertEquals(mop.call(tb, "varArgs", mop), "varArgs-int..."); assertEquals(mop.call(tb, "moreSpecific", mop, "someString"), "moreSpecific-String"); } public void testNullArgsSameAsEmpty() { tb.setSomeDouble(2.0d); assertEquals(mop.call(tb, "getSomeDouble", mop, (Object[])null), Double.valueOf(2.0d)); } public void testWideningPrimitiveConversionOnCall() { assertNull(mop.call(tb, "setSomeDouble", mop, new Object[] { Integer.valueOf(1) })); assertEquals(tb.getSomeDouble(), 1.0d); } public void testNoConversionOnCall() { try { mop.call(tb, "setSomeDouble", mop, "a"); fail(); } catch(IllegalArgumentException e) { // this is expected } } public void testPropertiesNotCallable() { assertEquals(mop.call(tb, "someBool", mop, "a", "b"), Result.noAuthority); } public void testNonexistantMethodInvocation() { assertEquals(mop.call(tb, "someMethodThatIsNot", mop, "a", "b"), Result.noAuthority); } public void testConstructorOverloading() { assertCreatedBeanForTest(true, 0, 0d); assertCreatedBeanForTest(false, 0, 0d, false); assertCreatedBeanForTest(true, 1, 0d, 1); assertCreatedBeanForTest(true, 0, 1d, 1d); assertCreatedBeanForTest(false, 1, 0d, false, 1); assertCreatedBeanForTest(false, 0, 1d, false, 1d); assertCreatedBeanForTest(true, 1, 1d, 1, 1d); // No signature matches -- expected to throw an exception try { assertCreatedBeanForTest(true, 0, 0d, new Object()); fail(); } catch(IllegalArgumentException e) { assertEquals("No signature of method on class org.dynalang.mop.beans.BeanForTest matches the arguments", e.getMessage()); } } public void testStaticMethodOverloading() { assertStaticTest(true, 0, 0d); assertStaticTest(false, 0, 0d, false); assertStaticTest(true, 1, 0d, 1); assertStaticTest(true, 0, 1d, 1d); } public void testStaticMethodNotFound() { assertEquals(Result.doesNotExist, mop.getBeanMetaobjectProtocol( BeanForTest.class).callStatic("foo", mop)); } public void testInstanceVsStaticMethod() { // No signature matches -- expected to throw an exception. The create // method taking a string is an instance, not static method. try { assertStaticTest(true, 0, 0d, ""); fail(); } catch(IllegalArgumentException e) { assertEquals("No signature of method create on class org.dynalang.mop.beans.BeanForTest matches the arguments", e.getMessage()); } // No signature matches -- expected to throw an exception. The create // method taking a double is a static, not instance method. try { mop.call(tb, "create", mop, 1d); fail(); } catch(IllegalArgumentException e) { assertEquals("Can't represent java.lang.Double as java.lang.String for invoking public void org.dynalang.mop.beans.BeanForTest.create(java.lang.String)", e.getMessage()); } } private void assertCreatedBeanForTest(boolean someBool, int someInteger, double someDouble, Object... args) { BeanForTest bft = mop.getBeanMetaobjectProtocol(BeanForTest.class).newInstance(mop, args); assertEquals(someBool, bft.isSomeBool()); assertEquals(someInteger, bft.getSomeInteger()); assertEquals(someDouble, bft.getSomeDouble()); } private void assertStaticTest(boolean someBool, int someInteger, double someDouble, Object... args) { Object retval = mop.getBeanMetaobjectProtocol(BeanForTest.class).callStatic("create", mop, args); assertTrue(retval instanceof BeanForTest); BeanForTest bft = (BeanForTest)retval; assertEquals(someBool, bft.isSomeBool()); assertEquals(someInteger, bft.getSomeInteger()); assertEquals(someDouble, bft.getSomeDouble()); } }dynalang-0.4/mop/testsrc/org/dynalang/mop/beans/BeanForTest.java0000644000175000017500000001157111063206304024660 0ustar twernertwerner/* Copyright 2007 Attila Szegedi Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ package org.dynalang.mop.beans; import java.io.Serializable; import java.util.Arrays; import junit.framework.AssertionFailedError; public class BeanForTest { private boolean someBool = true; private int someInteger; private double someDouble; public BeanForTest() { } public BeanForTest(boolean someBool) { this.someBool = someBool; } public BeanForTest(int someInteger) { this.someInteger = someInteger; } public BeanForTest(double someDouble) { this.someDouble = someDouble; } public BeanForTest(boolean someBool, int someInteger) { this.someBool = someBool; this.someInteger = someInteger; } public BeanForTest(boolean someBool, double someDouble) { this.someBool = someBool; this.someDouble = someDouble; } public BeanForTest(int someInteger, double someDouble) { this.someInteger = someInteger; this.someDouble = someDouble; } public void setSomeDouble(double someDouble) { this.someDouble = someDouble; } public double getSomeDouble() { return someDouble; } public void setSomeInteger(int someInt) { this.someInteger = someInt; } public int getSomeInteger() { return someInteger; } public void setSomeBool(boolean someBool) { this.someBool = someBool; } public boolean isSomeBool() { return someBool; } public String simpleFixArgMethod(Object o1, Object o2) { return o1 + ":" + o2; } public String simpleVarArgMethod(int i, Object... o) { return i + ":" + Arrays.toString(o); } public String simpleVarArgPrimitiveMethod(int i, int... o) { return i + ":" + Arrays.toString(o); } public String overloadedFixArgMethod(int i) { return "int:" + i; } public String overloadedFixArgMethod(String s) { return "string:" + s; } public String overloadedFixArgMethod(String s, int i) { return "string/int:" + s + i; } public String overloadedFixArgMethod(int i, String s) { return "int/string:" + i + s; } public String overloadedVarArgMethod(int i, int j, String... s) { return "int/int/String...:" + i + j + Arrays.toString(s); } public String overloadedVarArgMethod(int i, String... s) { return "int/String...:" + i + Arrays.toString(s); } public String overloadedAmbiguous(Comparable c) { throw new AssertionFailedError(); // Not meant to be called } public String overloadedAmbiguous(Serializable s) { throw new AssertionFailedError(); // Not meant to be called } public String varArgs(int... is) { return "varArgs-int..."; } public String varArgs(int i1, int i2) { return "varArgs-int,int"; } public String varArgs(String s, String... ss) { /* * This isn't invoked, but it triggers the "Vararg unwrap spec with * exactly one parameter more than the current spec influences the * types of the current spec" rule when the varArgs(String) method * is processed. */ throw new AssertionFailedError("Not supposed to be called"); } public String varArgs(String s) { /* * This isn't invoked ever, but is here only to have a 1-arg fixed * arglen method as well, so when varArgs(1) is invoked, the method * map will be forced to rewrap the last argument. */ throw new AssertionFailedError("Not supposed to be called"); } public String moreSpecific(String s) { return "moreSpecific-String"; } public String moreSpecific(Object s) { return "moreSpecific-Object"; } public static BeanForTest create() { return new BeanForTest(); } public static BeanForTest create(boolean someBool) { return new BeanForTest(someBool); } public static BeanForTest create(int someInteger) { return new BeanForTest(someInteger); } public static BeanForTest create(double someDouble) { return new BeanForTest(someDouble); } public void create(String string) { } }dynalang-0.4/mop/testsrc/org/dynalang/mop/impl/0000755000175000017500000000000011425436177021524 5ustar twernertwernerdynalang-0.4/mop/testsrc/org/dynalang/mop/impl/test/0000755000175000017500000000000011425436177022503 5ustar twernertwernerdynalang-0.4/mop/testsrc/org/dynalang/mop/impl/test/TestStandardMetaobjectProtocolFactory.java0000644000175000017500000002000311063167034033000 0ustar twernertwernerpackage org.dynalang.mop.impl.test; import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; import java.util.HashMap; import java.util.HashSet; import java.util.Iterator; import java.util.List; import java.util.Map; import java.util.Set; import junit.framework.TestCase; import org.dynalang.mop.MetaobjectProtocol; import org.dynalang.mop.BaseMetaobjectProtocol.Result; import org.dynalang.mop.impl.StandardMetaobjectProtocolFactory; public class TestStandardMetaobjectProtocolFactory extends TestCase { public void testDynaObject1() throws Exception { Thread.currentThread().setContextClassLoader(getClass().getClassLoader()); MetaobjectProtocol mop = StandardMetaobjectProtocolFactory.createStandardMetaobjectProtocol(true, false); DynaObject1 o1 = new DynaObject1(); assertEquals(Result.notCallable, mop.call(o1, mop, (Map)null)); assertEquals("called1", mop.call(o1, mop)); assertEquals(Result.doesNotExist, mop.call(o1, "prop2", mop)); assertEquals(Result.notCallable, mop.call(o1, "prop1", mop)); assertEquals(Result.notDeleteable, mop.delete(o1, "prop1")); assertEquals(Result.doesNotExist, mop.delete(o1, "prop2")); assertEquals(Result.doesNotExist, mop.get(o1, 0L)); assertEquals(Result.doesNotExist, mop.get(o1, "prop2")); assertEquals("value1", mop.get(o1, "prop1")); assertEquals(Boolean.FALSE, mop.has(o1, "prop2")); assertEquals(Boolean.TRUE, mop.has(o1, "prop1")); assertEquals(Result.notWritable, mop.put(o1, "prop1", "newValue", mop)); assertEquals(Result.doesNotExist, mop.put(o1, "prop2", "newValue", mop)); assertEquals(Result.doesNotExist, mop.put(o1, 0L, "newValue", mop)); assertEquals("value1", mop.representAs(o1, String.class)); assertEquals(Result.noRepresentation, mop.representAs(o1, Integer.class)); assertSame(o1, mop.representAs(o1, DynaObject1.class)); Iterator it = mop.propertyIds(o1); assertTrue(it.hasNext()); assertEquals("prop1", it.next()); assertFalse(it.hasNext()); Iterator eit = mop.properties(o1); assertTrue(eit.hasNext()); Map.Entry e = eit.next(); assertEquals("prop1", e.getKey()); assertEquals("value1", e.getValue()); assertFalse(eit.hasNext()); } public void testDynaObject2() throws Exception { Thread.currentThread().setContextClassLoader(getClass().getClassLoader()); MetaobjectProtocol mop = StandardMetaobjectProtocolFactory.createStandardMetaobjectProtocol(true, false); DynaObject2 o2 = new DynaObject2(); assertEquals("called2-named", mop.call(o2, mop, (Map)null)); assertEquals("called2-positional", mop.call(o2, mop)); assertEquals(Result.doesNotExist, mop.call(o2, "prop2", mop)); assertEquals(Result.doesNotExist, mop.call(o2, "prop1", mop)); assertEquals(Result.doesNotExist, mop.delete(o2, "prop1")); assertEquals(Result.doesNotExist, mop.delete(o2, "prop2")); assertEquals(Result.ok, mop.put(o2, "prop2", "value2", mop)); assertEquals("value2", mop.get(o2, "prop2")); assertEquals(Result.ok, mop.delete(o2, "prop2")); assertEquals(Result.doesNotExist, mop.get(o2, "prop2")); assertEquals(Boolean.FALSE, mop.has(o2, "prop2")); assertEquals(Result.ok, mop.put(o2, "prop2", "value3", mop)); assertEquals("value3", mop.get(o2, "prop2")); assertEquals(Result.notCallable, mop.call(o2, "prop2", mop)); assertEquals(Result.doesNotExist, mop.get(o2, 0L)); assertEquals(Result.doesNotExist, mop.get(o2, "prop1")); assertEquals(Boolean.FALSE, mop.has(o2, "prop1")); assertEquals(Boolean.TRUE, mop.has(o2, "prop2")); assertEquals(Result.doesNotExist, mop.put(o2, 0L, "newValue", mop)); assertEquals("value3", mop.representAs(o2, String.class)); assertEquals(Result.noRepresentation, mop.representAs(o2, Integer.class)); assertSame(o2, mop.representAs(o2, DynaObject2.class)); // Fallback to POJO method assertEquals("tadatada", mop.call(o2, "callablePojoMethod", mop, "tada")); Object callablePojoMethod = mop.get(o2, "callablePojoMethod"); assertFalse(callablePojoMethod instanceof Result); assertNotNull(callablePojoMethod); assertEquals("foofoo", mop.call(callablePojoMethod, mop, "foo")); } public void testList() throws Exception { Thread.currentThread().setContextClassLoader( getClass().getClassLoader()); MetaobjectProtocol mop = StandardMetaobjectProtocolFactory.createStandardMetaobjectProtocol( true, false); List l = new ArrayList(); assertEquals(Result.notCallable, mop.call(l, mop)); assertEquals(Result.doesNotExist, mop.call(l, 0, mop)); Iterator it = mop.properties(l); assertNotNull(it); assertFalse(it.hasNext()); // Can't put into an empty list assertEquals(Result.doesNotExist, mop.put(l, 0, "0th", mop)); // Can only add an element through the Java method assertEquals(Boolean.TRUE, mop.call(l, "add", mop, "0th")); assertEquals("0th", mop.get(l, 0)); // Can't put out of bound assertEquals(Result.doesNotExist, mop.put(l, -1, "0th", mop)); assertEquals(Result.doesNotExist, mop.put(l, 1, "0th", mop)); assertEquals(Result.ok, mop.put(l, 0, "0th, 2nd time", mop)); assertEquals(Boolean.TRUE, mop.call(l, "add", mop, "1st")); it = mop.properties(l); assertNotNull(it); assertTrue(it.hasNext()); Map.Entry e = it.next(); assertEquals(0, e.getKey()); assertEquals("0th, 2nd time", e.getValue()); assertTrue(it.hasNext()); e = it.next(); assertEquals(1, e.getKey()); assertEquals("1st", e.getValue()); assertFalse(it.hasNext()); Iterator it2 = mop.propertyIds(l); assertNotNull(it2); assertTrue(it2.hasNext()); assertEquals(0, it2.next()); assertTrue(it2.hasNext()); assertEquals(1, it2.next()); assertFalse(it2.hasNext()); assertEquals(Result.doesNotExist, mop.delete(l, -1)); assertEquals(Result.notDeleteable, mop.delete(l, 0)); assertEquals(Result.notDeleteable, mop.delete(l, 1)); assertEquals(Result.doesNotExist, mop.delete(l, 2)); assertEquals(Boolean.FALSE, mop.has(l, -1)); assertEquals(Boolean.TRUE, mop.has(l, 0)); assertEquals(Boolean.TRUE, mop.has(l, 1)); assertEquals(Boolean.FALSE, mop.has(l, 2)); } public void testMap() throws Exception { Thread.currentThread().setContextClassLoader( getClass().getClassLoader()); MetaobjectProtocol mop = StandardMetaobjectProtocolFactory.createStandardMetaobjectProtocol( true, false); Map m = new HashMap(); assertEquals(Result.notCallable, mop.call(m, mop)); assertEquals(Result.doesNotExist, mop.call(m, 0, mop)); Iterator it = mop.properties(m); assertNotNull(it); assertFalse(it.hasNext()); assertEquals(Result.doesNotExist, mop.delete(m, "foo")); assertEquals(Result.doesNotExist, mop.get(m, "foo")); assertEquals(Boolean.FALSE, mop.has(m, "foo")); assertEquals(Result.ok, mop.put(m, "foo", "bar", mop)); assertEquals("bar", mop.get(m, "foo")); assertEquals(Boolean.TRUE, mop.has(m, "foo")); String s = "foobarbaz"; Object hash = mop.call(s, "hashCode", mop); Object hashMethod = mop.get(s, "hashCode"); assertEquals(hash, mop.call(hashMethod, mop)); mop.put(m, "stringHashCode", hashMethod, mop); assertEquals(hash, mop.call(m, "stringHashCode", mop)); assertEquals(Result.ok, mop.put(m, "baz", "bing", mop)); } public void testCompositeProperties() throws Exception { Thread.currentThread().setContextClassLoader( getClass().getClassLoader()); MetaobjectProtocol mop = StandardMetaobjectProtocolFactory.createStandardMetaobjectProtocol( true, true); Map m = new HashMap(); m.put("foo", "bar"); m.put("baz", "bing"); Iterator it = mop.propertyIds(m); Set s1 = new HashSet(Arrays.asList(new Object[] {"foo", "hashCode", "entrySet", "isEmpty", "baz", "getClass", "get", "values", "toString", "class", "put", "putAll", "clone", "remove", "keySet", "containsValue", "notifyAll", "containsKey", "clear", "equals", "size", "wait", "empty", "notify"})); Set s2 = new HashSet(); while(it.hasNext()) { s2.add(it.next()); } assertEquals(s1, s2); } }dynalang-0.4/mop/testsrc/org/dynalang/mop/impl/test/DynaObject1.java0000644000175000017500000000011010716622735025440 0ustar twernertwernerpackage org.dynalang.mop.impl.test; public class DynaObject1 { } dynalang-0.4/mop/testsrc/org/dynalang/mop/impl/test/DynaObject2.java0000644000175000017500000000032110716622735025445 0ustar twernertwernerpackage org.dynalang.mop.impl.test; public class DynaObject2 { boolean propertyDefined = false; Object property; public String callablePojoMethod(String x) { return x + x; } } dynalang-0.4/mop/testsrc/org/dynalang/mop/impl/test/DummyMetaobjectProtocol2.java0000644000175000017500000000572410724016017030237 0ustar twernertwernerpackage org.dynalang.mop.impl.test; import java.util.Collections; import java.util.HashMap; import java.util.Iterator; import java.util.Map; import java.util.Map.Entry; import org.dynalang.mop.ClassBasedMetaobjectProtocol; import org.dynalang.mop.CallProtocol; import org.dynalang.mop.impl.MetaobjectProtocolBase; public class DummyMetaobjectProtocol2 extends MetaobjectProtocolBase implements ClassBasedMetaobjectProtocol { public boolean isAuthoritativeForClass(Class clazz) { return clazz == DynaObject2.class; } public Object call(Object callable, CallProtocol callProtocol, Map args) { return isDynaObject2(callable) ? "called2-named" : Result.noAuthority; } public Object call(Object callable, CallProtocol callProtocol, Object... args) { return isDynaObject2(callable) ? "called2-positional" : Result.noAuthority; } public Result delete(Object target, Object propertyId) { if(isAuthoritative(target, propertyId)) { DynaObject2 do2 = (DynaObject2)target; if(do2.propertyDefined) { do2.propertyDefined = false; do2.property = null; return Result.ok; } } return Result.noAuthority; } public Object get(Object target, Object propertyId) { if(isAuthoritative(target, propertyId)) { DynaObject2 do2 = (DynaObject2)target; return do2.propertyDefined ? do2.property : Result.noAuthority; } return Result.noAuthority; } public Boolean has(Object target, Object propertyId) { if(isAuthoritative(target, propertyId)) { DynaObject2 do2 = (DynaObject2)target; return do2.propertyDefined ? Boolean.TRUE : null; } return null; } private boolean isAuthoritative(Object target, Object propertyId) { return isDynaObject2(target) && "prop2".equals(propertyId); } public Iterator properties(Object target) { if(isDynaObject2(target)) { DynaObject2 do2 = (DynaObject2)target; if(do2.propertyDefined) { Map m = new HashMap(); m.put("prop2", do2.property); return m.entrySet().iterator(); } } return Collections.EMPTY_MAP.entrySet().iterator(); } public Result put(Object target, Object propertyId, Object value, CallProtocol callProtocol) { if(isAuthoritative(target, propertyId)) { DynaObject2 do2 = (DynaObject2)target; do2.propertyDefined = true; do2.property = value; return Result.ok; } return Result.noAuthority; } public Object representAs(Object object, Class targetClass) { return isDynaObject2(object) && targetClass == String.class ? ((DynaObject2)object).property : Result.noAuthority; } private boolean isDynaObject2(Object object) { return object instanceof DynaObject2; } }dynalang-0.4/mop/testsrc/org/dynalang/mop/impl/test/DummyMetaobjectProtocol1.java0000644000175000017500000000431410724016017030230 0ustar twernertwernerpackage org.dynalang.mop.impl.test; import java.util.Collections; import java.util.HashMap; import java.util.Iterator; import java.util.Map; import java.util.Map.Entry; import org.dynalang.mop.ClassBasedMetaobjectProtocol; import org.dynalang.mop.CallProtocol; import org.dynalang.mop.impl.MetaobjectProtocolBase; public class DummyMetaobjectProtocol1 extends MetaobjectProtocolBase implements ClassBasedMetaobjectProtocol { public boolean isAuthoritativeForClass(Class clazz) { return clazz == DynaObject1.class; } public Object call(Object callable, CallProtocol callProtocol, Map args) { return Result.noAuthority; // not callable with named args } public Object call(Object callable, CallProtocol callProtocol, Object... args) { return isDynaObject1(callable) ? "called1" : Result.noAuthority; } public Result delete(Object target, Object propertyId) { return isAuthoritative(target, propertyId) ? Result.notDeleteable : Result.noAuthority; } public Object get(Object target, Object propertyId) { return isAuthoritative(target, propertyId) ? "value1" : Result.noAuthority; } public Boolean has(Object target, Object propertyId) { return isAuthoritative(target, propertyId) ? Boolean.TRUE : null; } private boolean isAuthoritative(Object target, Object propertyId) { return isDynaObject1(target) && "prop1".equals(propertyId); } public Iterator properties(Object target) { if(isDynaObject1(target)) { Map m = new HashMap(); m.put("prop1", "value1"); return m.entrySet().iterator(); } else { return Collections.EMPTY_MAP.entrySet().iterator(); } } public Result put(Object target, Object propertyId, Object value, CallProtocol callProtocol) { return isAuthoritative(target, propertyId) ? Result.notWritable : Result.noAuthority; } public Object representAs(Object object, Class targetClass) { return isDynaObject1(object) && targetClass == String.class ? "value1" : Result.noAuthority; } private boolean isDynaObject1(Object object) { return object instanceof DynaObject1; } }dynalang-0.4/mop/testsrc/org/dynalang/mop/impl/test/TestAutodiscovery.java0000644000175000017500000000143510716652770027052 0ustar twernertwernerpackage org.dynalang.mop.impl.test; import junit.framework.TestCase; import org.dynalang.mop.BaseMetaobjectProtocol; import org.dynalang.mop.impl.AutoDiscovery; /** * Tests the AutoDiscovery features * @author Attila Szegedi * @version $Id: $ */ public class TestAutodiscovery extends TestCase { public void testAutoDiscovery() throws Exception { Thread.currentThread().setContextClassLoader(getClass().getClassLoader()); BaseMetaobjectProtocol[] mops = AutoDiscovery.discoverBaseMetaobjectProtocols(); assertNotNull(mops); assertEquals(2, mops.length); assertNotNull(mops[0]); assertSame(DummyMetaobjectProtocol1.class, mops[0].getClass()); assertNotNull(mops[1]); assertSame(DummyMetaobjectProtocol2.class, mops[1].getClass()); } } dynalang-0.4/mop/changelog.txt0000644000175000017500000000236411063210136016371 0ustar twernertwerner0.4 (2008.09.14) ================ - Introduced a weak reference mechanism where needed that ensures no MOP code keeps classes from being unloaded. - Renamed BaseMetaobjectProtocol.Results enum to Result - Renamed ClassMetaobjectProtocol to BeanMetaobjectProtocol in org.dynalang.mop.beans - Renamed ArrayClassMetaobjectProtocol to ArrayMetaobjectProtocol in org.dynalang.mop.beans - Public constructors and static methods can now be invoked using BeanMetaobjectProtocol - Distribution now created with a top-level directory in the .tgz file - ClassBasedMetaobjectProtocol contract changed to be more efficient - Refactored to eliminate all code duplication between fixed-arg and var-arg overloaded method handling - Allowed {Array|Bean}MetaobjectProtocol to be used as first-class MOPs, primarily so that various language implementations can bind to them with a shorter lookup path. - Various corner-case semantic fixes: - CompositeClassBasedMOP.representAs() consults target class' MOP when object MOP declares no authority - Make sure marshalling starts from the same source argument after each failed overload resolution attempt in OverloadedVarArgMethod 0.3 (2007.11.30) ================ - Initial public releasedynalang-0.4/mop/build.xml0000644000175000017500000001664311050657744015547 0ustar twernertwerner dynalang-0.4/mop/ivy.xml0000644000175000017500000000116711011557162015240 0ustar twernertwerner dynalang-0.4/mop/src/0000755000175000017500000000000011425436177014504 5ustar twernertwernerdynalang-0.4/mop/src/overview.html0000644000175000017500000001564010751423420017232 0ustar twernertwerner JVM Dynamic Languages Metaobject Protocol

This library aims to make it possible for objects created by a runtime for one dynamic language to be passed to and manipulated by a different dynamic language, running within the same JVM. More generally, it aims to provide a facility where an arbitrary system (usually a language runtime) can intuitively manipulate any arbitrary object model built atop of Java objects (usually the native object model of some other language).

Basically, it provides a unified mechanism that all dynamic languages on the JVM can use to inter-operably manipulate their own objects as well as objects from any other language that also uses this mechanism.

It strives to achieve this goal not by defining "One True Object", a single interface to be implemented by all Java objects that represent objects of the dynamic languages in the JVM, but rather by providing an extensible metaobject protocol (MOP) mechanism, as first formulated in the "In-process cross-language object interaction: adapters or navigators?" article. The idea is to completely throw away the idea of a dedicated interface on objects themselves, and having to wrap foreign objects into adapter objects that expose the expected interface. Instead, the operations on objects themselves are encapsulated behind MOP objects (you can also think about them as being the "navigators" and "manipulators" for the objects they know about), with usually only a single MOP required per language implementation.

The basic usage difference is that a dynamic language runtime will retrieve a property on an object not by using code like this: ((MyDynamicInterface)obj).get("foo"); but rather it will use a MOP: metaobjectProtocol.get(obj, "foo");

The real strength of the approach lies in extensibility and pluggability of MOPs. MOPs can be easily composed, so if you compose your language's native MOP with other languages' MOPs, your code will be able to natively manipulate those other languages' objects. You can have a MOP for DOM objects as well to natively add XML manipulating abilities into your languages. Finally, a JavaBeans MOP is provided as standard component in the library - you can add it as the last element of your composite MOP so that your language can manipulate any POJO directly if no other MOP recognizes the object. Full range of Java amenities, including optimized runtime resolution of overloaded methods and support for JDK 1.5 variable arguments is available.

The secret of composability is MOPs ability to declare it has no authority to perform an operation on an object. When an operation is attempted in a composite MOP, all its element MOPs will be attempted in turn while they claim no authority for it. Only when one MOP either performs the operation or authoritatively decides it must fail is the operation outcome final. Note that the authority declaration is very fine-grained: it is per operation and per object. It is therefore much more versatile than the wrapper interfaces approach: when using interfaces, a wrapper class must decide up-front which interfaces to implement on the object. A MOP can decide based on the actual state of the object whether it can perform an operation. This can also be handily used to extend any objects with language specific meta-properties. Since the API allows any object, not just strings, to be used as property identifiers, it is easy to use implementation-private objects as property IDs for things like ECMAScript "prototype" property and similar. A theoretical ECMAScript MOP would thus answer the get and put requests for the prototype property of a POJO, but would claim no authority for get and put requests for other properties, letting those fall through to the JavaBeans MOP.

Getting started

The {@link org.dynalang.mop.impl.StandardMetaobjectProtocolFactory} is most likely all you need to get started using MOPs. A suitable code snippet for obtaining a MOP capable of handling all known object models in the current thread's class loader is:

import org.dynalang.mop.MetaobjectProtocol;
import org.dynalang.mop.impl.StandardMetaobjectProtocolFactory;
...

MetaobjectProtocol compositeMop = 
    StandardMetaobjectProtocolFactory.createStandardMetaobjectProtocol(true,false);
In case you're developing a library that supplies its own native metaobject protocol for some native object model (most likely, you are developing a language runtime), then you'd create an instance of your native MOP and pass it to be merged with other available MOPs into a single composite MOP as:
import org.dynalang.mop.MetaobjectProtocol;
import org.dynalang.mop.impl.StandardMetaobjectProtocolFactory;
...
MetaobjectProtocol nativeMop = new MyLanguageMop();
MetaobjectProtocol compositeMop = 
    StandardMetaobjectProtocolFactory.createStandardMetaobjectProtocol(nativeMop, true, false);

If you are developing your own MOP, you'll probably want to subclass {@link org.dynalang.mop.impl.MetaobjectProtocolBase}.

Developer resources

The project is hosted at SourceForge, under http://www.sf.net/projects/dynalang.

If you check out the latest version from SVN, try running ant test. This produces both a JUnit test report at build/test/report/index.html and test coverage report at build/coverage/report/index.html. To build this JavaDoc, use ant doc, and then open build/doc/index.html.

dynalang-0.4/mop/src/doc/0000755000175000017500000000000011425436177015251 5ustar twernertwernerdynalang-0.4/mop/src/doc/index.html0000755000175000017500000002227310716362023017245 0ustar twernertwerner dynalang.org

dynalang.org


Main page
  Download
  Developer resources
  JavaDoc
  Licensing
  Who we are
SourceForge project page

dynalang.org is currently the home of the generic metaobject protocol specification for dynamic programming languages on the JVM. If these words don't mean anything to you, don't worry - chances are you are not involved in business of actually building runtime environments for dynamic programming languages. Such runtime environment builders are our sole target audience at the moment, although we hope to eventually expand the focus to a broader range of topics involving dynamic languages - both creation and usage, both on JVM and CLR.

The JVM Dynamic Languages Metaobject Protocol Library

This library aims to make it possible for objects created by a runtime for one dynamic language to be passed to and manipulated by a different dynamic language, running within the same JVM. More generally, it aims to provide a facility where an arbitrary system (usually a language runtime) can intuitively manipulate any arbitrary object model built atop of Java objects (usually the native object model of some other language).

Basically, it provides a unified mechanism that all dynamic languages on the JVM can use to inter-operably manipulate their own objects as well as objects from any other language that also uses this mechanism.

It strives to achieve this goal not by defining "One True Object", a single interface to be implemented by all Java objects that represent objects of the dynamic languages in the JVM, but rather by providing an extensible metaobject protocol (MOP) mechanism, as first formulated in the "In-process cross-language object interaction: adapters or navigators?" article. The idea is to completely throw away the idea of a dedicated interface on objects themselves, and having to wrap foreign objects into adapter objects that expose the expected interface. Instead, the operations on objects themselves are encapsulated behind MOP objects (you can also think about them as being the "navigators" and "manipulators" for the objects they know about), with usually only a single MOP required per language implementation.

The basic usage difference is that a dynamic language runtime will retrieve a property on an object not by using code like this: ((MyDynamicInterface)obj).get("foo"); but rather it will use a MOP: metaobjectProtocol.get(obj, "foo");

The real strength of the approach lies in extensibility and pluggability of MOPs. MOPs can be easily composed, so if you compose your language's native MOP with other languages' MOPs, your code will be able to natively manipulate those other languages' objects. You can have a MOP for DOM objects as well to natively add XML manipulating abilities into your languages. Finally, a JavaBeans MOP is provided as standard component in the library - you can add it as the last element of your composite MOP so that your language can manipulate any POJO directly if no other MOP recognizes the object. Full range of Java amenities, including optimized runtime resolution of overloaded methods and support for JDK 1.5 variable arguments is available.

The secret of composability is MOPs ability to declare it has no authority to perform an operation on an object. When an operation is attempted in a composite MOP, all its element MOPs will be attempted in turn while they claim no authority for it. Only when one MOP either performs the operation or authoritatively decides it must fail is the operation outcome final. Note that the authority declaration is very fine-grained: it is per operation and per object. It is therefore much more versatile than the wrapper interfaces approach: when using interfaces, a wrapper class must decide up-front which interfaces to implement on the object. A MOP can decide based on the actual state of the object whether it can perform an operation. This can also be handily used to extend any objects with language specific meta-properties. Since the API allows any object, not just strings, to be used as property identifiers, it is easy to use implementation-private objects as property IDs for things like ECMAScript "prototype" property and similar. A theoretical ECMAScript MOP would thus answer the get and put requests for the prototype property of a POJO, but would claim no authority for get and put requests for other properties, letting those fall through to the JavaBeans MOP.

Download

You can download builds from the project's SourceForge download page

Developer resources

The project is hosted at SourceForge, under http://www.sf.net/projects/dynalang.

If you check out the latest version from SVN, try running ant test. This produces both a JUnit test report at build/test/report/index.html and test coverage report at build/coverage/report/index.html. ant doc will generate the browsable documentation in build/doc.

The JavaDoc overview page also contains few pointers for getting started using and extending the library.

This software can be discussed in the JVM Languages Google group

Volunteers welcome for all aspects of the project.

Licensing

org.dynalang.mop is Open Source Software, distributed under the terms of Apache License, version 2.0.

Who we are

This project was founded by Attila Szegedi.

Open Source definition
SourceForge Logo
dynalang-0.4/mop/src/org/0000755000175000017500000000000011425436177015273 5ustar twernertwernerdynalang-0.4/mop/src/org/dynalang/0000755000175000017500000000000011425436177017070 5ustar twernertwernerdynalang-0.4/mop/src/org/dynalang/mop/0000755000175000017500000000000011425436177017663 5ustar twernertwernerdynalang-0.4/mop/src/org/dynalang/mop/package.html0000644000175000017500000000016710651504546022144 0ustar twernertwerner

This package defines the metaobject protocol interfaces.

dynalang-0.4/mop/src/org/dynalang/mop/CallProtocol.java0000644000175000017500000001306610724016017023115 0ustar twernertwerner/* Copyright 2007 Attila Szegedi Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ package org.dynalang.mop; import java.util.Map; /** * An interface for objects that are capable of creating alternative * representations for objects, for purposes of converting between types where * necessary (usually used for arguments of method invocation and property * setters). It is also capable of invoking callable objects, and retrieving * a property from an object. Note that {@link BaseMetaobjectProtocol} extends * this interface. * @author Attila Szegedi * @version $Id: $ */ public interface CallProtocol { /** * Returns a representation of the specified target object as an object of * the specified target class. Typical supported target classes would be * wrappers for Java primitive types that map to native types of the higher * level languages. I.e. if an object is used as a boolean expression, then * the language would ask the protocol to interpret it as boolean by * calling representAs(Boolean.TYPE). * @param object the object to represent * @param targetClass the target class for representation. * @return the representation that must be instance of the targetClass, or * in case targetClass is primitive, of its adequate boxing class. It can * also be a special value to indicate conversion failure: * {@link BaseMetaobjectProtocol.Result#noAuthority} is returned if the * marshaller can not authoritatively decide on a representation; * {@link BaseMetaobjectProtocol.Result#noRepresentation} is returned if * the marshaller can authoritatively decide that the requested * representation is not possible. representation of null should be null, * except when the target class is a primitive type in which case * {@link BaseMetaobjectProtocol.Result#noRepresentation} should be * returned. */ public Object representAs(Object object, Class targetClass); /** * Retrieves the property value from the target object. * @param target the target object * @param propertyId the ID of the property. Usually a String or an * Integer, but other property ID types can also be supported. * @return the property value for the target object. A null value means * that the protocol authoritatively decided that the value of the property * is null. If the protocol decides that the property does not exist, it * will return {@link BaseMetaobjectProtocol.Result#doesNotExist}. If the protocol decides that * the property exists, but is not readable, it will return * {@link BaseMetaobjectProtocol.Result#notReadable}. If the protocol can not make * an authoritative decision, it will return {@link BaseMetaobjectProtocol.Result#noAuthority}. */ public Object get(Object target, Object propertyId); /** * Calls a callable object with named arguments. * @param callProtocol a marshaller that should be used by this * metaobject protocol to convert the arguments to conform to expected * argument types for the call. * @param args the named arguments for the callable object. null must * be treated as empty map. Usually, the map keys are strings, but it is * possible that some protocols support non-string keys. * @param callable the callable object * @return the return value of the call, or a special result. * {@link BaseMetaobjectProtocol.Result#notCallable} is returned if the protocol can * authoritatively decide that the target is not a callable, or is not * callable with named arguments. {@link BaseMetaobjectProtocol.Result#doesNotExist} is returned * if the callable does not exist at all. {@link BaseMetaobjectProtocol.Result#noAuthority} is * returned if the protocol can not authoritatively decide whether the * target is callable. */ public Object call(Object callable, CallProtocol callProtocol, Map args); /** * Calls a callable object with positional arguments. * @param callable the callable object * @param callProtocol a marshaller that should be used by this * metaobject protocol to convert the arguments to conform to expected * argument types for the call. * @param args the positional arguments for the callable object. null must * be treated as empty array. * @return the return value of the call, or a special result. * {@link BaseMetaobjectProtocol.Result#notCallable} is returned if the protocol can * authoritatively decide that the target is not a callable, or is not * callable with positional arguments. {@link BaseMetaobjectProtocol.Result#doesNotExist} is * returned if the callable does not exist at all. * {@link BaseMetaobjectProtocol.Result#noAuthority} is returned if the protocol can not * authoritatively decide whether the target is callable. */ public Object call(Object callable, CallProtocol callProtocol, Object... args); } dynalang-0.4/mop/src/org/dynalang/mop/BaseMetaobjectProtocol.java0000644000175000017500000001630110724016017025105 0ustar twernertwerner/* Copyright 2007 Attila Szegedi Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ package org.dynalang.mop; import java.lang.reflect.UndeclaredThrowableException; import java.util.Iterator; import java.util.Map; /** * The base metaobject protocol interface that provides essential functionality * for implementing a metaobject protocol. Some notes on the design: *
    *
  • No methods throw checked exceptions. If a method's implementation * relies on calling Java methods that throw checked exceptions (most likely * the various call methods), then they must wrap them into a * {@link UndeclaredThrowableException} first.
  • *
  • Various expected failures are not indicated by exceptions, but rather * indicated with special return values, either by returning null from * methods that otherwise return a Boolean, or more frequently, by returning * a special value from the {@link Result} enum where methods return * {@link Object}. The rationale for this is that the protocols are designed * with chaining in mind, namely more than one protocol can be invoked for * an operation on an object, and certain protocols can declare that they * can't handle that particular object (in our self-chosen terminology, * they don't have authority over it) so the next protocol gets tried. * Using exceptions for such expected flow control seemed like a bad * practice. Also, a language implementation using multiple protocols can * choose to signal an error on its own if all protocols are exhausted * without success for a particular operation, and it is at liberty to use * whatever is its natural error signaling method, which is not necessarily * equivalent or best implemented using Java structured exception handling. *
  • *
* * @author Attila Szegedi * @version $Id: $ */ public interface BaseMetaobjectProtocol extends CallProtocol { /** * Defines special operation results that are used as return values from * many metaobject protocol methods to indicate success or failure. * @author Attila Szegedi * @version $Id: $ */ public static enum Result { /** * The requested property does not exist. */ doesNotExist, /** * The metaobject protocol can't authoritatively perform the requested * operation on the object (the object is foreign to it). */ noAuthority, /** * The target object that was attempted to be called does not support * calling (is not a callable) in the context of the attempted call * operation (either with positional or named arguments). */ notCallable, /** * The property attempted to be deleted can not be deleted. */ notDeleteable, /** * The property attempted to be read exists, but is not readable. */ notReadable, /** * A suitable type representation for a value could not be obtained. */ noRepresentation, /** * The property attempted to be written exists, but is not writable. */ notWritable, /** * The operation succeeded. */ ok, }; /* -- Property access --*/ /** * Deletes an association of a value with a property in the target object. * @param target the target object * @param propertyId the ID of the property. Usually a String or an * Integer, but other property ID types can also be supported. * @return the status of the operation. If the protocol decides that the * property did not previously exist, it will return * {@link BaseMetaobjectProtocol.Result#doesNotExist}. If the protocol authoritatively decides * that the property can not be deleted, it will return * {@link BaseMetaobjectProtocol.Result#notDeleteable}. If the protocol doesn't have the * authority to delete the property, it will leave the object unchanged, * and return {@link BaseMetaobjectProtocol.Result#noAuthority}. If the operation succeeds, * {@link BaseMetaobjectProtocol.Result#ok} is returned. */ public Result delete(Object target, Object propertyId); /** * Tells whether the target object has a particular property. * @param target the target object * @param propertyId the ID of the property. Usually a String or an * Integer, but other property ID types can also be supported. * @return {@link Boolean#TRUE} or {@link Boolean#FALSE} if the protocol * can authoritatively decide whether the target has or has not the * property, or null if it does not have the authority to decide. */ public Boolean has(Object target, Object propertyId); /** * Returns an iterator over the property ID-value pairs in the target * object this MOP knows about (and chooses to expose - not all properties * must be exposed; hidden properties are allowed). * @param target the target object * @return an iterator over all the property ID-value pairs. */ public Iterator properties(Object target); /* -- Iteration --*/ /** * Associates a value with a property in the target object. * @param target the target object * @param propertyId the ID of the property. Usually a String or an * Integer, but other property ID types can also be supported. * @param value the new value for the property * @param callProtocol a marshaller that is used to convert the value in * case the property can only accept values of certain types, and the * metaobject protocol allows automatic coercing to those types. * @return a value indicating the outcome of the operation. If the protocol * decides that the property does not exist, and can not be created, it * will return {@link BaseMetaobjectProtocol.Result#doesNotExist}. If the protocol * authoritatively decides that the property is read-only, it will return * {@link BaseMetaobjectProtocol.Result#notWritable}. If the property has a limitation on types * it can take as values, and the supplied marshaller is not able to * provide a suitable representation, then the value of the property is not * changed, and {@link BaseMetaobjectProtocol.Result#noRepresentation} is returned. Finally, if * the protocol doesn't have the authority to put the new property value, * it will leave the property value unchanged, and return * {@link BaseMetaobjectProtocol.Result#noAuthority}. If the operation succeeds, * {@link BaseMetaobjectProtocol.Result#ok} is returned. */ public Result put(Object target, Object propertyId, Object value, CallProtocol callProtocol); }dynalang-0.4/mop/src/org/dynalang/mop/MetaobjectProtocol.java0000644000175000017500000001516210724016017024316 0ustar twernertwerner/* Copyright 2007 Attila Szegedi Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ package org.dynalang.mop; import java.util.Iterator; import java.util.Map; import org.dynalang.mop.impl.MetaobjectProtocolAdaptor; import org.dynalang.mop.impl.MetaobjectProtocolBase; /** * An extension of {@link BaseMetaobjectProtocol} that can provide various * convenience functionality that can implemented in terms of base * functionality, but the specialized implementations can be optimized. To * easily adapt an existing {@link BaseMetaobjectProtocol} into a full-fledged * {@link MetaobjectProtocol}, you can use {@link MetaobjectProtocolAdaptor}. * Alternatively, you can easily get a full-fledged {@link MetaobjectProtocol} * if you subclass {@link MetaobjectProtocolBase} and only implement * {@link BaseMetaobjectProtocol} methods on it. * @author Attila Szegedi * @version $Id: $ */ public interface MetaobjectProtocol extends BaseMetaobjectProtocol { /** * Calls a method on the target object with supplied named arguments. * Must behave identically to: *
     * Object callable = get(target, callableId);
     * if(callable instanceof Result) {
     *     return callable;
     * }
     * return call(callable, args);
     * 
* @param target the target object * @param callableId the ID of the method to call * @param callProtocol a marshaller that should be used by this * metaobject protocol to convert the arguments to conform to expected * argument types for the call. * @param args the arguments of the call * @return the result of the invocation, or a special result. Can return * any return value that {@link BaseMetaobjectProtocol#get(Object, Object)} * would return while looking up the callable. Can also return any return * value that {@link BaseMetaobjectProtocol#call(Object, CallProtocol, Map)} * would return while calling. */ public Object call(Object target, Object callableId, CallProtocol callProtocol, Map args); /** * Calls a method on the target object with supplied positional arguments. * Must behave identically to: *
     * Object callable = get(target, callableId);
     * if(callable instanceof Result) {
     *     return callable;
     * }
     * return call(callable, args);
     * 
* @param target the target object * @param callableId the ID of the method to call * @param callProtocol a marshaller that should be used by this * metaobject protocol to convert the arguments to conform to expected * argument types for the call. * @param args the arguments of the call * @return the result of the invocation, or a special result. Can return * any return value that {@link BaseMetaobjectProtocol#get(Object, Object)} * would return while looking up the callable. Can also return any return * value that {@link BaseMetaobjectProtocol#call(Object, CallProtocol, Object[])} * would return while calling. */ public Object call(Object target, Object callableId, CallProtocol callProtocol, Object... args); /** * Behaves as {@link BaseMetaobjectProtocol#delete(Object, Object)} with an * integer property ID. * @param target the target object * @param propertyId the ID of the property. * @return see {@link BaseMetaobjectProtocol#delete(Object, Object)}. */ public Result delete(Object target, long propertyId); /** * Behaves as {@link BaseMetaobjectProtocol#get(Object, Object)} with an * integer property ID. * @param target the target object * @param propertyId the ID of the property. * @return see {@link BaseMetaobjectProtocol#get(Object, Object)}. */ public Object get(Object target, long propertyId); /* -- Iteration --*/ /** * Behaves as {@link BaseMetaobjectProtocol#has(Object, Object)} with an * integer property ID. * @param target the target object * @param propertyId the ID of the property. * @return see {@link BaseMetaobjectProtocol#has(Object, Object)}. */ public Boolean has(Object target, long propertyId); /* -- Direct call --*/ /** * Returns an iterator over the property IDs in the target object this MOP * knows about (and chooses to expose - not all properties must be exposed; * hidden properties are allowed). * @param target the target object * @return an iterator over the property IDs. */ public Iterator propertyIds(Object target); /** * Behaves as {@link BaseMetaobjectProtocol#put(Object, Object, Object,CallProtocol)} * with an integer property ID. * Associates a value with a property in the target object. * @param target the target object * @param propertyId the ID of the property. Usually a String or an * Integer, but other property ID types can also be supported. * @param value the new value for the property * @param callProtocol a marshaller that is used to convert the value in * case the property can only accept values of certain types, and the * metaobject protocol allows automatic coercing to those types. * @return the previous value of the property, or a special value. A null * value means that the protocol authoritatively decided that the previous * value of the property is null. If the protocol decides that the property * does not exist, and can not be created, it will return * {@link BaseMetaobjectProtocol.Result#doesNotExist}. If the protocol can not set the new value, * it will return {@link BaseMetaobjectProtocol.Result#notWritable}. If the protocol * doesn't have the authority to put the new property value, it will leave * the object unchanged, and return {@link BaseMetaobjectProtocol.Result#noAuthority}. If the * operation succeeds, {@link BaseMetaobjectProtocol.Result#ok} is returned. */ public Result put(Object target, long propertyId, Object value, CallProtocol callProtocol); }dynalang-0.4/mop/src/org/dynalang/mop/beans/0000755000175000017500000000000011425436177020753 5ustar twernertwernerdynalang-0.4/mop/src/org/dynalang/mop/beans/BeanMetaobjectProtocol.java0000644000175000017500000004446511063206304026201 0ustar twernertwerner/* Copyright 2007 Attila Szegedi Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ package org.dynalang.mop.beans; import java.beans.BeanInfo; import java.beans.IntrospectionException; import java.beans.Introspector; import java.beans.MethodDescriptor; import java.beans.PropertyDescriptor; import java.lang.reflect.Constructor; import java.lang.reflect.Member; import java.lang.reflect.Method; import java.lang.reflect.Modifier; import java.lang.reflect.UndeclaredThrowableException; import java.util.ArrayList; import java.util.Arrays; import java.util.Collection; import java.util.Collections; import java.util.HashMap; import java.util.HashSet; import java.util.Iterator; import java.util.Map; import java.util.Map.Entry; import org.dynalang.classtoken.ClassToken; import org.dynalang.mop.BaseMetaobjectProtocol; import org.dynalang.mop.CallProtocol; import org.dynalang.mop.MetaobjectProtocol; /** * Exposes a metaobject protocol for a single Java class, treating it as a * JavaBean. You can use it for shorter access path when you can bind it to the * object ahead of time. In other circumstances, you would just use * {@link BeansMetaobjectProtocol} as a central MOP to handle the class MOPs. * In addition to being a generic MOP, it also exposes access to class' static * methods and constructors using {@link #newInstance(CallProtocol, Object...)} * and {@link #callStatic(String, CallProtocol, Object...)} methods. * @param the class of objects this MOP can handle * @author Attila Szegedi * @version $Id: $ */ public class BeanMetaobjectProtocol implements MetaobjectProtocol { private final Map properties = new HashMap(); private final Map> methods = new HashMap>(); private final Map> staticMethods; private final DynamicMethod> constructor; private final Collection names; /** * Constructs a new metaobject protocol for objects of a certain class. * @param clazz the class to construct a metaobject protocol for * @param methodsEnumerable if true, methods are enumerable through the * {@link #properties(Object)} and {@link #propertyIds(Object)}. * @throws IntrospectionException * @throws IllegalArgumentException if the passed class is a primitive class */ public BeanMetaobjectProtocol(Class clazz, boolean methodsEnumerable) throws IntrospectionException { if(clazz.isPrimitive()) { throw new IllegalArgumentException("Class " + clazz.getName() + " is primitive"); } BeanInfo beanInfo = Introspector.getBeanInfo(clazz); Map accessibleMethods = discoverAccessibleMethods(clazz); PropertyDescriptor[] propDescs = beanInfo.getPropertyDescriptors(); for (int i = 0; i < propDescs.length; i++) { PropertyDescriptor descriptor = propDescs[i]; Method readMethod = descriptor.getReadMethod(); if(readMethod != null) { descriptor.setReadMethod(getAccessibleMethod(readMethod, accessibleMethods)); } Method writeMethod = descriptor.getWriteMethod(); if(writeMethod != null) { descriptor.setWriteMethod(getAccessibleMethod(writeMethod, accessibleMethods)); } if(descriptor.getReadMethod() != null || descriptor.getWriteMethod() != null) { properties.put(descriptor.getName(), descriptor); } } // Add instance methods Map> statics = new HashMap>(); MethodDescriptor[] methodDescs = beanInfo.getMethodDescriptors(); for (int i = 0; i < methodDescs.length; i++) { MethodDescriptor descriptor = methodDescs[i]; Method method = getAccessibleMethod(descriptor.getMethod(), accessibleMethods); if(method == null) { continue; } String name = descriptor.getName(); if(Modifier.isStatic(method.getModifiers())) { addMember(method, name, clazz, statics); } else { addMember(method, name, clazz, methods); } } staticMethods = Collections.unmodifiableMap(statics); // Add constructors DynamicMethod> dynaCtor = null; Constructor[] ctrs = clazz.getConstructors(); for (int i = 0; i < ctrs.length; i++) { Constructor ctr = ctrs[i]; dynaCtor = addMember(ctr, "", clazz, dynaCtor); } constructor = dynaCtor; if(methodsEnumerable) { Collection cnames = new HashSet(properties.size() + methods.size() * 4 / 3, 0.75f); cnames.addAll(properties.keySet()); cnames.addAll(methods.keySet()); // Sorting is not really necessary, but it's nice to make it // deterministic and it doesn't cost that much ArrayList lnames = new ArrayList(cnames); Collections.sort(lnames); lnames.trimToSize(); names = Collections.unmodifiableCollection(lnames); } else { names = Collections.emptySet(); } } private static void addMember(M method, String name, Class declaringClass, Map> map) { DynamicMethod existingMethod = map.get(name); DynamicMethod newMethod = addMember(method, name, declaringClass, existingMethod); if(newMethod != existingMethod) { map.put(name, newMethod); } } private static DynamicMethod addMember(M method, String name, Class declaringClass, DynamicMethod existing) { if(existing == null) { return new SimpleDynamicMethod(method); } else if(existing instanceof SimpleDynamicMethod) { OverloadedDynamicMethod odm = new OverloadedDynamicMethod(name, declaringClass); odm.addMember(((SimpleDynamicMethod)existing).getMember()); odm.addMember(method); return odm; } else if(existing instanceof OverloadedDynamicMethod) { ((OverloadedDynamicMethod)existing).addMember(method); return existing; } throw new AssertionError(); } void onClassTokensInvalidated(ClassToken[] tokens) { onClassTokensInvalidated(tokens, methods); onClassTokensInvalidated(tokens, staticMethods); if(constructor instanceof OverloadedDynamicMethod) { ((OverloadedDynamicMethod>)constructor).onClassTokensInvalidated(tokens); } } private static void onClassTokensInvalidated(ClassToken[] tokens, Map> methods) { for (DynamicMethod method : methods.values()) { if(method instanceof OverloadedDynamicMethod) { ((OverloadedDynamicMethod)method).onClassTokensInvalidated(tokens); } } } public Object call(Object callable, CallProtocol callProtocol, Map args) { // Java methods aren't callable with named arguments return Result.noAuthority; } public Object call(Object target, Object callableId, CallProtocol callProtocol, Map args) { return BeansMetaobjectProtocol.callWithMap(target, callableId, callProtocol); } public Object call(Object callable, CallProtocol callProtocol, Object... args) { return BeansMetaobjectProtocol.callMethod(callable, callProtocol, args); } /** * Invokes a public static method of the class with the specified name, and * appropriate for the passed arguments. Performs overload resolution and * vararg packing if needed. * @param name the name of the method to invoke * @param callProtocol the call protocol for converting arguments * @param args the arguments to the method * @return the result of the method invocation. If the method with the * given name does not exist, returns {@link BaseMetaobjectProtocol.Result#doesNotExist}. */ public Object callStatic(String name, CallProtocol callProtocol, Object... args) { DynamicMethod method = staticMethods.get(name); if(method == null) { return Result.doesNotExist; } return method.call(null, callProtocol, args); } /** * Creates a new instance of the class, invoking a public constructor * appropriate for the passed arguments. Performs overload resolution and * vararg packing if needed. * @param callProtocol the call protocol for converting arguments * @param args the arguments to the constructor * @return a newly constructed object instance. If the class has no public * constructors, returns null. */ public T newInstance(CallProtocol callProtocol, Object... args) { if(constructor == null) { return null; } return (T)constructor.call(null, callProtocol, args); } public Object call(Object target, Object callableId, CallProtocol callProtocol, Object... args) { String name = String.valueOf(callableId); DynamicMethod dynaMethod = methods.get(name); if(dynaMethod == null) { return Result.noAuthority; } return dynaMethod.call(target, callProtocol, args); } public Object get(Object target, long propertyId) { return Result.noAuthority; } public Object get(Object target, Object propertyId) { String name = String.valueOf(propertyId); PropertyDescriptor desc = properties.get(name); if(desc == null) { DynamicMethod dynaMethod = methods.get(name); if(dynaMethod == null) { // No property and no method - doesn't exist return Result.noAuthority; } // Return instance-bound method return new DynamicInstanceMethod(target, dynaMethod); } Method method = desc.getReadMethod(); if(method == null) { // Write-only property return Result.notReadable; } try { return method.invoke(target, (Object[])null); } catch(RuntimeException e) { throw e; } catch(Exception e) { throw new UndeclaredThrowableException(e); } } public Boolean has(Object target, long propertyId) { return null; } public Boolean has(Object target, Object propertyId) { String name = String.valueOf(propertyId); if(properties.containsKey(name) || methods.containsKey(name)) { return Boolean.TRUE; } return null; } public Result delete(Object target, long propertyId) { return has(target, propertyId) == Boolean.TRUE ? Result.notDeleteable : Result.noAuthority; } public Result delete(Object target, Object propertyId) { return has(target, propertyId) == Boolean.TRUE ? Result.notDeleteable : Result.noAuthority; } public Iterator properties(final Object target) { final Iterator it = propertyIds(target); return new Iterator() { public boolean hasNext() { return it.hasNext(); } public Entry next() { final Object key = it.next(); return new Map.Entry() { private boolean hasValue; private Object value; public Object getKey() { return key; } public Object getValue() { if(!hasValue) { value = get(target, key); hasValue = true; } return value; } public Object setValue(Object value) { Object previousValue = get(target, key); if(put(target, key, value, BeanMetaobjectProtocol.this) != Result.ok) { throw new UnsupportedOperationException(); } return previousValue; } @Override public int hashCode() { Object value = getValue(); return (key == null ? 0 : key.hashCode()) ^ (value == null ? 0 : value.hashCode()); } @Override public boolean equals(Object obj) { if(!(obj instanceof Map.Entry)) { return false; } Map.Entry e = (Map.Entry)obj; Object value = getValue(); return (key == null ? e.getKey() == null : key.equals(e.getKey())) && (value == null ? e.getValue() == null : value.equals(e.getValue())); } }; } public void remove() { throw new UnsupportedOperationException(); } }; } public Iterator propertyIds(Object target) { return names.iterator(); } public Result put(Object target, long propertyId, Object value, CallProtocol callProtocol) { return Result.noAuthority; } public Result put(Object target, Object propertyId, Object value, CallProtocol callProtocol) { PropertyDescriptor desc = properties.get(String.valueOf(propertyId)); if(desc == null) { return Result.noAuthority; } Method writeMethod = desc.getWriteMethod(); if(writeMethod == null) { return Result.notWritable; } try { Class propType = desc.getPropertyType(); if(propType == null) { return Result.notWritable; } value = callProtocol.representAs(value, propType); if(value == Result.noAuthority || value == Result.noRepresentation) { return Result.noRepresentation; } writeMethod.invoke(target, new Object[] { value }); return Result.ok; } catch(RuntimeException e) { throw e; } catch(Exception e) { throw new UndeclaredThrowableException(e); } } public Object representAs(Object object, Class targetClass) { return BeansMetaobjectProtocol.representAsInternal(object, targetClass); } private static Map discoverAccessibleMethods(Class clazz) { Map map = new HashMap(); discoverAccessibleMethods(clazz, map); return map; } private static void discoverAccessibleMethods(Class clazz, Map map) { if(Modifier.isPublic(clazz.getModifiers())) { try { Method[] methods = clazz.getMethods(); for(int i = 0; i < methods.length; i++) { Method method = methods[i]; MethodSignature sig = new MethodSignature(method); map.put(sig, method); } return; } catch(SecurityException e) { System.err.println( "Could not discover accessible methods of class " + clazz.getName() + ", attemping superclasses/interfaces."); e.printStackTrace(); // Fall through and attempt to discover superclass/interface // methods } } Class[] interfaces = clazz.getInterfaces(); for(int i = 0; i < interfaces.length; i++) { discoverAccessibleMethods(interfaces[i], map); } Class superclass = clazz.getSuperclass(); if(superclass != null) { discoverAccessibleMethods(superclass, map); } } private static Method getAccessibleMethod(Method m, Map accessibles) { return m == null ? null : accessibles.get(new MethodSignature(m)); } private static final class MethodSignature { private final String name; private final Class[] args; private MethodSignature(String name, Class[] args) { this.name = name; this.args = args; } MethodSignature(Method method) { this(method.getName(), method.getParameterTypes()); } public boolean equals(Object o) { if(o instanceof MethodSignature) { MethodSignature ms = (MethodSignature)o; return ms.name.equals(name) && Arrays.equals(args, ms.args); } return false; } public int hashCode() { return name.hashCode() ^ Arrays.hashCode(args); } } }dynalang-0.4/mop/src/org/dynalang/mop/beans/package.html0000644000175000017500000000116110716322716023226 0ustar twernertwerner

This package defines a metaobject protocol implementation that follows the JavaBeans specification. An instance of this MOP can be typically used among the last, fallback MOPs in a composite MOP (together with {@link org.dynalang.mop.collections.ListMetaobjectProtocol list} and {@link org.dynalang.mop.collections.MapMetaobjectProtocol map} MOPs as well as a {@link org.dynalang.mop.impl.BottomMetaobjectProtocol bottom} MOP) to provide commonsensical POJO manipulation abilities to dynamic language runtimes.

dynalang-0.4/mop/src/org/dynalang/mop/beans/DynamicMethod.java0000644000175000017500000000645511063206304024336 0ustar twernertwerner/* Copyright 2007 Attila Szegedi Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ package org.dynalang.mop.beans; import java.lang.reflect.Constructor; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Member; import java.lang.reflect.Method; import org.dynalang.mop.CallProtocol; /** * Represents a single dynamic method. A "dynamic" method is considered to be * the union of all methods of the same name on a class. In the simplest case, * it corresponds to a single method, but can actually represent any number of * methods if the method name is overloaded. Invoking a dynamic method whose * name is overloaded will perform overload resolution. * @param the type of class members this dynamic method represents. It is * either {@link Method} or {@link Constructor}. * @author Attila Szegedi * @version $Id: $ */ public abstract class DynamicMethod { static final Object[] NULL_ARGS = new Object[0]; /** * Invokes the dynamic method. * @param target the target object -- the "this" of the invoked method, or * null for static methods. * @param callProtocol the call protocol object used to convert arguments * if needed * @param args the arguments to the method. Note that you never need to * pack varargs into an array, nor need to be aware of the vararg concept * at all when using this API. If the called Java method ends up being a * vararg method, its varargs will be packed into an appropriate array * automatically. * @return the result of the method invocation. */ public abstract Object call(Object target, CallProtocol callProtocol, Object... args); static Class[] getParameterTypes(Member member) { if(member instanceof Method) { return ((Method)member).getParameterTypes(); } if(member instanceof Constructor) { return ((Constructor)member).getParameterTypes(); } throw new AssertionError(); } static boolean isVarArgs(Member member) { if(member instanceof Method) { return ((Method)member).isVarArgs(); } else if(member instanceof Constructor) { return ((Constructor)member).isVarArgs(); } throw new AssertionError(); } static Object invoke(Member member, Object target, Object... args) throws InstantiationException, IllegalAccessException, InvocationTargetException { if(member instanceof Method) { return ((Method)member).invoke(target, args); } else if(member instanceof Constructor) { return ((Constructor)member).newInstance(args); } throw new AssertionError(); } } dynalang-0.4/mop/src/org/dynalang/mop/beans/OverloadedMethodUtilities.java0000644000175000017500000001304111063206304026717 0ustar twernertwerner/* Copyright 2007 Attila Szegedi Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ package org.dynalang.mop.beans; import java.util.ArrayList; import java.util.HashSet; import java.util.Iterator; import java.util.List; import java.util.Set; class OverloadedMethodUtilities { static final Class OBJECT_CLASS = Object.class; static Class getMostSpecificCommonType(Class c1, Class c2) { if(c1 == c2) { return c1; } if(c2.isPrimitive()) { if(c2 == Byte.TYPE) c2 = Byte.class; else if(c2 == Short.TYPE) c2 = Short.class; else if(c2 == Character.TYPE) c2 = Character.class; else if(c2 == Integer.TYPE) c2 = Integer.class; else if(c2 == Float.TYPE) c2 = Float.class; else if(c2 == Long.TYPE) c2 = Long.class; else if(c2 == Double.TYPE) c2 = Double.class; } Set> a1 = getAssignables(c1, c2); Set> a2 = getAssignables(c2, c1); a1.retainAll(a2); if(a1.isEmpty()) { // Can happen when at least one of the arguments is an interface, as // they don't have Object at the root of their hierarchy return Object.class; } // Gather maximally specific elements. Yes, there can be more than one // thank to interfaces. I.e., if you call this method for String.class // and Number.class, you'll have Comparable, Serializable, and Object as // maximal elements. List> max = new ArrayList>(); outer: for (Class clazz : a1) { for (Iterator> maxiter = max.iterator(); maxiter.hasNext();) { Class maxClazz = maxiter.next(); if(isMoreSpecific(maxClazz, clazz)) { // It can't be maximal, if there's already a more specific // maximal than it. continue outer; } if(isMoreSpecific(clazz, maxClazz)) { // If it's more specific than a currently maximal element, // that currently maximal is no longer a maximal. maxiter.remove(); } } // If we get here, no current maximal is more specific than the // current class, so it is considered maximal as well max.add(clazz); } if(max.size() > 1) { return OBJECT_CLASS; } return max.get(0); } /** * Determines whether a type represented by a class object is * convertible to another type represented by a class object using a * method invocation conversion, without matching object and primitive * types. This method is used to determine the more specific type when * comparing signatures of methods. * @return true if either formal type is assignable from actual type, * or formal and actual are both primitive types and actual can be * subject to widening conversion to formal. */ static boolean isMoreSpecific(Class specific, Class generic) { // Check for identity or widening reference conversion if(generic.isAssignableFrom(specific)) { return true; } // Check for widening primitive conversion. if(generic.isPrimitive()) { if(generic == Short.TYPE && (specific == Byte.TYPE)) { return true; } if(generic == Integer.TYPE && (specific == Short.TYPE || specific == Byte.TYPE)) { return true; } if(generic == Long.TYPE && (specific == Integer.TYPE || specific == Short.TYPE || specific == Byte.TYPE)) { return true; } if(generic == Float.TYPE && (specific == Long.TYPE || specific == Integer.TYPE || specific == Short.TYPE || specific == Byte.TYPE)) { return true; } if(generic == Double.TYPE && (specific == Float.TYPE || specific == Long.TYPE || specific == Integer.TYPE || specific == Short.TYPE || specific == Byte.TYPE)) { return true; } } return false; } private static Set> getAssignables(Class c1, Class c2) { Set> s = new HashSet>(); collectAssignables(c1, c2, s); return s; } private static void collectAssignables(Class c1, Class c2, Set> s) { if(c1.isAssignableFrom(c2)) { s.add(c1); } Class sc = c1.getSuperclass(); if(sc != null) { collectAssignables(sc, c2, s); } Class[] itf = c1.getInterfaces(); for(int i = 0; i < itf.length; ++i) { collectAssignables(itf[i], c2, s); } } } dynalang-0.4/mop/src/org/dynalang/mop/beans/ClassString.java0000644000175000017500000002006711063206304024040 0ustar twernertwerner/* Copyright 2007 Attila Szegedi Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ package org.dynalang.mop.beans; import java.lang.reflect.Member; import java.util.Iterator; import java.util.LinkedList; import java.util.List; /** * * @author Attila Szegedi * @version $Id: $ * @param */ final class ClassString { private final Class[] classes; ClassString(Class[] classes) { this.classes = classes; } Class[] getClasses() { return classes; } private static final int MORE_SPECIFIC = 0; private static final int LESS_SPECIFIC = 1; private static final int INDETERMINATE = 2; Object getMostSpecific(List methods, boolean varArg) { LinkedList applicables = getApplicables(methods, varArg); if(applicables.isEmpty()) { return OverloadedDynamicMethod.NO_SUCH_METHOD; } if(applicables.size() == 1) { return applicables.getFirst(); } LinkedList maximals = new LinkedList(); for (T applicable : applicables) { Class[] appArgs = DynamicMethod.getParameterTypes(applicable); boolean lessSpecific = false; for (Iterator maximal = maximals.iterator(); maximal.hasNext();) { Member max = maximal.next(); Class[] maxArgs = DynamicMethod.getParameterTypes(max); switch(moreSpecific(appArgs, maxArgs, varArg)) { case MORE_SPECIFIC: { maximal.remove(); break; } case LESS_SPECIFIC: { lessSpecific = true; break; } } } if(!lessSpecific) { maximals.addLast(applicable); } } if(maximals.size() > 1) { return OverloadedDynamicMethod.AMBIGUOUS_METHOD; } return maximals.getFirst(); } private static int moreSpecific(Class[] c1, Class[] c2, boolean varArg) { boolean c1MoreSpecific = false; boolean c2MoreSpecific = false; final int cl1 = c1.length; final int cl2 = c2.length; assert varArg || cl1 == cl2; for(int i = 0; i < cl1; ++i) { Class class1 = getClass(c1, cl1, i, varArg); Class class2 = getClass(c2, cl2, i, varArg); if(class1 != class2) { c1MoreSpecific = c1MoreSpecific || OverloadedMethodUtilities.isMoreSpecific(class1, class2); c2MoreSpecific = c2MoreSpecific || OverloadedMethodUtilities.isMoreSpecific(class2, class1); } } if(c1MoreSpecific) { if(c2MoreSpecific) { return INDETERMINATE; } return MORE_SPECIFIC; } if(c2MoreSpecific) { return LESS_SPECIFIC; } return INDETERMINATE; } private static Class getClass(Class[] classes, int l, int i, boolean varArg) { return varArg && i >= l - 1 ? classes[l - 1].getComponentType() : classes[i]; } /** * Returns all methods that are applicable to actual * parameter classes represented by this ClassString object. */ LinkedList getApplicables(List methods, boolean varArg) { LinkedList list = new LinkedList(); for (T member : methods) { if(isApplicable(member, varArg)) { list.add(member); } } return list; } /** * Returns true if the supplied method is applicable to actual * parameter classes represented by this ClassString object. * */ private boolean isApplicable(T member, boolean varArg) { final Class[] formalTypes = DynamicMethod.getParameterTypes(member); final int cl = classes.length; final int fl = formalTypes.length - (varArg ? 1 : 0); if(varArg) { if(cl < fl) { return false; } } else { if(cl != fl) { return false; } } for(int i = 0; i < fl; ++i) { if(!isMethodInvocationConvertible(formalTypes[i], classes[i])) { return false; } } if(varArg) { Class varArgType = formalTypes[fl].getComponentType(); for(int i = fl; i < cl; ++i) { if(!isMethodInvocationConvertible(varArgType, classes[i])) { return false; } } } return true; } /** * Determines whether a type represented by a class object is * convertible to another type represented by a class object using a * method invocation conversion, treating object types of primitive * types as if they were primitive types (that is, a Boolean actual * parameter type matches boolean primitive formal type). This behavior * is because this method is used to determine applicable methods for * an actual parameter list, and primitive types are represented by * their object duals in reflective method calls. * @param formal the formal parameter type to which the actual * parameter type should be convertible * @param actual the actual parameter type. * @return true if either formal type is assignable from actual type, * or formal is a primitive type and actual is its corresponding object * type or an object type of a primitive type that can be converted to * the formal type. */ static boolean isMethodInvocationConvertible(Class formal, Class actual) { // Check for identity or widening reference conversion if(formal.isAssignableFrom(actual)) { return true; } // Check for boxing with widening primitive conversion. Note that // actual parameters are never primitives. if(formal.isPrimitive()) { if(formal == Boolean.TYPE) return actual == Boolean.class; if(formal == Character.TYPE) return actual == Character.class; if(formal == Byte.TYPE && actual == Byte.class) return true; if(formal == Short.TYPE && (actual == Short.class || actual == Byte.class)) return true; if(formal == Integer.TYPE && (actual == Integer.class || actual == Short.class || actual == Byte.class)) return true; if(formal == Long.TYPE && (actual == Long.class || actual == Integer.class || actual == Short.class || actual == Byte.class)) return true; if(formal == Float.TYPE && (actual == Float.class || actual == Long.class || actual == Integer.class || actual == Short.class || actual == Byte.class)) return true; if(formal == Double.TYPE && (actual == Double.class || actual == Float.class || actual == Long.class || actual == Integer.class || actual == Short.class || actual == Byte.class)) return true; } return false; } }dynalang-0.4/mop/src/org/dynalang/mop/beans/OverloadedDynamicMethod.java0000644000175000017500000000612311063206304026333 0ustar twernertwerner/* Copyright 2007 Attila Szegedi Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ package org.dynalang.mop.beans; import java.lang.reflect.Member; import java.lang.reflect.UndeclaredThrowableException; import org.dynalang.classtoken.ClassToken; import org.dynalang.mop.CallProtocol; /** * TODO: rename "unwrap" * @author Attila Szegedi * @version $Id: $ * @param */ class OverloadedDynamicMethod extends DynamicMethod { static final Object NO_SUCH_METHOD = new Object(); static final Object AMBIGUOUS_METHOD = new Object(); private final OverloadedFixArgMethod fixArgMethod = new OverloadedFixArgMethod(); private final String name; private final Class declaringClass; private OverloadedVarArgMethod varArgMethod; OverloadedDynamicMethod(String name, Class declaringClass) { this.name = name; this.declaringClass = declaringClass; } void onClassTokensInvalidated(ClassToken[] tokens) { fixArgMethod.onClassTokensInvalidated(tokens); if(varArgMethod != null) { varArgMethod.onClassTokensInvalidated(tokens); } } @Override public Object call(Object target, CallProtocol callProtocol, Object... args) { // Try fixarg first Object invocation = fixArgMethod.createInvocation(target, args, callProtocol); if(invocation == NO_SUCH_METHOD) { if(varArgMethod != null) { invocation = varArgMethod.createInvocation(target, args, callProtocol); } if(invocation == NO_SUCH_METHOD) { throw new IllegalArgumentException("No signature of method " + name + " on " + declaringClass + " matches the arguments"); } } if(invocation == AMBIGUOUS_METHOD) { throw new IllegalArgumentException("Multiple signatures of method " + name + " on " + declaringClass + " match the arguments"); } try { return ((Invocation)invocation).invoke(); } catch(RuntimeException e) { throw e; } catch(Exception e) { throw new UndeclaredThrowableException(e); } } void addMember(T member) { fixArgMethod.addMember(member); boolean isVarArg = isVarArgs(member); if(isVarArg) { if(varArgMethod == null) { varArgMethod = new OverloadedVarArgMethod(); } varArgMethod.addMember(member); } } }dynalang-0.4/mop/src/org/dynalang/mop/beans/ArrayMetaobjectProtocol.java0000644000175000017500000001521011063206304026374 0ustar twernertwerner/* Copyright 2007 Attila Szegedi Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ package org.dynalang.mop.beans; import java.beans.IntrospectionException; import java.lang.reflect.Array; import java.util.Collections; import java.util.Iterator; import java.util.NoSuchElementException; import java.util.Set; import org.dynalang.mop.CallProtocol; /** * Adds access to array elements by numeric index as well as the "length" * read-only property to {@link BeanMetaobjectProtocol}. * @author Attila Szegedi * @version $Id: $ * @param the class of the array */ public class ArrayMetaobjectProtocol extends BeanMetaobjectProtocol { private final Class componentType; /** * Constructs a new metaobject protocol for objects of a certain array class. * @param clazz the class to construct a metaobject protocol for * @param methodsEnumerable if true, methods are enumerable through the * {@link #properties(Object)} and {@link #propertyIds(Object)}. * @throws IllegalArgumentException if the passed class is not an array * class. * @throws IntrospectionException */ public ArrayMetaobjectProtocol(Class clazz, boolean methodsEnumerable) throws IntrospectionException { super(clazz, methodsEnumerable); if(!clazz.isArray()) { throw new IllegalArgumentException("Class " + clazz.getName() + " is not an array class"); } componentType = clazz.getComponentType(); } @Override public Object get(Object target, Object propertyId) { if(propertyId instanceof Number) { return get(target, ((Number)propertyId).longValue()); } if("length".equals(propertyId)) { return Integer.valueOf(Array.getLength(target)); } return super.get(target, propertyId); } @Override public Object get(Object target, long propertyId) { return isWithinBounds(target, propertyId) ? Array.get(target, (int)propertyId) : Result.doesNotExist; } @Override public Boolean has(Object target, Object propertyId) { if(propertyId instanceof Number) { return has(target, ((Number)propertyId).longValue()); } if("length".equals(propertyId)) { return Boolean.TRUE; } return super.has(target, propertyId); } @Override public Boolean has(Object target, long propertyId) { return Boolean.valueOf(isWithinBounds(target, propertyId)); } private static enum PropertyIterationPhase { array, length, methods } private static final Set lengthSet = Collections.singleton((Object)"length"); private Iterator getSuperPropertyIds(Object target) { return super.propertyIds(target); } @Override public Iterator propertyIds(final Object target) { return new Iterator() { private Iterator curr = new Iterator() { private int i = 0; private final int l = Array.getLength(target); public boolean hasNext() { return i < l; } public Integer next() { if(i < l) { return Integer.valueOf(i++); } throw new NoSuchElementException(); } public void remove() { throw new UnsupportedOperationException(); } }; private PropertyIterationPhase phase = PropertyIterationPhase.array; public boolean hasNext() { for(;;) { if(curr.hasNext()) { return true; } if(!switchState()) { return false; } } } private boolean switchState() { switch(phase) { case array: { phase = PropertyIterationPhase.length; curr = lengthSet.iterator(); return true; } case length: { phase = PropertyIterationPhase.methods; curr = getSuperPropertyIds(target); return true; } case methods: { return false; } default: { throw new AssertionError(); } } } public Object next() { for(;;) { try { return curr.next(); } catch(NoSuchElementException e) { if(!switchState()) { throw e; } } } } public void remove() { throw new UnsupportedOperationException(); } }; } @Override public Result put(Object target, Object propertyId, Object value, CallProtocol callProtocol) { if(propertyId instanceof Number) { return put(target, ((Number)propertyId).longValue(), value, callProtocol); } if("length".equals(propertyId)) { return Result.notWritable; } return super.put(target, propertyId, value, callProtocol); } @Override public Result put(Object target, long propertyId, Object value, CallProtocol callProtocol) { if(isWithinBounds(target, propertyId)) { value = callProtocol.representAs(value, componentType); if(value == Result.noAuthority || value == Result.noRepresentation) { return Result.noRepresentation; } Array.set(target, (int)propertyId, value); return Result.ok; } return Result.doesNotExist; } private static boolean isWithinBounds(Object target, long propertyId) { return 0 <= propertyId && propertyId < Array.getLength(target); } } dynalang-0.4/mop/src/org/dynalang/mop/beans/OverloadedVarArgMethod.java0000644000175000017500000002130710763766762026163 0ustar twernertwerner/* Copyright 2007 Attila Szegedi Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ package org.dynalang.mop.beans; import java.lang.reflect.Array; import java.lang.reflect.Member; import java.util.HashMap; import java.util.Map; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentMap; import org.dynalang.mop.CallProtocol; import org.dynalang.mop.BaseMetaobjectProtocol.Result; /** * @author Attila Szegedi * @version $Id: $ */ class OverloadedVarArgMethod extends OverloadedMethod { private static final ConcurrentMap canoncialArgPackers = new ConcurrentHashMap(); private final Map argPackers = new HashMap(); private static class ArgumentPacker { private final int argCount; // This is declared type of a method argument, so we can strongly // reference it as the class itself references it, so it can't get // unloaded. private final Class varArgType; ArgumentPacker(Class[] argTypes) { argCount = argTypes.length; varArgType = argTypes[argCount - 1].getComponentType(); } Object[] packArgs(Object[] args, Object[] originalArgs, boolean cloned, CallProtocol callProtocol) { final int actualArgCount = args.length; final int fixArgCount = argCount - 1; if(args.length != argCount) { Object[] newargs = new Object[argCount]; System.arraycopy(args, 0, newargs, 0, fixArgCount); Object array = Array.newInstance(varArgType, actualArgCount - fixArgCount); for(int i = fixArgCount; i < actualArgCount; ++i) { Object val = callProtocol.representAs(originalArgs[i], varArgType); if(val == Result.noRepresentation || val == Result.noAuthority) { return null; } Array.set(array, i - fixArgCount, val); } newargs[fixArgCount] = array; return newargs; } Object val = callProtocol.representAs(originalArgs[fixArgCount], varArgType); if(val == Result.noRepresentation || val == Result.noAuthority) { return null; } Object array = Array.newInstance(varArgType, 1); Array.set(array, 0, val); if(!cloned) { args = args.clone(); } args[fixArgCount] = array; return args; } @Override public boolean equals(Object obj) { if(obj instanceof ArgumentPacker) { ArgumentPacker p = (ArgumentPacker)obj; return argCount == p.argCount && varArgType == p.varArgType; } return false; } @Override public int hashCode() { return argCount ^ varArgType.hashCode(); } } void onAddSignature(T member, Class[] argTypes) { ArgumentPacker argPacker = new ArgumentPacker(argTypes); ArgumentPacker canonical = canoncialArgPackers.putIfAbsent(argPacker, argPacker); argPackers.put(member, canonical != null ? canonical : argPacker); componentizeLastType(argTypes); } void updateSignature(int l) { Class[][] marshalTypes = getMarshalTypes(); Class[] newTypes = marshalTypes[l]; // First vararg marshal type spec with less parameters than the // current spec influences the types of the current marshal spec. for(int i = l; i-->0;) { Class[] previousTypes = marshalTypes[i]; if(previousTypes != null) { varArgUpdate(newTypes, previousTypes); break; } } // Vararg marshal spec with exactly one parameter more than the current // spec influences the types of the current spec if(l + 1 < marshalTypes.length) { Class[] oneLongerTypes = marshalTypes[l + 1]; if(oneLongerTypes != null) { varArgUpdate(newTypes, oneLongerTypes); } } } void afterSignatureAdded(int l) { // Since this member is vararg, its types influence the types in all // type specs longer than itself. Class[][] marshalTypes = getMarshalTypes(); Class[] newTypes = marshalTypes[l]; for(int i = l + 1; i < marshalTypes.length; ++i) { Class[] existingTypes = marshalTypes[i]; if(existingTypes != null) { varArgUpdate(existingTypes, newTypes); } } // It also influences the types in the marshal spec that is exactly // one argument shorter (as vararg methods can be invoked with 0 // variable arguments, that is, with k-1 cardinality). if(l > 0) { Class[] oneShorterTypes = marshalTypes[l - 1]; if(oneShorterTypes != null) { varArgUpdate(oneShorterTypes, newTypes); } } } private static void varArgUpdate(Class[] modifiedTypes, Class[] modifyingTypes) { final int dl = modifiedTypes.length; final int gl = modifyingTypes.length; int min = Math.min(gl, dl); for(int i = 0; i < min; ++i) { modifiedTypes[i] = OverloadedMethodUtilities.getMostSpecificCommonType(modifiedTypes[i], modifyingTypes[i]); } if(dl > gl) { Class varArgType = modifyingTypes[gl - 1]; for(int i = gl; i < dl; ++i) { modifiedTypes[i] = OverloadedMethodUtilities.getMostSpecificCommonType(modifiedTypes[i], varArgType); } } } private static void componentizeLastType(Class[] types) { int l1 = types.length - 1; assert l1 >= 0; assert types[l1].isArray(); types[l1] = types[l1].getComponentType(); } Object createInvocation(Object target, Object[] args, CallProtocol callProtocol) { if(args == null) { // null is treated as empty args args = DynamicMethod.NULL_ARGS; } int l = args.length; boolean argsCloned = false; Class[][] marshalTypes = getMarshalTypes(); Object[] newArgs = args; // Starting from args.length + 1 as we must try to match against a case // where all specified args are fixargs, and the vararg portion // contains zero args outer: for(int j = Math.min(l + 1, marshalTypes.length - 1); j >= 0; --j) { Class[] types = marshalTypes[j]; if(types == null) { if(j == 0) { return OverloadedDynamicMethod.NO_SUCH_METHOD; } continue; } // Marshal the arguments for(int i = 0; i < l; ++i) { // We're relying on i == types.length here Object dst = callProtocol.representAs(args[i], i < j ? types[i] : types[j - 1]); if(dst == Result.noAuthority || dst == Result.noRepresentation) { continue outer; // Try a shorter signature, using more varargs and less fixargs } if(dst != newArgs[i]) { if(!argsCloned) { newArgs = args.clone(); } newArgs[i] = dst; } } break; } Object objMember = getMemberForArgs(newArgs, true); if(objMember instanceof Member) { T member = (T)objMember; newArgs = argPackers.get(member).packArgs(newArgs, args, argsCloned, callProtocol); if(newArgs == null) { return OverloadedDynamicMethod.NO_SUCH_METHOD; } return new Invocation(target, member, newArgs); } return objMember; // either NOT_FOUND or AMBIGUOUS } }dynalang-0.4/mop/src/org/dynalang/mop/beans/Invocation.java0000644000175000017500000000271010726254021023714 0ustar twernertwerner/* Copyright 2007 Attila Szegedi Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ package org.dynalang.mop.beans; import java.lang.reflect.Constructor; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Member; import java.lang.reflect.Method; class Invocation { private final Object target; private final T member; private final Object[] args; Invocation(Object target, T member, Object[] args) { this.target = target; this.member = member; this.args = args; } Object invoke() throws IllegalAccessException, InvocationTargetException, InstantiationException { if(member == null) { return OverloadedDynamicMethod.AMBIGUOUS_METHOD; } return member instanceof Method ? ((Method)member).invoke(target, args) : ((Constructor)member).newInstance(args); } } dynalang-0.4/mop/src/org/dynalang/mop/beans/OverloadedMethod.java0000644000175000017500000000736611063206304025040 0ustar twernertwerner/* Copyright 2007 Attila Szegedi Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ package org.dynalang.mop.beans; import java.lang.reflect.Member; import java.util.Iterator; import java.util.LinkedList; import java.util.List; import java.util.Map; import java.util.concurrent.ConcurrentHashMap; import org.dynalang.classtoken.ClassToken; import org.dynalang.mop.CallProtocol; /** * @author Attila Szegedi * @version $Id: $ * @param */ abstract class OverloadedMethod { // This contains either declared types of method arguments, or their // superclasses/interfaces, so we can strongly reference them. private Class[][] marshalTypes; private final Map selectorCache = new ConcurrentHashMap(); private final List members = new LinkedList(); void addMember(T member) { members.add(member); Class[] argTypes = DynamicMethod.getParameterTypes(member); int l = argTypes.length; onAddSignature(member, argTypes); if(marshalTypes == null) { marshalTypes = new Class[l + 1][]; marshalTypes[l] = argTypes; updateSignature(l); } else if(marshalTypes.length <= l) { Class[][] newMarshalTypes = new Class[l + 1][]; System.arraycopy(marshalTypes, 0, newMarshalTypes, 0, marshalTypes.length); marshalTypes = newMarshalTypes; marshalTypes[l] = argTypes; updateSignature(l); } else { Class[] oldTypes = marshalTypes[l]; if(oldTypes == null) { marshalTypes[l] = argTypes; } else { for(int i = 0; i < oldTypes.length; ++i) { oldTypes[i] = OverloadedMethodUtilities.getMostSpecificCommonType(oldTypes[i], argTypes[i]); } } updateSignature(l); } afterSignatureAdded(l); } void onClassTokensInvalidated(ClassToken[] tokens) { for(Iterator i = selectorCache.keySet().iterator(); i.hasNext();) { if(i.next().containsAny(tokens)) { i.remove(); } } } Class[][] getMarshalTypes() { return marshalTypes; } Object getMemberForArgs(Object[] args, boolean varArg) { Class[] argTypes = new Class[args.length]; for(int i = 0; i < argTypes.length; ++i) { Object arg = args[i]; argTypes[i] = arg == null ? OverloadedMethodUtilities.OBJECT_CLASS : arg.getClass(); } ClassTokenString argTypeTokens = new ClassTokenString(argTypes); Object objMember = selectorCache.get(argTypeTokens); if(objMember == null) { objMember = new ClassString(argTypes).getMostSpecific(members, varArg); selectorCache.put(argTypeTokens, objMember); } return objMember; } abstract void onAddSignature(T member, Class[] argTypes); abstract void updateSignature(int l); abstract void afterSignatureAdded(int l); abstract Object createInvocation(Object target, Object[] args, CallProtocol callProtocol); } dynalang-0.4/mop/src/org/dynalang/mop/beans/OverloadedFixArgMethod.java0000644000175000017500000000466310727032654026151 0ustar twernertwerner/* Copyright 2007 Attila Szegedi Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ package org.dynalang.mop.beans; import java.lang.reflect.Member; import org.dynalang.mop.CallProtocol; import org.dynalang.mop.BaseMetaobjectProtocol.Result; /** * @author Attila Szegedi * @version $Id: $ */ class OverloadedFixArgMethod extends OverloadedMethod { void onAddSignature(T member, Class[] argTypes) { }; void updateSignature(int l) { }; void afterSignatureAdded(int l) { }; Object createInvocation(Object target, Object[] args, CallProtocol callProtocol) { if(args == null) { // null is treated as empty args args = DynamicMethod.NULL_ARGS; } int l = args.length; boolean argsCloned = false; Class[][] marshalTypes = getMarshalTypes(); if(marshalTypes.length <= l) { return OverloadedDynamicMethod.NO_SUCH_METHOD; } Class[] types = marshalTypes[l]; if(types == null) { return OverloadedDynamicMethod.NO_SUCH_METHOD; } assert types.length == l; // Marshal the arguments for(int i = 0; i < l; ++i) { Object src = args[i]; Object dst = callProtocol.representAs(src, types[i]); if(dst == Result.noAuthority || dst == Result.noRepresentation) { return OverloadedDynamicMethod.NO_SUCH_METHOD; } if(dst != src) { if(!argsCloned) { args = args.clone(); } args[i] = dst; } } Object objMember = getMemberForArgs(args, false); if(objMember instanceof Member) { return new Invocation(target, (T)objMember, args); } return objMember; // either NOT_FOUND or AMBIGUOUS } } dynalang-0.4/mop/src/org/dynalang/mop/beans/SimpleDynamicMethod.java0000644000175000017500000001236111063206304025501 0ustar twernertwerner/* Copyright 2007 Attila Szegedi Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ package org.dynalang.mop.beans; import java.lang.reflect.Array; import java.lang.reflect.Member; import java.lang.reflect.UndeclaredThrowableException; import org.dynalang.mop.CallProtocol; import org.dynalang.mop.BaseMetaobjectProtocol.Result; class SimpleDynamicMethod extends DynamicMethod { private final T member; // We can directly reference the classes, as they're declared parameters, // and are accessible to the class that owns this method anyway. Therefore, // referencing them here can't cause memory leaks. private final Class[] paramTypes; SimpleDynamicMethod(T method) { this.member = method; this.paramTypes = getParameterTypes(method); } T getMember() { return member; } @Override public Object call(Object target, CallProtocol callProtocol, Object... args) { if(args == null) { // null is treated as empty args args = NULL_ARGS; } int argsLen = args.length; int paramTypesLen = paramTypes.length; int paramTypesLenM1 = paramTypesLen - 1; boolean varArg = isVarArgs(member); int fixArgsLen = varArg ? paramTypesLenM1 : paramTypesLen; // Convert arguments if needed int min = Math.min(argsLen, fixArgsLen); boolean argsCloned = false; for(int i = 0; i < min; ++i) { Object src = args[i]; Object dst = marshal(args[i], paramTypes[i], callProtocol); if(dst != src) { if(!argsCloned) { args = args.clone(); } args[i] = dst; } } if(varArg) { Class varArgType = paramTypes[paramTypesLenM1]; Class componentType = varArgType.getComponentType(); if(argsLen != paramTypesLen) { // Zero or multiple varargs specified -- we must resize the // arguments array Object[] newargs = new Object[paramTypesLen]; System.arraycopy(args, 0, newargs, 0, paramTypesLenM1); int varArgLen = argsLen - paramTypesLenM1; // Set the last argument to be the vararg array Object varArgArray = Array.newInstance(componentType, varArgLen); newargs[paramTypesLenM1] = varArgArray; // Populate the vararg array for(int i = 0; i < varArgLen; ++i) { Array.set(varArgArray, i, marshal( args[paramTypesLenM1 + i], componentType, callProtocol)); } args = newargs; } else { // exactly one vararg specified. It might be an array of the // expected type in itself Object lastArg = args[paramTypesLenM1]; Object varArgArray = callProtocol.representAs(lastArg, varArgType); if(varArgArray != null && !varArgType.isInstance(varArgArray)) { // It isn't. Well then, let's assume it's a one-element // vararg, and construct a 1-element array for it varArgArray = Array.newInstance(componentType, 1); Array.set(varArgArray, 0, marshal(lastArg, componentType, callProtocol)); } // If varArgArray isn't identical to lastArg, update the last // args element if(lastArg != varArgArray) { if(!argsCloned) { args = args.clone(); } args[paramTypesLenM1] = varArgArray; } } } try { return invoke(member, target, args); } catch(RuntimeException e) { throw e; } catch(Exception e) { throw new UndeclaredThrowableException(e); } } private Object marshal(Object src, Class targetClass, CallProtocol callProtocol) { Object dst = callProtocol.representAs(src, targetClass); if(dst == Result.noAuthority || dst == Result.noRepresentation) { String className = src == null ? "null" : src.getClass().getName(); throw new IllegalArgumentException("Can't represent " + className + " as " + targetClass.getName() + " for invoking " + member); } return dst; } }dynalang-0.4/mop/src/org/dynalang/mop/beans/ClassTokenString.java0000644000175000017500000000305010763766762025063 0ustar twernertwernerpackage org.dynalang.mop.beans; import org.dynalang.classtoken.ClassToken; /** * @author Attila Szegedi * @version $Id: $ */ public class ClassTokenString { private final ClassToken[] classTokens; ClassTokenString(Class[] classes) { classTokens = new ClassToken[classes.length]; for(int i = 0; i < classes.length; ++i) { classTokens[i] = ClassToken.forClass(classes[i]); } } public int hashCode() { int hash = 0; for(int i = 0; i < classTokens.length; ++i) { hash ^= classTokens[i].hashCode(); } return hash; } public boolean equals(Object o) { if(o instanceof ClassTokenString) { ClassTokenString ct = (ClassTokenString)o; if(ct.classTokens.length != classTokens.length) { return false; } for(int i = 0; i < classTokens.length; ++i) { // ClassToken objects are canonicalized, so we can use identity // comparison here. if(ct.classTokens[i] != classTokens[i]) { return false; } } return true; } return false; } boolean containsAny(ClassToken[] tokens) { for (int i = 0; i < classTokens.length; i++) { ClassToken classToken = classTokens[i]; for (int j = 0; j < tokens.length; j++) { if(classToken == tokens[j]) { return true; } } } return false; } }dynalang-0.4/mop/src/org/dynalang/mop/beans/BeansMetaobjectProtocol.java0000644000175000017500000003571311063206304026360 0ustar twernertwerner/* Copyright 2007 Attila Szegedi Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ package org.dynalang.mop.beans; import java.beans.IntrospectionException; import java.lang.ref.SoftReference; import java.lang.reflect.UndeclaredThrowableException; import java.util.IdentityHashMap; import java.util.Iterator; import java.util.Map; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentMap; import org.dynalang.classtoken.ClassToken; import org.dynalang.classtoken.ClassTokenInvalidatedEvent; import org.dynalang.classtoken.ClassTokenListener; import org.dynalang.mop.BaseMetaobjectProtocol; import org.dynalang.mop.CallProtocol; import org.dynalang.mop.MetaobjectProtocol; /** * A metaobject protocol implementation that allows access and manipulation of * POJOS using semantics adhering to the JavaBeans specification, as well as * access and manipulation of native Java arrays. In addition to using it as a * generic MOP, you can also use it as a factory for individual * {@link BeanMetaobjectProtocol} objects using * {@link #getBeanMetaobjectProtocol(Class)}. These objects can subsequently * be used to access constructors and static methods of the Java classes they * represent, but be aware that functionality falls outside of the generic MOP * API. * @author Attila Szegedi * @version $Id: $ */ public class BeansMetaobjectProtocol implements MetaobjectProtocol { private final boolean methodsEnumerable; // Using a soft reference is a compromise solution. If we used a hard // reference, we'd prevent the class from unloading, as the // BeanMetaobjectProtocol holds a reference to Method objects of the // class, which in turn hold a reference to Class objects. If we used a // weak reference, the BeanMetaobjectProtocol would be recreated too // often. Using a soft reference allows a decent amount of caching, but // still ensures that the class information will eventually get cleaned up // after the class is no longer used, allowing it to unload if it is // otherwise unreferenced from the rest of the system. private final ConcurrentMap>> mops = new ConcurrentHashMap>>(); /** * Creates a new JavaBeans metaobject protocol that doesn't expose objects' * methods and JavaBeans properties as enumerable. */ public BeansMetaobjectProtocol() { this(false); ClassToken.addClassRefListener(new ClassTokenListener() { public void classTokenInvalidated(ClassTokenInvalidatedEvent e) { onClassTokensInvalidated(e.getClassTokens()); } }); } /** * Creates a new JavaBeans metaobject protocol. * @param methodsEnumerable if true, then objects' methods and JavaBeans * properties show up in the results of {@link #properties(Object)} and * {@link #propertyIds(Object)}. If false, these can still be accessed by * directly addressing them, but don't show up in aforementioned methods' * results. */ public BeansMetaobjectProtocol(boolean methodsEnumerable) { this.methodsEnumerable = methodsEnumerable; } private void onClassTokensInvalidated(ClassToken[] tokens) { mops.remove(tokens); for(Iterator>> i = mops.values().iterator(); i.hasNext();) { SoftReference> ref = i.next(); BeanMetaobjectProtocol mop = ref.get(); if(mop == null) { i.remove(); } mop.onClassTokensInvalidated(tokens); } } public Object call(Object callable, CallProtocol callProtocol, Map args) { // Java methods aren't callable with named arguments return Result.noAuthority; } public Object call(Object target, Object callableId, CallProtocol callProtocol, Map args) { return callWithMap(target, callableId, callProtocol); } static Object callWithMap(Object target, Object callableId, CallProtocol callProtocol) { // Give chance to notFound etc. first Object result = callProtocol.get(target, callableId); if(result instanceof Result) { return result; } // Java methods aren't callable with named arguments return Result.noAuthority; } public Object call(Object target, Object callableId, CallProtocol callProtocol, Object... args) { return getBeanMetaobjectProtocol(target).call(target, callableId, callProtocol, args); } public Object call(Object callable, CallProtocol callProtocol, Object... args) { return callMethod(callable, callProtocol, args); } static Object callMethod(Object callable, CallProtocol callProtocol, Object[] args) { if(callable instanceof DynamicInstanceMethod) { return ((DynamicInstanceMethod)callable).call(args, callProtocol); } return Result.noAuthority; } public Result delete(Object target, long propertyId) { return getBeanMetaobjectProtocol(target).delete(target, propertyId); } public Result delete(Object target, Object propertyId) { return getBeanMetaobjectProtocol(target).delete(target, propertyId); } public Object get(Object target, long propertyId) { return getBeanMetaobjectProtocol(target).get(target, propertyId); } public Object get(Object target, Object propertyId) { return getBeanMetaobjectProtocol(target).get(target, propertyId); } public Boolean has(Object target, long propertyId) { return getBeanMetaobjectProtocol(target).has(target, propertyId); } public Boolean has(Object target, Object propertyId) { return getBeanMetaobjectProtocol(target).has(target, propertyId); } public Iterator properties(final Object target) { return getBeanMetaobjectProtocol(target).properties(target); } public Iterator propertyIds(Object target) { return getBeanMetaobjectProtocol(target).propertyIds(target); } public Result put(Object target, long propertyId, Object value, CallProtocol callProtocol) { return getBeanMetaobjectProtocol(target).put(target, propertyId, value, callProtocol); } public Result put(Object target, Object propertyId, Object value, CallProtocol callProtocol) { return getBeanMetaobjectProtocol(target).put(target, propertyId, value, callProtocol); } private static final Map, PrimitiveConverter> primitiveConverters = new IdentityHashMap, PrimitiveConverter>(); private static abstract class PrimitiveConverter { abstract Object representAs(Object object); } static { primitiveConverters.put(Boolean.TYPE, new PrimitiveConverter() { @Override Object representAs(Object object) { return object instanceof Boolean ? ((Boolean)object) : Result.noRepresentation; } }); primitiveConverters.put(Byte.TYPE, new PrimitiveConverter() { @Override Object representAs(Object object) { return object instanceof Byte ? ((Byte)object) : Result.noRepresentation; } }); primitiveConverters.put(Character.TYPE, new PrimitiveConverter() { @Override Object representAs(Object object) { return object instanceof Character ? ((Character)object) : Result.noRepresentation; } }); primitiveConverters.put(Double.TYPE, new PrimitiveConverter() { @Override Object representAs(Object object) { if(object instanceof Double) { return object; } if(object instanceof Integer || object instanceof Long || object instanceof Float || object instanceof Byte || object instanceof Short) { return Double.valueOf(((Number)object).doubleValue()); } if(object instanceof Character) { return Double.valueOf(((Character)object).charValue()); } return Result.noRepresentation; } }); primitiveConverters.put(Float.TYPE, new PrimitiveConverter() { @Override Object representAs(Object object) { if(object instanceof Float) { return object; } if(object instanceof Integer || object instanceof Long || object instanceof Byte || object instanceof Short) { return Float.valueOf(((Number)object).floatValue()); } if(object instanceof Character) { return Float.valueOf(((Character)object).charValue()); } return Result.noRepresentation; } }); primitiveConverters.put(Integer.TYPE, new PrimitiveConverter() { @Override Object representAs(Object object) { if(object instanceof Integer) { return object; } if(object instanceof Byte || object instanceof Short) { return Integer.valueOf(((Number)object).intValue()); } if(object instanceof Character) { return Integer.valueOf(((Character)object).charValue()); } return Result.noRepresentation; } }); primitiveConverters.put(Long.TYPE, new PrimitiveConverter() { @Override Object representAs(Object object) { if(object instanceof Long) { return object; } if(object instanceof Integer || object instanceof Byte || object instanceof Short) { return Long.valueOf(((Number)object).longValue()); } if(object instanceof Character) { return Long.valueOf(((Character)object).charValue()); } return Result.noRepresentation; } }); primitiveConverters.put(Short.TYPE, new PrimitiveConverter() { @Override Object representAs(Object object) { if(object instanceof Short) { return object; } if(object instanceof Byte) { return Short.valueOf(((Number)object).shortValue()); } return Result.noRepresentation; } }); primitiveConverters.put(Void.TYPE, new PrimitiveConverter() { @Override Object representAs(Object object) { return Result.noRepresentation; } }); } /** * In case object is an instance of the target class, returns it unchanged. * In case object is an instance of the boxing class for a primitive target * class, returns it unchanged. In case object is null and target class is * primitive, returns {@link BaseMetaobjectProtocol.Result#noRepresentation}. * In case the target class is primitive, and there exists a * * widening primitive conversion from the object's class unboxed * primitive type to the target class, returns a boxed representation of * the widened value. In all other cases, * {@link BaseMetaobjectProtocol.Result#noRepresentation} is returned. */ public Object representAs(Object object, Class targetClass) { return representAsInternal(object, targetClass); } static Object representAsInternal(Object object, Class targetClass) { // Object representations for primitive types are allowed if(targetClass.isPrimitive()) { if(object == null) { // null has no primitive representation return Result.noRepresentation; } return primitiveConverters.get(targetClass).representAs(object); } else if(object == null) { // null is a valid representation for all reference types return null; } // If the object is instance of the target class, it itself is the // representation, otherwise there's no representation. return targetClass.isInstance(object) ? object : Result.noRepresentation; } /** * Returns a MOP instance for a specified Java object that treats the * object as a generic JavaBean. The MOP is class specific. * @param object the object in question * @return a JavaBeans MOP for the object's class * @throws NullPointerException if object is null */ private BeanMetaobjectProtocol getBeanMetaobjectProtocol(T object) { return (BeanMetaobjectProtocol)getBeanMetaobjectProtocol(object.getClass()); } /** * Returns a MOP instance for a specified Java class that treats the class * instances as a generic JavaBean. * @param clazz the class in question * @param the type of the class * @return a JavaBeans MOP for the class */ public BeanMetaobjectProtocol getBeanMetaobjectProtocol(Class clazz) { ClassToken token = ClassToken.forClass(clazz); SoftReference> ref = mops.get(token); BeanMetaobjectProtocol mop; if(ref != null) { mop = (BeanMetaobjectProtocol)ref.get(); if(mop != null) { return mop; } } try { if(clazz.isArray()) { mop = new ArrayMetaobjectProtocol(clazz, methodsEnumerable); } else { mop = new BeanMetaobjectProtocol(clazz, methodsEnumerable); } mops.put(token, new SoftReference>(mop)); } catch(IntrospectionException e) { throw new UndeclaredThrowableException(e); } return mop; } }dynalang-0.4/mop/src/org/dynalang/mop/beans/DynamicInstanceMethod.java0000644000175000017500000000227011063206304026012 0ustar twernertwerner/* Copyright 2007 Attila Szegedi Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ package org.dynalang.mop.beans; import java.lang.reflect.Method; import org.dynalang.mop.CallProtocol; /** * @author Attila Szegedi * @version $Id: $ */ class DynamicInstanceMethod { private final Object target; private final DynamicMethod dynamicMethod; DynamicInstanceMethod(Object target, DynamicMethod dynamicMethod) { this.target = target; this.dynamicMethod = dynamicMethod; } Object call(Object[] args, CallProtocol callProtocol) { return dynamicMethod.call(target, callProtocol, args); } } dynalang-0.4/mop/src/org/dynalang/mop/ClassBasedMetaobjectProtocol.java0000644000175000017500000000271110726526507026253 0ustar twernertwernerpackage org.dynalang.mop; import org.dynalang.mop.impl.CompositeClassBasedMetaobjectProtocol; /** * An interface that can be optionally implemented by any MOP if it is strictly * class-based (that is, the class of an object used as either target or * property identifier solely determines whether it has authority over it or * not). The provision for property identifiers is put in place so that MOPs * can implement special "metaproperties" (i.e. "prototype" in JavaScript) by * using property IDs of classes private to their implementation. * @author Attila Szegedi * @version $Id: $ */ public interface ClassBasedMetaobjectProtocol extends MetaobjectProtocol { /** * Returns whether this metaobject protocol has authority over objects of * the specified class. Note that if a MOP claims that it has authority * over objects of a certain class, it can still return * {@link BaseMetaobjectProtocol.Result#noAuthority} for certain objects. * In that case - when used in {@link CompositeClassBasedMetaobjectProtocol} * - the other participating MOPs will also be given the chance to handle * the object after this MOP was given the chance first. * @param clazz the class of the handled object * @return true if this metaobject protocol has authority over objects of * the specified class, false otherwise. */ public boolean isAuthoritativeForClass(Class clazz); } dynalang-0.4/mop/src/org/dynalang/mop/impl/0000755000175000017500000000000011425436177020624 5ustar twernertwernerdynalang-0.4/mop/src/org/dynalang/mop/impl/CompositeMetaobjectProtocol.java0000644000175000017500000001715210724016017027143 0ustar twernertwerner/* Copyright 2007 Attila Szegedi Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ package org.dynalang.mop.impl; import java.io.Serializable; import java.util.Iterator; import java.util.Map; import java.util.Map.Entry; import org.dynalang.mop.CallProtocol; import org.dynalang.mop.MetaobjectProtocol; /** * A simple composite MOP that uses a chain of other MOPs to carry out its * operations. Most operations are attempted from the first MOP in chain towards * the last, until one returns an authoritative answer. The only exceptions to * this are the {@link #properties(Object)} and {@link #propertyIds(Object)} * methods, that return the union of all authoritative answers. In case there * is a conflict among property IDs returned from an earlier MOP and a later * MOP, the earlier takes precedence and the later will not be returned. If you * have a list of MOPs that you want to use, you might want to consider using * {@link CompositeClassBasedMetaobjectProtocol#optimize(MetaobjectProtocol[])} * on them before using them to construct a composite metaobject protocol. * might consider * @author Attila Szegedi * @version $Id: $ */ public class CompositeMetaobjectProtocol implements MetaobjectProtocol, Serializable { private static final long serialVersionUID = 1L; private final MetaobjectProtocol[] members; /** * Creates a new composite metaobject protocol from the specified members. * @param members the member metaobject protocols. */ public CompositeMetaobjectProtocol(MetaobjectProtocol[] members) { this.members = members.clone(); } public Object call(Object callable, CallProtocol callProtocol, Map args) { for (MetaobjectProtocol mop : members) { Object res = mop.call(callable, callProtocol, args); if(res != Result.noAuthority) { return res; } } return Result.noAuthority; } public Object call(Object target, Object callableId, CallProtocol callProtocol, Map args) { for (MetaobjectProtocol mop : members) { Object res = mop.call(target, callableId, callProtocol, args); if(res != Result.noAuthority) { return res; } } return Result.noAuthority; } public Object call(Object target, Object callableId, CallProtocol callProtocol, Object... args) { for (MetaobjectProtocol mop : members) { Object res = mop.call(target, callableId, callProtocol, args); if(res != Result.noAuthority) { return res; } } return Result.noAuthority; } public Object call(Object callable, CallProtocol callProtocol, Object... args) { for (MetaobjectProtocol mop : members) { Object res = mop.call(callable, callProtocol, args); if(res != Result.noAuthority) { return res; } } return Result.noAuthority; } public Result delete(Object target, long propertyId) { for (MetaobjectProtocol mop : members) { Result res = mop.delete(target, propertyId); if(res != Result.noAuthority) { return res; } } return Result.noAuthority; } public Result delete(Object target, Object propertyId) { for (MetaobjectProtocol mop : members) { Result res = mop.delete(target, propertyId); if(res != Result.noAuthority) { return res; } } return Result.noAuthority; } public Object get(Object target, long propertyId) { for (MetaobjectProtocol mop : members) { Object res = mop.get(target, propertyId); if(res != Result.noAuthority) { return res; } } return Result.noAuthority; } public Object get(Object target, Object propertyId) { for (MetaobjectProtocol mop : members) { Object res = mop.get(target, propertyId); if(res != Result.noAuthority) { return res; } } return Result.noAuthority; } public Boolean has(Object target, long propertyId) { for (MetaobjectProtocol mop : members) { Boolean has = mop.has(target, propertyId); if(has != null) { return has; } } return null; } public Boolean has(Object target, Object propertyId) { for (MetaobjectProtocol mop : members) { Boolean has = mop.has(target, propertyId); if(has != null) { return has; } } return null; } public Iterator properties(Object target) { Iterator compositeIt = null; for (MetaobjectProtocol mop : members) { Iterator it = mop.properties(target); if(it != null) { if(compositeIt == null) { compositeIt = it; } else if(compositeIt instanceof CompositeUniqueEntryIterator) { ((CompositeUniqueEntryIterator)compositeIt).add(it); } else { compositeIt = new CompositeUniqueEntryIterator(compositeIt, it); } } } return compositeIt; } public Iterator propertyIds(Object target) { Iterator compositeIt = null; for (MetaobjectProtocol mop : members) { Iterator it = mop.propertyIds(target); if(it != null) { if(compositeIt == null) { compositeIt = it; } else if(compositeIt instanceof CompositeUniqueIterator) { ((CompositeUniqueIterator)compositeIt).add(it); } else { compositeIt = new CompositeUniqueIterator(compositeIt, it); } } } return compositeIt; } public Result put(Object target, long propertyId, Object value, CallProtocol callProtocol) { for (MetaobjectProtocol mop : members) { Result res = mop.put(target, propertyId, value, callProtocol); if(res != Result.noAuthority) { return res; } } return Result.noAuthority; } public Result put(Object target, Object propertyId, Object value, CallProtocol callProtocol) { for (MetaobjectProtocol mop : members) { Result res = mop.put(target, propertyId, value, callProtocol); if(res != Result.noAuthority) { return res; } } return Result.noAuthority; } public Object representAs(Object object, Class targetClass) { for (MetaobjectProtocol mop : members) { Object res = mop.representAs(object, targetClass); if(res != Result.noAuthority) { return res; } } return Result.noAuthority; } }dynalang-0.4/mop/src/org/dynalang/mop/impl/package.html0000644000175000017500000000162710716322716023106 0ustar twernertwerner

This package defines classes that help in implementing MOPs as well as creating (mostly composite) MOP instances. A simple composite MOP is provided, as well an adapter to convert any base metaobject protocol into a full metaobject protocol, and a base class that can be used to more easily (if not the most optimally) implement custom MOPs.

Also, the package contains utility classes for {@link org.dynalang.mop.impl.AutoDiscovery automatically discovering MOP implementations} available in a classpath of any class loader and for {@link org.dynalang.mop.impl.StandardMetaobjectProtocolFactory creating "standard" composite MOPs} that merge all available MOPs in the classpath into one. To use existing MOPs, you will usually only need these facilities.

dynalang-0.4/mop/src/org/dynalang/mop/impl/StandardMetaobjectProtocolFactory.java0000644000175000017500000003131110716623133030266 0ustar twernertwerner/* Copyright 2007 Attila Szegedi Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ package org.dynalang.mop.impl; import java.io.IOException; import java.util.ArrayList; import java.util.Arrays; import java.util.HashSet; import java.util.List; import java.util.Set; import org.dynalang.mop.BaseMetaobjectProtocol; import org.dynalang.mop.ClassBasedMetaobjectProtocol; import org.dynalang.mop.MetaobjectProtocol; import org.dynalang.mop.beans.BeansMetaobjectProtocol; import org.dynalang.mop.collections.ListMetaobjectProtocol; import org.dynalang.mop.collections.MapMetaobjectProtocol; /** * A class with static utility methods for creating a "standard" MOP. A * standard MOP is a MOP that is a compositional of MOPs known and precreated * by the caller as well as any {@link AutoDiscovery automatically discovered} * MOPs. * @author Attila Szegedi * @version $Id: $ */ public class StandardMetaobjectProtocolFactory { private StandardMetaobjectProtocolFactory() { } /** * This method implements the "usual" way for creation of a composite * metaobject protocol instance that encompasses all available MOPs in the * classpath of the current thread's class loader. This makes this method * useful for creating a class loader specific composite MOP for * environments that do not have their own native object model but wish * to manipulate all available object models. * The returned composite MOP will feature all MOPs found in the class * loader's JAR files, followed by standard fallback MOPs for beans * (POJOs), Maps, and Lists. * @param elementsShadowMethods the order of fallback MOPs. If true, List * and Map MOP are put before the beans MOP. If false, beans MOP is put * before the List and Map MOP. Note that List and Map MOPs implement * {@link ClassBasedMetaobjectProtocol} while beans MOP does not, so you'll * generally get better performance if you pass true for this parameter. * @return a MetaobjectProtocol that optimally composes the automatically * discovered and fallback MOPs. * @param methodsEnumerable if true, then objects' methods and JavaBeans * properties show up in the results of * {@link BaseMetaobjectProtocol#properties(Object)} and * {@link MetaobjectProtocol#propertyIds(Object)}. If false, these can * still be accessed by directly addressing them, but don't show up in * aforementioned methods' results. * @throws IOException * @throws InstantiationException * @throws IllegalAccessException * @throws ClassNotFoundException */ public static MetaobjectProtocol createStandardMetaobjectProtocol( boolean elementsShadowMethods, boolean methodsEnumerable) throws IOException, InstantiationException, IllegalAccessException, ClassNotFoundException { return createStandardMetaobjectProtocol( Thread.currentThread().getContextClassLoader(), null, createStandardFallback(elementsShadowMethods, methodsEnumerable)); } /** * This method implements the "usual" way for creation of a composite * metaobject protocol instance that encompasses all available MOPs in the * classpath of the current thread's class loader, adding a single * metaobject protocol as the first MOP of the composite. This single * metaobject protocol usually implements the default MOP for the * environment's "standard" language. This makes this method useful for * creating a class loader specific composite MOP for environments that * have their own native object model (i.e. dynamic language runtimes). * The returned composite MOP will feature the passed MOP as its first * element, followed by any other MOPs found in the class loader's JAR * files, followed by standard fallback MOPs for beans (POJOs), Maps, and * Lists. * @param nativeProtocol the MOP for the environment's native objects (i.e. * a JavaScript runtime creating a MOP will pass a JavaScript MOP here). If * a MOP of the same class is later discovered in JARs on the class path, * it will be ignored and the explicitly passed instance used. * @param elementsShadowMethods the order of fallback MOPs. If true, List * and Map MOP are put before the beans MOP. If false, beans MOP is put * before the List and Map MOP. Note that List and Map MOPs implement * {@link ClassBasedMetaobjectProtocol} while beans MOP does not, so you'll * generally get better performance if you pass true for this parameter. * @return a MetaobjectProtocol that optimally composes the preferred MOP, * automatically discovered, and fallback MOPs. Those automatically * discovered MOPs that are of the same class as any of the prioritized or * fallback MOPs are ignored. * @param methodsEnumerable if true, then objects' methods and JavaBeans * properties show up in the results of * {@link BaseMetaobjectProtocol#properties(Object)} and * {@link MetaobjectProtocol#propertyIds(Object)}. If false, these can * still be accessed by directly addressing them, but don't show up in * aforementioned methods' results. * @throws IOException * @throws InstantiationException * @throws IllegalAccessException * @throws ClassNotFoundException */ public static MetaobjectProtocol createStandardMetaobjectProtocol( MetaobjectProtocol nativeProtocol, boolean elementsShadowMethods, boolean methodsEnumerable) throws IOException, InstantiationException, IllegalAccessException, ClassNotFoundException { return createStandardMetaobjectProtocol( Thread.currentThread().getContextClassLoader(), new MetaobjectProtocol[] { nativeProtocol }, createStandardFallback(elementsShadowMethods, methodsEnumerable)); } /** * This method implements the "usual" way for creation of a composite * metaobject protocol instance that encompasses all available MOPs. It is * more generic than the other two methods of the same name, allowing * maximum flexibility in configuration. * @param classLoader the class loader within which the MOPs are * discovered. null can be used to denote the * {@link ClassLoader#getSystemClassLoader() system class loader}, although * you'll usually want the thread context class loader instead. * @param prioritized an array of precreated, prioritized MOPs. These MOPs * will be given a chance to handle objects before any automatically * discovered MOPs. Can be null. * @param fallbacks an array of precreated fallback MOPs. These MOPs will * be given a chance to handle objects after any automatically discovered * MOPs. Tipically, you'll want to specify an instance of * {@link BeansMetaobjectProtocol}, an instance of * {@link ListMetaobjectProtocol}, an instance of * {@link MapMetaobjectProtocol} (in order of your preference), and an * instance of {@link BottomMetaobjectProtocol} to seal it all. The method * {@link #createStandardFallback(boolean, boolean)} can be used to * conveniently create this standard fallback MOP configuration. * @return a MetaobjectProtocol that optimally composes all prioritized, * automatically discovered, and fallback MOPs. Those automatically * discovered MOPs that are of the same class as any of the prioritized or * fallback MOPs are ignored. * @throws IOException * @throws InstantiationException * @throws IllegalAccessException * @throws ClassNotFoundException */ public static MetaobjectProtocol createStandardMetaobjectProtocol( ClassLoader classLoader, MetaobjectProtocol[] prioritized, MetaobjectProtocol[] fallbacks) throws IOException, InstantiationException, IllegalAccessException, ClassNotFoundException { // Treat nulls appropriately if(prioritized == null) { prioritized = new MetaobjectProtocol[0]; } if(fallbacks == null) { fallbacks = new MetaobjectProtocol[0]; } // Perform discovery MetaobjectProtocol[] discovered = MetaobjectProtocolAdaptor.toMetaobjectProtocols( AutoDiscovery.discoverBaseMetaobjectProtocols(classLoader)); // Gather classes of all precreated (prioritized and fallback) MOPs. // We'll filter out any discovered MOPs of the same class. Set> knownMopClasses = new HashSet>(); for (MetaobjectProtocol protocol : prioritized) { knownMopClasses.add(protocol.getClass()); } for (MetaobjectProtocol protocol : fallbacks) { knownMopClasses.add(protocol.getClass()); } // Now, concatenate ... List mops = new ArrayList( prioritized.length + discovered.length + fallbacks.length); // ... prioritized MOPs, ... mops.addAll(Arrays.asList(prioritized)); // ... filtered discovered MOPs, ... for (int i = 0; i < discovered.length; i++) { MetaobjectProtocol protocol = discovered[i]; if(!knownMopClasses.contains(protocol.getClass())) { mops.add(protocol); } } // ... and finally fallback MOPs. mops.addAll(Arrays.asList(fallbacks)); // Optimize the final sequence for class-based lookup MetaobjectProtocol[] optimized = CompositeClassBasedMetaobjectProtocol.optimize(mops.toArray( new MetaobjectProtocol[mops.size()])); switch(optimized.length) { case 0: { return new BottomMetaobjectProtocol(); } case 1: { return optimized[0]; } default: { return new CompositeMetaobjectProtocol(optimized); } } } /** * Creates "standard" fallback MOP sequence to use as the fallback * parameter in {@link #createStandardMetaobjectProtocol(ClassLoader, * MetaobjectProtocol[], MetaobjectProtocol[])}. The sequence consists of * a {@link BeansMetaobjectProtocol}, {@link MapMetaobjectProtocol}, * {@link ListMetaobjectProtocol}, and ultimately of a * {@link BottomMetaobjectProtocol}. * @param elementsShadowMethods if true, map and list MOPs are put before * the beans MOP (thus, map elements will hide bean properties and * methods). If false, beans MOP is put first (thus, bean properties and * methods will shadow map elements). Note that List and Map MOPs implement * {@link ClassBasedMetaobjectProtocol} while beans MOP does not, so you'll * generally get better performance if you pass true for this parameter. * @return an array containing the four standard fallback MOPs. * @param methodsEnumerable if true, then objects' methods and JavaBeans * properties show up in the results of * {@link BaseMetaobjectProtocol#properties(Object)} and * {@link MetaobjectProtocol#propertyIds(Object)}. If false, these can * still be accessed by directly addressing them, but don't show up in * aforementioned methods' results. */ public static MetaobjectProtocol[] createStandardFallback( boolean elementsShadowMethods, boolean methodsEnumerable) { MetaobjectProtocol[] fallback = new MetaobjectProtocol[4]; MetaobjectProtocol listMop = new ListMetaobjectProtocol(); MetaobjectProtocol mapMop = new MapMetaobjectProtocol(); MetaobjectProtocol beansMop = new BeansMetaobjectProtocol(methodsEnumerable); if(elementsShadowMethods) { fallback[0] = mapMop; fallback[1] = listMop; fallback[2] = beansMop; } else { fallback[0] = beansMop; fallback[1] = mapMop; fallback[2] = listMop; } fallback[3] = new BottomMetaobjectProtocol(); return fallback; } } dynalang-0.4/mop/src/org/dynalang/mop/impl/CompositeUniqueEntryIterator.java0000644000175000017500000000177610716573525027370 0ustar twernertwerner/* Copyright 2007 Attila Szegedi Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ package org.dynalang.mop.impl; import java.util.Iterator; import java.util.Map.Entry; class CompositeUniqueEntryIterator extends CompositeUniqueIterator { CompositeUniqueEntryIterator(Iterator i1, Iterator i2) { super(i1, i2); } @Override protected Object getKey(Object value) { return ((Entry)value).getKey(); } }dynalang-0.4/mop/src/org/dynalang/mop/impl/MetaobjectProtocolBase.java0000644000175000017500000000541110724016017026046 0ustar twernertwerner/* Copyright 2007 Attila Szegedi Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ package org.dynalang.mop.impl; import java.util.Iterator; import java.util.Map; import org.dynalang.mop.CallProtocol; import org.dynalang.mop.MetaobjectProtocol; /** * A convenient base class for implementing a {@link MetaobjectProtocol} that * requires you to only implement {@link MetaobjectProtocolBase} methods on it. * @author Attila Szegedi * @version $Id: $ */ public abstract class MetaobjectProtocolBase implements MetaobjectProtocol { public Object call(Object target, Object callableId, CallProtocol callProtocol, Map args) { Object callable = callProtocol.get(target, callableId); if(callable instanceof Result) { return callable; } return callProtocol.call(callable, callProtocol, args); } public Object call(Object target, Object callableId, CallProtocol callProtocol, Object... args) { Object callable = callProtocol.get(target, callableId); if(callable instanceof Result) { return callable; } return callProtocol.call(callable, callProtocol, args); } public Result delete(Object target, long propertyId) { return delete(target, Long.valueOf(propertyId)); } public Object get(Object target, long propertyId) { return get(target, Long.valueOf(propertyId)); } public Boolean has(Object target, long propertyId) { return has(target, Long.valueOf(propertyId)); } public Iterator propertyIds(Object target) { final Iterator it = properties(target); assert it != null : getClass().getName() + " returned null properties iterator"; return new Iterator() { public boolean hasNext() { return it.hasNext(); } public Object next() { return it.next().getKey(); } public void remove() { it.remove(); } }; } public Result put(Object target, long propertyId, Object value, CallProtocol callProtocol) { return put(target, Long.valueOf(propertyId), value, callProtocol); } } dynalang-0.4/mop/src/org/dynalang/mop/impl/AutoDiscovery.java0000644000175000017500000001235410716573437024277 0ustar twernertwerner/* Copyright 2007 Attila Szegedi Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ package org.dynalang.mop.impl; import java.io.BufferedReader; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; import java.net.URL; import java.util.Enumeration; import java.util.LinkedList; import java.util.List; import org.dynalang.mop.BaseMetaobjectProtocol; /** * Provides methods for automatic discovery of all metaobject protocols * listed in the /META-INF/services/org.dynalang.mop.BaseMetaobjectProtocol * resources of all JAR files for a particular class loader. * @author Attila Szegedi * @version $Id: $ */ public class AutoDiscovery { private static final String RESOURCE_PATH = "META-INF/services/org.dynalang.mop.BaseMetaobjectProtocol"; private AutoDiscovery() { } /** * Returns an instance of all metaobject protocol classes that are declared * in the /META-INF/services/org.dynalang.mop.BaseMetaobjectProtocol * resources of all JAR files in the current thread's context class loader's * classpath. * @return an array of base MOPs. The returned array can be empty. You will * probably want to run the return value through * {@link MetaobjectProtocolAdaptor#toMetaobjectProtocols(BaseMetaobjectProtocol[])} * if your code uses the full MOP interface instead of the base one. * @throws IOException if there is a problem reading classpath resources * @throws InstantiationException if a class declared in a service list can * not be instantiated * @throws IllegalAccessException if a class declared in a service list is * not public or does not have a publicly visible default constructor * @throws ClassNotFoundException if a class declared in a service list is * not found * @throws ClassCastException if a class declared in a service list does * not implement the {@link BaseMetaobjectProtocol} interface. */ public static BaseMetaobjectProtocol[] discoverBaseMetaobjectProtocols() throws IOException, InstantiationException, IllegalAccessException, ClassNotFoundException { return discoverBaseMetaobjectProtocols(Thread.currentThread().getContextClassLoader()); } /** * Returns an instance of all metaobject protocol classes that are declared * in the /META-INF/services/org.dynalang.mop.BaseMetaobjectProtocol * resources of all JAR files in the specified class loader's classpath. * @param cl the class loader within which the MOPs are discovered. null * can be used to denote the {@link ClassLoader#getSystemClassLoader() * system class loader}. * @return an array of base MOPs. The returned array can be empty. You will * probably want to run the return value through. * {@link MetaobjectProtocolAdaptor#toMetaobjectProtocols(BaseMetaobjectProtocol[])} * if your code uses the full MOP interface instead of the base one. * @throws IOException if there is a problem reading classpath resources * @throws InstantiationException if a class declared in a service list can * not be instantiated * @throws IllegalAccessException if a class declared in a service list is * not public or does not have a publicly visible default constructor * @throws ClassNotFoundException if a class declared in a service list is * not found * @throws ClassCastException if a class declared in a service list does * not implement the {@link BaseMetaobjectProtocol} interface. */ public static BaseMetaobjectProtocol[] discoverBaseMetaobjectProtocols(ClassLoader cl) throws IOException, InstantiationException, IllegalAccessException, ClassNotFoundException { List protocols = new LinkedList(); Enumeration urls; if(cl == null) { urls = ClassLoader.getSystemResources(RESOURCE_PATH); cl = ClassLoader.getSystemClassLoader(); } else { urls = cl.getResources(RESOURCE_PATH); } for(;urls.hasMoreElements();) { URL url = urls.nextElement(); InputStream in = url.openStream(); try { BufferedReader r = new BufferedReader(new InputStreamReader(in)); for(;;) { String className = r.readLine(); if(className == null) { break; } className = className.trim(); if("".equals(className) || className.startsWith("#")) { continue; } protocols.add((BaseMetaobjectProtocol)Class.forName( className.toString(), true, cl).newInstance()); } } finally { in.close(); } } return protocols.toArray(new BaseMetaobjectProtocol[protocols.size()]); } }dynalang-0.4/mop/src/org/dynalang/mop/impl/BottomMetaobjectProtocol.java0000644000175000017500000000354110724016017026442 0ustar twernertwernerpackage org.dynalang.mop.impl; import java.util.Iterator; import java.util.Map; import java.util.NoSuchElementException; import java.util.Map.Entry; import org.dynalang.mop.CallProtocol; /** * An implementation for "bottom" metaobject protocol, one that returns * authoritative answer for all methods, and claims nonexistence (and * non-callability) for everything. Useful as a last element in a composite * metaobject protocol if the user of the composite metaobject protocol is not * able or not willing to deal with non-authoritative answers. * @author Attila Szegedi * @version $Id: $ */ public class BottomMetaobjectProtocol extends MetaobjectProtocolBase { public Object call(Object callable, CallProtocol callProtocol, Map args) { return Result.notCallable; } public Object call(Object callable, CallProtocol callProtocol, Object... args) { return Result.notCallable; } public Result delete(Object target, Object propertyId) { return Result.doesNotExist; } public Object get(Object target, Object propertyId) { return Result.doesNotExist; } public Boolean has(Object target, Object propertyId) { return Boolean.FALSE; } public Iterator properties(Object target) { return new Iterator() { public boolean hasNext() { return false; } public Entry next() { throw new NoSuchElementException(); } public void remove() { throw new NoSuchElementException(); } }; } public Result put(Object target, Object propertyId, Object value, CallProtocol callProtocol) { return Result.doesNotExist; } public Object representAs(Object object, Class targetClass) { return Result.noRepresentation; } } dynalang-0.4/mop/src/org/dynalang/mop/impl/CompositeClassBasedMetaobjectProtocol.java0000644000175000017500000002137711011340743031070 0ustar twernertwernerpackage org.dynalang.mop.impl; import java.io.Serializable; import java.util.Collections; import java.util.Iterator; import java.util.LinkedList; import java.util.List; import java.util.Map; import java.util.Map.Entry; import java.util.concurrent.ConcurrentHashMap; import org.dynalang.classtoken.ClassToken; import org.dynalang.classtoken.ClassTokenInvalidatedEvent; import org.dynalang.classtoken.ClassTokenListener; import org.dynalang.mop.CallProtocol; import org.dynalang.mop.ClassBasedMetaobjectProtocol; import org.dynalang.mop.MetaobjectProtocol; /** * A MOP that is composed of {@link ClassBasedMetaobjectProtocol} instances. * Every operation is dispatched first to the the first member that claims * authority over the class of the target object. If it returns a * non-authoritative answer the operation is also dispatched (where reasonable) * to the first member that claims authority over the class of the property id * object. * @author Attila Szegedi * @version $Id: $ */ public class CompositeClassBasedMetaobjectProtocol implements ClassBasedMetaobjectProtocol, Serializable { private static final long serialVersionUID = 1L; private final ClassBasedMetaobjectProtocol[] members; private final Map mops = new ConcurrentHashMap(); /** * Optimizes a list of MOPs. If a group of adjacent MOPs in the list all * implement {@link ClassBasedMetaobjectProtocol}, they will be replaced * with a single instance of {@link CompositeClassBasedMetaobjectProtocol} * that contains them. * @param mops the list of MOPs to optimize * @return the optimized list */ public static MetaobjectProtocol[] optimize(MetaobjectProtocol[] mops) { List lmops = new LinkedList(); List cbmops = new LinkedList(); for (MetaobjectProtocol protocol : mops) { if(protocol instanceof ClassBasedMetaobjectProtocol) { cbmops.add((ClassBasedMetaobjectProtocol)protocol); } else { addClassBased(lmops, cbmops); lmops.add(protocol); } } addClassBased(lmops, cbmops); return lmops.toArray(new MetaobjectProtocol[lmops.size()]); } private static void addClassBased(List lmops, List cbmops) { switch(cbmops.size()) { case 0: { break; } case 1: { lmops.addAll(cbmops); lmops.clear(); break; } default: { lmops.add(new CompositeClassBasedMetaobjectProtocol( cbmops.toArray( new ClassBasedMetaobjectProtocol[cbmops.size()]))); cbmops.clear(); break; } } } /** * Creates a new composite class-based metaobject protocol from the * specified members. * @param members the member metaobject protocols. */ public CompositeClassBasedMetaobjectProtocol(ClassBasedMetaobjectProtocol[] members) { this.members = members.clone(); ClassToken.addClassRefListener(new ClassTokenListener() { public void classTokenInvalidated(ClassTokenInvalidatedEvent e) { mops.remove(e.getClassTokens()); } }); } private ClassBasedMetaobjectProtocol getMop(Object obj) { return obj == null ? null : getMop(obj.getClass()); } private ClassBasedMetaobjectProtocol getMop(Class clazz) { ClassToken token = ClassToken.forClass(clazz); ClassBasedMetaobjectProtocol mop = mops.get(token); if(mop == null) { // Interrogate MOPs in order to see which has authority for (ClassBasedMetaobjectProtocol protocol : members) { if(protocol.isAuthoritativeForClass(clazz)) { mops.put(token, protocol); return protocol; } } mops.put(token, this); return this; } return mop == this ? null : mop; } public boolean isAuthoritativeForClass(Class clazz) { return getMop(clazz) != null; } public Object call(Object callable, CallProtocol callProtocol, Map args) { MetaobjectProtocol mop = getMop(callable); if(mop != null) { return mop.call(callable, callProtocol, args); } return Result.noAuthority; } public Object call(Object target, Object callableId, CallProtocol callProtocol, Map args) { MetaobjectProtocol mop = getMop(target); Object result = Result.noAuthority; if(mop != null) { result = mop.call(target, callableId, callProtocol, args); } if(result == Result.noAuthority) { mop = getMop(callableId); if(mop != null) { return mop.call(target, callableId, callProtocol, args); } } return result; } public Object call(Object target, Object callableId, CallProtocol callProtocol, Object... args) { MetaobjectProtocol mop = getMop(target); Object result = Result.noAuthority; if(mop != null) { result = mop.call(target, callableId, callProtocol, args); } if(result == Result.noAuthority) { mop = getMop(callableId); if(mop != null) { return mop.call(target, callableId, callProtocol, args); } } return result; } public Object call(Object callable, CallProtocol callProtocol, Object... args) { MetaobjectProtocol mop = getMop(callable); if(mop != null) { return mop.call(callable, callProtocol, args); } return Result.noAuthority; } public Result delete(Object target, long propertyId) { MetaobjectProtocol mop = getMop(target); if(mop != null) { return mop.delete(target, propertyId); } return Result.noAuthority; } public Result delete(Object target, Object propertyId) { MetaobjectProtocol mop = getMop(target); Result result = Result.noAuthority; if(mop != null) { result = mop.delete(target, propertyId); } if(result == Result.noAuthority) { mop = getMop(propertyId); if(mop != null) { return mop.delete(target, propertyId); } } return result; } public Object get(Object target, long propertyId) { MetaobjectProtocol mop = getMop(target); if(mop != null) { return mop.get(target, propertyId); } return Result.noAuthority; } public Object get(Object target, Object propertyId) { MetaobjectProtocol mop = getMop(target); Object result = Result.noAuthority; if(mop != null) { result = mop.get(target, propertyId); } if(result == Result.noAuthority) { mop = getMop(propertyId); if(mop != null) { return mop.get(target, propertyId); } } return result; } public Boolean has(Object target, long propertyId) { MetaobjectProtocol mop = getMop(target); if(mop != null) { return mop.has(target, propertyId); } return null; } public Boolean has(Object target, Object propertyId) { MetaobjectProtocol mop = getMop(target); Boolean result = null; if(mop != null) { result = mop.has(target, propertyId); } if(result == null) { mop = getMop(propertyId); if(mop != null) { return mop.has(target, propertyId); } } return result; } public Iterator properties(Object target) { MetaobjectProtocol mop = getMop(target); if(mop != null) { return mop.properties(target); } return Collections.EMPTY_MAP.entrySet().iterator(); } public Iterator propertyIds(Object target) { MetaobjectProtocol mop = getMop(target); if(mop != null) { return mop.propertyIds(target); } return Collections.EMPTY_MAP.entrySet().iterator(); } public Result put(Object target, long propertyId, Object value, CallProtocol callProtocol) { MetaobjectProtocol mop = getMop(target); if(mop != null) { return mop.put(target, propertyId, value, callProtocol); } return Result.noAuthority; } public Result put(Object target, Object propertyId, Object value, CallProtocol callProtocol) { MetaobjectProtocol mop = getMop(target); Result result = Result.noAuthority; if(mop != null) { result = mop.put(target, propertyId, value, callProtocol); } if(result == Result.noAuthority) { mop = getMop(propertyId); if(mop != null) { return mop.put(target, propertyId, value, callProtocol); } } return result; } public Object representAs(Object object, Class targetClass) { MetaobjectProtocol mop = getMop(object); if(mop != null) { Object result = mop.representAs(object, targetClass); if(result != Result.noAuthority && result != Result.noRepresentation) { return result; } } mop = getMop(targetClass); if(mop != null) { return mop.representAs(object, targetClass); } return Result.noAuthority; } }dynalang-0.4/mop/src/org/dynalang/mop/impl/MetaobjectProtocolAdaptor.java0000644000175000017500000001237410724016017026574 0ustar twernertwerner/* Copyright 2007 Attila Szegedi Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ package org.dynalang.mop.impl; import java.util.Iterator; import java.util.Map; import java.util.Map.Entry; import org.dynalang.mop.BaseMetaobjectProtocol; import org.dynalang.mop.CallProtocol; import org.dynalang.mop.MetaobjectProtocol; /** * This class can turn any {@link BaseMetaobjectProtocol} into a full * {@link MetaobjectProtocol} by implementing the MOP methods using only the * Base MOP methods. The resulting MOP is fully functional (assuming the * underlying Base MOP was too), however the additional MOP methods might not * have the most optimal implementation possible. * @author Attila Szegedi * @version $Id: $ */ public class MetaobjectProtocolAdaptor implements MetaobjectProtocol { private final BaseMetaobjectProtocol bmop; /** * Constructs a new MetaobjectProtocolAdaptor that enhances the adapted * BaseMetaobjectProtocol with additional MetaobjectProtocol methods. * @param bmop the base MOP to enhance. */ public MetaobjectProtocolAdaptor(BaseMetaobjectProtocol bmop) { this.bmop = bmop; } public Object call(Object callable, CallProtocol callProtocol, Map args) { return bmop.call(callable, callProtocol, args); } public Object call(Object target, Object callableId, CallProtocol callProtocol, Map args) { Object callable = callProtocol.get(target, callableId); if(callable instanceof Result) { return callable; } return call(callable, callProtocol, args); } public Object call(Object target, Object callableId, CallProtocol callProtocol, Object... args) { Object callable = callProtocol.get(target, callableId); if(callable instanceof Result) { return callable; } return call(callable, callProtocol, args); } public Object call(Object callable, CallProtocol callProtocol, Object... args) { return bmop.call(callable, callProtocol, args); } public Result delete(Object target, long propertyId) { return delete(target, Long.valueOf(propertyId)); } public Result delete(Object target, Object propertyId) { return bmop.delete(target, propertyId); } public Object get(Object target, long propertyId) { return get(target, Long.valueOf(propertyId)); } public Object get(Object target, Object propertyId) { return bmop.get(target, propertyId); } public Boolean has(Object target, long propertyId) { return has(target, Long.valueOf(propertyId)); } public Boolean has(Object target, Object propertyId) { return bmop.has(target, propertyId); } public Iterator properties(Object target) { return bmop.properties(target); } public Iterator propertyIds(Object target) { final Iterator it = properties(target); return new Iterator() { public boolean hasNext() { return it.hasNext(); } public Object next() { return it.next().getKey(); } public void remove() { it.remove(); } }; } public Result put(Object target, long propertyId, Object value, CallProtocol callProtocol) { return put(target, Long.valueOf(propertyId), value, callProtocol); } public Result put(Object target, Object propertyId, Object value, CallProtocol callProtocol) { return bmop.put(target, propertyId, value, callProtocol); } public Object representAs(Object object, Class targetClass) { return bmop.representAs(object, targetClass); } /** * Takes an array of base MOPs and "upgrades" them to a full MOP. If any * element of the input array is already a full mop, it is left unchanged. * If it is a base MOP, it is wrapped in an instance of * {@link MetaobjectProtocolAdaptor}. * @param protocols the input array of base MOPs * @return an array of full MOPs. */ public static MetaobjectProtocol[] toMetaobjectProtocols(BaseMetaobjectProtocol[] protocols) { MetaobjectProtocol[] protocols2 = new MetaobjectProtocol[protocols.length]; for (int i = 0; i < protocols.length; i++) { BaseMetaobjectProtocol protocol = protocols[i]; if(protocol instanceof MetaobjectProtocol) { protocols2[i] = (MetaobjectProtocol)protocol; } else { protocols2[i] = new MetaobjectProtocolAdaptor(protocol); } } return protocols2; } } dynalang-0.4/mop/src/org/dynalang/mop/impl/CompositeUniqueIterator.java0000644000175000017500000000412411063166757026335 0ustar twernertwerner/* Copyright 2007 Attila Szegedi Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ package org.dynalang.mop.impl; import java.util.HashSet; import java.util.Iterator; import java.util.LinkedList; import java.util.Set; class CompositeUniqueIterator implements Iterator { private final Set seenValues = new HashSet(); private final LinkedList> iterators = new LinkedList>(); private Iterator curr; private T next; private boolean needSeek = true; CompositeUniqueIterator(Iterator i1, Iterator i2) { assert i1 != null; assert i2 != null; curr = i1; iterators.add(i2); } void add(Iterator it) { assert it != null; iterators.add(it); } public boolean hasNext() { seekIfNeeded(); return !needSeek; } public T next() { seekIfNeeded(); needSeek = true; return next; } public void remove() { curr.remove(); } private void seekIfNeeded() { if(needSeek) { for(;;) { while(curr.hasNext()) { next = curr.next(); if(seenValues.add(getKey(next))) { needSeek = false; return; } } if(iterators.isEmpty()) { return; } curr = iterators.removeFirst(); } } } Object getKey(Object value) { return value; } }dynalang-0.4/mop/src/org/dynalang/mop/collections/0000755000175000017500000000000011425436177022201 5ustar twernertwernerdynalang-0.4/mop/src/org/dynalang/mop/collections/package.html0000644000175000017500000000106310716323073024452 0ustar twernertwerner

This package defines metaobject protocol implementations that expose standard Java lists and maps as dynamic objects, with the usually expected semantics (lists act as number-indexed associative arrays, maps act as generic associative arrays). These MOPs don't provide access to Java methods of lists and maps. You would want to combine them in a composite MOP with a {@link org.dynalang.mop.beans.BeansMetaobjectProtocol beans MOP} to achieve that effect.

dynalang-0.4/mop/src/org/dynalang/mop/collections/ListMetaobjectProtocol.java0000644000175000017500000003051310726276644027505 0ustar twernertwernerpackage org.dynalang.mop.collections; import java.util.Collections; import java.util.Iterator; import java.util.List; import java.util.ListIterator; import java.util.Map; import java.util.Map.Entry; import org.dynalang.mop.BaseMetaobjectProtocol; import org.dynalang.mop.ClassBasedMetaobjectProtocol; import org.dynalang.mop.CallProtocol; /** * A metaobject protocol that knows how to manipulate Java lists. * @author Attila Szegedi * @version $Id: $ */ public class ListMetaobjectProtocol implements ClassBasedMetaobjectProtocol { public boolean isAuthoritativeForClass(Class clazz) { return List.class.isAssignableFrom(clazz); } /** * @return {@link BaseMetaobjectProtocol.Result#noAuthority} as this MOP has no concept of callables */ public Object call(Object callable, CallProtocol callProtocol, Map args) { return Result.noAuthority; } /** * @return {@link BaseMetaobjectProtocol.Result#noAuthority} as this MOP has no concept of callables */ public Object call(Object callable, CallProtocol callProtocol, Object... args) { return Result.noAuthority; } /** * @return {@link BaseMetaobjectProtocol.Result#noAuthority} as this MOP has no concept of callables */ public Object call(Object target, Object callableId, CallProtocol callProtocol, Object... args) { return Result.noAuthority; } /** * @return {@link BaseMetaobjectProtocol.Result#noAuthority} as this MOP has no concept of callables */ public Object call(Object target, Object callableId, CallProtocol callProtocol, Map args) { return Result.noAuthority; } /** * Handles the delete attempt from the list. Note that the list semantics * actually don't allow an element to be deleted from it. * @param target the list to remove element from * @param propertyId the numeric index of the element * @return If the index is within the bounds of the target list, * {@link BaseMetaobjectProtocol.Result#notDeleteable} is returned. If the index is out of * bounds, or the target is not a list, {@link BaseMetaobjectProtocol.Result#noAuthority} * is returned. */ public Result delete(Object target, long propertyId) { if(target instanceof List) { if(isWithinBounds(propertyId, ((List)target))) { return Result.notDeleteable; } } return Result.noAuthority; } /** * Handles the delete attempt from the list. Note that the list semantics * actually don't allow an element to be deleted from it. * @param target the list to remove element from * @param propertyId the numeric index of the element * @return If the index is a number, and it is within the bounds of the * list, {@link BaseMetaobjectProtocol.Result#notDeleteable} is returned. * If the index is out of bounds, or the target is not a list, * {@link BaseMetaobjectProtocol.Result#noAuthority} is returned. */ public Result delete(Object target, Object propertyId) { if(propertyId instanceof Number) { return delete(target, ((Number)propertyId).longValue()); } return Result.noAuthority; } /** * Retrieves a value from the list. * @param target the list to retrieve from * @param propertyId the numeric index of the element * @return If the list contains the element, returns it. If the index is * out of bounds, or the target is not a list, * {@link BaseMetaobjectProtocol.Result#noAuthority} is returned. */ public Object get(Object target, long propertyId) { if(target instanceof List) { List l = (List)target; if(isWithinBounds(propertyId, l)) { return l.get((int)propertyId); } } return Result.noAuthority; } /** * Retrieves a value from the list. * @param target the list to retrieve from * @param propertyId the numeric index of the element * @return If the list contains the element at the index * {@link Number#longValue()}, returns it. If the index is out of bounds, * or it is not an instance of {@link Number}, or the target is not a list, * {@link BaseMetaobjectProtocol.Result#noAuthority} is returned. */ public Object get(Object target, Object propertyId) { if(propertyId instanceof Number) { return get(target, ((Number)propertyId).longValue()); } return Result.noAuthority; } /** * Tells whether the index is valid for the list. * @param target the list * @param propertyId the index * @return if propertyId is a valid index for this list, returns * {@link Boolean#TRUE}. If it is not valid, or the target is not a list, * returns null (meaning, no authority). */ public Boolean has(Object target, long propertyId) { if(target instanceof List) { return isWithinBounds(propertyId, (List)target) ? Boolean.TRUE : null; } return null; } /** * Tells whether the index is valid for the list. * @param target the list * @param propertyId the index * @return if {@link Number#longValue()} of propertyId is a valid index for * this list, returns {@link Boolean#TRUE}. If it is not valid, or the * target is not a list, or propertyId is not a {@link Number}, returns * null (meaning, no authority). */ public Boolean has(Object target, Object propertyId) { if(propertyId instanceof Number) { return has(target, ((Number)propertyId).longValue()); } return null; } /** * Returns mappings from indexes to elements for a list. * @param target the list * @return an iterator of map entries, keys being {@link Integer} objects. * The iterator does not support removal. */ public Iterator properties(final Object target) { if(!(target instanceof List)) { return Collections.EMPTY_MAP.entrySet().iterator(); } return new Iterator() { int i = 0; final ListIterator it = ((List)target).listIterator(); public boolean hasNext() { return it.hasNext(); } public Entry next() { final int key = i++; return new Entry() { Object value = it.next(); @Override public boolean equals(Object obj) { if(obj instanceof Entry) { Entry e = (Entry)obj; return (value == null ? e.getValue() == null : value.equals(e.getValue())) && (Integer.valueOf(key).equals(e.getKey())); } return false; } public Object getKey() { return key; } public Object getValue() { // TODO Auto-generated method stub return value; } @Override public int hashCode() { return key ^ (value == null ? 0 : value.hashCode()); } public Object setValue(Object value) { if(i == key + 1) { // optimal way that doesn't invalidate iterator, // used if the iterator hasn't moved yet, i.e. if // this method is called from within the loop that // traverses the list using the iterator Object oldValue = this.value; it.set(value); this.value = value; return oldValue; } else { // Less optimal way that quite likely invalidates // the iterator, used if the iterator already // moved. Usually, this means the entry is accessed // outside the traversing loop, so it fortunately // won't cause concurrent modification exception. return ((List)target).set(key, value); } } }; } public void remove() { throw new UnsupportedOperationException(); } }; } /** * Returns an iterator over all indexes in a list * @param target the list * @return an iterator of valid indexes ({@link Integer} objects). * The iterator does not support removal. */ public Iterator propertyIds(final Object target) { if(!(target instanceof List)) { return Collections.emptySet().iterator(); } return new Iterator() { int i = 0; Iterator it = ((List)target).iterator(); public boolean hasNext() { return it.hasNext(); } public Integer next() { it.next(); return i++; } public void remove() { throw new UnsupportedOperationException(); } }; } /** * Puts an element into the list. * @param target the list to put the element into * @param propertyId the numeric index of the element * @param callProtocol not used * @return {@link BaseMetaobjectProtocol.Result#ok} if the put was successful. If the list is * read-only (throws a {@link UnsupportedOperationException} on put * attempt), {@link BaseMetaobjectProtocol.Result#notWritable} is returned. If the index is * out of bounds, or the target is not a list, {@link BaseMetaobjectProtocol.Result#noAuthority} * is returned. If the list throws {@link ClassCastException} (because it * is limited in types of values it can accept), * {@link BaseMetaobjectProtocol.Result#noRepresentation} is returned. */ public Result put(Object target, long propertyId, Object value, CallProtocol callProtocol) { if(target instanceof List) { List l = (List)target; if(isWithinBounds(propertyId, l)) { try { l.set((int)propertyId, value); return Result.ok; } catch(ClassCastException e) { return Result.noRepresentation; } catch(UnsupportedOperationException e) { return Result.notWritable; } } } return Result.noAuthority; } /** * Puts an element into the list. * @param target the list to put the element into * @param propertyId the numeric index of the element. If this argument is * a {@link Number}, it's {@link Number#longValue()} method is used. * @param callProtocol not used * @return {@link BaseMetaobjectProtocol.Result#ok} if the put was successful. If the list is * read-only (throws a {@link UnsupportedOperationException} on put * attempt), {@link BaseMetaobjectProtocol.Result#notWritable} is returned. If the index is * out of bounds, or is not a {@link Number}, or the target is not a list, * {@link BaseMetaobjectProtocol.Result#noAuthority} is returned. If the list throws * {@link ClassCastException} (because it is limited in types of values it * can accept), {@link BaseMetaobjectProtocol.Result#noRepresentation} is returned. */ public Result put(Object target, Object propertyId, Object value, CallProtocol callProtocol) { if(propertyId instanceof Number) { return put(target, ((Number)propertyId).longValue(), value, callProtocol); } return Result.noAuthority; } /** * @return {@link BaseMetaobjectProtocol.Result#noAuthority} as this MOP has no concept of type * conversion */ public Object representAs(Object object, Class targetClass) { return Result.noAuthority; } private static boolean isWithinBounds(long propertyId, List l) { return propertyId >= 0 && propertyId < l.size(); } }dynalang-0.4/mop/src/org/dynalang/mop/collections/MapMetaobjectProtocol.java0000644000175000017500000001742210724016017027273 0ustar twernertwernerpackage org.dynalang.mop.collections; import java.util.Collections; import java.util.Iterator; import java.util.Map; import java.util.Map.Entry; import org.dynalang.mop.BaseMetaobjectProtocol; import org.dynalang.mop.ClassBasedMetaobjectProtocol; import org.dynalang.mop.CallProtocol; import org.dynalang.mop.impl.MetaobjectProtocolBase; /** * A metaobject protocol that knows how to manipulate Java maps. Operates on * all keys present in the map, and returns {@link BaseMetaobjectProtocol.Result#noAuthority} for * keys not present (thus allowing fallback to other navigators below it). * @author Attila Szegedi * @version $Id: $ */ public class MapMetaobjectProtocol extends MetaobjectProtocolBase implements ClassBasedMetaobjectProtocol{ public boolean isAuthoritativeForClass(Class clazz) { return Map.class.isAssignableFrom(clazz); } /** * @return {@link BaseMetaobjectProtocol.Result#noAuthority} as this MOP * has no concept of callables */ public Object call(Object callable, CallProtocol callProtocol, Map args) { return Result.noAuthority; } /** * @return {@link BaseMetaobjectProtocol.Result#noAuthority} as this MOP * has no concept of callables */ public Object call(Object callable, CallProtocol callProtocol, Object... args) { return Result.noAuthority; } /** * Removes a key-value mapping from the map. * @param target the map to remove element from * @param propertyId the map key * @return {@link BaseMetaobjectProtocol.Result#ok} if the removal was successful. If the map is * read-only (throws a {@link UnsupportedOperationException} on removal * attempt), {@link BaseMetaobjectProtocol.Result#notDeleteable} is returned. If the map does not * contain the key, or it throws a {@link NullPointerException} for a null * key, or the target is not a map, {@link BaseMetaobjectProtocol.Result#noAuthority} is * returned. */ public Result delete(Object target, Object propertyId) { if(target instanceof Map) { Map m = (Map)target; try { if(m.containsKey(propertyId)) { try { m.remove(propertyId); return Result.ok; } catch(UnsupportedOperationException e) { // Read-only map return Result.notDeleteable; } } } catch(NullPointerException e) { if(propertyId == null) { // Map implementation doesn't handle null return Result.noAuthority; } // key was not null -- probably a bug in the map implementation throw e; } } return Result.noAuthority; } /** * Retrieves a value from the map. * @param target the map to retrieve from * @param propertyId the key for retrieval * @return If the map contains the key, returns the associated value. If * the map does not contain the key, or it throws a * {@link NullPointerException} for a null key, or the target is not a map, * {@link BaseMetaobjectProtocol.Result#noAuthority} is returned. */ public Object get(Object target, Object propertyId) { if(target instanceof Map) { Map m = (Map)target; try { if(m.containsKey(propertyId)) { return m.get(propertyId); } } catch(NullPointerException e) { if(propertyId == null) { // Map implementation doesn't handle null return Result.noAuthority; } // key was not null -- probably a bug in the map implementation throw e; } } return Result.noAuthority; } /** * Determines whether a key is present in the map. * @param target the map to test * @param propertyId the key to test for * @return If the map contains the key, returns {@link Boolean#TRUE}. If * the map does not contain the key, or it throws a * {@link NullPointerException} for a null key, or the target is not a map, * {@link BaseMetaobjectProtocol.Result#noAuthority} is returned. */ public Boolean has(Object target, Object propertyId) { if(target instanceof Map) { try { if(((Map)target).containsKey(propertyId)) { return Boolean.TRUE; } } catch(NullPointerException e) { if(propertyId == null) { // Map implementation doesn't handle null return null; } // key was not null -- probably a bug in the map implementation throw e; } } return null; } /** * Retrieves the mappings in the map. * @param target the map whose mappings are retrieved * @return the iterator over the entry set of the map, or empty iterator if * the target is not a map. */ public Iterator properties(Object target) { if(target instanceof Map) { return ((Map)target).entrySet().iterator(); } return Collections.EMPTY_MAP.entrySet().iterator(); } /** * Binds a key-value pair into the map. * @param target the map where to bind the new mapping * @param propertyId the mapping key * @param value the mapped value * @param callProtocol not used * @return {@link BaseMetaobjectProtocol.Result#ok} if the binding was successful. If the map is * read-only (throws a {@link UnsupportedOperationException} on put * attempt), {@link BaseMetaobjectProtocol.Result#notWritable} is returned. If the map does not * contain the key, or it throws a {@link NullPointerException} for a null * key or null value, or the target is not a map, * {@link BaseMetaobjectProtocol.Result#noAuthority} is returned. If the map throws * {@link ClassCastException} (because it is limited in types of values it * can accept), {@link BaseMetaobjectProtocol.Result#noRepresentation} is returned. */ public Result put(Object target, Object propertyId, Object value, CallProtocol callProtocol) { if(target instanceof Map) { try { ((Map)target).put(propertyId, value); return Result.ok; } catch(NullPointerException e) { if(propertyId == null) { // Map implementation doesn't handle null keys return Result.noAuthority; } else if(value == null) { // Can't store null value in the map return Result.noRepresentation; } else { // Neither propertyId nor value was null, but we still have // a NPE -- probably a bug in the map implementation, so // make sure we don't hide it. throw e; } } catch(ClassCastException e) { // Map only accepts limited types, but we can't know what ones // so we can't attempt to marshal it return Result.noRepresentation; } catch(UnsupportedOperationException e) { // Read-only map return Result.notWritable; } } return Result.noAuthority; } /** * @return {@link BaseMetaobjectProtocol.Result#noAuthority} as this MOP has no concept of type * conversion */ public Object representAs(Object object, Class targetClass) { return Result.noAuthority; } }dynalang-0.4/mop/src/org/dynalang/classtoken/0000755000175000017500000000000011425436177021236 5ustar twernertwernerdynalang-0.4/mop/src/org/dynalang/classtoken/ClassTokenInvalidatedEvent.java0000644000175000017500000000137610763766762027337 0ustar twernertwernerpackage org.dynalang.classtoken; import java.util.EventObject; /** * Event that is fired sometime (no later than next invocation of * {@link ClassToken#forClass(Class)})after one or more class tokens becomes * invalid (the classes they represent became less than weakly reachable). * @author Attila Szegedi * @version $Id: $ */ public class ClassTokenInvalidatedEvent extends EventObject { private static final long serialVersionUID = 1L; ClassTokenInvalidatedEvent(ClassToken[] source) { super(source); } /** * Returns the class token objects that were invalidated * @return the invalidated class tokens */ public ClassToken[] getClassTokens() { return (ClassToken[])getSource(); } }dynalang-0.4/mop/src/org/dynalang/classtoken/ClassToken.java0000644000175000017500000001211310763777404024152 0ustar twernertwernerpackage org.dynalang.classtoken; import java.lang.ref.ReferenceQueue; import java.lang.ref.WeakReference; import java.util.Iterator; import java.util.LinkedList; import java.util.List; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentMap; /** * The class token is used as a surrogate representation for a * {@link java.lang.Class} object in various contexts where it is undesirable * to keep a strong reference to the Class object itself. This class guarantees * that at most one ClassToken object exists for every loaded Class object. * Holding a reference to a ClassToken does not prevent the Class object from * unloading. There is an event listener mechanism to observe when a ClassToken * becomes invalid (its associated class becomes unloaded). * @author Attila Szegedi * @version $Id: $ */ public class ClassToken { private static final ReferenceQueue> queue = new ReferenceQueue>(); private static final ConcurrentMap canonicals = new ConcurrentHashMap(); private static final List> listeners = new LinkedList>(); // This is never read - it is used solely to prevent the reference object // itself from getting garbage collected. private WeakClassRef weakClassRef; /** * Gets a class token for a given class. * @param clazz the class for which the token is requested * @return a class token for the given class. Always returns the same * ClassToken object for the same Class object, allowing ClassTokens to be * compared using identity. */ public static ClassToken forClass(Class clazz) { processClearedReferences(); ClassTokenKey tokenKey = new ClassTokenKey(clazz); ClassToken token = canonicals.get(tokenKey); if(token == null) { token = new ClassToken(); if(canonicals.putIfAbsent(tokenKey, token) == null) { token.weakClassRef = new WeakClassRef(tokenKey, token, clazz); } } return token; } /** * Adds a {@link ClassTokenListener} that will get notified whenever a * {@link ClassToken} object gets invalidated. * @param listener the listener */ public static void addClassRefListener(ClassTokenListener listener) { synchronized(listeners) { listeners.add(new WeakReference(listener)); } } /** * Removes a {@link ClassTokenListener} previously registered with the * {@link #addClassRefListener(ClassTokenListener)} method. It is not * strictly necessary to eagerly remove listeners, as this class references * its listeners weakly, and won't prevent a listener from getting garbage * collected. * @param listener the listener */ public static void removeClassRefListener(ClassTokenListener listener) { synchronized(listeners) { for (Iterator> iterator = listeners.iterator(); iterator.hasNext();) { WeakReference listenerRef = iterator.next(); ClassTokenListener refListener = listenerRef.get(); if(refListener == null || refListener == listener) { iterator.remove(); if(refListener != null) { break; } } } listeners.remove(listener); } } private static void processClearedReferences() { List list = null; for(;;) { WeakClassRef clearedWeakRef = (WeakClassRef)queue.poll(); if(clearedWeakRef == null) { break; } ClassToken token = clearedWeakRef.classToken; canonicals.remove(clearedWeakRef.classTokenKey, token); if(list == null) { list = new LinkedList(); } list.add(token); } if(list != null) { // Note: we accumulate all invalidated tokens into a single event // as it is anticipated that class unloads happen in batches so // this will be more effective than firing one event per class // token. fireClassTokenInvalidatedEvent(list.toArray( new ClassToken[list.size()])); } } private static void fireClassTokenInvalidatedEvent(ClassToken[] tokens) { ClassTokenInvalidatedEvent event = new ClassTokenInvalidatedEvent(tokens); synchronized(listeners) { for (Iterator> iterator = listeners.iterator(); iterator.hasNext();) { WeakReference listenerRef = iterator.next(); ClassTokenListener listener = listenerRef.get(); if(listener == null) { iterator.remove(); } else { listener.classTokenInvalidated(event); } } } } private static class WeakClassRef extends WeakReference> { private final ClassTokenKey classTokenKey; private final ClassToken classToken; WeakClassRef(ClassTokenKey classTokenKey, ClassToken classToken, Class clazz) { super(clazz, queue); this.classTokenKey = classTokenKey; this.classToken = classToken; } } }dynalang-0.4/mop/src/org/dynalang/classtoken/ClassTokenKey.java0000644000175000017500000000263410763777404024632 0ustar twernertwernerpackage org.dynalang.classtoken; /** * Used as the key for class token canonicalization. Relies on the fact that no * two concurrently loaded Class objects will have identical hash code, Class * uses Object.hashCode() which says "As much as is reasonably practical, the * hashCode method defined by class Object does return distinct * integers for distinct objects. (This is typically implemented by converting * the internal address of the object into an integer, but this implementation * technique is not required...)". This would actually not be required at all * if only Java would have ConcurrentWeakHashMap. * @author Attila Szegedi * @version $Id: $ */ class ClassTokenKey { private final String className; private final int classHashCode; ClassTokenKey(Class clazz) { this.className = clazz.getName(); // java.lang.Class uses Object.hashCode, which is the system identity // hash code, so no two concurrently loaded classes will have the same // value. this.classHashCode = clazz.hashCode(); } @Override public boolean equals(Object obj) { if(obj instanceof ClassTokenKey) { ClassTokenKey token = (ClassTokenKey)obj; return classHashCode == token.classHashCode && className.equals( token.className); } return false; } @Override public int hashCode() { return classHashCode; } }dynalang-0.4/mop/src/org/dynalang/classtoken/ClassTokenListener.java0000644000175000017500000000130310763766762025664 0ustar twernertwernerpackage org.dynalang.classtoken; import java.util.EventListener; /** * Interface that can be implemented in objects interested in receiving events * about class tokens. * @author Attila Szegedi * @version $Id: $ */ public interface ClassTokenListener extends EventListener { /** * This method is invoked on the listener sometime (no later than next * invocation of {@link ClassToken#forClass(Class)}) after one or more * class tokens become invalid (the classes they represent became less than * weakly reachable). * @param e the event object describing the event */ public void classTokenInvalidated(ClassTokenInvalidatedEvent e); } dynalang-0.4/ivy/0000755000175000017500000000000011425436176013730 5ustar twernertwernerdynalang-0.4/ivy/ivysettings.properties0000644000175000017500000000006311011556627020430 0ustar twernertwernerrepository.dir=${ivy.settings.dir}/build/repositorydynalang-0.4/ivy/ivysettings.xml0000644000175000017500000000113411011556627017034 0ustar twernertwerner dynalang-0.4/build.xml0000644000175000017500000000103411011561313014717 0ustar twernertwerner