Subtree merge in gwtexpui as gerrit-gwtexpui

Nobody uses the standalone gwtexpui project that we know of. Its
release process is frustrating, as even getting a simple bugfix into
Gerrit requires releasing gwtexpui (incrementing the version, tagging,
deploying, setting the next snapshot version).

Change-Id: I958ed659b8de8d855f7f9a7f4df66f6b4aad882f
This commit is contained in:
Dave Borowitz 2013-04-11 14:28:45 -07:00
commit dac17eac20
79 changed files with 6584 additions and 0 deletions

6
gerrit-gwtexpui/.gitignore vendored Normal file
View File

@ -0,0 +1,6 @@
/target
/generated_classes
/.classpath
/.project
/.settings/org.maven.ide.eclipse.prefs
.settings/org.eclipse.m2e.core.prefs

View File

@ -0,0 +1,4 @@
eclipse.preferences.version=1
encoding//src/main/java=UTF-8
encoding//src/test/java=UTF-8
encoding/<project>=UTF-8

View File

@ -0,0 +1,3 @@
#Tue Sep 02 16:59:24 PDT 2008
eclipse.preferences.version=1
line.separator=\n

View File

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

View File

@ -0,0 +1,61 @@
#Thu Nov 05 16:18:16 PST 2009
eclipse.preferences.version=1
editor_save_participant_org.eclipse.jdt.ui.postsavelistener.cleanup=true
formatter_profile=_Google Format
formatter_settings_version=11
org.eclipse.jdt.ui.ignorelowercasenames=true
org.eclipse.jdt.ui.importorder=com.google;com;junit;net;org;java;javax;
org.eclipse.jdt.ui.ondemandthreshold=99
org.eclipse.jdt.ui.staticondemandthreshold=99
org.eclipse.jdt.ui.text.custom_code_templates=<?xml version\="1.0" encoding\="UTF-8" standalone\="no"?><templates/>
sp_cleanup.add_default_serial_version_id=true
sp_cleanup.add_generated_serial_version_id=false
sp_cleanup.add_missing_annotations=false
sp_cleanup.add_missing_deprecated_annotations=true
sp_cleanup.add_missing_methods=false
sp_cleanup.add_missing_nls_tags=false
sp_cleanup.add_missing_override_annotations=true
sp_cleanup.add_serial_version_id=false
sp_cleanup.always_use_blocks=true
sp_cleanup.always_use_parentheses_in_expressions=false
sp_cleanup.always_use_this_for_non_static_field_access=false
sp_cleanup.always_use_this_for_non_static_method_access=false
sp_cleanup.convert_to_enhanced_for_loop=false
sp_cleanup.correct_indentation=false
sp_cleanup.format_source_code=false
sp_cleanup.format_source_code_changes_only=false
sp_cleanup.make_local_variable_final=true
sp_cleanup.make_parameters_final=true
sp_cleanup.make_private_fields_final=true
sp_cleanup.make_type_abstract_if_missing_method=false
sp_cleanup.make_variable_declarations_final=false
sp_cleanup.never_use_blocks=false
sp_cleanup.never_use_parentheses_in_expressions=true
sp_cleanup.on_save_use_additional_actions=true
sp_cleanup.organize_imports=false
sp_cleanup.qualify_static_field_accesses_with_declaring_class=false
sp_cleanup.qualify_static_member_accesses_through_instances_with_declaring_class=true
sp_cleanup.qualify_static_member_accesses_through_subtypes_with_declaring_class=true
sp_cleanup.qualify_static_member_accesses_with_declaring_class=false
sp_cleanup.qualify_static_method_accesses_with_declaring_class=false
sp_cleanup.remove_private_constructors=true
sp_cleanup.remove_trailing_whitespaces=true
sp_cleanup.remove_trailing_whitespaces_all=true
sp_cleanup.remove_trailing_whitespaces_ignore_empty=false
sp_cleanup.remove_unnecessary_casts=false
sp_cleanup.remove_unnecessary_nls_tags=false
sp_cleanup.remove_unused_imports=false
sp_cleanup.remove_unused_local_variables=false
sp_cleanup.remove_unused_private_fields=true
sp_cleanup.remove_unused_private_members=false
sp_cleanup.remove_unused_private_methods=true
sp_cleanup.remove_unused_private_types=true
sp_cleanup.sort_members=false
sp_cleanup.sort_members_all=false
sp_cleanup.use_blocks=false
sp_cleanup.use_blocks_only_for_return_and_throw=false
sp_cleanup.use_parentheses_in_expressions=false
sp_cleanup.use_this_for_non_static_field_access=false
sp_cleanup.use_this_for_non_static_field_access_only_if_necessary=true
sp_cleanup.use_this_for_non_static_method_access=false
sp_cleanup.use_this_for_non_static_method_access_only_if_necessary=true

202
gerrit-gwtexpui/COPYING Normal file
View File

@ -0,0 +1,202 @@
Apache License
Version 2.0, January 2004
http://www.apache.org/licenses/
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
1. Definitions.
"License" shall mean the terms and conditions for use, reproduction,
and distribution as defined by Sections 1 through 9 of this document.
"Licensor" shall mean the copyright owner or entity authorized by
the copyright owner that is granting the License.
"Legal Entity" shall mean the union of the acting entity and all
other entities that control, are controlled by, or are under common
control with that entity. For the purposes of this definition,
"control" means (i) the power, direct or indirect, to cause the
direction or management of such entity, whether by contract or
otherwise, or (ii) ownership of fifty percent (50%) or more of the
outstanding shares, or (iii) beneficial ownership of such entity.
"You" (or "Your") shall mean an individual or Legal Entity
exercising permissions granted by this License.
"Source" form shall mean the preferred form for making modifications,
including but not limited to software source code, documentation
source, and configuration files.
"Object" form shall mean any form resulting from mechanical
transformation or translation of a Source form, including but
not limited to compiled object code, generated documentation,
and conversions to other media types.
"Work" shall mean the work of authorship, whether in Source or
Object form, made available under the License, as indicated by a
copyright notice that is included in or attached to the work
(an example is provided in the Appendix below).
"Derivative Works" shall mean any work, whether in Source or Object
form, that is based on (or derived from) the Work and for which the
editorial revisions, annotations, elaborations, or other modifications
represent, as a whole, an original work of authorship. For the purposes
of this License, Derivative Works shall not include works that remain
separable from, or merely link (or bind by name) to the interfaces of,
the Work and Derivative Works thereof.
"Contribution" shall mean any work of authorship, including
the original version of the Work and any modifications or additions
to that Work or Derivative Works thereof, that is intentionally
submitted to Licensor for inclusion in the Work by the copyright owner
or by an individual or Legal Entity authorized to submit on behalf of
the copyright owner. For the purposes of this definition, "submitted"
means any form of electronic, verbal, or written communication sent
to the Licensor or its representatives, including but not limited to
communication on electronic mailing lists, source code control systems,
and issue tracking systems that are managed by, or on behalf of, the
Licensor for the purpose of discussing and improving the Work, but
excluding communication that is conspicuously marked or otherwise
designated in writing by the copyright owner as "Not a Contribution."
"Contributor" shall mean Licensor and any individual or Legal Entity
on behalf of whom a Contribution has been received by Licensor and
subsequently incorporated within the Work.
2. Grant of Copyright License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
copyright license to reproduce, prepare Derivative Works of,
publicly display, publicly perform, sublicense, and distribute the
Work and such Derivative Works in Source or Object form.
3. Grant of Patent License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
(except as stated in this section) patent license to make, have made,
use, offer to sell, sell, import, and otherwise transfer the Work,
where such license applies only to those patent claims licensable
by such Contributor that are necessarily infringed by their
Contribution(s) alone or by combination of their Contribution(s)
with the Work to which such Contribution(s) was submitted. If You
institute patent litigation against any entity (including a
cross-claim or counterclaim in a lawsuit) alleging that the Work
or a Contribution incorporated within the Work constitutes direct
or contributory patent infringement, then any patent licenses
granted to You under this License for that Work shall terminate
as of the date such litigation is filed.
4. Redistribution. You may reproduce and distribute copies of the
Work or Derivative Works thereof in any medium, with or without
modifications, and in Source or Object form, provided that You
meet the following conditions:
(a) You must give any other recipients of the Work or
Derivative Works a copy of this License; and
(b) You must cause any modified files to carry prominent notices
stating that You changed the files; and
(c) You must retain, in the Source form of any Derivative Works
that You distribute, all copyright, patent, trademark, and
attribution notices from the Source form of the Work,
excluding those notices that do not pertain to any part of
the Derivative Works; and
(d) If the Work includes a "NOTICE" text file as part of its
distribution, then any Derivative Works that You distribute must
include a readable copy of the attribution notices contained
within such NOTICE file, excluding those notices that do not
pertain to any part of the Derivative Works, in at least one
of the following places: within a NOTICE text file distributed
as part of the Derivative Works; within the Source form or
documentation, if provided along with the Derivative Works; or,
within a display generated by the Derivative Works, if and
wherever such third-party notices normally appear. The contents
of the NOTICE file are for informational purposes only and
do not modify the License. You may add Your own attribution
notices within Derivative Works that You distribute, alongside
or as an addendum to the NOTICE text from the Work, provided
that such additional attribution notices cannot be construed
as modifying the License.
You may add Your own copyright statement to Your modifications and
may provide additional or different license terms and conditions
for use, reproduction, or distribution of Your modifications, or
for any such Derivative Works as a whole, provided Your use,
reproduction, and distribution of the Work otherwise complies with
the conditions stated in this License.
5. Submission of Contributions. Unless You explicitly state otherwise,
any Contribution intentionally submitted for inclusion in the Work
by You to the Licensor shall be under the terms and conditions of
this License, without any additional terms or conditions.
Notwithstanding the above, nothing herein shall supersede or modify
the terms of any separate license agreement you may have executed
with Licensor regarding such Contributions.
6. Trademarks. This License does not grant permission to use the trade
names, trademarks, service marks, or product names of the Licensor,
except as required for reasonable and customary use in describing the
origin of the Work and reproducing the content of the NOTICE file.
7. Disclaimer of Warranty. Unless required by applicable law or
agreed to in writing, Licensor provides the Work (and each
Contributor provides its Contributions) on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
implied, including, without limitation, any warranties or conditions
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
PARTICULAR PURPOSE. You are solely responsible for determining the
appropriateness of using or redistributing the Work and assume any
risks associated with Your exercise of permissions under this License.
8. Limitation of Liability. In no event and under no legal theory,
whether in tort (including negligence), contract, or otherwise,
unless required by applicable law (such as deliberate and grossly
negligent acts) or agreed to in writing, shall any Contributor be
liable to You for damages, including any direct, indirect, special,
incidental, or consequential damages of any character arising as a
result of this License or out of the use or inability to use the
Work (including but not limited to damages for loss of goodwill,
work stoppage, computer failure or malfunction, or any and all
other commercial damages or losses), even if such Contributor
has been advised of the possibility of such damages.
9. Accepting Warranty or Additional Liability. While redistributing
the Work or Derivative Works thereof, You may choose to offer,
and charge a fee for, acceptance of support, warranty, indemnity,
or other liability obligations and/or rights consistent with this
License. However, in accepting such obligations, You may act only
on Your own behalf and on Your sole responsibility, not on behalf
of any other Contributor, and only if You agree to indemnify,
defend, and hold each Contributor harmless for any liability
incurred by, or claims asserted against, such Contributor by reason
of your accepting any such warranty or additional liability.
END OF TERMS AND CONDITIONS
APPENDIX: How to apply the Apache License to your work.
To apply the Apache License to your work, attach the following
boilerplate notice, with the fields enclosed by brackets "[]"
replaced with your own identifying information. (Don't include
the brackets!) The text should be enclosed in the appropriate
comment syntax for the file format. We also recommend that a
file or class name and description of purpose be included on the
same "printed page" as the copyright notice for easier
identification within third-party archives.
Copyright [yyyy] [name of copyright owner]
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.

View File

@ -0,0 +1,267 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<profiles version="11">
<profile kind="CodeFormatterProfile" name="Google Format" version="11">
<setting id="org.eclipse.jdt.core.formatter.comment.insert_new_line_before_root_tags" value="insert"/>
<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="do not insert"/>
<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.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="16"/>
<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.5"/>
<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.insert_space_after_closing_angle_bracket_in_type_arguments" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.comment.format_line_comments" value="true"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_enum_declarations" value="insert"/>
<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="0"/>
<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="false"/>
<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.insert_new_line_in_empty_type_declaration" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.comment.clear_blank_lines_in_block_comment" value="false"/>
<setting id="org.eclipse.jdt.core.formatter.lineSplit" value="80"/>
<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.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.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="16"/>
<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_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.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.insert_space_before_closing_paren_in_method_invocation" 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_before_closing_bracket_in_array_allocation_expression" value="do not insert"/>
<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.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.insert_space_before_closing_bracket_in_array_reference" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.brace_position_for_enum_constant" value="end_of_line"/>
<setting id="org.eclipse.jdt.core.formatter.comment.indent_root_tags" value="true"/>
<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.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_after_comma_in_superinterfaces" 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_before_comma_in_allocation_expression" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.tabulation.size" value="2"/>
<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="do not 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_after_opening_paren_in_if" 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.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="3"/>
<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.insert_space_after_and_in_type_parameter" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.alignment_for_arguments_in_qualified_allocation_expression" value="16"/>
<setting id="org.eclipse.jdt.core.compiler.compliance" value="1.5"/>
<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="true"/>
<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="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_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.put_empty_statement_on_new_line" value="false"/>
<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.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="2"/>
<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.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.insert_space_after_colon_in_assert" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.blank_lines_before_imports" value="0"/>
<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="do not 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="do not insert"/>
<setting id="org.eclipse.jdt.core.compiler.codegen.targetPlatform" value="1.5"/>
<setting id="org.eclipse.jdt.core.formatter.use_tabs_only_for_leading_indentations" value="false"/>
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_member" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.comment.format_header" value="true"/>
<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="16"/>
<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.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_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>

334
gerrit-gwtexpui/pom.xml Normal file
View File

@ -0,0 +1,334 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
Copyright (C) 2009 The Android Open Source Project
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
-->
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>gwtexpui</groupId>
<artifactId>gwtexpui</artifactId>
<packaging>jar</packaging>
<version>1.3.4</version>
<name>gwtexpui</name>
<description>Extended UI tools for GWT</description>
<url>https://gerrit.googlesource.com/gwtexpui</url>
<mailingLists>
<mailingList>
<name>repo-discuss mailing list</name>
<post>repo-discuss@googlegroups.com</post>
</mailingList>
</mailingLists>
<developers>
<developer>
<name>Shawn O. Pearce</name>
<email>sop@google.com</email>
<roles>
<role>Maintainer</role>
</roles>
</developer>
</developers>
<licenses>
<license>
<name>Apache License, 2.0</name>
<comments>
Apache License
Version 2.0, January 2004
http://www.apache.org/licenses/
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
1. Definitions.
"License" shall mean the terms and conditions for use, reproduction,
and distribution as defined by Sections 1 through 9 of this document.
"Licensor" shall mean the copyright owner or entity authorized by
the copyright owner that is granting the License.
"Legal Entity" shall mean the union of the acting entity and all
other entities that control, are controlled by, or are under common
control with that entity. For the purposes of this definition,
"control" means (i) the power, direct or indirect, to cause the
direction or management of such entity, whether by contract or
otherwise, or (ii) ownership of fifty percent (50%) or more of the
outstanding shares, or (iii) beneficial ownership of such entity.
"You" (or "Your") shall mean an individual or Legal Entity
exercising permissions granted by this License.
"Source" form shall mean the preferred form for making modifications,
including but not limited to software source code, documentation
source, and configuration files.
"Object" form shall mean any form resulting from mechanical
transformation or translation of a Source form, including but
not limited to compiled object code, generated documentation,
and conversions to other media types.
"Work" shall mean the work of authorship, whether in Source or
Object form, made available under the License, as indicated by a
copyright notice that is included in or attached to the work
(an example is provided in the Appendix below).
"Derivative Works" shall mean any work, whether in Source or Object
form, that is based on (or derived from) the Work and for which the
editorial revisions, annotations, elaborations, or other modifications
represent, as a whole, an original work of authorship. For the purposes
of this License, Derivative Works shall not include works that remain
separable from, or merely link (or bind by name) to the interfaces of,
the Work and Derivative Works thereof.
"Contribution" shall mean any work of authorship, including
the original version of the Work and any modifications or additions
to that Work or Derivative Works thereof, that is intentionally
submitted to Licensor for inclusion in the Work by the copyright owner
or by an individual or Legal Entity authorized to submit on behalf of
the copyright owner. For the purposes of this definition, "submitted"
means any form of electronic, verbal, or written communication sent
to the Licensor or its representatives, including but not limited to
communication on electronic mailing lists, source code control systems,
and issue tracking systems that are managed by, or on behalf of, the
Licensor for the purpose of discussing and improving the Work, but
excluding communication that is conspicuously marked or otherwise
designated in writing by the copyright owner as "Not a Contribution."
"Contributor" shall mean Licensor and any individual or Legal Entity
on behalf of whom a Contribution has been received by Licensor and
subsequently incorporated within the Work.
2. Grant of Copyright License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
copyright license to reproduce, prepare Derivative Works of,
publicly display, publicly perform, sublicense, and distribute the
Work and such Derivative Works in Source or Object form.
3. Grant of Patent License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
(except as stated in this section) patent license to make, have made,
use, offer to sell, sell, import, and otherwise transfer the Work,
where such license applies only to those patent claims licensable
by such Contributor that are necessarily infringed by their
Contribution(s) alone or by combination of their Contribution(s)
with the Work to which such Contribution(s) was submitted. If You
institute patent litigation against any entity (including a
cross-claim or counterclaim in a lawsuit) alleging that the Work
or a Contribution incorporated within the Work constitutes direct
or contributory patent infringement, then any patent licenses
granted to You under this License for that Work shall terminate
as of the date such litigation is filed.
4. Redistribution. You may reproduce and distribute copies of the
Work or Derivative Works thereof in any medium, with or without
modifications, and in Source or Object form, provided that You
meet the following conditions:
(a) You must give any other recipients of the Work or
Derivative Works a copy of this License; and
(b) You must cause any modified files to carry prominent notices
stating that You changed the files; and
(c) You must retain, in the Source form of any Derivative Works
that You distribute, all copyright, patent, trademark, and
attribution notices from the Source form of the Work,
excluding those notices that do not pertain to any part of
the Derivative Works; and
(d) If the Work includes a "NOTICE" text file as part of its
distribution, then any Derivative Works that You distribute must
include a readable copy of the attribution notices contained
within such NOTICE file, excluding those notices that do not
pertain to any part of the Derivative Works, in at least one
of the following places: within a NOTICE text file distributed
as part of the Derivative Works; within the Source form or
documentation, if provided along with the Derivative Works; or,
within a display generated by the Derivative Works, if and
wherever such third-party notices normally appear. The contents
of the NOTICE file are for informational purposes only and
do not modify the License. You may add Your own attribution
notices within Derivative Works that You distribute, alongside
or as an addendum to the NOTICE text from the Work, provided
that such additional attribution notices cannot be construed
as modifying the License.
You may add Your own copyright statement to Your modifications and
may provide additional or different license terms and conditions
for use, reproduction, or distribution of Your modifications, or
for any such Derivative Works as a whole, provided Your use,
reproduction, and distribution of the Work otherwise complies with
the conditions stated in this License.
5. Submission of Contributions. Unless You explicitly state otherwise,
any Contribution intentionally submitted for inclusion in the Work
by You to the Licensor shall be under the terms and conditions of
this License, without any additional terms or conditions.
Notwithstanding the above, nothing herein shall supersede or modify
the terms of any separate license agreement you may have executed
with Licensor regarding such Contributions.
6. Trademarks. This License does not grant permission to use the trade
names, trademarks, service marks, or product names of the Licensor,
except as required for reasonable and customary use in describing the
origin of the Work and reproducing the content of the NOTICE file.
7. Disclaimer of Warranty. Unless required by applicable law or
agreed to in writing, Licensor provides the Work (and each
Contributor provides its Contributions) on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
implied, including, without limitation, any warranties or conditions
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
PARTICULAR PURPOSE. You are solely responsible for determining the
appropriateness of using or redistributing the Work and assume any
risks associated with Your exercise of permissions under this License.
8. Limitation of Liability. In no event and under no legal theory,
whether in tort (including negligence), contract, or otherwise,
unless required by applicable law (such as deliberate and grossly
negligent acts) or agreed to in writing, shall any Contributor be
liable to You for damages, including any direct, indirect, special,
incidental, or consequential damages of any character arising as a
result of this License or out of the use or inability to use the
Work (including but not limited to damages for loss of goodwill,
work stoppage, computer failure or malfunction, or any and all
other commercial damages or losses), even if such Contributor
has been advised of the possibility of such damages.
9. Accepting Warranty or Additional Liability. While redistributing
the Work or Derivative Works thereof, You may choose to offer,
and charge a fee for, acceptance of support, warranty, indemnity,
or other liability obligations and/or rights consistent with this
License. However, in accepting such obligations, You may act only
on Your own behalf and on Your sole responsibility, not on behalf
of any other Contributor, and only if You agree to indemnify,
defend, and hold each Contributor harmless for any liability
incurred by, or claims asserted against, such Contributor by reason
of your accepting any such warranty or additional liability.
END OF TERMS AND CONDITIONS
APPENDIX: How to apply the Apache License to your work.
To apply the Apache License to your work, attach the following
boilerplate notice, with the fields enclosed by brackets "[]"
replaced with your own identifying information. (Don't include
the brackets!) The text should be enclosed in the appropriate
comment syntax for the file format. We also recommend that a
file or class name and description of purpose be included on the
same "printed page" as the copyright notice for easier
identification within third-party archives.
Copyright [yyyy] [name of copyright owner]
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
</comments>
</license>
</licenses>
<properties>
<gwtVersion>2.3.0</gwtVersion>
<project.build.sourceEncoding>
UTF-8
</project.build.sourceEncoding>
<project.reporting.outputEncoding>
UTF-8
</project.reporting.outputEncoding>
</properties>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<source>1.6</source>
<target>1.6</target>
<encoding>UTF-8</encoding>
</configuration>
</plugin>
<plugin>
<artifactId>maven-source-plugin</artifactId>
<executions>
<execution>
<goals>
<goal>jar</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
<extensions>
<extension>
<groupId>com.googlesource.gerrit</groupId>
<artifactId>gs-maven-wagon</artifactId>
<version>3.3</version>
</extension>
</extensions>
</build>
<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>3.8.2</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>com.google.gwt</groupId>
<artifactId>gwt-user</artifactId>
<version>${gwtVersion}</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>com.google.gwt</groupId>
<artifactId>gwt-dev</artifactId>
<version>${gwtVersion}</version>
<scope>provided</scope>
</dependency>
</dependencies>
<distributionManagement>
<repository>
<id>gerrit-maven-repository</id>
<url>gs://gerrit-maven</url>
<uniqueVersion>true</uniqueVersion>
</repository>
</distributionManagement>
<repositories>
<repository>
<id>gerrit-maven</id>
<url>https://gerrit-maven.commondatastorage.googleapis.com</url>
</repository>
</repositories>
</project>

View File

@ -0,0 +1,20 @@
<!--
Copyright (C) 2009 The Android Open Source Project
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
-->
<module>
<inherits name='com.google.gwt.resources.Resources'/>
<inherits name="com.google.gwtexpui.safehtml.SafeHtml"/>
<inherits name="com.google.gwtexpui.user.User"/>
</module>

View File

@ -0,0 +1,22 @@
// Copyright (C) 2009 The Android Open Source Project
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package com.google.gwtexpui.clippy.client;
import com.google.gwt.resources.client.CssResource;
public interface ClippyCss extends CssResource {
String label();
String control();
}

View File

@ -0,0 +1,25 @@
// Copyright (C) 2009 The Android Open Source Project
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package com.google.gwtexpui.clippy.client;
import com.google.gwt.core.client.GWT;
import com.google.gwt.resources.client.ClientBundle;
public interface ClippyResources extends ClientBundle {
public static final ClippyResources I = GWT.create(ClippyResources.class);
@Source("clippy.css")
ClippyCss css();
}

View File

@ -0,0 +1,230 @@
// Copyright (C) 2009 The Android Open Source Project
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package com.google.gwtexpui.clippy.client;
import com.google.gwt.core.client.GWT;
import com.google.gwt.core.client.Scheduler;
import com.google.gwt.event.dom.client.BlurEvent;
import com.google.gwt.event.dom.client.BlurHandler;
import com.google.gwt.event.dom.client.ClickEvent;
import com.google.gwt.event.dom.client.ClickHandler;
import com.google.gwt.event.dom.client.KeyPressEvent;
import com.google.gwt.event.dom.client.KeyPressHandler;
import com.google.gwt.http.client.URL;
import com.google.gwt.user.client.Command;
import com.google.gwt.user.client.DOM;
import com.google.gwt.user.client.Element;
import com.google.gwt.user.client.ui.Composite;
import com.google.gwt.user.client.ui.FlowPanel;
import com.google.gwt.user.client.ui.HasText;
import com.google.gwt.user.client.ui.InlineLabel;
import com.google.gwt.user.client.ui.Label;
import com.google.gwt.user.client.ui.TextBox;
import com.google.gwtexpui.safehtml.client.SafeHtml;
import com.google.gwtexpui.safehtml.client.SafeHtmlBuilder;
import com.google.gwtexpui.user.client.UserAgent;
/**
* Label which permits the user to easily copy the complete content.
* <p>
* If the Flash plugin is available a "movie" is embedded that provides
* one-click copying of the content onto the system clipboard. The label (if
* visible) can also be clicked, switching from a label to an input box,
* allowing the user to copy the text with a keyboard shortcut.
*/
public class CopyableLabel extends Composite implements HasText {
private static final int SWF_WIDTH = 110;
private static final int SWF_HEIGHT = 14;
private static String swfUrl;
private static boolean flashEnabled = true;
static {
ClippyResources.I.css().ensureInjected();
}
public static boolean isFlashEnabled() {
return flashEnabled;
}
public static void setFlashEnabled(final boolean on) {
flashEnabled = on;
}
private static String swfUrl() {
if (swfUrl == null) {
swfUrl = GWT.getModuleBaseURL() + "gwtexpui_clippy1.cache.swf";
}
return swfUrl;
}
private final FlowPanel content;
private String text;
private int visibleLen;
private Label textLabel;
private TextBox textBox;
private Element swf;
/**
* Create a new label
*
* @param str initial content
*/
public CopyableLabel(final String str) {
this(str, true);
}
/**
* Create a new label
*
* @param str initial content
* @param showLabel if true, the content is shown, if false it is hidden from
* view and only the copy icon is displayed.
*/
public CopyableLabel(final String str, final boolean showLabel) {
content = new FlowPanel();
initWidget(content);
text = str;
visibleLen = text.length();
if (showLabel) {
textLabel = new InlineLabel(getText());
textLabel.setStyleName(ClippyResources.I.css().label());
textLabel.addClickHandler(new ClickHandler() {
@Override
public void onClick(final ClickEvent event) {
showTextBox();
}
});
content.add(textLabel);
}
embedMovie();
}
/**
* Change the text which is displayed in the clickable label.
*
* @param text the new preview text, should be shorter than the original text
* which would be copied to the clipboard.
*/
public void setPreviewText(final String text) {
if (textLabel != null) {
textLabel.setText(text);
visibleLen = text.length();
}
}
private void embedMovie() {
if (flashEnabled && UserAgent.hasFlash) {
final String flashVars = "text=" + URL.encodeQueryString(getText());
final SafeHtmlBuilder h = new SafeHtmlBuilder();
h.openElement("div");
h.setStyleName(ClippyResources.I.css().control());
h.openElement("object");
h.setWidth(SWF_WIDTH);
h.setHeight(SWF_HEIGHT);
h.setAttribute("classid", "clsid:d27cdb6e-ae6d-11cf-96b8-444553540000");
h.paramElement("movie", swfUrl());
h.paramElement("FlashVars", flashVars);
h.openElement("embed");
h.setWidth(SWF_WIDTH);
h.setHeight(SWF_HEIGHT);
h.setAttribute("wmode", "transparent");
h.setAttribute("type", "application/x-shockwave-flash");
h.setAttribute("src", swfUrl());
h.setAttribute("FlashVars", flashVars);
h.closeSelf();
h.closeElement("object");
h.closeElement("div");
if (swf != null) {
DOM.removeChild(getElement(), swf);
}
DOM.appendChild(getElement(), swf = SafeHtml.parse(h));
}
}
public String getText() {
return text;
}
public void setText(final String newText) {
text = newText;
visibleLen = newText.length();
if (textLabel != null) {
textLabel.setText(getText());
}
if (textBox != null) {
textBox.setText(getText());
textBox.selectAll();
}
embedMovie();
}
private void showTextBox() {
if (textBox == null) {
textBox = new TextBox();
textBox.setText(getText());
textBox.setVisibleLength(visibleLen);
textBox.addKeyPressHandler(new KeyPressHandler() {
@Override
public void onKeyPress(final KeyPressEvent event) {
if (event.isControlKeyDown() || event.isMetaKeyDown()) {
switch (event.getCharCode()) {
case 'c':
case 'x':
Scheduler.get().scheduleDeferred(new Command() {
public void execute() {
hideTextBox();
}
});
break;
}
}
}
});
textBox.addBlurHandler(new BlurHandler() {
@Override
public void onBlur(final BlurEvent event) {
hideTextBox();
}
});
content.insert(textBox, 1);
}
textLabel.setVisible(false);
textBox.setVisible(true);
Scheduler.get().scheduleDeferred(new Command() {
@Override
public void execute() {
textBox.selectAll();
textBox.setFocus(true);
}
});
}
private void hideTextBox() {
if (textBox != null) {
textBox.removeFromParent();
textBox = null;
}
textLabel.setVisible(true);
}
}

View File

@ -0,0 +1,25 @@
/* Copyright (C) 2009 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
.label {
vertical-align: top;
}
.control {
margin-left: 5px;
display: inline-block !important;
height: 14px;
width: 14px;
overflow: hidden;
}

View File

@ -0,0 +1,19 @@
<!--
Copyright (C) 2009 The Android Open Source Project
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
-->
<module>
<define-linker name='cachecss' class='com.google.gwtexpui.css.rebind.CssLinker'/>
<add-linker name='cachecss'/>
</module>

View File

@ -0,0 +1,130 @@
// Copyright (C) 2009 The Android Open Source Project
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package com.google.gwtexpui.css.rebind;
import com.google.gwt.core.ext.LinkerContext;
import com.google.gwt.core.ext.TreeLogger;
import com.google.gwt.core.ext.UnableToCompleteException;
import com.google.gwt.core.ext.linker.AbstractLinker;
import com.google.gwt.core.ext.linker.Artifact;
import com.google.gwt.core.ext.linker.ArtifactSet;
import com.google.gwt.core.ext.linker.LinkerOrder;
import com.google.gwt.core.ext.linker.PublicResource;
import com.google.gwt.core.ext.linker.impl.StandardLinkerContext;
import com.google.gwt.core.ext.linker.impl.StandardStylesheetReference;
import com.google.gwt.dev.util.Util;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.HashMap;
@LinkerOrder(LinkerOrder.Order.PRE)
public class CssLinker extends AbstractLinker {
@Override
public String getDescription() {
return "CssLinker";
}
@SuppressWarnings("unchecked")
@Override
public ArtifactSet link(final TreeLogger logger, final LinkerContext context,
final ArtifactSet artifacts) throws UnableToCompleteException {
final ArtifactSet returnTo = new ArtifactSet();
int index = 0;
final HashMap<String, PublicResource> css =
new HashMap<String, PublicResource>();
for (final StandardStylesheetReference ssr : artifacts
.<StandardStylesheetReference> find(StandardStylesheetReference.class)) {
css.put(ssr.getSrc(), null);
}
for (final PublicResource pr : artifacts
.<PublicResource> find(PublicResource.class)) {
if (css.containsKey(pr.getPartialPath())) {
css.put(pr.getPartialPath(), new CssPubRsrc(name(logger, pr), pr));
}
}
for (Artifact a : artifacts) {
if (a instanceof PublicResource) {
final PublicResource r = (PublicResource) a;
if (css.containsKey(r.getPartialPath())) {
a = css.get(r.getPartialPath());
}
} else if (a instanceof StandardStylesheetReference) {
final StandardStylesheetReference r = (StandardStylesheetReference) a;
final PublicResource p = css.get(r.getSrc());
a = new StandardStylesheetReference(p.getPartialPath(), index);
}
returnTo.add(a);
index++;
}
return returnTo;
}
private String name(final TreeLogger logger, final PublicResource r)
throws UnableToCompleteException {
final InputStream in = r.getContents(logger);
final ByteArrayOutputStream tmp = new ByteArrayOutputStream();
try {
try {
final byte[] buf = new byte[2048];
int n;
while ((n = in.read(buf)) >= 0) {
tmp.write(buf, 0, n);
}
tmp.close();
} finally {
in.close();
}
} catch (IOException e) {
final UnableToCompleteException ute = new UnableToCompleteException();
ute.initCause(e);
throw ute;
}
String base = r.getPartialPath();
final int s = base.lastIndexOf('/');
if (0 < s) {
base = base.substring(0, s + 1);
} else {
base = "";
}
return base + Util.computeStrongName(tmp.toByteArray()) + ".cache.css";
}
private static class CssPubRsrc extends PublicResource {
private final PublicResource src;
CssPubRsrc(final String partialPath, final PublicResource r) {
super(StandardLinkerContext.class, partialPath);
src = r;
}
@Override
public InputStream getContents(final TreeLogger logger)
throws UnableToCompleteException {
return src.getContents(logger);
}
@Override
public long getLastModified() {
return src.getLastModified();
}
}
}

View File

@ -0,0 +1,20 @@
<!--
Copyright (C) 2009 The Android Open Source Project
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
-->
<module>
<inherits name='com.google.gwt.resources.Resources'/>
<inherits name='com.google.gwtexpui.user.User'/>
<inherits name='com.google.gwtexpui.safehtml.SafeHtml'/>
</module>

View File

@ -0,0 +1,40 @@
// Copyright (C) 2009 The Android Open Source Project
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package com.google.gwtexpui.globalkey.client;
import com.google.gwt.event.dom.client.KeyPressEvent;
public final class CompoundKeyCommand extends KeyCommand {
final KeyCommandSet set;
public CompoundKeyCommand(int mask, char key, String help, KeyCommandSet s) {
super(mask, key, help);
set = s;
}
public CompoundKeyCommand(int mask, int key, String help, KeyCommandSet s) {
super(mask, key, help);
set = s;
}
public KeyCommandSet getSet() {
return set;
}
@Override
public void onKeyPress(final KeyPressEvent event) {
GlobalKey.temporaryWithTimeout(set);
}
}

View File

@ -0,0 +1,51 @@
// Copyright (C) 2009 The Android Open Source Project
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package com.google.gwtexpui.globalkey.client;
import com.google.gwt.dom.client.Document;
import com.google.gwt.dom.client.Element;
import com.google.gwt.dom.client.Node;
import com.google.gwt.event.dom.client.HasKeyPressHandlers;
import com.google.gwt.event.dom.client.KeyPressEvent;
import com.google.gwt.event.dom.client.KeyPressHandler;
import com.google.gwt.event.shared.HandlerRegistration;
import com.google.gwt.user.client.ui.RootPanel;
import com.google.gwt.user.client.ui.Widget;
class DocWidget extends Widget implements HasKeyPressHandlers {
private static DocWidget me;
static DocWidget get() {
if (me == null) {
me = new DocWidget();
}
return me;
}
private DocWidget() {
setElement((Element) docnode());
onAttach();
RootPanel.detachOnWindowClose(this);
}
@Override
public HandlerRegistration addKeyPressHandler(KeyPressHandler handler) {
return addDomHandler(handler, KeyPressEvent.getType());
}
private static Node docnode() {
return Document.get();
}
}

View File

@ -0,0 +1,183 @@
// Copyright (C) 2009 The Android Open Source Project
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package com.google.gwtexpui.globalkey.client;
import com.google.gwt.event.dom.client.KeyCodes;
import com.google.gwt.event.dom.client.KeyPressEvent;
import com.google.gwt.event.dom.client.KeyPressHandler;
import com.google.gwt.event.logical.shared.CloseEvent;
import com.google.gwt.event.logical.shared.CloseHandler;
import com.google.gwt.event.shared.HandlerRegistration;
import com.google.gwt.user.client.Timer;
import com.google.gwt.user.client.ui.PopupPanel;
import com.google.gwt.user.client.ui.Widget;
public class GlobalKey {
public static final KeyPressHandler STOP_PROPAGATION = new KeyPressHandler() {
@Override
public void onKeyPress(final KeyPressEvent event) {
event.stopPropagation();
}
};
private static State global;
static State active;
private static CloseHandler<PopupPanel> restoreGlobal;
private static Timer restoreTimer;
static {
KeyResources.I.css().ensureInjected();
}
private static void initEvents() {
if (active == null) {
DocWidget.get().addKeyPressHandler(new KeyPressHandler() {
@Override
public void onKeyPress(final KeyPressEvent event) {
final KeyCommandSet s = active.live;
if (s != active.all) {
active.live = active.all;
restoreTimer.cancel();
}
s.onKeyPress(event);
}
});
restoreTimer = new Timer() {
@Override
public void run() {
active.live = active.all;
}
};
global = new State(null);
active = global;
}
}
private static void initDialog() {
if (restoreGlobal == null) {
restoreGlobal = new CloseHandler<PopupPanel>() {
@Override
public void onClose(final CloseEvent<PopupPanel> event) {
active = global;
}
};
}
}
static void temporaryWithTimeout(final KeyCommandSet s) {
active.live = s;
restoreTimer.schedule(250);
}
public static void dialog(final PopupPanel panel) {
initEvents();
initDialog();
assert panel.isShowing();
assert active == global;
active = new State(panel);
active.add(new HidePopupPanelCommand(0, KeyCodes.KEY_ESCAPE, panel));
panel.addCloseHandler(restoreGlobal);
}
public static HandlerRegistration addApplication(final Widget widget,
final KeyCommand appKey) {
initEvents();
final State state = stateFor(widget);
state.add(appKey);
return new HandlerRegistration() {
@Override
public void removeHandler() {
state.remove(appKey);
}
};
}
public static HandlerRegistration add(final Widget widget,
final KeyCommandSet cmdSet) {
initEvents();
final State state = stateFor(widget);
state.add(cmdSet);
return new HandlerRegistration() {
@Override
public void removeHandler() {
state.remove(cmdSet);
}
};
}
private static State stateFor(Widget w) {
while (w != null) {
if (w == active.root) {
return active;
}
w = w.getParent();
}
return global;
}
public static void filter(final KeyCommandFilter filter) {
active.filter(filter);
if (active != global) {
global.filter(filter);
}
}
private GlobalKey() {
}
static class State {
final Widget root;
final KeyCommandSet app;
final KeyCommandSet all;
KeyCommandSet live;
State(final Widget r) {
root = r;
app = new KeyCommandSet(KeyConstants.I.applicationSection());
app.add(ShowHelpCommand.INSTANCE);
all = new KeyCommandSet();
all.add(app);
live = all;
}
void add(final KeyCommand k) {
app.add(k);
all.add(k);
}
void remove(final KeyCommand k) {
app.remove(k);
all.remove(k);
}
void add(final KeyCommandSet s) {
all.add(s);
}
void remove(final KeyCommandSet s) {
all.remove(s);
}
void filter(final KeyCommandFilter f) {
all.filter(f);
}
}
}

View File

@ -0,0 +1,33 @@
// Copyright (C) 2009 The Android Open Source Project
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package com.google.gwtexpui.globalkey.client;
import com.google.gwt.event.dom.client.KeyPressEvent;
import com.google.gwt.user.client.ui.PopupPanel;
/** Hides the given popup panel when invoked. */
public class HidePopupPanelCommand extends KeyCommand {
private final PopupPanel panel;
public HidePopupPanelCommand(int mask, int key, PopupPanel panel) {
super(mask, key, KeyConstants.I.closeCurrentDialog());
this.panel = panel;
}
@Override
public void onKeyPress(final KeyPressEvent event) {
panel.hide();
}
}

View File

@ -0,0 +1,94 @@
// Copyright (C) 2009 The Android Open Source Project
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package com.google.gwtexpui.globalkey.client;
import com.google.gwt.event.dom.client.KeyCodes;
import com.google.gwt.event.dom.client.KeyPressHandler;
import com.google.gwtexpui.safehtml.client.SafeHtml;
import com.google.gwtexpui.safehtml.client.SafeHtmlBuilder;
public abstract class KeyCommand implements KeyPressHandler {
public static final int M_CTRL = 1 << 16;
public static final int M_ALT = 2 << 16;
public static final int M_META = 4 << 16;
public static boolean same(final KeyCommand a, final KeyCommand b) {
return a.getClass() == b.getClass() && a.helpText.equals(b.helpText);
}
final int keyMask;
private final String helpText;
public KeyCommand(final int mask, final int key, final String help) {
this(mask, (char) key, help);
}
public KeyCommand(final int mask, final char key, final String help) {
assert help != null;
keyMask = mask | key;
helpText = help;
}
public String getHelpText() {
return helpText;
}
SafeHtml describeKeyStroke() {
final SafeHtmlBuilder b = new SafeHtmlBuilder();
if ((keyMask & M_CTRL) == M_CTRL) {
modifier(b, KeyConstants.I.keyCtrl());
}
if ((keyMask & M_ALT) == M_ALT) {
modifier(b, KeyConstants.I.keyAlt());
}
if ((keyMask & M_META) == M_META) {
modifier(b, KeyConstants.I.keyMeta());
}
final char c = (char) (keyMask & 0xffff);
switch (c) {
case KeyCodes.KEY_ENTER:
namedKey(b, KeyConstants.I.keyEnter());
break;
case KeyCodes.KEY_ESCAPE:
namedKey(b, KeyConstants.I.keyEsc());
break;
default:
b.openSpan();
b.setStyleName(KeyResources.I.css().helpKey());
b.append(String.valueOf(c));
b.closeSpan();
break;
}
return b;
}
private void modifier(final SafeHtmlBuilder b, final String name) {
namedKey(b, name);
b.append(" + ");
}
private void namedKey(final SafeHtmlBuilder b, final String name) {
b.append('<');
b.openSpan();
b.setStyleName(KeyResources.I.css().helpKey());
b.append(name);
b.closeSpan();
b.append(">");
}
}

View File

@ -0,0 +1,19 @@
// Copyright (C) 2009 The Android Open Source Project
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package com.google.gwtexpui.globalkey.client;
public interface KeyCommandFilter {
public boolean include(KeyCommand key);
}

View File

@ -0,0 +1,136 @@
// Copyright (C) 2009 The Android Open Source Project
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package com.google.gwtexpui.globalkey.client;
import com.google.gwt.event.dom.client.KeyPressEvent;
import com.google.gwt.event.dom.client.KeyPressHandler;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
public class KeyCommandSet implements KeyPressHandler {
private final Map<Integer, KeyCommand> map;
private List<KeyCommandSet> sets;
private String name;
public KeyCommandSet() {
this("");
}
public KeyCommandSet(final String setName) {
map = new HashMap<Integer, KeyCommand>();
name = setName;
}
public String getName() {
return name;
}
public void setName(final String setName) {
assert setName != null;
name = setName;
}
public boolean isEmpty() {
return map.isEmpty();
}
public void add(final KeyCommand k) {
assert !map.containsKey(k.keyMask)
: "Key " + k.describeKeyStroke().asString()
+ " already registered";
if (!map.containsKey(k.keyMask)) {
map.put(k.keyMask, k);
}
}
public void remove(final KeyCommand k) {
assert map.get(k.keyMask) == k;
map.remove(k.keyMask);
}
public void add(final KeyCommandSet set) {
if (sets == null) {
sets = new ArrayList<KeyCommandSet>();
}
assert !sets.contains(set);
sets.add(set);
for (final KeyCommand k : set.map.values()) {
add(k);
}
}
public void remove(final KeyCommandSet set) {
assert sets != null;
assert sets.contains(set);
sets.remove(set);
for (final KeyCommand k : set.map.values()) {
remove(k);
}
}
public void filter(final KeyCommandFilter filter) {
if (sets != null) {
for (final KeyCommandSet s : sets) {
s.filter(filter);
}
}
for (final Iterator<KeyCommand> i = map.values().iterator(); i.hasNext();) {
final KeyCommand kc = i.next();
if (!filter.include(kc)) {
i.remove();
} else if (kc instanceof CompoundKeyCommand) {
((CompoundKeyCommand) kc).set.filter(filter);
}
}
}
public Collection<KeyCommand> getKeys() {
return map.values();
}
public Collection<KeyCommandSet> getSets() {
return sets != null ? sets : Collections.<KeyCommandSet> emptyList();
}
@Override
public void onKeyPress(final KeyPressEvent event) {
final KeyCommand k = map.get(toMask(event));
if (k != null) {
event.preventDefault();
event.stopPropagation();
k.onKeyPress(event);
}
}
static int toMask(final KeyPressEvent event) {
int mask = event.getCharCode();
if (event.isAltKeyDown()) {
mask |= KeyCommand.M_ALT;
}
if (event.isControlKeyDown()) {
mask |= KeyCommand.M_CTRL;
}
if (event.isMetaKeyDown()) {
mask |= KeyCommand.M_META;
}
return mask;
}
}

View File

@ -0,0 +1,37 @@
// Copyright (C) 2009 The Android Open Source Project
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package com.google.gwtexpui.globalkey.client;
import com.google.gwt.core.client.GWT;
import com.google.gwt.i18n.client.Constants;
public interface KeyConstants extends Constants {
public static final KeyConstants I = GWT.create(KeyConstants.class);
String applicationSection();
String showHelp();
String closeCurrentDialog();
String keyboardShortcuts();
String closeButton();
String orOtherKey();
String thenOtherKey();
String keyCtrl();
String keyAlt();
String keyMeta();
String keyEnter();
String keyEsc();
}

View File

@ -0,0 +1,14 @@
applicationSection = Application
showHelp = Open shortcut help
closeCurrentDialog = Close current dialog
keyboardShortcuts = Keyboard Shortcuts
closeButton = Close
orOtherKey = or
thenOtherKey = then
keyCtrl = Ctrl
keyAlt = Alt
keyMeta = Meta
keyEnter = Enter
keyEsc = Esc

View File

@ -0,0 +1,29 @@
// Copyright (C) 2009 The Android Open Source Project
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package com.google.gwtexpui.globalkey.client;
import com.google.gwt.resources.client.CssResource;
public interface KeyCss extends CssResource {
String helpPopup();
String helpHeader();
String helpHeaderGlue();
String helpTable();
String helpTableGlue();
String helpGroup();
String helpKeyStroke();
String helpSeparator();
String helpKey();
}

View File

@ -0,0 +1,228 @@
// Copyright (C) 2009 The Android Open Source Project
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package com.google.gwtexpui.globalkey.client;
import com.google.gwt.event.dom.client.ClickEvent;
import com.google.gwt.event.dom.client.ClickHandler;
import com.google.gwt.event.dom.client.KeyPressEvent;
import com.google.gwt.event.dom.client.KeyPressHandler;
import com.google.gwt.user.client.DOM;
import com.google.gwt.user.client.ui.Anchor;
import com.google.gwt.user.client.ui.FlowPanel;
import com.google.gwt.user.client.ui.FocusPanel;
import com.google.gwt.user.client.ui.Grid;
import com.google.gwt.user.client.ui.HasHorizontalAlignment;
import com.google.gwt.user.client.ui.HTMLTable.CellFormatter;
import com.google.gwtexpui.safehtml.client.SafeHtml;
import com.google.gwtexpui.safehtml.client.SafeHtmlBuilder;
import com.google.gwtexpui.user.client.PluginSafePopupPanel;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.Comparator;
import java.util.LinkedHashMap;
import java.util.List;
public class KeyHelpPopup extends PluginSafePopupPanel implements
KeyPressHandler {
private final FocusPanel focus;
public KeyHelpPopup() {
super(true/* autohide */, true/* modal */);
setStyleName(KeyResources.I.css().helpPopup());
final Anchor closer = new Anchor(KeyConstants.I.closeButton());
closer.addClickHandler(new ClickHandler() {
@Override
public void onClick(final ClickEvent event) {
hide();
}
});
final Grid header = new Grid(1, 3);
header.setStyleName(KeyResources.I.css().helpHeader());
header.setText(0, 0, KeyConstants.I.keyboardShortcuts());
header.setWidget(0, 2, closer);
final CellFormatter fmt = header.getCellFormatter();
fmt.addStyleName(0, 1, KeyResources.I.css().helpHeaderGlue());
fmt.setHorizontalAlignment(0, 2, HasHorizontalAlignment.ALIGN_RIGHT);
final Grid lists = new Grid(0, 7);
lists.setStyleName(KeyResources.I.css().helpTable());
populate(lists);
lists.getCellFormatter().addStyleName(0, 3,
KeyResources.I.css().helpTableGlue());
final FlowPanel body = new FlowPanel();
body.add(header);
DOM.appendChild(body.getElement(), DOM.createElement("hr"));
body.add(lists);
focus = new FocusPanel(body);
DOM.setStyleAttribute(focus.getElement(), "outline", "0px");
DOM.setElementAttribute(focus.getElement(), "hideFocus", "true");
focus.addKeyPressHandler(this);
add(focus);
}
@Override
public void setVisible(final boolean show) {
super.setVisible(show);
if (show) {
focus.setFocus(true);
}
}
@Override
public void onKeyPress(final KeyPressEvent event) {
if (KeyCommandSet.toMask(event) == ShowHelpCommand.INSTANCE.keyMask) {
// Block the '?' key from triggering us to show right after
// we just hide ourselves.
//
event.stopPropagation();
event.preventDefault();
}
hide();
}
private void populate(final Grid lists) {
int end[] = new int[5];
int column = 0;
for (final KeyCommandSet set : combinedSetsByName()) {
int row = end[column];
row = formatGroup(lists, row, column, set);
end[column] = row;
if (column == 0) {
column = 4;
} else {
column = 0;
}
}
}
/**
* @return an ordered collection of KeyCommandSet, combining sets which share
* the same name, so that each set name appears at most once.
*/
private static Collection<KeyCommandSet> combinedSetsByName() {
final LinkedHashMap<String, KeyCommandSet> byName =
new LinkedHashMap<String, KeyCommandSet>();
for (final KeyCommandSet set : GlobalKey.active.all.getSets()) {
KeyCommandSet v = byName.get(set.getName());
if (v == null) {
v = new KeyCommandSet(set.getName());
byName.put(v.getName(), v);
}
v.add(set);
}
return byName.values();
}
private int formatGroup(final Grid lists, int row, final int col,
final KeyCommandSet set) {
if (set.isEmpty()) {
return row;
}
if (lists.getRowCount() < row + 1) {
lists.resizeRows(row + 1);
}
lists.setText(row, col + 2, set.getName());
lists.getCellFormatter().addStyleName(row, col + 2,
KeyResources.I.css().helpGroup());
row++;
return formatKeys(lists, row, col, set, null);
}
private int formatKeys(final Grid lists, int row, final int col,
final KeyCommandSet set, final SafeHtml prefix) {
final CellFormatter fmt = lists.getCellFormatter();
final int initialRow = row;
final List<KeyCommand> keys = sort(set);
if (lists.getRowCount() < row + keys.size()) {
lists.resizeRows(row + keys.size());
}
FORMAT_KEYS: for (int i = 0; i < keys.size(); i++) {
final KeyCommand k = keys.get(i);
if (k instanceof CompoundKeyCommand) {
final SafeHtmlBuilder b = new SafeHtmlBuilder();
b.append(k.describeKeyStroke());
row = formatKeys(lists, row, col, ((CompoundKeyCommand) k).getSet(), b);
continue;
}
for (int prior = 0; prior < i; prior++) {
if (KeyCommand.same(keys.get(prior), k)) {
final int r = initialRow + prior;
final SafeHtmlBuilder b = new SafeHtmlBuilder();
b.append(SafeHtml.get(lists, r, col + 0));
b.append(" ");
b.append(KeyConstants.I.orOtherKey());
b.append(" ");
if (prefix != null) {
b.append(prefix);
b.append(" ");
b.append(KeyConstants.I.thenOtherKey());
b.append(" ");
}
b.append(k.describeKeyStroke());
SafeHtml.set(lists, r, col + 0, b);
continue FORMAT_KEYS;
}
}
if (prefix != null) {
final SafeHtmlBuilder b = new SafeHtmlBuilder();
b.append(prefix);
b.append(" ");
b.append(KeyConstants.I.thenOtherKey());
b.append(" ");
b.append(k.describeKeyStroke());
SafeHtml.set(lists, row, col + 0, b);
} else {
SafeHtml.set(lists, row, col + 0, k.describeKeyStroke());
}
lists.setText(row, col + 1, ":");
lists.setText(row, col + 2, k.getHelpText());
fmt.addStyleName(row, col + 0, KeyResources.I.css().helpKeyStroke());
fmt.addStyleName(row, col + 1, KeyResources.I.css().helpSeparator());
row++;
}
return row;
}
private List<KeyCommand> sort(final KeyCommandSet set) {
final List<KeyCommand> keys = new ArrayList<KeyCommand>(set.getKeys());
Collections.sort(keys, new Comparator<KeyCommand>() {
@Override
public int compare(KeyCommand arg0, KeyCommand arg1) {
if (arg0.keyMask < arg1.keyMask) {
return -1;
} else if (arg0.keyMask > arg1.keyMask) {
return 1;
}
return 0;
}
});
return keys;
}
}

View File

@ -0,0 +1,25 @@
// Copyright (C) 2009 The Android Open Source Project
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package com.google.gwtexpui.globalkey.client;
import com.google.gwt.core.client.GWT;
import com.google.gwt.resources.client.ClientBundle;
public interface KeyResources extends ClientBundle {
public static final KeyResources I = GWT.create(KeyResources.class);
@Source("key.css")
KeyCss css();
}

View File

@ -0,0 +1,34 @@
// Copyright (C) 2009 The Android Open Source Project
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package com.google.gwtexpui.globalkey.client;
import com.google.gwt.dom.client.Element;
import com.google.gwt.user.client.DOM;
import com.google.gwt.user.client.ui.TextArea;
public class NpTextArea extends TextArea {
public NpTextArea() {
addKeyPressHandler(GlobalKey.STOP_PROPAGATION);
}
public NpTextArea(final Element element) {
super(element);
addKeyPressHandler(GlobalKey.STOP_PROPAGATION);
}
public void setSpellCheck(boolean spell) {
DOM.setElementPropertyBoolean(getElement(), "spellcheck", spell);
}
}

View File

@ -0,0 +1,29 @@
// Copyright (C) 2009 The Android Open Source Project
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package com.google.gwtexpui.globalkey.client;
import com.google.gwt.dom.client.Element;
import com.google.gwt.user.client.ui.TextBox;
public class NpTextBox extends TextBox {
public NpTextBox() {
addKeyPressHandler(GlobalKey.STOP_PROPAGATION);
}
public NpTextBox(final Element element) {
super(element);
addKeyPressHandler(GlobalKey.STOP_PROPAGATION);
}
}

View File

@ -0,0 +1,61 @@
// Copyright (C) 2009 The Android Open Source Project
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package com.google.gwtexpui.globalkey.client;
import com.google.gwt.event.dom.client.KeyPressEvent;
import com.google.gwt.event.logical.shared.CloseEvent;
import com.google.gwt.event.logical.shared.CloseHandler;
import com.google.gwt.user.client.Window;
import com.google.gwt.user.client.ui.PopupPanel;
import com.google.gwt.user.client.ui.PopupPanel.PositionCallback;
public class ShowHelpCommand extends KeyCommand {
public static final ShowHelpCommand INSTANCE = new ShowHelpCommand();
private static KeyHelpPopup current;
public ShowHelpCommand() {
super(0, '?', KeyConstants.I.showHelp());
}
@Override
public void onKeyPress(final KeyPressEvent event) {
if (current != null) {
// Already open? Close the dialog.
//
current.hide();
current = null;
return;
}
final KeyHelpPopup help = new KeyHelpPopup();
help.addCloseHandler(new CloseHandler<PopupPanel>() {
@Override
public void onClose(final CloseEvent<PopupPanel> event) {
current = null;
}
});
current = help;
help.setPopupPositionAndShow(new PositionCallback() {
@Override
public void setPosition(final int pWidth, final int pHeight) {
final int left = (Window.getClientWidth() - pWidth) >> 1;
final int wLeft = Window.getScrollLeft();
final int wTop = Window.getScrollTop();
help.setPopupPosition(wLeft + left, wTop + 50);
}
});
}
}

View File

@ -0,0 +1,99 @@
/* Copyright (C) 2009 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
@external .popupContent;
.helpPopup {
background: #000000 none repeat scroll 0 50%;
color: #ffffff;
font-family: arial,sans-serif;
font-weight: bold;
overflow: hidden;
text-align: left;
text-shadow: 1px 1px 7px #000000;
width: 92%;
z-index: 1002;
opacity: 0.85;
}
@if user.agent safari {
.helpPopup {
\-webkit-border-radius: 10px;
}
}
@if user.agent gecko1_8 {
.helpPopup {
\-moz-border-radius: 10px;
}
}
.helpPopup .popupContent {
margin: 10px;
}
.helpPopup hr {
width: 100%;
}
.helpHeader {
width: 100%;
}
.helpHeader td {
white-space: nowrap;
color: #ffffff;
}
.helpHeader a,
.helpHeader a:visited,
.helpHeader a:hover {
color: #dddd00;
}
.helpHeaderGlue {
width: 100%;
}
.helpTable {
width: 90%;
}
.helpTable td {
vertical-align: top;
white-space: nowrap;
}
.helpTableGlue {
width: 25px;
}
.helpGroup {
color: #dddd00;
padding-top: 0.8em;
text-align: left;
}
.helpKeyStroke {
text-align: right;
}
.helpSeparator {
width: 0.5em;
text-align: center;
font-weight: bold;
}
.helpKey {
color: #dddd00;
}

View File

@ -0,0 +1,19 @@
<!--
Copyright (C) 2009 The Android Open Source Project
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http:..www.apache.org.licenses.LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
-->
<module>
<define-linker name='serverplanned' class='com.google.gwtexpui.linker.rebind.ServerPlannedIFrameLinker'/>
<add-linker name='serverplanned'/>
</module>

View File

@ -0,0 +1,68 @@
// Copyright (C) 2009 The Android Open Source Project
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package com.google.gwtexpui.linker.rebind;
import com.google.gwt.core.ext.LinkerContext;
import com.google.gwt.core.ext.TreeLogger;
import com.google.gwt.core.ext.UnableToCompleteException;
import com.google.gwt.core.ext.linker.AbstractLinker;
import com.google.gwt.core.ext.linker.ArtifactSet;
import com.google.gwt.core.ext.linker.CompilationResult;
import com.google.gwt.core.ext.linker.LinkerOrder;
import com.google.gwt.core.ext.linker.SelectionProperty;
import com.google.gwt.core.ext.linker.StylesheetReference;
import java.util.Map;
import java.util.SortedMap;
/** Saves data normally used by the {@code nocache.js} file. */
@LinkerOrder(LinkerOrder.Order.POST)
public class ServerPlannedIFrameLinker extends AbstractLinker {
@Override
public String getDescription() {
return "ServerPlannedIFrameLinker";
}
@SuppressWarnings("unchecked")
@Override
public ArtifactSet link(final TreeLogger logger, final LinkerContext context,
final ArtifactSet artifacts) throws UnableToCompleteException {
ArtifactSet toReturn = new ArtifactSet(artifacts);
StringBuilder table = new StringBuilder();
for (StylesheetReference r : artifacts.find(StylesheetReference.class)) {
table.append("css ");
table.append(r.getSrc());
table.append("\n");
}
for (CompilationResult r : artifacts.find(CompilationResult.class)) {
table.append(r.getStrongName() + "\n");
for (SortedMap<SelectionProperty, String> p : r.getPropertyMap()) {
for (Map.Entry<SelectionProperty, String> e : p.entrySet()) {
table.append(" ");
table.append(e.getKey().getName());
table.append("=");
table.append(e.getValue());
table.append('\n');
}
}
table.append("\n");
}
toReturn.add(emitString(logger, table.toString(), "permutations"));
return toReturn;
}
}

View File

@ -0,0 +1,36 @@
// Copyright (C) 2009 The Android Open Source Project
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package com.google.gwtexpui.linker.server;
import javax.servlet.http.HttpServletRequest;
/** A rule that must execute on the client, as we don't know how to compute it. */
final class ClientSideRule implements Rule {
private final String name;
ClientSideRule(String name) {
this.name = name;
}
@Override
public String getName() {
return name;
}
@Override
public String select(HttpServletRequest req) {
return null;
}
}

View File

@ -0,0 +1,160 @@
// Copyright (C) 2009 The Android Open Source Project
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package com.google.gwtexpui.linker.server;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.Arrays;
/** A single permutation of the compiled GWT application. */
public class Permutation {
private final PermutationSelector selector;
private final String cacheHTML;
private final String[] values;
Permutation(PermutationSelector sel, String cacheHTML, String[] values) {
this.selector = sel;
this.cacheHTML = cacheHTML;
this.values = values;
}
boolean matches(String[] r) {
return Arrays.equals(values, r);
}
/**
* Append GWT bootstrap for this permutation onto the end of the body.
* <p>
* The GWT bootstrap for this particular permutation is appended onto the end
* of the {@code body} element of the passed host page.
* <p>
* To keep the bootstrap code small and simple, not all GWT features are
* actually supported. The {@code gwt:property}, {@code gwt:onPropertyErrorFn}
* and {@code gwt:onLoadErrorFn} meta tags are ignored and not handled.
* <p>
* Load order may differ from the standard GWT {@code nocache.js}. The browser
* is asked to load the iframe immediately, rather than after the body has
* finished loading.
*
* @param dom host page HTML document.
*/
public void inject(Document dom) {
String moduleName = selector.getModuleName();
String moduleFunc = moduleName;
StringBuilder s = new StringBuilder();
s.append("\n");
s.append("function " + moduleFunc + "(){");
s.append("var s,l,t");
s.append(",w=window");
s.append(",d=document");
s.append(",n='" + moduleName + "'");
s.append(",f=d.createElement('iframe')");
s.append(";");
// Callback to execute the module once both s and l are true.
//
s.append("function m(){");
s.append("if(s&&l){");
// Base path needs to be absolute. There isn't an easy way to do this
// other than forcing an image to load and then pulling the URL back.
//
s.append("var b,i=d.createElement('img');");
s.append("i.src=n+'/clear.cache.gif';");
s.append("b=i.src;");
s.append("b=b.substring(0,b.lastIndexOf('/')+1);");
s.append(moduleFunc + "=null;"); // allow us to GC
s.append("f.contentWindow.gwtOnLoad(undefined,n,b);");
s.append("}");
s.append("}");
// Set s true when the module script has finished loading. The
// exact name here is known to the IFrameLinker and is called by
// the code in the iframe.
//
s.append(moduleFunc + ".onScriptLoad=function(){");
s.append("s=1;m();");
s.append("};");
// Set l true when the browser has finished processing the iframe
// tag, and everything else on the page.
//
s.append(moduleFunc + ".r=function(){");
s.append("l=1;m();");
s.append("};");
// Prevents mixed mode security in IE6/7.
s.append("f.src=\"javascript:''\";");
s.append("f.id=n;");
s.append("f.style.cssText"
+ "='position:absolute;width:0;height:0;border:none';");
s.append("f.tabIndex=-1;");
s.append("d.body.appendChild(f);");
// The src has to be set after the iframe is attached to the DOM to avoid
// refresh quirks in Safari. We have to use the location.replace trick to
// avoid FF2 refresh quirks.
//
s.append("f.contentWindow.location.replace(n+'/" + cacheHTML + "');");
// defer attribute here is to workaround IE running immediately.
//
s.append("d.write('<script defer=\"defer\">" //
+ moduleFunc + ".r()</'+'script>');");
s.append("}");
s.append(moduleFunc + "();");
s.append("\n//");
final Element html = dom.getDocumentElement();
final Element head = (Element) html.getElementsByTagName("head").item(0);
final Element body = (Element) html.getElementsByTagName("body").item(0);
for (String css : selector.getCSS()) {
if (isRelativeURL(css)) {
css = moduleName + '/' + css;
}
final Element link = dom.createElement("link");
link.setAttribute("rel", "stylesheet");
link.setAttribute("href", css);
head.appendChild(link);
}
final Element script = dom.createElement("script");
script.setAttribute("type", "text/javascript");
script.setAttribute("language", "javascript");
script.appendChild(dom.createComment(s.toString()));
body.appendChild(script);
}
private static boolean isRelativeURL(String src) {
if (src.startsWith("/")) {
return false;
}
try {
// If it parses as a URL, assume it is not relative.
//
new URL(src);
return false;
} catch (MalformedURLException e) {
}
return true;
}
}

View File

@ -0,0 +1,205 @@
// Copyright (C) 2009 The Android Open Source Project
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package com.google.gwtexpui.linker.server;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
/**
* Selects a permutation based on the HTTP request.
* <p>
* To use this class the application's GWT module must include our linker by
* inheriting our module:
*
* <pre>
* &lt;inherits name='com.google.gwtexpui.linker.ServerPlannedIFrameLinker'/&gt;
* </pre>
*/
public class PermutationSelector {
private final String moduleName;
private final Map<String, Rule> rulesByName;
private final List<Rule> ruleOrder;
private final List<Permutation> permutations;
private final List<String> css;
/**
* Create an empty selector for a module.
* <p>
* {@link UserAgentRule} rule is automatically registered. Additional custom
* selector rules may be registered before {@link #init(ServletContext)} is
* called to finish the selector setup.
*
* @param moduleName the name of the module within the context.
*/
public PermutationSelector(final String moduleName) {
this.moduleName = moduleName;
this.rulesByName = new HashMap<String, Rule>();
this.ruleOrder = new ArrayList<Rule>();
this.permutations = new ArrayList<Permutation>();
this.css = new ArrayList<String>();
register(new UserAgentRule());
}
private void notInitialized() {
if (!ruleOrder.isEmpty()) {
throw new IllegalStateException("Already initialized");
}
}
/**
* Register a property selection rule.
*
* @param r the rule implementation.
*/
public void register(Rule r) {
notInitialized();
rulesByName.put(r.getName(), r);
}
/**
* Initialize the selector by reading the module's {@code permutations} file.
*
* @param ctx context to load the module data from.
* @throws ServletException
* @throws IOException
*/
public void init(ServletContext ctx) throws ServletException, IOException {
notInitialized();
final String tableName = "/" + moduleName + "/permutations";
final InputStream in = ctx.getResourceAsStream(tableName);
if (in == null) {
throw new ServletException("No " + tableName + " in context");
}
try {
BufferedReader r = new BufferedReader(new InputStreamReader(in, "UTF-8"));
for (;;) {
final String strongName = r.readLine();
if (strongName == null) {
break;
}
if (strongName.startsWith("css ")) {
css.add(strongName.substring("css ".length()));
continue;
}
Map<String, String> selections = new LinkedHashMap<String, String>();
for (;;) {
String permutation = r.readLine();
if (permutation == null || permutation.isEmpty()) {
break;
}
int eq = permutation.indexOf('=');
if (eq < 0) {
throw new ServletException(tableName + " has malformed content");
}
String k = permutation.substring(0, eq).trim();
String v = permutation.substring(eq + 1);
Rule rule = get(k);
if (!ruleOrder.contains(rule)) {
ruleOrder.add(rule);
}
if (selections.put(k, v) != null) {
throw new ServletException("Table " + tableName
+ " has multiple values for " + k + " within permutation "
+ strongName);
}
}
String cacheHtml = strongName + ".cache.html";
String[] values = new String[ruleOrder.size()];
for (int i = 0; i < values.length; i++) {
values[i] = selections.get(ruleOrder.get(i).getName());
}
permutations.add(new Permutation(this, cacheHtml, values));
}
} finally {
in.close();
}
}
private Rule get(final String name) {
Rule r = rulesByName.get(name);
if (r == null) {
r = new ClientSideRule(name);
register(r);
}
return r;
}
/** @return name of the module (within the application context). */
public String getModuleName() {
return moduleName;
}
/** @return all possible permutations */
public List<Permutation> getPermutations() {
return Collections.unmodifiableList(permutations);
}
/**
* Select the permutation that best matches the browser request.
*
* @param req current request.
* @return the selected permutation; null if no permutation can be fit to the
* request and the standard {@code nocache.js} loader must be used.
*/
public Permutation select(HttpServletRequest req) {
final String[] values = new String[ruleOrder.size()];
for (int i = 0; i < values.length; i++) {
final String value = ruleOrder.get(i).select(req);
if (value == null) {
// If the rule returned null it doesn't know how to compute
// the value for this HTTP request. Since we can't do that
// defer to JavaScript by not picking a permutation.
//
return null;
}
values[i] = value;
}
for (Permutation p : permutations) {
if (p.matches(values)) {
return p;
}
}
return null;
}
Collection<String> getCSS() {
return css;
}
}

View File

@ -0,0 +1,40 @@
// Copyright (C) 2009 The Android Open Source Project
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package com.google.gwtexpui.linker.server;
import javax.servlet.http.HttpServletRequest;
/** A selection rule for a permutation property. */
public interface Rule {
/** @return the property name, for example {@code "user.agent"}. */
public String getName();
/**
* Compute the value for this property, given the current request.
* <p>
* This rule method must compute the proper permutation value, matching what
* the GWT module XML files use for this property. The rule may use any state
* available in the current servlet request.
* <p>
* If this method returns {@code null} server side selection will be aborted
* and selection for all properties will be handled on the client side by the
* {@code nocache.js} file.
*
* @param req the request
* @return the value for the property; null if the value cannot be determined
* on the server side.
*/
public String select(HttpServletRequest req);
}

View File

@ -0,0 +1,93 @@
// Copyright (C) 2009 The Android Open Source Project
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package com.google.gwtexpui.linker.server;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import static java.util.regex.Pattern.compile;
import javax.servlet.http.HttpServletRequest;
/**
* Selects the value for the {@code user.agent} property.
* <p>
* Examines the {@code User-Agent} HTTP request header, and tries to match it to
* known {@code user.agent} values.
* <p>
* Ported from JavaScript in {@code com.google.gwt.user.UserAgent.gwt.xml}.
*/
public class UserAgentRule implements Rule {
private static final Pattern msie = compile(".*msie ([0-9]+)\\.([0-9]+).*");
private static final Pattern gecko = compile(".*rv:([0-9]+)\\.([0-9]+).*");
public String getName() {
return "user.agent";
}
@Override
public String select(HttpServletRequest req) {
String ua = req.getHeader("User-Agent");
if (ua == null) {
return null;
}
ua = ua.toLowerCase();
if (ua.indexOf("opera") != -1) {
return "opera";
} else if (ua.indexOf("webkit") != -1) {
return "safari";
} else if (ua.indexOf("msie") != -1) {
// GWT 2.0 uses document.documentMode here, which we can't do
// on the server side.
Matcher m = msie.matcher(ua);
if (m.matches() && m.groupCount() == 2) {
int v = makeVersion(m);
if (v >= 10000) {
return "ie10";
}
if (v >= 9000) {
return "ie9";
}
if (v >= 8000) {
return "ie8";
}
if (v >= 6000) {
return "ie6";
}
}
return null;
} else if (ua.indexOf("gecko") != -1) {
Matcher m = gecko.matcher(ua);
if (m.matches() && m.groupCount() == 2) {
if (makeVersion(m) >= 1008) {
return "gecko1_8";
}
}
return "gecko";
}
return null;
}
private int makeVersion(Matcher result) {
return (Integer.parseInt(result.group(1)) * 1000)
+ Integer.parseInt(result.group(2));
}
}

View File

@ -0,0 +1,19 @@
<!--
Copyright (C) 2009 The Android Open Source Project
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
-->
<module>
<inherits name='com.google.gwt.resources.Resources'/>
<inherits name="com.google.gwt.user.User"/>
</module>

View File

@ -0,0 +1,77 @@
// Copyright (C) 2009 The Android Open Source Project
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package com.google.gwtexpui.progress.client;
import com.google.gwt.user.client.ui.Composite;
import com.google.gwt.user.client.ui.FlowPanel;
import com.google.gwt.user.client.ui.Label;
/**
* A simple progress bar with a text label.
* <p>
* The bar is 200 pixels wide and 20 pixels high. To keep the implementation
* simple and lightweight this dimensions are fixed and shouldn't be modified by
* style overrides in client code or CSS.
*/
public class ProgressBar extends Composite {
static {
ProgressResources.I.css().ensureInjected();
}
private final String callerText;
private final Label bar;
private final Label msg;
private int value;
/** Create a bar with no message text. */
public ProgressBar() {
this("");
}
/** Create a bar displaying the specified message. */
public ProgressBar(final String text) {
if (text == null || text.length() == 0) {
callerText = "";
} else {
callerText = text + " ";
}
final FlowPanel body = new FlowPanel();
body.setStyleName(ProgressResources.I.css().container());
msg = new Label(callerText);
msg.setStyleName(ProgressResources.I.css().text());
body.add(msg);
bar = new Label("");
bar.setStyleName(ProgressResources.I.css().bar());
body.add(bar);
initWidget(body);
}
/** @return the current value of the progress meter. */
public int getValue() {
return value;
}
/** Update the bar's percent completion. */
public void setValue(final int pComplete) {
assert 0 <= pComplete && pComplete <= 100;
value = pComplete;
bar.setWidth("" + (2 * pComplete) + "px");
msg.setText(callerText + pComplete + "%");
}
}

View File

@ -0,0 +1,23 @@
// Copyright (C) 2009 The Android Open Source Project
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package com.google.gwtexpui.progress.client;
import com.google.gwt.resources.client.CssResource;
public interface ProgressCss extends CssResource {
String container();
String text();
String bar();
}

View File

@ -0,0 +1,25 @@
// Copyright (C) 2009 The Android Open Source Project
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package com.google.gwtexpui.progress.client;
import com.google.gwt.core.client.GWT;
import com.google.gwt.resources.client.ClientBundle;
public interface ProgressResources extends ClientBundle {
public static final ProgressResources I = GWT.create(ProgressResources.class);
@Source("progress.css")
ProgressCss css();
}

View File

@ -0,0 +1,43 @@
/* Copyright (C) 2009 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
.container {
position: relative;
border: 1px solid #6B90DA;
height: 20px;
width: 200px;
}
.text {
position: absolute;
bottom: 0;
left: 0;
z-index: 2;
width: 200px;
padding-bottom: 3px;
text-align: center;
font-weight: bold;
font-style: italic;
font-size: smaller;
}
.bar {
background: #F0F7F9;
border-right: 1px solid #D0D7D9;
position: absolute;
top: 0;
left: 0;
height: 20px;
}

View File

@ -0,0 +1,19 @@
<!--
Copyright (C) 2009 The Android Open Source Project
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
-->
<module>
<inherits name='com.google.gwt.resources.Resources'/>
<inherits name="com.google.gwt.user.User"/>
</module>

View File

@ -0,0 +1,137 @@
// Copyright (C) 2009 The Android Open Source Project
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package com.google.gwtexpui.safehtml.client;
import java.util.ArrayList;
import java.util.HashMap;
/** Lightweight map of names/values for element attribute construction. */
class AttMap {
private static final Tag ANY = new AnyTag();
private static final HashMap<String, Tag> TAGS;
static {
final Tag src = new SrcTag();
TAGS = new HashMap<String, Tag>();
TAGS.put("a", new AnchorTag());
TAGS.put("form", new FormTag());
TAGS.put("img", src);
TAGS.put("script", src);
TAGS.put("frame", src);
}
private final ArrayList<String> names = new ArrayList<String>();
private final ArrayList<String> values = new ArrayList<String>();
private Tag tag = ANY;
private int live;
void reset(final String tagName) {
tag = TAGS.get(tagName.toLowerCase());
if (tag == null) {
tag = ANY;
}
live = 0;
}
void onto(final Buffer raw, final SafeHtmlBuilder esc) {
for (int i = 0; i < live; i++) {
final String v = values.get(i);
if (v.length() > 0) {
raw.append(" ");
raw.append(names.get(i));
raw.append("=\"");
esc.append(v);
raw.append("\"");
}
}
}
String get(String name) {
name = name.toLowerCase();
for (int i = 0; i < live; i++) {
if (name.equals(names.get(i))) {
return values.get(i);
}
}
return "";
}
void set(String name, final String value) {
name = name.toLowerCase();
tag.assertSafe(name, value);
for (int i = 0; i < live; i++) {
if (name.equals(names.get(i))) {
values.set(i, value);
return;
}
}
final int i = live++;
if (names.size() < live) {
names.add(name);
values.add(value);
} else {
names.set(i, name);
values.set(i, value);
}
}
private static void assertNotJavascriptUrl(final String value) {
if (value.startsWith("#")) {
// common in GWT, and safe, so bypass further checks
} else if (value.trim().toLowerCase().startsWith("javascript:")) {
// possibly unsafe, we could have random user code here
// we can't tell if its safe or not so we refuse to accept
//
throw new RuntimeException("javascript unsafe in href: " + value);
}
}
private static interface Tag {
void assertSafe(String name, String value);
}
private static class AnyTag implements Tag {
public void assertSafe(String name, String value) {
}
}
private static class AnchorTag implements Tag {
public void assertSafe(String name, String value) {
if ("href".equals(name)) {
assertNotJavascriptUrl(value);
}
}
}
private static class FormTag implements Tag {
public void assertSafe(String name, String value) {
if ("action".equals(name)) {
assertNotJavascriptUrl(value);
}
}
}
private static class SrcTag implements Tag {
public void assertSafe(String name, String value) {
if ("src".equals(name)) {
assertNotJavascriptUrl(value);
}
}
}
}

View File

@ -0,0 +1,33 @@
// Copyright (C) 2009 The Android Open Source Project
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package com.google.gwtexpui.safehtml.client;
interface Buffer {
void append(boolean v);
void append(char v);
void append(int v);
void append(long v);
void append(float v);
void append(double v);
void append(String v);
String toString();
}

View File

@ -0,0 +1,56 @@
// Copyright (C) 2009 The Android Open Source Project
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package com.google.gwtexpui.safehtml.client;
final class BufferDirect implements Buffer {
private final StringBuilder strbuf = new StringBuilder();
boolean isEmpty() {
return strbuf.length() == 0;
}
public void append(final boolean v) {
strbuf.append(v);
}
public void append(final char v) {
strbuf.append(v);
}
public void append(final int v) {
strbuf.append(v);
}
public void append(final long v) {
strbuf.append(v);
}
public void append(final float v) {
strbuf.append(v);
}
public void append(final double v) {
strbuf.append(v);
}
public void append(final String v) {
strbuf.append(v);
}
@Override
public String toString() {
return strbuf.toString();
}
}

View File

@ -0,0 +1,56 @@
// Copyright (C) 2009 The Android Open Source Project
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package com.google.gwtexpui.safehtml.client;
final class BufferSealElement implements Buffer {
private final SafeHtmlBuilder shb;
BufferSealElement(final SafeHtmlBuilder safeHtmlBuilder) {
shb = safeHtmlBuilder;
}
public void append(final boolean v) {
shb.sealElement().append(v);
}
public void append(final char v) {
shb.sealElement().append(v);
}
public void append(final double v) {
shb.sealElement().append(v);
}
public void append(final float v) {
shb.sealElement().append(v);
}
public void append(final int v) {
shb.sealElement().append(v);
}
public void append(final long v) {
shb.sealElement().append(v);
}
public void append(final String v) {
shb.sealElement().append(v);
}
@Override
public String toString() {
return shb.sealElement().toString();
}
}

View File

@ -0,0 +1,40 @@
// Copyright (C) 2013 The Android Open Source Project
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package com.google.gwtexpui.safehtml.client;
import com.google.gwt.regexp.shared.RegExp;
/** A Find/Replace pair used against the {@link SafeHtml} block of text. */
public interface FindReplace {
/**
* @return regular expression to match substrings with; should be treated as
* immutable.
*/
public RegExp pattern();
/**
* Find and replace a single instance of this pattern in an input.
* <p>
* <b>WARNING:</b> No XSS sanitization is done on the return value of this
* method, e.g. this value may be passed directly to
* {@link SafeHtml#replaceAll(String, String)}. Implementations must sanitize output
* appropriately.
*
* @param input input string.
* @return result of regular expression replacement.
* @throws IllegalArgumentException if the input could not be safely sanitized.
*/
public String replace(String input);
}

View File

@ -0,0 +1,96 @@
// Copyright (C) 2009 The Android Open Source Project
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package com.google.gwtexpui.safehtml.client;
import com.google.gwt.user.client.ui.SuggestOracle;
import java.util.ArrayList;
/**
* A suggestion oracle that tries to highlight the matched text.
* <p>
* Suggestions supplied by the implementation of
* {@link #onRequestSuggestions(Request, Callback)} are modified to wrap all
* occurrences of the {@link SuggestOracle.Request#getQuery()} substring in HTML
* <code>&lt;strong&gt;</code> tags, so they can be emphasized to the user.
*/
public abstract class HighlightSuggestOracle extends SuggestOracle {
private static String escape(String ds) {
return new SafeHtmlBuilder().append(ds).asString();
}
@Override
public final boolean isDisplayStringHTML() {
return true;
}
@Override
public final void requestSuggestions(final Request request, final Callback cb) {
onRequestSuggestions(request, new Callback() {
public void onSuggestionsReady(final Request request,
final Response response) {
final String qpat = getQueryPattern(request.getQuery());
final boolean html = isHTML();
final ArrayList<Suggestion> r = new ArrayList<Suggestion>();
for (final Suggestion s : response.getSuggestions()) {
r.add(new BoldSuggestion(qpat, s, html));
}
cb.onSuggestionsReady(request, new Response(r));
}
});
}
protected String getQueryPattern(final String query) {
return "(" + escape(query) + ")";
}
/**
* @return true if {@link SuggestOracle.Suggestion#getDisplayString()} returns
* HTML; false if the text must be escaped before evaluating in an
* HTML like context.
*/
protected boolean isHTML() {
return false;
}
/** Compute the suggestions and return them for display. */
protected abstract void onRequestSuggestions(Request request, Callback done);
private static class BoldSuggestion implements Suggestion {
private final Suggestion suggestion;
private final String displayString;
BoldSuggestion(final String qstr, final Suggestion s, final boolean html) {
suggestion = s;
String ds = s.getDisplayString();
if (!html) {
ds = escape(ds);
}
displayString = sgi(ds, qstr, "<strong>$1</strong>");
}
private static native String sgi(String inString, String pat, String newHtml)
/*-{ return inString.replace(RegExp(pat, 'gi'), newHtml); }-*/;
public String getDisplayString() {
return displayString;
}
public String getReplacementString() {
return suggestion.getReplacementString();
}
}
}

View File

@ -0,0 +1,84 @@
// Copyright (C) 2013 The Android Open Source Project
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package com.google.gwtexpui.safehtml.client;
import com.google.gwt.regexp.shared.RegExp;
/**
* A Find/Replace pair whose replacement string is a link.
* <p>
* It is safe to pass arbitrary user-provided links to this class. Links are
* sanitized as follows:
* <ul>
* <li>Only http(s) and mailto links are supported; any other scheme results in
* an {@link IllegalArgumentException} from {@link #replace(String)}.
* <li>Special characters in the link after regex replacement are escaped with
* {@link SafeHtmlBuilder}.</li>
* </ul>
*/
public class LinkFindReplace implements FindReplace {
public static boolean hasValidScheme(String link) {
int colon = link.indexOf(':');
if (colon < 0) {
return true;
}
String scheme = link.substring(0, colon);
return "http".equalsIgnoreCase(scheme)
|| "https".equalsIgnoreCase(scheme)
|| "mailto".equalsIgnoreCase(scheme);
}
private RegExp pat;
private String link;
protected LinkFindReplace() {
}
/**
* @param regex regular expression pattern to match substrings with.
* @param repl replacement link href. Capture groups within
* <code>regex</code> can be referenced with <code>$<i>n</i></code>.
*/
public LinkFindReplace(String find, String link) {
this.pat = RegExp.compile(find);
this.link = link;
}
@Override
public RegExp pattern() {
return pat;
}
@Override
public String replace(String input) {
String href = pat.replace(input, link);
if (!hasValidScheme(href)) {
throw new IllegalArgumentException(
"Invalid scheme (" + toString() + "): " + href);
}
String result = new SafeHtmlBuilder()
.openAnchor()
.setAttribute("href", href)
.append(SafeHtml.asis(input))
.closeAnchor()
.asString();
return result;
}
@Override
public String toString() {
return "find = " + pat.getSource() + ", link = " + link;
}
}

View File

@ -0,0 +1,55 @@
// Copyright (C) 2009 The Android Open Source Project
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package com.google.gwtexpui.safehtml.client;
import com.google.gwt.regexp.shared.RegExp;
/**
* A Find/Replace pair whose replacement string is arbitrary HTML.
* <p>
* <b>WARNING:</b> This class is not safe used with user-provided patterns.
*/
public class RawFindReplace implements FindReplace {
private RegExp pat;
private String replace;
protected RawFindReplace() {
}
/**
* @param regex regular expression pattern to match substrings with.
* @param repl replacement expression. Capture groups within
* <code>regex</code> can be referenced with <code>$<i>n</i></code>.
*/
public RawFindReplace(String find, String replace) {
this.pat = RegExp.compile(find);
this.replace = replace;
}
@Override
public RegExp pattern() {
return pat;
}
@Override
public String replace(String input) {
return pat.replace(input, replace);
}
@Override
public String toString() {
return "find = " + pat.getSource() + ", replace = " + replace;
}
}

View File

@ -0,0 +1,302 @@
// Copyright (C) 2009 The Android Open Source Project
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package com.google.gwtexpui.safehtml.client;
import com.google.gwt.core.client.GWT;
import com.google.gwt.regexp.shared.MatchResult;
import com.google.gwt.regexp.shared.RegExp;
import com.google.gwt.user.client.DOM;
import com.google.gwt.user.client.Element;
import com.google.gwt.user.client.ui.HTML;
import com.google.gwt.user.client.ui.HTMLTable;
import com.google.gwt.user.client.ui.HasHTML;
import com.google.gwt.user.client.ui.InlineHTML;
import com.google.gwt.user.client.ui.Widget;
import java.util.Iterator;
import java.util.List;
/** Immutable string safely placed as HTML without further escaping. */
public abstract class SafeHtml {
public static final SafeHtmlResources RESOURCES;
static {
if (GWT.isClient()) {
RESOURCES = GWT.create(SafeHtmlResources.class);
RESOURCES.css().ensureInjected();
} else {
RESOURCES = new SafeHtmlResources() {
@Override
public SafeHtmlCss css() {
return new SafeHtmlCss() {
public String wikiList() {
return "wikiList";
}
public String wikiPreFormat() {
return "wikiPreFormat";
}
public boolean ensureInjected() {
return false;
}
public String getName() {
return null;
}
public String getText() {
return null;
}
};
}
};
}
}
/** @return the existing HTML property of a widget. */
public static SafeHtml get(final HasHTML t) {
return new SafeHtmlString(t.getHTML());
}
/** @return the existing HTML text, wrapped in a safe buffer. */
public static SafeHtml asis(final String htmlText) {
return new SafeHtmlString(htmlText);
}
/** Set the HTML property of a widget. */
public static <T extends HasHTML> T set(final T e, final SafeHtml str) {
e.setHTML(str.asString());
return e;
}
/** @return the existing inner HTML of any element. */
public static SafeHtml get(final Element e) {
return new SafeHtmlString(DOM.getInnerHTML(e));
}
/** Set the inner HTML of any element. */
public static Element set(final Element e, final SafeHtml str) {
DOM.setInnerHTML(e, str.asString());
return e;
}
/** @return the existing inner HTML of a table cell. */
public static SafeHtml get(final HTMLTable t, final int row, final int col) {
return new SafeHtmlString(t.getHTML(row, col));
}
/** Set the inner HTML of a table cell. */
public static <T extends HTMLTable> T set(final T t, final int row,
final int col, final SafeHtml str) {
t.setHTML(row, col, str.asString());
return t;
}
/** Parse an HTML block and return the first (typically root) element. */
public static Element parse(final SafeHtml str) {
return DOM.getFirstChild(set(DOM.createDiv(), str));
}
/** Convert bare http:// and https:// URLs into &lt;a href&gt; tags. */
public SafeHtml linkify() {
final String part = "(?:" +
"[a-zA-Z0-9$_.+!*',%;:@=?#/~-]" +
"|&(?!lt;|gt;)" +
")";
return replaceAll(
"(https?://" +
part + "{2,}" +
"(?:[(]" + part + "*" + "[)])*" +
part + "*" +
")",
"<a href=\"$1\" target=\"_blank\">$1</a>");
}
/**
* Apply {@link #linkify()}, and "\n\n" to &lt;p&gt;.
* <p>
* Lines that start with whitespace are assumed to be preformatted, and are
* formatted by the {@link SafeHtmlCss#wikiPreFormat()} CSS class.
*/
public SafeHtml wikify() {
final SafeHtmlBuilder r = new SafeHtmlBuilder();
for (final String p : linkify().asString().split("\n\n")) {
if (isPreFormat(p)) {
r.openElement("p");
for (final String line : p.split("\n")) {
r.openSpan();
r.setStyleName(RESOURCES.css().wikiPreFormat());
r.append(asis(line));
r.closeSpan();
r.br();
}
r.closeElement("p");
} else if (isList(p)) {
wikifyList(r, p);
} else {
r.openElement("p");
r.append(asis(p));
r.closeElement("p");
}
}
return r.toSafeHtml();
}
private void wikifyList(final SafeHtmlBuilder r, final String p) {
boolean in_ul = false;
boolean in_p = false;
for (String line : p.split("\n")) {
if (line.startsWith("-") || line.startsWith("*")) {
if (!in_ul) {
if (in_p) {
in_p = false;
r.closeElement("p");
}
in_ul = true;
r.openElement("ul");
r.setStyleName(RESOURCES.css().wikiList());
}
line = line.substring(1).trim();
} else if (!in_ul) {
if (!in_p) {
in_p = true;
r.openElement("p");
} else {
r.append(' ');
}
r.append(asis(line));
continue;
}
r.openElement("li");
r.append(asis(line));
r.closeElement("li");
}
if (in_ul) {
r.closeElement("ul");
} else if (in_p) {
r.closeElement("p");
}
}
private static boolean isPreFormat(final String p) {
return p.contains("\n ") || p.contains("\n\t") || p.startsWith(" ")
|| p.startsWith("\t");
}
private static boolean isList(final String p) {
return p.contains("\n- ") || p.contains("\n* ") || p.startsWith("- ")
|| p.startsWith("* ");
}
/**
* Replace first occurrence of <code>regex</code> with <code>repl</code> .
* <p>
* <b>WARNING:</b> This replacement is being performed against an otherwise
* safe HTML string. The caller must ensure that the replacement does not
* introduce cross-site scripting attack entry points.
*
* @param regex regular expression pattern to match the substring with.
* @param repl replacement expression. Capture groups within
* <code>regex</code> can be referenced with <code>$<i>n</i></code>.
* @return a new string, after the replacement has been made.
*/
public SafeHtml replaceFirst(final String regex, final String repl) {
return new SafeHtmlString(asString().replaceFirst(regex, repl));
}
/**
* Replace each occurrence of <code>regex</code> with <code>repl</code> .
* <p>
* <b>WARNING:</b> This replacement is being performed against an otherwise
* safe HTML string. The caller must ensure that the replacement does not
* introduce cross-site scripting attack entry points.
*
* @param regex regular expression pattern to match substrings with.
* @param repl replacement expression. Capture groups within
* <code>regex</code> can be referenced with <code>$<i>n</i></code>.
* @return a new string, after the replacements have been made.
*/
public SafeHtml replaceAll(final String regex, final String repl) {
return new SafeHtmlString(asString().replaceAll(regex, repl));
}
/**
* Replace all find/replace pairs in the list in a single pass.
*
* @param findReplaceList find/replace pairs to use.
* @return a new string, after the replacements have been made.
*/
public <T> SafeHtml replaceAll(List<? extends FindReplace> findReplaceList) {
if (findReplaceList == null || findReplaceList.isEmpty()) {
return this;
}
StringBuilder pat = new StringBuilder();
Iterator<? extends FindReplace> it = findReplaceList.iterator();
while (it.hasNext()) {
FindReplace fr = it.next();
pat.append(fr.pattern().getSource());
if (it.hasNext()) {
pat.append('|');
}
}
StringBuilder result = new StringBuilder();
RegExp re = RegExp.compile(pat.toString(), "g");
String orig = asString();
int index = 0;
MatchResult mat;
while ((mat = re.exec(orig)) != null) {
String g = mat.getGroup(0);
// Re-run each candidate to find which one matched.
for (FindReplace fr : findReplaceList) {
if (fr.pattern().test(g)) {
try {
String repl = fr.replace(g);
result.append(orig.substring(index, mat.getIndex()));
result.append(repl);
} catch (IllegalArgumentException e) {
continue;
}
index = mat.getIndex() + g.length();
break;
}
}
}
result.append(orig.substring(index, orig.length()));
return asis(result.toString());
}
/** @return a GWT block display widget displaying this HTML. */
public Widget toBlockWidget() {
return new HTML(asString());
}
/** @return a GWT inline display widget displaying this HTML. */
public Widget toInlineWidget() {
return new InlineHTML(asString());
}
/** @return a clean HTML string safe for inclusion in any context. */
public abstract String asString();
}

View File

@ -0,0 +1,411 @@
// Copyright (C) 2009 The Android Open Source Project
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package com.google.gwtexpui.safehtml.client;
import com.google.gwt.core.client.GWT;
/**
* Safely constructs a {@link SafeHtml}, escaping user provided content.
*/
public class SafeHtmlBuilder extends SafeHtml {
private static final Impl impl;
static {
if (GWT.isClient()) {
impl = new ClientImpl();
} else {
impl = new ServerImpl();
}
}
private final BufferDirect dBuf;
private Buffer cb;
private BufferSealElement sBuf;
private AttMap att;
public SafeHtmlBuilder() {
cb = dBuf = new BufferDirect();
}
/** @return true if this builder has not had an append occur yet. */
public boolean isEmpty() {
return dBuf.isEmpty();
}
/** @return true if this builder has content appended into it. */
public boolean hasContent() {
return !isEmpty();
}
public SafeHtmlBuilder append(final boolean in) {
cb.append(in);
return this;
}
public SafeHtmlBuilder append(final char in) {
switch (in) {
case '&':
cb.append("&amp;");
break;
case '>':
cb.append("&gt;");
break;
case '<':
cb.append("&lt;");
break;
case '"':
cb.append("&quot;");
break;
case '\'':
cb.append("&#39;");
break;
default:
cb.append(in);
break;
}
return this;
}
public SafeHtmlBuilder append(final int in) {
cb.append(in);
return this;
}
public SafeHtmlBuilder append(final long in) {
cb.append(in);
return this;
}
public SafeHtmlBuilder append(final float in) {
cb.append(in);
return this;
}
public SafeHtmlBuilder append(final double in) {
cb.append(in);
return this;
}
/** Append already safe HTML as-is, avoiding double escaping. */
public SafeHtmlBuilder append(final SafeHtml in) {
if (in != null) {
cb.append(in.asString());
}
return this;
}
/** Append the string, escaping unsafe characters. */
public SafeHtmlBuilder append(final String in) {
if (in != null) {
impl.escapeStr(this, in);
}
return this;
}
/** Append the string, escaping unsafe characters. */
public SafeHtmlBuilder append(final StringBuilder in) {
if (in != null) {
append(in.toString());
}
return this;
}
/** Append the string, escaping unsafe characters. */
public SafeHtmlBuilder append(final StringBuffer in) {
if (in != null) {
append(in.toString());
}
return this;
}
/** Append the result of toString(), escaping unsafe characters. */
public SafeHtmlBuilder append(final Object in) {
if (in != null) {
append(in.toString());
}
return this;
}
/** Append the string, escaping unsafe characters. */
public SafeHtmlBuilder append(final CharSequence in) {
if (in != null) {
escapeCS(this, in);
}
return this;
}
/**
* Open an element, appending "<tagName>" to the buffer.
* <p>
* After the element is open the attributes may be manipulated until the next
* <code>append</code>, <code>openElement</code>, <code>closeSelf</code> or
* <code>closeElement</code> call.
*
* @param tagName name of the HTML element to open.
*/
public SafeHtmlBuilder openElement(final String tagName) {
assert isElementName(tagName);
cb.append("<");
cb.append(tagName);
if (sBuf == null) {
att = new AttMap();
sBuf = new BufferSealElement(this);
}
att.reset(tagName);
cb = sBuf;
return this;
}
/**
* Get an attribute of the last opened element.
*
* @param name name of the attribute to read.
* @return the attribute value, as a string. The empty string if the attribute
* has not been assigned a value. The returned string is the raw
* (unescaped) value.
*/
public String getAttribute(final String name) {
assert isAttributeName(name);
assert cb == sBuf;
return att.get(name);
}
/**
* Set an attribute of the last opened element.
*
* @param name name of the attribute to set.
* @param value value to assign; any existing value is replaced. The value is
* escaped (if necessary) during the assignment.
*/
public SafeHtmlBuilder setAttribute(final String name, final String value) {
assert isAttributeName(name);
assert cb == sBuf;
att.set(name, value != null ? value : "");
return this;
}
/**
* Set an attribute of the last opened element.
*
* @param name name of the attribute to set.
* @param value value to assign, any existing value is replaced.
*/
public SafeHtmlBuilder setAttribute(final String name, final int value) {
return setAttribute(name, String.valueOf(value));
}
/**
* Append a new value into a whitespace delimited attribute.
* <p>
* If the attribute is not yet assigned, this method sets the attribute. If
* the attribute is already assigned, the new value is appended onto the end,
* after appending a single space to delimit the values.
*
* @param name name of the attribute to append onto.
* @param value additional value to append.
*/
public SafeHtmlBuilder appendAttribute(final String name, String value) {
if (value != null && value.length() > 0) {
final String e = getAttribute(name);
return setAttribute(name, e.length() > 0 ? e + " " + value : value);
}
return this;
}
/** Set the height attribute of the current element. */
public SafeHtmlBuilder setHeight(final int height) {
return setAttribute("height", height);
}
/** Set the width attribute of the current element. */
public SafeHtmlBuilder setWidth(final int width) {
return setAttribute("width", width);
}
/** Set the CSS class name for this element. */
public SafeHtmlBuilder setStyleName(final String style) {
assert isCssName(style);
return setAttribute("class", style);
}
/**
* Add an additional CSS class name to this element.
*<p>
* If no CSS class name has been specified yet, this method initializes it to
* the single name.
*/
public SafeHtmlBuilder addStyleName(final String style) {
assert isCssName(style);
return appendAttribute("class", style);
}
private void sealElement0() {
assert cb == sBuf;
cb = dBuf;
att.onto(cb, this);
}
Buffer sealElement() {
sealElement0();
cb.append(">");
return cb;
}
/** Close the current element with a self closing suffix ("/ &gt;"). */
public SafeHtmlBuilder closeSelf() {
sealElement0();
cb.append(" />");
return this;
}
/** Append a closing tag for the named element. */
public SafeHtmlBuilder closeElement(final String name) {
assert isElementName(name);
cb.append("</");
cb.append(name);
cb.append(">");
return this;
}
/** Append "&amp;nbsp;" - a non-breaking space, useful in empty table cells. */
public SafeHtmlBuilder nbsp() {
cb.append("&nbsp;");
return this;
}
/** Append "&lt;br /&gt;" - a line break with no attributes */
public SafeHtmlBuilder br() {
cb.append("<br />");
return this;
}
/** Append "&lt;tr&gt;"; attributes may be set if needed */
public SafeHtmlBuilder openTr() {
return openElement("tr");
}
/** Append "&lt;/tr&gt;" */
public SafeHtmlBuilder closeTr() {
return closeElement("tr");
}
/** Append "&lt;td&gt;"; attributes may be set if needed */
public SafeHtmlBuilder openTd() {
return openElement("td");
}
/** Append "&lt;/td&gt;" */
public SafeHtmlBuilder closeTd() {
return closeElement("td");
}
/** Append "&lt;div&gt;"; attributes may be set if needed */
public SafeHtmlBuilder openDiv() {
return openElement("div");
}
/** Append "&lt;/div&gt;" */
public SafeHtmlBuilder closeDiv() {
return closeElement("div");
}
/** Append "&lt;span&gt;"; attributes may be set if needed */
public SafeHtmlBuilder openSpan() {
return openElement("span");
}
/** Append "&lt;/span&gt;" */
public SafeHtmlBuilder closeSpan() {
return closeElement("span");
}
/** Append "&lt;a&gt;"; attributes may be set if needed */
public SafeHtmlBuilder openAnchor() {
return openElement("a");
}
/** Append "&lt;/a&gt;" */
public SafeHtmlBuilder closeAnchor() {
return closeElement("a");
}
/** Append "&lt;param name=... value=... /&gt;". */
public SafeHtmlBuilder paramElement(final String name, final String value) {
openElement("param");
setAttribute("name", name);
setAttribute("value", value);
return closeSelf();
}
/** @return an immutable {@link SafeHtml} representation of the buffer. */
public SafeHtml toSafeHtml() {
return new SafeHtmlString(asString());
}
@Override
public String asString() {
return cb.toString();
}
private static void escapeCS(final SafeHtmlBuilder b, final CharSequence in) {
for (int i = 0; i < in.length(); i++) {
b.append(in.charAt(i));
}
}
private static boolean isElementName(final String name) {
return name.matches("^[a-zA-Z][a-zA-Z0-9_-]*$");
}
private static boolean isAttributeName(final String name) {
return isElementName(name);
}
private static boolean isCssName(final String name) {
return isElementName(name);
}
private static abstract class Impl {
abstract void escapeStr(SafeHtmlBuilder b, String in);
}
private static class ServerImpl extends Impl {
@Override
void escapeStr(final SafeHtmlBuilder b, final String in) {
SafeHtmlBuilder.escapeCS(b, in);
}
}
private static class ClientImpl extends Impl {
@Override
void escapeStr(final SafeHtmlBuilder b, final String in) {
b.cb.append(escape(in));
}
private static native String escape(String src)
/*-{ return src.replace(/&/g,'&amp;')
.replace(/>/g,'&gt;')
.replace(/</g,'&lt;')
.replace(/"/g,'&quot;')
.replace(/'/g,'&#39;');
}-*/;
}
}

View File

@ -0,0 +1,22 @@
// Copyright (C) 2009 The Android Open Source Project
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package com.google.gwtexpui.safehtml.client;
import com.google.gwt.resources.client.CssResource;
public interface SafeHtmlCss extends CssResource {
String wikiPreFormat();
String wikiList();
}

View File

@ -0,0 +1,22 @@
// Copyright (C) 2009 The Android Open Source Project
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package com.google.gwtexpui.safehtml.client;
import com.google.gwt.resources.client.ClientBundle;
public interface SafeHtmlResources extends ClientBundle {
@Source("safehtml.css")
SafeHtmlCss css();
}

View File

@ -0,0 +1,28 @@
// Copyright (C) 2009 The Android Open Source Project
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package com.google.gwtexpui.safehtml.client;
class SafeHtmlString extends SafeHtml {
private final String html;
SafeHtmlString(final String h) {
html = h;
}
@Override
public String asString() {
return html;
}
}

View File

@ -0,0 +1,23 @@
/* Copyright (C) 2009 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
.wikiPreFormat {
white-space: pre;
font-family: 'Lucida Console', 'Lucida Sans Typewriter', Monaco, monospace;
font-size: small;
}
.wikiList {
}

View File

@ -0,0 +1,106 @@
// Copyright (C) 2008 The Android Open Source Project
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package com.google.gwtexpui.server;
import java.io.IOException;
import java.util.concurrent.TimeUnit;
import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
/**
* Forces GWT resources to cache for a very long time.
* <p>
* GWT compiled JavaScript and ImageBundles can be cached indefinitely by a
* browser and/or an edge proxy, as they never contain user-specific data and
* are named by a unique checksum. If their content is ever modified then the
* URL changes, so user agents would request a different resource. We force
* these resources to have very long expiration times.
* <p>
* To use, add the following block to your <code>web.xml</code>:
*
* <pre>
* &lt;filter&gt;
* &lt;filter-name&gt;CacheControl&lt;/filter-name&gt;
* &lt;filter-class&gt;com.google.gwtexpui.server.CacheControlFilter&lt;/filter-class&gt;
* &lt;/filter&gt;
* &lt;filter-mapping&gt;
* &lt;filter-name&gt;CacheControl&lt;/filter-name&gt;
* &lt;url-pattern&gt;/*&lt;/url-pattern&gt;
* &lt;/filter-mapping&gt;
* </pre>
*/
public class CacheControlFilter implements Filter {
public void init(final FilterConfig config) {
}
public void destroy() {
}
public void doFilter(final ServletRequest sreq, final ServletResponse srsp,
final FilterChain chain) throws IOException, ServletException {
final HttpServletRequest req = (HttpServletRequest) sreq;
final HttpServletResponse rsp = (HttpServletResponse) srsp;
final String pathInfo = pathInfo(req);
if (cacheForever(pathInfo, req)) {
CacheHeaders.setCacheable(req, rsp, 365, TimeUnit.DAYS);
} else if (nocache(pathInfo)) {
CacheHeaders.setNotCacheable(rsp);
}
chain.doFilter(req, rsp);
}
private static boolean cacheForever(final String pathInfo,
final HttpServletRequest req) {
if (pathInfo.endsWith(".cache.html")) {
return true;
} else if (pathInfo.endsWith(".cache.gif")) {
return true;
} else if (pathInfo.endsWith(".cache.png")) {
return true;
} else if (pathInfo.endsWith(".cache.css")) {
return true;
} else if (pathInfo.endsWith(".cache.jar")) {
return true;
} else if (pathInfo.endsWith(".cache.swf")) {
return true;
} else if (pathInfo.endsWith(".nocache.js")) {
final String v = req.getParameter("content");
return v != null && v.length() > 20;
}
return false;
}
private static boolean nocache(final String pathInfo) {
if (pathInfo.endsWith(".nocache.js")) {
return true;
}
return false;
}
private static String pathInfo(final HttpServletRequest req) {
final String uri = req.getRequestURI();
final String ctx = req.getContextPath();
return uri.startsWith(ctx) ? uri.substring(ctx.length()) : uri;
}
}

View File

@ -0,0 +1,118 @@
// Copyright (C) 2013 The Android Open Source Project
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package com.google.gwtexpui.server;
import static java.util.concurrent.TimeUnit.DAYS;
import static java.util.concurrent.TimeUnit.SECONDS;
import java.util.concurrent.TimeUnit;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
/** Utilities to manage HTTP caching directives in responses. */
public class CacheHeaders {
private static final long MAX_CACHE_DURATION = DAYS.toSeconds(365);
/**
* Do not cache the response, anywhere.
*
* @param res response being returned.
*/
public static void setNotCacheable(HttpServletResponse res) {
String cc = "no-cache, no-store, max-age=0, must-revalidate";
res.setHeader("Cache-Control", cc);
res.setHeader("Pragma", "no-cache");
res.setHeader("Expires", "Fri, 01 Jan 1990 00:00:00 GMT");
res.setDateHeader("Date", System.currentTimeMillis());
}
/**
* Permit caching the response for up to the age specified.
* <p>
* If the request is on a secure connection (e.g. SSL) private caching is
* used. This allows the user-agent to cache the response, but requests
* intermediate proxies to not cache. This may offer better protection for
* Set-Cookie headers.
* <p>
* If the request is on plaintext (insecure), public caching is used. This may
* allow an intermediate proxy to cache the response, including any Set-Cookie
* header that may have also been included.
*
* @param req current request.
* @param res response being returned.
* @param age how long the response can be cached.
* @param unit time unit for age, usually {@link TimeUnit#SECONDS}.
*/
public static void setCacheable(
HttpServletRequest req, HttpServletResponse res,
long age, TimeUnit unit) {
if (req.isSecure()) {
setCacheablePrivate(res, age, unit);
} else {
setCacheablePublic(res, age, unit);
}
}
/**
* Allow the response to be cached by proxies and user-agents.
* <p>
* If the response includes a Set-Cookie header the cookie may be cached by a
* proxy and returned to multiple browsers behind the same proxy. This is
* insecure for authenticated connections.
*
* @param res response being returned.
* @param age how long the response can be cached.
* @param unit time unit for age, usually {@link TimeUnit#SECONDS}.
*/
public static void setCacheablePublic(HttpServletResponse res,
long age, TimeUnit unit) {
long now = System.currentTimeMillis();
long sec = maxAgeSeconds(age, unit);
res.setDateHeader("Expires", now + SECONDS.toMillis(sec));
res.setDateHeader("Date", now);
cache(res, "public", age, unit);
}
/**
* Allow the response to be cached only by the user-agent.
*
* @param res response being returned.
* @param age how long the response can be cached.
* @param unit time unit for age, usually {@link TimeUnit#SECONDS}.
*/
public static void setCacheablePrivate(HttpServletResponse res,
long age, TimeUnit unit) {
long now = System.currentTimeMillis();
res.setDateHeader("Expires", now);
res.setDateHeader("Date", now);
cache(res, "private", age, unit);
}
private static void cache(HttpServletResponse res,
String type, long age, TimeUnit unit) {
res.setHeader("Cache-Control", String.format(
"%s, max-age=%d",
type, maxAgeSeconds(age, unit)));
}
private static long maxAgeSeconds(long age, TimeUnit unit) {
return Math.min(unit.toSeconds(age), MAX_CACHE_DURATION);
}
private CacheHeaders() {
}
}

View File

@ -0,0 +1,27 @@
<!--
Copyright (C) 2009 The Android Open Source Project
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
-->
<module>
<inherits name="com.google.gwt.user.User"/>
<replace-with class="com.google.gwtexpui.user.client.PluginSafeDialogBoxImplAutoHide">
<when-type-is class="com.google.gwtexpui.user.client.PluginSafeDialogBoxImpl" />
<any>
<when-property-is name="user.agent" value="safari"/>
<when-property-is name="user.agent" value="gecko"/>
<when-property-is name="user.agent" value="gecko1_8"/>
</any>
</replace-with>
</module>

View File

@ -0,0 +1,76 @@
// Copyright (C) 2008 The Android Open Source Project
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package com.google.gwtexpui.user.client;
import com.google.gwt.event.logical.shared.ResizeEvent;
import com.google.gwt.event.logical.shared.ResizeHandler;
import com.google.gwt.event.shared.HandlerRegistration;
import com.google.gwt.user.client.Window;
/** A DialogBox that automatically re-centers itself if the window changes */
public class AutoCenterDialogBox extends PluginSafeDialogBox {
private HandlerRegistration recenter;
public AutoCenterDialogBox() {
this(false);
}
public AutoCenterDialogBox(final boolean autoHide) {
this(autoHide, true);
}
public AutoCenterDialogBox(final boolean autoHide, final boolean modal) {
super(autoHide, modal);
}
@Override
public void show() {
if (recenter == null) {
recenter = Window.addResizeHandler(new ResizeHandler() {
@Override
public void onResize(final ResizeEvent event) {
final int w = event.getWidth();
final int h = event.getHeight();
AutoCenterDialogBox.this.onResize(w, h);
}
});
}
super.show();
}
@Override
protected void onUnload() {
if (recenter != null) {
recenter.removeHandler();
recenter = null;
}
super.onUnload();
}
/**
* Invoked when the outer browser window resizes.
* <p>
* Subclasses may override (but should ensure they still call super.onResize)
* to implement custom logic when a window resize occurs.
*
* @param width new browser window width
* @param height new browser window height
*/
protected void onResize(final int width, final int height) {
if (isAttached()) {
center();
}
}
}

View File

@ -0,0 +1,65 @@
// Copyright (C) 2009 The Android Open Source Project
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package com.google.gwtexpui.user.client;
import com.google.gwt.core.client.GWT;
import com.google.gwt.user.client.ui.DialogBox;
/**
* A DialogBox that can appear over Flash movies and Java applets.
* <p>
* Some browsers have issues with placing a &lt;div&gt; (such as that used by
* the DialogBox implementation) over top of native UI such as that used by the
* Flash plugin. Often the native UI leaks over top of the &lt;div&gt;, which is
* not the desired behavior for a dialog box.
* <p>
* This implementation hides the native resources by setting their display
* property to 'none' when the dialog is shown, and restores them back to their
* prior setting when the dialog is hidden.
* */
public class PluginSafeDialogBox extends DialogBox {
private final PluginSafeDialogBoxImpl impl =
GWT.create(PluginSafeDialogBoxImpl.class);
public PluginSafeDialogBox() {
this(false);
}
public PluginSafeDialogBox(final boolean autoHide) {
this(autoHide, true);
}
public PluginSafeDialogBox(final boolean autoHide, final boolean modal) {
super(autoHide, modal);
}
@Override
public void setVisible(final boolean show) {
impl.visible(show);
super.setVisible(show);
}
@Override
public void show() {
impl.visible(true);
super.show();
}
@Override
public void hide(final boolean autoClosed) {
impl.visible(false);
super.hide(autoClosed);
}
}

View File

@ -0,0 +1,20 @@
// Copyright (C) 2009 The Android Open Source Project
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package com.google.gwtexpui.user.client;
class PluginSafeDialogBoxImpl {
void visible(final boolean dialogVisible) {
}
}

View File

@ -0,0 +1,86 @@
// Copyright (C) 2009 The Android Open Source Project
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package com.google.gwtexpui.user.client;
import com.google.gwt.dom.client.Document;
import com.google.gwt.dom.client.Element;
import com.google.gwt.dom.client.NodeList;
import com.google.gwt.user.client.ui.UIObject;
import java.util.ArrayList;
class PluginSafeDialogBoxImplAutoHide extends PluginSafeDialogBoxImpl {
private boolean hidden;
private ArrayList<HiddenElement> hiddenElements =
new ArrayList<HiddenElement>();
@Override
void visible(final boolean dialogVisible) {
if (dialogVisible) {
hideAll();
} else {
showAll();
}
}
private void hideAll() {
if (!hidden) {
hideSet(Document.get().getElementsByTagName("object"));
hideSet(Document.get().getElementsByTagName("embed"));
hideSet(Document.get().getElementsByTagName("applet"));
hidden = true;
}
}
private void hideSet(final NodeList<Element> all) {
for (int i = 0; i < all.getLength(); i++) {
final Element e = all.getItem(i);
if (UIObject.isVisible(e)) {
hiddenElements.add(new HiddenElement(e));
}
}
}
private void showAll() {
if (hidden) {
for (final HiddenElement e : hiddenElements) {
e.restore();
}
hiddenElements.clear();
hidden = false;
}
}
private static class HiddenElement {
private final Element element;
private final String visibility;
HiddenElement(final Element element) {
this.element = element;
this.visibility = getVisibility(element);
setVisibility(element, "hidden");
}
void restore() {
setVisibility(element, visibility);
}
private static native String getVisibility(Element elem)
/*-{ return elem.style.visibility; }-*/;
private static native void setVisibility(Element elem, String disp)
/*-{ elem.style.visibility = disp; }-*/;
}
}

View File

@ -0,0 +1,65 @@
// Copyright (C) 2009 The Android Open Source Project
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package com.google.gwtexpui.user.client;
import com.google.gwt.core.client.GWT;
import com.google.gwt.user.client.ui.PopupPanel;
/**
* A PopupPanel that can appear over Flash movies and Java applets.
* <p>
* Some browsers have issues with placing a &lt;div&gt; (such as that used by
* the PopupPanel implementation) over top of native UI such as that used by the
* Flash plugin. Often the native UI leaks over top of the &lt;div&gt;, which is
* not the desired behavior for a dialog box.
* <p>
* This implementation hides the native resources by setting their display
* property to 'none' when the dialog is shown, and restores them back to their
* prior setting when the dialog is hidden.
* */
public class PluginSafePopupPanel extends PopupPanel {
private final PluginSafeDialogBoxImpl impl =
GWT.create(PluginSafeDialogBoxImpl.class);
public PluginSafePopupPanel() {
this(false);
}
public PluginSafePopupPanel(final boolean autoHide) {
this(autoHide, true);
}
public PluginSafePopupPanel(final boolean autoHide, final boolean modal) {
super(autoHide, modal);
}
@Override
public void setVisible(final boolean show) {
impl.visible(show);
super.setVisible(show);
}
@Override
public void show() {
impl.visible(true);
super.show();
}
@Override
public void hide(final boolean autoClosed) {
impl.visible(false);
super.hide(autoClosed);
}
}

View File

@ -0,0 +1,81 @@
// Copyright (C) 2009 The Android Open Source Project
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package com.google.gwtexpui.user.client;
import com.google.gwt.core.client.GWT;
import com.google.gwt.user.client.Window;
/**
* User agent feature tests we don't create permutations for.
* <p>
* Some features aren't worth creating full permutations in GWT for, as each new
* boolean permutation (only two settings) doubles the compile time required. If
* the setting only affects a couple of lines of JavaScript code, the slightly
* larger cache files for user agents that lack the functionality requested is
* trivial compared to the time developers lose building their application.
*/
public class UserAgent {
/** Does the browser have ShockwaveFlash plugin enabled? */
public static final boolean hasFlash = hasFlash();
private static native boolean hasFlash()
/*-{
if (navigator.plugins && navigator.plugins.length) {
if (navigator.plugins['Shockwave Flash']) return true;
if (navigator.plugins['Shockwave Flash 2.0']) return true;
} else if (navigator.mimeTypes && navigator.mimeTypes.length) {
var mimeType = navigator.mimeTypes['application/x-shockwave-flash'];
if (mimeType && mimeType.enabledPlugin) return true;
} else {
try { new ActiveXObject('ShockwaveFlash.ShockwaveFlash.7'); return true; } catch (e) {}
try { new ActiveXObject('ShockwaveFlash.ShockwaveFlash.6'); return true; } catch (e) {}
try { new ActiveXObject('ShockwaveFlash.ShockwaveFlash'); return true; } catch (e) {}
}
return false;
}-*/;
/**
* Test for and disallow running this application in an &lt;iframe&gt;.
* <p>
* If the application is running within an iframe this method requests a
* browser generated redirect to pop the application out of the iframe into
* the top level window, and then aborts execution by throwing an exception.
* This is call should be placed early within the module's onLoad() method,
* before any real UI can be initialized that an attacking site could try to
* snip out and present in a confusing context.
* <p>
* If the break out works, execution will restart automatically in a proper
* top level window, where the script has full control over the display. If
* the break out fails, execution will abort and stop immediately, preventing
* UI widgets from being created, leaving the user with an empty frame.
*/
public static void assertNotInIFrame() {
if (GWT.isScript() && amInsideIFrame()) {
bustOutOfIFrame(Window.Location.getHref());
throw new RuntimeException();
}
}
private static native boolean amInsideIFrame()
/*-{ return top.location != $wnd.location; }-*/;
private static native void bustOutOfIFrame(String newloc)
/*-{ top.location.href = newloc }-*/;
private UserAgent() {
}
}

View File

@ -0,0 +1,57 @@
// Copyright (C) 2009 The Android Open Source Project
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package com.google.gwtexpui.user.client;
import com.google.gwt.user.client.ui.Composite;
import com.google.gwt.user.client.ui.Widget;
/**
* Widget to display within a {@link ViewSite}.
*<p>
* Implementations must override <code>protected void onLoad()</code> and
* arrange for {@link #display()} to be invoked once the DOM within the view is
* consistent for presentation to the user. Typically this means that the
* subclass can start RPCs within <code>onLoad()</code> and then invoke
* <code>display()</code> from within the AsyncCallback's
* <code>onSuccess(Object)</code> method.
*/
public abstract class View extends Composite {
ViewSite<? extends View> site;
@Override
protected void onUnload() {
site = null;
super.onUnload();
}
/** true if this is the current view of its parent view site */
public final boolean isCurrentView() {
Widget p = getParent();
while (p != null) {
if (p instanceof ViewSite<?>) {
return ((ViewSite<?>) p).getView() == this;
}
p = p.getParent();
}
return false;
}
/** Replace the current view in the parent ViewSite with this view. */
public final void display() {
if (site != null) {
site.swap(this);
}
}
}

View File

@ -0,0 +1,87 @@
// Copyright (C) 2009 The Android Open Source Project
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package com.google.gwtexpui.user.client;
import com.google.gwt.user.client.ui.Composite;
import com.google.gwt.user.client.ui.FlowPanel;
import com.google.gwt.user.client.ui.SimplePanel;
/**
* Hosts a single {@link View}.
* <p>
* View instances are attached inside of an invisible DOM node, permitting their
* <code>onLoad()</code> method to be invoked and to update the DOM prior to the
* elements being made visible in the UI.
* <p>
* Complaint View instances must invoke {@link View#display()} once the DOM is
* ready for presentation.
*/
public class ViewSite<V extends View> extends Composite {
private final FlowPanel main;
private SimplePanel current;
private SimplePanel next;
public ViewSite() {
main = new FlowPanel();
initWidget(main);
}
/** Get the current view; null if there is no view being displayed. */
@SuppressWarnings("unchecked")
public V getView() {
return current != null ? (V) current.getWidget() : null;
}
/**
* Set the next view to display.
* <p>
* The view will be attached to the DOM tree within a hidden container,
* permitting its <code>onLoad()</code> method to execute and update the DOM
* without the user seeing the result.
*
* @param view the next view to display.
*/
public void setView(final V view) {
if (next != null) {
main.remove(next);
}
view.site = this;
next = new SimplePanel();
next.setVisible(false);
main.add(next);
next.add(view);
}
/**
* Invoked after the view becomes the current view and has been made visible.
*
* @param view the view being displayed.
*/
protected void onShowView(final V view) {
}
@SuppressWarnings("unchecked")
final void swap(final View v) {
if (next != null && next.getWidget() == v) {
if (current != null) {
main.remove(current);
}
current = next;
next = null;
current.setVisible(true);
onShowView((V) v);
}
}
}

View File

@ -0,0 +1,77 @@
// Copyright (C) 2013 The Android Open Source Project
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package com.google.gwtexpui.safehtml.client;
import static com.google.gwtexpui.safehtml.client.LinkFindReplace.hasValidScheme;
import junit.framework.TestCase;
public class LinkFindReplaceTest extends TestCase {
public void testNoEscaping() {
String find = "find";
String link = "link";
LinkFindReplace a = new LinkFindReplace(find, link);
assertEquals(find, a.pattern().getSource());
assertEquals("<a href=\"link\">find</a>", a.replace(find));
assertEquals("find = " + find + ", link = " + link, a.toString());
}
public void testBackreference() {
assertEquals("<a href=\"/bug?id=123\">issue 123</a>",
new LinkFindReplace("(bug|issue)\\s*([0-9]+)", "/bug?id=$2")
.replace("issue 123"));
}
public void testHasValidScheme() {
assertTrue(hasValidScheme("/absolute/path"));
assertTrue(hasValidScheme("relative/path"));
assertTrue(hasValidScheme("http://url/"));
assertTrue(hasValidScheme("HTTP://url/"));
assertTrue(hasValidScheme("https://url/"));
assertTrue(hasValidScheme("mailto://url/"));
assertFalse(hasValidScheme("ftp://url/"));
assertFalse(hasValidScheme("data:evil"));
assertFalse(hasValidScheme("javascript:alert(1)"));
}
public void testInvalidSchemeInReplace() {
try {
new LinkFindReplace("find", "javascript:alert(1)").replace("find");
fail("Expected IllegalStateException");
} catch (IllegalArgumentException expected) {
}
}
public void testInvalidSchemeWithBackreference() {
try {
new LinkFindReplace(".*(script:[^;]*)", "java$1")
.replace("Look at this script: alert(1);");
fail("Expected IllegalStateException");
} catch (IllegalArgumentException expected) {
}
}
public void testReplaceEscaping() {
assertEquals("<a href=\"a&quot;&amp;&#39;&lt;&gt;b\">find</a>",
new LinkFindReplace("find", "a\"&'<>b").replace("find"));
}
public void testHtmlInFind() {
String rawFind = "<b>&quot;bold&quot;</b>";
LinkFindReplace a = new LinkFindReplace(rawFind, "/bold");
assertEquals(rawFind, a.pattern().getSource());
assertEquals("<a href=\"/bold\">" + rawFind + "</a>", a.replace(rawFind));
}
}

View File

@ -0,0 +1,28 @@
// Copyright (C) 2009 The Android Open Source Project
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package com.google.gwtexpui.safehtml.client;
import junit.framework.TestCase;
public class RawFindReplaceTest extends TestCase {
public void testFindReplace() {
final String find = "find";
final String replace = "replace";
final RawFindReplace a = new RawFindReplace(find, replace);
assertEquals(find, a.pattern().getSource());
assertEquals(replace, a.replace(find));
assertEquals("find = " + find + ", replace = " + replace, a.toString());
}
}

View File

@ -0,0 +1,265 @@
// Copyright (C) 2009 The Android Open Source Project
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package com.google.gwtexpui.safehtml.client;
import junit.framework.TestCase;
public class SafeHtmlBuilderTest extends TestCase {
public void testEmpty() {
final SafeHtmlBuilder b = new SafeHtmlBuilder();
assertTrue(b.isEmpty());
assertFalse(b.hasContent());
assertEquals("", b.asString());
b.append("a");
assertTrue(b.hasContent());
assertEquals("a", b.asString());
}
public void testToSafeHtml() {
final SafeHtmlBuilder b = new SafeHtmlBuilder();
b.append(1);
final SafeHtml h = b.toSafeHtml();
assertNotNull(h);
assertNotSame(h, b);
assertFalse(h instanceof SafeHtmlBuilder);
assertEquals("1", h.asString());
}
public void testAppend_boolean() {
final SafeHtmlBuilder b = new SafeHtmlBuilder();
assertSame(b, b.append(true));
assertSame(b, b.append(false));
assertEquals("truefalse", b.asString());
}
public void testAppend_char() {
final SafeHtmlBuilder b = new SafeHtmlBuilder();
assertSame(b, b.append('a'));
assertSame(b, b.append('b'));
assertEquals("ab", b.asString());
}
public void testAppend_int() {
final SafeHtmlBuilder b = new SafeHtmlBuilder();
assertSame(b, b.append(4));
assertSame(b, b.append(2));
assertSame(b, b.append(-100));
assertEquals("42-100", b.asString());
}
public void testAppend_long() {
final SafeHtmlBuilder b = new SafeHtmlBuilder();
assertSame(b, b.append(4L));
assertSame(b, b.append(2L));
assertEquals("42", b.asString());
}
public void testAppend_float() {
final SafeHtmlBuilder b = new SafeHtmlBuilder();
assertSame(b, b.append(0.0f));
assertEquals("0.0", b.asString());
}
public void testAppend_double() {
final SafeHtmlBuilder b = new SafeHtmlBuilder();
assertSame(b, b.append(0.0));
assertEquals("0.0", b.asString());
}
public void testAppend_String() {
final SafeHtmlBuilder b = new SafeHtmlBuilder();
assertSame(b, b.append((String) null));
assertEquals("", b.asString());
assertSame(b, b.append("foo"));
assertSame(b, b.append("bar"));
assertEquals("foobar", b.asString());
}
public void testAppend_StringBuilder() {
final SafeHtmlBuilder b = new SafeHtmlBuilder();
assertSame(b, b.append((StringBuilder) null));
assertEquals("", b.asString());
assertSame(b, b.append(new StringBuilder("foo")));
assertSame(b, b.append(new StringBuilder("bar")));
assertEquals("foobar", b.asString());
}
public void testAppend_StringBuffer() {
final SafeHtmlBuilder b = new SafeHtmlBuilder();
assertSame(b, b.append((StringBuffer) null));
assertEquals("", b.asString());
assertSame(b, b.append(new StringBuffer("foo")));
assertSame(b, b.append(new StringBuffer("bar")));
assertEquals("foobar", b.asString());
}
public void testAppend_Object() {
final SafeHtmlBuilder b = new SafeHtmlBuilder();
assertSame(b, b.append((Object) null));
assertEquals("", b.asString());
assertSame(b, b.append(new Object() {
@Override
public String toString() {
return "foobar";
}
}));
assertEquals("foobar", b.asString());
}
public void testAppend_CharSequence() {
final SafeHtmlBuilder b = new SafeHtmlBuilder();
assertSame(b, b.append((CharSequence) null));
assertEquals("", b.asString());
assertSame(b, b.append((CharSequence) "foo"));
assertSame(b, b.append((CharSequence) "bar"));
assertEquals("foobar", b.asString());
}
public void testAppend_SafeHtml() {
final SafeHtmlBuilder b = new SafeHtmlBuilder();
assertSame(b, b.append((SafeHtml) null));
assertEquals("", b.asString());
assertSame(b, b.append(new SafeHtmlString("foo")));
assertSame(b, b.append(new SafeHtmlBuilder().append("bar")));
assertEquals("foobar", b.asString());
}
public void testHtmlSpecialCharacters() {
assertEquals("&amp;", escape("&"));
assertEquals("&lt;", escape("<"));
assertEquals("&gt;", escape(">"));
assertEquals("&quot;", escape("\""));
assertEquals("&#39;", escape("'"));
assertEquals("&amp;", escape('&'));
assertEquals("&lt;", escape('<'));
assertEquals("&gt;", escape('>'));
assertEquals("&quot;", escape('"'));
assertEquals("&#39;", escape('\''));
assertEquals("&lt;b&gt;", escape("<b>"));
assertEquals("&amp;lt;b&amp;gt;", escape("&lt;b&gt;"));
}
public void testEntityNbsp() {
final SafeHtmlBuilder b = new SafeHtmlBuilder();
assertSame(b, b.nbsp());
assertEquals("&nbsp;", b.asString());
}
public void testTagBr() {
final SafeHtmlBuilder b = new SafeHtmlBuilder();
assertSame(b, b.br());
assertEquals("<br />", b.asString());
}
public void testTagTableTrTd() {
final SafeHtmlBuilder b = new SafeHtmlBuilder();
assertSame(b, b.openElement("table"));
assertSame(b, b.openTr());
assertSame(b, b.openTd());
assertSame(b, b.append("d<a>ta"));
assertSame(b, b.closeTd());
assertSame(b, b.closeTr());
assertSame(b, b.closeElement("table"));
assertEquals("<table><tr><td>d&lt;a&gt;ta</td></tr></table>", b.asString());
}
public void testTagDiv() {
final SafeHtmlBuilder b = new SafeHtmlBuilder();
assertSame(b, b.openDiv());
assertSame(b, b.append("d<a>ta"));
assertSame(b, b.closeDiv());
assertEquals("<div>d&lt;a&gt;ta</div>", b.asString());
}
public void testTagAnchor() {
final SafeHtmlBuilder b = new SafeHtmlBuilder();
assertSame(b, b.openAnchor());
assertEquals("", b.getAttribute("href"));
assertSame(b, b.setAttribute("href", "http://here"));
assertEquals("http://here", b.getAttribute("href"));
assertSame(b, b.setAttribute("href", "d<a>ta"));
assertEquals("d<a>ta", b.getAttribute("href"));
assertEquals("", b.getAttribute("target"));
assertSame(b, b.setAttribute("target", null));
assertEquals("", b.getAttribute("target"));
assertSame(b, b.append("go"));
assertSame(b, b.closeAnchor());
assertEquals("<a href=\"d&lt;a&gt;ta\">go</a>", b.asString());
}
public void testTagHeightWidth() {
final SafeHtmlBuilder b = new SafeHtmlBuilder();
assertSame(b, b.openElement("img"));
assertSame(b, b.setHeight(100));
assertSame(b, b.setWidth(42));
assertSame(b, b.closeSelf());
assertEquals("<img height=\"100\" width=\"42\" />", b.asString());
}
public void testStyleName() {
final SafeHtmlBuilder b = new SafeHtmlBuilder();
assertSame(b, b.openSpan());
assertSame(b, b.setStyleName("foo"));
assertSame(b, b.addStyleName("bar"));
assertSame(b, b.append("d<a>ta"));
assertSame(b, b.closeSpan());
assertEquals("<span class=\"foo bar\">d&lt;a&gt;ta</span>", b.asString());
}
public void testRejectJavaScript_AnchorHref() {
final String href = "javascript:window.close();";
try {
new SafeHtmlBuilder().openAnchor().setAttribute("href", href);
fail("accepted javascript in a href");
} catch (RuntimeException e) {
assertEquals("javascript unsafe in href: " + href, e.getMessage());
}
}
public void testRejectJavaScript_ImgSrc() {
final String href = "javascript:window.close();";
try {
new SafeHtmlBuilder().openElement("img").setAttribute("src", href);
fail("accepted javascript in img src");
} catch (RuntimeException e) {
assertEquals("javascript unsafe in href: " + href, e.getMessage());
}
}
public void testRejectJavaScript_FormAction() {
final String href = "javascript:window.close();";
try {
new SafeHtmlBuilder().openElement("form").setAttribute("action", href);
fail("accepted javascript in form action");
} catch (RuntimeException e) {
assertEquals("javascript unsafe in href: " + href, e.getMessage());
}
}
private static String escape(final char c) {
return new SafeHtmlBuilder().append(c).asString();
}
private static String escape(final String c) {
return new SafeHtmlBuilder().append(c).asString();
}
}

View File

@ -0,0 +1,58 @@
// Copyright (C) 2009 The Android Open Source Project
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package com.google.gwtexpui.safehtml.client;
import junit.framework.TestCase;
public class SafeHtml_LinkifyTest extends TestCase {
public void testLinkify_SimpleHttp1() {
final SafeHtml o = html("A http://go.here/ B");
final SafeHtml n = o.linkify();
assertNotSame(o, n);
assertEquals("A <a href=\"http://go.here/\" target=\"_blank\">http://go.here/</a> B", n.asString());
}
public void testLinkify_SimpleHttps2() {
final SafeHtml o = html("A https://go.here/ B");
final SafeHtml n = o.linkify();
assertNotSame(o, n);
assertEquals("A <a href=\"https://go.here/\" target=\"_blank\">https://go.here/</a> B", n.asString());
}
public void testLinkify_Parens1() {
final SafeHtml o = html("A (http://go.here/) B");
final SafeHtml n = o.linkify();
assertNotSame(o, n);
assertEquals("A (<a href=\"http://go.here/\" target=\"_blank\">http://go.here/</a>) B", n.asString());
}
public void testLinkify_Parens() {
final SafeHtml o = html("A http://go.here/#m() B");
final SafeHtml n = o.linkify();
assertNotSame(o, n);
assertEquals("A <a href=\"http://go.here/#m()\" target=\"_blank\">http://go.here/#m()</a> B", n.asString());
}
public void testLinkify_AngleBrackets1() {
final SafeHtml o = html("A <http://go.here/> B");
final SafeHtml n = o.linkify();
assertNotSame(o, n);
assertEquals("A &lt;<a href=\"http://go.here/\" target=\"_blank\">http://go.here/</a>&gt; B", n.asString());
}
private static SafeHtml html(String text) {
return new SafeHtmlBuilder().append(text).toSafeHtml();
}
}

View File

@ -0,0 +1,119 @@
// Copyright (C) 2009 The Android Open Source Project
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package com.google.gwtexpui.safehtml.client;
import junit.framework.TestCase;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
public class SafeHtml_ReplaceTest extends TestCase {
public void testReplaceEmpty() {
SafeHtml o = html("A\nissue42\nB");
assertSame(o, o.replaceAll(null));
assertSame(o, o.replaceAll(Collections.<FindReplace> emptyList()));
}
public void testReplaceOneLink() {
SafeHtml o = html("A\nissue 42\nB");
SafeHtml n = o.replaceAll(repls(
new RawFindReplace("(issue\\s(\\d+))", "<a href=\"?$2\">$1</a>")));
assertNotSame(o, n);
assertEquals("A\n<a href=\"?42\">issue 42</a>\nB", n.asString());
}
public void testReplaceNoLeadingOrTrailingText() {
SafeHtml o = html("issue 42");
SafeHtml n = o.replaceAll(repls(
new RawFindReplace("(issue\\s(\\d+))", "<a href=\"?$2\">$1</a>")));
assertNotSame(o, n);
assertEquals("<a href=\"?42\">issue 42</a>", n.asString());
}
public void testReplaceTwoLinks() {
SafeHtml o = html("A\nissue 42\nissue 9918\nB");
SafeHtml n = o.replaceAll(repls(
new RawFindReplace("(issue\\s(\\d+))", "<a href=\"?$2\">$1</a>")));
assertNotSame(o, n);
assertEquals("A\n"
+ "<a href=\"?42\">issue 42</a>\n"
+ "<a href=\"?9918\">issue 9918</a>\n"
+ "B"
, n.asString());
}
public void testReplaceInOrder() {
SafeHtml o = html("A\nissue 42\nReally GWTEXPUI-9918 is better\nB");
SafeHtml n = o.replaceAll(repls(
new RawFindReplace("(GWTEXPUI-(\\d+))",
"<a href=\"gwtexpui-bug?$2\">$1</a>"),
new RawFindReplace("(issue\\s+(\\d+))",
"<a href=\"generic-bug?$2\">$1</a>")));
assertNotSame(o, n);
assertEquals("A\n"
+ "<a href=\"generic-bug?42\">issue 42</a>\n"
+ "Really <a href=\"gwtexpui-bug?9918\">GWTEXPUI-9918</a> is better\n"
+ "B"
, n.asString());
}
public void testReplaceOverlappingAfterFirstChar() {
SafeHtml o = html("abcd");
RawFindReplace ab = new RawFindReplace("ab", "AB");
RawFindReplace bc = new RawFindReplace("bc", "23");
RawFindReplace cd = new RawFindReplace("cd", "YZ");
assertEquals("ABcd", o.replaceAll(repls(ab, bc)).asString());
assertEquals("ABcd", o.replaceAll(repls(bc, ab)).asString());
assertEquals("ABYZ", o.replaceAll(repls(ab, bc, cd)).asString());
}
public void testReplaceOverlappingAtFirstCharLongestMatch() {
SafeHtml o = html("abcd");
RawFindReplace ab = new RawFindReplace("ab", "AB");
RawFindReplace abc = new RawFindReplace("[^d][^d][^d]", "234");
assertEquals("ABcd", o.replaceAll(repls(ab, abc)).asString());
assertEquals("234d", o.replaceAll(repls(abc, ab)).asString());
}
public void testReplaceOverlappingAtFirstCharFirstMatch() {
SafeHtml o = html("abcd");
RawFindReplace ab1 = new RawFindReplace("ab", "AB");
RawFindReplace ab2 = new RawFindReplace("[^cd][^cd]", "12");
assertEquals("ABcd", o.replaceAll(repls(ab1, ab2)).asString());
assertEquals("12cd", o.replaceAll(repls(ab2, ab1)).asString());
}
public void testFailedSanitization() {
SafeHtml o = html("abcd");
LinkFindReplace evil = new LinkFindReplace("(b)", "javascript:alert('$1')");
LinkFindReplace ok = new LinkFindReplace("(b)", "/$1");
assertEquals("abcd", o.replaceAll(repls(evil)).asString());
String linked = "a<a href=\"/b\">b</a>cd";
assertEquals(linked, o.replaceAll(repls(ok)).asString());
assertEquals(linked, o.replaceAll(repls(evil, ok)).asString());
}
private static SafeHtml html(String text) {
return new SafeHtmlBuilder().append(text).toSafeHtml();
}
private static List<FindReplace> repls(FindReplace... repls) {
return Arrays.asList(repls);
}
}

View File

@ -0,0 +1,133 @@
// Copyright (C) 2009 The Android Open Source Project
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "<p>AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package com.google.gwtexpui.safehtml.client;
import junit.framework.TestCase;
public class SafeHtml_WikifyListTest extends TestCase {
private static final String BEGIN_LIST = "<ul class=\"wikiList\">";
private static final String END_LIST = "</ul>";
private static String item(String raw) {
return "<li>" + raw + "</li>";
}
public void testBulletList1() {
final SafeHtml o = html("A\n\n* line 1\n* 2nd line");
final SafeHtml n = o.wikify();
assertNotSame(o, n);
assertEquals("<p>A</p>"//
+ BEGIN_LIST //
+ item("line 1") //
+ item("2nd line") //
+ END_LIST //
, n.asString());
}
public void testBulletList2() {
final SafeHtml o = html("A\n\n* line 1\n* 2nd line\n\nB");
final SafeHtml n = o.wikify();
assertNotSame(o, n);
assertEquals("<p>A</p>"//
+ BEGIN_LIST //
+ item("line 1") //
+ item("2nd line") //
+ END_LIST //
+ "<p>B</p>" //
, n.asString());
}
public void testBulletList3() {
final SafeHtml o = html("* line 1\n* 2nd line\n\nB");
final SafeHtml n = o.wikify();
assertNotSame(o, n);
assertEquals(BEGIN_LIST //
+ item("line 1") //
+ item("2nd line") //
+ END_LIST //
+ "<p>B</p>" //
, n.asString());
}
public void testBulletList4() {
final SafeHtml o = html("To see this bug, you have to:\n" //
+ "* Be on IMAP or EAS (not on POP)\n"//
+ "* Be very unlucky\n");
final SafeHtml n = o.wikify();
assertNotSame(o, n);
assertEquals("<p>To see this bug, you have to:</p>" //
+ BEGIN_LIST //
+ item("Be on IMAP or EAS (not on POP)") //
+ item("Be very unlucky") //
+ END_LIST //
, n.asString());
}
public void testBulletList5() {
final SafeHtml o = html("To see this bug,\n" //
+ "you have to:\n" //
+ "* Be on IMAP or EAS (not on POP)\n"//
+ "* Be very unlucky\n");
final SafeHtml n = o.wikify();
assertNotSame(o, n);
assertEquals("<p>To see this bug, you have to:</p>" //
+ BEGIN_LIST //
+ item("Be on IMAP or EAS (not on POP)") //
+ item("Be very unlucky") //
+ END_LIST //
, n.asString());
}
public void testDashList1() {
final SafeHtml o = html("A\n\n- line 1\n- 2nd line");
final SafeHtml n = o.wikify();
assertNotSame(o, n);
assertEquals("<p>A</p>"//
+ BEGIN_LIST //
+ item("line 1") //
+ item("2nd line") //
+ END_LIST //
, n.asString());
}
public void testDashList2() {
final SafeHtml o = html("A\n\n- line 1\n- 2nd line\n\nB");
final SafeHtml n = o.wikify();
assertNotSame(o, n);
assertEquals("<p>A</p>"//
+ BEGIN_LIST //
+ item("line 1") //
+ item("2nd line") //
+ END_LIST //
+ "<p>B</p>" //
, n.asString());
}
public void testDashList3() {
final SafeHtml o = html("- line 1\n- 2nd line\n\nB");
final SafeHtml n = o.wikify();
assertNotSame(o, n);
assertEquals(BEGIN_LIST //
+ item("line 1") //
+ item("2nd line") //
+ END_LIST //
+ "<p>B</p>" //
, n.asString());
}
private static SafeHtml html(String text) {
return new SafeHtmlBuilder().append(text).toSafeHtml();
}
}

View File

@ -0,0 +1,82 @@
// Copyright (C) 2009 The Android Open Source Project
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "<p>AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package com.google.gwtexpui.safehtml.client;
import junit.framework.TestCase;
public class SafeHtml_WikifyPreformatTest extends TestCase {
private static final String B = "<span class=\"wikiPreFormat\">";
private static final String E = "</span><br />";
private static String pre(String raw) {
return B + raw + E;
}
public void testPreformat1() {
final SafeHtml o = html("A\n\n This is pre\n formatted");
final SafeHtml n = o.wikify();
assertNotSame(o, n);
assertEquals("<p>A</p>"//
+ "<p>" //
+ pre(" This is pre") //
+ pre(" formatted") //
+ "</p>" //
, n.asString());
}
public void testPreformat2() {
final SafeHtml o = html("A\n\n This is pre\n formatted\n\nbut this is not");
final SafeHtml n = o.wikify();
assertNotSame(o, n);
assertEquals("<p>A</p>" //
+ "<p>" //
+ pre(" This is pre") //
+ pre(" formatted") //
+ "</p>" //
+ "<p>but this is not</p>" //
, n.asString());
}
public void testPreformat3() {
final SafeHtml o = html("A\n\n Q\n <R>\n S\n\nB");
final SafeHtml n = o.wikify();
assertNotSame(o, n);
assertEquals("<p>A</p>" //
+ "<p>" //
+ pre(" Q") //
+ pre(" &lt;R&gt;") //
+ pre(" S") //
+ "</p>" //
+ "<p>B</p>" //
, n.asString());
}
public void testPreformat4() {
final SafeHtml o = html(" Q\n <R>\n S\n\nB");
final SafeHtml n = o.wikify();
assertNotSame(o, n);
assertEquals("<p>" //
+ pre(" Q") //
+ pre(" &lt;R&gt;") //
+ pre(" S") //
+ "</p>" //
+ "<p>B</p>" //
, n.asString());
}
private static SafeHtml html(String text) {
return new SafeHtmlBuilder().append(text).toSafeHtml();
}
}

View File

@ -0,0 +1,93 @@
// Copyright (C) 2009 The Android Open Source Project
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "<p>AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package com.google.gwtexpui.safehtml.client;
import junit.framework.TestCase;
public class SafeHtml_WikifyTest extends TestCase {
public void testWikify_OneLine1() {
final SafeHtml o = html("A B");
final SafeHtml n = o.wikify();
assertNotSame(o, n);
assertEquals("<p>A B</p>", n.asString());
}
public void testWikify_OneLine2() {
final SafeHtml o = html("A B\n");
final SafeHtml n = o.wikify();
assertNotSame(o, n);
assertEquals("<p>A B\n</p>", n.asString());
}
public void testWikify_OneParagraph1() {
final SafeHtml o = html("A\nB");
final SafeHtml n = o.wikify();
assertNotSame(o, n);
assertEquals("<p>A\nB</p>", n.asString());
}
public void testWikify_OneParagraph2() {
final SafeHtml o = html("A\nB\n");
final SafeHtml n = o.wikify();
assertNotSame(o, n);
assertEquals("<p>A\nB\n</p>", n.asString());
}
public void testWikify_TwoParagraphs() {
final SafeHtml o = html("A\nB\n\nC\nD");
final SafeHtml n = o.wikify();
assertNotSame(o, n);
assertEquals("<p>A\nB</p><p>C\nD</p>", n.asString());
}
public void testLinkify_SimpleHttp1() {
final SafeHtml o = html("A http://go.here/ B");
final SafeHtml n = o.wikify();
assertNotSame(o, n);
assertEquals("<p>A <a href=\"http://go.here/\" target=\"_blank\">http://go.here/</a> B</p>", n.asString());
}
public void testLinkify_SimpleHttps2() {
final SafeHtml o = html("A https://go.here/ B");
final SafeHtml n = o.wikify();
assertNotSame(o, n);
assertEquals("<p>A <a href=\"https://go.here/\" target=\"_blank\">https://go.here/</a> B</p>", n.asString());
}
public void testLinkify_Parens1() {
final SafeHtml o = html("A (http://go.here/) B");
final SafeHtml n = o.wikify();
assertNotSame(o, n);
assertEquals("<p>A (<a href=\"http://go.here/\" target=\"_blank\">http://go.here/</a>) B</p>", n.asString());
}
public void testLinkify_Parens() {
final SafeHtml o = html("A http://go.here/#m() B");
final SafeHtml n = o.wikify();
assertNotSame(o, n);
assertEquals("<p>A <a href=\"http://go.here/#m()\" target=\"_blank\">http://go.here/#m()</a> B</p>", n.asString());
}
public void testLinkify_AngleBrackets1() {
final SafeHtml o = html("A <http://go.here/> B");
final SafeHtml n = o.wikify();
assertNotSame(o, n);
assertEquals("<p>A &lt;<a href=\"http://go.here/\" target=\"_blank\">http://go.here/</a>&gt; B</p>", n.asString());
}
private static SafeHtml html(String text) {
return new SafeHtmlBuilder().append(text).toSafeHtml();
}
}