Formatted code

Added Eclipse formatter and cleanup configuration
This commit is contained in:
Patrick Gotthard 2013-10-12 15:04:12 +02:00
parent ebcf32caea
commit 6ac4408ddf
43 changed files with 1196 additions and 963 deletions

56
cleanup.xml Normal file
View file

@ -0,0 +1,56 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<profiles version="2">
<profile kind="CleanUpProfile" name="ROME" version="2">
<setting id="cleanup.remove_unused_private_fields" value="true"/>
<setting id="cleanup.always_use_parentheses_in_expressions" value="false"/>
<setting id="cleanup.never_use_blocks" value="false"/>
<setting id="cleanup.remove_unused_private_methods" value="true"/>
<setting id="cleanup.add_missing_deprecated_annotations" value="true"/>
<setting id="cleanup.convert_to_enhanced_for_loop" value="true"/>
<setting id="cleanup.remove_unnecessary_nls_tags" value="true"/>
<setting id="cleanup.sort_members" value="false"/>
<setting id="cleanup.remove_unused_local_variables" value="false"/>
<setting id="cleanup.never_use_parentheses_in_expressions" value="true"/>
<setting id="cleanup.remove_unused_private_members" value="false"/>
<setting id="cleanup.remove_unnecessary_casts" value="true"/>
<setting id="cleanup.make_parameters_final" value="true"/>
<setting id="cleanup.use_this_for_non_static_field_access" value="true"/>
<setting id="cleanup.remove_private_constructors" value="true"/>
<setting id="cleanup.use_blocks" value="true"/>
<setting id="cleanup.always_use_this_for_non_static_method_access" value="false"/>
<setting id="cleanup.remove_trailing_whitespaces_all" value="true"/>
<setting id="cleanup.always_use_this_for_non_static_field_access" value="false"/>
<setting id="cleanup.use_this_for_non_static_field_access_only_if_necessary" value="true"/>
<setting id="cleanup.add_default_serial_version_id" value="true"/>
<setting id="cleanup.make_type_abstract_if_missing_method" value="false"/>
<setting id="cleanup.qualify_static_member_accesses_through_subtypes_with_declaring_class" value="true"/>
<setting id="cleanup.make_variable_declarations_final" value="true"/>
<setting id="cleanup.add_missing_nls_tags" value="false"/>
<setting id="cleanup.format_source_code" value="true"/>
<setting id="cleanup.qualify_static_method_accesses_with_declaring_class" value="false"/>
<setting id="cleanup.add_missing_override_annotations" value="true"/>
<setting id="cleanup.remove_unused_private_types" value="true"/>
<setting id="cleanup.add_missing_methods" value="false"/>
<setting id="cleanup.make_local_variable_final" value="true"/>
<setting id="cleanup.correct_indentation" value="true"/>
<setting id="cleanup.add_missing_override_annotations_interface_methods" value="true"/>
<setting id="cleanup.remove_unused_imports" value="true"/>
<setting id="cleanup.remove_trailing_whitespaces_ignore_empty" value="false"/>
<setting id="cleanup.make_private_fields_final" value="true"/>
<setting id="cleanup.add_generated_serial_version_id" value="false"/>
<setting id="cleanup.organize_imports" value="true"/>
<setting id="cleanup.remove_trailing_whitespaces" value="true"/>
<setting id="cleanup.sort_members_all" value="false"/>
<setting id="cleanup.use_blocks_only_for_return_and_throw" value="false"/>
<setting id="cleanup.add_missing_annotations" value="true"/>
<setting id="cleanup.use_parentheses_in_expressions" value="true"/>
<setting id="cleanup.qualify_static_field_accesses_with_declaring_class" value="false"/>
<setting id="cleanup.use_this_for_non_static_method_access_only_if_necessary" value="true"/>
<setting id="cleanup.use_this_for_non_static_method_access" value="true"/>
<setting id="cleanup.qualify_static_member_accesses_through_instances_with_declaring_class" value="true"/>
<setting id="cleanup.add_serial_version_id" value="false"/>
<setting id="cleanup.format_source_code_changes_only" value="false"/>
<setting id="cleanup.qualify_static_member_accesses_with_declaring_class" value="true"/>
<setting id="cleanup.always_use_blocks" value="true"/>
</profile>
</profiles>

291
formatter.xml Normal file
View file

@ -0,0 +1,291 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<profiles version="12">
<profile kind="CodeFormatterProfile" name="ROME" version="12">
<setting id="org.eclipse.jdt.core.formatter.comment.insert_new_line_before_root_tags" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.disabling_tag" value="@formatter:off"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_annotation" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_type_parameters" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_type_declaration" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_type_arguments" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.brace_position_for_anonymous_type_declaration" value="end_of_line"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_colon_in_case" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_brace_in_array_initializer" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.comment.new_lines_at_block_boundaries" value="true"/>
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_in_empty_annotation_declaration" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_before_closing_brace_in_array_initializer" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_annotation" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.blank_lines_before_field" value="0"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_while" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.use_on_off_tags" value="false"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_annotation_type_member_declaration" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_before_else_in_if_statement" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_prefix_operator" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.keep_else_statement_on_same_line" value="false"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_ellipsis" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.comment.insert_new_line_for_parameter" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_annotation_type_declaration" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.indent_breaks_compare_to_cases" value="true"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_at_in_annotation" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.alignment_for_multiple_fields" value="16"/>
<setting id="org.eclipse.jdt.core.formatter.alignment_for_expressions_in_array_initializer" value="16"/>
<setting id="org.eclipse.jdt.core.formatter.alignment_for_conditional_expression" value="80"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_for" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_binary_operator" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_question_in_wildcard" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.brace_position_for_array_initializer" value="end_of_line"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_enum_constant" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_before_finally_in_try_statement" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_local_variable" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_before_catch_in_try_statement" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_while" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.blank_lines_after_package" value="1"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_type_parameters" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.continuation_indentation" value="2"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_postfix_operator" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.alignment_for_arguments_in_method_invocation" value="16"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_angle_bracket_in_type_arguments" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_superinterfaces" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.blank_lines_before_new_chunk" value="1"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_binary_operator" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.blank_lines_before_package" value="0"/>
<setting id="org.eclipse.jdt.core.compiler.source" value="1.7"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_enum_constant_arguments" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_constructor_declaration" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.comment.format_line_comments" value="true"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_closing_angle_bracket_in_type_arguments" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_enum_declarations" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.join_wrapped_lines" value="true"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_block" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.alignment_for_arguments_in_explicit_constructor_call" value="16"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_method_invocation_arguments" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.blank_lines_before_member_type" value="1"/>
<setting id="org.eclipse.jdt.core.formatter.align_type_members_on_columns" value="false"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_enum_constant" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_for" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_method_declaration" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.alignment_for_selector_in_method_invocation" value="16"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_switch" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_unary_operator" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_colon_in_case" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.comment.indent_parameter_description" value="true"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_method_declaration" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_switch" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_enum_declaration" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_angle_bracket_in_type_parameters" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.comment.clear_blank_lines_in_block_comment" value="true"/>
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_in_empty_type_declaration" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.lineSplit" value="160"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_if" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_between_brackets_in_array_type_reference" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_parenthesized_expression" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_explicitconstructorcall_arguments" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_constructor_declaration" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.blank_lines_before_first_class_body_declaration" value="0"/>
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_method" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.indentation.size" value="4"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_method_declaration" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.enabling_tag" value="@formatter:on"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_enum_constant" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.alignment_for_superclass_in_type_declaration" value="16"/>
<setting id="org.eclipse.jdt.core.formatter.alignment_for_assignment" value="0"/>
<setting id="org.eclipse.jdt.core.compiler.problem.assertIdentifier" value="error"/>
<setting id="org.eclipse.jdt.core.formatter.tabulation.char" value="space"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_constructor_declaration_parameters" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_semicolon_in_try_resources" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_prefix_operator" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.indent_statements_compare_to_body" value="true"/>
<setting id="org.eclipse.jdt.core.formatter.blank_lines_before_method" value="1"/>
<setting id="org.eclipse.jdt.core.formatter.wrap_outer_expressions_when_nested" value="true"/>
<setting id="org.eclipse.jdt.core.formatter.format_guardian_clause_on_one_line" value="false"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_colon_in_for" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_cast" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.alignment_for_parameters_in_constructor_declaration" value="16"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_colon_in_labeled_statement" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.brace_position_for_annotation_type_declaration" value="end_of_line"/>
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_in_empty_method_body" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.alignment_for_method_declaration" value="0"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_method_invocation" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_try" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_bracket_in_array_allocation_expression" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_enum_constant" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_annotation" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_at_in_annotation_type_declaration" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_method_declaration_throws" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_if" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.brace_position_for_switch" value="end_of_line"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_method_declaration_throws" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_parenthesized_expression_in_return" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_annotation" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_question_in_conditional" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_question_in_wildcard" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_try" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_bracket_in_array_allocation_expression" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.comment.preserve_white_space_between_code_and_line_comments" value="false"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_parenthesized_expression_in_throw" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_type_arguments" value="do not insert"/>
<setting id="org.eclipse.jdt.core.compiler.problem.enumIdentifier" value="error"/>
<setting id="org.eclipse.jdt.core.formatter.indent_switchstatements_compare_to_switch" value="true"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_ellipsis" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.brace_position_for_block" value="end_of_line"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_for_inits" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.brace_position_for_method_declaration" value="end_of_line"/>
<setting id="org.eclipse.jdt.core.formatter.compact_else_if" value="true"/>
<setting id="org.eclipse.jdt.core.formatter.wrap_before_or_operator_multicatch" value="true"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_array_initializer" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_for_increments" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.format_line_comment_starting_on_first_column" value="true"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_bracket_in_array_reference" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_field" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.comment.indent_root_tags" value="true"/>
<setting id="org.eclipse.jdt.core.formatter.brace_position_for_enum_constant" value="end_of_line"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_enum_declarations" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.alignment_for_union_type_in_multicatch" value="16"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_explicitconstructorcall_arguments" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_switch" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_method_declaration_parameters" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_superinterfaces" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_allocation_expression" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.tabulation.size" value="4"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_bracket_in_array_type_reference" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_after_opening_brace_in_array_initializer" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_closing_brace_in_block" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_bracket_in_array_reference" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_in_empty_enum_constant" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_angle_bracket_in_type_arguments" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_constructor_declaration" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_constructor_declaration_throws" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_if" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.comment.clear_blank_lines_in_javadoc_comment" value="false"/>
<setting id="org.eclipse.jdt.core.formatter.alignment_for_throws_clause_in_constructor_declaration" value="16"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_assignment_operator" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_assignment_operator" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.indent_empty_lines" value="false"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_synchronized" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_closing_paren_in_cast" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_method_declaration_parameters" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.brace_position_for_block_in_case" value="end_of_line"/>
<setting id="org.eclipse.jdt.core.formatter.number_of_empty_lines_to_preserve" value="1"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_method_declaration" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_catch" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_constructor_declaration" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_method_invocation" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_bracket_in_array_reference" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.alignment_for_arguments_in_qualified_allocation_expression" value="16"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_and_in_type_parameter" value="insert"/>
<setting id="org.eclipse.jdt.core.compiler.compliance" value="1.7"/>
<setting id="org.eclipse.jdt.core.formatter.continuation_indentation_for_array_initializer" value="2"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_between_empty_brackets_in_array_allocation_expression" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_at_in_annotation_type_declaration" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.alignment_for_arguments_in_allocation_expression" value="16"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_cast" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_unary_operator" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_angle_bracket_in_parameterized_type_reference" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_anonymous_type_declaration" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.keep_empty_array_initializer_on_one_line" value="false"/>
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_in_empty_enum_declaration" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.keep_imple_if_on_one_line" value="false"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_constructor_declaration_parameters" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_closing_angle_bracket_in_type_parameters" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_at_end_of_file_if_missing" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_colon_in_for" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_colon_in_labeled_statement" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_parameterized_type_reference" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.alignment_for_superinterfaces_in_type_declaration" value="16"/>
<setting id="org.eclipse.jdt.core.formatter.alignment_for_binary_expression" value="16"/>
<setting id="org.eclipse.jdt.core.formatter.brace_position_for_enum_declaration" value="end_of_line"/>
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_type" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_while" value="do not insert"/>
<setting id="org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode" value="enabled"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_try" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.put_empty_statement_on_new_line" value="true"/>
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_after_label" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_parameter" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_angle_bracket_in_type_parameters" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_method_invocation" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_before_while_in_do_statement" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.alignment_for_arguments_in_enum_constant" value="16"/>
<setting id="org.eclipse.jdt.core.formatter.comment.format_javadoc_comments" value="true"/>
<setting id="org.eclipse.jdt.core.formatter.comment.line_length" value="80"/>
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_package" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.blank_lines_between_import_groups" value="1"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_enum_constant_arguments" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_semicolon" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.brace_position_for_constructor_declaration" value="end_of_line"/>
<setting id="org.eclipse.jdt.core.formatter.number_of_blank_lines_at_beginning_of_method_body" value="0"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_colon_in_conditional" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_type_header" value="true"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_annotation_type_member_declaration" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.wrap_before_binary_operator" value="true"/>
<setting id="org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_enum_declaration_header" value="true"/>
<setting id="org.eclipse.jdt.core.formatter.blank_lines_between_type_declarations" value="1"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_synchronized" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.indent_statements_compare_to_block" value="true"/>
<setting id="org.eclipse.jdt.core.formatter.alignment_for_superinterfaces_in_enum_declaration" value="16"/>
<setting id="org.eclipse.jdt.core.formatter.join_lines_in_comments" value="true"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_question_in_conditional" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_multiple_field_declarations" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.alignment_for_compact_if" value="16"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_for_inits" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.indent_switchstatements_compare_to_cases" value="true"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_array_initializer" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_colon_in_default" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_and_in_type_parameter" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_constructor_declaration" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.blank_lines_before_imports" value="1"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_colon_in_assert" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.comment.format_html" value="true"/>
<setting id="org.eclipse.jdt.core.formatter.alignment_for_throws_clause_in_method_declaration" value="16"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_angle_bracket_in_type_parameters" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_bracket_in_array_allocation_expression" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_in_empty_anonymous_type_declaration" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_colon_in_conditional" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_angle_bracket_in_parameterized_type_reference" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_for" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_postfix_operator" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.comment.format_source_code" value="true"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_synchronized" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_allocation_expression" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_constructor_declaration_throws" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.alignment_for_parameters_in_method_declaration" value="16"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_brace_in_array_initializer" value="insert"/>
<setting id="org.eclipse.jdt.core.compiler.codegen.targetPlatform" value="1.7"/>
<setting id="org.eclipse.jdt.core.formatter.alignment_for_resources_in_try" value="80"/>
<setting id="org.eclipse.jdt.core.formatter.use_tabs_only_for_leading_indentations" value="true"/>
<setting id="org.eclipse.jdt.core.formatter.alignment_for_arguments_in_annotation" value="0"/>
<setting id="org.eclipse.jdt.core.formatter.comment.format_header" value="false"/>
<setting id="org.eclipse.jdt.core.formatter.comment.format_block_comments" value="true"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_enum_constant" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.alignment_for_enum_constants" value="0"/>
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_in_empty_block" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_annotation_declaration_header" value="true"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_parenthesized_expression" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_parenthesized_expression" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_catch" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_multiple_local_declarations" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_switch" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_for_increments" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_method_invocation" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_colon_in_assert" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.brace_position_for_type_declaration" value="end_of_line"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_array_initializer" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_between_empty_braces_in_array_initializer" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_method_declaration" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_semicolon_in_for" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_catch" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_angle_bracket_in_parameterized_type_reference" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_multiple_field_declarations" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_annotation" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_parameterized_type_reference" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_method_invocation_arguments" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.comment.new_lines_at_javadoc_boundaries" value="true"/>
<setting id="org.eclipse.jdt.core.formatter.blank_lines_after_imports" value="1"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_multiple_local_declarations" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_enum_constant_header" value="true"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_semicolon_in_for" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.never_indent_line_comments_on_first_column" value="false"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_semicolon_in_try_resources" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_angle_bracket_in_type_arguments" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.never_indent_block_comments_on_first_column" value="false"/>
<setting id="org.eclipse.jdt.core.formatter.keep_then_statement_on_same_line" value="false"/>
</profile>
</profiles>

View file

@ -16,24 +16,23 @@
* limitations under the License.
*/
package org.rometools.certiorem;
/**
*
*
* @author robert.cooper
*/
public class HttpStatusCodeException extends RuntimeException {
private final int status;
public HttpStatusCodeException(int status, String message, Throwable cause){
public HttpStatusCodeException(final int status, final String message, final Throwable cause) {
super(message, cause);
this.status = status;
}
public int getStatus(){
return this.status;
public int getStatus() {
return status;
}
}

View file

@ -5,33 +5,32 @@
package org.rometools.certiorem.hub;
import java.net.URL;
import org.rometools.fetcher.impl.FeedFetcherCache;
import org.rometools.fetcher.impl.SyndFeedInfo;
/**
* Wrapper FeedFetcherCache that wraps a backing FeedFetcherCache and makes sure that
* any SyndFeedInfo used within it are replaced with a DeltaSyndFeedInfo which is capable of
* tracking changes to entries in the underlying feed.
* Wrapper FeedFetcherCache that wraps a backing FeedFetcherCache and makes sure that any SyndFeedInfo used within it are replaced with a DeltaSyndFeedInfo
* which is capable of tracking changes to entries in the underlying feed.
*
* @author najmi
*/
public class DeltaFeedInfoCache implements FeedFetcherCache {
FeedFetcherCache backingCache;
public DeltaFeedInfoCache(FeedFetcherCache backingCache) {
public DeltaFeedInfoCache(final FeedFetcherCache backingCache) {
this.backingCache = backingCache;
}
@Override
public SyndFeedInfo getFeedInfo(URL feedUrl) {
public SyndFeedInfo getFeedInfo(final URL feedUrl) {
return backingCache.getFeedInfo(feedUrl);
}
@Override
public void setFeedInfo(URL feedUrl, SyndFeedInfo syndFeedInfo) {
//Make sure that syndFeedInfo is an instance of DeltaSyndFeedInfo
public void setFeedInfo(final URL feedUrl, SyndFeedInfo syndFeedInfo) {
// Make sure that syndFeedInfo is an instance of DeltaSyndFeedInfo
if (!(syndFeedInfo instanceof DeltaSyndFeedInfo)) {
syndFeedInfo = new DeltaSyndFeedInfo(syndFeedInfo);
}
@ -40,12 +39,12 @@ public class DeltaFeedInfoCache implements FeedFetcherCache {
@Override
public void clear() {
backingCache.clear();
backingCache.clear();
}
@Override
public SyndFeedInfo remove(URL feedUrl) {
public SyndFeedInfo remove(final URL feedUrl) {
return backingCache.remove(feedUrl);
}
}

View file

@ -4,8 +4,6 @@
*/
package org.rometools.certiorem.hub;
import com.sun.syndication.feed.synd.SyndEntry;
import com.sun.syndication.feed.synd.SyndFeed;
import java.math.BigInteger;
import java.security.MessageDigest;
import java.util.ArrayList;
@ -13,51 +11,55 @@ import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.rometools.fetcher.impl.SyndFeedInfo;
import com.sun.syndication.feed.synd.SyndEntry;
import com.sun.syndication.feed.synd.SyndFeed;
/**
* Extends SyndFeedInfo to also track etags for individual entries.
* This may be used with DeltaFeedInfoCache to only return feed with a subset of entries that have changed since last fetch.
* Extends SyndFeedInfo to also track etags for individual entries. This may be used with DeltaFeedInfoCache to only return feed with a subset of entries that
* have changed since last fetch.
*
* @author najmi
*/
public class DeltaSyndFeedInfo extends SyndFeedInfo {
public class DeltaSyndFeedInfo extends SyndFeedInfo {
Map<String, String> entryTagsMap = new HashMap<String, String>();
Map<String, Boolean> changedMap = new HashMap<String, Boolean>();
private DeltaSyndFeedInfo() {
private DeltaSyndFeedInfo() {
}
public DeltaSyndFeedInfo(SyndFeedInfo backingFeedInfo) {
this.setETag(backingFeedInfo.getETag());
this.setId(backingFeedInfo.getId());
this.setLastModified(backingFeedInfo.getLastModified());
this.setSyndFeed(backingFeedInfo.getSyndFeed());
public DeltaSyndFeedInfo(final SyndFeedInfo backingFeedInfo) {
setETag(backingFeedInfo.getETag());
setId(backingFeedInfo.getId());
setLastModified(backingFeedInfo.getLastModified());
setSyndFeed(backingFeedInfo.getSyndFeed());
}
/**
* Gets a filtered version of the SyndFeed that only has entries that were changed in the last setSyndFeed() call.
*
* @return
* @return
*/
@Override
public synchronized SyndFeed getSyndFeed() {
try {
SyndFeed feed = (SyndFeed) super.getSyndFeed().clone();
List<SyndEntry> changedEntries = new ArrayList<SyndEntry>();
List<SyndEntry> entries = feed.getEntries();
for (SyndEntry entry : entries) {
final SyndFeed feed = (SyndFeed) super.getSyndFeed().clone();
final List<SyndEntry> changedEntries = new ArrayList<SyndEntry>();
final List<SyndEntry> entries = feed.getEntries();
for (final SyndEntry entry : entries) {
if (changedMap.containsKey(entry.getUri())) {
changedEntries.add(entry);
changedEntries.add(entry);
}
}
feed.setEntries(changedEntries);
return feed;
} catch (CloneNotSupportedException ex) {
} catch (final CloneNotSupportedException ex) {
throw new RuntimeException(ex);
}
}
@ -65,58 +67,58 @@ public class DeltaSyndFeedInfo extends SyndFeedInfo {
/**
* Overrides super class method to update changedMap and entryTagsMap for tracking changed entries.
*
* @param feed
* @param feed
*/
@Override
public final synchronized void setSyndFeed(SyndFeed feed) {
public final synchronized void setSyndFeed(final SyndFeed feed) {
super.setSyndFeed(feed);
changedMap.clear();
List<SyndEntry> entries = feed.getEntries();
for (SyndEntry entry : entries) {
String currentEntryTag = computeEntryTag(entry);
String previousEntryTag = entryTagsMap.get(entry.getUri());
if ((previousEntryTag == null) || (!(currentEntryTag.equals(previousEntryTag)))) {
//Entry has changed
changedMap.clear();
final List<SyndEntry> entries = feed.getEntries();
for (final SyndEntry entry : entries) {
final String currentEntryTag = computeEntryTag(entry);
final String previousEntryTag = entryTagsMap.get(entry.getUri());
if (previousEntryTag == null || !currentEntryTag.equals(previousEntryTag)) {
// Entry has changed
changedMap.put(entry.getUri(), Boolean.TRUE);
}
entryTagsMap.put(entry.getUri(), currentEntryTag);
}
}
private String computeEntryTag(SyndEntry entry) {
//Following hash algorithm suggested by Robert Cooper needs to be evaluated in future.
// int hash = ( entry.getUri() != null ? entry.getUri().hashCode() : entry.getLink().hashCode() ) ^
// (entry.getUpdatedDate() != null ? entry.getUpdatedDate().hashCode() : entry.getPublishedDate().hashCode()) ^
// entry.getTitle().hashCode() ^
// entry.getDescription().hashCode();
private String computeEntryTag(final SyndEntry entry) {
String id = entry.getUri();
// Following hash algorithm suggested by Robert Cooper needs to be evaluated in future.
// int hash = ( entry.getUri() != null ? entry.getUri().hashCode() : entry.getLink().hashCode() ) ^
// (entry.getUpdatedDate() != null ? entry.getUpdatedDate().hashCode() : entry.getPublishedDate().hashCode()) ^
// entry.getTitle().hashCode() ^
// entry.getDescription().hashCode();
final String id = entry.getUri();
Date updateDate = entry.getUpdatedDate();
Date publishedDate = entry.getPublishedDate();
final Date publishedDate = entry.getPublishedDate();
if (updateDate == null) {
if (publishedDate != null) {
updateDate = publishedDate;
} else {
//For misbehaving feeds that do not set updateDate or publishedDate we use current tiem which pretty mucg assures that it will be viewed as changed even when it is not
} else {
// For misbehaving feeds that do not set updateDate or publishedDate we use current tiem which pretty mucg assures that it will be viewed as
// changed even when it is not
updateDate = new Date();
}
}
String key = id + ":" + entry.getUpdatedDate();
return computeDigest(key);
final String key = id + ":" + entry.getUpdatedDate();
return computeDigest(key);
}
private String computeDigest(String content) {
private String computeDigest(final String content) {
try {
MessageDigest md = MessageDigest.getInstance("SHA");
byte[] digest = md.digest(content.getBytes());
BigInteger bi = new BigInteger(digest);
final MessageDigest md = MessageDigest.getInstance("SHA");
final byte[] digest = md.digest(content.getBytes());
final BigInteger bi = new BigInteger(digest);
return bi.toString(16);
} catch (Exception e) {
} catch (final Exception e) {
return "";
}
}
}
}

View file

@ -18,21 +18,9 @@
package org.rometools.certiorem.hub;
import com.sun.syndication.feed.synd.SyndFeed;
import org.rometools.certiorem.HttpStatusCodeException;
import org.rometools.certiorem.hub.Notifier.SubscriptionSummaryCallback;
import org.rometools.certiorem.hub.Verifier.VerificationCallback;
import org.rometools.certiorem.hub.data.HubDAO;
import org.rometools.certiorem.hub.data.Subscriber;
import org.rometools.certiorem.hub.data.SubscriptionSummary;
import org.rometools.fetcher.FeedFetcher;
import java.net.URI;
import java.net.URISyntaxException;
import java.net.URL;
import java.util.Collections;
import java.util.HashSet;
import java.util.List;
@ -40,12 +28,20 @@ import java.util.Set;
import java.util.logging.Level;
import java.util.logging.Logger;
import org.rometools.certiorem.HttpStatusCodeException;
import org.rometools.certiorem.hub.Notifier.SubscriptionSummaryCallback;
import org.rometools.certiorem.hub.Verifier.VerificationCallback;
import org.rometools.certiorem.hub.data.HubDAO;
import org.rometools.certiorem.hub.data.Subscriber;
import org.rometools.certiorem.hub.data.SubscriptionSummary;
import org.rometools.fetcher.FeedFetcher;
import com.sun.syndication.feed.synd.SyndFeed;
/**
* The basic business logic controller for the Hub implementation. It is intended
* to be usable under a very thin servlet wrapper, or other, non-HTTP notification
* methods you might want to use.
*
* The basic business logic controller for the Hub implementation. It is intended to be usable under a very thin servlet wrapper, or other, non-HTTP
* notification methods you might want to use.
*
* @author robert.cooper
*/
public class Hub {
@ -66,6 +62,7 @@ public class Hub {
/**
* Constructs a new Hub instance
*
* @param dao The persistence HubDAO to use
* @param verifier The verification strategy to use.
*/
@ -74,122 +71,111 @@ public class Hub {
this.verifier = verifier;
this.notifier = notifier;
this.fetcher = fetcher;
this.validSchemes = STANDARD_SCHEMES;
this.validPorts = Collections.EMPTY_SET;
this.validTopics = Collections.EMPTY_SET;
validSchemes = STANDARD_SCHEMES;
validPorts = Collections.EMPTY_SET;
validTopics = Collections.EMPTY_SET;
}
/**
* Constructs a new Hub instance.
*
* @param dao The persistence HubDAO to use
* @param verifier The verification strategy to use
* @param validSchemes A list of valid URI schemes for callbacks (default: http, https)
* @param validPorts A list of valid port numbers for callbacks (default: any)
* @param validTopics A set of valid topic URIs which can be subscribed to (default: any)
*/
public Hub(final HubDAO dao, final Verifier verifier, final Notifier notifier, final FeedFetcher fetcher,
final Set<String> validSchemes, final Set<Integer> validPorts, final Set<String> validTopics) {
public Hub(final HubDAO dao, final Verifier verifier, final Notifier notifier, final FeedFetcher fetcher, final Set<String> validSchemes,
final Set<Integer> validPorts, final Set<String> validTopics) {
this.dao = dao;
this.verifier = verifier;
this.notifier = notifier;
this.fetcher = fetcher;
Set<String> readOnlySchemes = Collections.unmodifiableSet(validSchemes);
this.validSchemes = (readOnlySchemes == null) ? STANDARD_SCHEMES : readOnlySchemes;
final Set<String> readOnlySchemes = Collections.unmodifiableSet(validSchemes);
this.validSchemes = readOnlySchemes == null ? STANDARD_SCHEMES : readOnlySchemes;
Set<Integer> readOnlyPorts = Collections.unmodifiableSet(validPorts);
this.validPorts = (readOnlyPorts == null) ? Collections.EMPTY_SET : readOnlyPorts;
final Set<Integer> readOnlyPorts = Collections.unmodifiableSet(validPorts);
this.validPorts = readOnlyPorts == null ? Collections.EMPTY_SET : readOnlyPorts;
Set<String> readOnlyTopics = Collections.unmodifiableSet(validTopics);
this.validTopics = (readOnlyTopics == null) ? Collections.EMPTY_SET : readOnlyTopics;
final Set<String> readOnlyTopics = Collections.unmodifiableSet(validTopics);
this.validTopics = readOnlyTopics == null ? Collections.EMPTY_SET : readOnlyTopics;
}
/**
* Sends a notification to the subscribers
*
* @param requestHost the host name the hub is running on. (Used for the user agent)
* @param topic the URL of the topic that was updated.
* @throws HttpStatusCodeException a wrapper exception with a recommended status code for the request.
*/
public void sendNotification(String requestHost, final String topic) {
assert this.validTopics.isEmpty() || this.validTopics.contains(topic) : "That topic is not supported by this hub. " +
topic;
public void sendNotification(final String requestHost, final String topic) {
assert validTopics.isEmpty() || validTopics.contains(topic) : "That topic is not supported by this hub. " + topic;
Logger.getLogger(Hub.class.getName()).log(Level.FINE, "Sending notification for {0}", topic);
try {
List<?extends Subscriber> subscribers = dao.subscribersForTopic(topic);
final List<? extends Subscriber> subscribers = dao.subscribersForTopic(topic);
if (subscribers.isEmpty()) {
Logger.getLogger(Hub.class.getName()).log(Level.FINE, "No subscribers to notify for {0}", topic);
return;
}
List<SubscriptionSummary> summaries = (List<SubscriptionSummary>) dao.summariesForTopic(topic);
final List<SubscriptionSummary> summaries = (List<SubscriptionSummary>) dao.summariesForTopic(topic);
int total = 0;
StringBuilder hosts = new StringBuilder();
final StringBuilder hosts = new StringBuilder();
for (SubscriptionSummary s : summaries) {
for (final SubscriptionSummary s : summaries) {
if (s.getSubscribers() > 0) {
total += s.getSubscribers();
hosts.append(" (")
.append(s.getHost())
.append("; ")
.append(s.getSubscribers())
.append(" subscribers)");
hosts.append(" (").append(s.getHost()).append("; ").append(s.getSubscribers()).append(" subscribers)");
}
}
StringBuilder userAgent = new StringBuilder("ROME-Certiorem (+http://").append(requestHost)
.append("; ")
.append(total)
.append(" subscribers)")
.append(hosts);
SyndFeed feed = fetcher.retrieveFeed(userAgent.toString(), new URL(topic));
Logger.getLogger(Hub.class.getName()).log(Level.FINE, "Got feed for {0} Sending to {1} subscribers.", new Object[]{topic, subscribers.size()});
this.notifier.notifySubscribers((List<Subscriber>) subscribers, feed,
new SubscriptionSummaryCallback() {
@Override
public void onSummaryInfo(SubscriptionSummary summary) {
dao.handleSummary(topic, summary);
}
});
} catch (Exception ex) {
Logger.getLogger(Hub.class.getName())
.log(Level.SEVERE, "Exception getting " + topic, ex);
final StringBuilder userAgent = new StringBuilder("ROME-Certiorem (+http://").append(requestHost).append("; ").append(total)
.append(" subscribers)").append(hosts);
final SyndFeed feed = fetcher.retrieveFeed(userAgent.toString(), new URL(topic));
Logger.getLogger(Hub.class.getName()).log(Level.FINE, "Got feed for {0} Sending to {1} subscribers.", new Object[] { topic, subscribers.size() });
notifier.notifySubscribers((List<Subscriber>) subscribers, feed, new SubscriptionSummaryCallback() {
@Override
public void onSummaryInfo(final SubscriptionSummary summary) {
dao.handleSummary(topic, summary);
}
});
} catch (final Exception ex) {
Logger.getLogger(Hub.class.getName()).log(Level.SEVERE, "Exception getting " + topic, ex);
throw new HttpStatusCodeException(500, ex.getMessage(), ex);
}
}
/**
* Subscribes to a topic.
*
* @param callback Callback URI
* @param topic Topic URI
* @param verify Verification Type
* @param lease_seconds Duration of the lease
* @param secret Secret value
* @param verify_token verify_token;
* @return Boolean.TRUE if the subscription succeeded synchronously,
* Boolean.FALSE if the subscription failed synchronously, or null if the request is asynchronous.
* @return Boolean.TRUE if the subscription succeeded synchronously, Boolean.FALSE if the subscription failed synchronously, or null if the request is
* asynchronous.
* @throws HttpStatusCodeException a wrapper exception with a recommended status code for the request.
*/
public Boolean subscribe(String callback, String topic, String verify, long lease_seconds, String secret,
String verify_token) {
Logger.getLogger(Hub.class.getName()).log(Level.FINE, "{0} wants to subscribe to {1}", new Object[]{callback, topic});
public Boolean subscribe(final String callback, final String topic, final String verify, final long lease_seconds, final String secret,
final String verify_token) {
Logger.getLogger(Hub.class.getName()).log(Level.FINE, "{0} wants to subscribe to {1}", new Object[] { callback, topic });
try {
try {
assert callback != null : "Callback URL is required.";
assert topic != null : "Topic URL is required.";
URI uri = new URI(callback);
assert this.validSchemes.contains(uri.getScheme()) : "Not a valid protocol " + uri.getScheme();
assert this.validPorts.isEmpty() || this.validPorts.contains(uri.getPort()) : "Not a valid port " +
uri.getPort();
assert this.validTopics.isEmpty() || this.validTopics.contains(topic) : "Not a supported topic " +
topic;
} catch (URISyntaxException ex) {
final URI uri = new URI(callback);
assert validSchemes.contains(uri.getScheme()) : "Not a valid protocol " + uri.getScheme();
assert validPorts.isEmpty() || validPorts.contains(uri.getPort()) : "Not a valid port " + uri.getPort();
assert validTopics.isEmpty() || validTopics.contains(topic) : "Not a supported topic " + topic;
} catch (final URISyntaxException ex) {
assert false : "Not a valid URI " + callback;
}
assert (verify != null) &&
(verify.equals(Subscriber.VERIFY_ASYNC) || verify.equals(Subscriber.VERIFY_SYNC)) : "Unexpected verify value " +
verify;
assert verify != null && (verify.equals(Subscriber.VERIFY_ASYNC) || verify.equals(Subscriber.VERIFY_SYNC)) : "Unexpected verify value " + verify;
final Subscriber subscriber = new Subscriber();
subscriber.setCallback(callback);
@ -199,18 +185,19 @@ public class Hub {
subscriber.setVerify(verify);
subscriber.setVertifyToken(verify_token);
VerificationCallback verified = new VerificationCallback() {
@Override
public void onVerify(boolean verified) {
if (verified) {
Logger.getLogger(Hub.class.getName()).log(Level.FINE, "Verified {0} subscribed to {1}", new Object[]{subscriber.getCallback(), subscriber.getTopic()});
dao.addSubscriber(subscriber);
}
final VerificationCallback verified = new VerificationCallback() {
@Override
public void onVerify(final boolean verified) {
if (verified) {
Logger.getLogger(Hub.class.getName()).log(Level.FINE, "Verified {0} subscribed to {1}",
new Object[] { subscriber.getCallback(), subscriber.getTopic() });
dao.addSubscriber(subscriber);
}
};
}
};
if (Subscriber.VERIFY_SYNC.equals(subscriber.getVerify())) {
boolean result = verifier.verifySubcribeSyncronously(subscriber);
final boolean result = verifier.verifySubcribeSyncronously(subscriber);
verified.onVerify(result);
return result;
@ -219,33 +206,34 @@ public class Hub {
return null;
}
} catch (AssertionError ae) {
} catch (final AssertionError ae) {
throw new HttpStatusCodeException(400, ae.getMessage(), ae);
} catch (Exception e) {
} catch (final Exception e) {
throw new HttpStatusCodeException(500, e.getMessage(), e);
}
}
public Boolean unsubscribe(final String callback, final String topic, String verify, String secret, String verifyToken) {
public Boolean unsubscribe(final String callback, final String topic, final String verify, final String secret, final String verifyToken) {
final Subscriber subscriber = dao.findSubscriber(topic, callback);
if(subscriber == null){
if (subscriber == null) {
throw new HttpStatusCodeException(400, "Not a valid subscription.", null);
}
subscriber.setVertifyToken(verifyToken);
subscriber.setSecret(secret);
if(Subscriber.VERIFY_SYNC.equals(verify)){
if (Subscriber.VERIFY_SYNC.equals(verify)) {
boolean ret = verifier.verifyUnsubcribeSyncronously(subscriber);
if(ret){
final boolean ret = verifier.verifyUnsubcribeSyncronously(subscriber);
if (ret) {
dao.removeSubscriber(topic, callback);
}
} else {
verifier.verifyUnsubscribeAsyncronously(subscriber, new VerificationCallback(){
verifier.verifyUnsubscribeAsyncronously(subscriber, new VerificationCallback() {
@Override
public void onVerify(boolean verified) {
Logger.getLogger(Hub.class.getName()).log(Level.FINE, "Unsubscribe for {0} at {1} verified {2}", new Object[]{subscriber.getTopic(), subscriber.getCallback(), verified});
if(verified){
public void onVerify(final boolean verified) {
Logger.getLogger(Hub.class.getName()).log(Level.FINE, "Unsubscribe for {0} at {1} verified {2}",
new Object[] { subscriber.getTopic(), subscriber.getCallback(), verified });
if (verified) {
dao.removeSubscriber(topic, callback);
}
}

View file

@ -18,22 +18,21 @@
package org.rometools.certiorem.hub;
import com.sun.syndication.feed.synd.SyndFeed;
import java.util.List;
import org.rometools.certiorem.hub.data.Subscriber;
import org.rometools.certiorem.hub.data.SubscriptionSummary;
import java.util.List;
import com.sun.syndication.feed.synd.SyndFeed;
/**
*
*
* @author robert.cooper
*/
public interface Notifier {
/**
* Instructs the notifier to begin sending notifications to the list of subscribers
*
*
* @param subscribers Subscribers to notify
* @param value The SyndFeed to send them
* @param callback A callback that is invoked each time a subscriber is notified.
@ -41,11 +40,11 @@ public interface Notifier {
public void notifySubscribers(List<Subscriber> subscribers, SyndFeed value, SubscriptionSummaryCallback callback);
/**
* A callback that is invoked each time a subscriber is notified.
* A callback that is invoked each time a subscriber is notified.
*/
public static interface SubscriptionSummaryCallback {
/**
*
*
* @param summary A summary of the data received from the subscriber
*/
public void onSummaryInfo(SubscriptionSummary summary);

View file

@ -20,9 +20,9 @@ package org.rometools.certiorem.hub;
import org.rometools.certiorem.hub.data.Subscriber;
/**
* A strategy interface for verification of subscriptions.
*
* @author robert.cooper
*/
public interface Verifier {
@ -38,6 +38,7 @@ public interface Verifier {
/**
* Verifies a subscriber (possibly) asyncronously
*
* @param subscriber the Subscriber to verify
* @param callback a callback with the result of the verification.
*/
@ -45,32 +46,34 @@ public interface Verifier {
/**
* Verifies a subscriber syncronously
* @param subscriber The subscriber data
*
* @param subscriber The subscriber data
* @return boolean result;
*/
public boolean verifySubcribeSyncronously(Subscriber subscriber);
/**
* Verifies am unsubscribe (possibly) asyncronously
*
* @param subscriber The subscriber data
* @param callback result
*/
public void verifyUnsubscribeAsyncronously(Subscriber subscriber, VerificationCallback callback);
/**
/**
* Verifies an unsubscribe syncronously
* @param subscriber The subscriber data
*
* @param subscriber The subscriber data
* @return boolean result;
*/
public boolean verifyUnsubcribeSyncronously(Subscriber subscriber);
/**
* An interface for capturing the result of a verification (subscribe or unsubscribe)
*/
public static interface VerificationCallback {
/**
*
*
* @param verified success state of the verification
*/
public void onVerify(boolean verified);

View file

@ -16,13 +16,12 @@
* limitations under the License.
*/
package org.rometools.certiorem.hub.data;
import java.util.List;
/**
*
*
* @author robert.cooper
*/
public interface HubDAO {

View file

@ -20,9 +20,8 @@ package org.rometools.certiorem.hub.data;
import java.io.Serializable;
/**
*
*
* @author robert.cooper
*/
public class Subscriber implements Serializable {
@ -38,132 +37,132 @@ public class Subscriber implements Serializable {
/**
* Set the value of callback
*
*
* @param newcallback new value of callback
*/
public void setCallback(String newcallback) {
this.callback = newcallback;
public void setCallback(final String newcallback) {
callback = newcallback;
}
/**
* Get the value of callback
*
*
* @return the value of callback
*/
public String getCallback() {
return this.callback;
return callback;
}
/**
* Set the value of creationTime
*
*
* @param newcreationTime new value of creationTime
*/
public void setCreationTime(long newcreationTime) {
this.creationTime = newcreationTime;
public void setCreationTime(final long newcreationTime) {
creationTime = newcreationTime;
}
/**
* Get the value of creationTime
*
*
* @return the value of creationTime
*/
public long getCreationTime() {
return this.creationTime;
return creationTime;
}
/**
* Set the value of leaseSeconds
*
*
* @param newleaseSeconds new value of leaseSeconds
*/
public void setLeaseSeconds(long newleaseSeconds) {
this.leaseSeconds = newleaseSeconds;
public void setLeaseSeconds(final long newleaseSeconds) {
leaseSeconds = newleaseSeconds;
}
/**
* Get the value of leaseSeconds
*
*
* @return the value of leaseSeconds
*/
public long getLeaseSeconds() {
return this.leaseSeconds;
return leaseSeconds;
}
/**
* Set the value of secret
*
*
* @param newsecret new value of secret
*/
public void setSecret(String newsecret) {
this.secret = newsecret;
public void setSecret(final String newsecret) {
secret = newsecret;
}
/**
* Get the value of secret
*
*
* @return the value of secret
*/
public String getSecret() {
return this.secret;
return secret;
}
/**
* Set the value of topic
*
*
* @param newtopic new value of topic
*/
public void setTopic(String newtopic) {
this.topic = newtopic;
public void setTopic(final String newtopic) {
topic = newtopic;
}
/**
* Get the value of topic
*
*
* @return the value of topic
*/
public String getTopic() {
return this.topic;
return topic;
}
/**
* Set the value of verify
*
*
* @param newverify new value of verify
*/
public void setVerify(String newverify) {
this.verify = newverify;
public void setVerify(final String newverify) {
verify = newverify;
}
/**
* Get the value of verify
*
*
* @return the value of verify
*/
public String getVerify() {
return this.verify;
return verify;
}
/**
* Set the value of vertifyToken
*
*
* @param newvertifyToken new value of vertifyToken
*/
public void setVertifyToken(String newvertifyToken) {
this.vertifyToken = newvertifyToken;
public void setVertifyToken(final String newvertifyToken) {
vertifyToken = newvertifyToken;
}
/**
* Get the value of vertifyToken
*
*
* @return the value of vertifyToken
*/
public String getVertifyToken() {
return this.vertifyToken;
return vertifyToken;
}
@Override
public boolean equals(Object obj) {
public boolean equals(final Object obj) {
if (obj == null) {
return false;
}
@ -174,31 +173,31 @@ public class Subscriber implements Serializable {
final Subscriber other = (Subscriber) obj;
if ((this.callback == null) ? (other.callback != null) : (!this.callback.equals(other.callback))) {
if (callback == null ? other.callback != null : !callback.equals(other.callback)) {
return false;
}
if ((this.secret == null) ? (other.secret != null) : (!this.secret.equals(other.secret))) {
if (secret == null ? other.secret != null : !secret.equals(other.secret)) {
return false;
}
if ((this.topic == null) ? (other.topic != null) : (!this.topic.equals(other.topic))) {
if (topic == null ? other.topic != null : !topic.equals(other.topic)) {
return false;
}
if ((this.verify == null) ? (other.verify != null) : (!this.verify.equals(other.verify))) {
if (verify == null ? other.verify != null : !verify.equals(other.verify)) {
return false;
}
if ((this.vertifyToken == null) ? (other.vertifyToken != null) : (!this.vertifyToken.equals(other.vertifyToken))) {
if (vertifyToken == null ? other.vertifyToken != null : !vertifyToken.equals(other.vertifyToken)) {
return false;
}
if (this.creationTime != other.creationTime) {
if (creationTime != other.creationTime) {
return false;
}
if (this.leaseSeconds != other.leaseSeconds) {
if (leaseSeconds != other.leaseSeconds) {
return false;
}
@ -208,13 +207,13 @@ public class Subscriber implements Serializable {
@Override
public int hashCode() {
int hash = 7;
hash = (67 * hash) + ((this.callback != null) ? this.callback.hashCode() : 0);
hash = (67 * hash) + ((this.secret != null) ? this.secret.hashCode() : 0);
hash = (67 * hash) + ((this.topic != null) ? this.topic.hashCode() : 0);
hash = (67 * hash) + ((this.verify != null) ? this.verify.hashCode() : 0);
hash = (67 * hash) + ((this.vertifyToken != null) ? this.vertifyToken.hashCode() : 0);
hash = (67 * hash) + (int) (this.creationTime ^ (this.creationTime >>> 32));
hash = (67 * hash) + (int) (this.leaseSeconds ^ (this.leaseSeconds >>> 32));
hash = 67 * hash + (callback != null ? callback.hashCode() : 0);
hash = 67 * hash + (secret != null ? secret.hashCode() : 0);
hash = 67 * hash + (topic != null ? topic.hashCode() : 0);
hash = 67 * hash + (verify != null ? verify.hashCode() : 0);
hash = 67 * hash + (vertifyToken != null ? vertifyToken.hashCode() : 0);
hash = 67 * hash + (int) (creationTime ^ creationTime >>> 32);
hash = 67 * hash + (int) (leaseSeconds ^ leaseSeconds >>> 32);
return hash;
}

View file

@ -20,9 +20,8 @@ package org.rometools.certiorem.hub.data;
import java.io.Serializable;
/**
*
*
* @author robert.cooper
*/
public class SubscriptionSummary implements Serializable {
@ -32,55 +31,55 @@ public class SubscriptionSummary implements Serializable {
/**
* Set the value of host
*
*
* @param newhost new value of host
*/
public void setHost(String newhost) {
this.host = newhost;
public void setHost(final String newhost) {
host = newhost;
}
/**
* Get the value of host
*
*
* @return the value of host
*/
public String getHost() {
return this.host;
return host;
}
/**
* Set the value of lastPublishSuccessful
*
*
* @param newlastPublishSuccessful new value of lastPublishSuccessful
*/
public void setLastPublishSuccessful(boolean newlastPublishSuccessful) {
this.lastPublishSuccessful = newlastPublishSuccessful;
public void setLastPublishSuccessful(final boolean newlastPublishSuccessful) {
lastPublishSuccessful = newlastPublishSuccessful;
}
/**
* Get the value of lastPublishSuccessful
*
*
* @return the value of lastPublishSuccessful
*/
public boolean isLastPublishSuccessful() {
return this.lastPublishSuccessful;
return lastPublishSuccessful;
}
/**
* Set the value of subscribers
*
*
* @param newsubscribers new value of subscribers
*/
public void setSubscribers(int newsubscribers) {
this.subscribers = newsubscribers;
public void setSubscribers(final int newsubscribers) {
subscribers = newsubscribers;
}
/**
* Get the value of subscribers
*
*
* @return the value of subscribers
*/
public int getSubscribers() {
return this.subscribers;
return subscribers;
}
}

View file

@ -16,12 +16,8 @@
* limitations under the License.
*/
package org.rometools.certiorem.hub.data.jpa;
import org.rometools.certiorem.hub.data.HubDAO;
import org.rometools.certiorem.hub.data.Subscriber;
import java.util.LinkedList;
import java.util.List;
import java.util.UUID;
@ -31,10 +27,13 @@ import javax.persistence.EntityManagerFactory;
import javax.persistence.EntityTransaction;
import javax.persistence.NoResultException;
import javax.persistence.Query;
import org.rometools.certiorem.hub.data.HubDAO;
import org.rometools.certiorem.hub.data.Subscriber;
import org.rometools.certiorem.hub.data.SubscriptionSummary;
/**
*
*
* @author robert.cooper
*/
public class JPADAO implements HubDAO {
@ -48,41 +47,39 @@ public class JPADAO implements HubDAO {
}
@Override
public List<? extends Subscriber> subscribersForTopic(String topic) {
LinkedList<JPASubscriber> result = new LinkedList<JPASubscriber>();
EntityManager em = factory.createEntityManager();
EntityTransaction tx = em.getTransaction();
public List<? extends Subscriber> subscribersForTopic(final String topic) {
final LinkedList<JPASubscriber> result = new LinkedList<JPASubscriber>();
final EntityManager em = factory.createEntityManager();
final EntityTransaction tx = em.getTransaction();
tx.begin();
Query query = em.createNamedQuery("Subcriber.forTopic");
final Query query = em.createNamedQuery("Subcriber.forTopic");
query.setParameter("topic", topic);
try {
for (JPASubscriber subscriber : (List<JPASubscriber>) query.getResultList()) {
for (final JPASubscriber subscriber : (List<JPASubscriber>) query.getResultList()) {
if (subscriber.getLeaseSeconds() == -1) {
result.add(subscriber);
continue;
}
if (subscriber.getSubscribedAt().getTime() < (System.currentTimeMillis() - (1000 * subscriber.getLeaseSeconds()))) {
if (subscriber.getSubscribedAt().getTime() < System.currentTimeMillis() - 1000 * subscriber.getLeaseSeconds()) {
subscriber.setExpired(true);
} else {
result.add(subscriber);
}
if (subscriber.isExpired() && this.purgeExpired) {
if (subscriber.isExpired() && purgeExpired) {
em.remove(subscriber);
}
}
} catch (NoResultException e) {
} catch (final NoResultException e) {
tx.rollback();
em.close();
return result;
}
if (!tx.getRollbackOnly()) {
tx.commit();
} else {
@ -95,12 +92,12 @@ public class JPADAO implements HubDAO {
}
@Override
public Subscriber addSubscriber(Subscriber subscriber) {
public Subscriber addSubscriber(final Subscriber subscriber) {
assert subscriber != null : "Attempt to store a null subscriber";
EntityManager em = factory.createEntityManager();
EntityTransaction tx = em.getTransaction();
final EntityManager em = factory.createEntityManager();
final EntityTransaction tx = em.getTransaction();
tx.begin();
JPASubscriber data = new JPASubscriber();
final JPASubscriber data = new JPASubscriber();
data.copyFrom(subscriber);
data.setId(UUID.randomUUID().toString());
em.persist(data);
@ -110,22 +107,22 @@ public class JPADAO implements HubDAO {
}
@Override
public Subscriber findSubscriber(String topic, String callbackUrl) {
public Subscriber findSubscriber(final String topic, final String callbackUrl) {
throw new UnsupportedOperationException("Not supported yet.");
}
@Override
public void handleSummary(String topic, SubscriptionSummary summary) {
public void handleSummary(final String topic, final SubscriptionSummary summary) {
throw new UnsupportedOperationException("Not supported yet.");
}
@Override
public List<? extends SubscriptionSummary> summariesForTopic(String topic) {
public List<? extends SubscriptionSummary> summariesForTopic(final String topic) {
throw new UnsupportedOperationException("Not supported yet.");
}
@Override
public void removeSubscriber(String topic, String callback) {
public void removeSubscriber(final String topic, final String callback) {
throw new UnsupportedOperationException("Not supported yet.");
}
}

View file

@ -16,13 +16,9 @@
* limitations under the License.
*/
package org.rometools.certiorem.hub.data.jpa;
import org.rometools.certiorem.hub.data.Subscriber;
import java.io.Serializable;
import java.util.Date;
import javax.persistence.Entity;
@ -32,14 +28,14 @@ import javax.persistence.NamedQuery;
import javax.persistence.Temporal;
import javax.persistence.TemporalType;
import org.rometools.certiorem.hub.data.Subscriber;
/**
*
*
* @author robert.cooper
*/
@Entity
@NamedQueries({@NamedQuery(name = "Subcriber.forTopic", query = "SELECT o FROM JPASubscriber o WHERE o.topic = :topic AND o.expired = false ORDER BY o.subscribedAt")
})
@NamedQueries({ @NamedQuery(name = "Subcriber.forTopic", query = "SELECT o FROM JPASubscriber o WHERE o.topic = :topic AND o.expired = false ORDER BY o.subscribedAt") })
public class JPASubscriber extends Subscriber implements Serializable {
private Date subscribedAt = new Date();
private String id;
@ -47,65 +43,65 @@ public class JPASubscriber extends Subscriber implements Serializable {
/**
* Set the value of expired
*
*
* @param newexpired new value of expired
*/
public void setExpired(boolean newexpired) {
this.expired = newexpired;
public void setExpired(final boolean newexpired) {
expired = newexpired;
}
/**
* Get the value of expired
*
*
* @return the value of expired
*/
public boolean isExpired() {
return this.expired;
return expired;
}
/**
* Set the value of id
*
*
* @param newid new value of id
*/
public void setId(String newid) {
this.id = newid;
public void setId(final String newid) {
id = newid;
}
/**
* Get the value of id
*
*
* @return the value of id
*/
@Id
public String getId() {
return this.id;
return id;
}
/**
* Set the value of subscribedAt
*
*
* @param newsubscribedAt new value of subscribedAt
*/
public void setSubscribedAt(Date newsubscribedAt) {
this.subscribedAt = newsubscribedAt;
public void setSubscribedAt(final Date newsubscribedAt) {
subscribedAt = newsubscribedAt;
}
/**
* Get the value of subscribedAt
*
*
* @return the value of subscribedAt
*/
@Temporal(TemporalType.TIMESTAMP)
public Date getSubscribedAt() {
return this.subscribedAt;
return subscribedAt;
}
public void copyFrom(Subscriber source) {
this.setLeaseSeconds(source.getLeaseSeconds());
this.setSecret(source.getSecret());
this.setTopic(source.getTopic());
this.setVerify(source.getVerify());
this.setVertifyToken(source.getVertifyToken());
public void copyFrom(final Subscriber source) {
setLeaseSeconds(source.getLeaseSeconds());
setSecret(source.getSecret());
setTopic(source.getTopic());
setVerify(source.getVerify());
setVertifyToken(source.getVertifyToken());
}
}

View file

@ -18,36 +18,35 @@
package org.rometools.certiorem.hub.data.ram;
import org.rometools.certiorem.hub.data.HubDAO;
import org.rometools.certiorem.hub.data.Subscriber;
import org.rometools.certiorem.hub.data.SubscriptionSummary;
import java.util.Collections;
import java.util.LinkedList;
import java.util.List;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.CopyOnWriteArrayList;
import org.rometools.certiorem.hub.data.HubDAO;
import org.rometools.certiorem.hub.data.Subscriber;
import org.rometools.certiorem.hub.data.SubscriptionSummary;
/**
* A Simple In-Memory HubDAO for subscribers.
*
*
* @author robert.cooper
*/
public class InMemoryHubDAO implements HubDAO {
private ConcurrentHashMap<String, List<Subscriber>> subscribers = new ConcurrentHashMap<String, List<Subscriber>>();
private ConcurrentHashMap<String, ConcurrentHashMap<String, SubscriptionSummary>> summaries = new ConcurrentHashMap<String, ConcurrentHashMap<String, SubscriptionSummary>>();
private final ConcurrentHashMap<String, List<Subscriber>> subscribers = new ConcurrentHashMap<String, List<Subscriber>>();
private final ConcurrentHashMap<String, ConcurrentHashMap<String, SubscriptionSummary>> summaries = new ConcurrentHashMap<String, ConcurrentHashMap<String, SubscriptionSummary>>();
@Override
public Subscriber addSubscriber(Subscriber subscriber) {
public Subscriber addSubscriber(final Subscriber subscriber) {
assert subscriber != null : "Attempt to store a null subscriber";
List<Subscriber> subList = this.subscribers.get(subscriber.getTopic());
List<Subscriber> subList = subscribers.get(subscriber.getTopic());
if (subList == null) {
synchronized (this) {
subList = new CopyOnWriteArrayList<Subscriber>();
this.subscribers.put(subscriber.getTopic(), subList);
subscribers.put(subscriber.getTopic(), subList);
}
}
@ -57,13 +56,13 @@ public class InMemoryHubDAO implements HubDAO {
}
@Override
public void handleSummary(String topic, SubscriptionSummary summary) {
ConcurrentHashMap<String, SubscriptionSummary> hostsToSummaries = this.summaries.get(topic);
public void handleSummary(final String topic, final SubscriptionSummary summary) {
ConcurrentHashMap<String, SubscriptionSummary> hostsToSummaries = summaries.get(topic);
if (hostsToSummaries == null) {
synchronized (this) {
hostsToSummaries = new ConcurrentHashMap<String, SubscriptionSummary>();
this.summaries.put(topic, hostsToSummaries);
summaries.put(topic, hostsToSummaries);
}
}
@ -71,14 +70,13 @@ public class InMemoryHubDAO implements HubDAO {
}
@Override
public List<?extends Subscriber> subscribersForTopic(String topic) {
public List<? extends Subscriber> subscribersForTopic(final String topic) {
if (subscribers.containsKey(topic)) {
List<Subscriber> result = new LinkedList<Subscriber>();
LinkedList<Subscriber> expired = new LinkedList<Subscriber>();
final List<Subscriber> result = new LinkedList<Subscriber>();
final LinkedList<Subscriber> expired = new LinkedList<Subscriber>();
for (Subscriber s : subscribers.get(topic)) {
if ((s.getLeaseSeconds() > 0) &&
(System.currentTimeMillis() >= (s.getCreationTime() + (s.getLeaseSeconds() * 1000L)))) {
for (final Subscriber s : subscribers.get(topic)) {
if (s.getLeaseSeconds() > 0 && System.currentTimeMillis() >= s.getCreationTime() + s.getLeaseSeconds() * 1000L) {
expired.add(s);
} else {
result.add(s);
@ -86,8 +84,7 @@ public class InMemoryHubDAO implements HubDAO {
}
if (!expired.isEmpty()) {
subscribers.get(topic)
.removeAll(expired);
subscribers.get(topic).removeAll(expired);
}
return result;
@ -97,41 +94,41 @@ public class InMemoryHubDAO implements HubDAO {
}
@Override
public List<?extends SubscriptionSummary> summariesForTopic(String topic) {
LinkedList<SubscriptionSummary> result = new LinkedList<SubscriptionSummary>();
public List<? extends SubscriptionSummary> summariesForTopic(final String topic) {
final LinkedList<SubscriptionSummary> result = new LinkedList<SubscriptionSummary>();
if (this.summaries.containsKey(topic)) {
result.addAll(this.summaries.get(topic).values());
if (summaries.containsKey(topic)) {
result.addAll(summaries.get(topic).values());
}
return result;
}
@Override
public Subscriber findSubscriber(String topic, String callbackUrl) {
public Subscriber findSubscriber(final String topic, final String callbackUrl) {
for (Subscriber s : this.subscribersForTopic(topic)) {
for (final Subscriber s : subscribersForTopic(topic)) {
if (callbackUrl.equals(s.getCallback())) {
return s;
return s;
}
}
return null;
}
@Override
public void removeSubscriber(String topic, String callback) {
List<Subscriber> subs = this.subscribers.get(topic);
if(subs == null){
public void removeSubscriber(final String topic, final String callback) {
final List<Subscriber> subs = subscribers.get(topic);
if (subs == null) {
return;
}
Subscriber match = null;
for(Subscriber s: subs){
if(s.getCallback().equals(callback)){
for (final Subscriber s : subs) {
if (s.getCallback().equals(callback)) {
match = s;
break;
}
}
if(match != null){
if (match != null) {
subs.remove(match);
}
}

View file

@ -16,152 +16,140 @@
* limitations under the License.
*/
package org.rometools.certiorem.hub.notify.standard;
import com.sun.syndication.feed.synd.SyndFeed;
import com.sun.syndication.io.FeedException;
import com.sun.syndication.io.SyndFeedOutput;
import org.rometools.certiorem.hub.Notifier;
import org.rometools.certiorem.hub.data.Subscriber;
import org.rometools.certiorem.hub.data.SubscriptionSummary;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.List;
import java.util.logging.Level;
import java.util.logging.Logger;
import org.rometools.certiorem.sub.data.ram.InMemorySubDAO;
import org.rometools.certiorem.hub.Notifier;
import org.rometools.certiorem.hub.data.Subscriber;
import org.rometools.certiorem.hub.data.SubscriptionSummary;
import com.sun.syndication.feed.synd.SyndFeed;
import com.sun.syndication.io.FeedException;
import com.sun.syndication.io.SyndFeedOutput;
/**
*
*
* @author robert.cooper
*/
public abstract class AbstractNotifier implements Notifier {
/**
* This method will serialize the synd feed and build Notifications for the
* implementation class to handle.
* @see enqueueNotification
*
* This method will serialize the synd feed and build Notifications for the implementation class to handle.
*
* @see enqueueNotification
*
* @param subscribers List of subscribers to notify
* @param value The SyndFeed object to send
* @param callback A callback that will be invoked each time a subscriber is notified.
*
*
*/
@Override
public void notifySubscribers(List<Subscriber> subscribers, SyndFeed value, SubscriptionSummaryCallback callback) {
public void notifySubscribers(final List<Subscriber> subscribers, final SyndFeed value, final SubscriptionSummaryCallback callback) {
String mimeType = null;
if (value.getFeedType()
.startsWith("rss")) {
if (value.getFeedType().startsWith("rss")) {
mimeType = "application/rss+xml";
} else {
mimeType = "application/atom+xml";
}
SyndFeedOutput output = new SyndFeedOutput();
ByteArrayOutputStream baos = new ByteArrayOutputStream();
final SyndFeedOutput output = new SyndFeedOutput();
final ByteArrayOutputStream baos = new ByteArrayOutputStream();
try {
output.output(value, new OutputStreamWriter(baos));
baos.close();
} catch (IOException ex) {
Logger.getLogger(AbstractNotifier.class.getName())
.log(Level.SEVERE, null, ex);
} catch (final IOException ex) {
Logger.getLogger(AbstractNotifier.class.getName()).log(Level.SEVERE, null, ex);
throw new RuntimeException("Unable to output the feed.", ex);
} catch (FeedException ex) {
Logger.getLogger(AbstractNotifier.class.getName())
.log(Level.SEVERE, null, ex);
} catch (final FeedException ex) {
Logger.getLogger(AbstractNotifier.class.getName()).log(Level.SEVERE, null, ex);
throw new RuntimeException("Unable to output the feed.", ex);
}
byte[] payload = baos.toByteArray();
final byte[] payload = baos.toByteArray();
for (Subscriber s : subscribers) {
Notification not = new Notification();
for (final Subscriber s : subscribers) {
final Notification not = new Notification();
not.callback = callback;
not.lastRun = 0;
not.mimeType = mimeType;
not.payload = payload;
not.retryCount = 0;
not.subscriber = s;
this.enqueueNotification(not);
enqueueNotification(not);
}
}
/** Implementation method that queues/sends a notification
*
/**
* Implementation method that queues/sends a notification
*
* @param not notification to send.
*/
protected abstract void enqueueNotification(Notification not);
/**
* POSTs the payload to the subscriber's callback and returns a
* SubscriptionSummary with subscriber counts (where possible) and the
* success state of the notification.
* POSTs the payload to the subscriber's callback and returns a SubscriptionSummary with subscriber counts (where possible) and the success state of the
* notification.
*
* @param subscriber subscriber data.
* @param mimeType MIME type for the request
* @param payload payload of the feed to send
* @return SubscriptionSummary with the returned data.
*/
protected SubscriptionSummary postNotification(Subscriber subscriber, String mimeType, byte[] payload) {
SubscriptionSummary result = new SubscriptionSummary();
protected SubscriptionSummary postNotification(final Subscriber subscriber, final String mimeType, final byte[] payload) {
final SubscriptionSummary result = new SubscriptionSummary();
try {
URL target = new URL(subscriber.getCallback());
final URL target = new URL(subscriber.getCallback());
Logger.getLogger(AbstractNotifier.class.getName()).log(Level.INFO, "Posting notification to subscriber {0}", subscriber.getCallback());
result.setHost(target.getHost());
HttpURLConnection connection = (HttpURLConnection) target.openConnection();
final HttpURLConnection connection = (HttpURLConnection) target.openConnection();
connection.setRequestMethod("POST");
connection.setRequestProperty("Content-Type", mimeType);
connection.setDoOutput(true);
connection.connect();
OutputStream os = connection.getOutputStream();
final OutputStream os = connection.getOutputStream();
os.write(payload);
os.close();
int responseCode = connection.getResponseCode();
String subscribers = connection.getHeaderField("X-Hub-On-Behalf-Of");
final int responseCode = connection.getResponseCode();
final String subscribers = connection.getHeaderField("X-Hub-On-Behalf-Of");
connection.disconnect();
if (responseCode != 200) {
Logger.getLogger(AbstractNotifier.class.getName())
.log(Level.WARNING, "Got code " + responseCode + " from " + target);
Logger.getLogger(AbstractNotifier.class.getName()).log(Level.WARNING, "Got code " + responseCode + " from " + target);
result.setLastPublishSuccessful(false);
return result;
}
if (subscribers != null) {
try {
result.setSubscribers(Integer.parseInt(subscribers));
} catch (NumberFormatException nfe) {
Logger.getLogger(AbstractNotifier.class.getName())
.log(Level.WARNING, "Invalid subscriber value " + subscribers + " " + target, nfe);
} catch (final NumberFormatException nfe) {
Logger.getLogger(AbstractNotifier.class.getName()).log(Level.WARNING, "Invalid subscriber value " + subscribers + " " + target, nfe);
result.setSubscribers(-1);
}
} else {
result.setSubscribers(-1);
}
} catch (MalformedURLException ex) {
Logger.getLogger(AbstractNotifier.class.getName())
.log(Level.WARNING, null, ex);
} catch (final MalformedURLException ex) {
Logger.getLogger(AbstractNotifier.class.getName()).log(Level.WARNING, null, ex);
result.setLastPublishSuccessful(false);
} catch (IOException ex) {
Logger.getLogger(AbstractNotifier.class.getName())
.log(Level.SEVERE, null, ex);
} catch (final IOException ex) {
Logger.getLogger(AbstractNotifier.class.getName()).log(Level.SEVERE, null, ex);
result.setLastPublishSuccessful(false);
}

View file

@ -16,14 +16,13 @@
* limitations under the License.
*/
package org.rometools.certiorem.hub.notify.standard;
import org.rometools.certiorem.hub.Notifier.SubscriptionSummaryCallback;
import org.rometools.certiorem.hub.data.Subscriber;
/**
*
*
* @author robert.cooper
*/
public class Notification {

View file

@ -16,11 +16,8 @@
* limitations under the License.
*/
package org.rometools.certiorem.hub.notify.standard;
import org.rometools.certiorem.hub.data.SubscriptionSummary;
import java.util.Timer;
import java.util.TimerTask;
import java.util.concurrent.ConcurrentSkipListSet;
@ -28,11 +25,11 @@ import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
import org.rometools.certiorem.hub.data.SubscriptionSummary;
/**
* A notifier implementation that uses a thread pool to deliver notifications to
* subscribers
*
* A notifier implementation that uses a thread pool to deliver notifications to subscribers
*
* @author robert.cooper
*/
public class ThreadPoolNotifier extends AbstractNotifier {
@ -45,47 +42,47 @@ public class ThreadPoolNotifier extends AbstractNotifier {
this(2, 5, 5);
}
public ThreadPoolNotifier(int startPoolSize, int maxPoolSize, int queueSize) {
this.exeuctor = new ThreadPoolExecutor(startPoolSize, maxPoolSize, 300, TimeUnit.SECONDS,
new LinkedBlockingQueue<Runnable>(queueSize));
public ThreadPoolNotifier(final int startPoolSize, final int maxPoolSize, final int queueSize) {
exeuctor = new ThreadPoolExecutor(startPoolSize, maxPoolSize, 300, TimeUnit.SECONDS, new LinkedBlockingQueue<Runnable>(queueSize));
}
protected ThreadPoolNotifier(final ThreadPoolExecutor executor) {
this.exeuctor = executor;
exeuctor = executor;
}
/**
* Enqueues a notification to run. If the notification fails, it will be
* retried every two minutes until 5 attempts are completed. Notifications
* to the same callback should be delivered successfully in order.
* Enqueues a notification to run. If the notification fails, it will be retried every two minutes until 5 attempts are completed. Notifications to the same
* callback should be delivered successfully in order.
*
* @param not
*/
@Override
protected void enqueueNotification(final Notification not) {
Runnable r = new Runnable() {
@Override
public void run() {
not.lastRun = System.currentTimeMillis();
final Runnable r = new Runnable() {
@Override
public void run() {
not.lastRun = System.currentTimeMillis();
SubscriptionSummary summary = postNotification(not.subscriber, not.mimeType, not.payload);
final SubscriptionSummary summary = postNotification(not.subscriber, not.mimeType, not.payload);
if (!summary.isLastPublishSuccessful()) {
not.retryCount++;
if (!summary.isLastPublishSuccessful()) {
not.retryCount++;
if (not.retryCount <= 5) {
retry(not);
}
if (not.retryCount <= 5) {
retry(not);
}
not.callback.onSummaryInfo(summary);
}
};
this.exeuctor.execute(r);
not.callback.onSummaryInfo(summary);
}
};
exeuctor.execute(r);
}
/**
* Schedules a notification to retry in two minutes.
*
* @param not Notification to retry
*/
protected void retry(final Notification not) {
@ -94,21 +91,21 @@ public class ThreadPoolNotifier extends AbstractNotifier {
// will schedule the retry
pendings.add(not.subscriber.getCallback());
timer.schedule(new TimerTask() {
@Override
public void run() {
pendings.remove(not.subscriber.getCallback());
enqueueNotification(not);
}
}, TWO_MINUTES);
@Override
public void run() {
pendings.remove(not.subscriber.getCallback());
enqueueNotification(not);
}
}, TWO_MINUTES);
} else {
// There is a retry in front of this one, so we will just schedule
// it to retry again in a bit
timer.schedule(new TimerTask() {
@Override
public void run() {
retry(not);
}
}, TWO_MINUTES);
@Override
public void run() {
retry(not);
}
}, TWO_MINUTES);
}
}
}

View file

@ -18,32 +18,30 @@
package org.rometools.certiorem.hub.notify.standard;
import org.rometools.certiorem.hub.data.SubscriptionSummary;
import java.util.concurrent.ConcurrentSkipListSet;
import org.rometools.certiorem.hub.data.SubscriptionSummary;
/**
* A notifier that does not use threads. All calls are blocking and synchronous.
*
*
* @author robert.cooper
*/
public class UnthreadedNotifier extends AbstractNotifier {
private final ConcurrentSkipListSet<Notification> retries = new ConcurrentSkipListSet<Notification>();
/**
* A blocking call that performs a notification.
* If there are pending retries that are older than two minutes old, they will
* be retried before the method returns.
*
* A blocking call that performs a notification. If there are pending retries that are older than two minutes old, they will be retried before the method
* returns.
*
* @param not
*/
@Override
protected void enqueueNotification(Notification not) {
protected void enqueueNotification(final Notification not) {
not.lastRun = System.currentTimeMillis();
SubscriptionSummary summary = postNotification(not.subscriber, not.mimeType, not.payload);
final SubscriptionSummary summary = postNotification(not.subscriber, not.mimeType, not.payload);
not.callback.onSummaryInfo(summary);
}
}

View file

@ -16,91 +16,77 @@
* limitations under the License.
*/
package org.rometools.certiorem.hub.verify.standard;
import org.rometools.certiorem.hub.Verifier;
import org.rometools.certiorem.hub.data.Subscriber;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.UnsupportedEncodingException;
import java.net.HttpURLConnection;
import java.net.URL;
import java.net.URLEncoder;
import java.util.UUID;
import java.util.logging.Level;
import java.util.logging.Logger;
import org.rometools.certiorem.hub.Verifier;
import org.rometools.certiorem.hub.data.Subscriber;
/**
* An abstract verifier based on the java.net HTTP classes. This implements only
* synchronous operations, and expects a child class to do Async ops.
* An abstract verifier based on the java.net HTTP classes. This implements only synchronous operations, and expects a child class to do Async ops.
*
* @author robert.cooper
*/
public abstract class AbstractVerifier implements Verifier {
@Override
public boolean verifySubcribeSyncronously(Subscriber subscriber) {
public boolean verifySubcribeSyncronously(final Subscriber subscriber) {
return doOp(Verifier.MODE_SUBSCRIBE, subscriber);
}
@Override
public boolean verifyUnsubcribeSyncronously(Subscriber subscriber) {
public boolean verifyUnsubcribeSyncronously(final Subscriber subscriber) {
return doOp(Verifier.MODE_UNSUBSCRIBE, subscriber);
}
private boolean doOp(String mode, Subscriber subscriber){
private boolean doOp(final String mode, final Subscriber subscriber) {
try {
String challenge = UUID.randomUUID()
.toString();
StringBuilder queryString = new StringBuilder();
queryString.append("hub.mode=")
.append(mode)
.append("&hub.topic=")
.append(URLEncoder.encode(subscriber.getTopic(), "UTF-8"))
.append("&hub.challenge=")
.append(challenge);
final String challenge = UUID.randomUUID().toString();
final StringBuilder queryString = new StringBuilder();
queryString.append("hub.mode=").append(mode).append("&hub.topic=").append(URLEncoder.encode(subscriber.getTopic(), "UTF-8"))
.append("&hub.challenge=").append(challenge);
if (subscriber.getLeaseSeconds() != -1) {
queryString.append("&hub.lease_seconds=")
.append(subscriber.getLeaseSeconds());
queryString.append("&hub.lease_seconds=").append(subscriber.getLeaseSeconds());
}
if (subscriber.getVertifyToken() != null) {
queryString.append("&hub.verify_token=")
.append(URLEncoder.encode(subscriber.getVertifyToken(), "UTF-8"));
queryString.append("&hub.verify_token=").append(URLEncoder.encode(subscriber.getVertifyToken(), "UTF-8"));
}
URL url = new URL(subscriber.getCallback() + "?" + queryString.toString());
HttpURLConnection connection = (HttpURLConnection) url.openConnection();
final URL url = new URL(subscriber.getCallback() + "?" + queryString.toString());
final HttpURLConnection connection = (HttpURLConnection) url.openConnection();
connection.setDoInput(true);
// connection.setRequestProperty("Host", url.getHost());
// connection.setRequestProperty("Port", Integer.toString(url.getPort()));
// connection.setRequestProperty("Host", url.getHost());
// connection.setRequestProperty("Port", Integer.toString(url.getPort()));
connection.setRequestProperty("User-Agent", "ROME-Certiorem");
connection.connect();
int rc = connection.getResponseCode();
InputStream is = connection.getInputStream();
BufferedReader reader = new BufferedReader(new InputStreamReader(is));
String result = reader.readLine();
final int rc = connection.getResponseCode();
final InputStream is = connection.getInputStream();
final BufferedReader reader = new BufferedReader(new InputStreamReader(is));
final String result = reader.readLine();
reader.close();
connection.disconnect();
if ((rc != 200) || !challenge.equals(result.trim())) {
if (rc != 200 || !challenge.equals(result.trim())) {
return false;
} else {
return true;
}
} catch (UnsupportedEncodingException ex) {
Logger.getLogger(AbstractVerifier.class.getName())
.log(Level.SEVERE, null, ex);
} catch (final UnsupportedEncodingException ex) {
Logger.getLogger(AbstractVerifier.class.getName()).log(Level.SEVERE, null, ex);
throw new RuntimeException("Should not happen. UTF-8 threw unsupported encoding", ex);
} catch (IOException ex) {
Logger.getLogger(AbstractVerifier.class.getName())
.log(Level.SEVERE, null, ex);
} catch (final IOException ex) {
Logger.getLogger(AbstractVerifier.class.getName()).log(Level.SEVERE, null, ex);
return false;
}

View file

@ -16,53 +16,51 @@
* limitations under the License.
*/
package org.rometools.certiorem.hub.verify.standard;
import org.rometools.certiorem.hub.data.Subscriber;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
import org.rometools.certiorem.hub.data.Subscriber;
/**
* Uses a ThreadPoolExecutor to do async verifications.
*
* @author robert.cooper
*/
public class ThreadPoolVerifier extends AbstractVerifier {
protected final ThreadPoolExecutor exeuctor;
protected ThreadPoolVerifier(final ThreadPoolExecutor executor){
this.exeuctor = executor;
protected ThreadPoolVerifier(final ThreadPoolExecutor executor) {
exeuctor = executor;
}
public ThreadPoolVerifier() {
this(2, 5, 5);
}
public ThreadPoolVerifier(int startPoolSize, int maxPoolSize, int queueSize) {
this.exeuctor = new ThreadPoolExecutor(startPoolSize, maxPoolSize, 300, TimeUnit.SECONDS,
new LinkedBlockingQueue<Runnable>(queueSize));
public ThreadPoolVerifier(final int startPoolSize, final int maxPoolSize, final int queueSize) {
exeuctor = new ThreadPoolExecutor(startPoolSize, maxPoolSize, 300, TimeUnit.SECONDS, new LinkedBlockingQueue<Runnable>(queueSize));
}
@Override
public void verifySubscribeAsyncronously(final Subscriber subscriber, final VerificationCallback callback) {
this.exeuctor.execute(new Runnable() {
@Override
public void run() {
callback.onVerify(verifySubcribeSyncronously(subscriber));
}
});
exeuctor.execute(new Runnable() {
@Override
public void run() {
callback.onVerify(verifySubcribeSyncronously(subscriber));
}
});
}
@Override
public void verifyUnsubscribeAsyncronously(final Subscriber subscriber, final VerificationCallback callback) {
this.exeuctor.execute(new Runnable() {
@Override
public void run() {
callback.onVerify(verifyUnsubcribeSyncronously(subscriber));
}
});
exeuctor.execute(new Runnable() {
@Override
public void run() {
callback.onVerify(verifyUnsubcribeSyncronously(subscriber));
}
});
}
}

View file

@ -21,12 +21,12 @@ package org.rometools.certiorem.hub.verify.standard;
import java.util.concurrent.ThreadPoolExecutor;
/**
*
*
* @author robert.cooper
*/
public class ThreadpoolVerifierAdvanced extends ThreadPoolVerifier{
public class ThreadpoolVerifierAdvanced extends ThreadPoolVerifier {
public ThreadpoolVerifierAdvanced(ThreadPoolExecutor executor){
public ThreadpoolVerifierAdvanced(final ThreadPoolExecutor executor) {
super(executor);
}

View file

@ -16,25 +16,24 @@
* limitations under the License.
*/
package org.rometools.certiorem.hub.verify.standard;
import org.rometools.certiorem.hub.data.Subscriber;
/**
* A verifier that does not use threads. Suitable for Google App Engine.
*
* @author robert.cooper
*/
public class UnthreadedVerifier extends AbstractVerifier{
public class UnthreadedVerifier extends AbstractVerifier {
@Override
public void verifySubscribeAsyncronously(Subscriber subscriber, VerificationCallback callback) {
public void verifySubscribeAsyncronously(final Subscriber subscriber, final VerificationCallback callback) {
callback.onVerify(verifySubcribeSyncronously(subscriber));
}
@Override
public void verifyUnsubscribeAsyncronously(Subscriber subscriber, VerificationCallback callback) {
public void verifyUnsubscribeAsyncronously(final Subscriber subscriber, final VerificationCallback callback) {
callback.onVerify(verifyUnsubcribeSyncronously(subscriber));
}

View file

@ -16,20 +16,19 @@
* limitations under the License.
*/
package org.rometools.certiorem.pub;
/**
*
*
* @author robert.cooper
*/
public class NotificationException extends Exception {
public NotificationException(String message){
public NotificationException(final String message) {
super(message);
}
public NotificationException(String message, Throwable cause){
public NotificationException(final String message, final Throwable cause) {
super(message, cause);
}

View file

@ -16,28 +16,24 @@
* limitations under the License.
*/
package org.rometools.certiorem.pub;
import com.sun.syndication.feed.synd.SyndFeed;
import com.sun.syndication.feed.synd.SyndLink;
import java.io.IOException;
import java.io.OutputStream;
import java.io.UnsupportedEncodingException;
import java.net.HttpURLConnection;
import java.net.URL;
import java.net.URLEncoder;
import java.util.List;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.logging.Level;
import java.util.logging.Logger;
import com.sun.syndication.feed.synd.SyndFeed;
import com.sun.syndication.feed.synd.SyndLink;
/**
* A class for sending update notifications to a hub.
*
* @author robert.cooper
*/
public class Publisher {
@ -52,61 +48,57 @@ public class Publisher {
/**
* Constructs a new publisher with an optional ThreadPoolExector for sending updates.
*/
public Publisher(ThreadPoolExecutor executor) {
public Publisher(final ThreadPoolExecutor executor) {
this.executor = executor;
}
/**
* Sends the HUB url a notification of a change in topic
*
* @param hub URL of the hub to notify.
* @param topic The Topic that has changed
* @param topic The Topic that has changed
* @throws NotificationException Any failure
*/
public void sendUpdateNotification(String hub, String topic)
throws NotificationException {
public void sendUpdateNotification(final String hub, final String topic) throws NotificationException {
try {
StringBuilder sb = new StringBuilder("hub.mode=publish&hub.url=").append(URLEncoder.encode(topic, "UTF-8"));
URL hubUrl = new URL(hub);
HttpURLConnection connection = (HttpURLConnection) hubUrl.openConnection();
// connection.setRequestProperty("Host", hubUrl.getHost());
final StringBuilder sb = new StringBuilder("hub.mode=publish&hub.url=").append(URLEncoder.encode(topic, "UTF-8"));
final URL hubUrl = new URL(hub);
final HttpURLConnection connection = (HttpURLConnection) hubUrl.openConnection();
// connection.setRequestProperty("Host", hubUrl.getHost());
connection.setRequestProperty("User-Agent", "ROME-Certiorem");
connection.setRequestProperty("ContentType", "application/x-www-form-urlencoded");
connection.setDoOutput(true);
connection.connect();
OutputStream os = connection.getOutputStream();
final OutputStream os = connection.getOutputStream();
os.write(sb.toString().getBytes("UTF-8"));
os.close();
int rc = connection.getResponseCode();
final int rc = connection.getResponseCode();
connection.disconnect();
if (rc != 204) {
throw new NotificationException("Server returned an unexcepted response code: " + rc + " " +
connection.getResponseMessage());
throw new NotificationException("Server returned an unexcepted response code: " + rc + " " + connection.getResponseMessage());
}
} catch (UnsupportedEncodingException ex) {
Logger.getLogger(Publisher.class.getName())
.log(Level.SEVERE, null, ex);
} catch (final UnsupportedEncodingException ex) {
Logger.getLogger(Publisher.class.getName()).log(Level.SEVERE, null, ex);
throw new NotificationException("Could not encode URL", ex);
} catch (IOException ex) {
Logger.getLogger(Publisher.class.getName())
.log(Level.SEVERE, null, ex);
} catch (final IOException ex) {
Logger.getLogger(Publisher.class.getName()).log(Level.SEVERE, null, ex);
throw new NotificationException("Unable to communicate with " + hub, ex);
}
}
/**
* Sends a notification for a feed located at "topic". The feed MUST contain rel="hub".
*
* @param topic URL for the feed
* @param feed The feed itself
* @throws NotificationException Any failure
*/
public void sendUpdateNotification(String topic, SyndFeed feed)
throws NotificationException {
for (SyndLink link : (List<SyndLink>) feed.getLinks()) {
public void sendUpdateNotification(final String topic, final SyndFeed feed) throws NotificationException {
for (final SyndLink link : feed.getLinks()) {
if ("hub".equals(link.getRel())) {
sendUpdateNotification(link.getRel(), topic);
@ -118,14 +110,15 @@ public class Publisher {
/**
* Sends a notification for a feed. The feed MUST contain rel="hub" and rel="self" links.
*
* @param feed The feed to notify
* @throws NotificationException Any failure
*/
public void sendUpdateNotification(SyndFeed feed) throws NotificationException {
public void sendUpdateNotification(final SyndFeed feed) throws NotificationException {
SyndLink hub = null;
SyndLink self = null;
for (SyndLink link : (List<SyndLink>) feed.getLinks()) {
for (final SyndLink link : feed.getLinks()) {
if ("hub".equals(link.getRel())) {
hub = link;
}
@ -134,7 +127,7 @@ public class Publisher {
self = link;
}
if ((hub != null) && (self != null)) {
if (hub != null && self != null) {
break;
}
}
@ -152,27 +145,27 @@ public class Publisher {
/**
* Sends the HUB url a notification of a change in topic asynchronously
*
* @param hub URL of the hub to notify.
* @param topic The Topic that has changed
* @param callback A callback invoked when the notification completes.
* @param topic The Topic that has changed
* @param callback A callback invoked when the notification completes.
* @throws NotificationException Any failure
*/
public void sendUpdateNotificationAsyncronously(final String hub, final String topic,
final AsyncNotificationCallback callback) {
Runnable r = new Runnable() {
@Override
public void run() {
try {
sendUpdateNotification(hub, topic);
callback.onSuccess();
} catch (Throwable t) {
callback.onFailure(t);
}
public void sendUpdateNotificationAsyncronously(final String hub, final String topic, final AsyncNotificationCallback callback) {
final Runnable r = new Runnable() {
@Override
public void run() {
try {
sendUpdateNotification(hub, topic);
callback.onSuccess();
} catch (final Throwable t) {
callback.onFailure(t);
}
};
}
};
if (this.executor != null) {
this.executor.execute(r);
if (executor != null) {
executor.execute(r);
} else {
new Thread(r).start();
}
@ -180,66 +173,70 @@ public class Publisher {
/**
* Asynchronously sends a notification for a feed located at "topic". The feed MUST contain rel="hub".
*
* @param topic URL for the feed
* @param feed The feed itself
* @param callback A callback invoked when the notification completes.
* @param callback A callback invoked when the notification completes.
* @throws NotificationException Any failure
*/
public void sendUpdateNotificationAsyncronously(final String topic, final SyndFeed feed,
final AsyncNotificationCallback callback) {
Runnable r = new Runnable() {
@Override
public void run() {
try {
sendUpdateNotification(topic, feed);
callback.onSuccess();
} catch (Throwable t) {
callback.onFailure(t);
}
public void sendUpdateNotificationAsyncronously(final String topic, final SyndFeed feed, final AsyncNotificationCallback callback) {
final Runnable r = new Runnable() {
@Override
public void run() {
try {
sendUpdateNotification(topic, feed);
callback.onSuccess();
} catch (final Throwable t) {
callback.onFailure(t);
}
};
}
};
if (this.executor != null) {
this.executor.execute(r);
if (executor != null) {
executor.execute(r);
} else {
new Thread(r).start();
}
}
/**
* Asyncronously sends a notification for a feed. The feed MUST contain rel="hub" and rel="self" links.
* Asyncronously sends a notification for a feed. The feed MUST contain rel="hub" and rel="self" links.
*
* @param feed The feed to notify
* @param callback A callback invoked when the notification completes.
* @param callback A callback invoked when the notification completes.
* @throws NotificationException Any failure
*/
public void sendUpdateNotificationAsyncronously(final SyndFeed feed, final AsyncNotificationCallback callback) {
Runnable r = new Runnable() {
@Override
public void run() {
try {
sendUpdateNotification(feed);
callback.onSuccess();
} catch (Throwable t) {
callback.onFailure(t);
}
final Runnable r = new Runnable() {
@Override
public void run() {
try {
sendUpdateNotification(feed);
callback.onSuccess();
} catch (final Throwable t) {
callback.onFailure(t);
}
};
}
};
if (this.executor != null) {
this.executor.execute(r);
if (executor != null) {
executor.execute(r);
} else {
new Thread(r).start();
}
}
/**
* A callback interface for asynchronous notifications.
*/
public static interface AsyncNotificationCallback {
/**
* Called when a notification fails
*
* @param thrown Whatever was thrown during the failure
*/
public void onFailure(Throwable thrown);
/**
* Invoked with the asyncronous notification completes successfully.
*/

View file

@ -20,17 +20,15 @@ package org.rometools.certiorem.sub;
import org.rometools.certiorem.sub.data.Subscription;
/**
*
*
* @author robert.cooper
*/
public interface Requester {
public void sendSubscribeRequest(String hubUrl, Subscription subscription, String verifySync, long leaseSeconds,
String secret, String callbackUrl, RequestCallback callback);
public void sendSubscribeRequest(String hubUrl, Subscription subscription, String verifySync, long leaseSeconds, String secret, String callbackUrl,
RequestCallback callback);
public void sendUnsubscribeRequest(String hubUrl, Subscription subscription, String verifySync, String secret,
String callbackUrl, RequestCallback callback);
public void sendUnsubscribeRequest(String hubUrl, Subscription subscription, String verifySync, String secret, String callbackUrl, RequestCallback callback);
public static interface RequestCallback {
public void onFailure(Exception e);

View file

@ -18,104 +18,95 @@
package org.rometools.certiorem.sub;
import com.sun.syndication.feed.synd.SyndFeed;
import com.sun.syndication.feed.synd.SyndLink;
import com.sun.syndication.io.FeedException;
import com.sun.syndication.io.SyndFeedInput;
import org.rometools.certiorem.HttpStatusCodeException;
import org.rometools.certiorem.sub.Requester.RequestCallback;
import org.rometools.certiorem.sub.data.SubDAO;
import org.rometools.certiorem.sub.data.Subscription;
import org.rometools.fetcher.impl.FeedFetcherCache;
import org.rometools.fetcher.impl.SyndFeedInfo;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.UnsupportedEncodingException;
import java.net.MalformedURLException;
import java.net.URI;
import java.net.URISyntaxException;
import java.net.URL;
import java.util.List;
import java.util.UUID;
import java.util.logging.Level;
import java.util.logging.Logger;
import org.rometools.certiorem.sub.data.SubscriptionCallback;
import org.rometools.certiorem.HttpStatusCodeException;
import org.rometools.certiorem.sub.Requester.RequestCallback;
import org.rometools.certiorem.sub.data.SubDAO;
import org.rometools.certiorem.sub.data.Subscription;
import org.rometools.certiorem.sub.data.SubscriptionCallback;
import org.rometools.fetcher.impl.FeedFetcherCache;
import org.rometools.fetcher.impl.SyndFeedInfo;
import com.sun.syndication.feed.synd.SyndFeed;
import com.sun.syndication.feed.synd.SyndLink;
import com.sun.syndication.io.FeedException;
import com.sun.syndication.io.SyndFeedInput;
/**
*
*
* @author robert.cooper
*/
public class Subscriptions {
//TODO unsubscribe.
// TODO unsubscribe.
private FeedFetcherCache cache;
private Requester requester;
private String callbackPrefix;
private SubDAO dao;
public Subscriptions() {
public Subscriptions() {
}
public Subscriptions(final FeedFetcherCache cache, final Requester requester, final String callbackPrefix,
final SubDAO dao) {
public Subscriptions(final FeedFetcherCache cache, final Requester requester, final String callbackPrefix, final SubDAO dao) {
this.cache = cache;
this.requester = requester;
this.callbackPrefix = callbackPrefix;
this.dao = dao;
}
public void callback(String callbackPath, String feed) {
public void callback(final String callbackPath, final String feed) {
try {
this.callback(callbackPath, feed.getBytes("UTF-8"));
} catch (UnsupportedEncodingException ex) {
Logger.getLogger(Subscriptions.class.getName())
.log(Level.SEVERE, null, ex);
} catch (final UnsupportedEncodingException ex) {
Logger.getLogger(Subscriptions.class.getName()).log(Level.SEVERE, null, ex);
throw new HttpStatusCodeException(400, "Unable to parse feed.", ex);
}
}
public void callback(String callbackPath, InputStream feed) {
SyndFeedInput input = new SyndFeedInput();
public void callback(final String callbackPath, final InputStream feed) {
final SyndFeedInput input = new SyndFeedInput();
try {
this.callback(callbackPath, input.build(new InputStreamReader(feed)));
} catch (IllegalArgumentException ex) {
Logger.getLogger(Subscriptions.class.getName())
.log(Level.SEVERE, null, ex);
} catch (final IllegalArgumentException ex) {
Logger.getLogger(Subscriptions.class.getName()).log(Level.SEVERE, null, ex);
throw new HttpStatusCodeException(500, "Unable to parse feed.", ex);
} catch (FeedException ex) {
Logger.getLogger(Subscriptions.class.getName())
.log(Level.SEVERE, null, ex);
} catch (final FeedException ex) {
Logger.getLogger(Subscriptions.class.getName()).log(Level.SEVERE, null, ex);
throw new HttpStatusCodeException(400, "Unable to parse feed.", ex);
}
}
public void callback(String callbackPath, byte[] feed) {
public void callback(final String callbackPath, final byte[] feed) {
this.callback(callbackPath, new ByteArrayInputStream(feed));
}
public void callback(String callbackPath, SyndFeed feed) {
public void callback(final String callbackPath, final SyndFeed feed) {
if (!callbackPath.startsWith(callbackPrefix)) {
throw new HttpStatusCodeException(404, "Not a valid callback prefix.", new Exception(callbackPath+" doesnt start with "+callbackPrefix));
throw new HttpStatusCodeException(404, "Not a valid callback prefix.", new Exception(callbackPath + " doesnt start with " + callbackPrefix));
}
String id = callbackPath.substring(callbackPrefix.length());
final String id = callbackPath.substring(callbackPrefix.length());
Logger.getLogger(Subscriptions.class.getName()).log(Level.FINE, "Got callback for {0}", id);
Subscription s = dao.findById(id);
final Subscription s = dao.findById(id);
if (s == null) {
throw new HttpStatusCodeException(404, "Not a valid callback.", null);
}
this.validateLink(feed, s.getSourceUrl());
validateLink(feed, s.getSourceUrl());
SyndFeedInfo info = null;
URL url = null;
@ -123,9 +114,8 @@ public class Subscriptions {
try {
url = new URL(s.getSourceUrl());
info = cache.getFeedInfo(url);
} catch (MalformedURLException ex) {
Logger.getLogger(Subscriptions.class.getName())
.log(Level.SEVERE, null, ex);
} catch (final MalformedURLException ex) {
Logger.getLogger(Subscriptions.class.getName()).log(Level.SEVERE, null, ex);
}
if (info == null) {
@ -141,58 +131,53 @@ public class Subscriptions {
s.getCallback().onNotify(s, info);
}
public void unsubscribe(final Subscription subscription, String hubUrl, boolean sync, String secret,
final SubscriptionCallback callback) {
public void unsubscribe(final Subscription subscription, final String hubUrl, final boolean sync, final String secret, final SubscriptionCallback callback) {
subscription.setUnsubscribed(true);
this.requester.sendUnsubscribeRequest(hubUrl, subscription, (sync ? "sync" : "async"), secret,
this.callbackPrefix + subscription.getId(),
new RequestCallback() {
@Override
public void onSuccess() {
callback.onUnsubscribe(subscription);
}
requester.sendUnsubscribeRequest(hubUrl, subscription, sync ? "sync" : "async", secret, callbackPrefix + subscription.getId(), new RequestCallback() {
@Override
public void onSuccess() {
callback.onUnsubscribe(subscription);
}
@Override
public void onFailure(Exception e) {
callback.onFailure(e);
}
});
@Override
public void onFailure(final Exception e) {
callback.onFailure(e);
}
});
}
public void subscribe(String hubUrl, String topic, boolean sync, long leaseSeconds, String secret,
final SubscriptionCallback callback) {
Subscription s = new Subscription();
public void subscribe(final String hubUrl, final String topic, final boolean sync, final long leaseSeconds, final String secret,
final SubscriptionCallback callback) {
final Subscription s = new Subscription();
s.setId(UUID.randomUUID().toString());
s.setVerifyToken(UUID.randomUUID().toString());
s.setSourceUrl(topic);
s.setCallback(callback);
if (leaseSeconds > 0) {
s.setExpirationTime(System.currentTimeMillis() + (leaseSeconds * 1000));
s.setExpirationTime(System.currentTimeMillis() + leaseSeconds * 1000);
}
final Subscription stored = this.dao.addSubscription(s);
final Subscription stored = dao.addSubscription(s);
this.requester.sendSubscribeRequest(hubUrl, stored, (sync ? "sync" : "async"), leaseSeconds, secret,
this.callbackPrefix + stored.getId(),
new RequestCallback() {
@Override
public void onSuccess() {
callback.onSubscribe(stored);
}
requester.sendSubscribeRequest(hubUrl, stored, sync ? "sync" : "async", leaseSeconds, secret, callbackPrefix + stored.getId(), new RequestCallback() {
@Override
public void onSuccess() {
callback.onSubscribe(stored);
}
@Override
public void onFailure(Exception e) {
callback.onFailure(e);
}
});
@Override
public void onFailure(final Exception e) {
callback.onFailure(e);
}
});
}
public void subscribe(String topic, boolean sync, long leaseSeconds, String secret,
final SubscriptionCallback callback) throws IllegalArgumentException, IOException, FeedException {
SyndFeedInput input = new SyndFeedInput();
SyndFeed feed = input.build(new InputStreamReader(new URL(topic).openStream()));
String hubUrl = this.findHubUrl(feed);
public void subscribe(final String topic, final boolean sync, final long leaseSeconds, final String secret, final SubscriptionCallback callback)
throws IllegalArgumentException, IOException, FeedException {
final SyndFeedInput input = new SyndFeedInput();
final SyndFeed feed = input.build(new InputStreamReader(new URL(topic).openStream()));
final String hubUrl = findHubUrl(feed);
if (hubUrl == null) {
throw new FeedException("No hub link");
@ -201,20 +186,19 @@ public class Subscriptions {
this.subscribe(hubUrl, topic, sync, leaseSeconds, secret, callback);
}
public String validate(String callbackPath, String topic, String mode, String challenge, String leaseSeconds,
String verifyToken) {
public String validate(final String callbackPath, final String topic, final String mode, final String challenge, final String leaseSeconds,
final String verifyToken) {
if (!callbackPath.startsWith(callbackPrefix)) {
throw new HttpStatusCodeException(404, "Not a valid callback prefix.", new Exception(callbackPath+" doesnt start with "+callbackPrefix));
throw new HttpStatusCodeException(404, "Not a valid callback prefix.", new Exception(callbackPath + " doesnt start with " + callbackPrefix));
}
String id = callbackPath.substring(callbackPrefix.length());
final String id = callbackPath.substring(callbackPrefix.length());
Logger.getLogger(Subscriptions.class.getName()).log(Level.FINE, "Handling validation request for id {0}", id);
Subscription s = dao.findById(id);
if(s == null){
final Subscription s = dao.findById(id);
if (s == null) {
throw new HttpStatusCodeException(404, "Not a valid subscription id", null);
}
if (!s.getVerifyToken()
.equals(verifyToken)) {
if (!s.getVerifyToken().equals(verifyToken)) {
throw new HttpStatusCodeException(403, "Verification Token Mismatch.", null);
}
@ -238,8 +222,8 @@ public class Subscriptions {
return challenge;
}
private String findHubUrl(SyndFeed feed) {
for (SyndLink l : (List<SyndLink>) feed.getLinks()) {
private String findHubUrl(final SyndFeed feed) {
for (final SyndLink l : feed.getLinks()) {
if ("hub".equals(l.getRel())) {
return l.getHref();
}
@ -248,21 +232,20 @@ public class Subscriptions {
return null;
}
private void validateLink(SyndFeed feed, String source) {
for (SyndLink l : (List<SyndLink>) feed.getLinks()) {
private void validateLink(final SyndFeed feed, final String source) {
for (final SyndLink l : feed.getLinks()) {
if ("self".equalsIgnoreCase(l.getRel())) {
try {
URI u = new URI(l.getHref());
URI t = new URI(source);
final URI u = new URI(l.getHref());
final URI t = new URI(source);
if (!u.equals(t)) {
throw new HttpStatusCodeException(400, "Feed self link does not match the subscribed URI.", null);
}
break;
} catch (URISyntaxException ex) {
Logger.getLogger(Subscriptions.class.getName())
.log(Level.SEVERE, null, ex);
} catch (final URISyntaxException ex) {
Logger.getLogger(Subscriptions.class.getName()).log(Level.SEVERE, null, ex);
}
}
}
@ -271,28 +254,28 @@ public class Subscriptions {
/**
* @param cache the cache to set
*/
public void setCache(FeedFetcherCache cache) {
public void setCache(final FeedFetcherCache cache) {
this.cache = cache;
}
/**
* @param requester the requester to set
*/
public void setRequester(Requester requester) {
public void setRequester(final Requester requester) {
this.requester = requester;
}
/**
* @param callbackPrefix the callbackPrefix to set
*/
public void setCallbackPrefix(String callbackPrefix) {
public void setCallbackPrefix(final String callbackPrefix) {
this.callbackPrefix = callbackPrefix;
}
/**
* @param dao the dao to set
*/
public void setDao(SubDAO dao) {
public void setDao(final SubDAO dao) {
this.dao = dao;
}
}

View file

@ -16,11 +16,10 @@
* limitations under the License.
*/
package org.rometools.certiorem.sub.data;
/**
*
*
* @author robert.cooper
*/
public interface SubDAO {

View file

@ -20,9 +20,8 @@ package org.rometools.certiorem.sub.data;
import java.io.Serializable;
/**
*
*
* @author robert.cooper
*/
public class Subscription implements Serializable {
@ -36,110 +35,110 @@ public class Subscription implements Serializable {
/**
* Set the value of expirationTime
*
*
* @param newexpirationTime new value of expirationTime
*/
public void setExpirationTime(long newexpirationTime) {
this.expirationTime = newexpirationTime;
public void setExpirationTime(final long newexpirationTime) {
expirationTime = newexpirationTime;
}
/**
* Get the value of expirationTime
*
*
* @return the value of expirationTime
*/
public long getExpirationTime() {
return this.expirationTime;
return expirationTime;
}
/**
* Set the value of id
*
*
* @param newid new value of id
*/
public void setId(String newid) {
this.id = newid;
public void setId(final String newid) {
id = newid;
}
/**
* Get the value of id
*
*
* @return the value of id
*/
public String getId() {
return this.id;
return id;
}
/**
* Set the value of sourceUrl
*
*
* @param newsourceUrl new value of sourceUrl
*/
public void setSourceUrl(String newsourceUrl) {
this.sourceUrl = newsourceUrl;
public void setSourceUrl(final String newsourceUrl) {
sourceUrl = newsourceUrl;
}
/**
* Get the value of sourceUrl
*
*
* @return the value of sourceUrl
*/
public String getSourceUrl() {
return this.sourceUrl;
return sourceUrl;
}
/**
* Set the value of unsubscribed
*
*
* @param newunsubscribed new value of unsubscribed
*/
public void setUnsubscribed(boolean newunsubscribed) {
this.unsubscribed = newunsubscribed;
public void setUnsubscribed(final boolean newunsubscribed) {
unsubscribed = newunsubscribed;
}
/**
* Get the value of unsubscribed
*
*
* @return the value of unsubscribed
*/
public boolean isUnsubscribed() {
return this.unsubscribed;
return unsubscribed;
}
/**
* Set the value of validated
*
*
* @param newvalidated new value of validated
*/
public void setValidated(boolean newvalidated) {
this.validated = newvalidated;
public void setValidated(final boolean newvalidated) {
validated = newvalidated;
}
/**
* Get the value of validated
*
*
* @return the value of validated
*/
public boolean isValidated() {
return this.validated;
return validated;
}
/**
* Set the value of verifyToken
*
*
* @param newverifyToken new value of verifyToken
*/
public void setVerifyToken(String newverifyToken) {
this.verifyToken = newverifyToken;
public void setVerifyToken(final String newverifyToken) {
verifyToken = newverifyToken;
}
/**
* Get the value of verifyToken
*
*
* @return the value of verifyToken
*/
public String getVerifyToken() {
return this.verifyToken;
return verifyToken;
}
/**
@ -152,7 +151,7 @@ public class Subscription implements Serializable {
/**
* @param callback the callback to set
*/
public void setCallback(SubscriptionCallback callback) {
public void setCallback(final SubscriptionCallback callback) {
this.callback = callback;
}
}

View file

@ -8,7 +8,7 @@ package org.rometools.certiorem.sub.data;
import org.rometools.fetcher.impl.SyndFeedInfo;
/**
*
*
* @author najmi
*/
public interface SubscriptionCallback {
@ -18,6 +18,6 @@ public interface SubscriptionCallback {
void onFailure(Exception e);
void onSubscribe(Subscription subscribed);
void onUnsubscribe(Subscription subscribed);
}

View file

@ -27,25 +27,27 @@ import java.util.Date;
import java.util.concurrent.ConcurrentHashMap;
import java.util.logging.Level;
import java.util.logging.Logger;
import org.rometools.certiorem.sub.data.SubDAO;
import org.rometools.certiorem.sub.data.Subscription;
/**
*
*
* @author robert.cooper
*/
public class InMemorySubDAO implements SubDAO {
private ConcurrentHashMap<String, Subscription> subscriptions = new ConcurrentHashMap<String, Subscription>();
private final ConcurrentHashMap<String, Subscription> subscriptions = new ConcurrentHashMap<String, Subscription>();
@Override
public Subscription findById(String id) {
Subscription s = subscriptions.get(id);
if(s == null){
public Subscription findById(final String id) {
final Subscription s = subscriptions.get(id);
if (s == null) {
return null;
}
if(s.getExpirationTime() > 0 && s.getExpirationTime() <= System.currentTimeMillis()){
Logger.getLogger(InMemorySubDAO.class.getName()).log(Level.FINE, "Subscription {0} expired at {1}", new Object[]{s.getSourceUrl(), new Date(s.getExpirationTime())});
if (s.getExpirationTime() > 0 && s.getExpirationTime() <= System.currentTimeMillis()) {
Logger.getLogger(InMemorySubDAO.class.getName()).log(Level.FINE, "Subscription {0} expired at {1}",
new Object[] { s.getSourceUrl(), new Date(s.getExpirationTime()) });
subscriptions.remove(id);
return null;
@ -54,20 +56,20 @@ public class InMemorySubDAO implements SubDAO {
}
@Override
public Subscription addSubscription(Subscription s) {
public Subscription addSubscription(final Subscription s) {
subscriptions.put(s.getId(), s);
Logger.getLogger(InMemorySubDAO.class.getName()).log(Level.FINE, "Stored subscription {0} {1}", new Object[]{s.getSourceUrl(), s.getId()});
Logger.getLogger(InMemorySubDAO.class.getName()).log(Level.FINE, "Stored subscription {0} {1}", new Object[] { s.getSourceUrl(), s.getId() });
return s;
}
@Override
public Subscription updateSubscription(Subscription s) {
public Subscription updateSubscription(final Subscription s) {
subscriptions.put(s.getId(), s);
return s;
}
@Override
public void removeSubscription(Subscription s) {
public void removeSubscription(final Subscription s) {
subscriptions.remove(s.getId());
}

View file

@ -16,64 +16,51 @@
* limitations under the License.
*/
package org.rometools.certiorem.sub.request;
import org.rometools.certiorem.sub.Requester;
import org.rometools.certiorem.sub.data.Subscription;
import java.io.IOException;
import java.net.HttpURLConnection;
import java.net.URL;
import java.net.URLEncoder;
import org.rometools.certiorem.sub.Requester;
import org.rometools.certiorem.sub.data.Subscription;
/**
*
*
* @author robert.cooper
*/
public abstract class AbstractRequester implements Requester {
protected boolean sendRequest(String hubUrl, String mode, Subscription subscription, String verifySync,
long leaseSeconds, String secret, String callbackUrl, RequestCallback callback)
throws IOException {
StringBuilder sb = new StringBuilder("hub.callback=").append(URLEncoder.encode(callbackUrl, "UTF-8"))
.append("&hub.topic=")
.append(URLEncoder.encode(subscription.getSourceUrl(),
"UTF-8"))
.append("&hub.verify=")
.append(URLEncoder.encode(verifySync, "UTF-8"))
.append("&hub.mode=")
.append(URLEncoder.encode(mode, "UTF-8"));
protected boolean sendRequest(final String hubUrl, final String mode, final Subscription subscription, final String verifySync, final long leaseSeconds,
final String secret, final String callbackUrl, final RequestCallback callback) throws IOException {
final StringBuilder sb = new StringBuilder("hub.callback=").append(URLEncoder.encode(callbackUrl, "UTF-8")).append("&hub.topic=")
.append(URLEncoder.encode(subscription.getSourceUrl(), "UTF-8")).append("&hub.verify=").append(URLEncoder.encode(verifySync, "UTF-8"))
.append("&hub.mode=").append(URLEncoder.encode(mode, "UTF-8"));
if (leaseSeconds > 0) {
sb.append("&hub.lease_seconds=")
.append(Long.toString(leaseSeconds));
sb.append("&hub.lease_seconds=").append(Long.toString(leaseSeconds));
}
if (secret != null) {
sb.append("&hub.secret=")
.append(URLEncoder.encode(secret, "UTF-8"));
sb.append("&hub.secret=").append(URLEncoder.encode(secret, "UTF-8"));
}
if (subscription.getVerifyToken() != null) {
sb.append("&hub.verify_token=")
.append(URLEncoder.encode(subscription.getVerifyToken(), "UTF-8"));
sb.append("&hub.verify_token=").append(URLEncoder.encode(subscription.getVerifyToken(), "UTF-8"));
}
URL url = new URL(hubUrl);
HttpURLConnection connection = (HttpURLConnection) url.openConnection();
final URL url = new URL(hubUrl);
final HttpURLConnection connection = (HttpURLConnection) url.openConnection();
connection.setRequestMethod("POST");
connection.setRequestProperty("Content-Type", "application/x-www-form-urlencoded");
connection.setDoOutput(true);
// connection.setRequestProperty("Host", url.getHost());
// connection.setRequestProperty("Host", url.getHost());
connection.setRequestProperty("User-Agent", "ROME-Certiorem");
connection.connect();
connection.getOutputStream()
.write(sb.toString().getBytes("UTF-8"));
connection.getOutputStream().write(sb.toString().getBytes("UTF-8"));
int rc = connection.getResponseCode();
final int rc = connection.getResponseCode();
connection.disconnect();
if (rc != 204) {

View file

@ -18,57 +18,53 @@
package org.rometools.certiorem.sub.request;
import org.rometools.certiorem.sub.data.Subscription;
import java.io.IOException;
import java.util.logging.Level;
import java.util.logging.Logger;
import org.rometools.certiorem.sub.data.Subscription;
/**
* A simple requester implementation that always makes requests as Async.
*
* @author robert.cooper
*/
public class AsyncRequester extends AbstractRequester {
@Override
public void sendSubscribeRequest(final String hubUrl, final Subscription subscription, final String verifySync,
final long leaseSeconds, final String secret, final String callbackUrl, final RequestCallback callback) {
Logger.getLogger(AsyncRequester.class.getName()).log(Level.FINE, "Sending subscribe request to {0} for {1} to {2}", new Object[]{hubUrl, subscription.getSourceUrl(), callbackUrl});
Runnable r = new Runnable() {
@Override
public void run() {
try {
sendRequest(hubUrl, "subscribe", subscription, verifySync, leaseSeconds, secret, callbackUrl,
callback);
} catch (Exception ex) {
Logger.getLogger(AsyncRequester.class.getName())
.log(Level.SEVERE, null, ex);
callback.onFailure(ex);
}
public void sendSubscribeRequest(final String hubUrl, final Subscription subscription, final String verifySync, final long leaseSeconds,
final String secret, final String callbackUrl, final RequestCallback callback) {
Logger.getLogger(AsyncRequester.class.getName()).log(Level.FINE, "Sending subscribe request to {0} for {1} to {2}",
new Object[] { hubUrl, subscription.getSourceUrl(), callbackUrl });
final Runnable r = new Runnable() {
@Override
public void run() {
try {
sendRequest(hubUrl, "subscribe", subscription, verifySync, leaseSeconds, secret, callbackUrl, callback);
} catch (final Exception ex) {
Logger.getLogger(AsyncRequester.class.getName()).log(Level.SEVERE, null, ex);
callback.onFailure(ex);
}
};
new Thread(r).start();
}
};
new Thread(r).start();
}
@Override
public void sendUnsubscribeRequest(final String hubUrl, final Subscription subscription, final String verifySync,
final String secret,
final String callbackUrl, final RequestCallback callback) {
Logger.getLogger(AsyncRequester.class.getName()).log(Level.FINE, "Sending unsubscribe request to {0} for {1} to {2}", new Object[]{hubUrl, subscription.getSourceUrl(), callbackUrl});
Runnable r = new Runnable() {
@Override
public void run() {
try {
sendRequest(hubUrl, "unsubscribe", subscription, verifySync, -1, secret, callbackUrl,
callback);
} catch (IOException ex) {
Logger.getLogger(AsyncRequester.class.getName())
.log(Level.SEVERE, null, ex);
callback.onFailure(ex);
}
public void sendUnsubscribeRequest(final String hubUrl, final Subscription subscription, final String verifySync, final String secret,
final String callbackUrl, final RequestCallback callback) {
Logger.getLogger(AsyncRequester.class.getName()).log(Level.FINE, "Sending unsubscribe request to {0} for {1} to {2}",
new Object[] { hubUrl, subscription.getSourceUrl(), callbackUrl });
final Runnable r = new Runnable() {
@Override
public void run() {
try {
sendRequest(hubUrl, "unsubscribe", subscription, verifySync, -1, secret, callbackUrl, callback);
} catch (final IOException ex) {
Logger.getLogger(AsyncRequester.class.getName()).log(Level.SEVERE, null, ex);
callback.onFailure(ex);
}
};
new Thread(r).start();
}
};
new Thread(r).start();
}
}

View file

@ -22,46 +22,42 @@
*/
package org.rometools.certiorem.sub.request;
import org.rometools.certiorem.sub.data.Subscription;
import java.io.IOException;
import java.util.logging.Level;
import java.util.logging.Logger;
import org.rometools.certiorem.sub.data.Subscription;
/**
* A simple requester implementation that always makes requests as Async.
*
* @author Farrukh Najmi
*/
public class SyncRequester extends AbstractRequester {
@Override
public void sendSubscribeRequest(final String hubUrl, final Subscription subscription, final String verifySync,
final long leaseSeconds, final String secret, final String callbackUrl, final RequestCallback callback) {
Logger.getLogger(SyncRequester.class.getName()).log(Level.INFO, "Sending subscribe request to {0} for {1} to {2}", new Object[]{hubUrl, subscription.getSourceUrl(), callbackUrl});
public void sendSubscribeRequest(final String hubUrl, final Subscription subscription, final String verifySync, final long leaseSeconds,
final String secret, final String callbackUrl, final RequestCallback callback) {
Logger.getLogger(SyncRequester.class.getName()).log(Level.INFO, "Sending subscribe request to {0} for {1} to {2}",
new Object[] { hubUrl, subscription.getSourceUrl(), callbackUrl });
try {
sendRequest(hubUrl, "subscribe", subscription, verifySync, leaseSeconds, secret, callbackUrl,
callback);
sendRequest(hubUrl, "subscribe", subscription, verifySync, leaseSeconds, secret, callbackUrl, callback);
callback.onSuccess();
} catch (Exception ex) {
Logger.getLogger(SyncRequester.class.getName())
.log(Level.SEVERE, null, ex);
} catch (final Exception ex) {
Logger.getLogger(SyncRequester.class.getName()).log(Level.SEVERE, null, ex);
callback.onFailure(ex);
}
}
@Override
public void sendUnsubscribeRequest(final String hubUrl, final Subscription subscription, final String verifySync,
final String secret,
final String callbackUrl, final RequestCallback callback) {
Logger.getLogger(SyncRequester.class.getName()).log(Level.INFO, "Sending unsubscribe request to {0} for {1} to {2}", new Object[]{hubUrl, subscription.getSourceUrl(), callbackUrl});
public void sendUnsubscribeRequest(final String hubUrl, final Subscription subscription, final String verifySync, final String secret,
final String callbackUrl, final RequestCallback callback) {
Logger.getLogger(SyncRequester.class.getName()).log(Level.INFO, "Sending unsubscribe request to {0} for {1} to {2}",
new Object[] { hubUrl, subscription.getSourceUrl(), callbackUrl });
try {
sendRequest(hubUrl, "unsubscribe", subscription, verifySync, -1, secret, callbackUrl,
callback);
sendRequest(hubUrl, "unsubscribe", subscription, verifySync, -1, secret, callbackUrl, callback);
callback.onSuccess();
} catch (IOException ex) {
Logger.getLogger(SyncRequester.class.getName())
.log(Level.SEVERE, null, ex);
} catch (final IOException ex) {
Logger.getLogger(SyncRequester.class.getName()).log(Level.SEVERE, null, ex);
callback.onFailure(ex);
}
}

View file

@ -16,14 +16,9 @@
* limitations under the License.
*/
package org.rometools.certiorem.web;
import org.rometools.certiorem.HttpStatusCodeException;
import org.rometools.certiorem.hub.Hub;
import java.io.IOException;
import java.util.Arrays;
import javax.servlet.ServletException;
@ -31,9 +26,11 @@ import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.rometools.certiorem.HttpStatusCodeException;
import org.rometools.certiorem.hub.Hub;
/**
*
*
* @author robert.cooper
*/
public abstract class AbstractHubServlet extends HttpServlet {
@ -46,37 +43,34 @@ public abstract class AbstractHubServlet extends HttpServlet {
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp)
throws ServletException, IOException {
protected void doPost(final HttpServletRequest req, final HttpServletResponse resp) throws ServletException, IOException {
try {
if ("publish".equals(req.getParameter(HUBMODE))) {
hub.sendNotification(req.getServerName(), req.getParameter("hub.url"));
} else {
String callback = req.getParameter("hub.callback");
String topic = req.getParameter("hub.topic");
String[] verifies = req.getParameterValues("hub.verify");
String leaseString = req.getParameter("hub.lease_seconds");
String secret = req.getParameter("hub.secret");
String verifyToken = req.getParameter("hub.verify_token");
String verifyMode = Arrays.asList(verifies)
.contains("async") ? "async" : "sync";
final String callback = req.getParameter("hub.callback");
final String topic = req.getParameter("hub.topic");
final String[] verifies = req.getParameterValues("hub.verify");
final String leaseString = req.getParameter("hub.lease_seconds");
final String secret = req.getParameter("hub.secret");
final String verifyToken = req.getParameter("hub.verify_token");
final String verifyMode = Arrays.asList(verifies).contains("async") ? "async" : "sync";
Boolean result = null;
if ("subscribe".equals(req.getParameter(HUBMODE))) {
long leaseSeconds = (leaseString != null) ? Long.parseLong(leaseString) : (-1);
final long leaseSeconds = leaseString != null ? Long.parseLong(leaseString) : -1;
result = hub.subscribe(callback, topic, verifyMode, leaseSeconds, secret, verifyToken);
} else if ("unsubscribe".equals(req.getParameter(HUBMODE))) {
result = hub.unsubscribe(callback, topic, verifyMode, secret, verifyToken);
}
if ((result != null) && !result) {
if (result != null && !result) {
throw new HttpStatusCodeException(500, "Operation failed.", null);
}
}
} catch (HttpStatusCodeException sc) {
} catch (final HttpStatusCodeException sc) {
resp.setStatus(sc.getStatus());
resp.getWriter()
.println(sc.getMessage());
resp.getWriter().println(sc.getMessage());
return;
}

View file

@ -16,45 +16,46 @@
* limitations under the License.
*/
package org.rometools.certiorem.web;
import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpUtils;
import org.rometools.certiorem.HttpStatusCodeException;
import org.rometools.certiorem.sub.Subscriptions;
/**
*
*
* @author robert.cooper
*/
public class AbstractSubServlet extends HttpServlet {
private final Subscriptions subscriptions;
protected AbstractSubServlet(final Subscriptions subscriptions){
protected AbstractSubServlet(final Subscriptions subscriptions) {
super();
this.subscriptions = subscriptions;
}
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
String mode = req.getParameter("hub.mode");
String topic = req.getParameter("hub.topic");
String challenge = req.getParameter("hub.challenge");
String leaseString = req.getParameter("hub.lease_seconds");
String verifyToken = req.getParameter("hub.verify_token");
try{
String result = subscriptions.validate(HttpUtils.getRequestURL(req).toString(), topic, mode, challenge, leaseString, verifyToken);
protected void doGet(final HttpServletRequest req, final HttpServletResponse resp) throws ServletException, IOException {
final String mode = req.getParameter("hub.mode");
final String topic = req.getParameter("hub.topic");
final String challenge = req.getParameter("hub.challenge");
final String leaseString = req.getParameter("hub.lease_seconds");
final String verifyToken = req.getParameter("hub.verify_token");
try {
final String result = subscriptions.validate(HttpUtils.getRequestURL(req).toString(), topic, mode, challenge, leaseString, verifyToken);
resp.setStatus(200);
resp.getWriter().print(result);
return;
} catch(HttpStatusCodeException e){
} catch (final HttpStatusCodeException e) {
e.printStackTrace();
resp.setStatus(e.getStatus());
resp.getWriter().print(e.getMessage());
@ -63,17 +64,15 @@ public class AbstractSubServlet extends HttpServlet {
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
try{
this.subscriptions.callback(HttpUtils.getRequestURL(req).toString(), req.getInputStream());
protected void doPost(final HttpServletRequest req, final HttpServletResponse resp) throws ServletException, IOException {
try {
subscriptions.callback(HttpUtils.getRequestURL(req).toString(), req.getInputStream());
return;
} catch(HttpStatusCodeException e){
} catch (final HttpStatusCodeException e) {
e.printStackTrace();
resp.setStatus(e.getStatus());
resp.getWriter().println(e.getMessage());
}
}
}

View file

@ -16,34 +16,33 @@
* limitations under the License.
*/
package org.rometools.certiorem.hub;
import org.rometools.certiorem.hub.data.Subscriber;
/**
*
*
* @author robert.cooper
*/
public class AlwaysVerifier implements Verifier {
@Override
public void verifySubscribeAsyncronously(Subscriber subscriber, VerificationCallback callback) {
public void verifySubscribeAsyncronously(final Subscriber subscriber, final VerificationCallback callback) {
callback.onVerify(true);
}
@Override
public boolean verifySubcribeSyncronously(Subscriber subscriber) {
public boolean verifySubcribeSyncronously(final Subscriber subscriber) {
return true;
}
@Override
public void verifyUnsubscribeAsyncronously(Subscriber subscriber, VerificationCallback callback) {
public void verifyUnsubscribeAsyncronously(final Subscriber subscriber, final VerificationCallback callback) {
callback.onVerify(true);
}
@Override
public boolean verifyUnsubcribeSyncronously(Subscriber subscriber) {
public boolean verifyUnsubcribeSyncronously(final Subscriber subscriber) {
return true;
}

View file

@ -18,25 +18,25 @@
package org.rometools.certiorem.hub;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.fail;
import java.util.logging.Logger;
import org.junit.After;
import org.junit.AfterClass;
import org.junit.Before;
import org.junit.BeforeClass;
import org.junit.Test;
import org.rometools.certiorem.HttpStatusCodeException;
import org.rometools.certiorem.hub.data.HubDAO;
import org.rometools.certiorem.hub.data.ram.InMemoryHubDAO;
import org.rometools.fetcher.FeedFetcher;
import org.rometools.fetcher.impl.HashMapFeedInfoCache;
import org.rometools.fetcher.impl.HttpURLFeedFetcher;
import org.junit.After;
import org.junit.AfterClass;
import static org.junit.Assert.*;
import org.junit.Before;
import org.junit.BeforeClass;
import org.junit.Test;
import org.rometools.certiorem.hub.data.HubDAO;
import org.rometools.certiorem.hub.data.ram.InMemoryHubDAO;
/**
*
*
* @author robert.cooper
*/
public class ControllerTest {
@ -66,14 +66,14 @@ public class ControllerTest {
public void testSubscribe() {
Logger.getLogger(ControllerTest.class.getName()).info("subscribe");
String callback = "http://localhost/doNothing";
String topic = "http://feeds.feedburner.com/screaming-penguin";
long lease_seconds = -1;
String secret = null;
String verify_token = "MyVoiceIsMyPassport";
HubDAO dao = new InMemoryHubDAO();
Notifier notifier = null;
FeedFetcher fetcher = new HttpURLFeedFetcher(HashMapFeedInfoCache.getInstance());
final String callback = "http://localhost/doNothing";
final String topic = "http://feeds.feedburner.com/screaming-penguin";
final long lease_seconds = -1;
final String secret = null;
final String verify_token = "MyVoiceIsMyPassport";
final HubDAO dao = new InMemoryHubDAO();
final Notifier notifier = null;
final FeedFetcher fetcher = new HttpURLFeedFetcher(HashMapFeedInfoCache.getInstance());
Hub instance = new Hub(dao, new AlwaysVerifier(), notifier, fetcher);
Boolean result = instance.subscribe(callback, topic, "sync", lease_seconds, secret, verify_token);
@ -90,7 +90,7 @@ public class ControllerTest {
try {
instance.subscribe(null, topic, "async", lease_seconds, secret, verify_token);
fail();
} catch (HttpStatusCodeException e) {
} catch (final HttpStatusCodeException e) {
assertEquals(400, e.getStatus());
Logger.getLogger(ControllerTest.class.getName()).info(e.getMessage());
}
@ -98,7 +98,7 @@ public class ControllerTest {
try {
instance.subscribe(callback, null, "async", lease_seconds, secret, verify_token);
fail();
} catch (HttpStatusCodeException e) {
} catch (final HttpStatusCodeException e) {
assertEquals(400, e.getStatus());
Logger.getLogger(ControllerTest.class.getName()).info(e.getMessage());
}
@ -106,7 +106,7 @@ public class ControllerTest {
try {
instance.subscribe(callback, topic, "foo", lease_seconds, secret, verify_token);
fail();
} catch (HttpStatusCodeException e) {
} catch (final HttpStatusCodeException e) {
assertEquals(400, e.getStatus());
Logger.getLogger(ControllerTest.class.getName()).info(e.getMessage());
}
@ -117,7 +117,7 @@ public class ControllerTest {
try {
result = instance.subscribe(callback, topic, "sync", lease_seconds, secret, verify_token);
fail();
} catch (HttpStatusCodeException e) {
} catch (final HttpStatusCodeException e) {
assertEquals(500, e.getStatus());
}
}

View file

@ -5,29 +5,32 @@
package org.rometools.certiorem.hub;
import java.io.IOException;
import com.sun.syndication.feed.synd.SyndEntry;
import java.util.List;
import junit.framework.Assert;
import org.rometools.fetcher.impl.HashMapFeedInfoCache;
import org.rometools.fetcher.impl.HttpURLFeedFetcher;
import java.net.URL;
import com.sun.syndication.feed.synd.SyndFeed;
import java.util.List;
import junit.framework.Assert;
import org.junit.After;
import org.junit.AfterClass;
import org.junit.Before;
import org.junit.BeforeClass;
import org.junit.Test;
import org.rometools.fetcher.impl.HashMapFeedInfoCache;
import org.rometools.fetcher.impl.HttpURLFeedFetcher;
import com.sun.syndication.feed.synd.SyndEntry;
import com.sun.syndication.feed.synd.SyndFeed;
/**
*
*
* @author najmi
*/
public class DeltaSyndFeedInfoTest {
DeltaFeedInfoCache feedInfoCache;
HttpURLFeedFetcher feedFetcher;
SyndFeed feed;
public DeltaSyndFeedInfoTest() {
}
@ -38,18 +41,16 @@ public class DeltaSyndFeedInfoTest {
@AfterClass
public static void tearDownClass() throws Exception {
}
@Before
public void setUp() {
feedInfoCache = new DeltaFeedInfoCache(new HashMapFeedInfoCache());
feedFetcher = new HttpURLFeedFetcher(feedInfoCache);
}
@After
public void tearDown() {
public void tearDown() {
}
/**
* Test of getSyndFeed method, of class DeltaSyndFeedInfo.
@ -57,21 +58,21 @@ public class DeltaSyndFeedInfoTest {
@Test
public void testGetSyndFeed() throws Exception {
System.out.println("getSyndFeed");
feed = feedFetcher.retrieveFeed(getFeedUrl());
List<SyndEntry> entries = feed.getEntries();
Assert.assertTrue(!entries.isEmpty());
//Fetch again and this time the entries should be empty as none have changed.
// Fetch again and this time the entries should be empty as none have changed.
feed = feedFetcher.retrieveFeed(getFeedUrl());
entries = feed.getEntries();
Assert.assertTrue(entries.isEmpty());
Assert.assertTrue(entries.isEmpty());
}
private URL getFeedUrl() throws IOException {
URL feedUrl = new URL("http://news.google.com/news?pz=1&cf=all&ned=us&hl=en&output=rss");
// URL feedUrl = new URL("http://newsrss.bbc.co.uk/rss/newsonline_world_edition/front_page/rss.xml");
final URL feedUrl = new URL("http://news.google.com/news?pz=1&cf=all&ned=us&hl=en&output=rss");
// URL feedUrl = new URL("http://newsrss.bbc.co.uk/rss/newsonline_world_edition/front_page/rss.xml");
return feedUrl;
}
}
}

View file

@ -16,34 +16,33 @@
* limitations under the License.
*/
package org.rometools.certiorem.hub;
import org.rometools.certiorem.hub.data.Subscriber;
/**
*
*
* @author robert.cooper
*/
public class ExceptionVerifier implements Verifier{
public class ExceptionVerifier implements Verifier {
@Override
public void verifySubscribeAsyncronously(Subscriber subscriber, VerificationCallback callback) {
public void verifySubscribeAsyncronously(final Subscriber subscriber, final VerificationCallback callback) {
throw new UnsupportedOperationException("Not supported yet.");
}
@Override
public boolean verifySubcribeSyncronously(Subscriber subscriber) {
public boolean verifySubcribeSyncronously(final Subscriber subscriber) {
throw new UnsupportedOperationException("Not supported yet.");
}
@Override
public void verifyUnsubscribeAsyncronously(Subscriber subscriber, VerificationCallback callback) {
public void verifyUnsubscribeAsyncronously(final Subscriber subscriber, final VerificationCallback callback) {
throw new UnsupportedOperationException("Not supported yet.");
}
@Override
public boolean verifyUnsubcribeSyncronously(Subscriber subscriber) {
public boolean verifyUnsubcribeSyncronously(final Subscriber subscriber) {
throw new UnsupportedOperationException("Not supported yet.");
}

View file

@ -16,34 +16,33 @@
* limitations under the License.
*/
package org.rometools.certiorem.hub;
import org.rometools.certiorem.hub.data.Subscriber;
/**
*
*
* @author robert.cooper
*/
public class NeverVerifier implements Verifier{
public class NeverVerifier implements Verifier {
@Override
public void verifySubscribeAsyncronously(Subscriber subscriber, VerificationCallback callback) {
public void verifySubscribeAsyncronously(final Subscriber subscriber, final VerificationCallback callback) {
callback.onVerify(false);
}
@Override
public boolean verifySubcribeSyncronously(Subscriber subscriber) {
public boolean verifySubcribeSyncronously(final Subscriber subscriber) {
return false;
}
@Override
public void verifyUnsubscribeAsyncronously(Subscriber subscriber, VerificationCallback callback) {
public void verifyUnsubscribeAsyncronously(final Subscriber subscriber, final VerificationCallback callback) {
callback.onVerify(false);
}
@Override
public boolean verifyUnsubcribeSyncronously(Subscriber subscriber) {
public boolean verifyUnsubcribeSyncronously(final Subscriber subscriber) {
return false;
}

View file

@ -21,10 +21,11 @@ package org.rometools.certiorem.hub.data;
import java.util.List;
import java.util.logging.Level;
import java.util.logging.Logger;
import org.junit.Test;
/**
*
*
* @author robert.cooper
*/
public abstract class AbstractDAOTest {
@ -33,40 +34,40 @@ public abstract class AbstractDAOTest {
@Test
public void testSubscribe() {
HubDAO instance = get();
final HubDAO instance = get();
Logger.getLogger(AbstractDAOTest.class.getName()).log(Level.INFO, "{0} testSubscribe", instance.getClass().getName());
Subscriber subscriber = new Subscriber();
final Subscriber subscriber = new Subscriber();
subscriber.setCallback("http://localhost:9797/noop");
subscriber.setTopic("http://feeds.feedburner.com/screaming-penguin");
subscriber.setLeaseSeconds(-1);
subscriber.setVerify("VerifyMe");
Subscriber result = instance.addSubscriber(subscriber);
final Subscriber result = instance.addSubscriber(subscriber);
assert result.equals(subscriber) : "Subscriber not equal.";
List<Subscriber> subscribers = (List<Subscriber>) instance.subscribersForTopic(subscriber.getTopic());
final List<Subscriber> subscribers = (List<Subscriber>) instance.subscribersForTopic(subscriber.getTopic());
assert subscribers.contains(result) : "Subscriber not in result.";
}
@Test
public void testLeaseExpire() throws InterruptedException {
HubDAO instance = get();
final HubDAO instance = get();
Logger.getLogger(AbstractDAOTest.class.getName()).log(Level.INFO, "{0} testLeaseExpire", instance.getClass().getName());
Subscriber subscriber = new Subscriber();
final Subscriber subscriber = new Subscriber();
subscriber.setCallback("http://localhost:9797/noop");
subscriber.setTopic("http://feeds.feedburner.com/screaming-penguin");
subscriber.setLeaseSeconds(1);
subscriber.setVerify("VerifyMe");
Subscriber result = instance.addSubscriber(subscriber);
final Subscriber result = instance.addSubscriber(subscriber);
assert subscriber.equals(result) : "Subscriber not equal.";
//quick test for store.
// quick test for store.
List<Subscriber> subscribers = (List<Subscriber>) instance.subscribersForTopic(subscriber.getTopic());
assert subscribers.contains(result) : "Subscriber not in result.";
//sleep past expiration
// sleep past expiration
Thread.sleep(1100);
subscribers = (List<Subscriber>) instance.subscribersForTopic(subscriber.getTopic());
assert !subscribers.contains(result) : "Subscriber should have expired";
@ -74,15 +75,15 @@ public abstract class AbstractDAOTest {
@Test
public void testUnsubscribe() throws InterruptedException {
HubDAO instance = get();
final HubDAO instance = get();
Logger.getLogger(AbstractDAOTest.class.getName()).log(Level.INFO, "{0} testUnsubscribe", instance.getClass().getName());
Subscriber subscriber = new Subscriber();
final Subscriber subscriber = new Subscriber();
subscriber.setCallback("http://localhost:9797/noop");
subscriber.setTopic("http://feeds.feedburner.com/screaming-penguin");
subscriber.setLeaseSeconds(1);
subscriber.setVerify("VerifyMe");
Subscriber result = instance.addSubscriber(subscriber);
final Subscriber result = instance.addSubscriber(subscriber);
// TODO
}

View file

@ -16,18 +16,17 @@
* limitations under the License.
*/
package org.rometools.certiorem.hub.data.ram;
import org.rometools.certiorem.hub.data.AbstractDAOTest;
import org.rometools.certiorem.hub.data.HubDAO;
/**
*
*
* @author robert.cooper
*/
public class InMemoryDAOTest extends AbstractDAOTest{
private InMemoryHubDAO dao = new InMemoryHubDAO();
public class InMemoryDAOTest extends AbstractDAOTest {
private final InMemoryHubDAO dao = new InMemoryHubDAO();
public InMemoryDAOTest() {
}
@ -37,8 +36,4 @@ public class InMemoryDAOTest extends AbstractDAOTest{
return dao;
}
}

1
src/test/resources/.gitignore vendored Normal file
View file

@ -0,0 +1 @@
# needed to commit empty folder