diff --git a/tycho-its/projects/api-tools/missing-bin/.mvn/extensions.xml b/tycho-its/projects/api-tools/missing-bin/.mvn/extensions.xml new file mode 100644 index 0000000000..79a6c51e8d --- /dev/null +++ b/tycho-its/projects/api-tools/missing-bin/.mvn/extensions.xml @@ -0,0 +1,7 @@ + + + org.eclipse.tycho + tycho-build + ${tycho-version} + + diff --git a/tycho-its/projects/api-tools/missing-bin/.mvn/maven.config b/tycho-its/projects/api-tools/missing-bin/.mvn/maven.config new file mode 100644 index 0000000000..babb6c469f --- /dev/null +++ b/tycho-its/projects/api-tools/missing-bin/.mvn/maven.config @@ -0,0 +1 @@ +-Dtycho-version=5.0.0-SNAPSHOT diff --git a/tycho-its/projects/api-tools/missing-bin/org.eclipse.equinox.p2.ui/.classpath b/tycho-its/projects/api-tools/missing-bin/org.eclipse.equinox.p2.ui/.classpath new file mode 100644 index 0000000000..81fe078c20 --- /dev/null +++ b/tycho-its/projects/api-tools/missing-bin/org.eclipse.equinox.p2.ui/.classpath @@ -0,0 +1,7 @@ + + + + + + + diff --git a/tycho-its/projects/api-tools/missing-bin/org.eclipse.equinox.p2.ui/.project b/tycho-its/projects/api-tools/missing-bin/org.eclipse.equinox.p2.ui/.project new file mode 100644 index 0000000000..1b62af1af1 --- /dev/null +++ b/tycho-its/projects/api-tools/missing-bin/org.eclipse.equinox.p2.ui/.project @@ -0,0 +1,39 @@ + + + org.eclipse.equinox.p2.ui + + + + + + org.eclipse.jdt.core.javabuilder + + + + + org.eclipse.pde.ManifestBuilder + + + + + org.eclipse.pde.SchemaBuilder + + + + + org.eclipse.pde.api.tools.apiAnalysisBuilder + + + + + org.eclipse.pde.ds.core.builder + + + + + + org.eclipse.pde.PluginNature + org.eclipse.jdt.core.javanature + org.eclipse.pde.api.tools.apiAnalysisNature + + diff --git a/tycho-its/projects/api-tools/missing-bin/org.eclipse.equinox.p2.ui/.settings/org.eclipse.jdt.core.prefs b/tycho-its/projects/api-tools/missing-bin/org.eclipse.equinox.p2.ui/.settings/org.eclipse.jdt.core.prefs new file mode 100644 index 0000000000..81c29d4466 --- /dev/null +++ b/tycho-its/projects/api-tools/missing-bin/org.eclipse.equinox.p2.ui/.settings/org.eclipse.jdt.core.prefs @@ -0,0 +1,488 @@ +eclipse.preferences.version=1 +org.eclipse.jdt.core.builder.cleanOutputFolder=clean +org.eclipse.jdt.core.builder.duplicateResourceTask=warning +org.eclipse.jdt.core.builder.invalidClasspath=abort +org.eclipse.jdt.core.builder.resourceCopyExclusionFilter=*.launch +org.eclipse.jdt.core.circularClasspath=error +org.eclipse.jdt.core.classpath.exclusionPatterns=enabled +org.eclipse.jdt.core.classpath.multipleOutputLocations=enabled +org.eclipse.jdt.core.compiler.annotation.inheritNullAnnotations=disabled +org.eclipse.jdt.core.compiler.annotation.missingNonNullByDefaultAnnotation=ignore +org.eclipse.jdt.core.compiler.annotation.nonnull=org.eclipse.jdt.annotation.NonNull +org.eclipse.jdt.core.compiler.annotation.nonnull.secondary= +org.eclipse.jdt.core.compiler.annotation.nonnullbydefault=org.eclipse.jdt.annotation.NonNullByDefault +org.eclipse.jdt.core.compiler.annotation.nonnullbydefault.secondary= +org.eclipse.jdt.core.compiler.annotation.nullable=org.eclipse.jdt.annotation.Nullable +org.eclipse.jdt.core.compiler.annotation.nullable.secondary= +org.eclipse.jdt.core.compiler.annotation.nullanalysis=disabled +org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled +org.eclipse.jdt.core.compiler.codegen.methodParameters=do not generate +org.eclipse.jdt.core.compiler.codegen.targetPlatform=17 +org.eclipse.jdt.core.compiler.codegen.unusedLocal=preserve +org.eclipse.jdt.core.compiler.compliance=17 +org.eclipse.jdt.core.compiler.debug.lineNumber=generate +org.eclipse.jdt.core.compiler.debug.localVariable=generate +org.eclipse.jdt.core.compiler.debug.sourceFile=generate +org.eclipse.jdt.core.compiler.doc.comment.support=enabled +org.eclipse.jdt.core.compiler.maxProblemPerUnit=1000 +org.eclipse.jdt.core.compiler.problem.annotationSuperInterface=warning +org.eclipse.jdt.core.compiler.problem.assertIdentifier=error +org.eclipse.jdt.core.compiler.problem.autoboxing=ignore +org.eclipse.jdt.core.compiler.problem.comparingIdentical=error +org.eclipse.jdt.core.compiler.problem.deadCode=warning +org.eclipse.jdt.core.compiler.problem.deprecation=warning +org.eclipse.jdt.core.compiler.problem.deprecationInDeprecatedCode=disabled +org.eclipse.jdt.core.compiler.problem.deprecationWhenOverridingDeprecatedMethod=enabled +org.eclipse.jdt.core.compiler.problem.discouragedReference=error +org.eclipse.jdt.core.compiler.problem.emptyStatement=warning +org.eclipse.jdt.core.compiler.problem.enablePreviewFeatures=disabled +org.eclipse.jdt.core.compiler.problem.enumIdentifier=error +org.eclipse.jdt.core.compiler.problem.explicitlyClosedAutoCloseable=ignore +org.eclipse.jdt.core.compiler.problem.fallthroughCase=ignore +org.eclipse.jdt.core.compiler.problem.fatalOptionalError=disabled +org.eclipse.jdt.core.compiler.problem.fieldHiding=warning +org.eclipse.jdt.core.compiler.problem.finalParameterBound=ignore +org.eclipse.jdt.core.compiler.problem.finallyBlockNotCompletingNormally=warning +org.eclipse.jdt.core.compiler.problem.forbiddenReference=error +org.eclipse.jdt.core.compiler.problem.hiddenCatchBlock=warning +org.eclipse.jdt.core.compiler.problem.includeNullInfoFromAsserts=disabled +org.eclipse.jdt.core.compiler.problem.incompatibleNonInheritedInterfaceMethod=warning +org.eclipse.jdt.core.compiler.problem.incompleteEnumSwitch=ignore +org.eclipse.jdt.core.compiler.problem.indirectStaticAccess=warning +org.eclipse.jdt.core.compiler.problem.invalidJavadoc=error +org.eclipse.jdt.core.compiler.problem.invalidJavadocTagsVisibility=private +org.eclipse.jdt.core.compiler.problem.localVariableHiding=warning +org.eclipse.jdt.core.compiler.problem.methodWithConstructorName=warning +org.eclipse.jdt.core.compiler.problem.missingDefaultCase=ignore +org.eclipse.jdt.core.compiler.problem.missingDeprecatedAnnotation=ignore +org.eclipse.jdt.core.compiler.problem.missingEnumCaseDespiteDefault=disabled +org.eclipse.jdt.core.compiler.problem.missingHashCodeMethod=warning +org.eclipse.jdt.core.compiler.problem.missingJavadocComments=ignore +org.eclipse.jdt.core.compiler.problem.missingJavadocCommentsOverriding=enabled +org.eclipse.jdt.core.compiler.problem.missingJavadocCommentsVisibility=public +org.eclipse.jdt.core.compiler.problem.missingJavadocTags=ignore +org.eclipse.jdt.core.compiler.problem.missingJavadocTagsOverriding=enabled +org.eclipse.jdt.core.compiler.problem.missingJavadocTagsVisibility=public +org.eclipse.jdt.core.compiler.problem.missingOverrideAnnotation=ignore +org.eclipse.jdt.core.compiler.problem.missingOverrideAnnotationForInterfaceMethodImplementation=enabled +org.eclipse.jdt.core.compiler.problem.missingSerialVersion=warning +org.eclipse.jdt.core.compiler.problem.missingSynchronizedOnInheritedMethod=ignore +org.eclipse.jdt.core.compiler.problem.noEffectAssignment=warning +org.eclipse.jdt.core.compiler.problem.noImplicitStringConversion=warning +org.eclipse.jdt.core.compiler.problem.nonExternalizedStringLiteral=warning +org.eclipse.jdt.core.compiler.problem.nonnullParameterAnnotationDropped=warning +org.eclipse.jdt.core.compiler.problem.nonnullTypeVariableFromLegacyInvocation=warning +org.eclipse.jdt.core.compiler.problem.nullAnnotationInferenceConflict=error +org.eclipse.jdt.core.compiler.problem.nullReference=warning +org.eclipse.jdt.core.compiler.problem.nullSpecViolation=error +org.eclipse.jdt.core.compiler.problem.nullUncheckedConversion=warning +org.eclipse.jdt.core.compiler.problem.overridingPackageDefaultMethod=warning +org.eclipse.jdt.core.compiler.problem.parameterAssignment=ignore +org.eclipse.jdt.core.compiler.problem.pessimisticNullAnalysisForFreeTypeVariables=warning +org.eclipse.jdt.core.compiler.problem.possibleAccidentalBooleanAssignment=warning +org.eclipse.jdt.core.compiler.problem.potentialNullReference=ignore +org.eclipse.jdt.core.compiler.problem.potentiallyUnclosedCloseable=warning +org.eclipse.jdt.core.compiler.problem.rawTypeReference=warning +org.eclipse.jdt.core.compiler.problem.redundantNullAnnotation=warning +org.eclipse.jdt.core.compiler.problem.redundantNullCheck=ignore +org.eclipse.jdt.core.compiler.problem.redundantSpecificationOfTypeArguments=error +org.eclipse.jdt.core.compiler.problem.redundantSuperinterface=ignore +org.eclipse.jdt.core.compiler.problem.reportMethodCanBePotentiallyStatic=ignore +org.eclipse.jdt.core.compiler.problem.reportMethodCanBeStatic=ignore +org.eclipse.jdt.core.compiler.problem.reportPreviewFeatures=warning +org.eclipse.jdt.core.compiler.problem.specialParameterHidingField=disabled +org.eclipse.jdt.core.compiler.problem.staticAccessReceiver=warning +org.eclipse.jdt.core.compiler.problem.suppressOptionalErrors=disabled +org.eclipse.jdt.core.compiler.problem.suppressWarnings=enabled +org.eclipse.jdt.core.compiler.problem.syntacticNullAnalysisForFields=disabled +org.eclipse.jdt.core.compiler.problem.syntheticAccessEmulation=warning +org.eclipse.jdt.core.compiler.problem.typeParameterHiding=warning +org.eclipse.jdt.core.compiler.problem.unavoidableGenericTypeProblems=enabled +org.eclipse.jdt.core.compiler.problem.uncheckedTypeOperation=warning +org.eclipse.jdt.core.compiler.problem.unclosedCloseable=warning +org.eclipse.jdt.core.compiler.problem.undocumentedEmptyBlock=warning +org.eclipse.jdt.core.compiler.problem.unhandledWarningToken=warning +org.eclipse.jdt.core.compiler.problem.unlikelyCollectionMethodArgumentType=warning +org.eclipse.jdt.core.compiler.problem.unlikelyCollectionMethodArgumentTypeStrict=disabled +org.eclipse.jdt.core.compiler.problem.unlikelyEqualsArgumentType=info +org.eclipse.jdt.core.compiler.problem.unnecessaryElse=warning +org.eclipse.jdt.core.compiler.problem.unnecessaryTypeCheck=warning +org.eclipse.jdt.core.compiler.problem.unqualifiedFieldAccess=ignore +org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownException=warning +org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownExceptionExemptExceptionAndThrowable=enabled +org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownExceptionIncludeDocCommentReference=enabled +org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownExceptionWhenOverriding=enabled +org.eclipse.jdt.core.compiler.problem.unusedExceptionParameter=ignore +org.eclipse.jdt.core.compiler.problem.unusedImport=error +org.eclipse.jdt.core.compiler.problem.unusedLabel=warning +org.eclipse.jdt.core.compiler.problem.unusedLocal=warning +org.eclipse.jdt.core.compiler.problem.unusedObjectAllocation=ignore +org.eclipse.jdt.core.compiler.problem.unusedParameter=ignore +org.eclipse.jdt.core.compiler.problem.unusedParameterIncludeDocCommentReference=enabled +org.eclipse.jdt.core.compiler.problem.unusedParameterWhenImplementingAbstract=enabled +org.eclipse.jdt.core.compiler.problem.unusedParameterWhenOverridingConcrete=enabled +org.eclipse.jdt.core.compiler.problem.unusedPrivateMember=error +org.eclipse.jdt.core.compiler.problem.unusedTypeParameter=ignore +org.eclipse.jdt.core.compiler.problem.unusedWarningToken=warning +org.eclipse.jdt.core.compiler.problem.varargsArgumentNeedCast=warning +org.eclipse.jdt.core.compiler.release=enabled +org.eclipse.jdt.core.compiler.source=17 +org.eclipse.jdt.core.formatter.align_assignment_statements_on_columns=false +org.eclipse.jdt.core.formatter.align_fields_grouping_blank_lines=2147483647 +org.eclipse.jdt.core.formatter.align_type_members_on_columns=false +org.eclipse.jdt.core.formatter.align_variable_declarations_on_columns=false +org.eclipse.jdt.core.formatter.align_with_spaces=false +org.eclipse.jdt.core.formatter.alignment_for_additive_operator=16 +org.eclipse.jdt.core.formatter.alignment_for_arguments_in_allocation_expression=16 +org.eclipse.jdt.core.formatter.alignment_for_arguments_in_annotation=0 +org.eclipse.jdt.core.formatter.alignment_for_arguments_in_enum_constant=16 +org.eclipse.jdt.core.formatter.alignment_for_arguments_in_explicit_constructor_call=16 +org.eclipse.jdt.core.formatter.alignment_for_arguments_in_method_invocation=16 +org.eclipse.jdt.core.formatter.alignment_for_arguments_in_qualified_allocation_expression=16 +org.eclipse.jdt.core.formatter.alignment_for_assignment=0 +org.eclipse.jdt.core.formatter.alignment_for_bitwise_operator=16 +org.eclipse.jdt.core.formatter.alignment_for_compact_if=16 +org.eclipse.jdt.core.formatter.alignment_for_compact_loops=16 +org.eclipse.jdt.core.formatter.alignment_for_conditional_expression=80 +org.eclipse.jdt.core.formatter.alignment_for_conditional_expression_chain=0 +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_expressions_in_for_loop_header=0 +org.eclipse.jdt.core.formatter.alignment_for_logical_operator=16 +org.eclipse.jdt.core.formatter.alignment_for_method_declaration=0 +org.eclipse.jdt.core.formatter.alignment_for_module_statements=16 +org.eclipse.jdt.core.formatter.alignment_for_multiple_fields=16 +org.eclipse.jdt.core.formatter.alignment_for_multiplicative_operator=16 +org.eclipse.jdt.core.formatter.alignment_for_parameterized_type_references=0 +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_relational_operator=0 +org.eclipse.jdt.core.formatter.alignment_for_resources_in_try=80 +org.eclipse.jdt.core.formatter.alignment_for_selector_in_method_invocation=16 +org.eclipse.jdt.core.formatter.alignment_for_shift_operator=0 +org.eclipse.jdt.core.formatter.alignment_for_string_concatenation=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.alignment_for_type_arguments=0 +org.eclipse.jdt.core.formatter.alignment_for_type_parameters=0 +org.eclipse.jdt.core.formatter.alignment_for_union_type_in_multicatch=16 +org.eclipse.jdt.core.formatter.blank_lines_after_imports=1 +org.eclipse.jdt.core.formatter.blank_lines_after_package=1 +org.eclipse.jdt.core.formatter.blank_lines_before_field=0 +org.eclipse.jdt.core.formatter.blank_lines_before_first_class_body_declaration=0 +org.eclipse.jdt.core.formatter.blank_lines_before_imports=1 +org.eclipse.jdt.core.formatter.blank_lines_before_member_type=1 +org.eclipse.jdt.core.formatter.blank_lines_before_method=1 +org.eclipse.jdt.core.formatter.blank_lines_before_new_chunk=1 +org.eclipse.jdt.core.formatter.blank_lines_before_package=0 +org.eclipse.jdt.core.formatter.blank_lines_between_import_groups=1 +org.eclipse.jdt.core.formatter.blank_lines_between_type_declarations=1 +org.eclipse.jdt.core.formatter.brace_position_for_annotation_type_declaration=end_of_line +org.eclipse.jdt.core.formatter.brace_position_for_anonymous_type_declaration=end_of_line +org.eclipse.jdt.core.formatter.brace_position_for_array_initializer=end_of_line +org.eclipse.jdt.core.formatter.brace_position_for_block=end_of_line +org.eclipse.jdt.core.formatter.brace_position_for_block_in_case=end_of_line +org.eclipse.jdt.core.formatter.brace_position_for_constructor_declaration=end_of_line +org.eclipse.jdt.core.formatter.brace_position_for_enum_constant=end_of_line +org.eclipse.jdt.core.formatter.brace_position_for_enum_declaration=end_of_line +org.eclipse.jdt.core.formatter.brace_position_for_lambda_body=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.align_tags_descriptions_grouped=true +org.eclipse.jdt.core.formatter.comment.align_tags_names_descriptions=false +org.eclipse.jdt.core.formatter.comment.clear_blank_lines_in_block_comment=false +org.eclipse.jdt.core.formatter.comment.clear_blank_lines_in_javadoc_comment=false +org.eclipse.jdt.core.formatter.comment.count_line_length_from_starting_position=true +org.eclipse.jdt.core.formatter.comment.format_block_comments=true +org.eclipse.jdt.core.formatter.comment.format_header=false +org.eclipse.jdt.core.formatter.comment.format_html=true +org.eclipse.jdt.core.formatter.comment.format_javadoc_comments=true +org.eclipse.jdt.core.formatter.comment.format_line_comments=true +org.eclipse.jdt.core.formatter.comment.format_source_code=true +org.eclipse.jdt.core.formatter.comment.indent_parameter_description=false +org.eclipse.jdt.core.formatter.comment.indent_root_tags=false +org.eclipse.jdt.core.formatter.comment.indent_tag_description=false +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.comment.new_lines_at_block_boundaries=true +org.eclipse.jdt.core.formatter.comment.new_lines_at_javadoc_boundaries=true +org.eclipse.jdt.core.formatter.comment.preserve_white_space_between_code_and_line_comments=false +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.disabling_tag=@formatter\:off +org.eclipse.jdt.core.formatter.enabling_tag=@formatter\:on +org.eclipse.jdt.core.formatter.format_guardian_clause_on_one_line=false +org.eclipse.jdt.core.formatter.format_line_comment_starting_on_first_column=false +org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_annotation_declaration_header=true +org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_enum_constant_header=true +org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_enum_declaration_header=true +org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_type_header=true +org.eclipse.jdt.core.formatter.indent_breaks_compare_to_cases=true +org.eclipse.jdt.core.formatter.indent_empty_lines=false +org.eclipse.jdt.core.formatter.indent_statements_compare_to_block=true +org.eclipse.jdt.core.formatter.indent_statements_compare_to_body=true +org.eclipse.jdt.core.formatter.indent_switchstatements_compare_to_cases=true +org.eclipse.jdt.core.formatter.indent_switchstatements_compare_to_switch=false +org.eclipse.jdt.core.formatter.indentation.size=4 +org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_enum_constant=insert +org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_field=insert +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_method=insert +org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_package=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_annotation_on_type=insert +org.eclipse.jdt.core.formatter.insert_new_line_after_label=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_after_type_annotation=do not insert +org.eclipse.jdt.core.formatter.insert_new_line_at_end_of_file_if_missing=do not insert +org.eclipse.jdt.core.formatter.insert_new_line_before_catch_in_try_statement=do not insert +org.eclipse.jdt.core.formatter.insert_new_line_before_closing_brace_in_array_initializer=do not insert +org.eclipse.jdt.core.formatter.insert_new_line_before_else_in_if_statement=do not insert +org.eclipse.jdt.core.formatter.insert_new_line_before_finally_in_try_statement=do not insert +org.eclipse.jdt.core.formatter.insert_new_line_before_while_in_do_statement=do not insert +org.eclipse.jdt.core.formatter.insert_new_line_in_empty_annotation_declaration=insert +org.eclipse.jdt.core.formatter.insert_new_line_in_empty_anonymous_type_declaration=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=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_additive_operator=insert +org.eclipse.jdt.core.formatter.insert_space_after_and_in_type_parameter=insert +org.eclipse.jdt.core.formatter.insert_space_after_arrow_in_switch_case=insert +org.eclipse.jdt.core.formatter.insert_space_after_arrow_in_switch_default=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_bitwise_operator=insert +org.eclipse.jdt.core.formatter.insert_space_after_closing_angle_bracket_in_type_arguments=do not 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_switch_case_expressions=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_lambda_arrow=insert +org.eclipse.jdt.core.formatter.insert_space_after_logical_operator=insert +org.eclipse.jdt.core.formatter.insert_space_after_multiplicative_operator=insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_angle_bracket_in_parameterized_type_reference=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_angle_bracket_in_type_arguments=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_angle_bracket_in_type_parameters=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_brace_in_array_initializer=insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_bracket_in_array_allocation_expression=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_bracket_in_array_reference=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_annotation=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_cast=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_catch=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_constructor_declaration=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_enum_constant=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_for=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_if=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_method_declaration=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_method_invocation=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_parenthesized_expression=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_switch=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_synchronized=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_try=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_relational_operator=insert +org.eclipse.jdt.core.formatter.insert_space_after_semicolon_in_for=insert +org.eclipse.jdt.core.formatter.insert_space_after_semicolon_in_try_resources=insert +org.eclipse.jdt.core.formatter.insert_space_after_shift_operator=insert +org.eclipse.jdt.core.formatter.insert_space_after_string_concatenation=insert +org.eclipse.jdt.core.formatter.insert_space_after_unary_operator=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_additive_operator=insert +org.eclipse.jdt.core.formatter.insert_space_before_and_in_type_parameter=insert +org.eclipse.jdt.core.formatter.insert_space_before_arrow_in_switch_case=insert +org.eclipse.jdt.core.formatter.insert_space_before_arrow_in_switch_default=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_bitwise_operator=insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_angle_bracket_in_parameterized_type_reference=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_angle_bracket_in_type_arguments=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_angle_bracket_in_type_parameters=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_brace_in_array_initializer=insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_bracket_in_array_allocation_expression=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_bracket_in_array_reference=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_annotation=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_cast=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_catch=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_constructor_declaration=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_enum_constant=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_for=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_if=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_method_declaration=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_method_invocation=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_parenthesized_expression=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_switch=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_synchronized=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_try=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_switch_case_expressions=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_lambda_arrow=insert +org.eclipse.jdt.core.formatter.insert_space_before_logical_operator=insert +org.eclipse.jdt.core.formatter.insert_space_before_multiplicative_operator=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_try=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_relational_operator=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_semicolon_in_try_resources=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_shift_operator=insert +org.eclipse.jdt.core.formatter.insert_space_before_string_concatenation=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.join_lines_in_comments=true +org.eclipse.jdt.core.formatter.join_wrapped_lines=true +org.eclipse.jdt.core.formatter.keep_annotation_declaration_on_one_line=one_line_never +org.eclipse.jdt.core.formatter.keep_anonymous_type_declaration_on_one_line=one_line_never +org.eclipse.jdt.core.formatter.keep_code_block_on_one_line=one_line_never +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_enum_constant_declaration_on_one_line=one_line_never +org.eclipse.jdt.core.formatter.keep_enum_declaration_on_one_line=one_line_never +org.eclipse.jdt.core.formatter.keep_if_then_body_block_on_one_line=one_line_never +org.eclipse.jdt.core.formatter.keep_imple_if_on_one_line=false +org.eclipse.jdt.core.formatter.keep_lambda_body_block_on_one_line=one_line_never +org.eclipse.jdt.core.formatter.keep_loop_body_block_on_one_line=one_line_never +org.eclipse.jdt.core.formatter.keep_method_body_on_one_line=one_line_never +org.eclipse.jdt.core.formatter.keep_simple_do_while_body_on_same_line=false +org.eclipse.jdt.core.formatter.keep_simple_for_body_on_same_line=false +org.eclipse.jdt.core.formatter.keep_simple_getter_setter_on_one_line=false +org.eclipse.jdt.core.formatter.keep_simple_while_body_on_same_line=false +org.eclipse.jdt.core.formatter.keep_then_statement_on_same_line=false +org.eclipse.jdt.core.formatter.keep_type_declaration_on_one_line=one_line_never +org.eclipse.jdt.core.formatter.lineSplit=120 +org.eclipse.jdt.core.formatter.never_indent_block_comments_on_first_column=false +org.eclipse.jdt.core.formatter.never_indent_line_comments_on_first_column=false +org.eclipse.jdt.core.formatter.number_of_blank_lines_at_beginning_of_method_body=0 +org.eclipse.jdt.core.formatter.number_of_empty_lines_to_preserve=1 +org.eclipse.jdt.core.formatter.parentheses_positions_in_annotation=common_lines +org.eclipse.jdt.core.formatter.parentheses_positions_in_catch_clause=common_lines +org.eclipse.jdt.core.formatter.parentheses_positions_in_enum_constant_declaration=common_lines +org.eclipse.jdt.core.formatter.parentheses_positions_in_for_statment=common_lines +org.eclipse.jdt.core.formatter.parentheses_positions_in_if_while_statement=common_lines +org.eclipse.jdt.core.formatter.parentheses_positions_in_lambda_declaration=common_lines +org.eclipse.jdt.core.formatter.parentheses_positions_in_method_delcaration=common_lines +org.eclipse.jdt.core.formatter.parentheses_positions_in_method_invocation=common_lines +org.eclipse.jdt.core.formatter.parentheses_positions_in_switch_statement=common_lines +org.eclipse.jdt.core.formatter.parentheses_positions_in_try_clause=common_lines +org.eclipse.jdt.core.formatter.put_empty_statement_on_new_line=true +org.eclipse.jdt.core.formatter.tabulation.char=tab +org.eclipse.jdt.core.formatter.tabulation.size=4 +org.eclipse.jdt.core.formatter.use_on_off_tags=false +org.eclipse.jdt.core.formatter.use_tabs_only_for_leading_indentations=false +org.eclipse.jdt.core.formatter.wrap_before_additive_operator=true +org.eclipse.jdt.core.formatter.wrap_before_assignment_operator=false +org.eclipse.jdt.core.formatter.wrap_before_bitwise_operator=true +org.eclipse.jdt.core.formatter.wrap_before_conditional_operator=true +org.eclipse.jdt.core.formatter.wrap_before_logical_operator=true +org.eclipse.jdt.core.formatter.wrap_before_multiplicative_operator=true +org.eclipse.jdt.core.formatter.wrap_before_or_operator_multicatch=true +org.eclipse.jdt.core.formatter.wrap_before_relational_operator=true +org.eclipse.jdt.core.formatter.wrap_before_shift_operator=true +org.eclipse.jdt.core.formatter.wrap_before_string_concatenation=true +org.eclipse.jdt.core.formatter.wrap_outer_expressions_when_nested=true +org.eclipse.jdt.core.incompatibleJDKLevel=ignore +org.eclipse.jdt.core.incompleteClasspath=error +org.eclipse.jdt.core.javaFormatter=org.eclipse.jdt.core.defaultJavaFormatter diff --git a/tycho-its/projects/api-tools/missing-bin/org.eclipse.equinox.p2.ui/.settings/org.eclipse.jdt.ui.prefs b/tycho-its/projects/api-tools/missing-bin/org.eclipse.equinox.p2.ui/.settings/org.eclipse.jdt.ui.prefs new file mode 100644 index 0000000000..afe11a26eb --- /dev/null +++ b/tycho-its/projects/api-tools/missing-bin/org.eclipse.equinox.p2.ui/.settings/org.eclipse.jdt.ui.prefs @@ -0,0 +1,68 @@ +eclipse.preferences.version=1 +editor_save_participant_org.eclipse.jdt.ui.postsavelistener.cleanup=true +formatter_profile=org.eclipse.jdt.ui.default.eclipse_profile +formatter_settings_version=16 +org.eclipse.jdt.ui.ignorelowercasenames=true +org.eclipse.jdt.ui.importorder=; +org.eclipse.jdt.ui.ondemandthreshold=3 +org.eclipse.jdt.ui.staticondemandthreshold=3 +org.eclipse.jdt.ui.text.custom_code_templates= +sp_cleanup.add_default_serial_version_id=true +sp_cleanup.add_generated_serial_version_id=false +sp_cleanup.add_missing_annotations=true +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_missing_override_annotations_interface_methods=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_functional_interfaces=true +sp_cleanup.convert_to_enhanced_for_loop=true +sp_cleanup.correct_indentation=false +sp_cleanup.format_source_code=true +sp_cleanup.format_source_code_changes_only=false +sp_cleanup.insert_inferred_type_arguments=false +sp_cleanup.make_local_variable_final=false +sp_cleanup.make_parameters_final=false +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=true +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_redundant_modifiers=true +sp_cleanup.remove_redundant_semicolons=true +sp_cleanup.remove_redundant_type_arguments=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=true +sp_cleanup.remove_unnecessary_nls_tags=false +sp_cleanup.remove_unused_imports=true +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_anonymous_class_creation=false +sp_cleanup.use_blocks=false +sp_cleanup.use_blocks_only_for_return_and_throw=false +sp_cleanup.use_lambda=true +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 diff --git a/tycho-its/projects/api-tools/missing-bin/org.eclipse.equinox.p2.ui/META-INF/MANIFEST.MF b/tycho-its/projects/api-tools/missing-bin/org.eclipse.equinox.p2.ui/META-INF/MANIFEST.MF new file mode 100644 index 0000000000..eebed503eb --- /dev/null +++ b/tycho-its/projects/api-tools/missing-bin/org.eclipse.equinox.p2.ui/META-INF/MANIFEST.MF @@ -0,0 +1,81 @@ +Manifest-Version: 1.0 +Bundle-ManifestVersion: 2 +Bundle-Name: %bundleName +Bundle-SymbolicName: org.eclipse.equinox.p2.ui;singleton:=true +Bundle-Version: 2.8.200.qualifier +Bundle-Activator: org.eclipse.equinox.internal.p2.ui.ProvUIActivator +Bundle-Vendor: %providerName +Bundle-Localization: plugin +Export-Package: org.eclipse.equinox.internal.p2.ui; + x-friends:="org.eclipse.equinox.p2.ui.admin, + org.eclipse.pde.ui, + org.eclipse.equinox.p2.ui.sdk, + org.eclipse.equinox.p2.ui.rcp, + org.eclipse.equinox.p2.ui.importexport, + org.eclipse.equinox.p2.ui.sdk.scheduler, + org.eclipse.equinox.p2.discovery, + org.eclipse.equinox.p2.ui.discovery", + org.eclipse.equinox.internal.p2.ui.actions;x-friends:="org.eclipse.equinox.p2.ui.admin,org.eclipse.equinox.p2.ui.sdk.scheduler", + org.eclipse.equinox.internal.p2.ui.dialogs; + x-friends:="org.eclipse.equinox.p2.ui.admin, + org.eclipse.equinox.p2.ui.sdk.scheduler, + org.eclipse.equinox.p2.ui.sdk, + org.eclipse.pde.ui, + org.eclipse.equinox.p2.ui.importexport", + org.eclipse.equinox.internal.p2.ui.model; + x-friends:="org.eclipse.equinox.internal.p2.ui.analysis, + org.eclipse.equinox.p2.ui.admin, + org.eclipse.equinox.p2.ui.sdk.scheduler, + org.eclipse.equinox.p2.ui.sdk, + org.eclipse.equinox.p2.ui.importexport", + org.eclipse.equinox.internal.p2.ui.query;x-friends:="org.eclipse.equinox.internal.p2.ui.analysis,org.eclipse.equinox.p2.ui.admin", + org.eclipse.equinox.internal.p2.ui.viewers;x-friends:="org.eclipse.equinox.p2.ui.admin,org.eclipse.equinox.p2.ui.sdk,org.eclipse.equinox.p2.ui.sdk.scheduler,org.eclipse.equinox.p2.ui.importexport", + org.eclipse.equinox.p2.ui;version="2.6.0" +Require-Bundle: org.eclipse.ui;bundle-version="3.107.0", + org.eclipse.core.runtime;bundle-version="[3.0.0,4.0.0)", + org.eclipse.core.expressions, + org.eclipse.equinox.security.ui;bundle-version="[1.0.0,2.0.0)", + org.eclipse.e4.ui.dialogs;bundle-version="1.1.600" +Import-Package: javax.xml.parsers, + org.bouncycastle.bcpg;version="1.65.0", + org.bouncycastle.openpgp;version="1.65.0", + org.bouncycastle.util;version="1.65.1", + org.eclipse.e4.ui.progress, + org.eclipse.e4.ui.workbench, + org.eclipse.equinox.internal.p2.artifact.processors.pgp, + org.eclipse.equinox.internal.p2.artifact.repository, + org.eclipse.equinox.internal.p2.core.helpers, + org.eclipse.equinox.internal.p2.director, + org.eclipse.equinox.internal.p2.engine.phases, + org.eclipse.equinox.internal.p2.extensionlocation, + org.eclipse.equinox.internal.p2.metadata, + org.eclipse.equinox.internal.p2.metadata.repository, + org.eclipse.equinox.internal.p2.metadata.repository.io, + org.eclipse.equinox.internal.p2.operations, + org.eclipse.equinox.internal.p2.persistence, + org.eclipse.equinox.internal.p2.repository.helpers, + org.eclipse.equinox.internal.provisional.configurator, + org.eclipse.equinox.internal.provisional.p2.core.eventbus, + org.eclipse.equinox.internal.provisional.p2.repository, + org.eclipse.equinox.p2.core;version="[2.7.0,3.0.0)", + org.eclipse.equinox.p2.core.spi;version="[2.0.0,3.0.0)", + org.eclipse.equinox.p2.engine;version="[2.0.0,3.0.0)", + org.eclipse.equinox.p2.engine.query;version="[2.0.0,3.0.0)", + org.eclipse.equinox.p2.metadata;version="[2.0.0,3.0.0)", + org.eclipse.equinox.p2.metadata.expression;version="[2.0.0,3.0.0)", + org.eclipse.equinox.p2.operations;version="[2.0.0,3.0.0)", + org.eclipse.equinox.p2.planner;version="[2.0.0,3.0.0)", + org.eclipse.equinox.p2.query;version="[2.0.0,3.0.0)", + org.eclipse.equinox.p2.repository;version="[2.0.0,3.0.0)", + org.eclipse.equinox.p2.repository.artifact;version="[2.0.0,3.0.0)", + org.eclipse.equinox.p2.repository.artifact.spi;version="[2.0.0,3.0.0)", + org.eclipse.equinox.p2.repository.metadata;version="[2.0.0,3.0.0)", + org.eclipse.equinox.p2.repository.metadata.spi;version="[2.0.0,3.0.0)", + org.eclipse.equinox.p2.repository.spi;version="2.0.0", + org.osgi.framework;version="1.6.0", + org.osgi.service.packageadmin;version="1.2.0", + org.w3c.dom, + org.xml.sax +Bundle-ActivationPolicy: lazy +Bundle-RequiredExecutionEnvironment: JavaSE-17 +Automatic-Module-Name: org.eclipse.equinox.p2.ui diff --git a/tycho-its/projects/api-tools/missing-bin/org.eclipse.equinox.p2.ui/build.properties b/tycho-its/projects/api-tools/missing-bin/org.eclipse.equinox.p2.ui/build.properties new file mode 100644 index 0000000000..29e6d9c192 --- /dev/null +++ b/tycho-its/projects/api-tools/missing-bin/org.eclipse.equinox.p2.ui/build.properties @@ -0,0 +1,19 @@ +############################################################################### +# Copyright (c) 2007, 2010 IBM Corporation and others. +# +# This program and the accompanying materials +# are made available under the terms of the Eclipse Public License 2.0 +# which accompanies this distribution, and is available at +# https://www.eclipse.org/legal/epl-2.0/ +# +# SPDX-License-Identifier: EPL-2.0 +# +# Contributors: +# IBM Corporation - initial API and implementation +############################################################################### +bin.includes = plugin.properties,\ + .,\ + META-INF/,\ + plugin.xml +source.. = src/ +# this is the missing one we want to test: output.. = bin/ \ No newline at end of file diff --git a/tycho-its/projects/api-tools/missing-bin/org.eclipse.equinox.p2.ui/plugin.properties b/tycho-its/projects/api-tools/missing-bin/org.eclipse.equinox.p2.ui/plugin.properties new file mode 100644 index 0000000000..4a76b50a68 --- /dev/null +++ b/tycho-its/projects/api-tools/missing-bin/org.eclipse.equinox.p2.ui/plugin.properties @@ -0,0 +1,22 @@ +############################################################################### +# Copyright (c) 2007, 2010 IBM Corporation and others. +# +# This program and the accompanying materials +# are made available under the terms of the Eclipse Public License 2.0 +# which accompanies this distribution, and is available at +# https://www.eclipse.org/legal/epl-2.0/ +# +# SPDX-License-Identifier: EPL-2.0 +# +# Contributors: +# IBM Corporation - initial API and implementation +############################################################################### +# +# Provisioning UI plugin resources +# +providerName = Eclipse.org - Equinox +bundleName=Equinox Provisioning UI Support +IU.general=General Information +IU.license=License Agreement +IU.copyright=Copyright + diff --git a/tycho-its/projects/api-tools/missing-bin/org.eclipse.equinox.p2.ui/plugin.xml b/tycho-its/projects/api-tools/missing-bin/org.eclipse.equinox.p2.ui/plugin.xml new file mode 100644 index 0000000000..87e8645fd2 --- /dev/null +++ b/tycho-its/projects/api-tools/missing-bin/org.eclipse.equinox.p2.ui/plugin.xml @@ -0,0 +1,57 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/tycho-its/projects/api-tools/missing-bin/org.eclipse.equinox.p2.ui/src/org/eclipse/equinox/internal/p2/ui/ColocatedRepositoryTracker.java b/tycho-its/projects/api-tools/missing-bin/org.eclipse.equinox.p2.ui/src/org/eclipse/equinox/internal/p2/ui/ColocatedRepositoryTracker.java new file mode 100644 index 0000000000..5ed23ab845 --- /dev/null +++ b/tycho-its/projects/api-tools/missing-bin/org.eclipse.equinox.p2.ui/src/org/eclipse/equinox/internal/p2/ui/ColocatedRepositoryTracker.java @@ -0,0 +1,232 @@ +/******************************************************************************* + * Copyright (c) 2008, 2018 IBM Corporation and others. + * + * This program and the accompanying materials + * are made available under the terms of the Eclipse Public License 2.0 + * which accompanies this distribution, and is available at + * https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + * + * Contributors: + * IBM Corporation - initial API and implementation + *******************************************************************************/ +package org.eclipse.equinox.internal.p2.ui; + +import java.net.URI; +import org.eclipse.core.runtime.*; +import org.eclipse.equinox.internal.p2.ui.dialogs.RepositoryNameAndLocationDialog; +import org.eclipse.equinox.internal.provisional.p2.repository.RepositoryEvent; +import org.eclipse.equinox.p2.core.ProvisionException; +import org.eclipse.equinox.p2.operations.ProvisioningSession; +import org.eclipse.equinox.p2.operations.RepositoryTracker; +import org.eclipse.equinox.p2.repository.IRepository; +import org.eclipse.equinox.p2.repository.IRepositoryManager; +import org.eclipse.equinox.p2.repository.artifact.IArtifactRepositoryManager; +import org.eclipse.equinox.p2.repository.metadata.IMetadataRepositoryManager; +import org.eclipse.equinox.p2.ui.ProvisioningUI; +import org.eclipse.jface.dialogs.IDialogConstants; +import org.eclipse.jface.dialogs.MessageDialog; +import org.eclipse.jface.window.Window; +import org.eclipse.osgi.util.NLS; +import org.eclipse.swt.SWT; +import org.eclipse.swt.widgets.Shell; +import org.eclipse.ui.IWorkbench; +import org.eclipse.ui.PlatformUI; +import org.eclipse.ui.statushandlers.StatusManager; + +/** + * Provides a repository tracker that interprets URLs as colocated artifact and + * metadata repositories. + * + * @since 2.0 + */ + +public class ColocatedRepositoryTracker extends RepositoryTracker { + + ProvisioningUI ui; + String parsedNickname; + URI parsedLocation; + + public ColocatedRepositoryTracker(ProvisioningUI ui) { + this.ui = ui; + setArtifactRepositoryFlags(IRepositoryManager.REPOSITORIES_NON_SYSTEM); + setMetadataRepositoryFlags(IRepositoryManager.REPOSITORIES_NON_SYSTEM); + } + + @Override + public URI[] getKnownRepositories(ProvisioningSession session) { + return getMetadataRepositoryManager().getKnownRepositories(getMetadataRepositoryFlags()); + } + + @Override + public void addRepository(URI repoLocation, String nickname, ProvisioningSession session) { + ui.signalRepositoryOperationStart(); + try { + getMetadataRepositoryManager().addRepository(repoLocation); + getArtifactRepositoryManager().addRepository(repoLocation); + getMetadataRepositoryManager().setRepositoryProperty(repoLocation, IRepository.PROP_SYSTEM, + Boolean.FALSE.toString()); + getArtifactRepositoryManager().setRepositoryProperty(repoLocation, IRepository.PROP_SYSTEM, + Boolean.FALSE.toString()); + if (nickname != null) { + getMetadataRepositoryManager().setRepositoryProperty(repoLocation, IRepository.PROP_NICKNAME, nickname); + getArtifactRepositoryManager().setRepositoryProperty(repoLocation, IRepository.PROP_NICKNAME, nickname); + + } + } finally { + // We know that the UI only responds to metadata repo events so we cheat... + ui.signalRepositoryOperationComplete( + new RepositoryEvent(repoLocation, IRepository.TYPE_METADATA, RepositoryEvent.ADDED, true), true); + } + } + + @Override + public void removeRepositories(URI[] repoLocations, ProvisioningSession session) { + ui.signalRepositoryOperationStart(); + try { + for (URI repoLocation : repoLocations) { + getMetadataRepositoryManager().removeRepository(repoLocation); + getArtifactRepositoryManager().removeRepository(repoLocation); + } + } finally { + ui.signalRepositoryOperationComplete(null, true); + } + } + + @Override + public void refreshRepositories(URI[] locations, ProvisioningSession session, IProgressMonitor monitor) { + ui.signalRepositoryOperationStart(); + SubMonitor mon = SubMonitor.convert(monitor, locations.length * 100); + for (URI location : locations) { + try { + getArtifactRepositoryManager().refreshRepository(location, mon.newChild(50)); + getMetadataRepositoryManager().refreshRepository(location, mon.newChild(50)); + } catch (ProvisionException e) { + // ignore problematic repositories when refreshing + } + } + // We have no idea how many repos may have been added/removed as a result of + // refreshing these, this one, so we do not use a specific repository event to + // represent it. + ui.signalRepositoryOperationComplete(null, true); + } + + @Override + public void reportLoadFailure(final URI location, ProvisionException e) { + int code = e.getStatus().getCode(); + // If the user doesn't have a way to manage repositories, then don't report + // failures. + if (!ui.getPolicy().getRepositoriesVisible()) { + super.reportLoadFailure(location, e); + return; + } + + // Special handling when the location is bad (not found, etc.) vs. a failure + // associated with a known repo. + if (code == ProvisionException.REPOSITORY_NOT_FOUND || code == ProvisionException.REPOSITORY_INVALID_LOCATION) { + if (!hasNotFoundStatusBeenReported(location)) { + addNotFound(location); + PlatformUI.getWorkbench().getDisplay().asyncExec(() -> { + IWorkbench workbench = PlatformUI.getWorkbench(); + if (workbench.isClosing()) + return; + Shell shell = ProvUI.getDefaultParentShell(); + int result = MessageDialog.open(MessageDialog.QUESTION, shell, + ProvUIMessages.ColocatedRepositoryTracker_SiteNotFoundTitle, + NLS.bind(ProvUIMessages.ColocatedRepositoryTracker_PromptForSiteLocationEdit, + URIUtil.toUnencodedString(location)), + SWT.NONE, ProvUIMessages.ColocatedRepositoryTracker_SiteNotFound_EditButtonLabel, + IDialogConstants.NO_LABEL); + if (result == 0) { + RepositoryNameAndLocationDialog dialog = new RepositoryNameAndLocationDialog(shell, ui) { + @Override + protected String getInitialLocationText() { + return URIUtil.toUnencodedString(location); + } + + @Override + protected String getInitialNameText() { + String nickname = getMetadataRepositoryManager().getRepositoryProperty(location, + IRepository.PROP_NICKNAME); + return nickname == null ? "" : nickname; //$NON-NLS-1$ + } + }; + int ret = dialog.open(); + if (ret == Window.OK) { + URI correctedLocation = dialog.getLocation(); + if (correctedLocation != null) { + ui.signalRepositoryOperationStart(); + try { + removeRepositories(new URI[] { location }, ui.getSession()); + addRepository(correctedLocation, dialog.getName(), ui.getSession()); + } finally { + ui.signalRepositoryOperationComplete(null, true); + } + } + } + } + }); + } + } else { + ProvUI.handleException(e, null, StatusManager.SHOW | StatusManager.LOG); + } + } + + IMetadataRepositoryManager getMetadataRepositoryManager() { + return ProvUI.getMetadataRepositoryManager(ui.getSession()); + } + + IArtifactRepositoryManager getArtifactRepositoryManager() { + return ProvUI.getArtifactRepositoryManager(ui.getSession()); + } + + /* + * Overridden to support "Name - Location" parsing + */ + @Override + public URI locationFromString(String locationString) { + URI uri = super.locationFromString(locationString); + if (uri != null) + return uri; + // Look for the "Name - Location" pattern + // There could be a hyphen in the name or URI, so we have to visit all + // combinations + int start = 0; + int index = 0; + String locationSubset; + String pattern = ProvUIMessages.RepositorySelectionGroup_NameAndLocationSeparator; + while (index >= 0) { + index = locationString.indexOf(pattern, start); + if (index >= 0) { + start = index + pattern.length(); + locationSubset = locationString.substring(start); + uri = super.locationFromString(locationSubset); + if (uri != null) { + parsedLocation = uri; + parsedNickname = locationString.substring(0, index); + return uri; + } + } + } + return null; + } + + /* + * Used by the UI to get a name that might have been supplied when the location + * was originally parsed. see + * https://bugs.eclipse.org/bugs/show_bug.cgi?id=293068 + */ + public String getParsedNickname(URI location) { + if (parsedNickname == null || parsedLocation == null) + return null; + if (location.toString().equals(parsedLocation.toString())) + return parsedNickname; + return null; + } + + @Override + protected boolean contains(URI location, ProvisioningSession session) { + return ProvUI.getMetadataRepositoryManager(session).contains(location); + } +} diff --git a/tycho-its/projects/api-tools/missing-bin/org.eclipse.equinox.p2.ui/src/org/eclipse/equinox/internal/p2/ui/ElementQueryDescriptor.java b/tycho-its/projects/api-tools/missing-bin/org.eclipse.equinox.p2.ui/src/org/eclipse/equinox/internal/p2/ui/ElementQueryDescriptor.java new file mode 100644 index 0000000000..f6da400302 --- /dev/null +++ b/tycho-its/projects/api-tools/missing-bin/org.eclipse.equinox.p2.ui/src/org/eclipse/equinox/internal/p2/ui/ElementQueryDescriptor.java @@ -0,0 +1,84 @@ +/******************************************************************************* + * Copyright (c) 2007, 2010 IBM Corporation and others. + * + * This program and the accompanying materials + * are made available under the terms of the Eclipse Public License 2.0 + * which accompanies this distribution, and is available at + * https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + * + * Contributors: + * IBM Corporation - initial API and implementation + * EclipseSource - ongoing development + *******************************************************************************/ +package org.eclipse.equinox.internal.p2.ui; + +import java.util.Collection; +import org.eclipse.core.runtime.IProgressMonitor; +import org.eclipse.equinox.p2.query.*; + +/** + * ElementQueryDescriptor represents everything needed to run a query, including + * the object to be queried, the query to use, and the query result. It can optionally + * wrap the query results in a UI element. + * + * @since 3.4 + */ +public class ElementQueryDescriptor { + + private IQuery query; + private Collector collector; + private IQueryable queryable; + private ElementWrapper wrapper; + + /** + * Creates an ElementQueryDescriptor to represent a Query, its collector the queryable + * on which it will run. + */ + public ElementQueryDescriptor(IQueryable queryable, IQuery query, Collector collector) { + this(queryable, query, collector, null); + } + + /** + * Creates an ElementQueryDescriptor to represent a Query, its collector the queryable + * on which it will run, and the transformer used to transform the results. + */ + @SuppressWarnings("unchecked") + public ElementQueryDescriptor(IQueryable queryable, IQuery query, Collector collector, ElementWrapper wrapper) { + this.query = (IQuery) query; + this.collector = (Collector) collector; + this.queryable = (IQueryable) queryable; + this.wrapper = wrapper; + } + + /** + * Performs the query returning a collection of results. + * @param monitor + */ + public Collection performQuery(IProgressMonitor monitor) { + Collector results = this.collector; + // If the query is completely described, perform it + if (query != null && collector != null && queryable != null) + results.addAll(this.queryable.query(this.query, monitor)); + else if (results == null) + results = new Collector<>(); + // Let the wrapper analyze the results, even if we didn't perform the query. + // This allows the wrapper to modify the results with explanations. + if (wrapper != null) + return wrapper.getElements(results); + return results.toUnmodifiableSet(); + } + + public boolean hasCollector() { + return this.collector != null; + } + + public boolean hasQueryable() { + return this.queryable != null; + } + + public boolean hasQuery() { + return this.query != null; + } +} diff --git a/tycho-its/projects/api-tools/missing-bin/org.eclipse.equinox.p2.ui/src/org/eclipse/equinox/internal/p2/ui/ElementWrapper.java b/tycho-its/projects/api-tools/missing-bin/org.eclipse.equinox.p2.ui/src/org/eclipse/equinox/internal/p2/ui/ElementWrapper.java new file mode 100644 index 0000000000..0cc7fbc4b4 --- /dev/null +++ b/tycho-its/projects/api-tools/missing-bin/org.eclipse.equinox.p2.ui/src/org/eclipse/equinox/internal/p2/ui/ElementWrapper.java @@ -0,0 +1,62 @@ +/******************************************************************************* +* Copyright (c) 2009, 2010 EclipseSource and others. + * + * This +* program and the accompanying materials are made available under the terms of +* the Eclipse Public License 2.0 which accompanies this distribution, and is +* available at + * https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 +* +* Contributors: +* EclipseSource - initial API and implementation +* IBM Corporation - ongoing development +******************************************************************************/ +package org.eclipse.equinox.internal.p2.ui; + +import java.util.*; +import org.eclipse.equinox.p2.query.Collector; + +/** + * Wraps query results inside corresponding UI elements + */ +public abstract class ElementWrapper { + + private Collection collection = null; + + /** + * Transforms a collector returned by a query to a collection + * of UI elements + */ + public Collection getElements(Collector collector) { + collection = new ArrayList<>(collector.size()); + Iterator iter = collector.iterator(); + while (iter.hasNext()) { + Object o = iter.next(); + if (shouldWrap(o)) + collection.add(wrap(o)); + } + return getCollection(); + } + + /** + * Gets the collection where the elements are being stored. + */ + protected Collection getCollection() { + return collection == null ? Collections.emptyList() : collection; + } + + /** + * Determines if this object should be accepted and wrapped + * by a UI element. + */ + protected boolean shouldWrap(Object o) { + return true; + } + + /** + * Wraps a single element of the query result inside a UI element. + */ + protected abstract Object wrap(Object item); +} diff --git a/tycho-its/projects/api-tools/missing-bin/org.eclipse.equinox.p2.ui/src/org/eclipse/equinox/internal/p2/ui/IProvHelpContextIds.java b/tycho-its/projects/api-tools/missing-bin/org.eclipse.equinox.p2.ui/src/org/eclipse/equinox/internal/p2/ui/IProvHelpContextIds.java new file mode 100644 index 0000000000..e701152a1e --- /dev/null +++ b/tycho-its/projects/api-tools/missing-bin/org.eclipse.equinox.p2.ui/src/org/eclipse/equinox/internal/p2/ui/IProvHelpContextIds.java @@ -0,0 +1,50 @@ +/******************************************************************************* + * Copyright (c) 2008, 2010 IBM Corporation and others. + * + * This program and the accompanying materials + * are made available under the terms of the Eclipse Public License 2.0 + * which accompanies this distribution, and is available at + * https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + * + * Contributors: + * IBM Corporation - initial API and implementation + *******************************************************************************/ +package org.eclipse.equinox.internal.p2.ui; + +/** + * Help context ids for the P2 UI + *

+ * This interface contains constants only; it is not intended to be implemented + * or extended. + *

+ * + * @since 3.4 + * @noextend This interface is not intended to be extended by clients. + * @noimplement This interface is not intended to be implemented by clients. + */ + +public interface IProvHelpContextIds { + String PREFIX = ProvUIActivator.PLUGIN_ID + "."; //$NON-NLS-1$ + + String REVERT_CONFIGURATION_WIZARD = PREFIX + "revert_configuration_wizard_context"; //$NON-NLS-1$ + + String UNINSTALL_WIZARD = PREFIX + "uinstall_wizard_context"; //$NON-NLS-1$ + + String UPDATE_WIZARD = PREFIX + "update_wizard_context"; //$NON-NLS-1$ + + String ADD_REPOSITORY_DIALOG = PREFIX + "add_repository_dialog_context"; //$NON-NLS-1$ + + String INSTALL_WIZARD = PREFIX + "install_wizard_context"; //$NON-NLS-1$ + + String REPOSITORY_MANIPULATION_DIALOG = PREFIX + "repository_manipulation_dialog_context"; //$NON-NLS-1$ + + String INSTALLED_SOFTWARE = PREFIX + "installed_software_context"; //$NON-NLS-1$ + + String AVAILABLE_SOFTWARE = PREFIX + "available_software_context"; //$NON-NLS-1$ + + String TRUST_DIALOG = PREFIX + "trust_dialog_context"; //$NON-NLS-1$ + + String TRUST_AUTHORITIES_DIALOG = PREFIX + "trust_authorities_dialog_context"; //$NON-NLS-1$ +} diff --git a/tycho-its/projects/api-tools/missing-bin/org.eclipse.equinox.p2.ui/src/org/eclipse/equinox/internal/p2/ui/KeySigningInfoFactory.java b/tycho-its/projects/api-tools/missing-bin/org.eclipse.equinox.p2.ui/src/org/eclipse/equinox/internal/p2/ui/KeySigningInfoFactory.java new file mode 100644 index 0000000000..de71046576 --- /dev/null +++ b/tycho-its/projects/api-tools/missing-bin/org.eclipse.equinox.p2.ui/src/org/eclipse/equinox/internal/p2/ui/KeySigningInfoFactory.java @@ -0,0 +1,182 @@ +/******************************************************************************* + * Copyright (c) 2022 Eclipse contributors and others. + * + * This program and the accompanying materials + * are made available under the terms of the Eclipse Public License 2.0 + * which accompanies this distribution, and is available at + * https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + *******************************************************************************/ +package org.eclipse.equinox.internal.p2.ui; + +import java.io.File; +import java.io.IOException; +import java.util.*; +import org.bouncycastle.openpgp.*; +import org.eclipse.core.runtime.*; +import org.eclipse.equinox.internal.p2.artifact.processors.pgp.PGPPublicKeyStore; +import org.eclipse.equinox.internal.p2.artifact.processors.pgp.PGPSignatureVerifier; +import org.eclipse.equinox.p2.core.IProvisioningAgent; +import org.eclipse.equinox.p2.metadata.IArtifactKey; +import org.eclipse.equinox.p2.query.IQueryResult; +import org.eclipse.equinox.p2.repository.artifact.*; +import org.eclipse.equinox.p2.repository.spi.PGPPublicKeyService; +import org.eclipse.ui.internal.about.AboutBundleData; +import org.eclipse.ui.internal.about.AboutPluginsPage; +import org.osgi.framework.Bundle; + +/** + * A factory used by the {@link AboutPluginsPage} to provide extended signing + * information, in particular information about PGP signing. + * + * @since 2.7.400 + */ +public class KeySigningInfoFactory implements IAdapterFactory { + + private static final Class[] CLASSES = new Class[] { AboutBundleData.ExtendedSigningInfo.class }; + + @Override + public T getAdapter(Object adaptableObject, Class adapterType) { + if (adapterType == AboutBundleData.ExtendedSigningInfo.class) { + return adapterType.cast(new AboutBundleData.ExtendedSigningInfo() { + private final Map> bundlePoolArtficactSigningDetails = getBundlePoolArtficactPGPSigningDetails(); + + @Override + public boolean isSigned(Bundle bundle) { + return getDetails(bundle) != null; + } + + @Override + public String getSigningType(Bundle bundle) { + return ProvUIMessages.KeySigningInfoFactory_PGPSigningType; + } + + @Override + public String getSigningDetails(Bundle bundle) { + Map details = getDetails(bundle); + if (details != null) { + PGPPublicKeyService keyService = getKeyService(); + List lines = new ArrayList<>(); + for (PGPPublicKey key : details.values()) { + if (keyService != null) { + // Be sure to normalize/enhance the key so we properly don't show + // self-signatures. + key = keyService.addKey(key); + } + if (!lines.isEmpty()) { + lines.add(""); //$NON-NLS-1$ + } + addDetails(key, lines, ""); //$NON-NLS-1$ + if (keyService != null) { + Set verifiedCertifications = keyService.getVerifiedCertifications(key); + boolean first = true; + for (PGPPublicKey verifyingKey : verifiedCertifications) { + /// Don't show self-signatures. + if (!verifyingKey.equals(key)) { + if (first) { + lines.add(" " + ProvUIMessages.KeySigningInfoFactory_KeySignersSection); //$NON-NLS-1$ + first = false; + } + addDetails(verifyingKey, lines, " "); //$NON-NLS-1$ + } + } + } + } + return String.join("\n", lines); //$NON-NLS-1$ + } + return null; + } + + @Override + public Date getSigningTime(Bundle bundle) { + Map details = getDetails(bundle); + return details == null ? null : details.keySet().iterator().next().getCreationTime(); + } + + private void addDetails(PGPPublicKey key, List lines, String indentation) { + lines.add(indentation + ProvUIMessages.KeySigningInfoFactory_FingerprintItem + + PGPPublicKeyService.toHexFingerprint(key)); + for (Iterator userIDs = key.getUserIDs(); userIDs.hasNext();) { + lines.add(indentation + ProvUIMessages.KeySigningInfoFactory_UserIDItem + userIDs.next()); + } + } + + private PGPPublicKeyService getKeyService() { + IProvisioningAgent agent = org.eclipse.equinox.internal.p2.extensionlocation.Activator + .getCurrentAgent(); + return agent == null ? null : agent.getService(PGPPublicKeyService.class); + } + + private Map getDetails(Bundle bundle) { + try { + File bundleFile = FileLocator.getBundleFileLocation(bundle).orElseThrow().getCanonicalFile(); + return bundlePoolArtficactSigningDetails.get(bundleFile); + } catch (IOException | RuntimeException e) { + ProvUIActivator.getDefault().getLog().log(Status.error(e.getMessage(), e)); + return null; + } + } + }); + } + + return null; + } + + @Override + public Class[] getAdapterList() { + return CLASSES; + } + + /** + * Returns a map from artifact files to the PGP signature/key pairs that were + * used to {@link PGPSignatureVerifier#close() verify} the artifact while it was + * being downloaded. + * + * @return a map of all the PGP signed artifact files to their signature/key + * pairs. + */ + private static Map> getBundlePoolArtficactPGPSigningDetails() { + Map> result = new LinkedHashMap<>(); + try { + // Look up artifact metadata for all the bundle pool repository of the + // installation. + IFileArtifactRepository bundlePoolRepository = org.eclipse.equinox.internal.p2.extensionlocation.Activator + .getBundlePoolRepository(); + if (bundlePoolRepository == null) { + return Collections.emptyMap(); + } + IQueryResult allArtifactKeys = bundlePoolRepository.query(ArtifactKeyQuery.ALL_KEYS, null); + for (IArtifactKey key : allArtifactKeys) { + for (IArtifactDescriptor descriptor : bundlePoolRepository.getArtifactDescriptors(key)) { + File file = bundlePoolRepository.getArtifactFile(descriptor); + if (file != null) { + try { + Collection signatures = PGPSignatureVerifier.getSignatures(descriptor); + if (!signatures.isEmpty()) { + Map details = new LinkedHashMap<>(); + PGPPublicKeyStore keys = PGPSignatureVerifier.getKeys(descriptor); + for (PGPSignature signature : signatures) { + Collection signingKeys = keys.getKeys(signature.getKeyID()); + if (!signingKeys.isEmpty()) { + // There is vanishingly small chance that two keys with colliding key IDs were + // used on two different signatures on the same artifact. + details.put(signature, signingKeys.iterator().next()); + } + } + if (!details.isEmpty()) { + result.put(file.getCanonicalFile(), details); + } + } + } catch (IOException | PGPException | RuntimeException e) { + ProvUIActivator.getDefault().getLog().log(Status.error(e.getMessage(), e)); + } + } + } + } + } catch (RuntimeException e) { + ProvUIActivator.getDefault().getLog().log(Status.error(e.getMessage(), e)); + } + return result; + } +} diff --git a/tycho-its/projects/api-tools/missing-bin/org.eclipse.equinox.p2.ui/src/org/eclipse/equinox/internal/p2/ui/MessageDialogWithLink.java b/tycho-its/projects/api-tools/missing-bin/org.eclipse.equinox.p2.ui/src/org/eclipse/equinox/internal/p2/ui/MessageDialogWithLink.java new file mode 100644 index 0000000000..34044e1d93 --- /dev/null +++ b/tycho-its/projects/api-tools/missing-bin/org.eclipse.equinox.p2.ui/src/org/eclipse/equinox/internal/p2/ui/MessageDialogWithLink.java @@ -0,0 +1,71 @@ +/******************************************************************************* + * Copyright (c) 2015 Red Hat Inc. + * + * This program and the accompanying materials + * are made available under the terms of the Eclipse Public License 2.0 + * which accompanies this distribution, and is available at + * https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + * + * Contributors: + * Mickael Istria (Red Hat Inc.) - 483644 Improve "No updates found" dialog + *******************************************************************************/ +package org.eclipse.equinox.internal.p2.ui; + +import java.util.ArrayList; +import java.util.List; +import org.eclipse.jface.dialogs.IDialogConstants; +import org.eclipse.jface.dialogs.MessageDialog; +import org.eclipse.jface.layout.GridDataFactory; +import org.eclipse.swt.SWT; +import org.eclipse.swt.events.SelectionListener; +import org.eclipse.swt.graphics.Image; +import org.eclipse.swt.widgets.*; + +public class MessageDialogWithLink extends MessageDialog { + + protected String linkMessage; + protected Link link; + protected List linkListeners = new ArrayList<>(); + + public MessageDialogWithLink(Shell parentShell, String dialogTitle, Image dialogTitleImage, String dialogMessage, int dialogImageType, String[] dialogButtonLabels, int defaultIndex) { + super(parentShell, dialogTitle, dialogTitleImage, dialogMessage, dialogImageType, dialogButtonLabels, defaultIndex); + this.message = null; + this.linkMessage = dialogMessage; + } + + public MessageDialogWithLink(Shell parentShell, String dialogTitle, Image dialogTitleImage, String dialogMessage, int dialogImageType, int defaultIndex, String... dialogButtonLabels) { + this(parentShell, dialogTitle, dialogTitleImage, dialogMessage, dialogImageType, dialogButtonLabels, defaultIndex); + } + + @Override + protected Control createMessageArea(Composite composite) { + super.createMessageArea(composite); + // create message + if (linkMessage != null) { + this.link = new Link(composite, getMessageLabelStyle()); + this.link.setText(this.linkMessage); + GridDataFactory.fillDefaults().align(SWT.FILL, SWT.BEGINNING).grab(true, false).hint(convertHorizontalDLUsToPixels(IDialogConstants.MINIMUM_MESSAGE_AREA_WIDTH), SWT.DEFAULT).applyTo(this.link); + for (SelectionListener linkListener : this.linkListeners) { + this.link.addSelectionListener(linkListener); + } + } + return composite; + } + + public void addSelectionListener(SelectionListener listener) { + if (link != null && !link.isDisposed()) { + link.addSelectionListener(listener); + } + this.linkListeners.add(listener); + } + + public void removeSelectionListener(SelectionListener listener) { + if (link != null && !link.isDisposed()) { + link.removeSelectionListener(listener); + } + this.linkListeners.add(listener); + } + +} diff --git a/tycho-its/projects/api-tools/missing-bin/org.eclipse.equinox.p2.ui/src/org/eclipse/equinox/internal/p2/ui/ProvUI.java b/tycho-its/projects/api-tools/missing-bin/org.eclipse.equinox.p2.ui/src/org/eclipse/equinox/internal/p2/ui/ProvUI.java new file mode 100644 index 0000000000..efc21e8384 --- /dev/null +++ b/tycho-its/projects/api-tools/missing-bin/org.eclipse.equinox.p2.ui/src/org/eclipse/equinox/internal/p2/ui/ProvUI.java @@ -0,0 +1,427 @@ +/******************************************************************************* + * Copyright (c) 2007, 2018 IBM Corporation and others. + * + * This program and the accompanying materials + * are made available under the terms of the Eclipse Public License 2.0 + * which accompanies this distribution, and is available at + * https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + * + * Contributors: + * IBM Corporation - initial API and implementation + * Ericsson AB (Hamdan Msheik) - Bug 396420 - Control Install dialog through preference customization + * Red Hat Inc. - Bug 460967 + * Mickael Istria (Red Hat Inc.) - 483644 Improve "No updates found" dialog + *******************************************************************************/ + +package org.eclipse.equinox.internal.p2.ui; + +import java.util.*; +import java.util.stream.Collectors; +import java.util.stream.Stream; +import org.eclipse.core.commands.*; +import org.eclipse.core.commands.common.NotDefinedException; +import org.eclipse.core.runtime.*; +import org.eclipse.equinox.internal.p2.director.ProfileChangeRequest; +import org.eclipse.equinox.internal.p2.metadata.ProvidedCapability; +import org.eclipse.equinox.internal.p2.ui.dialogs.ILayoutConstants; +import org.eclipse.equinox.internal.p2.ui.query.IUViewQueryContext; +import org.eclipse.equinox.internal.p2.ui.viewers.IUColumnConfig; +import org.eclipse.equinox.internal.provisional.p2.core.eventbus.IProvisioningEventBus; +import org.eclipse.equinox.p2.engine.*; +import org.eclipse.equinox.p2.metadata.*; +import org.eclipse.equinox.p2.metadata.MetadataFactory.InstallableUnitDescription; +import org.eclipse.equinox.p2.operations.*; +import org.eclipse.equinox.p2.planner.IPlanner; +import org.eclipse.equinox.p2.planner.IProfileChangeRequest; +import org.eclipse.equinox.p2.query.QueryUtil; +import org.eclipse.equinox.p2.repository.artifact.IArtifactRepositoryManager; +import org.eclipse.equinox.p2.repository.metadata.IMetadataRepositoryManager; +import org.eclipse.equinox.p2.ui.Policy; +import org.eclipse.equinox.p2.ui.ProvisioningUI; +import org.eclipse.jface.dialogs.IDialogConstants; +import org.eclipse.jface.dialogs.MessageDialog; +import org.eclipse.osgi.util.ManifestElement; +import org.eclipse.swt.events.SelectionListener; +import org.eclipse.swt.widgets.Event; +import org.eclipse.swt.widgets.Shell; +import org.eclipse.ui.PlatformUI; +import org.eclipse.ui.commands.ICommandService; +import org.eclipse.ui.handlers.IHandlerService; +import org.eclipse.ui.statushandlers.StatusManager; +import org.osgi.framework.BundleException; +import org.osgi.framework.Constants; + +/** + * Generic provisioning UI utility and policy methods. + * + * @since 3.4 + */ +public class ProvUI { + + // Public constants for common command and tooltip names + public static final String INSTALL_COMMAND_LABEL = ProvUIMessages.InstallIUCommandLabel; + public static final String INSTALL_COMMAND_TOOLTIP = ProvUIMessages.InstallIUCommandTooltip; + public static final String UNINSTALL_COMMAND_LABEL = ProvUIMessages.UninstallIUCommandLabel; + public static final String UNINSTALL_COMMAND_TOOLTIP = ProvUIMessages.UninstallIUCommandTooltip; + public static final String UPDATE_COMMAND_LABEL = ProvUIMessages.UpdateIUCommandLabel; + public static final String UPDATE_COMMAND_TOOLTIP = ProvUIMessages.UpdateIUCommandTooltip; + public static final String REVERT_COMMAND_LABEL = ProvUIMessages.RevertIUCommandLabel; + public static final String REVERT_COMMAND_TOOLTIP = ProvUIMessages.RevertIUCommandTooltip; + + /** + * A constant indicating that there was nothing to size (there was no valid plan + * that could be used to compute size). + */ + public static final long SIZE_NOTAPPLICABLE = -3L; + /** + * Indicates that the size is unavailable (an attempt was made to compute size + * but it failed) + */ + public static final long SIZE_UNAVAILABLE = -2L; + /** + * Indicates that the size is currently unknown + */ + public static final long SIZE_UNKNOWN = -1L; + + private static IUColumnConfig[] columnConfig; + + // These values rely on the command markup in org.eclipse.ui.ide that defines + // the update commands + private static final String UPDATE_MANAGER_FIND_AND_INSTALL = "org.eclipse.ui.update.findAndInstallUpdates"; //$NON-NLS-1$ + // This value relies on the command markup in org.eclipse.ui + private static final String INSTALLATION_DIALOG = "org.eclipse.ui.help.installationDialog"; //$NON-NLS-1$ + + public static IStatus handleException(Throwable t, String message, int style) { + if (message == null && t != null) { + message = t.getMessage(); + } + IStatus status = new Status(IStatus.ERROR, ProvUIActivator.PLUGIN_ID, 0, message, t); + StatusManager.getManager().handle(status, style); + return status; + } + + public static void reportStatus(IStatus status, int style) { + // workaround for + // https://bugs.eclipse.org/bugs/show_bug.cgi?id=211933 + // Note we'd rather have a proper looking dialog than get the + // blocking right. + if ((style & StatusManager.BLOCK) == StatusManager.BLOCK + || (style & StatusManager.SHOW) == StatusManager.SHOW) { + if (status.getSeverity() == IStatus.INFO) { + final MessageDialogWithLink dialog = new MessageDialogWithLink(ProvUI.getDefaultParentShell(), + ProvUIMessages.ProvUI_InformationTitle, null, status.getMessage(), MessageDialog.INFORMATION, 0, + IDialogConstants.OK_LABEL); + if (status.getCode() == UpdateOperation.STATUS_NOTHING_TO_UPDATE) { + dialog.addSelectionListener(SelectionListener.widgetSelectedAdapter( + e -> ProvisioningUI.getDefaultUI().manipulateRepositories(dialog.getShell()))); + } + dialog.open(); + // unset the dialog bits + style = style & ~StatusManager.BLOCK; + style = style & ~StatusManager.SHOW; + // unset logging for statuses that should never be logged. + // Ideally the caller would do this but this bug keeps coming back. + // see https://bugs.eclipse.org/bugs/show_bug.cgi?id=274074 + if (status.getCode() == UpdateOperation.STATUS_NOTHING_TO_UPDATE) + style = 0; + } else if (status.getSeverity() == IStatus.WARNING) { + MessageDialog.openWarning(ProvUI.getDefaultParentShell(), ProvUIMessages.ProvUI_WarningTitle, + status.getMessage()); + // unset the dialog bits + style = style & ~StatusManager.BLOCK; + style = style & ~StatusManager.SHOW; + } + } + if (style != 0) + StatusManager.getManager().handle(status, style); + } + + public static IUColumnConfig[] getIUColumnConfig() { + if (columnConfig == null) + columnConfig = new IUColumnConfig[] { + new IUColumnConfig(ProvUIMessages.ProvUI_NameColumnTitle, IUColumnConfig.COLUMN_NAME, + ILayoutConstants.DEFAULT_PRIMARY_COLUMN_WIDTH), + new IUColumnConfig(ProvUIMessages.ProvUI_VersionColumnTitle, IUColumnConfig.COLUMN_VERSION, + ILayoutConstants.DEFAULT_COLUMN_WIDTH) }; + return columnConfig; + + } + + // Factory method returning a new instance of a IUViewQueryContext + public static IUViewQueryContext getQueryContext(Policy policy) { + IUViewQueryContext queryContext = new IUViewQueryContext( + policy.getGroupByCategory() ? IUViewQueryContext.AVAILABLE_VIEW_BY_CATEGORY + : IUViewQueryContext.AVAILABLE_VIEW_FLAT); + queryContext.setShowInstallChildren(policy.getShowDrilldownRequirements()); + queryContext.setShowProvisioningPlanChildren(policy.getShowDrilldownRequirements()); + + // among other things the 4 calls below are used to control the available + // software dialog (AvailableIUPage) + queryContext.setShowLatestVersionsOnly(policy.getShowLatestVersionsOnly()); + queryContext.setHideAlreadyInstalled(policy.getHideAlreadyInstalled()); + queryContext.setUseCategories(policy.getGroupByCategory()); + queryContext.setFilterOnEnv(policy.getFilterOnEnv()); + return queryContext; + } + + @SuppressWarnings("unchecked") + public static T getAdapter(Object object, Class adapterType) { + if (object == null) + return null; + if (adapterType.isInstance(object)) + // Ideally, we would use Class.cast here but it was introduced in Java 1.5 + return (T) object; + if (object instanceof IAdaptable) + // Ideally, we would use Class.cast here but it was introduced in Java 1.5 + return ((IAdaptable) object).getAdapter(adapterType); + return null; + } + + /** + * Returns a shell that is appropriate to use as the parent for a modal dialog. + */ + public static Shell getDefaultParentShell() { + return PlatformUI.getWorkbench().getModalDialogShellProvider().getShell(); + } + + public static void openUpdateManagerInstaller(Event event) { + runCommand(UPDATE_MANAGER_FIND_AND_INSTALL, + ProvUIMessages.UpdateManagerCompatibility_UnableToOpenFindAndInstall, event); + } + + public static void openInstallationDialog(Event event) { + runCommand(INSTALLATION_DIALOG, ProvUIMessages.ProvUI_InstallDialogError, event); + } + + public static boolean isUpdateManagerInstallerPresent() { + ICommandService commandService = PlatformUI.getWorkbench().getService(ICommandService.class); + Command command = commandService.getCommand(UPDATE_MANAGER_FIND_AND_INSTALL); + return command.isDefined(); + } + + private static void runCommand(String commandId, String errorMessage, Event event) { + ICommandService commandService = PlatformUI.getWorkbench().getService(ICommandService.class); + Command command = commandService.getCommand(commandId); + if (!command.isDefined()) { + return; + } + IHandlerService handlerService = PlatformUI.getWorkbench().getService(IHandlerService.class); + try { + handlerService.executeCommand(commandId, event); + } catch (ExecutionException e) { + reportFail(errorMessage, e); + } catch (NotDefinedException e) { + reportFail(errorMessage, e); + } catch (NotEnabledException e) { + reportFail(errorMessage, e); + } catch (NotHandledException e) { + reportFail(errorMessage, e); + } + } + + public static boolean isCategory(IInstallableUnit iu) { + return QueryUtil.isCategory(iu); + } + + private static void reportFail(String message, Throwable t) { + Status failStatus = new Status(IStatus.ERROR, ProvUIActivator.PLUGIN_ID, message, t); + reportStatus(failStatus, StatusManager.BLOCK | StatusManager.LOG); + } + + /** + * Get sizing information about the specified plan. + * + * @param engine the engine + * @param plan the provisioning plan + * @param context the provisioning context to be used for the sizing + * @param monitor the progress monitor + * + * @return a long integer describing the disk size required for the provisioning + * plan. + * + * @see #SIZE_UNKNOWN + * @see #SIZE_UNAVAILABLE + * @see #SIZE_NOTAPPLICABLE + */ + public static long getSize(IEngine engine, IProvisioningPlan plan, ProvisioningContext context, + IProgressMonitor monitor) { + // If there is nothing to size, return 0 + if (plan == null) + return SIZE_NOTAPPLICABLE; + if (countPlanElements(plan) == 0) + return 0; + long installPlanSize = 0; + SubMonitor mon = SubMonitor.convert(monitor, 300); + if (plan.getInstallerPlan() != null) { + ISizingPhaseSet sizingPhaseSet = PhaseSetFactory.createSizingPhaseSet(); + IStatus status = engine.perform(plan.getInstallerPlan(), sizingPhaseSet, mon.newChild(100)); + if (status.isOK()) + installPlanSize = sizingPhaseSet.getDiskSize(); + } else { + mon.worked(100); + } + ISizingPhaseSet sizingPhaseSet = PhaseSetFactory.createSizingPhaseSet(); + IStatus status = engine.perform(plan, sizingPhaseSet, mon.newChild(200)); + if (status.isOK()) + return installPlanSize + sizingPhaseSet.getDiskSize(); + return SIZE_UNAVAILABLE; + } + + private static int countPlanElements(IProvisioningPlan plan) { + return QueryUtil.compoundQueryable(plan.getAdditions(), plan.getRemovals()) + .query(QueryUtil.createIUAnyQuery(), null).toUnmodifiableSet().size(); + } + + /** + * Return the artifact repository manager for the given session + * + * @return the repository manager + */ + public static IArtifactRepositoryManager getArtifactRepositoryManager(ProvisioningSession session) { + return session.getProvisioningAgent().getService(IArtifactRepositoryManager.class); + } + + /** + * Return the metadata repository manager for the given session + * + * @return the repository manager + */ + public static IMetadataRepositoryManager getMetadataRepositoryManager(ProvisioningSession session) { + return session.getProvisioningAgent().getService(IMetadataRepositoryManager.class); + } + + /** + * Return the profile registry for the given session + * + * @return the profile registry + */ + public static IProfileRegistry getProfileRegistry(ProvisioningSession session) { + return session.getProvisioningAgent().getService(IProfileRegistry.class); + } + + /** + * Return the provisioning engine for the given session + * + * @return the provisioning engine + */ + public static IEngine getEngine(ProvisioningSession session) { + return session.getProvisioningAgent().getService(IEngine.class); + } + + /** + * Return the provisioning event bus used for dispatching events. + * + * @return the event bus + */ + public static IProvisioningEventBus getProvisioningEventBus(ProvisioningSession session) { + return session.getProvisioningAgent().getService(IProvisioningEventBus.class); + } + + public static IProvisioningPlan toCompabilityWithCurrentJREProvisioningPlan( + ProfileChangeOperation referenceOperation, IProgressMonitor monitor) { + IInstallableUnit currentJREUnit = createCurrentJavaSEUnit(); + IProfileChangeRequest compatibilityWithCurrentRequest = toCurrentJREOperation(referenceOperation, + currentJREUnit); + IPlanner planner = referenceOperation.getProvisioningPlan().getProfile().getProvisioningAgent() + .getService(IPlanner.class); + IProvisioningPlan res = planner.getProvisioningPlan(compatibilityWithCurrentRequest, + referenceOperation.getProvisioningContext(), monitor); + return res; + } + + private static IProfileChangeRequest toCurrentJREOperation(ProfileChangeOperation operation, + IInstallableUnit currnetJREUnit) { + IProfileChangeRequest initialRequest = operation.getProfileChangeRequest(); + if (initialRequest == null) { + throw new IllegalStateException("operation plan must be resolved"); //$NON-NLS-1$ + } + IProfileChangeRequest res = ((ProfileChangeRequest) initialRequest).clone(); + res.addExtraRequirements(Collections.singleton(MetadataFactory + .createRequirement(IInstallableUnit.NAMESPACE_IU_ID, "a.jre.javase", null, null, 0, 0, false))); //$NON-NLS-1$ + operation.getProvisioningPlan().getProfile().query(QueryUtil.createIUQuery("a.jre.javase"), null) //$NON-NLS-1$ + .forEach(res::remove); + res.add(currnetJREUnit); + return res; + } + + private static IInstallableUnit createCurrentJavaSEUnit() { + InstallableUnitDescription desc = new InstallableUnitDescription(); + desc.setId("currently-running-execution-environement-do-not-actually-install"); //$NON-NLS-1$ + Version eeVersion = getCurrentJavaSEVersion(); + desc.setVersion(eeVersion); + desc.addProvidedCapabilities(Collections + .singletonList(new ProvidedCapability(IInstallableUnit.NAMESPACE_IU_ID, desc.getId(), eeVersion))); + desc.addProvidedCapabilities(parseSystemCapabilities(Constants.FRAMEWORK_SYSTEMCAPABILITIES)); + desc.addProvidedCapabilities(parseSystemCapabilities(Constants.FRAMEWORK_SYSTEMCAPABILITIES_EXTRA)); + desc.addProvidedCapabilities(toJavaPackageCapabilities(Constants.FRAMEWORK_SYSTEMPACKAGES)); + desc.addProvidedCapabilities(toJavaPackageCapabilities(Constants.FRAMEWORK_SYSTEMPACKAGES_EXTRA)); + return MetadataFactory.createInstallableUnit(desc); + } + + private static List toJavaPackageCapabilities(String systemPropertyName) { + String packages = System.getProperty(systemPropertyName); + if (packages != null && !packages.trim().isEmpty()) { + try { + return Arrays.stream(ManifestElement.parseHeader(systemPropertyName, packages)) // + .map(jrePackage -> { + String packageName = jrePackage.getValue(); + Version packageVersion = Version.create(jrePackage.getAttribute("version")); //$NON-NLS-1$ + return MetadataFactory.createProvidedCapability("java.package", packageName, //$NON-NLS-1$ + packageVersion); + }).collect(Collectors.toList()); + } catch (BundleException e) { + ProvUIActivator.getDefault().getLog() + .log(new Status(IStatus.ERROR, ProvUIActivator.PLUGIN_ID, e.getMessage(), e)); + } + } + return Collections.emptyList(); + } + + private static Version getCurrentJavaSEVersion() { + String[] segments = System.getProperty("java.version").split("\\."); //$NON-NLS-1$ //$NON-NLS-2$ + if ("1".equals(segments[0])) { //$NON-NLS-1$ + return Version.create(segments[0] + '.' + segments[1] + ".0"); //$NON-NLS-1$ + } + return Version.create(segments[0].split("-")[0] + ".0.0"); //$NON-NLS-1$ //$NON-NLS-2$ + } + + static Collection parseSystemCapabilities(String systemProperty) { + String systemCapabilities = System.getProperty(systemProperty); + if (systemCapabilities == null || systemCapabilities.trim().isEmpty()) { + return Collections.emptyList(); + } + try { + return Arrays.stream(ManifestElement.parseHeader(systemProperty, systemCapabilities)) // + .flatMap(eeCapability -> { + String eeName = eeCapability.getAttribute("osgi.ee"); //$NON-NLS-1$ + if (eeName == null) { + return Stream.empty(); + } + return parseEECapabilityVersion(eeCapability) // + .map(version -> MetadataFactory.createProvidedCapability("osgi.ee", eeName, version)); //$NON-NLS-1$ + }).collect(Collectors.toList()); + } catch (BundleException e) { + ProvUIActivator.getDefault().getLog() + .log(new Status(IStatus.ERROR, ProvUIActivator.PLUGIN_ID, e.getMessage(), e)); + return Collections.emptyList(); + } + } + + private static Stream parseEECapabilityVersion(ManifestElement eeCapability) { + String singleVersion = eeCapability.getAttribute("version:Version"); //$NON-NLS-1$ + String[] multipleVersions = ManifestElement + .getArrayFromList(eeCapability.getAttribute("version:List")); //$NON-NLS-1$ + + if (singleVersion == null && multipleVersions == null) { + return Stream.empty(); + } else if (singleVersion == null) { + return Arrays.stream(multipleVersions).map(Version::parseVersion); + } else if (multipleVersions == null) { + return Stream.of(singleVersion).map(Version::parseVersion); + } + return Stream.empty(); + } + +} diff --git a/tycho-its/projects/api-tools/missing-bin/org.eclipse.equinox.p2.ui/src/org/eclipse/equinox/internal/p2/ui/ProvUIActivator.java b/tycho-its/projects/api-tools/missing-bin/org.eclipse.equinox.p2.ui/src/org/eclipse/equinox/internal/p2/ui/ProvUIActivator.java new file mode 100644 index 0000000000..f26a6c0acb --- /dev/null +++ b/tycho-its/projects/api-tools/missing-bin/org.eclipse.equinox.p2.ui/src/org/eclipse/equinox/internal/p2/ui/ProvUIActivator.java @@ -0,0 +1,136 @@ +/******************************************************************************* + * Copyright (c) 2007, 2018 IBM Corporation and others. + * + * This program and the accompanying materials + * are made available under the terms of the Eclipse Public License 2.0 + * which accompanies this distribution, and is available at + * https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + * + * Contributors: + * IBM Corporation - initial API and implementation + * Red Hat, Inc. - support for remediation page, Bug 460967 + *******************************************************************************/ +package org.eclipse.equinox.internal.p2.ui; + +import java.net.URL; +import org.eclipse.core.runtime.*; +import org.eclipse.core.runtime.jobs.Job; +import org.eclipse.equinox.internal.p2.core.helpers.ServiceHelper; +import org.eclipse.equinox.internal.p2.core.helpers.Tracing; +import org.eclipse.equinox.p2.core.IProvisioningAgent; +import org.eclipse.equinox.p2.engine.IProfileRegistry; +import org.eclipse.equinox.p2.operations.ProvisioningSession; +import org.eclipse.equinox.p2.ui.*; +import org.eclipse.jface.resource.ImageDescriptor; +import org.eclipse.jface.resource.ImageRegistry; +import org.eclipse.ui.plugin.AbstractUIPlugin; +import org.osgi.framework.BundleContext; + +/** + * Controls the lifecycle of the provisioning UI bundle + * + * @since 3.4 + */ +public class ProvUIActivator extends AbstractUIPlugin { + private static BundleContext context; + private static ProvUIActivator plugin; + public static final String PLUGIN_ID = "org.eclipse.equinox.p2.ui"; //$NON-NLS-1$ + + private ProvisioningSession session; + private ProvisioningUI ui; + + public static BundleContext getContext() { + return context; + } + + /** + * Returns the singleton plugin instance + * + * @return the instance + */ + public static ProvUIActivator getDefault() { + return plugin; + } + + public ProvUIActivator() { + // do nothing + } + + @Override + public void start(BundleContext bundleContext) throws Exception { + super.start(bundleContext); + + plugin = this; + ProvUIActivator.context = bundleContext; + } + + @Override + public void stop(BundleContext bundleContext) throws Exception { + try { + // cancel any repository load jobs started in the UI + Job.getJobManager().cancel(LoadMetadataRepositoryJob.LOAD_FAMILY); + // See https://bugs.eclipse.org/bugs/show_bug.cgi?id=305163 + // join the jobs so that this bundle does not stop until the jobs are + // actually cancelled. + Job.getJobManager().join(LoadMetadataRepositoryJob.LOAD_FAMILY, new NullProgressMonitor()); + plugin = null; + ProvUIActivator.context = null; + ui = null; + } finally { + super.stop(bundleContext); + } + } + + @Override + protected void initializeImageRegistry(ImageRegistry reg) { + createImageDescriptor(ProvUIImages.IMG_METADATA_REPOSITORY, reg); + createImageDescriptor(ProvUIImages.IMG_ARTIFACT_REPOSITORY, reg); + createImageDescriptor(ProvUIImages.IMG_IU, reg); + createImageDescriptor(ProvUIImages.IMG_DISABLED_IU, reg); + createImageDescriptor(ProvUIImages.IMG_UPDATED_IU, reg); + createImageDescriptor(ProvUIImages.IMG_ADDED_OVERLAY, reg); + createImageDescriptor(ProvUIImages.IMG_REMOVED_OVERLAY, reg); + createImageDescriptor(ProvUIImages.IMG_UPGRADED_IU, reg); + createImageDescriptor(ProvUIImages.IMG_DOWNGRADED_IU, reg); + createImageDescriptor(ProvUIImages.IMG_PATCH_IU, reg); + createImageDescriptor(ProvUIImages.IMG_DISABLED_PATCH_IU, reg); + createImageDescriptor(ProvUIImages.IMG_CATEGORY, reg); + createImageDescriptor(ProvUIImages.IMG_PROFILE, reg); + createImageDescriptor(ProvUIImages.IMG_INFO, reg); + createImageDescriptor(ProvUIImages.IMG_ADDED, reg); + createImageDescriptor(ProvUIImages.IMG_REMOVED, reg); + createImageDescriptor(ProvUIImages.IMG_CHANGED, reg); + createImageDescriptor(ProvUIImages.IMG_NOTADDED, reg); + createImageDescriptor(ProvUIImages.IMG_COPY, reg); + createImageDescriptor(ProvUIImages.WIZARD_BANNER_INSTALL, reg); + createImageDescriptor(ProvUIImages.WIZARD_BANNER_REVERT, reg); + createImageDescriptor(ProvUIImages.WIZARD_BANNER_UNINSTALL, reg); + createImageDescriptor(ProvUIImages.WIZARD_BANNER_UPDATE, reg); + } + + /** + * Creates the specified image descriptor and registers it + */ + private void createImageDescriptor(String id, ImageRegistry reg) { + URL url = FileLocator.find(getBundle(), IPath.fromOSString(ProvUIImages.ICON_PATH + id), null); + ImageDescriptor desc = ImageDescriptor.createFromURL(url); + reg.put(id, desc); + } + + public ProvisioningUI getProvisioningUI() { + if (Tracing.DEBUG_DEFAULT_UI) + Tracing.debug("Falling back to default provisioning UI"); //$NON-NLS-1$ + + if (ui == null) { + IProvisioningAgent agent = ServiceHelper.getService(getContext(), IProvisioningAgent.class); + session = new ProvisioningSession(agent); + Policy policy = ServiceHelper.getService(ProvUIActivator.getContext(), Policy.class); + if (policy == null) + policy = new Policy(); + ui = new ProvisioningUI(session, IProfileRegistry.SELF, policy); + } + return ui; + } +} diff --git a/tycho-its/projects/api-tools/missing-bin/org.eclipse.equinox.p2.ui/src/org/eclipse/equinox/internal/p2/ui/ProvUIAdapterFactory.java b/tycho-its/projects/api-tools/missing-bin/org.eclipse.equinox.p2.ui/src/org/eclipse/equinox/internal/p2/ui/ProvUIAdapterFactory.java new file mode 100644 index 0000000000..45e5ae4cbe --- /dev/null +++ b/tycho-its/projects/api-tools/missing-bin/org.eclipse.equinox.p2.ui/src/org/eclipse/equinox/internal/p2/ui/ProvUIAdapterFactory.java @@ -0,0 +1,44 @@ +/******************************************************************************* + * Copyright (c) 2007, 2015 IBM Corporation and others. + * + * This program and the accompanying materials + * are made available under the terms of the Eclipse Public License 2.0 + * which accompanies this distribution, and is available at + * https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + * + * Contributors: + * IBM Corporation - initial API and implementation + * Red Hat Inc. - Fix compiler problems from generified IAdaptable#getAdapter + *******************************************************************************/ +package org.eclipse.equinox.internal.p2.ui; + +import org.eclipse.core.runtime.IAdapterFactory; +import org.eclipse.equinox.p2.engine.IProfile; +import org.eclipse.equinox.p2.metadata.IInstallableUnit; +import org.eclipse.equinox.p2.repository.IRepository; +import org.eclipse.equinox.p2.repository.artifact.IArtifactRepository; +import org.eclipse.equinox.p2.repository.metadata.IMetadataRepository; + +/** + * Adapter factory for provisioning elements + * + * @since 3.4 + * + */ + +public class ProvUIAdapterFactory implements IAdapterFactory { + private static final Class[] CLASSES = new Class[] {IInstallableUnit.class, IProfile.class, IRepository.class, IMetadataRepository.class, IArtifactRepository.class}; + + @Override + public T getAdapter(Object adaptableObject, Class adapterType) { + return ProvUI.getAdapter(adaptableObject, adapterType); + } + + @Override + public Class[] getAdapterList() { + return CLASSES; + } + +} diff --git a/tycho-its/projects/api-tools/missing-bin/org.eclipse.equinox.p2.ui/src/org/eclipse/equinox/internal/p2/ui/ProvUIImages.java b/tycho-its/projects/api-tools/missing-bin/org.eclipse.equinox.p2.ui/src/org/eclipse/equinox/internal/p2/ui/ProvUIImages.java new file mode 100644 index 0000000000..a60edbaa57 --- /dev/null +++ b/tycho-its/projects/api-tools/missing-bin/org.eclipse.equinox.p2.ui/src/org/eclipse/equinox/internal/p2/ui/ProvUIImages.java @@ -0,0 +1,92 @@ +/******************************************************************************* + * Copyright (c) 2007, 2013 IBM Corporation and others. + * + * This program and the accompanying materials + * are made available under the terms of the Eclipse Public License 2.0 + * which accompanies this distribution, and is available at + * https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + * + * Contributors: + * IBM Corporation - initial API and implementation + * Red Hat, Inc. - support for remediation page + *******************************************************************************/ +package org.eclipse.equinox.internal.p2.ui; + +import org.eclipse.jface.resource.ImageDescriptor; +import org.eclipse.swt.graphics.Image; + +/** + * ProvUIImages provides convenience methods for accessing shared images + * provided by the org.eclipse.equinox.internal.provisional.p2.ui plug-in. + *

+ * This class provides ImageDescriptors for each named image in + * {@link ProvUIImages}. All Image objects created from the + * provided descriptors are managed the caller and must be disposed + * appropriately. + *

+ *

+ * This class is not intended to be subclassed or instantiated by clients + * + * @since 3.4 + * @noextend This class is not intended to be subclassed by clients. + * @noinstantiate This class is not intended to be instantiated by clients. + */ +public class ProvUIImages { + + // bundle-relative icon path + public final static String ICON_PATH = "$nl$/icons/"; //$NON-NLS-1$ + //objects + public final static String IMG_ARTIFACT_REPOSITORY = "obj/artifact_repo_obj.png"; //$NON-NLS-1$ + public final static String IMG_METADATA_REPOSITORY = "obj/metadata_repo_obj.png"; //$NON-NLS-1$ + public final static String IMG_IU = "obj/iu_obj.png"; //$NON-NLS-1$ + public final static String IMG_DISABLED_IU = "obj/iu_disabled_obj.png"; //$NON-NLS-1$ + public final static String IMG_ADDED = "obj/iu_add.png"; //$NON-NLS-1$ + public final static String IMG_REMOVED = "obj/iu_remove.png"; //$NON-NLS-1$ + public final static String IMG_CHANGED = "obj/iu_update_obj.png"; //$NON-NLS-1$ + public final static String IMG_NOTADDED = "obj/iu_notadd.png"; //$NON-NLS-1$ + + public final static String IMG_UPDATED_IU = "obj/iu_update_obj.png"; //$NON-NLS-1$ + public final static String IMG_UPGRADED_IU = "obj/iu_upgraded.png"; //$NON-NLS-1$ + public final static String IMG_DOWNGRADED_IU = "obj/iu_downgraded.png"; //$NON-NLS-1$ + public final static String IMG_ADDED_OVERLAY = "ovr/added_overlay.png"; //$NON-NLS-1$ + public final static String IMG_REMOVED_OVERLAY = "ovr/removed_overlay.png"; //$NON-NLS-1$ + public final static String IMG_PATCH_IU = "obj/iu_patch_obj.png"; //$NON-NLS-1$ + public final static String IMG_DISABLED_PATCH_IU = "obj/iu_disabled_patch_obj.png"; //$NON-NLS-1$ + public final static String IMG_PROFILE = "obj/profile_obj.png"; //$NON-NLS-1$ + public final static String IMG_CATEGORY = "obj/category_obj.png"; //$NON-NLS-1$ + public final static String IMG_INFO = "obj/iu_info.png"; //$NON-NLS-1$ + public final static String IMG_COPY = "obj/copy_edit.png"; //$NON-NLS-1$ + + // wizard graphics + public final static String WIZARD_BANNER_INSTALL = "wizban/install_wiz.png"; //$NON-NLS-1$ + public final static String WIZARD_BANNER_UNINSTALL = "wizban/uninstall_wiz.png"; //$NON-NLS-1$ + public final static String WIZARD_BANNER_UPDATE = "wizban/update_wiz.png"; //$NON-NLS-1$ + public final static String WIZARD_BANNER_REVERT = "wizban/revert_wiz.png"; //$NON-NLS-1$ + + /** + * Returns the image descriptor for the given image ID. Returns + * null if there is no such image. + * + * @param id + * the identifier for the image to retrieve + * @return the image descriptor associated with the given ID + */ + public static ImageDescriptor getImageDescriptor(String id) { + return ProvUIActivator.getDefault().getImageRegistry().getDescriptor(id); + } + + /** + * Returns the image for the given image ID. Returns null if + * there is no such image. + * + * @param id + * the identifier for the image to retrieve + * @return the image associated with the given ID. This image is managed in + * an image registry and should not be freed by the client. + */ + public static Image getImage(String id) { + return ProvUIActivator.getDefault().getImageRegistry().get(id); + } +} diff --git a/tycho-its/projects/api-tools/missing-bin/org.eclipse.equinox.p2.ui/src/org/eclipse/equinox/internal/p2/ui/ProvUIMessages.java b/tycho-its/projects/api-tools/missing-bin/org.eclipse.equinox.p2.ui/src/org/eclipse/equinox/internal/p2/ui/ProvUIMessages.java new file mode 100644 index 0000000000..cc4398f4e3 --- /dev/null +++ b/tycho-its/projects/api-tools/missing-bin/org.eclipse.equinox.p2.ui/src/org/eclipse/equinox/internal/p2/ui/ProvUIMessages.java @@ -0,0 +1,370 @@ +/******************************************************************************* + * Copyright (c) 2007, 2018 IBM Corporation and others. + * + * This program and the accompanying materials + * are made available under the terms of the Eclipse Public License 2.0 + * which accompanies this distribution, and is available at + * https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + * + * Contributors: + * IBM Corporation - initial API and implementation + * Red Hat, Inc - support for remediation page + *******************************************************************************/ + +package org.eclipse.equinox.internal.p2.ui; + +import org.eclipse.osgi.util.NLS; + +/** + * Message class for provisioning UI messages. + * + * @since 3.4 + */ +public class ProvUIMessages extends NLS { + private static final String BUNDLE_NAME = "org.eclipse.equinox.internal.p2.ui.messages"; //$NON-NLS-1$ + static { + // load message values from bundle file + NLS.initializeMessages(BUNDLE_NAME, ProvUIMessages.class); + } + + public static String AcceptLicensesWizardPage_AcceptMultiple; + public static String AcceptLicensesWizardPage_AcceptSingle; + public static String AcceptLicensesWizardPage_ItemsLabel; + public static String AcceptLicensesWizardPage_LicenseTextLabel; + public static String AcceptLicensesWizardPage_NoLicensesDescription; + public static String AcceptLicensesWizardPage_RejectMultiple; + public static String AcceptLicensesWizardPage_RejectSingle; + public static String AcceptLicensesWizardPage_ReviewExtraLicensesDescription; + public static String AcceptLicensesWizardPage_ReviewLicensesDescription; + public static String AcceptLicensesWizardPage_SingleLicenseTextLabel; + public static String AcceptLicensesWizardPage_Title; + public static String ApplicationInRestartDialog; + public static String ApplyProfileChangesDialog_ApplyChanges; + public static String ApplyProfileChangesDialog_Restart; + public static String ApplyProfileChangesDialog_NotYet; + public static String ColocatedRepositoryManipulator_AddSiteOperationLabel; + public static String ColocatedRepositoryTracker_PromptForSiteLocationEdit; + public static String ColocatedRepositoryTracker_SiteNotFoundTitle; + public static String ColocatedRepositoryTracker_SiteNotFound_EditButtonLabel; + public static String RevertProfilePage_ConfirmDeleteMultipleConfigs; + public static String RevertProfilePage_ConfirmDeleteSingleConfig; + public static String RevertProfilePage_Delete; + public static String RevertProfilePage_CancelButtonLabel; + public static String RevertProfilePage_DeleteMultipleConfigurationsTitle; + public static String RevertProfilePage_DeleteSingleConfigurationTitle; + public static String RevertProfilePage_DeleteTooltip; + public static String RevertProfilePage_NoProfile; + public static String RevertProfilePage_RevertLabel; + public static String RevertProfilePage_RevertTooltip; + public static String RevertProfilePage_CompareLabel; + public static String RevertProfilePage_CompareTooltip; + public static String RevertProfilePage_ProfileTagColumn; + public static String RevertProfilePage_ProfileTimestampColumn; + public static String IUCopyrightPropertyPage_NoCopyright; + public static String IUCopyrightPropertyPage_ViewLinkLabel; + public static String IUDetailsLabelProvider_KB; + public static String IUDetailsLabelProvider_Bytes; + public static String IUDetailsLabelProvider_ComputingSize; + public static String IUDetailsLabelProvider_Unknown; + public static String IUGeneralInfoPropertyPage_ContactLabel; + public static String IUGeneralInfoPropertyPage_CouldNotOpenBrowser; + public static String IUGeneralInfoPropertyPage_DescriptionLabel; + public static String IUGeneralInfoPropertyPage_DocumentationLink; + public static String IUGeneralInfoPropertyPage_IdentifierLabel; + public static String IUGeneralInfoPropertyPage_NameLabel; + public static String IUGeneralInfoPropertyPage_ProviderLabel; + public static String IUGeneralInfoPropertyPage_VersionLabel; + public static String IULicensePropertyPage_NoLicense; + public static String IULicensePropertyPage_ViewLicenseLabel; + public static String PGPPublicKeyViewDialog_Title; + public static String ProfileModificationAction_InvalidSelections; + public static String ProfileModificationWizardPage_DetailsLabel; + public static String ProfileSnapshots_Label; + + // viewer support + public static String ProvDropAdapter_InvalidDropTarget; + public static String ProvDropAdapter_NoIUsToDrop; + public static String ProvDropAdapter_UnsupportedDropOperation; + public static String ProvElementContentProvider_FetchJobTitle; + + // Provisioning operations + public static String ProvisioningOperationRunner_CannotApplyChanges; + public static String ProvisioningOperationWizard_Remediation_Operation; + public static String ProvisioningOperationWizard_UnexpectedFailureToResolve; + public static String InstalledSoftwarePage_Filter_Installed_Software; + public static String InstalledSoftwarePage_NoProfile; + public static String InstallIUOperationLabel; + public static String InstallIUOperationTask; + public static String InstallIUCommandLabel; + public static String InstallIUCommandTooltip; + public static String InstallWizardPage_NoCheckboxDescription; + public static String InstallWizardPage_Title; + public static String PreselectedIUInstallWizard_Title; + public static String PreselectedIUInstallWizard_Description; + public static String UninstallDialog_UninstallMessage; + public static String UninstallIUOperationLabel; + public static String UninstallIUOperationTask; + public static String UninstallIUCommandLabel; + public static String UninstallIUCommandTooltip; + public static String UninstallIUProgress; + public static String UninstallWizardPage_Description; + public static String UninstallWizardPage_Title; + public static String UpdateIUOperationLabel; + public static String UpdateIUOperationTask; + public static String UpdateIUCommandLabel; + public static String UpdateIUCommandTooltip; + public static String UpdateIUProgress; + public static String RefreshAction_Label; + public static String RefreshAction_Tooltip; + public static String RemoveColocatedRepositoryAction_Label; + public static String RemoveColocatedRepositoryAction_Tooltip; + public static String RevertIUCommandLabel; + public static String RevertIUCommandTooltip; + + // Property pages + public static String IUPropertyPage_NoIUSelected; + + public static String RepositoryDetailsLabelProvider_Disabled; + public static String RepositoryDetailsLabelProvider_Enabled; + // Dialog groups + public static String RepositoryGroup_LocalRepoBrowseButton; + public static String RepositoryGroup_ArchivedRepoBrowseButton; + public static String RepositoryGroup_RepositoryFile; + public static String RepositoryGroup_SelectRepositoryDirectory; + public static String RepositoryGroup_URLRequired; + public static String RepositoryManipulationPage_Add; + public static String RepositoryManipulationPage_ContactingSiteMessage; + public static String RepositoryManipulationPage_DefaultFilterString; + public static String RepositoryManipulationPage_Description; + public static String RepositoryManipulationPage_DisableButton; + public static String RepositoryManipulationPage_EnableButton; + public static String RepositoryManipulationPage_EnabledColumnTitle; + public static String RepositoryManipulationPage_Export; + public static String RepositoryManipulationPage_Import; + public static String RepositoryManipulationPage_LocationColumnTitle; + public static String RepositoryManipulationPage_NameColumnTitle; + public static String RepositoryManipulationPage_Edit; + public static String RepositoryManipulationPage_RefreshConnection; + public static String RepositoryManipulationPage_RefreshOperationCanceled; + public static String RepositoryManipulationPage_Remove; + public static String RepositoryManipulationPage_RemoveConfirmMessage; + public static String RepositoryManipulationPage_RemoveConfirmSingleMessage; + public static String RepositoryManipulationPage_RemoveConfirmTitle; + public static String RepositoryManipulationPage_TestConnectionSuccess; + public static String RepositoryManipulationPage_TestConnectionTitle; + public static String RepositoryManipulationPage_Title; + public static String RepositoryManipulationPage_Manage; + public static String RepositoryManipulatorDropTarget_DragAndDropJobLabel; + public static String RepositoryManipulatorDropTarget_DragSourceNotValid; + public static String RepositoryNameAndLocationDialog_Title; + + public static String RepositorySelectionGroup_NameAndLocationSeparator; + public static String ResolutionWizardPage_Canceled; + public static String ResolutionWizardPage_ErrorStatus; + public static String ResolutionWizardPage_NoSelections; + public static String ResolutionWizardPage_WarningInfoStatus; + public static String ResolutionWizardPage_RelaxedConstraints; + public static String ResolutionWizardPage_RelaxedConstraintsTip; + public static String ResolutionStatusPage_ErrorIULocked; + + // Dialogs + public static String AddRepositoryDialog_InvalidURL; + public static String AddRepositoryDialog_LocationLabel; + public static String AddRepositoryDialog_NameLabel; + public static String AddRepositoryDialog_Title; + public static String AddRepositoryDialog_addButtonLabel; + public static String AvailableIUGroup_LoadingRepository; + public static String AvailableIUGroup_NoSitesConfiguredDescription; + public static String AvailableIUGroup_NoSitesConfiguredExplanation; + public static String ColocatedRepositoryManipulator_NoContentExplanation; + public static String AvailableIUGroup_NoSitesExplanation; + public static String AvailableIUsPage_AddButton; + public static String AvailableIUsPage_AllSites; + public static String AvailableIUsPage_Description; + public static String AvailableIUsPage_FilterOnEnvCheckBox; + public static String AvailableIUsPage_GotoInstallInfo; + public static String AvailableIUsPage_GotoProperties; + public static String AvailableIUsPage_GroupByCategory; + public static String AvailableIUsPage_HideInstalledItems; + public static String AvailableIUsPage_LocalSites; + public static String AvailableIUsPage_MultipleSelectionCount; + public static String AvailableIUsPage_NameWithLocation; + public static String AvailableIUsPage_NoSites; + public static String AvailableIUsPage_RepoFilterInstructions; + public static String AvailableIUsPage_RepoFilterLabel; + public static String AvailableIUsPage_ResolveAllCheckbox; + public static String AvailableIUsPage_SelectASite; + public static String AvailableIUsPage_ShowLatestVersions; + public static String AvailableIUsPage_SingleSelectionCount; + public static String AvailableIUsPage_Title; + public static String AvailableIUsPage_Fetching; + public static String AvailableIUWrapper_AllAreInstalled; + public static String IUViewQueryContext_AllAreInstalledDescription; + public static String Label_Profiles; + public static String Label_Repositories; + public static String LaunchUpdateManagerButton; + public static String LoadMetadataRepositoryJob_ContactSitesProgress; + public static String LoadMetadataRepositoryJob_SitesMissingError; + public static String RepositoryElement_NotFound; + public static String RepositoryTracker_DuplicateLocation; + public static String MetadataRepositoryElement_RepositoryLoadError; + public static String UpdateAction_UpdatesAvailableMessage; + public static String UpdateAction_UpdatesAvailableTitle; + public static String UpdateActionRemediationJobName; + public static String UpdateActionRemediationJobTask; + public static String PlatformUpdateTitle; + public static String PlatformRestartMessage; + public static String Policy_RequiresUpdateManagerMessage; + public static String Policy_RequiresUpdateManagerTitle; + public static String ProvUI_ErrorDuringApplyConfig; + public static String ProvUI_InformationTitle; + public static String ProvUI_InstallDialogError; + public static String ProvUI_NameColumnTitle; + public static String ProvUI_IdColumnTitle; + public static String ProvUI_ProviderColumnTitle; + public static String ProvUI_VersionColumnTitle; + public static String ProvUI_WarningTitle; + public static String ProvUIMessages_NotAccepted_EnterFor_0; + public static String ProvUIMessages_SavedNotAccepted_EnterFor_0; + public static String OptionalPlatformRestartMessage; + public static String IUViewQueryContext_NoCategorizedItemsDescription; + public static String QueriedElementWrapper_NoCategorizedItemsExplanation; + public static String QueriedElementWrapper_NoItemsExplanation; + public static String QueriedElementWrapper_SiteNotFound; + public static String QueryableMetadataRepositoryManager_LoadRepositoryProgress; + public static String QueryableProfileRegistry_QueryProfileProgress; + public static String QueryableUpdates_UpdateListProgress; + public static String SizeComputingWizardPage_SizeJobTitle; + public static String RevertDialog_ConfigContentsLabel; + public static String RevertDialog_ConfigsLabel; + public static String RevertDialog_ConfirmRestartMessage; + public static String RevertDialog_RevertOperationLabel; + public static String RevertDialog_Title; + public static String RevertDialog_CancelButtonLabel; + public static String RollbackProfileElement_CurrentInstallation; + public static String SelectableIUsPage_Select_All; + public static String SelectableIUsPage_Deselect_All; + public static String InstallRemediationPage_Title; + public static String InstallRemediationPage_Description; + public static String KeySigningInfoFactory_FingerprintItem; + public static String KeySigningInfoFactory_KeySignersSection; + public static String KeySigningInfoFactory_PGPSigningType; + public static String KeySigningInfoFactory_UserIDItem; + public static String UpdateRemediationPage_Title; + public static String UpdateRemediationPage_Description; + public static String RemediationPage_SubDescription; + public static String RemediationPage_NoSolutionFound; + public static String RemediationPage_BeingInstalledSection; + public static String RemediationPage_InstalledSection; + public static String RemediationPage_BeingInstalledSection_AllowPartialInstall; + public static String RemediationPage_BeingInstalledSection_AllowDifferentVersion; + public static String RemediationPage_InstalledSection_AllowInstalledUpdate; + public static String RemediationPage_InstalledSection_AllowInstalledRemoval; + public static String RemediationPage_BestSolutionBeingInstalledRelaxed; + public static String RemediationPage_BestSolutionInstallationRelaxed; + public static String RemediationPage_BestSolutionBuilt; + public static String RemediationPage_SolutionDetails; + public static String RemedyCategoryAdded; + public static String RemedyCategoryRemoved; + public static String RemedyCategoryChanged; + public static String RemedyCategoryNotAdded; + public static String RemedyElementInstalledVersion; + public static String RemedyElementRequestedVersion; + public static String RemedyElementBeingInstalledVersion; + public static String RemedyElementNotHighestVersion; + + public static String TrustAuthorityDialog_AcceptTrustAllAuthorities; + public static String TrustAuthorityDialog_AuthoritiesCollapseAllButton; + public static String TrustAuthorityDialog_AuthoritiesDeselectAllButton; + public static String TrustAuthorityDialog_AuthoritiesExpandAllButton; + public static String TrustAuthorityDialog_AuthoritiesSelectAllButton; + public static String TrustAuthorityDialog_AuthorityColumnTitle; + public static String TrustAuthorityDialog_AuthorityCopyLinkMenu; + public static String TrustAuthorityDialog_AuthorityInsecure; + public static String TrustAuthorityDialog_AuthoritySecure; + public static String TrustAuthorityDialog_CertificateDetailsButton; + public static String TrustAuthorityDialog_CertificateExportButton; + public static String TrustAuthorityDialog_ComputingAuthorityCertficate; + public static String TrustAuthorityDialog_ExportDialogTitle; + public static String TrustAuthorityDialog_IUColumnTitle; + public static String TrustAuthorityDialog_IUDetailDialogDescriptionMessage; + public static String TrustAuthorityDialog_IUDetailsButton; + public static String TrustAuthorityDialog_IUDetailsDialogCountMessage; + public static String TrustAuthorityDialog_IUDetailsDialogTitle; + public static String TrustAuthorityDialog_IUVersionColumnTitle; + public static String TrustAuthorityDialog_RejectTrustAllAuthorities; + public static String TrustAuthorityDialog_RememberSelectedAuthoritiesCheckbox; + public static String TrustAuthorityDialog_SecuredColumnTitle; + public static String TrustAuthorityDialog_TrustAllAuthoritiesCheckbox; + public static String TrustAuthorityDialog_TrustAllAuthoritiesConfirmationDescription; + public static String TrustAuthorityDialog_TrustAllAuthoritiesConfirmationTitle; + public static String TrustAuthorityDialog_TrustAuthoritiesTitle; + public static String TrustAuthorityDialog_TrustAuthorityDescriptionMessage; + public static String TrustAuthorityDialog_TrustAuthorityMainMessage; + public static String TrustAuthorityDialog_TrustInsecureAuthorityMessage; + public static String TrustAuthorityDialog_TrustSelectedCheckbox; + public static String TrustAuthorityDialog_UnitsColumnTitle; + + public static String TrustCertificateDialog_Details; + public static String TrustCertificateDialog_Export; + public static String TrustCertificateDialog_ExportDialogTitle; + public static String TrustCertificateDialog_Title; + public static String TrustCertificateDialog_Message; + public static String TrustCertificateDialog_MessageUnsigned; + public static String TrustCertificateDialog_MessageNameWarning; + public static String TrustCertificateDialog_MessagePGP; + public static String TrustCertificateDialog_MessageRevoked; + public static String TrustCertificateDialog_AcceptSelectedButtonLabel; + public static String TrustCertificateDialog_AlwaysTrust; + public static String TrustCertificateDialog_AlwaysTrustConfirmationMessage; + public static String TrustCertificateDialog_AlwaysTrustConfirmationTitle; + public static String TrustCertificateDialog_AlwaysTrustNo; + public static String TrustCertificateDialog_AlwaysTrustYes; + public static String TrustCertificateDialog_ArtifactId; + public static String TrustCertificateDialog_SelectAll; + public static String TrustCertificateDialog_DeselectAll; + public static String TrustCertificateDialog_ObjectType; + public static String TrustCertificateDialog_Id; + public static String TrustCertificateDialog_Name; + public static String TrustCertificateDialog_Classifier; + public static String TrustCertificateDialog_CopyFingerprint; + public static String TrustCertificateDialog_dates; + public static String TrustCertificateDialog_NotApplicable; + public static String TrustCertificateDialog_NotYetValidStartDate; + public static String TrustCertificateDialog_expiredSince; + public static String TrustCertificateDialog_validExpires; + public static String TrustCertificateDialog_valid; + public static String TrustCertificateDialog_expired; + public static String TrustCertificateDialog_notYetValid; + public static String TrustCertificateDialog_RememberSigners; + public static String TrustCertificateDialog_revoked; + public static String TrustCertificateDialog_Unknown; + public static String TrustCertificateDialog_Unsigned; + public static String TrustCertificateDialog_Version; + public static String TrustCertificateDialogQuestionTrustRevokedKeyAccept; + public static String TrustCertificateDialogQuestionTrustRevokedKeyQuestion; + public static String TrustCertificateDialogQuestionTrustRevokedKeyReject; + public static String TrustCertificateDialogQuestionTrustRevokedKeyTitle; + // Operations + public static String UpdateManagerCompatibility_ExportSitesTitle; + public static String UpdateManagerCompatibility_ImportSitesTitle; + public static String UpdateManagerCompatibility_InvalidSiteFileMessage; + public static String UpdateManagerCompatibility_InvalidSitesTitle; + public static String UpdateManagerCompatibility_ItemRequiresUpdateManager; + public static String UpdateManagerCompatibility_UnableToOpenFindAndInstall; + public static String ServiceUI_LoginDetails; + public static String ServiceUI_LoginRequired; + public static String ServiceUI_unsigned_message; + public static String ServiceUI_warning_title; + public static String ServiceUI_InstallAnywayAction_Label; + public static String UpdateOrInstallWizardPage_Size; + public static String Updates_Label; + public static String UpdateSingleIUPage_SingleUpdateDescription; + public static String UpdateWizardPage_Description; + public static String UpdateWizardPage_Title; + public static String UserValidationDialog_PasswordLabel; + public static String UserValidationDialog_SavePasswordButton; + public static String UserValidationDialog_UsernameLabel; +} diff --git a/tycho-its/projects/api-tools/missing-bin/org.eclipse.equinox.p2.ui/src/org/eclipse/equinox/internal/p2/ui/ProvUIProvisioningListener.java b/tycho-its/projects/api-tools/missing-bin/org.eclipse.equinox.p2.ui/src/org/eclipse/equinox/internal/p2/ui/ProvUIProvisioningListener.java new file mode 100644 index 0000000000..61d82adf30 --- /dev/null +++ b/tycho-its/projects/api-tools/missing-bin/org.eclipse.equinox.p2.ui/src/org/eclipse/equinox/internal/p2/ui/ProvUIProvisioningListener.java @@ -0,0 +1,241 @@ +/******************************************************************************* + * Copyright (c) 2009, 2011 IBM Corporation and others. + * + * This program and the accompanying materials + * are made available under the terms of the Eclipse Public License 2.0 + * which accompanies this distribution, and is available at + * https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + * + * Contributors: + * IBM Corporation - initial API and implementation + *******************************************************************************/ + +package org.eclipse.equinox.internal.p2.ui; + +import java.util.EventObject; +import org.eclipse.equinox.internal.p2.core.helpers.Tracing; +import org.eclipse.equinox.internal.provisional.p2.core.eventbus.SynchronousProvisioningListener; +import org.eclipse.equinox.internal.provisional.p2.repository.RepositoryEvent; +import org.eclipse.equinox.p2.engine.IProfileEvent; +import org.eclipse.equinox.p2.repository.IRepository; + +/** + * ProvisioningListener which handles event batching and other + * extensions to the provisioning event framework that are used by + * the UI. + * + * @since 3.5 + */ +public abstract class ProvUIProvisioningListener implements SynchronousProvisioningListener { + + public static final int PROV_EVENT_METADATA_REPOSITORY = 0x0001; + public static final int PROV_EVENT_IU = 0x0002; + public static final int PROV_EVENT_PROFILE = 0x0004; + public static final int PROV_EVENT_ARTIFACT_REPOSITORY = 0x0008; + + int eventTypes = 0; + String name; + private ProvisioningOperationRunner runner; + + public ProvUIProvisioningListener(String name, int eventTypes, ProvisioningOperationRunner runner) { + this.name = name; + this.eventTypes = eventTypes; + this.runner = runner; + } + + @Override + public void notify(EventObject o) { + if (o instanceof RepositoryOperationBeginningEvent) { + if (Tracing.DEBUG_EVENTS_CLIENT) + Tracing.debug("Batch Eventing: Ignore Following Events. " + getReceiverString()); //$NON-NLS-1$ + } else if (o instanceof RepositoryOperationEndingEvent) { + RepositoryOperationEndingEvent event = (RepositoryOperationEndingEvent) o; + + if (Tracing.DEBUG_EVENTS_CLIENT) + Tracing.debug("Batch Eventing: Batch Ended. " + getReceiverString()); //$NON-NLS-1$ + // A batch operation completed. Refresh. + if (runner.eventBatchCount <= 0) { + if (Tracing.DEBUG_EVENTS_CLIENT) + Tracing.debug("Batch Eventing Complete." + getReceiverString()); //$NON-NLS-1$ + if (event.getEvent() == null && event.update()) { + if (Tracing.DEBUG_EVENTS_CLIENT) { + Tracing.debug("Refreshing After Batch." + getReceiverString()); //$NON-NLS-1$ + } + refreshAll(); + } else if (event.update()) { + if (Tracing.DEBUG_EVENTS_CLIENT) + Tracing.debug("Dispatching Last Event in Batch." + getReceiverString()); //$NON-NLS-1$ + notify(event.getEvent()); + } else if (Tracing.DEBUG_EVENTS_CLIENT) { + Tracing.debug("No Refresh on Batch Complete."); //$NON-NLS-1$ + } + } else { + // We are still in the middle of a batch operation, but we've been notified + // about a nested batch that ended. See if it ended with a specific event. + // If it did, this means there was a user action involving a repository + // (rather than side-effect events). For example, the user might add a repo while a full + // background load is running. We want to honor that + // event. See https://bugs.eclipse.org/bugs/show_bug.cgi?id=305478 + RepositoryEvent innerEvent = event.getEvent(); + if (innerEvent != null) { + handleRepositoryEvent(innerEvent); + } + } + } else if (runner.eventBatchCount > 0) { + // ignore raw events during a batch + if (Tracing.DEBUG_EVENTS_CLIENT) + Tracing.debug(name + " Ignoring: " + o.toString()); //$NON-NLS-1$ + return; + } else if (o instanceof IProfileEvent && (((eventTypes & PROV_EVENT_IU) == PROV_EVENT_IU) || ((eventTypes & PROV_EVENT_PROFILE) == PROV_EVENT_PROFILE))) { + if (Tracing.DEBUG_EVENTS_CLIENT) + Tracing.debug(o.toString() + getReceiverString()); + IProfileEvent event = (IProfileEvent) o; + if (event.getReason() == IProfileEvent.CHANGED) { + profileChanged(event.getProfileId()); + } else if (event.getReason() == IProfileEvent.ADDED) { + profileAdded(event.getProfileId()); + } else if (event.getReason() == IProfileEvent.REMOVED) { + profileRemoved(event.getProfileId()); + } + } else if (o instanceof RepositoryEvent) { + if (Tracing.DEBUG_EVENTS_CLIENT) + Tracing.debug(o.toString() + getReceiverString()); + handleRepositoryEvent((RepositoryEvent) o); + } + } + + private String getReceiverString() { + return " -- <" + name + "> "; //$NON-NLS-1$//$NON-NLS-2$ + } + + private void handleRepositoryEvent(RepositoryEvent event) { + // Do not handle unless this is the type of repo that we are interested in + if ((event.getRepositoryType() == IRepository.TYPE_METADATA && (eventTypes & PROV_EVENT_METADATA_REPOSITORY) == PROV_EVENT_METADATA_REPOSITORY) || (event.getRepositoryType() == IRepository.TYPE_ARTIFACT && (eventTypes & PROV_EVENT_ARTIFACT_REPOSITORY) == PROV_EVENT_ARTIFACT_REPOSITORY)) { + if (event.getKind() == RepositoryEvent.ADDED && event.isRepositoryEnabled()) { + repositoryAdded(event); + } else if (event.getKind() == RepositoryEvent.REMOVED && event.isRepositoryEnabled()) { + repositoryRemoved(event); + } else if (event.getKind() == RepositoryEvent.DISCOVERED) { + repositoryDiscovered(event); + } else if (event.getKind() == RepositoryEvent.CHANGED) { + repositoryChanged(event); + } else if (event.getKind() == RepositoryEvent.ENABLEMENT) { + repositoryEnablement(event); + } + } + } + + /** + * A repository has been added. Subclasses may override. May be called + * from a non-UI thread. + * + * @param event the RepositoryEvent describing the details + */ + protected void repositoryAdded(RepositoryEvent event) { + // Do nothing. This method is not abstract because subclasses + // may not be interested in repository events at all and should + // not have to implement it. + } + + /** + * A repository has been removed. Subclasses may override. May be called + * from a non-UI thread. + * + * @param event the RepositoryEvent describing the details + */ + protected void repositoryRemoved(RepositoryEvent event) { + // Do nothing. This method is not abstract because subclasses + // may not be interested in repository events at all and should + // not have to implement it. + } + + /** + * A repository has been discovered. Subclasses may override. May be called + * from a non-UI thread. + * + * @param event the RepositoryEvent describing the details + */ + protected void repositoryDiscovered(RepositoryEvent event) { + // Do nothing. This method is not abstract because subclasses + // may not be interested in repository events at all and should + // not have to implement it. + } + + /** + * A repository has changed. Subclasses may override. May be called + * from a non-UI thread. + * + * @param event the RepositoryEvent describing the details + */ + protected void repositoryChanged(RepositoryEvent event) { + // Do nothing. This method is not abstract because subclasses + // may not be interested in repository events at all and should + // not have to implement it. + } + + /** + * A repository's enablement state has changed. This is treated + * as repository addition or removal by default. Subclasses may + * override. May be called from a non-UI thread. + * @param event + */ + protected void repositoryEnablement(RepositoryEvent event) { + // We treat enablement of a repository as if one were added. + if (event.isRepositoryEnabled()) + repositoryAdded(event); + else + repositoryRemoved(event); + } + + /** + * The specified profile has changed. Subclasses may override. May be called + * from a non-UI thread. + * + * @param profileId the id of the profile that changed. + */ + protected void profileChanged(final String profileId) { + // Do nothing. This method is not abstract because subclasses + // may not be interested in profile events at all and should + // not have to implement it. + } + + /** + * The specified profile has been added. Subclasses may override. May be called + * from a non-UI thread. + * + * @param profileId the id of the profile that has been added. + */ + protected void profileAdded(final String profileId) { + // Do nothing. This method is not abstract because subclasses + // may not be interested in profile events at all and should + // not have to implement it. + } + + /** + * The specified profile has been removed. Subclasses may override. May be called + * from a non-UI thread. + * + * @param profileId the id of the profile that has been removed. + */ + protected void profileRemoved(final String profileId) { + // Do nothing. This method is not abstract because subclasses + // may not be interested in profile events at all and should + // not have to implement it. + } + + /** + * An event requiring a complete refresh of the listener's state has + * been received. This is used, for example, when a batch change has + * completed. Subclasses may override. May be called from a non-UI + * thread. + */ + protected void refreshAll() { + // Do nothing by default. + } + + public int getEventTypes() { + return eventTypes; + } +} diff --git a/tycho-its/projects/api-tools/missing-bin/org.eclipse.equinox.p2.ui/src/org/eclipse/equinox/internal/p2/ui/ProvisioningOperationRunner.java b/tycho-its/projects/api-tools/missing-bin/org.eclipse.equinox.p2.ui/src/org/eclipse/equinox/internal/p2/ui/ProvisioningOperationRunner.java new file mode 100644 index 0000000000..eceed6bb90 --- /dev/null +++ b/tycho-its/projects/api-tools/missing-bin/org.eclipse.equinox.p2.ui/src/org/eclipse/equinox/internal/p2/ui/ProvisioningOperationRunner.java @@ -0,0 +1,148 @@ +/******************************************************************************* + * Copyright (c) 2007, 2018 IBM Corporation and others. + * + * This program and the accompanying materials + * are made available under the terms of the Eclipse Public License 2.0 + * which accompanies this distribution, and is available at + * https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + * + * Contributors: + * IBM Corporation - initial API and implementation + * Red Hat Inc. - Bug 460967 + *******************************************************************************/ +package org.eclipse.equinox.internal.p2.ui; + +import java.io.IOException; +import org.eclipse.core.runtime.IStatus; +import org.eclipse.core.runtime.Status; +import org.eclipse.core.runtime.jobs.*; +import org.eclipse.equinox.internal.p2.core.helpers.ServiceHelper; +import org.eclipse.equinox.internal.p2.ui.dialogs.ApplyProfileChangesDialog; +import org.eclipse.equinox.internal.provisional.configurator.Configurator; +import org.eclipse.equinox.p2.operations.ProvisioningJob; +import org.eclipse.equinox.p2.ui.Policy; +import org.eclipse.equinox.p2.ui.ProvisioningUI; +import org.eclipse.ui.PlatformUI; +import org.eclipse.ui.progress.IProgressConstants; +import org.eclipse.ui.progress.IProgressConstants2; +import org.eclipse.ui.statushandlers.StatusManager; + +/** + * Utility methods for running provisioning operations. Operations can either + * be run synchronously or in a job. When scheduled as a job, the operation + * determines whether the job is run in + * the background or in the UI. + * + * @since 3.4 + */ +public class ProvisioningOperationRunner { + + boolean suppressRestart = false; + ProvisioningUI ui; + public int eventBatchCount = 0; + + public ProvisioningOperationRunner(ProvisioningUI ui) { + this.ui = ui; + } + + /** + * Schedule a job to execute the supplied ProvisioningOperation. + * + * @param job The operation to execute + * @param errorStyle the flags passed to the StatusManager for error reporting + */ + public void schedule(final ProvisioningJob job, final int errorStyle) { + final boolean noPrompt = (errorStyle & (StatusManager.BLOCK | StatusManager.SHOW)) == 0; + if (noPrompt) { + job.setProperty(IProgressConstants.KEEP_PROPERTY, Boolean.TRUE); + job.setProperty(IProgressConstants.NO_IMMEDIATE_ERROR_PROMPT_PROPERTY, Boolean.TRUE); + } + job.setProperty(IProgressConstants.ICON_PROPERTY, ProvUIImages.getImageDescriptor(ProvUIImages.IMG_PROFILE)); + job.setProperty(IProgressConstants2.SHOW_IN_TASKBAR_ICON_PROPERTY, Boolean.TRUE); + manageJob(job, job.getRestartPolicy()); + job.schedule(); + } + + /** + * Request a restart of the platform according to the specified + * restart policy. + * + * @param restartPolicy + */ + void requestRestart(final int restartPolicy) { + // Global override of restart (used in test cases). + if (suppressRestart) + return; + if (restartPolicy == Policy.RESTART_POLICY_FORCE) { + PlatformUI.getWorkbench().restart(); + return; + } + if (restartPolicy == Policy.RESTART_POLICY_FORCE_APPLY) { + applyProfileChanges(); + return; + } + + PlatformUI.getWorkbench().getDisplay().asyncExec(() -> { + if (PlatformUI.getWorkbench().isClosing()) + return; + int retCode = ApplyProfileChangesDialog.promptForRestart(ProvUI.getDefaultParentShell(), restartPolicy == Policy.RESTART_POLICY_PROMPT); + if (retCode == ApplyProfileChangesDialog.PROFILE_APPLYCHANGES) { + applyProfileChanges(); + } else if (retCode == ApplyProfileChangesDialog.PROFILE_RESTART) { + PlatformUI.getWorkbench().restart(true); + } + }); + } + + void applyProfileChanges() { + Configurator configurator = ServiceHelper.getService(ProvUIActivator.getContext(), Configurator.class); + try { + configurator.applyConfiguration(); + } catch (IOException e) { + ProvUI.handleException(e, ProvUIMessages.ProvUI_ErrorDuringApplyConfig, StatusManager.LOG | StatusManager.BLOCK); + } catch (IllegalStateException e) { + IStatus illegalApplyStatus = new Status(IStatus.WARNING, ProvUIActivator.PLUGIN_ID, 0, ProvUIMessages.ProvisioningOperationRunner_CannotApplyChanges, e); + ProvUI.reportStatus(illegalApplyStatus, StatusManager.LOG | StatusManager.BLOCK); + } + } + + public void manageJob(Job job, final int jobRestartPolicy) { + ui.getSession().rememberJob(job); + job.addJobChangeListener(new JobChangeAdapter() { + @Override + public void done(IJobChangeEvent event) { + int severity = event.getResult().getSeverity(); + // If the job finished without error, see if restart is needed + if (severity != IStatus.CANCEL && severity != IStatus.ERROR) { + if (jobRestartPolicy == ProvisioningJob.RESTART_NONE) { + return; + } + int globalRestartPolicy = ui.getPolicy().getRestartPolicy(); + // If the global policy allows apply changes, check the job policy to see if it supports it. + if (globalRestartPolicy == Policy.RESTART_POLICY_PROMPT_RESTART_OR_APPLY) { + if (jobRestartPolicy == ProvisioningJob.RESTART_OR_APPLY) + requestRestart(Policy.RESTART_POLICY_PROMPT_RESTART_OR_APPLY); + else + requestRestart(Policy.RESTART_POLICY_PROMPT); + } else + requestRestart(globalRestartPolicy); + } + } + }); + } + + /** + * This method is provided for use in automated test case. It should + * no longer be needed to be used by clients. + * + * @param suppress true to suppress all restarts and false + * to stop suppressing restarts. + * + * @noreference This method is not intended to be referenced by clients. + */ + public void suppressRestart(boolean suppress) { + suppressRestart = suppress; + } +} diff --git a/tycho-its/projects/api-tools/missing-bin/org.eclipse.equinox.p2.ui/src/org/eclipse/equinox/internal/p2/ui/QueryProvider.java b/tycho-its/projects/api-tools/missing-bin/org.eclipse.equinox.p2.ui/src/org/eclipse/equinox/internal/p2/ui/QueryProvider.java new file mode 100644 index 0000000000..aca5c6ec0b --- /dev/null +++ b/tycho-its/projects/api-tools/missing-bin/org.eclipse.equinox.p2.ui/src/org/eclipse/equinox/internal/p2/ui/QueryProvider.java @@ -0,0 +1,238 @@ +/******************************************************************************* + * Copyright (c) 2008, 2010 IBM Corporation and others. + * + * This program and the accompanying materials + * are made available under the terms of the Eclipse Public License 2.0 + * which accompanies this distribution, and is available at + * https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + * + * Contributors: + * IBM Corporation - initial API and implementation + * EclipseSource - ongoing development + *******************************************************************************/ +package org.eclipse.equinox.internal.p2.ui; + +import java.util.*; +import org.eclipse.equinox.internal.p2.metadata.InstallableUnit; +import org.eclipse.equinox.internal.p2.ui.model.*; +import org.eclipse.equinox.internal.p2.ui.query.*; +import org.eclipse.equinox.p2.engine.IProfile; +import org.eclipse.equinox.p2.metadata.IInstallableUnit; +import org.eclipse.equinox.p2.metadata.IRequirement; +import org.eclipse.equinox.p2.metadata.expression.*; +import org.eclipse.equinox.p2.query.*; +import org.eclipse.equinox.p2.repository.artifact.ArtifactKeyQuery; +import org.eclipse.equinox.p2.repository.artifact.IArtifactRepository; +import org.eclipse.equinox.p2.ui.Policy; +import org.eclipse.equinox.p2.ui.ProvisioningUI; + +/** + * Provides a default set of queries to drive the provisioning UI. + * + * @since 3.5 + */ + +public class QueryProvider { + + private ProvisioningUI ui; + + public static final int METADATA_REPOS = 1; + public static final int ARTIFACT_REPOS = 2; + public static final int PROFILES = 3; + public static final int AVAILABLE_IUS = 4; + public static final int AVAILABLE_UPDATES = 5; + public static final int INSTALLED_IUS = 6; + public static final int AVAILABLE_ARTIFACTS = 7; + + public QueryProvider(ProvisioningUI ui) { + this.ui = ui; + } + + /* + * Return a map of key/value pairs which are set to the environment settings + * for the given profile. May return null or an empty Map + * if the settings cannot be obtained. + */ + private static Map getEnvFromProfile(IProfile profile) { + if (profile == null) + return null; + String environments = profile.getProperty(IProfile.PROP_ENVIRONMENTS); + if (environments == null) + return null; + Map result = new HashMap<>(); + for (StringTokenizer tokenizer = new StringTokenizer(environments, ","); tokenizer.hasMoreElements();) { //$NON-NLS-1$ + String entry = tokenizer.nextToken(); + int i = entry.indexOf('='); + String key = entry.substring(0, i).trim(); + String value = entry.substring(i + 1).trim(); + result.put(key, value); + } + return result; + } + + // If we are supposed to filter out the results based on the environment settings in + // the target profile then create a compound query otherwise just return the given query + private IQuery createEnvironmentFilterQuery(IUViewQueryContext context, IProfile profile, IQuery query) { + if (!context.getFilterOnEnv()) + return query; + Map environment = getEnvFromProfile(profile); + if (environment == null) + return query; + IInstallableUnit envIU = InstallableUnit.contextIU(environment); + IQuery filterQuery = QueryUtil.createMatchQuery("filter == null || $0 ~= filter", envIU); //$NON-NLS-1$ + return QueryUtil.createCompoundQuery(query, filterQuery, true); + } + + public ElementQueryDescriptor getQueryDescriptor(final QueriedElement element) { + // Initialize queryable, queryContext, and queryType from the element. + // In some cases we override this. + Policy policy = ui.getPolicy(); + IQueryable queryable = element.getQueryable(); + int queryType = element.getQueryType(); + IUViewQueryContext context = element.getQueryContext(); + if (context == null) { + context = ProvUI.getQueryContext(policy); + context.setInstalledProfileId(ui.getProfileId()); + } + switch (queryType) { + case ARTIFACT_REPOS : + queryable = new QueryableArtifactRepositoryManager(ui, false).locationsQueriable(); + return new ElementQueryDescriptor(queryable, new RepositoryLocationQuery(), new Collector<>(), new ArtifactRepositoryElementWrapper(null, element)); + + case AVAILABLE_IUS : + // Things get more complicated if the user wants to filter out installed items. + // This involves setting up a secondary query for installed content that the various + // collectors will use to reject content. We can't use a compound query because the + // queryables are different (profile for installed content, repo for available content) + AvailableIUWrapper availableIUWrapper; + boolean showLatest = context.getShowLatestVersionsOnly(); + boolean hideInstalled = context.getHideAlreadyInstalled(); + IProfile targetProfile = null; + String profileId = context.getInstalledProfileId(); + if (profileId != null) { + targetProfile = ProvUI.getProfileRegistry(ui.getSession()).getProfile(profileId); + } + + IQuery topLevelQuery = policy.getVisibleAvailableIUQuery(); + IQuery categoryQuery = QueryUtil.createIUCategoryQuery(); + + topLevelQuery = createEnvironmentFilterQuery(context, targetProfile, topLevelQuery); + categoryQuery = createEnvironmentFilterQuery(context, targetProfile, categoryQuery); + + // Showing child IU's of a group of repositories, or of a single repository + if (element instanceof MetadataRepositories || element instanceof MetadataRepositoryElement) { + if (context.getViewType() == IUViewQueryContext.AVAILABLE_VIEW_FLAT || !context.getUseCategories()) { + AvailableIUWrapper wrapper = new AvailableIUWrapper(queryable, element, false, context.getShowAvailableChildren()); + if (showLatest) + topLevelQuery = QueryUtil.createLatestQuery(topLevelQuery); + if (targetProfile != null) + wrapper.markInstalledIUs(targetProfile, hideInstalled); + return new ElementQueryDescriptor(queryable, topLevelQuery, new Collector<>(), wrapper); + } + // Installed content not a concern for collecting categories + return new ElementQueryDescriptor(queryable, categoryQuery, new Collector<>(), new CategoryElementWrapper(queryable, element)); + } + + // If it's a category or some other IUElement to drill down in, we get the requirements and show all requirements + // that are also visible in the available list. + if (element instanceof CategoryElement || (element instanceof IIUElement && ((IIUElement) element).shouldShowChildren())) { + // children of a category should drill down according to the context. If we aren't in a category, we are already drilling down and + // continue to do so. + boolean drillDownTheChildren = element instanceof CategoryElement ? context.getShowAvailableChildren() : true; + IQuery memberOfCategoryQuery; + if (element instanceof CategoryElement) { + // We need an expression that uses the requirements of the element's requirements, which could be merged + // from multiple category IUs shown as one in the UI. + IExpression matchesRequirementsExpression = ExpressionUtil.parse("$0.exists(r | this ~= r)"); //$NON-NLS-1$ + memberOfCategoryQuery = QueryUtil.createMatchQuery(matchesRequirementsExpression, ((CategoryElement) element).getRequirements()); + } else { + memberOfCategoryQuery = QueryUtil.createIUCategoryMemberQuery(((IIUElement) element).getIU()); + } + memberOfCategoryQuery = createEnvironmentFilterQuery(context, targetProfile, memberOfCategoryQuery); + availableIUWrapper = new AvailableIUWrapper(queryable, element, true, drillDownTheChildren); + if (targetProfile != null) + availableIUWrapper.markInstalledIUs(targetProfile, hideInstalled); + // if it's a category, there is a special query. + if (element instanceof CategoryElement) { + if (showLatest) + memberOfCategoryQuery = QueryUtil.createLatestQuery(memberOfCategoryQuery); + return new ElementQueryDescriptor(queryable, memberOfCategoryQuery, new Collector<>(), availableIUWrapper); + } + // It is not a category, we want to traverse the requirements that are groups. + IQuery query = QueryUtil.createCompoundQuery(topLevelQuery, new RequiredIUsQuery(((IIUElement) element).getIU()), true); + if (showLatest) + query = QueryUtil.createLatestQuery(query); + // If it's not a category, these are generic requirements and should be filtered by the visibility property (topLevelQuery) + return new ElementQueryDescriptor(queryable, query, new Collector<>(), availableIUWrapper); + } + return null; + + case AVAILABLE_UPDATES : + // This query can be used by the automatic updater in headless cases (checking for updates). + // We traffic in IU's rather than wrapped elements + IProfile profile; + IInstallableUnit[] toUpdate = null; + if (element instanceof Updates) { + profile = ProvUI.getProfileRegistry(ui.getSession()).getProfile(((Updates) element).getProfileId()); + toUpdate = ((Updates) element).getIUs(); + } else { + profile = ProvUI.getAdapter(element, IProfile.class); + } + if (profile == null) + return null; + if (toUpdate == null) { + IQueryResult queryResult = profile.query(policy.getVisibleInstalledIUQuery(), null); + toUpdate = queryResult.toArray(IInstallableUnit.class); + } + QueryableUpdates updateQueryable = new QueryableUpdates(ui, toUpdate); + return new ElementQueryDescriptor(updateQueryable, context.getShowLatestVersionsOnly() ? QueryUtil.createLatestIUQuery() : QueryUtil.createIUAnyQuery(), new Collector<>()); + + case INSTALLED_IUS : + // Querying of IU's. We are drilling down into the requirements. + if (element instanceof IIUElement && context.getShowInstallChildren()) { + Collection reqs = ((IIUElement) element).getRequirements(); + if (reqs.size() == 0) + return null; // no children + IExpression[] requirementExpressions = new IExpression[reqs.size()]; + int i = 0; + for (IRequirement req : reqs) { + requirementExpressions[i++] = req.getMatches(); + } + + IExpressionFactory factory = ExpressionUtil.getFactory(); + IQuery meetsAnyRequirementQuery = QueryUtil.createMatchQuery(factory.or(requirementExpressions)); + IQuery visibleAsAvailableQuery = policy.getVisibleAvailableIUQuery(); + IQuery createCompoundQuery = QueryUtil.createCompoundQuery(visibleAsAvailableQuery, meetsAnyRequirementQuery, true); + return new ElementQueryDescriptor(queryable, createCompoundQuery, new Collector<>(), new InstalledIUElementWrapper(queryable, element)); + } + profile = ProvUI.getAdapter(element, IProfile.class); + if (profile == null) + return null; + return new ElementQueryDescriptor(profile, policy.getVisibleInstalledIUQuery(), new Collector<>(), new InstalledIUElementWrapper(profile, element)); + + case METADATA_REPOS : + if (element instanceof MetadataRepositories) { + if (queryable == null) { + queryable = new QueryableMetadataRepositoryManager(ui, ((MetadataRepositories) element).getIncludeDisabledRepositories()).locationsQueriable(); + element.setQueryable(queryable); + } + return new ElementQueryDescriptor(element.getQueryable(), new RepositoryLocationQuery(), new Collector<>(), new MetadataRepositoryElementWrapper(null, element)); + } + return null; + + case PROFILES : + queryable = new QueryableProfileRegistry(ui); + return new ElementQueryDescriptor(queryable, QueryUtil.createMatchQuery(IProfile.class, ExpressionUtil.TRUE_EXPRESSION), new Collector<>(), new ProfileElementWrapper(null, element)); + + case AVAILABLE_ARTIFACTS : + if (!(queryable instanceof IArtifactRepository)) + return null; + return new ElementQueryDescriptor(queryable, ArtifactKeyQuery.ALL_KEYS, new Collector<>(), new ArtifactKeyWrapper((IArtifactRepository) queryable, element)); + + default : + return null; + } + } +} diff --git a/tycho-its/projects/api-tools/missing-bin/org.eclipse.equinox.p2.ui/src/org/eclipse/equinox/internal/p2/ui/QueryableArtifactRepositoryManager.java b/tycho-its/projects/api-tools/missing-bin/org.eclipse.equinox.p2.ui/src/org/eclipse/equinox/internal/p2/ui/QueryableArtifactRepositoryManager.java new file mode 100644 index 0000000000..512bbb7afe --- /dev/null +++ b/tycho-its/projects/api-tools/missing-bin/org.eclipse.equinox.p2.ui/src/org/eclipse/equinox/internal/p2/ui/QueryableArtifactRepositoryManager.java @@ -0,0 +1,61 @@ +/******************************************************************************* + * Copyright (c) 2007, 2010 IBM Corporation and others. + * + * This program and the accompanying materials + * are made available under the terms of the Eclipse Public License 2.0 + * which accompanies this distribution, and is available at + * https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + * + * Contributors: + * IBM Corporation - initial API and implementation + * EclipseSource - ongoing development + *******************************************************************************/ +package org.eclipse.equinox.internal.p2.ui; + +import java.net.URI; +import org.eclipse.core.runtime.IProgressMonitor; +import org.eclipse.equinox.internal.p2.artifact.repository.ArtifactRepositoryManager; +import org.eclipse.equinox.p2.core.ProvisionException; +import org.eclipse.equinox.p2.metadata.IArtifactKey; +import org.eclipse.equinox.p2.operations.RepositoryTracker; +import org.eclipse.equinox.p2.repository.IRepositoryManager; +import org.eclipse.equinox.p2.repository.artifact.IArtifactRepository; +import org.eclipse.equinox.p2.repository.artifact.IArtifactRepositoryManager; +import org.eclipse.equinox.p2.ui.ProvisioningUI; + +/** + * An object that queries a particular set of artifact repositories. + */ +public class QueryableArtifactRepositoryManager extends QueryableRepositoryManager { + + public QueryableArtifactRepositoryManager(ProvisioningUI ui, boolean includeDisabledRepos) { + super(ui, includeDisabledRepos); + } + + @Override + protected IArtifactRepositoryManager getRepositoryManager() { + return ProvUI.getArtifactRepositoryManager(getSession()); + } + + @Override + protected IArtifactRepository doLoadRepository(IRepositoryManager manager, URI location, + IProgressMonitor monitor) throws ProvisionException { + return ui.loadArtifactRepository(location, false, monitor); + } + + @Override + protected int getRepositoryFlags(RepositoryTracker repositoryManipulator) { + return repositoryManipulator.getArtifactRepositoryFlags(); + } + + @Override + protected IArtifactRepository getRepository(IRepositoryManager manager, URI location) { + // note the use of ArtifactRepositoryManager (the concrete implementation). + if (manager instanceof ArtifactRepositoryManager) { + return ((ArtifactRepositoryManager) manager).getRepository(location); + } + return null; + } +} diff --git a/tycho-its/projects/api-tools/missing-bin/org.eclipse.equinox.p2.ui/src/org/eclipse/equinox/internal/p2/ui/QueryableMetadataRepositoryManager.java b/tycho-its/projects/api-tools/missing-bin/org.eclipse.equinox.p2.ui/src/org/eclipse/equinox/internal/p2/ui/QueryableMetadataRepositoryManager.java new file mode 100644 index 0000000000..c912f7c626 --- /dev/null +++ b/tycho-its/projects/api-tools/missing-bin/org.eclipse.equinox.p2.ui/src/org/eclipse/equinox/internal/p2/ui/QueryableMetadataRepositoryManager.java @@ -0,0 +1,60 @@ +/******************************************************************************* + * Copyright (c) 2007, 2010 IBM Corporation and others. + * + * This program and the accompanying materials + * are made available under the terms of the Eclipse Public License 2.0 + * which accompanies this distribution, and is available at + * https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + * + * Contributors: + * IBM Corporation - initial API and implementation + *******************************************************************************/ +package org.eclipse.equinox.internal.p2.ui; + +import java.net.URI; +import org.eclipse.core.runtime.IProgressMonitor; +import org.eclipse.equinox.internal.p2.metadata.repository.MetadataRepositoryManager; +import org.eclipse.equinox.p2.core.ProvisionException; +import org.eclipse.equinox.p2.metadata.IInstallableUnit; +import org.eclipse.equinox.p2.operations.RepositoryTracker; +import org.eclipse.equinox.p2.repository.IRepositoryManager; +import org.eclipse.equinox.p2.repository.metadata.IMetadataRepository; +import org.eclipse.equinox.p2.repository.metadata.IMetadataRepositoryManager; +import org.eclipse.equinox.p2.ui.ProvisioningUI; + +/** + * An object that queries a particular set of metadata repositories. + */ +public class QueryableMetadataRepositoryManager extends QueryableRepositoryManager { + + public QueryableMetadataRepositoryManager(ProvisioningUI ui, boolean includeDisabledRepos) { + super(ui, includeDisabledRepos); + } + + @Override + protected IMetadataRepository getRepository(IRepositoryManager manager, URI location) { + // note the use of MetadataRepositoryManager (the concrete implementation). + if (manager instanceof MetadataRepositoryManager) { + return ((MetadataRepositoryManager) manager).getRepository(location); + } + return null; + } + + @Override + protected IMetadataRepositoryManager getRepositoryManager() { + return ProvUI.getMetadataRepositoryManager(getSession()); + } + + @Override + protected IMetadataRepository doLoadRepository(IRepositoryManager manager, URI location, + IProgressMonitor monitor) throws ProvisionException { + return ui.loadMetadataRepository(location, false, monitor); + } + + @Override + protected int getRepositoryFlags(RepositoryTracker repositoryManipulator) { + return repositoryManipulator.getMetadataRepositoryFlags(); + } +} diff --git a/tycho-its/projects/api-tools/missing-bin/org.eclipse.equinox.p2.ui/src/org/eclipse/equinox/internal/p2/ui/QueryableRepositoryManager.java b/tycho-its/projects/api-tools/missing-bin/org.eclipse.equinox.p2.ui/src/org/eclipse/equinox/internal/p2/ui/QueryableRepositoryManager.java new file mode 100644 index 0000000000..8b5d9e7d72 --- /dev/null +++ b/tycho-its/projects/api-tools/missing-bin/org.eclipse.equinox.p2.ui/src/org/eclipse/equinox/internal/p2/ui/QueryableRepositoryManager.java @@ -0,0 +1,174 @@ +/******************************************************************************* + * Copyright (c) 2007, 2018 IBM Corporation and others. + * + * This program and the accompanying materials + * are made available under the terms of the Eclipse Public License 2.0 + * which accompanies this distribution, and is available at + * https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + * + * Contributors: + * IBM Corporation - initial API and implementation + *******************************************************************************/ +package org.eclipse.equinox.internal.p2.ui; + +import java.net.URI; +import java.util.*; +import org.eclipse.core.runtime.*; +import org.eclipse.equinox.p2.core.ProvisionException; +import org.eclipse.equinox.p2.operations.ProvisioningSession; +import org.eclipse.equinox.p2.operations.RepositoryTracker; +import org.eclipse.equinox.p2.query.*; +import org.eclipse.equinox.p2.repository.IRepository; +import org.eclipse.equinox.p2.repository.IRepositoryManager; +import org.eclipse.equinox.p2.ui.ProvisioningUI; +import org.eclipse.osgi.util.NLS; + +/** + * An object that provides query support for a specified + * set of repositories. The repository tracker flags determine which repositories + * are included in the query. Callers interested in only the resulting repository URIs + * should specify a {@link RepositoryLocationQuery}, in which case the + * query is performed over the URI's. Otherwise the repositories are loaded and + * the query is performed over the repositories themselves. + */ +public abstract class QueryableRepositoryManager implements IQueryable { + private ProvisioningSession session; + protected boolean includeDisabledRepos; + protected RepositoryTracker tracker; + protected int repositoryFlags; + protected ProvisioningUI ui; + + public QueryableRepositoryManager(ProvisioningUI ui, boolean includeDisabledRepos) { + this.includeDisabledRepos = includeDisabledRepos; + this.ui = ui; + this.tracker = ui.getRepositoryTracker(); + this.session = ui.getSession(); + repositoryFlags = getRepositoryFlags(tracker); + } + + protected ProvisioningSession getSession() { + return session; + } + + /** + * Iterates over the repositories configured in this queryable. + * For most queries, the query is run on each repository, passing any objects that satisfy the + * query. + *

+ * This method is long-running; progress and cancellation are provided + * by the given progress monitor. + *

+ * + * @param query The query to perform.. + * @param monitor a progress monitor, or null if progress + * reporting is not desired + * @return The QueryResult argument + */ + @Override + public IQueryResult query(IQuery query, IProgressMonitor monitor) { + IRepositoryManager manager = getRepositoryManager(); + if (monitor == null) + monitor = new NullProgressMonitor(); + return query(getRepoLocations(manager), query, monitor); + } + + public IQueryable locationsQueriable() { + return (query, monitor) -> query.perform(getRepoLocations(getRepositoryManager()).iterator()); + } + + protected Collection getRepoLocations(IRepositoryManager manager) { + Set locations = new HashSet<>(); + locations.addAll(Arrays.asList(manager.getKnownRepositories(repositoryFlags))); + if (includeDisabledRepos) { + locations.addAll(Arrays.asList(manager.getKnownRepositories(IRepositoryManager.REPOSITORIES_DISABLED | repositoryFlags))); + } + return locations; + } + + /** + * Return a boolean indicating whether all the repositories that + * can be queried by the receiver are already loaded. If a repository + * is not loaded because it was not found, this will not return false, + * because this repository cannot be queried. + * + * @return true if all repositories to be queried by the + * receiver are loaded, false if they + * are not. + */ + public boolean areRepositoriesLoaded() { + IRepositoryManager mgr = getRepositoryManager(); + if (mgr == null) + return false; + for (URI repoURI : getRepoLocations(mgr)) { + IRepository repo = getRepository(mgr, repoURI); + // A not-loaded repo doesn't count if it's considered missing (not found) + if (repo == null && !tracker.hasNotFoundStatusBeenReported(repoURI)) + return false; + } + return true; + } + + protected abstract IRepository getRepository(IRepositoryManager manager, URI location); + + protected IRepository loadRepository(IRepositoryManager manager, URI location, IProgressMonitor monitor) throws ProvisionException { + monitor.setTaskName(NLS.bind(ProvUIMessages.QueryableMetadataRepositoryManager_LoadRepositoryProgress, URIUtil.toUnencodedString(location))); + IRepository repo = doLoadRepository(manager, location, monitor); + return repo; + } + + /** + * Return the appropriate repository manager, or null if none could be found. + * @return the repository manager + */ + protected abstract IRepositoryManager getRepositoryManager(); + + /** + * Return the flags that should be used to access repositories given the + * manipulator. + */ + protected abstract int getRepositoryFlags(RepositoryTracker repositoryManipulator); + + /** + * Load the repository located at the specified location. + * + * @param manager the manager + * @param location the repository location + * @param monitor the progress monitor + * @return the repository that was loaded, or null if no repository could + * be found at that location. + */ + protected abstract IRepository doLoadRepository(IRepositoryManager manager, URI location, IProgressMonitor monitor) throws ProvisionException; + + @SuppressWarnings("unchecked") + protected IQueryResult query(Collection uris, IQuery query, IProgressMonitor monitor) { + if (query instanceof RepositoryLocationQuery) { + return (IQueryResult) locationsQueriable().query((IQuery) query, monitor); + } + SubMonitor sub = SubMonitor.convert(monitor, (uris.size() + 1) * 100); + ArrayList> loadedRepos = new ArrayList<>(uris.size()); + for (URI uri : uris) { + IRepository repo = null; + try { + repo = loadRepository(getRepositoryManager(), uri, sub.newChild(100)); + } catch (ProvisionException e) { + tracker.reportLoadFailure(uri, e); + } catch (OperationCanceledException e) { + // user has canceled + repo = null; + } + if (repo != null) + loadedRepos.add(repo); + } + if (loadedRepos.size() > 0) { + return QueryUtil.compoundQueryable(loadedRepos).query(query, sub.newChild(100)); + } + return Collector.emptyCollector(); + } + + public void setRespositoryFlags(int flags) { + this.repositoryFlags = flags; + } + +} diff --git a/tycho-its/projects/api-tools/missing-bin/org.eclipse.equinox.p2.ui/src/org/eclipse/equinox/internal/p2/ui/RepositoryLocationQuery.java b/tycho-its/projects/api-tools/missing-bin/org.eclipse.equinox.p2.ui/src/org/eclipse/equinox/internal/p2/ui/RepositoryLocationQuery.java new file mode 100644 index 0000000000..8f1ae7e94e --- /dev/null +++ b/tycho-its/projects/api-tools/missing-bin/org.eclipse.equinox.p2.ui/src/org/eclipse/equinox/internal/p2/ui/RepositoryLocationQuery.java @@ -0,0 +1,32 @@ +/******************************************************************************* + * Copyright (c) 2009, 2010 IBM Corporation and others. + * + * This program and the accompanying materials + * are made available under the terms of the Eclipse Public License 2.0 + * which accompanies this distribution, and is available at + * https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + * + * Contributors: + * IBM Corporation - initial API and implementation + ******************************************************************************/ + +package org.eclipse.equinox.internal.p2.ui; + +import org.eclipse.equinox.p2.query.ExpressionMatchQuery; + +import java.net.URI; +import org.eclipse.equinox.p2.metadata.expression.ExpressionUtil; + +/** + * RepositoryLocationQuery yields true for all URI elements. + * + * @since 3.5 + */ +public class RepositoryLocationQuery extends ExpressionMatchQuery { + + public RepositoryLocationQuery() { + super(URI.class, ExpressionUtil.TRUE_EXPRESSION); + } +} diff --git a/tycho-its/projects/api-tools/missing-bin/org.eclipse.equinox.p2.ui/src/org/eclipse/equinox/internal/p2/ui/RepositoryOperationBeginningEvent.java b/tycho-its/projects/api-tools/missing-bin/org.eclipse.equinox.p2.ui/src/org/eclipse/equinox/internal/p2/ui/RepositoryOperationBeginningEvent.java new file mode 100644 index 0000000000..89acad61cd --- /dev/null +++ b/tycho-its/projects/api-tools/missing-bin/org.eclipse.equinox.p2.ui/src/org/eclipse/equinox/internal/p2/ui/RepositoryOperationBeginningEvent.java @@ -0,0 +1,38 @@ +/******************************************************************************* + * Copyright (c) 2008, 2010 IBM Corporation and others. + * + * This program and the accompanying materials + * are made available under the terms of the Eclipse Public License 2.0 + * which accompanies this distribution, and is available at + * https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + * + * Contributors: + * IBM Corporation - initial API and implementation + ******************************************************************************/ + +package org.eclipse.equinox.internal.p2.ui; + +import java.util.EventObject; + +/** + * Event used to signal that a repository operation is about + * to begin. This event can be used to ignore lower-level repository events + * until the operation is complete. + * + * @since 2.0 + */ +public class RepositoryOperationBeginningEvent extends EventObject { + + private static final long serialVersionUID = -7529156836242774280L; + + /** + * Construct a new instance of this event. + * @param source the source of the event + */ + public RepositoryOperationBeginningEvent(Object source) { + super(source); + } + +} diff --git a/tycho-its/projects/api-tools/missing-bin/org.eclipse.equinox.p2.ui/src/org/eclipse/equinox/internal/p2/ui/RepositoryOperationEndingEvent.java b/tycho-its/projects/api-tools/missing-bin/org.eclipse.equinox.p2.ui/src/org/eclipse/equinox/internal/p2/ui/RepositoryOperationEndingEvent.java new file mode 100644 index 0000000000..7e953a8ef7 --- /dev/null +++ b/tycho-its/projects/api-tools/missing-bin/org.eclipse.equinox.p2.ui/src/org/eclipse/equinox/internal/p2/ui/RepositoryOperationEndingEvent.java @@ -0,0 +1,82 @@ +/******************************************************************************* + * Copyright (c) 2008, 2010 IBM Corporation and others. + * + * This program and the accompanying materials + * are made available under the terms of the Eclipse Public License 2.0 + * which accompanies this distribution, and is available at + * https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + * + * Contributors: + * IBM Corporation - initial API and implementation + *******************************************************************************/ + +package org.eclipse.equinox.internal.p2.ui; + +import java.util.EventObject; +import org.eclipse.equinox.internal.provisional.p2.repository.RepositoryEvent; + +/** + * Event used to signal that a repository operation has completed. + * + * @since 2.0 + */ +public class RepositoryOperationEndingEvent extends EventObject { + + private static final long serialVersionUID = -4513769756968621852L; + + /** + * A repository event describing the nature of the operation. + */ + private RepositoryEvent event; + + /** + * A boolean indicating whether the UI should be updated in response + * to this event. + */ + private boolean update; + + /** + * Construct a new instance of this event. + * + * @param source the source of the event + * @param update a boolean indicating whether the UI should be updated in response + * to this event. + * @param event a {@link RepositoryEvent} describing the underlying event, or null + * if no single event can describe the operation. This event may be used by clients to determine + * what should be updated after an operation completes. + */ + public RepositoryOperationEndingEvent(Object source, boolean update, RepositoryEvent event) { + super(source); + this.update = update; + this.event = event; + } + + /** + * Return a {@link RepositoryEvent} that reflects the operation that + * occurred. A null return value indicates that there + * was not a single underlying repository operation. + * + * @return the {@link RepositoryEvent} that was involved in the operation. May be + * null. This event may be used by clients to determine + * what should be updated after an operation completes. + + */ + public RepositoryEvent getEvent() { + return event; + } + + /** + * Return a boolean that indicates whether the client should update the UI in response + * to this event. + * event. + * + * @return true if clients should update to reflect to this event, false + * if the client should ignore the entire operation. + */ + public boolean update() { + return update; + } + +} diff --git a/tycho-its/projects/api-tools/missing-bin/org.eclipse.equinox.p2.ui/src/org/eclipse/equinox/internal/p2/ui/RepositoryTrackerComponent.java b/tycho-its/projects/api-tools/missing-bin/org.eclipse.equinox.p2.ui/src/org/eclipse/equinox/internal/p2/ui/RepositoryTrackerComponent.java new file mode 100644 index 0000000000..bcc152da87 --- /dev/null +++ b/tycho-its/projects/api-tools/missing-bin/org.eclipse.equinox.p2.ui/src/org/eclipse/equinox/internal/p2/ui/RepositoryTrackerComponent.java @@ -0,0 +1,34 @@ +/******************************************************************************* + * Copyright (c) 2011 EclipseSource Inc. and others. + * + * This program and the accompanying materials + * are made available under the terms of the Eclipse Public License 2.0 + * which accompanies this distribution, and is available at + * https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + * + * Contributors: + * EclipseSource Inc. - initial API and implementation + *******************************************************************************/ +package org.eclipse.equinox.internal.p2.ui; + +import org.eclipse.equinox.p2.core.IProvisioningAgent; +import org.eclipse.equinox.p2.core.spi.IAgentServiceFactory; +import org.eclipse.equinox.p2.operations.RepositoryTracker; +import org.eclipse.equinox.p2.ui.ProvisioningUI; + +/** + * Component that provides a factory that can create and initialize + * {@link RepositoryTracker} instances. + */ +public class RepositoryTrackerComponent implements IAgentServiceFactory { + + @Override + public Object createService(IProvisioningAgent agent) { + ProvisioningUI ui = agent.getService(ProvisioningUI.class); + if (ui == null) + return null; + return new ColocatedRepositoryTracker(ui); + } +} diff --git a/tycho-its/projects/api-tools/missing-bin/org.eclipse.equinox.p2.ui/src/org/eclipse/equinox/internal/p2/ui/ServiceUIComponent.java b/tycho-its/projects/api-tools/missing-bin/org.eclipse.equinox.p2.ui/src/org/eclipse/equinox/internal/p2/ui/ServiceUIComponent.java new file mode 100644 index 0000000000..cad8f35b98 --- /dev/null +++ b/tycho-its/projects/api-tools/missing-bin/org.eclipse.equinox.p2.ui/src/org/eclipse/equinox/internal/p2/ui/ServiceUIComponent.java @@ -0,0 +1,31 @@ +/******************************************************************************* + * Copyright (c) 2010 IBM Corporation and others. + * + * This program and the accompanying materials + * are made available under the terms of the Eclipse Public License 2.0 + * which accompanies this distribution, and is available at + * https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + * + * Contributors: + * IBM Corporation - initial API and implementation + *******************************************************************************/ +package org.eclipse.equinox.internal.p2.ui; + +import org.eclipse.equinox.p2.core.IProvisioningAgent; +import org.eclipse.equinox.p2.core.UIServices; +import org.eclipse.equinox.p2.core.spi.IAgentServiceFactory; + +/** + * Component that provides a factory that can create and initialize + * {@link UIServices} instances. + */ +public class ServiceUIComponent implements IAgentServiceFactory { + + @Override + public Object createService(IProvisioningAgent agent) { + return new ValidationDialogServiceUI(agent); + } + +} diff --git a/tycho-its/projects/api-tools/missing-bin/org.eclipse.equinox.p2.ui/src/org/eclipse/equinox/internal/p2/ui/UpdateManagerCompatibility.java b/tycho-its/projects/api-tools/missing-bin/org.eclipse.equinox.p2.ui/src/org/eclipse/equinox/internal/p2/ui/UpdateManagerCompatibility.java new file mode 100644 index 0000000000..b1adf7354b --- /dev/null +++ b/tycho-its/projects/api-tools/missing-bin/org.eclipse.equinox.p2.ui/src/org/eclipse/equinox/internal/p2/ui/UpdateManagerCompatibility.java @@ -0,0 +1,284 @@ +/******************************************************************************* + * Copyright (c) 2008, 2018 IBM Corporation and others. + * + * This program and the accompanying materials + * are made available under the terms of the Eclipse Public License 2.0 + * which accompanies this distribution, and is available at + * https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + * + * Contributors: + * IBM Corporation - initial API and implementation + *******************************************************************************/ +package org.eclipse.equinox.internal.p2.ui; + +import java.io.*; +import java.net.URI; +import java.net.URISyntaxException; +import java.util.Vector; +import javax.xml.parsers.*; +import org.eclipse.core.runtime.*; +import org.eclipse.equinox.internal.p2.core.helpers.SecureXMLUtil; +import org.eclipse.equinox.internal.p2.ui.model.MetadataRepositoryElement; +import org.eclipse.equinox.p2.engine.IProvisioningPlan; +import org.eclipse.equinox.p2.metadata.IInstallableUnit; +import org.eclipse.equinox.p2.query.IQueryResult; +import org.eclipse.equinox.p2.query.QueryUtil; +import org.eclipse.jface.dialogs.MessageDialog; +import org.eclipse.osgi.util.NLS; +import org.eclipse.swt.SWT; +import org.eclipse.swt.widgets.FileDialog; +import org.eclipse.swt.widgets.Shell; +import org.eclipse.ui.statushandlers.StatusManager; +import org.w3c.dom.*; +import org.xml.sax.SAXException; + +/** + * Utility methods involving compatibility with the Eclipse Update Manager. + * + * @since 3.4 + * + */ +public class UpdateManagerCompatibility { + + // This value was copied from MetadataGeneratorHelper. Must be the same. + private static final String ECLIPSE_INSTALL_HANDLER_PROP = "org.eclipse.update.installHandler"; //$NON-NLS-1$ + + private static void parse(String fileName, Vector bookmarks) { + File file = new File(fileName); + if (!file.exists()) + return; + + try { + DocumentBuilderFactory documentBuilderFactory = SecureXMLUtil.newSecureDocumentBuilderFactory(); + documentBuilderFactory.setNamespaceAware(true); + DocumentBuilder parser = documentBuilderFactory.newDocumentBuilder(); + Document doc = parser.parse(file); + Node root = doc.getDocumentElement(); + processRoot(root, bookmarks); + } catch (ParserConfigurationException e) { + logFail(e); + } catch (SAXException e) { + logFail(e); + } catch (IOException e) { + logFail(e); + } + } + + private static MetadataRepositoryElement[] getSites(Vector bookmarks) { + return bookmarks.toArray(new MetadataRepositoryElement[bookmarks.size()]); + } + + private static void processRoot(Node root, Vector bookmarks) { + if (root.getNodeName().equals("bookmarks")) { //$NON-NLS-1$ + NodeList children = root.getChildNodes(); + processChildren(children, bookmarks); + } + } + + private static void processChildren(NodeList children, Vector bookmarks) { + for (int i = 0; i < children.getLength(); i++) { + Node child = children.item(i); + if (child.getNodeType() == Node.ELEMENT_NODE) { + if (child.getNodeName().equals("site")) { //$NON-NLS-1$ + createSite(child, bookmarks); + } else if (child.getNodeName().equals("folder")) { //$NON-NLS-1$ + createFolder(child, bookmarks); + } + } + } + } + + private static void createSite(Node child, Vector bookmarks) { + URI uri = null; + try { + uri = URIUtil.fromString((getAttribute(child, "url"))); //$NON-NLS-1$ + } catch (URISyntaxException e) { + logFail(e); + return; + } + + String sel = getAttribute(child, "selected"); //$NON-NLS-1$ + boolean selected = (sel != null && sel.equals("true")); //$NON-NLS-1$ + + MetadataRepositoryElement element = new MetadataRepositoryElement(null, uri, selected); + String nickname = getAttribute(child, "name"); //$NON-NLS-1$ + if (nickname != null && nickname.length() > 0) + element.setNickname(nickname); + bookmarks.add(element); + } + + private static void createFolder(Node child, Vector bookmarks) { + if (child.hasChildNodes()) + processChildren(child.getChildNodes(), bookmarks); + } + + private static String getAttribute(Node node, String name) { + NamedNodeMap atts = node.getAttributes(); + Node att = atts.getNamedItem(name); + if (att != null) { + return att.getNodeValue(); + } + return ""; //$NON-NLS-1$ + } + + private static void store(String fileName, Vector bookmarks) { + FileOutputStream fos = null; + OutputStreamWriter osw = null; + PrintWriter writer = null; + try { + fos = new FileOutputStream(fileName); + osw = new OutputStreamWriter(fos, "UTF8"); //$NON-NLS-1$ + writer = new PrintWriter(osw); + writer.println(""); //$NON-NLS-1$ + writer.println(""); //$NON-NLS-1$ + for (MetadataRepositoryElement obj : bookmarks) { + writeObject(" ", obj, writer); //$NON-NLS-1$ + } + } catch (IOException e) { + logFail(e); + } finally { + if (writer != null) { + writer.println(""); //$NON-NLS-1$ + writer.flush(); + writer.close(); + } + try { + if (osw != null) + osw.close(); + } catch (IOException e1) { + logFail(e1); + } + try { + if (fos != null) + fos.close(); + } catch (IOException e2) { + logFail(e2); + } + } + } + + private static void writeObject(String indent, Object obj, PrintWriter writer) { + if (obj instanceof MetadataRepositoryElement) { + MetadataRepositoryElement element = (MetadataRepositoryElement) obj; + String sel = element.isEnabled() ? "true" : "false"; //$NON-NLS-1$ //$NON-NLS-2$ + String name = element.getName(); + writer.print(indent + ""); //$NON-NLS-1$ + } + } + + public static IStatus getInstallHandlerStatus(IProvisioningPlan plan) { + IQueryResult result = plan.getAdditions().query(QueryUtil.createIUAnyQuery(), null); + for (IInstallableUnit iu : result) { + if (iu != null && iu.getProperty(ECLIPSE_INSTALL_HANDLER_PROP) != null) + return new Status(IStatus.ERROR, ProvUIActivator.PLUGIN_ID, NLS.bind(ProvUIMessages.UpdateManagerCompatibility_ItemRequiresUpdateManager, iu.getId())); + } + return Status.OK_STATUS; + } + + /** + * Prompt the user for a file and import the sites specified in that + * file. Return the collection of repo elements in the import. + * @param shell the shell used to parent any dialogs used. + */ + public static MetadataRepositoryElement[] importSites(Shell shell) { + FileDialog dialog = new FileDialog(shell); + dialog.setText(ProvUIMessages.UpdateManagerCompatibility_ImportSitesTitle); + dialog.setFilterExtensions(new String[] {"*.xml", "*"}); //$NON-NLS-1$ //$NON-NLS-2$ + + MetadataRepositoryElement[] sites = null; + + String bookmarksFile = dialog.open(); + while (bookmarksFile != null && sites == null) { + File file = new File(bookmarksFile); + sites = readBookmarkFile(file); + if (sites == null || sites.length == 0) { + MessageDialog.openInformation(shell, ProvUIMessages.UpdateManagerCompatibility_InvalidSitesTitle, ProvUIMessages.UpdateManagerCompatibility_InvalidSiteFileMessage); + bookmarksFile = dialog.open(); + } + } + return sites == null ? new MetadataRepositoryElement[0] : sites; + } + + public static MetadataRepositoryElement[] readBookmarkFile(File file) { + Vector bookmarks = new Vector<>(); + parse(file.getAbsolutePath(), bookmarks); + return getSites(bookmarks); + } + + public static void writeBookmarkFile(String filename, MetadataRepositoryElement[] sites) { + Vector bookmarks = new Vector<>(sites.length); + for (MetadataRepositoryElement site : sites) + bookmarks.add(site); + store(filename, bookmarks); + + } + + /** + * Export the specified list of sites to a bookmarks file that + * can be read later. + * + * @param shell the shell used to parent the export dialog + * @param sites the sites to export + */ + + public static void exportSites(Shell shell, MetadataRepositoryElement[] sites) { + FileDialog dialog = new FileDialog(shell, SWT.SAVE); + dialog.setText(ProvUIMessages.UpdateManagerCompatibility_ExportSitesTitle); + dialog.setFileName("bookmarks.xml"); //$NON-NLS-1$ + dialog.setFilterExtensions(new String[] {"*.xml", "*"}); //$NON-NLS-1$ //$NON-NLS-2$ + dialog.setOverwrite(true); + + String bookmarksFile = dialog.open(); + if (bookmarksFile == null) + return; + + writeBookmarkFile(bookmarksFile, sites); + } + + /** + * Open the old UpdateManager installer UI using the specified shell. + * We do not call the UpdateManagerUI class directly because we want to be able to be configured + * without requiring those plug-ins. Instead, we invoke a known command. + */ + public static void openInstaller() { + ProvUI.openUpdateManagerInstaller(null); + } + + private static void logFail(Throwable t) { + Status failStatus = new Status(IStatus.ERROR, ProvUIActivator.PLUGIN_ID, t.getLocalizedMessage(), t); + ProvUI.reportStatus(failStatus, StatusManager.LOG); + } + + private static String getWritableXMLString(String value) { + StringBuilder buf = new StringBuilder(); + if (value == null) + return buf.toString(); + for (int i = 0; i < value.length(); i++) { + char c = value.charAt(i); + switch (c) { + case '&' : + buf.append("&"); //$NON-NLS-1$ + break; + case '<' : + buf.append("<"); //$NON-NLS-1$ + break; + case '>' : + buf.append(">"); //$NON-NLS-1$ + break; + case '\'' : + buf.append("'"); //$NON-NLS-1$ + break; + case '\"' : + buf.append("""); //$NON-NLS-1$ + break; + default : + buf.append(c); + break; + } + } + return buf.toString(); + } +} \ No newline at end of file diff --git a/tycho-its/projects/api-tools/missing-bin/org.eclipse.equinox.p2.ui/src/org/eclipse/equinox/internal/p2/ui/ValidationDialogServiceUI.java b/tycho-its/projects/api-tools/missing-bin/org.eclipse.equinox.p2.ui/src/org/eclipse/equinox/internal/p2/ui/ValidationDialogServiceUI.java new file mode 100644 index 0000000000..7dd479470f --- /dev/null +++ b/tycho-its/projects/api-tools/missing-bin/org.eclipse.equinox.p2.ui/src/org/eclipse/equinox/internal/p2/ui/ValidationDialogServiceUI.java @@ -0,0 +1,611 @@ +/******************************************************************************* + * Copyright (c) 2008, 2018 IBM Corporation and others. + * + * This program and the accompanying materials + * are made available under the terms of the Eclipse Public License 2.0 + * which accompanies this distribution, and is available at + * https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + * + * Contributors: + * IBM Corporation - initial API and implementation + * Rapicorp, Inc. - add support for information dialog + *******************************************************************************/ +package org.eclipse.equinox.internal.p2.ui; + +import java.io.File; +import java.net.URI; +import java.net.URL; +import java.security.cert.Certificate; +import java.security.cert.X509Certificate; +import java.util.*; +import java.util.List; +import java.util.concurrent.atomic.AtomicBoolean; +import java.util.function.Consumer; +import java.util.function.Function; +import java.util.stream.Collectors; +import org.bouncycastle.openpgp.PGPPublicKey; +import org.eclipse.core.runtime.*; +import org.eclipse.core.runtime.jobs.Job; +import org.eclipse.equinox.internal.p2.engine.phases.AuthorityChecker; +import org.eclipse.equinox.internal.p2.ui.dialogs.*; +import org.eclipse.equinox.p2.core.IProvisioningAgent; +import org.eclipse.equinox.p2.core.UIServices; +import org.eclipse.equinox.p2.metadata.IArtifactKey; +import org.eclipse.equinox.p2.metadata.IInstallableUnit; +import org.eclipse.equinox.p2.repository.artifact.spi.IArtifactUIServices; +import org.eclipse.equinox.p2.repository.metadata.spi.IInstallableUnitUIServices; +import org.eclipse.equinox.p2.repository.spi.PGPPublicKeyService; +import org.eclipse.equinox.p2.ui.LoadMetadataRepositoryJob; +import org.eclipse.jface.dialogs.*; +import org.eclipse.jface.viewers.TreeNode; +import org.eclipse.jface.window.IShellProvider; +import org.eclipse.jface.window.Window; +import org.eclipse.osgi.util.NLS; +import org.eclipse.swt.SWT; +import org.eclipse.swt.events.SelectionListener; +import org.eclipse.swt.graphics.Image; +import org.eclipse.swt.widgets.*; +import org.eclipse.ui.PlatformUI; + +/** + * The default GUI-based implementation of {@link UIServices}. The service + * declaration is made in the serviceui_component.xml file. + * + */ +public class ValidationDialogServiceUI extends UIServices implements IArtifactUIServices, IInstallableUnitUIServices { + + private final IProvisioningAgent agent; + + private Display display; + + private Consumer linkHandler = link -> { + if (PlatformUI.isWorkbenchRunning()) { + try { + URL url = new URL(link); + PlatformUI.getWorkbench().getBrowserSupport().getExternalBrowser().openURL(url); + } catch (Exception x) { + ProvUIActivator.getDefault().getLog() + .log(new Status(IStatus.ERROR, ProvUIActivator.PLUGIN_ID, x.getMessage(), x)); + } + } + }; + + private IShellProvider shellProvider = () -> ProvUI.getDefaultParentShell(); + + public ValidationDialogServiceUI() { + this(null); + } + + public ValidationDialogServiceUI(IProvisioningAgent agent) { + this.agent = agent; + } + + static final class MessageDialogWithLink extends MessageDialog { + private final String linkText; + private final Consumer linkOpener; + + MessageDialogWithLink(Shell parentShell, String dialogTitle, Image dialogTitleImage, String dialogMessage, + int dialogImageType, String[] dialogButtonLabels, int defaultIndex, String linkText, + Consumer linkOpener) { + super(parentShell, dialogTitle, dialogTitleImage, dialogMessage, dialogImageType, dialogButtonLabels, + defaultIndex); + this.linkText = linkText; + this.linkOpener = linkOpener; + } + + @Override + protected Control createCustomArea(Composite parent) { + if (linkText == null) + return super.createCustomArea(parent); + + Link link = new Link(parent, SWT.NONE); + link.setText(linkText); + link.addSelectionListener(SelectionListener.widgetSelectedAdapter(e -> { + linkOpener.accept(e.text); + })); + return link; + } + } + + /** + * Subclassed to add a cancel button to the error dialog. + */ + static class OkCancelErrorDialog extends ErrorDialog { + + public OkCancelErrorDialog(Shell parentShell, String dialogTitle, String message, IStatus status, + int displayMask) { + super(parentShell, dialogTitle, message, status, displayMask); + } + + @Override + protected void createButtonsForButtonBar(Composite parent) { + // create OK and Details buttons + createButton(parent, IDialogConstants.OK_ID, ProvUIMessages.ServiceUI_InstallAnywayAction_Label, true); + createButton(parent, IDialogConstants.CANCEL_ID, IDialogConstants.CANCEL_LABEL, true); + createDetailsButton(parent); + } + } + + @Override + public AuthenticationInfo getUsernamePassword(final String location) { + + final AuthenticationInfo[] result = new AuthenticationInfo[1]; + if (!suppressAuthentication() && !isHeadless()) { + getDisplay().syncExec(() -> { + Shell shell = shellProvider.getShell(); + String message = NLS.bind(ProvUIMessages.ServiceUI_LoginDetails, location); + UserValidationDialog dialog = new UserValidationDialog(shell, ProvUIMessages.ServiceUI_LoginRequired, + null, message); + int dialogCode = dialog.open(); + if (dialogCode == Window.OK) { + result[0] = dialog.getResult(); + } else if (dialogCode == Window.CANCEL) { + result[0] = AUTHENTICATION_PROMPT_CANCELED; + } + }); + } + return result[0]; + } + + private boolean suppressAuthentication() { + Job job = Job.getJobManager().currentJob(); + if (job != null) { + return job.getProperty(LoadMetadataRepositoryJob.SUPPRESS_AUTHENTICATION_JOB_MARKER) != null; + } + return false; + } + + @Override + public TrustInfo getTrustInfo(Certificate[][] untrustedChains, final String[] unsignedDetail) { + return getTrustInfo(untrustedChains, Collections.emptyList(), unsignedDetail); + } + + @Override + public TrustInfo getTrustInfo(Certificate[][] untrustedChains, Collection untrustedPublicKeys, + final String[] unsignedDetail) { + if (untrustedChains == null) { + untrustedChains = new Certificate[][] {}; + } + boolean trustUnsigned = true; + boolean persistTrust = false; + List trustedCertificates = new ArrayList<>(); + List trustedKeys = new ArrayList<>(); + // Some day we may summarize all of this in one UI, or perhaps we'll have a + // preference to honor regarding + // unsigned content. For now we prompt separately first as to whether unsigned + // detail should be trusted + if (!isHeadless() && unsignedDetail != null && unsignedDetail.length > 0) { + final boolean[] result = new boolean[] { false }; + getDisplay().syncExec(new Runnable() { + @Override + public void run() { + Shell shell = shellProvider.getShell(); + OkCancelErrorDialog dialog = new OkCancelErrorDialog(shell, ProvUIMessages.ServiceUI_warning_title, + null, createStatus(), IStatus.WARNING); + result[0] = dialog.open() == IDialogConstants.OK_ID; + } + + private IStatus createStatus() { + MultiStatus parent = new MultiStatus(ProvUIActivator.PLUGIN_ID, 0, + ProvUIMessages.ServiceUI_unsigned_message, null); + for (String element : unsignedDetail) { + parent.add(new Status(IStatus.WARNING, ProvUIActivator.PLUGIN_ID, element)); + } + return parent; + } + }); + trustUnsigned = result[0]; + } + // For now, there is no need to show certificates if there was unsigned content + // and we don't trust it. + if (!trustUnsigned) + return new TrustInfo(trustedCertificates, trustedKeys, persistTrust, trustUnsigned); + + // We've established trust for unsigned content, now examine the untrusted + // chains + if (!isHeadless() && (untrustedChains.length > 0 || !untrustedPublicKeys.isEmpty())) { + return getTrustInfo( + Arrays.stream(untrustedChains).collect( + Collectors.toMap(Arrays::asList, it -> Set.of(), (e1, e2) -> e1, LinkedHashMap::new)), + untrustedPublicKeys.stream().collect( + Collectors.toMap(Function.identity(), it -> Set.of(), (e1, e2) -> e1, LinkedHashMap::new)), + null, null); + + } + + return new TrustInfo(trustedCertificates, trustedKeys, persistTrust, trustUnsigned); + } + + @Override + public TrustInfo getTrustInfo(Map, Set> untrustedCertificates, + Map> untrustedPGPKeys, // + Set unsignedArtifacts, // + Map artifacts) { + boolean trustUnsigned = true; + AtomicBoolean persistTrust = new AtomicBoolean(); + AtomicBoolean trustAlways = new AtomicBoolean(); + List trustedCertificates = new ArrayList<>(); + List trustedKeys = new ArrayList<>(); + if (!isHeadless()) { + TreeNode[] input = createTreeNodes(untrustedCertificates, untrustedPGPKeys, unsignedArtifacts, artifacts); + if (input.length != 0) { + trustUnsigned = unsignedArtifacts == null || unsignedArtifacts.isEmpty(); + List result = new ArrayList<>(); + getDisplay().syncExec(() -> { + Shell shell = shellProvider.getShell(); + TrustCertificateDialog trustCertificateDialog = new TrustCertificateDialog(shell, input); + if (trustCertificateDialog.open() == Window.OK) { + Object[] dialogResult = trustCertificateDialog.getResult(); + if (dialogResult != null) { + result.addAll(Arrays.asList(dialogResult)); + } + persistTrust.set(trustCertificateDialog.isRememberSelectedSigners()); + trustAlways.set(trustCertificateDialog.isTrustAlways()); + } + }); + for (Object o : result) { + if (o instanceof TreeNode) { + o = ((TreeNode) o).getValue(); + } + if (o instanceof Certificate) { + trustedCertificates.add((Certificate) o); + } else if (o instanceof PGPPublicKey) { + trustedKeys.add((PGPPublicKey) o); + } else if (o == null) { + trustUnsigned = true; + } + } + } + } + + return new TrustInfo(trustedCertificates, trustedKeys, persistTrust.get(), trustUnsigned, trustAlways.get()); + } + + private TreeNode[] createTreeNodes(Map, Set> untrustedCertificates, + Map> untrustedPGPKeys, // + Set unsignedArtifacts, // + Map artifacts) { + + List children = new ArrayList<>(); + if (untrustedCertificates != null && !untrustedCertificates.isEmpty()) { + for (Map.Entry, Set> entry : untrustedCertificates.entrySet()) { + ExtendedTreeNode parent = null; + List key = entry.getKey(); + Set associatedArtifacts = entry.getValue(); + for (Certificate certificate : key) { + ExtendedTreeNode node = new ExtendedTreeNode(certificate, associatedArtifacts); + if (parent == null) { + children.add(node); + } else { + node.setParent(parent); + parent.setChildren(new TreeNode[] { node }); + } + parent = node; + } + } + } + + if (untrustedPGPKeys != null && !untrustedPGPKeys.isEmpty()) { + PGPPublicKeyService keyService = agent == null ? null : agent.getService(PGPPublicKeyService.class); + for (Map.Entry> entry : untrustedPGPKeys.entrySet()) { + PGPPublicKey key = entry.getKey(); + Set associatedArtifacts = entry.getValue(); + Date verifiedRevocationDate = keyService == null ? null : keyService.getVerifiedRevocationDate(key); + ExtendedTreeNode node = new ExtendedTreeNode(key, associatedArtifacts, verifiedRevocationDate); + children.add(node); + expandChildren(node, key, keyService, new HashSet<>(), Integer.getInteger("p2.pgp.trust.depth", 3)); //$NON-NLS-1$ + } + } + + if (unsignedArtifacts != null && !unsignedArtifacts.isEmpty()) { + ExtendedTreeNode node = new ExtendedTreeNode(null, unsignedArtifacts); + children.add(node); + + } + + return children.toArray(TreeNode[]::new); + } + + private void expandChildren(TreeNode result, PGPPublicKey key, PGPPublicKeyService keyService, + Set visited, int remainingDepth) { + if (keyService != null && remainingDepth > 0 && visited.add(key)) { + Set certifications = keyService.getVerifiedCertifications(key); + if (certifications != null && !certifications.isEmpty()) { + List children = new ArrayList<>(); + for (PGPPublicKey certifyingKey : certifications) { + if (visited.add(certifyingKey)) { + Date verifiedRevocationDate = keyService.getVerifiedRevocationDate(key); + TreeNode treeNode = new ExtendedTreeNode(certifyingKey, null, verifiedRevocationDate); + children.add(treeNode); + } + } + + if (!children.isEmpty()) { + result.setChildren(children.toArray(TreeNode[]::new)); + children.forEach(child -> { + child.setParent(result); + PGPPublicKey certifyingKey = (PGPPublicKey) child.getValue(); + visited.remove(certifyingKey); + expandChildren(child, certifyingKey, keyService, visited, remainingDepth - 1); + visited.add(certifyingKey); + }); + } + } + } + } + + @Override + public AuthenticationInfo getUsernamePassword(final String location, final AuthenticationInfo previousInfo) { + final AuthenticationInfo[] result = new AuthenticationInfo[1]; + if (!suppressAuthentication() && !isHeadless()) { + getDisplay().syncExec(() -> { + Shell shell = shellProvider.getShell(); + String message = null; + if (previousInfo.saveResult()) + message = NLS.bind(ProvUIMessages.ProvUIMessages_SavedNotAccepted_EnterFor_0, location); + else + message = NLS.bind(ProvUIMessages.ProvUIMessages_NotAccepted_EnterFor_0, location); + + UserValidationDialog dialog = new UserValidationDialog(previousInfo, shell, + ProvUIMessages.ServiceUI_LoginRequired, null, message); + int dialogCode = dialog.open(); + if (dialogCode == Window.OK) { + result[0] = dialog.getResult(); + } else if (dialogCode == Window.CANCEL) { + result[0] = AUTHENTICATION_PROMPT_CANCELED; + } + }); + } + return result[0]; + } + + @Override + public void showInformationMessage(final String title, final String text, final String linkText) { + if (isHeadless()) { + super.showInformationMessage(title, text, linkText); + return; + } + getDisplay().syncExec(() -> { + MessageDialog dialog = new MessageDialogWithLink(shellProvider.getShell(), title, null, text, + MessageDialog.INFORMATION, new String[] { IDialogConstants.OK_LABEL }, 0, linkText, linkHandler); + dialog.open(); + }); + } + + private static class OriginTreeNode extends TreeNode implements IAdaptable, Comparable { + + private final Set ius = new TreeSet<>(); + + private final List certificates = new ArrayList<>(); + + private final List children = new ArrayList<>(); + + public OriginTreeNode(URI value, List certificates) { + super(value); + if (certificates != null) { + this.certificates.addAll(certificates); + } + } + + @Override + public int compareTo(OriginTreeNode o) { + return ((URI) getValue()).compareTo(((URI) o.getValue())); + } + + @Override + public T getAdapter(Class adapter) { + if (adapter == X509Certificate.class && !certificates.isEmpty()) { + if (certificates.get(0) instanceof X509Certificate certificate) { + return adapter.cast(certificate); + } + } + if (adapter.equals(Certificate[].class)) { + return adapter.cast(certificates.toArray(Certificate[]::new)); + } + if (adapter.equals(IInstallableUnit[].class)) { + return adapter.cast(ius.toArray(IInstallableUnit[]::new)); + } + return null; + } + + public Set getIUs() { + return ius; + } + + public void setParent(OriginTreeNode parent) { + if (parent != getParent()) { + super.setParent(parent); + parent.children.add(this); + children.sort(null); + } + } + + @Override + public TreeNode[] getChildren() { + return children.toArray(TreeNode[]::new); + } + + @Override + public boolean hasChildren() { + return !children.isEmpty(); + } + } + + @Override + public TrustAuthorityInfo getTrustAuthorityInfo(Map> siteIUs, + Map> authorityCertificates) { + var trustedAuthorities = new TreeSet(); + var persistTrust = new AtomicBoolean(); + var trustAlways = new AtomicBoolean(); + if (!isHeadless()) { + var nodes = new TreeMap(); + for (var entry : siteIUs.entrySet()) { + URI location = entry.getKey(); + var authorityChain = AuthorityChecker.getAuthorityChain(location); + if (authorityChain.size() > 3) { + authorityChain.subList(2, authorityChain.size() - 1).clear(); + } + var ius = entry.getValue(); + var certificates = authorityCertificates.get(location); + OriginTreeNode parent = null; + for (var uri : authorityChain) { + var treeNode = nodes.computeIfAbsent(uri, key -> new OriginTreeNode(key, certificates)); + treeNode.getIUs().addAll(ius); + treeNode.setParent(parent); + parent = treeNode; + } + } + + if (!nodes.isEmpty()) { + nodes.values().removeIf(node -> node.getParent() != null); + getDisplay().syncExec(() -> { + var shell = shellProvider.getShell(); + var trustCertificateDialog = new TrustAuthorityDialog(shell, + nodes.values().toArray(TreeNode[]::new)); + if (trustCertificateDialog.open() == Window.OK) { + URI[] dialogResult = trustCertificateDialog.getResult(); + if (dialogResult != null) { + trustedAuthorities.addAll(Arrays.asList(dialogResult)); + } + persistTrust.set(trustCertificateDialog.isRememberSelectedAuthorities()); + trustAlways.set(trustCertificateDialog.isTrustAlways()); + } + }); + } + } + + return new TrustAuthorityInfo(trustedAuthorities, persistTrust.get(), trustAlways.get()); + } + + /** + * Returns a handler (used by + * {@link #showInformationMessage(String, String, String)}) to open a link in an + * external browser. + * + * @return a handler to open a link in an external browser. + * + * @since 2.7.400 + */ + public Consumer getLinkHandler() { + return linkHandler; + } + + /** + * Sets the handler used by + * {@link #showInformationMessage(String, String, String)} to open a link in an + * external browser. + * + * @param linkHandler the handler for opening links in an external browser. + * + * @since 2.7.400 + */ + public void setLinkHandler(Consumer linkHandler) { + this.linkHandler = linkHandler; + } + + /** + * Returns a shell that is appropriate to use as the parent for a modal dialog + * about to be opened. + * + * @return a shell that is appropriate to use as the parent for a modal dialog + * about to be opened. + * + * @see ProvUI#getDefaultParentShell() + * + * @since 2.7.400 + */ + public IShellProvider getShellProvider() { + return shellProvider; + } + + /** + * Set the provider that yields a shell that is appropriate to use as the parent + * for a modal dialog about to be opened. + * + * @param shellProvider the provider of a shell that is appropriate to use as + * the parent for a modal dialog about to be opened. + */ + public void setShellProvider(IShellProvider shellProvider) { + this.shellProvider = shellProvider; + } + + /** + * Returns the display of the workbench or the display set by + * {@link #setDisplay(Display)} in a non-workbench application. + * + * @since 2.7.400 + */ + public Display getDisplay() { + if (display == null && PlatformUI.isWorkbenchRunning()) { + display = PlatformUI.getWorkbench().getDisplay(); + } + return display; + } + + /** + * Can be called once to set the display in a non-workbench application. + * + * @throws IllegalStateException if there is a workbench running or the display + * has already been set differently. + * + * @since 2.7.400 + */ + public void setDisplay(Display display) { + if (this.display != null && this.display != display) { + throw new IllegalStateException("Cannot change the display"); //$NON-NLS-1$ + } + this.display = display; + } + + private boolean isHeadless() { + // If there is no UI available and we are still the IServiceUI, + // assume that the operation should proceed. See + // https://bugs.eclipse.org/bugs/show_bug.cgi?id=291049 + // + // But we shouldn't just assume that no workbench mean no display and no head. + // It should be possible to reuse this class in an application without a + // workbench, e.g., the Eclipse Installer. + return getDisplay() == null; + } + + private static class ExtendedTreeNode extends TreeNode implements IAdaptable { + private final Set artifacts; + private Date revocationDate; + + public ExtendedTreeNode(Object value) { + super(value); + artifacts = null; + } + + public ExtendedTreeNode(Object value, Set artifacts) { + this(value, artifacts, null); + } + + public ExtendedTreeNode(Object value, Set artifacts, Date revocationDate) { + super(value); + this.artifacts = artifacts; + this.revocationDate = revocationDate; + } + + @Override + public T getAdapter(Class adapter) { + if (adapter.isInstance(this)) { + return adapter.cast(this); + } + if (adapter.isInstance(getValue())) { + return adapter.cast(value); + } + if (adapter == IArtifactKey[].class && artifacts != null) { + return adapter.cast(artifacts.toArray(IArtifactKey[]::new)); + } + if (adapter == Date.class) { + return adapter.cast(revocationDate); + } + + return null; + } + } + +} diff --git a/tycho-its/projects/api-tools/missing-bin/org.eclipse.equinox.p2.ui/src/org/eclipse/equinox/internal/p2/ui/actions/ColocatedRepositoryAction.java b/tycho-its/projects/api-tools/missing-bin/org.eclipse.equinox.p2.ui/src/org/eclipse/equinox/internal/p2/ui/actions/ColocatedRepositoryAction.java new file mode 100644 index 0000000000..bdaf317d4f --- /dev/null +++ b/tycho-its/projects/api-tools/missing-bin/org.eclipse.equinox.p2.ui/src/org/eclipse/equinox/internal/p2/ui/actions/ColocatedRepositoryAction.java @@ -0,0 +1,47 @@ +/******************************************************************************* + * Copyright (c) 2008, 2010 IBM Corporation and others. + * + * This program and the accompanying materials + * are made available under the terms of the Eclipse Public License 2.0 + * which accompanies this distribution, and is available at + * https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + * + * Contributors: + * IBM Corporation - initial API and implementation + *******************************************************************************/ + +package org.eclipse.equinox.internal.p2.ui.actions; + +import java.net.URI; +import java.util.ArrayList; +import java.util.List; +import org.eclipse.equinox.internal.p2.ui.model.MetadataRepositoryElement; +import org.eclipse.equinox.p2.ui.ProvisioningUI; +import org.eclipse.jface.viewers.ISelectionProvider; + +public abstract class ColocatedRepositoryAction extends ProvisioningAction { + + public ColocatedRepositoryAction(ProvisioningUI ui, String label, String tooltipText, + ISelectionProvider selectionProvider) { + super(ui, label, selectionProvider); + setToolTipText(tooltipText); + init(); + } + + protected URI[] getSelectedLocations(Object[] selectionArray) { + List urls = new ArrayList<>(); + for (Object element : selectionArray) { + if (element instanceof MetadataRepositoryElement) { + urls.add(((MetadataRepositoryElement) element).getLocation()); + } + } + return urls.toArray(new URI[urls.size()]); + } + + @Override + protected void checkEnablement(Object[] selectionArray) { + setEnabled(getSelectedLocations(selectionArray).length > 0); + } +} diff --git a/tycho-its/projects/api-tools/missing-bin/org.eclipse.equinox.p2.ui/src/org/eclipse/equinox/internal/p2/ui/actions/ExistingIUInProfileAction.java b/tycho-its/projects/api-tools/missing-bin/org.eclipse.equinox.p2.ui/src/org/eclipse/equinox/internal/p2/ui/actions/ExistingIUInProfileAction.java new file mode 100644 index 0000000000..e671b4e0a2 --- /dev/null +++ b/tycho-its/projects/api-tools/missing-bin/org.eclipse.equinox.p2.ui/src/org/eclipse/equinox/internal/p2/ui/actions/ExistingIUInProfileAction.java @@ -0,0 +1,103 @@ +/******************************************************************************* + * Copyright (c) 2008, 2010 IBM Corporation and others. + * + * This program and the accompanying materials + * are made available under the terms of the Eclipse Public License 2.0 + * which accompanies this distribution, and is available at + * https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + * + * Contributors: + * IBM Corporation - initial API and implementation + *******************************************************************************/ + +package org.eclipse.equinox.internal.p2.ui.actions; + +import org.eclipse.equinox.p2.query.QueryUtil; + +import org.eclipse.equinox.internal.p2.ui.ProvUI; +import org.eclipse.equinox.internal.p2.ui.model.IIUElement; +import org.eclipse.equinox.internal.p2.ui.model.InstalledIUElement; +import org.eclipse.equinox.p2.engine.IProfile; +import org.eclipse.equinox.p2.metadata.IInstallableUnit; +import org.eclipse.equinox.p2.ui.ProvisioningUI; +import org.eclipse.jface.viewers.ISelectionProvider; + +/** + * + * Abstract class that implements the enablement rules for actions that + * affect IU's already in a profile. The action only enables when all of the + * IU's involved are top level IU's from the same profile. + * + * @since 3.5 + * + */ +public abstract class ExistingIUInProfileAction extends ProfileModificationAction { + + public ExistingIUInProfileAction(ProvisioningUI ui, String label, ISelectionProvider selectionProvider, String profileId) { + super(ui, label, selectionProvider, profileId); + } + + @Override + protected boolean isEnabledFor(Object[] selectionArray) { + Object parent = null; + // We don't want to prompt for a profile during validation, + // so we only consider the profile id that was set, or the profile + // referred to by the element itself.. + IProfile profile = getProfile(); + if (selectionArray.length > 0) { + for (Object selection : selectionArray) { + if (selection instanceof InstalledIUElement) { + InstalledIUElement element = (InstalledIUElement) selection; + // If the parents are different, then they are either from + // different profiles or are nested in different parts of the tree. + // Either way, this makes the selection invalid. + if (parent == null) { + parent = element.getParent(element); + } else if (parent != element.getParent(element)) { + return false; + } + // Now consider the validity of the element on its own + if (!isSelectable(element.getIU(), profile)) + return false; + } else { + IInstallableUnit iu = ProvUI.getAdapter(selection, IInstallableUnit.class); + if (iu == null || !isSelectable(iu)) + return false; + } + } + return true; + } + return false; + } + + @Override + protected boolean isSelectable(IIUElement element) { + if (!super.isSelectable(element)) + return false; + Object parent = element.getParent(element); + if (parent != null) { + IProfile profile = ProvUI.getAdapter(parent, IProfile.class); + if (profile != null) + return isSelectable(element.getIU(), profile); + } + return false; + } + + @Override + protected boolean isSelectable(IInstallableUnit iu) { + if (!super.isSelectable(iu)) + return false; + return isSelectable(iu, getProfile()); + } + + private boolean isSelectable(IInstallableUnit iu, IProfile profile) { + int lock = getLock(profile, iu); + if ((lock & getLockConstant()) == getLockConstant()) + return false; + return !profile.query(QueryUtil.createPipeQuery(QueryUtil.createIUQuery(iu), getPolicy().getVisibleInstalledIUQuery()), null).isEmpty(); + } + + protected abstract int getLockConstant(); +} diff --git a/tycho-its/projects/api-tools/missing-bin/org.eclipse.equinox.p2.ui/src/org/eclipse/equinox/internal/p2/ui/actions/ProfileModificationAction.java b/tycho-its/projects/api-tools/missing-bin/org.eclipse.equinox.p2.ui/src/org/eclipse/equinox/internal/p2/ui/actions/ProfileModificationAction.java new file mode 100644 index 0000000000..22cc60470f --- /dev/null +++ b/tycho-its/projects/api-tools/missing-bin/org.eclipse.equinox.p2.ui/src/org/eclipse/equinox/internal/p2/ui/actions/ProfileModificationAction.java @@ -0,0 +1,213 @@ +/******************************************************************************* + * Copyright (c) 2007, 2018 IBM Corporation and others. + * + * This program and the accompanying materials + * are made available under the terms of the Eclipse Public License 2.0 + * which accompanies this distribution, and is available at + * https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + * + * Contributors: + * IBM Corporation - initial API and implementation + * Sonatype, Inc. - ongoing development + *******************************************************************************/ + +package org.eclipse.equinox.internal.p2.ui.actions; + +import java.util.*; +import org.eclipse.core.runtime.IStatus; +import org.eclipse.core.runtime.Status; +import org.eclipse.core.runtime.jobs.IJobChangeEvent; +import org.eclipse.core.runtime.jobs.JobChangeAdapter; +import org.eclipse.equinox.internal.p2.ui.*; +import org.eclipse.equinox.internal.p2.ui.model.CategoryElement; +import org.eclipse.equinox.internal.p2.ui.model.IIUElement; +import org.eclipse.equinox.p2.engine.IProfile; +import org.eclipse.equinox.p2.metadata.IInstallableUnit; +import org.eclipse.equinox.p2.operations.ProfileChangeOperation; +import org.eclipse.equinox.p2.operations.ProvisioningJob; +import org.eclipse.equinox.p2.ui.LicenseManager; +import org.eclipse.equinox.p2.ui.ProvisioningUI; +import org.eclipse.jface.viewers.ISelectionProvider; +import org.eclipse.jface.window.Window; +import org.eclipse.osgi.util.NLS; +import org.eclipse.ui.PlatformUI; +import org.eclipse.ui.statushandlers.StatusManager; + +public abstract class ProfileModificationAction extends ProvisioningAction { + public static final int ACTION_NOT_RUN = -1; + String profileId; + int result = ACTION_NOT_RUN; + + protected ProfileModificationAction(ProvisioningUI ui, String text, ISelectionProvider selectionProvider, String profileId) { + super(ui, text, selectionProvider); + this.ui = ui; + this.profileId = profileId; + init(); + } + + @Override + public void run() { + Collection ius = getSelectedIUs(); + // No ius or no profile? + if (isInvalidProfileId() || ius.size() == 0) { + ProvUI.reportStatus(getNoProfileOrSelectionStatus(profileId, ius), StatusManager.BLOCK); + runCanceled(); + return; + } + run(ius, profileId); + } + + protected boolean isInvalidProfileId() { + return profileId == null; + } + + public IProfile getProfile() { + String id = profileId == null ? ui.getProfileId() : profileId; + return ProvUI.getProfileRegistry(ui.getSession()).getProfile(id); + } + + protected IStatus getNoProfileOrSelectionStatus(String id, Collection ius) { + return new Status(IStatus.WARNING, ProvUIActivator.PLUGIN_ID, NLS.bind(ProvUIMessages.ProfileModificationAction_InvalidSelections, id, Integer.valueOf(ius.size()))); + } + + protected abstract ProfileChangeOperation getProfileChangeOperation(Collection ius); + + protected void run(final Collection ius, final String id) { + final ProfileChangeOperation operation = getProfileChangeOperation(ius); + ProvisioningJob job = operation.getResolveJob(null); + if (job == null) { + ProvUI.reportStatus(operation.getResolutionResult(), StatusManager.SHOW); + } else { + job.addJobChangeListener(new JobChangeAdapter() { + @Override + public void done(IJobChangeEvent event) { + + if (PlatformUI.isWorkbenchRunning()) { + PlatformUI.getWorkbench().getDisplay().asyncExec(() -> { + if (validateOperation(operation)) + performAction(operation, ius); + }); + } + + } + + }); + // Don't show the error dialog anymore since the remediation operation should be computed + getProvisioningUI().schedule(job, StatusManager.NONE | StatusManager.LOG); + } + // Since we are resolving asynchronously, our job is done. Setting this allows + // callers to decide to close the launching window. + // See https://bugs.eclipse.org/bugs/show_bug.cgi?id=236495 + result = Window.OK; + } + + /** + * Get the integer return code returned by any wizards launched by this + * action. If the action has not been run, return ACTION_NOT_RUN. If the + * action does not open a wizard, return Window.OK if the operation was performed, + * and Window.CANCEL if it was canceled. + * + * @return integer return code + */ + public int getReturnCode() { + return result; + } + + /** + * Validate the operation and return true if the operation should + * be performed with plan. Report any errors to the user before returning false. + * @param operation + * @return a boolean indicating whether the operation should be used in a + * provisioning operation. + */ + protected boolean validateOperation(ProfileChangeOperation operation) { + if (operation != null) { + return getPolicy().continueWorkingWithOperation(operation, getShell()); + } + return false; + } + + protected abstract int performAction(ProfileChangeOperation operation, Collection ius); + + protected IInstallableUnit getIU(Object element) { + return ProvUI.getAdapter(element, IInstallableUnit.class); + + } + + /** + * Return an array of the selected and valid installable units. + * The number of IInstallableUnits in the array may be different than + * the actual number of selections in the action's selection provider. + * That is, if the action is disabled due to invalid selections, + * this method will return those selections that were valid. + * + * @return an array of selected IInstallableUnit that meet the + * enablement criteria for the action. + */ + protected List getSelectedIUs() { + List elements = getStructuredSelection().toList(); + List iusList = new ArrayList<>(elements.size()); + + for (int i = 0; i < elements.size(); i++) { + if (elements.get(i) instanceof IIUElement) { + IIUElement element = (IIUElement) elements.get(i); + if (isSelectable(element)) + iusList.add(getIU(element)); + } else { + IInstallableUnit iu = ProvUI.getAdapter(elements.get(i), IInstallableUnit.class); + if (iu != null && isSelectable(iu)) + iusList.add(iu); + } + } + return iusList; + } + + protected boolean isSelectable(IIUElement element) { + return !(element instanceof CategoryElement); + } + + protected boolean isSelectable(IInstallableUnit iu) { + return !ProvUI.isCategory(iu); + } + + protected LicenseManager getLicenseManager() { + return getProvisioningUI().getLicenseManager(); + } + + @Override + protected final void checkEnablement(Object[] selections) { + if (isEnabledFor(selections)) { + setEnabled(!getProvisioningUI().hasScheduledOperations()); + } else + setEnabled(false); + } + + protected abstract boolean isEnabledFor(Object[] selections); + + protected int getLock(IProfile profile, IInstallableUnit iu) { + if (profile == null) + return IProfile.LOCK_NONE; + try { + String value = profile.getInstallableUnitProperty(iu, IProfile.PROP_PROFILE_LOCKED_IU); + if (value != null) + return Integer.parseInt(value); + } catch (NumberFormatException e) { + // ignore and assume no lock + } + return IProfile.LOCK_NONE; + } + + protected String getProfileProperty(IProfile profile, IInstallableUnit iu, String propertyName) { + if (profile == null || iu == null) + return null; + return profile.getInstallableUnitProperty(iu, propertyName); + } + + protected void runCanceled() { + // The action was canceled, do any cleanup needed before + // it is run again. + result = Window.CANCEL; + } +} diff --git a/tycho-its/projects/api-tools/missing-bin/org.eclipse.equinox.p2.ui/src/org/eclipse/equinox/internal/p2/ui/actions/PropertyDialogAction.java b/tycho-its/projects/api-tools/missing-bin/org.eclipse.equinox.p2.ui/src/org/eclipse/equinox/internal/p2/ui/actions/PropertyDialogAction.java new file mode 100644 index 0000000000..97965dd811 --- /dev/null +++ b/tycho-its/projects/api-tools/missing-bin/org.eclipse.equinox.p2.ui/src/org/eclipse/equinox/internal/p2/ui/actions/PropertyDialogAction.java @@ -0,0 +1,40 @@ +/******************************************************************************* + * Copyright (c) 2007, 2010 IBM Corporation and others. + * + * This program and the accompanying materials + * are made available under the terms of the Eclipse Public License 2.0 + * which accompanies this distribution, and is available at + * https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + * + * Contributors: + * IBM Corporation - initial API and implementation + *******************************************************************************/ + +package org.eclipse.equinox.internal.p2.ui.actions; + +import org.eclipse.jface.viewers.*; +import org.eclipse.jface.window.IShellProvider; + +/** + * PropertyDialogAction which sets its enablement on construction. + * + * @since 3.4 + * + */ + +public class PropertyDialogAction extends org.eclipse.ui.dialogs.PropertyDialogAction { + public PropertyDialogAction(IShellProvider shell, ISelectionProvider provider) { + super(shell, provider); + // prime the selection validation + ISelection selection = provider.getSelection(); + if (selection instanceof IStructuredSelection) { + selectionChanged((IStructuredSelection) selection); + } else { + selectionChanged(selection); + } + + } + +} diff --git a/tycho-its/projects/api-tools/missing-bin/org.eclipse.equinox.p2.ui/src/org/eclipse/equinox/internal/p2/ui/actions/ProvisioningAction.java b/tycho-its/projects/api-tools/missing-bin/org.eclipse.equinox.p2.ui/src/org/eclipse/equinox/internal/p2/ui/actions/ProvisioningAction.java new file mode 100644 index 0000000000..43674157d9 --- /dev/null +++ b/tycho-its/projects/api-tools/missing-bin/org.eclipse.equinox.p2.ui/src/org/eclipse/equinox/internal/p2/ui/actions/ProvisioningAction.java @@ -0,0 +1,94 @@ +/******************************************************************************* + * Copyright (c) 2007, 2010 IBM Corporation and others. + * + * This program and the accompanying materials + * are made available under the terms of the Eclipse Public License 2.0 + * which accompanies this distribution, and is available at + * https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + * + * Contributors: + * IBM Corporation - initial API and implementation + *******************************************************************************/ + +package org.eclipse.equinox.internal.p2.ui.actions; + +import org.eclipse.equinox.internal.p2.ui.ProvUI; +import org.eclipse.equinox.p2.operations.ProvisioningSession; +import org.eclipse.equinox.p2.ui.Policy; +import org.eclipse.equinox.p2.ui.ProvisioningUI; +import org.eclipse.jface.viewers.*; +import org.eclipse.swt.widgets.Shell; +import org.eclipse.ui.actions.SelectionProviderAction; + +public abstract class ProvisioningAction extends SelectionProviderAction { + ProvisioningUI ui; + + protected ProvisioningAction(ProvisioningUI ui, String text, ISelectionProvider selectionProvider) { + super(selectionProvider, text); + this.ui = ui; + } + + /* + * perform initialization that should be done after creation. + */ + protected void init() { + // prime the selection validation + ISelection selection = getSelection(); + if (selection instanceof IStructuredSelection) { + selectionChanged((IStructuredSelection) selection); + } else { + selectionChanged(selection); + } + } + + protected Shell getShell() { + return ProvUI.getDefaultParentShell(); + } + + /* + * Overridden to use the selection from the selection provider, not the one from + * the triggering event. Some selection providers reinterpret the raw selections + */ + @Override + public final void selectionChanged(IStructuredSelection selection) { + ISelection providerSelection = getSelectionProvider().getSelection(); + if (providerSelection instanceof IStructuredSelection) { + checkEnablement(((IStructuredSelection) providerSelection).toArray()); + } else { + // shouldn't really happen, but a provider could decide to de-structure the + // selection + selectionChanged(providerSelection); + } + } + + protected void checkEnablement(Object[] selections) { + // Default is to nothing + } + + /** + * Recheck the enablement. Called by clients when some condition outside of the + * action that may effect its enablement should be changed. + */ + public final void checkEnablement() { + ISelection selection = getSelection(); + if (selection instanceof IStructuredSelection) { + checkEnablement(((IStructuredSelection) selection).toArray()); + } else { + selectionChanged(selection); + } + } + + protected ProvisioningSession getSession() { + return ui.getSession(); + } + + protected Policy getPolicy() { + return ui.getPolicy(); + } + + protected ProvisioningUI getProvisioningUI() { + return ui; + } +} \ No newline at end of file diff --git a/tycho-its/projects/api-tools/missing-bin/org.eclipse.equinox.p2.ui/src/org/eclipse/equinox/internal/p2/ui/actions/RefreshAction.java b/tycho-its/projects/api-tools/missing-bin/org.eclipse.equinox.p2.ui/src/org/eclipse/equinox/internal/p2/ui/actions/RefreshAction.java new file mode 100644 index 0000000000..f9487e45ab --- /dev/null +++ b/tycho-its/projects/api-tools/missing-bin/org.eclipse.equinox.p2.ui/src/org/eclipse/equinox/internal/p2/ui/actions/RefreshAction.java @@ -0,0 +1,63 @@ +/******************************************************************************* + * Copyright (c) 2008, 2018 IBM Corporation and others. + * + * This program and the accompanying materials + * are made available under the terms of the Eclipse Public License 2.0 + * which accompanies this distribution, and is available at + * https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + * + * Contributors: + * IBM Corporation - initial API and implementation + ******************************************************************************/ + +package org.eclipse.equinox.internal.p2.ui.actions; + +import org.eclipse.equinox.internal.p2.ui.ProvUIMessages; +import org.eclipse.equinox.p2.ui.ProvisioningUI; +import org.eclipse.jface.viewers.ISelectionProvider; +import org.eclipse.swt.SWT; +import org.eclipse.swt.events.KeyEvent; +import org.eclipse.swt.events.KeyListener; +import org.eclipse.swt.widgets.Control; + +/** + * @since 3.4 + * + */ +public abstract class RefreshAction extends ProvisioningAction { + + /** + */ + public RefreshAction(ProvisioningUI ui, ISelectionProvider selectionProvider, Control control) { + super(ui, ProvUIMessages.RefreshAction_Label, selectionProvider); + setToolTipText(ProvUIMessages.RefreshAction_Tooltip); + hookKeyListener(control); + init(); + } + + private void hookKeyListener(Control control) { + control.addKeyListener(KeyListener.keyReleasedAdapter(this::handleKeyReleased)); + } + + @Override + public void run() { + refresh(); + } + + protected abstract void refresh(); + + /** + * Handle a key released event. Used internally and also + * made available so that clients can watch key events from + * any other controls and dispatch to this action. + * + * @param event the key event + */ + public void handleKeyReleased(KeyEvent event) { + if (event.keyCode == SWT.F5 && event.stateMask == 0) { + refresh(); + } + } +} diff --git a/tycho-its/projects/api-tools/missing-bin/org.eclipse.equinox.p2.ui/src/org/eclipse/equinox/internal/p2/ui/actions/RemoveColocatedRepositoryAction.java b/tycho-its/projects/api-tools/missing-bin/org.eclipse.equinox.p2.ui/src/org/eclipse/equinox/internal/p2/ui/actions/RemoveColocatedRepositoryAction.java new file mode 100644 index 0000000000..393d8a4d60 --- /dev/null +++ b/tycho-its/projects/api-tools/missing-bin/org.eclipse.equinox.p2.ui/src/org/eclipse/equinox/internal/p2/ui/actions/RemoveColocatedRepositoryAction.java @@ -0,0 +1,32 @@ +/******************************************************************************* + * Copyright (c) 2007, 2010 IBM Corporation and others. + * + * This program and the accompanying materials + * are made available under the terms of the Eclipse Public License 2.0 + * which accompanies this distribution, and is available at + * https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + * + * Contributors: + * IBM Corporation - initial API and implementation + *******************************************************************************/ + +package org.eclipse.equinox.internal.p2.ui.actions; + +import org.eclipse.equinox.internal.p2.ui.ProvUIMessages; +import org.eclipse.equinox.p2.ui.ProvisioningUI; +import org.eclipse.jface.viewers.ISelectionProvider; + +public class RemoveColocatedRepositoryAction extends ColocatedRepositoryAction { + + public RemoveColocatedRepositoryAction(ProvisioningUI ui, ISelectionProvider selectionProvider) { + super(ui, ProvUIMessages.RemoveColocatedRepositoryAction_Label, ProvUIMessages.RemoveColocatedRepositoryAction_Tooltip, selectionProvider); + + } + + @Override + public void run() { + ui.getRepositoryTracker().removeRepositories(getSelectedLocations(getStructuredSelection().toArray()), ui.getSession()); + } +} diff --git a/tycho-its/projects/api-tools/missing-bin/org.eclipse.equinox.p2.ui/src/org/eclipse/equinox/internal/p2/ui/actions/UninstallAction.java b/tycho-its/projects/api-tools/missing-bin/org.eclipse.equinox.p2.ui/src/org/eclipse/equinox/internal/p2/ui/actions/UninstallAction.java new file mode 100644 index 0000000000..473c55cfeb --- /dev/null +++ b/tycho-its/projects/api-tools/missing-bin/org.eclipse.equinox.p2.ui/src/org/eclipse/equinox/internal/p2/ui/actions/UninstallAction.java @@ -0,0 +1,53 @@ +/******************************************************************************* + * Copyright (c) 2007, 2010 IBM Corporation and others. + * + * This program and the accompanying materials + * are made available under the terms of the Eclipse Public License 2.0 + * which accompanies this distribution, and is available at + * https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + * + * Contributors: + * IBM Corporation - initial API and implementation + * Sonatype, Inc. - ongoing development + *******************************************************************************/ + +package org.eclipse.equinox.internal.p2.ui.actions; + +import java.util.Collection; +import org.eclipse.equinox.internal.p2.ui.ProvUI; +import org.eclipse.equinox.internal.p2.ui.ProvUIMessages; +import org.eclipse.equinox.p2.engine.IProfile; +import org.eclipse.equinox.p2.metadata.IInstallableUnit; +import org.eclipse.equinox.p2.operations.ProfileChangeOperation; +import org.eclipse.equinox.p2.operations.UninstallOperation; +import org.eclipse.equinox.p2.ui.ProvisioningUI; +import org.eclipse.jface.viewers.ISelectionProvider; + +public class UninstallAction extends ExistingIUInProfileAction { + + public UninstallAction(ProvisioningUI ui, ISelectionProvider selectionProvider, String profileId) { + super(ui, ProvUI.UNINSTALL_COMMAND_LABEL, selectionProvider, profileId); + setToolTipText(ProvUI.UNINSTALL_COMMAND_TOOLTIP); + } + + protected String getTaskName() { + return ProvUIMessages.UninstallIUProgress; + } + + @Override + protected int getLockConstant() { + return IProfile.LOCK_UNINSTALL; + } + + @Override + protected ProfileChangeOperation getProfileChangeOperation(Collection ius) { + return ui.getUninstallOperation(ius, null); + } + + @Override + protected int performAction(ProfileChangeOperation operation, Collection ius) { + return ui.openUninstallWizard(ius, (UninstallOperation) operation, null); + } +} diff --git a/tycho-its/projects/api-tools/missing-bin/org.eclipse.equinox.p2.ui/src/org/eclipse/equinox/internal/p2/ui/actions/UpdateAction.java b/tycho-its/projects/api-tools/missing-bin/org.eclipse.equinox.p2.ui/src/org/eclipse/equinox/internal/p2/ui/actions/UpdateAction.java new file mode 100644 index 0000000000..adae0238cb --- /dev/null +++ b/tycho-its/projects/api-tools/missing-bin/org.eclipse.equinox.p2.ui/src/org/eclipse/equinox/internal/p2/ui/actions/UpdateAction.java @@ -0,0 +1,98 @@ +/******************************************************************************* + * Copyright (c) 2007, 2018 IBM Corporation and others. + * + * This program and the accompanying materials + * are made available under the terms of the Eclipse Public License 2.0 + * which accompanies this distribution, and is available at + * https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + * + * Contributors: + * IBM Corporation - initial API and implementation + * Sonatype, Inc. - ongoing development + *******************************************************************************/ + +package org.eclipse.equinox.internal.p2.ui.actions; + +import java.util.ArrayList; +import java.util.Collection; +import org.eclipse.core.runtime.*; +import org.eclipse.core.runtime.jobs.IJobChangeEvent; +import org.eclipse.core.runtime.jobs.JobChangeAdapter; +import org.eclipse.equinox.internal.p2.ui.ProvUI; +import org.eclipse.equinox.internal.p2.ui.ProvUIMessages; +import org.eclipse.equinox.internal.p2.ui.model.IUElementListRoot; +import org.eclipse.equinox.p2.engine.IProfile; +import org.eclipse.equinox.p2.metadata.IInstallableUnit; +import org.eclipse.equinox.p2.operations.*; +import org.eclipse.equinox.p2.ui.ProvisioningUI; +import org.eclipse.jface.viewers.ISelectionProvider; +import org.eclipse.jface.window.Window; +import org.eclipse.ui.PlatformUI; +import org.eclipse.ui.statushandlers.StatusManager; + +public class UpdateAction extends ExistingIUInProfileAction { + + protected IUElementListRoot root; // root that will be used to seed the wizard + protected ArrayList initialSelections; // the elements that should be selected in the wizard + boolean resolveIsVisible = true; + boolean skipSelectionPage = false; + + public UpdateAction(ProvisioningUI ui, ISelectionProvider selectionProvider, String profileId, boolean resolveIsVisible) { + super(ui, ProvUI.UPDATE_COMMAND_LABEL, selectionProvider, profileId); + setToolTipText(ProvUI.UPDATE_COMMAND_TOOLTIP); + this.resolveIsVisible = resolveIsVisible; + } + + public void setSkipSelectionPage(boolean skipSelectionPage) { + this.skipSelectionPage = skipSelectionPage; + } + + protected String getTaskName() { + return ProvUIMessages.UpdateIUProgress; + } + + protected boolean isResolveUserVisible() { + return resolveIsVisible; + } + + @Override + protected int getLockConstant() { + return IProfile.LOCK_UPDATE; + } + + @Override + protected ProfileChangeOperation getProfileChangeOperation(Collection ius) { + return ui.getUpdateOperation(ius, null); + } + + @Override + protected int performAction(final ProfileChangeOperation operation, Collection ius) { + if (operation.getResolutionResult() == Status.OK_STATUS) + return ui.openUpdateWizard(skipSelectionPage, (UpdateOperation) operation, null); + + if (!operation.hasResolved()) + return Window.CANCEL; + + final RemediationOperation remediationOperation = new RemediationOperation(getSession(), operation.getProfileChangeRequest()); + ProvisioningJob job = new ProvisioningJob(ProvUIMessages.UpdateActionRemediationJobName, getSession()) { + @Override + public IStatus runModal(IProgressMonitor monitor) { + monitor.beginTask(ProvUIMessages.UpdateActionRemediationJobTask, RemedyConfig.getAllRemedyConfigs().length); + return remediationOperation.resolveModal(monitor); + } + }; + job.addJobChangeListener(new JobChangeAdapter() { + @Override + public void done(IJobChangeEvent event) { + if (PlatformUI.isWorkbenchRunning()) { + PlatformUI.getWorkbench().getDisplay().asyncExec(() -> ui.openUpdateWizard(skipSelectionPage, (UpdateOperation) operation, remediationOperation, null)); + } + } + + }); + getProvisioningUI().schedule(job, StatusManager.SHOW | StatusManager.LOG); + return Window.CANCEL; + } +} diff --git a/tycho-its/projects/api-tools/missing-bin/org.eclipse.equinox.p2.ui/src/org/eclipse/equinox/internal/p2/ui/dialogs/AddRepositoryDialog.java b/tycho-its/projects/api-tools/missing-bin/org.eclipse.equinox.p2.ui/src/org/eclipse/equinox/internal/p2/ui/dialogs/AddRepositoryDialog.java new file mode 100644 index 0000000000..3d28322065 --- /dev/null +++ b/tycho-its/projects/api-tools/missing-bin/org.eclipse.equinox.p2.ui/src/org/eclipse/equinox/internal/p2/ui/dialogs/AddRepositoryDialog.java @@ -0,0 +1,150 @@ +/******************************************************************************* + * Copyright (c) 2007, 2019 IBM Corporation and others. + * + * This program and the accompanying materials + * are made available under the terms of the Eclipse Public License 2.0 + * which accompanies this distribution, and is available at + * https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + * + * Contributors: + * IBM Corporation - initial API and implementation + *******************************************************************************/ +package org.eclipse.equinox.internal.p2.ui.dialogs; + +import java.net.URI; +import java.net.URISyntaxException; +import org.eclipse.core.runtime.IStatus; +import org.eclipse.core.runtime.URIUtil; +import org.eclipse.equinox.internal.p2.repository.helpers.RepositoryHelper; +import org.eclipse.equinox.internal.p2.ui.IProvHelpContextIds; +import org.eclipse.equinox.internal.p2.ui.ProvUIMessages; +import org.eclipse.equinox.p2.ui.Policy; +import org.eclipse.equinox.p2.ui.ProvisioningUI; +import org.eclipse.jface.dialogs.Dialog; +import org.eclipse.jface.dialogs.IDialogConstants; +import org.eclipse.swt.SWT; +import org.eclipse.swt.events.SelectionListener; +import org.eclipse.swt.layout.GridData; +import org.eclipse.swt.layout.GridLayout; +import org.eclipse.swt.widgets.*; +import org.eclipse.ui.PlatformUI; + +/** + * Abstract dialog class for adding repositories of different types. This class + * assumes the user view of a repository is a name and URI. Individual subclasses + * will dictate what kind of repository and how it's created. + * + * @since 3.4 + * + */ +public abstract class AddRepositoryDialog extends RepositoryNameAndLocationDialog { + + URI addedLocation; + static final String[] ARCHIVE_EXTENSIONS = new String[] {"*.jar;*.zip"}; //$NON-NLS-1$ + static String lastLocalLocation = null; + static String lastArchiveLocation = null; + Policy policy; + + public AddRepositoryDialog(Shell parentShell, ProvisioningUI ui) { + super(parentShell, ui); + setTitle(ProvUIMessages.AddRepositoryDialog_Title); + PlatformUI.getWorkbench().getHelpSystem().setHelp(parentShell, IProvHelpContextIds.ADD_REPOSITORY_DIALOG); + } + + @Override + protected Control createDialogArea(Composite parent) { + Composite comp = new Composite(parent, SWT.NONE); + initializeDialogUnits(comp); + GridLayout layout = new GridLayout(); + layout.numColumns = 3; + layout.marginTop = convertVerticalDLUsToPixels(IDialogConstants.VERTICAL_SPACING); + + comp.setLayout(layout); + GridData data = new GridData(GridData.FILL_HORIZONTAL); + comp.setLayoutData(data); + + // Name: [] + nickname = createNameField(comp); + + Button localButton = new Button(comp, SWT.PUSH); + localButton.setText(ProvUIMessages.RepositoryGroup_LocalRepoBrowseButton); + localButton.addSelectionListener(SelectionListener.widgetSelectedAdapter(event -> { + DirectoryDialog dialog = new DirectoryDialog(getShell(), SWT.APPLICATION_MODAL); + dialog.setMessage(ProvUIMessages.RepositoryGroup_SelectRepositoryDirectory); + dialog.setFilterPath(lastLocalLocation); + String path = dialog.open(); + if (path != null) { + lastLocalLocation = path; + url.setText(makeLocalURIString(path)); + validateRepositoryURL(false); + } + })); + setButtonLayoutData(localButton); + + // Location: [] + url = createLocationField(comp); + + Button archiveButton = new Button(comp, SWT.PUSH); + archiveButton.setText(ProvUIMessages.RepositoryGroup_ArchivedRepoBrowseButton); + archiveButton.addSelectionListener(SelectionListener.widgetSelectedAdapter(event -> { + FileDialog dialog = new FileDialog(getShell(), SWT.APPLICATION_MODAL); + dialog.setText(ProvUIMessages.RepositoryGroup_RepositoryFile); + dialog.setFilterExtensions(ARCHIVE_EXTENSIONS); + dialog.setFileName(lastArchiveLocation); + String path = dialog.open(); + if (path != null) { + lastArchiveLocation = path; + url.setText(makeLocalURIString(path)); + validateRepositoryURL(false); + } + })); + setButtonLayoutData(archiveButton); + comp.setTabList(new Control[] {nickname, url, localButton, archiveButton}); + Dialog.applyDialogFont(comp); + return comp; + } + + String makeLocalURIString(String path) { + try { + URI localURI = URIUtil.fromString(path); + return URIUtil.toUnencodedString(RepositoryHelper.localRepoURIHelper(localURI)); + } catch (URISyntaxException e) { + return path; + } + } + + @Override + protected boolean handleOk() { + IStatus status = addRepository(); + return status.isOK(); + } + + /** + * Get the location of the repository that was added by this dialog. Return null + * if the dialog has not yet added a repository location. + * + * @return the location of the repository that has been added by this dialog, or null + * if no repository has been added. + */ + public URI getAddedLocation() { + return addedLocation; + } + + protected IStatus addRepository() { + IStatus status = validateRepositoryURL(false); + if (status.isOK()) { + addedLocation = getUserLocation(); + String nick = nickname.getText().trim(); + if (nick.length() == 0) + nick = null; + getRepositoryTracker().addRepository(addedLocation, nick, getProvisioningUI().getSession()); + } + return status; + } + @Override + protected boolean isResizable() { + return true; + } +} diff --git a/tycho-its/projects/api-tools/missing-bin/org.eclipse.equinox.p2.ui/src/org/eclipse/equinox/internal/p2/ui/dialogs/ApplyProfileChangesDialog.java b/tycho-its/projects/api-tools/missing-bin/org.eclipse.equinox.p2.ui/src/org/eclipse/equinox/internal/p2/ui/dialogs/ApplyProfileChangesDialog.java new file mode 100644 index 0000000000..bd9c739016 --- /dev/null +++ b/tycho-its/projects/api-tools/missing-bin/org.eclipse.equinox.p2.ui/src/org/eclipse/equinox/internal/p2/ui/dialogs/ApplyProfileChangesDialog.java @@ -0,0 +1,95 @@ +/******************************************************************************* + * Copyright (c) 2007, 2010 IBM Corporation and others. + * + * This program and the accompanying materials + * are made available under the terms of the Eclipse Public License 2.0 + * which accompanies this distribution, and is available at + * https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + * + * Contributors: + * IBM Corporation - initial API and implementation + *******************************************************************************/ +package org.eclipse.equinox.internal.p2.ui.dialogs; + +import org.eclipse.core.runtime.IProduct; +import org.eclipse.core.runtime.Platform; +import org.eclipse.equinox.internal.p2.ui.ProvUIMessages; +import org.eclipse.jface.dialogs.IDialogConstants; +import org.eclipse.jface.dialogs.MessageDialog; +import org.eclipse.jface.window.Window; +import org.eclipse.osgi.util.NLS; +import org.eclipse.swt.widgets.Shell; + +/** + * A dialog which prompts the user to restart. + * + * @since 3.4 + */ +public class ApplyProfileChangesDialog extends MessageDialog { + public static final int PROFILE_IGNORE = 0; + public static final int PROFILE_APPLYCHANGES = 1; + public static final int PROFILE_RESTART = 2; + private final static String[] yesNo = new String[] { ProvUIMessages.ApplyProfileChangesDialog_Restart, + IDialogConstants.NO_LABEL }; + private final static String[] yesNoApply = new String[] { ProvUIMessages.ApplyProfileChangesDialog_Restart, + ProvUIMessages.ApplyProfileChangesDialog_NotYet, ProvUIMessages.ApplyProfileChangesDialog_ApplyChanges }; + + private int returnCode = PROFILE_IGNORE; + + private ApplyProfileChangesDialog(Shell parent, String title, String message, boolean mustRestart) { + super(parent, title, null, // accept the default window icon + message, NONE, mustRestart ? yesNo : yesNoApply, 0); // yes is the default + } + + /** + * Prompt the user for restart or apply profile changes. + * + * @param parent the parent shell of the dialog, or null if + * none + * @param mustRestart indicates whether the user must restart to get the + * changes. If false, then the user may choose + * to apply the changes to the running profile rather than + * restarting. + * @return one of PROFILE_IGNORE (do nothing), PROFILE_APPLYCHANGES (attempt to + * apply the changes), or PROFILE_RESTART (restart the system). + */ + public static int promptForRestart(Shell parent, boolean mustRestart) { + String title = ProvUIMessages.PlatformUpdateTitle; + IProduct product = Platform.getProduct(); + String productName = product != null && product.getName() != null ? product.getName() + : ProvUIMessages.ApplicationInRestartDialog; + String message = NLS.bind( + mustRestart ? ProvUIMessages.PlatformRestartMessage : ProvUIMessages.OptionalPlatformRestartMessage, + productName); + ApplyProfileChangesDialog dialog = new ApplyProfileChangesDialog(parent, title, message, mustRestart); + if (dialog.open() == Window.CANCEL) + return PROFILE_IGNORE; + return dialog.returnCode; + } + + /** + * When a button is pressed, store the return code. + * + * @see org.eclipse.jface.dialogs.Dialog#buttonPressed(int) + */ + @Override + protected void buttonPressed(int id) { + switch (id) { + case 0: + // YES + returnCode = PROFILE_RESTART; + break; + case 1: + // NO + returnCode = PROFILE_IGNORE; + break; + default: + returnCode = PROFILE_APPLYCHANGES; + break; + } + + super.buttonPressed(id); + } +} diff --git a/tycho-its/projects/api-tools/missing-bin/org.eclipse.equinox.p2.ui/src/org/eclipse/equinox/internal/p2/ui/dialogs/AvailableIUGroup.java b/tycho-its/projects/api-tools/missing-bin/org.eclipse.equinox.p2.ui/src/org/eclipse/equinox/internal/p2/ui/dialogs/AvailableIUGroup.java new file mode 100644 index 0000000000..084d5cafeb --- /dev/null +++ b/tycho-its/projects/api-tools/missing-bin/org.eclipse.equinox.p2.ui/src/org/eclipse/equinox/internal/p2/ui/dialogs/AvailableIUGroup.java @@ -0,0 +1,521 @@ +/******************************************************************************* + * Copyright (c) 2008, 2018 IBM Corporation and others. + * + * This program and the accompanying materials + * are made available under the terms of the Eclipse Public License 2.0 + * which accompanies this distribution, and is available at + * https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + * + * Contributors: + * IBM Corporation - initial API and implementation + * Sonatype, Inc. - ongoing development + *******************************************************************************/ +package org.eclipse.equinox.internal.p2.ui.dialogs; + +import java.net.URI; +import java.util.ArrayList; +import org.eclipse.core.runtime.*; +import org.eclipse.core.runtime.jobs.*; +import org.eclipse.equinox.internal.p2.ui.*; +import org.eclipse.equinox.internal.p2.ui.model.*; +import org.eclipse.equinox.internal.p2.ui.query.IUViewQueryContext; +import org.eclipse.equinox.internal.p2.ui.viewers.*; +import org.eclipse.equinox.internal.provisional.p2.repository.RepositoryEvent; +import org.eclipse.equinox.p2.core.ProvisionException; +import org.eclipse.equinox.p2.metadata.IInstallableUnit; +import org.eclipse.equinox.p2.repository.IRepositoryManager; +import org.eclipse.equinox.p2.ui.LoadMetadataRepositoryJob; +import org.eclipse.equinox.p2.ui.ProvisioningUI; +import org.eclipse.jface.viewers.*; +import org.eclipse.osgi.util.NLS; +import org.eclipse.swt.SWT; +import org.eclipse.swt.custom.BusyIndicator; +import org.eclipse.swt.events.TreeEvent; +import org.eclipse.swt.events.TreeListener; +import org.eclipse.swt.graphics.Font; +import org.eclipse.swt.layout.GridData; +import org.eclipse.swt.widgets.*; +import org.eclipse.ui.IWorkbench; +import org.eclipse.ui.PlatformUI; + +/** + * An AvailableIUGroup is a reusable UI component that displays the + * IU's available for installation. By default, content from all available + * repositories is shown. + * + * @since 3.4 + */ +public class AvailableIUGroup extends StructuredIUGroup { + + /** + * Show contents from all repositories + */ + public static final int AVAILABLE_ALL = 1; + + /** + * Don't show any repository content + */ + public static final int AVAILABLE_NONE = 2; + + /** + * Show local repository content + */ + public static final int AVAILABLE_LOCAL = 3; + + /** + * Show content for a specific repository + */ + public static final int AVAILABLE_SPECIFIED = 4; + + IUViewQueryContext queryContext; + int filterConstant = AVAILABLE_ALL; + URI repositoryFilter; + QueryableMetadataRepositoryManager queryableManager; + // We restrict the type of the filter used because PatternFilter does + // unnecessary accesses of children that cause problems with the deferred + // tree. + AvailableIUPatternFilter filter; + private boolean useBold = false; + private IUDetailsLabelProvider labelProvider; + private int repoFlags; + Display display; + DelayedFilterCheckboxTree filteredTree; + Job lastRequestedLoadJob; + + /** + * Create a group that represents the available IU's from all available + * repositories. The default policy controls the visibility flags for + * repositories and IU's. + * + * @param parent the parent composite for the group + */ + public AvailableIUGroup(ProvisioningUI ui, final Composite parent) { + this(ui, parent, parent.getFont(), null, getDefaultColumnConfig(), AVAILABLE_ALL); + } + + private static IUColumnConfig[] getDefaultColumnConfig() { + // increase primary column width because we might be nesting names under categories and require more space than a flat list + IUColumnConfig nameColumn = new IUColumnConfig(ProvUIMessages.ProvUI_NameColumnTitle, IUColumnConfig.COLUMN_NAME, ILayoutConstants.DEFAULT_PRIMARY_COLUMN_WIDTH + 15); + IUColumnConfig versionColumn = new IUColumnConfig(ProvUIMessages.ProvUI_VersionColumnTitle, IUColumnConfig.COLUMN_VERSION, ILayoutConstants.DEFAULT_COLUMN_WIDTH); + return new IUColumnConfig[] {nameColumn, versionColumn}; + } + + /** + * Create a group that represents the available IU's. + * + * @param ui the policy to use for deciding what should be shown + * @param parent the parent composite for the group + * @param font The font to use for calculating pixel sizes. This font is + * not managed by the receiver. + * @param queryContext the IUViewQueryContext that determines additional + * information about what is shown, such as the visible repositories + * @param columnConfig the description of the columns that should be shown. If null, a default + * will be used. + * @param filterConstant a constant specifying which repositories are used when showing content + */ + public AvailableIUGroup(ProvisioningUI ui, final Composite parent, Font font, IUViewQueryContext queryContext, IUColumnConfig[] columnConfig, int filterConstant) { + super(ui, parent, font, columnConfig); + this.display = parent.getDisplay(); + if (queryContext == null) + this.queryContext = ProvUI.getQueryContext(getPolicy()); + else + this.queryContext = queryContext; + repoFlags = ui.getRepositoryTracker().getMetadataRepositoryFlags(); + this.queryableManager = new QueryableMetadataRepositoryManager(ui, false); + this.filterConstant = filterConstant; + this.filter = new AvailableIUPatternFilter(getColumnConfig()); + this.filter.setIncludeLeadingWildcard(true); + createGroupComposite(parent); + } + + @Override + protected StructuredViewer createViewer(Composite parent) { + // Table of available IU's + filteredTree = new DelayedFilterCheckboxTree(parent, SWT.MULTI | SWT.FULL_SELECTION | SWT.H_SCROLL | SWT.V_SCROLL | SWT.BORDER, filter, getPreFilterJobProvider()); + final TreeViewer availableIUViewer = filteredTree.getViewer(); + + availableIUViewer.getTree().setFont(parent.getFont()); + filteredTree.getFilterControl().setFont(parent.getFont()); + + // If the user expanded or collapsed anything while we were loading a repo + // in the background, we would not want to disrupt their work by making + // a newly loaded visible and expanding it. Setting the load job to null + // will take care of this. + availableIUViewer.getTree().addTreeListener(new TreeListener() { + @Override + public void treeCollapsed(TreeEvent e) { + lastRequestedLoadJob = null; + } + + @Override + public void treeExpanded(TreeEvent e) { + lastRequestedLoadJob = null; + } + }); + + labelProvider = new IUDetailsLabelProvider(filteredTree, getColumnConfig(), getShell()); + labelProvider.setUseBoldFontForFilteredItems(useBold); + labelProvider.setToolTipProperty(IInstallableUnit.PROP_DESCRIPTION); + + // Filters and sorters before establishing content, so we don't refresh unnecessarily. + IUComparator comparator = new IUComparator(IUComparator.IU_NAME); + comparator.useColumnConfig(getColumnConfig()); + availableIUViewer.setComparator(comparator); + availableIUViewer.setComparer(new ProvElementComparer()); + + // Now the content provider. + DeferredQueryContentProvider contentProvider = new DeferredQueryContentProvider(); + availableIUViewer.setContentProvider(contentProvider); + + // Now the presentation, columns before label provider. + setTreeColumns(availableIUViewer.getTree()); + availableIUViewer.setLabelProvider(labelProvider); + + // Notify the filtered tree so that it can hook listeners on the + // content provider. This is needed so that filtering is only allowed + // after content has been retrieved. + filteredTree.contentProviderSet(contentProvider); + + final StructuredViewerProvisioningListener listener = new StructuredViewerProvisioningListener(getClass().getName(), availableIUViewer, ProvUIProvisioningListener.PROV_EVENT_METADATA_REPOSITORY, getProvisioningUI().getOperationRunner()) { + @Override + protected void repositoryAdded(final RepositoryEvent event) { + makeRepositoryVisible(event.getRepositoryLocation()); + } + + @Override + protected void refreshViewer() { + final TreeViewer treeViewer = filteredTree.getViewer(); + final Tree tree = treeViewer.getTree(); + IWorkbench workbench = PlatformUI.getWorkbench(); + if (workbench.isClosing()) + return; + if (tree != null && !tree.isDisposed()) { + updateAvailableViewState(); + } + + } + }; + ProvUI.getProvisioningEventBus(getProvisioningUI().getSession()).addListener(listener); + + availableIUViewer.getControl().addDisposeListener(e -> ProvUI.getProvisioningEventBus(getProvisioningUI().getSession()).removeListener(listener)); + updateAvailableViewState(); + return availableIUViewer; + } + + private void setTreeColumns(Tree tree) { + tree.setHeaderVisible(true); + + IUColumnConfig[] cols = getColumnConfig(); + for (int i = 0; i < cols.length; i++) { + TreeColumn tc = new TreeColumn(tree, SWT.NONE, i); + tc.setResizable(true); + tc.setText(cols[i].getColumnTitle()); + tc.setWidth(cols[i].getWidthInPixels(tree)); + } + } + + Object getNewInput() { + if (repositoryFilter != null) { + return new MetadataRepositoryElement(queryContext, getProvisioningUI(), repositoryFilter, true); + } else if (filterConstant == AVAILABLE_NONE) { + // Dummy object that explains empty site list + return new ProvElement(null) { + @Override + public Object[] getChildren(Object o) { + String description; + String name; + int severity; + if (!getPolicy().getRepositoriesVisible()) { + // shouldn't get here ideally. No sites and no way to add any. + severity = IStatus.ERROR; + name = ProvUIMessages.AvailableIUGroup_NoSitesConfiguredExplanation; + description = ProvUIMessages.AvailableIUGroup_NoSitesConfiguredDescription; + } else { + severity = IStatus.INFO; + name = ProvUIMessages.AvailableIUGroup_NoSitesExplanation; + description = ProvUIMessages.ColocatedRepositoryManipulator_NoContentExplanation; + } + return new Object[] {new EmptyElementExplanation(null, severity, name, description)}; + } + + @Override + public String getLabel(Object o) { + // Label not needed for input + return null; + } + }; + } else { + queryableManager.setRespositoryFlags(repoFlags); + return new MetadataRepositories(queryContext, getProvisioningUI(), queryableManager); + } + } + + /** + * Set a boolean indicating whether a bold font should be used when + * showing filtered items. This method does not refresh the tree or + * labels, so that must be done explicitly by the caller. + * @param useBoldFont + */ + public void setUseBoldFontForFilteredItems(boolean useBoldFont) { + if (labelProvider != null) + labelProvider.setUseBoldFontForFilteredItems(useBoldFont); + } + + /** + * Return the composite that contains the controls in this group. + * @return the composite + */ + @Override + public Composite getComposite() { + return super.getComposite(); + } + + /** + * Get the viewer used to represent the available IU's + * @return the viewer + */ + @Override + public StructuredViewer getStructuredViewer() { + return super.getStructuredViewer(); + } + + /** + * Get the selected IU's + * @return the array of selected IU's + */ + // overridden for visibility in the public package + @Override + public java.util.List getSelectedIUs() { + return super.getSelectedIUs(); + } + + // overridden to weed out non-IU elements, such as repositories or empty explanations + @Override + public Object[] getSelectedIUElements() { + Object[] elements = viewer.getStructuredSelection().toArray(); + ArrayList list = new ArrayList<>(elements.length); + for (Object element : elements) + if (ElementUtils.getIU(element) != null) + list.add(element); + return list.toArray(); + } + + public CheckboxTreeViewer getCheckboxTreeViewer() { + return filteredTree.getCheckboxTreeViewer(); + } + + /** + * Get the selected IU's + * @return the array of checked IU's + */ + public IInstallableUnit[] getCheckedLeafIUs() { + Object[] selections = filteredTree.getCheckedElements(); // Get all the elements that have been selected, not just the visible ones + if (selections.length == 0) + return new IInstallableUnit[0]; + ArrayList leaves = new ArrayList<>(selections.length); + for (Object selection : selections) { + if (!getCheckboxTreeViewer().getGrayed(selection)) { + IInstallableUnit iu = ProvUI.getAdapter(selection, IInstallableUnit.class); + if (iu != null && !ProvUI.isCategory(iu) && !leaves.contains(iu)) + leaves.add(iu); + } + } + return leaves.toArray(new IInstallableUnit[leaves.size()]); + } + + public Tree getTree() { + if (viewer == null) + return null; + return ((TreeViewer) viewer).getTree(); + } + + /* + * Make the repository with the specified location visible in the viewer. + */ + void makeRepositoryVisible(final URI location) { + // If we are viewing by anything other than site, there is no specific way + // to make a repo visible. + if (!(queryContext.getViewType() == IUViewQueryContext.AVAILABLE_VIEW_BY_REPO)) { + if (Display.getCurrent() == null) + display.asyncExec(this::updateAvailableViewState); + else + updateAvailableViewState(); + return; + } + // First reset the input so that the new repo shows up + Runnable runnable = () -> { + final TreeViewer treeViewer = filteredTree.getViewer(); + final Tree tree = treeViewer.getTree(); + IWorkbench workbench = PlatformUI.getWorkbench(); + if (workbench.isClosing()) + return; + if (tree != null && !tree.isDisposed()) { + updateAvailableViewState(); + } + }; + if (Display.getCurrent() == null) + display.asyncExec(runnable); + else + runnable.run(); + // We don't know if loading will be a fast or slow operation. + // We do it in a job to be safe, and when it's done, we update + // the UI. + Job job = new Job(NLS.bind(ProvUIMessages.AvailableIUGroup_LoadingRepository, URIUtil.toUnencodedString(location))) { + @Override + protected IStatus run(IProgressMonitor monitor) { + try { + getProvisioningUI().loadMetadataRepository(location, true, monitor); + return Status.OK_STATUS; + } catch (ProvisionException e) { + return e.getStatus(); + } catch (OperationCanceledException e) { + return Status.CANCEL_STATUS; + } + } + }; + job.setPriority(Job.LONG); + job.setSystem(true); + job.setUser(false); + job.addJobChangeListener(new JobChangeAdapter() { + @Override + public void done(final IJobChangeEvent event) { + if (event.getResult().isOK()) + display.asyncExec(() -> { + final TreeViewer treeViewer = filteredTree.getViewer(); + IWorkbench workbench = PlatformUI.getWorkbench(); + if (workbench.isClosing()) + return; + // Expand only if there have been no other jobs started for other repos. + if (event.getJob() == lastRequestedLoadJob) { + final Tree tree = treeViewer.getTree(); + if (tree != null && !tree.isDisposed()) { + for (TreeItem item : tree.getItems()) { + if (item.getData() instanceof IRepositoryElement) { + URI url = ((IRepositoryElement) item.getData()).getLocation(); + if (url.equals(location)) { + treeViewer.expandToLevel(item.getData(), AbstractTreeViewer.ALL_LEVELS); + tree.select(item); + return; + } + } + } + } + } + }); + } + }); + lastRequestedLoadJob = job; + job.schedule(); + } + + public void updateAvailableViewState() { + if (getTree() == null || getTree().isDisposed()) + return; + final Composite parent = getComposite().getParent(); + setUseBoldFontForFilteredItems(queryContext.getViewType() != IUViewQueryContext.AVAILABLE_VIEW_FLAT); + + BusyIndicator.showWhile(display, () -> { + parent.setRedraw(false); + getCheckboxTreeViewer().setInput(getNewInput()); + parent.layout(true); + parent.setRedraw(true); + }); + } + + @Override + public Control getDefaultFocusControl() { + if (filteredTree != null) + return filteredTree.getFilterControl(); + return null; + } + + protected String getFilterString() { + return filteredTree.getFilterString(); + } + + @Override + protected GridData getViewerGridData() { + GridData data = super.getViewerGridData(); + data.heightHint = convertHeightInCharsToPixels(ILayoutConstants.DEFAULT_TABLE_HEIGHT); + return data; + } + + /** + * Set the checked elements to the specified selections. This method + * does not force visibility/expansion of the checked elements. If they are not + * visible, they will not be checked. + * @param selections + */ + public void setChecked(Object[] selections) { + filteredTree.getCheckboxTreeViewer().setCheckedElements(selections); + // TODO HACK ALERT! + // Since We don't have API for setAllChecked(boolean), clients have to use this method. + // We need to signal DelayedFilterCheckboxTree when everything needs to be deselected since + // we aren't firing an event for each item. + Object element = selections.length == 0 ? DelayedFilterCheckboxTree.ALL_ITEMS_HACK : selections[0]; + filteredTree.getCheckboxTreeViewer().fireCheckStateChanged(element, selections.length > 0); + } + + public void setRepositoryFilter(int filterFlag, URI repoLocation) { + // If there has been no change, don't do anything. We will be + // clearing out selection caches in this method and should not do + // so if there's really no change. + if (filterConstant == filterFlag) { + if (filterConstant != AVAILABLE_SPECIFIED) + return; + if (repoLocation != null && repoLocation.equals(repositoryFilter)) + return; + } + filterConstant = filterFlag; + + switch (filterFlag) { + case AVAILABLE_ALL : + case AVAILABLE_NONE : + repositoryFilter = null; + repoFlags &= ~IRepositoryManager.REPOSITORIES_LOCAL; + break; + case AVAILABLE_LOCAL : + repositoryFilter = null; + repoFlags |= IRepositoryManager.REPOSITORIES_LOCAL; + break; + default : + repositoryFilter = repoLocation; + break; + } + updateAvailableViewState(); + filteredTree.clearCheckStateCache(); + } + + private IPreFilterJobProvider getPreFilterJobProvider() { + return () -> { + switch (filterConstant) { + case AVAILABLE_ALL : + Job preFilterJob = new LoadMetadataRepositoryJob(getProvisioningUI()); + preFilterJob.setProperty(LoadMetadataRepositoryJob.SUPPRESS_REPOSITORY_EVENTS, Boolean.toString(true)); + return preFilterJob; + case AVAILABLE_NONE : + case AVAILABLE_LOCAL : + return null; + default : + if (repositoryFilter == null) + return null; + Job job = new Job("Repository Load Job") { //$NON-NLS-1$ + @Override + protected IStatus run(IProgressMonitor monitor) { + try { + getProvisioningUI().loadMetadataRepository(repositoryFilter, false, monitor); + return Status.OK_STATUS; + } catch (ProvisionException e) { + return e.getStatus(); + } + } + + }; + job.setPriority(Job.SHORT); + return job; + } + }; + } +} diff --git a/tycho-its/projects/api-tools/missing-bin/org.eclipse.equinox.p2.ui/src/org/eclipse/equinox/internal/p2/ui/dialogs/AvailableIUPatternFilter.java b/tycho-its/projects/api-tools/missing-bin/org.eclipse.equinox.p2.ui/src/org/eclipse/equinox/internal/p2/ui/dialogs/AvailableIUPatternFilter.java new file mode 100644 index 0000000000..af6d7f8e13 --- /dev/null +++ b/tycho-its/projects/api-tools/missing-bin/org.eclipse.equinox.p2.ui/src/org/eclipse/equinox/internal/p2/ui/dialogs/AvailableIUPatternFilter.java @@ -0,0 +1,125 @@ +/******************************************************************************* + * Copyright (c) 2008, 2016 IBM Corporation and others. + * + * This program and the accompanying materials + * are made available under the terms of the Eclipse Public License 2.0 + * which accompanies this distribution, and is available at + * https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + * + * Contributors: + * IBM Corporation - initial API and implementation + *******************************************************************************/ +package org.eclipse.equinox.internal.p2.ui.dialogs; + +import org.eclipse.equinox.internal.p2.ui.model.CategoryElement; +import org.eclipse.equinox.internal.p2.ui.model.IIUElement; +import org.eclipse.equinox.internal.p2.ui.viewers.IUColumnConfig; +import org.eclipse.equinox.p2.metadata.IInstallableUnit; +import org.eclipse.jface.viewers.Viewer; +import org.eclipse.ui.dialogs.PatternFilter; + +/** + * A class that handles filtering IU's based on a supplied matching string. + * + * @since 3.4 + * + */ +public class AvailableIUPatternFilter extends PatternFilter { + + boolean checkName, checkDescription, checkVersion, checkId = false; + String patternString; + + /** + * Create a new instance of a AvailableIUPatternFilter + */ + public AvailableIUPatternFilter(IUColumnConfig[] columnConfig) { + super(); + for (IUColumnConfig element : columnConfig) { + int field = element.getColumnType(); + switch (field) { + case IUColumnConfig.COLUMN_ID: + checkId = true; + break; + case IUColumnConfig.COLUMN_NAME: + checkName = true; + break; + case IUColumnConfig.COLUMN_DESCRIPTION: + checkDescription = true; + break; + case IUColumnConfig.COLUMN_VERSION: + checkVersion = true; + break; + default: + break; + } + } + + } + + @Override + public boolean isElementSelectable(Object element) { + return element instanceof IIUElement && !(element instanceof CategoryElement); + } + + /* + * Overridden to remember the pattern string for an optimization in + * isParentMatch + */ + @Override + public void setPattern(String patternString) { + super.setPattern(patternString); + this.patternString = patternString; + } + + /* + * Overridden to avoid getting children unless there is actually a filter. + */ + @Override + protected boolean isParentMatch(Viewer viewer, Object element) { + if (patternString == null || patternString.length() == 0) + return true; + return super.isParentMatch(viewer, element); + } + + @Override + protected boolean isLeafMatch(Viewer viewer, Object element) { + if (element instanceof CategoryElement) { + return false; + } + + String text = null; + if (element instanceof IIUElement) { + IInstallableUnit iu = ((IIUElement) element).getIU(); + if (checkName) { + // Get the iu name in the default locale + text = iu.getProperty(IInstallableUnit.PROP_NAME, null); + if (text != null && wordMatches(text)) + return true; + // Get the iu description in the default locale + text = iu.getProperty(IInstallableUnit.PROP_DESCRIPTION, null); + if (text != null && wordMatches(text)) + return true; + } + if (checkId || (checkName && text == null)) { + text = iu.getId(); + if (wordMatches(text)) { + return true; + } + } + if (!checkName && checkDescription) { + // Get the iu description in the default locale + text = iu.getProperty(IInstallableUnit.PROP_DESCRIPTION, null); + if (text != null && wordMatches(text)) + return true; + } + if (checkVersion) { + text = iu.getVersion().toString(); + if (wordMatches(text)) + return true; + } + } + return false; + } +} diff --git a/tycho-its/projects/api-tools/missing-bin/org.eclipse.equinox.p2.ui/src/org/eclipse/equinox/internal/p2/ui/dialogs/AvailableIUsPage.java b/tycho-its/projects/api-tools/missing-bin/org.eclipse.equinox.p2.ui/src/org/eclipse/equinox/internal/p2/ui/dialogs/AvailableIUsPage.java new file mode 100644 index 0000000000..4457aa964e --- /dev/null +++ b/tycho-its/projects/api-tools/missing-bin/org.eclipse.equinox.p2.ui/src/org/eclipse/equinox/internal/p2/ui/dialogs/AvailableIUsPage.java @@ -0,0 +1,750 @@ +/******************************************************************************* + * Copyright (c) 2007, 2018 IBM Corporation and others. + * + * This program and the accompanying materials + * are made available under the terms of the Eclipse Public License 2.0 + * which accompanies this distribution, and is available at + * https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + * + * Contributors: + * IBM Corporation - initial API and implementation + * EclipseSource - ongoing development + * Sonatype, Inc. - ongoing development + * Ericsson AB (Hamdan Msheik) - Bug 396420 - Control Install dialog through preference customization + *******************************************************************************/ +package org.eclipse.equinox.internal.p2.ui.dialogs; + +import java.net.URI; +import org.eclipse.equinox.internal.p2.ui.*; +import org.eclipse.equinox.internal.p2.ui.model.EmptyElementExplanation; +import org.eclipse.equinox.internal.p2.ui.model.QueriedElement; +import org.eclipse.equinox.internal.p2.ui.query.IUViewQueryContext; +import org.eclipse.equinox.internal.p2.ui.viewers.*; +import org.eclipse.equinox.p2.engine.ProvisioningContext; +import org.eclipse.equinox.p2.metadata.IInstallableUnit; +import org.eclipse.equinox.p2.ui.ProvisioningUI; +import org.eclipse.jface.action.Action; +import org.eclipse.jface.action.IAction; +import org.eclipse.jface.dialogs.Dialog; +import org.eclipse.jface.dialogs.IDialogConstants; +import org.eclipse.jface.dialogs.IDialogSettings; +import org.eclipse.jface.layout.GridLayoutFactory; +import org.eclipse.jface.resource.JFaceResources; +import org.eclipse.jface.viewers.IContentProvider; +import org.eclipse.osgi.util.NLS; +import org.eclipse.swt.SWT; +import org.eclipse.swt.custom.SashForm; +import org.eclipse.swt.dnd.*; +import org.eclipse.swt.events.*; +import org.eclipse.swt.layout.*; +import org.eclipse.swt.widgets.*; + +public class AvailableIUsPage extends ProvisioningWizardPage implements ISelectableIUsPage { + + private static final String DIALOG_SETTINGS_SECTION = "AvailableIUsPage"; //$NON-NLS-1$ + private static final String AVAILABLE_VIEW_TYPE = "AvailableViewType"; //$NON-NLS-1$ + private static final String SHOW_LATEST_VERSIONS_ONLY = "ShowLatestVersionsOnly"; //$NON-NLS-1$ + private static final String HIDE_INSTALLED_IUS = "HideInstalledContent"; //$NON-NLS-1$ + private static final String RESOLVE_ALL = "ResolveInstallWithAllSites"; //$NON-NLS-1$ + private static final String FILTER_ON_ENV = "FilterOnEnv"; //$NON-NLS-1$ + private static final String NAME_COLUMN_WIDTH = "AvailableNameColumnWidth"; //$NON-NLS-1$ + private static final String VERSION_COLUMN_WIDTH = "AvailableVersionColumnWidth"; //$NON-NLS-1$ + private static final String LIST_WEIGHT = "AvailableListSashWeight"; //$NON-NLS-1$ + private static final String DETAILS_WEIGHT = "AvailableDetailsSashWeight"; //$NON-NLS-1$ + private static final String LINKACTION = "linkAction"; //$NON-NLS-1$ + + Object[] initialSelections; + IUViewQueryContext queryContext; + AvailableIUGroup availableIUGroup; + Composite availableIUButtonBar; + Link installLink; + Button useCategoriesCheckbox; + Button hideInstalledCheckbox; + Button showLatestVersionsCheckbox; + Button resolveAllCheckbox; + Button filterOnEnvCheckBox; + SashForm sashForm; + IUColumnConfig nameColumn; + IUColumnConfig versionColumn; + StructuredViewerProvisioningListener profileListener; + Display display; + int batchCount = 0; + RepositorySelectionGroup repoSelector; + IUDetailsGroup iuDetailsGroup; + Label selectionCount; + int progressBarRefCount = 0; + + public AvailableIUsPage(ProvisioningUI ui, ProvisioningOperationWizard wizard) { + super("AvailableSoftwarePage", ui, wizard); //$NON-NLS-1$ + makeQueryContext(); + setTitle(ProvUIMessages.AvailableIUsPage_Title); + setDescription(ProvUIMessages.AvailableIUsPage_Description); + } + + @Override + public void createControl(Composite parent) { + initializeDialogUnits(parent); + this.display = parent.getDisplay(); + + Composite composite = new Composite(parent, SWT.NONE); + GridData gd = new GridData(SWT.FILL, SWT.FILL, true, true); + composite.setLayoutData(gd); + setDropTarget(composite); + + GridLayout layout = new GridLayout(); + layout.marginWidth = 0; + + composite.setLayout(layout); + // Repo manipulation + createRepoArea(composite); + + sashForm = new SashForm(composite, SWT.VERTICAL); + FillLayout fill = new FillLayout(); + sashForm.setLayout(fill); + GridData data = new GridData(SWT.FILL, SWT.FILL, true, true); + sashForm.setLayoutData(data); + + Composite aboveSash = new Composite(sashForm, SWT.NONE); + GridLayout grid = new GridLayout(); + grid.numColumns = 2; + grid.marginWidth = 0; + grid.marginHeight = 0; + aboveSash.setLayout(grid); + + // Now the available group + // If repositories are visible, we want to default to showing no repos. Otherwise all. + int filterConstant = AvailableIUGroup.AVAILABLE_NONE; + if (!getPolicy().getRepositoriesVisible()) { + filterConstant = AvailableIUGroup.AVAILABLE_ALL; + } + nameColumn = new IUColumnConfig(ProvUIMessages.ProvUI_NameColumnTitle, IUColumnConfig.COLUMN_NAME, ILayoutConstants.DEFAULT_PRIMARY_COLUMN_WIDTH + 15); + versionColumn = new IUColumnConfig(ProvUIMessages.ProvUI_VersionColumnTitle, IUColumnConfig.COLUMN_VERSION, ILayoutConstants.DEFAULT_COLUMN_WIDTH); + + getColumnWidthsFromSettings(); + availableIUGroup = new AvailableIUGroup(getProvisioningUI(), aboveSash, JFaceResources.getDialogFont(), queryContext, new IUColumnConfig[] {nameColumn, versionColumn}, filterConstant); + + // Selection listeners must be registered on both the normal selection + // events and the check mark events. Must be done after buttons + // are created so that the buttons can register and receive their selection notifications before us. + availableIUGroup.getStructuredViewer().addSelectionChangedListener(event -> { + updateDetails(); + iuDetailsGroup.enablePropertyLink(availableIUGroup.getSelectedIUElements().length == 1); + }); + + availableIUGroup.getCheckboxTreeViewer().addCheckStateListener(event -> updateSelection()); + + addViewerProvisioningListeners(); + + availableIUGroup.setUseBoldFontForFilteredItems(queryContext.getViewType() != IUViewQueryContext.AVAILABLE_VIEW_FLAT); + setDropTarget(availableIUGroup.getStructuredViewer().getControl()); + activateCopy(availableIUGroup.getStructuredViewer().getControl()); + + // select buttons + createSelectButtons(aboveSash); + createSelectionCount(aboveSash); + + // Details area + iuDetailsGroup = new IUDetailsGroup(sashForm, availableIUGroup.getStructuredViewer(), SWT.DEFAULT, true); + // Clear highlighted text pattern + availableIUGroup.getCheckboxTreeViewer().getTree().addFocusListener(FocusListener.focusLostAdapter(e -> iuDetailsGroup.setDetailHighlight(null))); + availableIUGroup.getDefaultFocusControl().addFocusListener(FocusListener.focusLostAdapter(e -> iuDetailsGroup.setDetailHighlight(null))); + + sashForm.setWeights(getSashWeights()); + + // Controls for filtering/presentation/site selection + Composite controlsComposite = new Composite(composite, SWT.NONE); + layout = new GridLayout(); + layout.marginWidth = 0; + layout.marginHeight = 0; + layout.numColumns = 2; + layout.makeColumnsEqualWidth = true; + layout.verticalSpacing = convertVerticalDLUsToPixels(IDialogConstants.VERTICAL_SPACING); + controlsComposite.setLayout(layout); + gd = new GridData(SWT.FILL, SWT.FILL, true, false); + controlsComposite.setLayoutData(gd); + + createViewControlsArea(controlsComposite); + + Composite progressBarComposite = createProgressBar(composite); + gd = new GridData(SWT.FILL, SWT.TOP, false, false); + progressBarComposite.setLayoutData(gd); + progressBarComposite.setVisible(false); + + initializeWidgetState(); + setControl(composite); + composite.addDisposeListener(e -> removeProvisioningListeners()); + Dialog.applyDialogFont(composite); + } + + private void createSelectionCount(Composite parentComposite) { + Composite selectionCountComposite = new Composite(parentComposite, SWT.NONE); + GridLayout layout = new GridLayout(); + layout.marginWidth = 0; + layout.verticalSpacing = 10; + selectionCountComposite.setLayout(layout); + selectionCountComposite.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, false, false, 2, 1)); + + selectionCount = new Label(selectionCountComposite, SWT.NONE); + GridData data = new GridData(SWT.FILL, SWT.CENTER, true, false); + selectionCount.setLayoutData(data); + + // separator underneath + Label sep = new Label(selectionCountComposite, SWT.HORIZONTAL | SWT.SEPARATOR); + GridData separatorGridData = new GridData(SWT.FILL, SWT.CENTER, true, false); + sep.setLayoutData(separatorGridData); + } + + private Composite createProgressBar(Composite parent) { + final Composite progressBarComposite = new Composite(parent, SWT.NONE); + Label progressBarLabel = new Label(progressBarComposite, SWT.NONE); + progressBarLabel.setText(ProvUIMessages.AvailableIUsPage_Fetching); + new ProgressBar(progressBarComposite, SWT.INDETERMINATE); + IContentProvider contentProvider = availableIUGroup.getCheckboxTreeViewer().getContentProvider(); + if (contentProvider instanceof DeferredQueryContentProvider) { + ((DeferredQueryContentProvider) contentProvider).addOnFetchingActionListener(new IDeferredQueryTreeListener() { + + @Override + public void finishedFetchingDeferredChildren(Object parent, Object placeHolder) { + if (parent instanceof QueriedElement) { + if (((QueriedElement) parent).getCachedChildren().length > 0) { + if (progressBarRefCount > 0) { + progressBarRefCount--; + } + } + } + changeProgressBarVisibility(progressBarComposite); + } + + @Override + public void fetchingDeferredChildren(Object parent, Object placeHolder) { + progressBarRefCount++; + changeProgressBarVisibility(progressBarComposite); + } + }); + } + GridLayoutFactory.fillDefaults().generateLayout(progressBarComposite); + return progressBarComposite; + } + + void changeProgressBarVisibility(final Composite progressBarComposite) { + this.display.asyncExec(() -> { + if (!progressBarComposite.isDisposed()) { + progressBarComposite.setVisible(progressBarRefCount > 0 ? true : false); + } + }); + } + + private void createSelectButtons(Composite parent) { + Composite buttonParent = new Composite(parent, SWT.NONE); + GridLayout gridLayout = new GridLayout(); + gridLayout.numColumns = 1; + gridLayout.horizontalSpacing = convertHorizontalDLUsToPixels(IDialogConstants.HORIZONTAL_SPACING); + gridLayout.marginHeight = 0; + gridLayout.marginWidth = 0; + gridLayout.horizontalSpacing = convertHorizontalDLUsToPixels(IDialogConstants.HORIZONTAL_SPACING); + buttonParent.setLayout(gridLayout); + + GridData data = new GridData(SWT.FILL, SWT.DEFAULT, false, false); + buttonParent.setLayoutData(data); + + Button selectAll = new Button(buttonParent, SWT.PUSH); + selectAll.setText(ProvUIMessages.SelectableIUsPage_Select_All); + setButtonLayoutData(selectAll); + selectAll.addListener(SWT.Selection, event -> setAllChecked(true)); + + Button deselectAll = new Button(buttonParent, SWT.PUSH); + deselectAll.setText(ProvUIMessages.SelectableIUsPage_Deselect_All); + setButtonLayoutData(deselectAll); + deselectAll.addListener(SWT.Selection, event -> setAllChecked(false)); + } + + // The viewer method is deprecated because it only applies to visible items, + // but this is exactly the behavior we want. + @SuppressWarnings("deprecation") + void setAllChecked(boolean checked) { + if (checked) { + // TODO ideally there should be API on AvailableIUGroup to do this. + // This is reachy and too knowledgeable of the group's implementation. + availableIUGroup.getCheckboxTreeViewer().setAllChecked(checked); + // to ensure that the listeners get processed. + availableIUGroup.setChecked(availableIUGroup.getCheckboxTreeViewer().getCheckedElements()); + + } else { + availableIUGroup.setChecked(new Object[0]); + } + updateSelection(); + } + + private void createViewControlsArea(Composite parent) { + showLatestVersionsCheckbox = new Button(parent, SWT.CHECK); + showLatestVersionsCheckbox.setText(ProvUIMessages.AvailableIUsPage_ShowLatestVersions); + showLatestVersionsCheckbox.addSelectionListener(new SelectionListener() { + @Override + public void widgetDefaultSelected(SelectionEvent e) { + updateQueryContext(); + availableIUGroup.updateAvailableViewState(); + } + + @Override + public void widgetSelected(SelectionEvent e) { + updateQueryContext(); + availableIUGroup.updateAvailableViewState(); + } + }); + + hideInstalledCheckbox = new Button(parent, SWT.CHECK); + hideInstalledCheckbox.setText(ProvUIMessages.AvailableIUsPage_HideInstalledItems); + hideInstalledCheckbox.addSelectionListener(new SelectionListener() { + @Override + public void widgetDefaultSelected(SelectionEvent e) { + updateQueryContext(); + availableIUGroup.updateAvailableViewState(); + } + + @Override + public void widgetSelected(SelectionEvent e) { + updateQueryContext(); + availableIUGroup.updateAvailableViewState(); + } + }); + + useCategoriesCheckbox = new Button(parent, SWT.CHECK); + useCategoriesCheckbox.setText(ProvUIMessages.AvailableIUsPage_GroupByCategory); + useCategoriesCheckbox.addSelectionListener(new SelectionListener() { + @Override + public void widgetDefaultSelected(SelectionEvent e) { + updateQueryContext(); + availableIUGroup.updateAvailableViewState(); + } + + @Override + public void widgetSelected(SelectionEvent e) { + updateQueryContext(); + availableIUGroup.updateAvailableViewState(); + } + }); + + GridData gd = new GridData(SWT.FILL, SWT.FILL, true, false); + gd.horizontalIndent = convertHorizontalDLUsToPixels(IDialogConstants.HORIZONTAL_MARGIN); + installLink = createLink(parent, new Action() { + @Override + public void runWithEvent(Event event) { + ProvUI.openInstallationDialog(event); + } + }, ProvUIMessages.AvailableIUsPage_GotoInstallInfo); + installLink.setLayoutData(gd); + + filterOnEnvCheckBox = new Button(parent, SWT.CHECK); + filterOnEnvCheckBox.setText(ProvUIMessages.AvailableIUsPage_FilterOnEnvCheckBox); + filterOnEnvCheckBox.addSelectionListener(new SelectionListener() { + @Override + public void widgetDefaultSelected(SelectionEvent e) { + updateQueryContext(); + availableIUGroup.updateAvailableViewState(); + } + + @Override + public void widgetSelected(SelectionEvent e) { + updateQueryContext(); + availableIUGroup.updateAvailableViewState(); + } + }); + + if (getPolicy().getRepositoriesVisible()) { + // Checkbox + resolveAllCheckbox = new Button(parent, SWT.CHECK); + resolveAllCheckbox.setText(ProvUIMessages.AvailableIUsPage_ResolveAllCheckbox); + gd = new GridData(SWT.FILL, SWT.FILL, true, false); + gd.horizontalSpan = 2; + resolveAllCheckbox.setLayoutData(gd); + } + } + + private void createRepoArea(Composite parent) { + // Site controls are only available if a repository manipulator + // is specified. + if (getPolicy().getRepositoriesVisible()) { + repoSelector = new RepositorySelectionGroup(getProvisioningUI(), getContainer(), parent, queryContext); + repoSelector.addRepositorySelectionListener(this::repoComboSelectionChanged); + + // The ProvisioningOperationWizard signals the start of a repository operation as a way + // to keep side-effect events from changing the selections or state of the wizard. + // This is the one case where we want to respond to repo events, because we are + // launching the repo manipulation page from the wizard. So we signal the wizard's + // operation as complete and then resignal the start when done. + // see https://bugs.eclipse.org/bugs/show_bug.cgi?id=277265#c38 + repoSelector.setRepositoryManipulationHook(new IRepositoryManipulationHook() { + @Override + public void preManipulateRepositories() { + getProvisioningUI().signalRepositoryOperationComplete(null, true); + } + + @Override + public void postManipulateRepositories() { + getProvisioningUI().signalRepositoryOperationStart(); + } + }); + } + } + + void repoComboSelectionChanged(int repoChoice, URI repoLocation) { + if (repoChoice == AvailableIUGroup.AVAILABLE_NONE) { + setDescription(ProvUIMessages.AvailableIUsPage_SelectASite); + } else { + setDescription(ProvUIMessages.AvailableIUsPage_Description); + } + availableIUGroup.setRepositoryFilter(repoChoice, repoLocation); + updateSelection(); + } + + void updateSelection() { + int count = availableIUGroup.getCheckedLeafIUs().length; + setPageComplete(count > 0); + if (count == 0) { + selectionCount.setText(""); //$NON-NLS-1$ + } else { + String message = count == 1 ? ProvUIMessages.AvailableIUsPage_SingleSelectionCount : ProvUIMessages.AvailableIUsPage_MultipleSelectionCount; + selectionCount.setText(NLS.bind(message, Integer.toString(count))); + } + getProvisioningWizard().operationSelectionsChanged(this); + } + + void updateQueryContext() { + queryContext.setShowLatestVersionsOnly(showLatestVersionsCheckbox.getSelection()); + queryContext.setHideAlreadyInstalled(hideInstalledCheckbox.getSelection()); + if (useCategoriesCheckbox.getSelection()) { + queryContext.setViewType(IUViewQueryContext.AVAILABLE_VIEW_BY_CATEGORY); + } else { + queryContext.setViewType(IUViewQueryContext.AVAILABLE_VIEW_FLAT); + } + queryContext.setFilterOnEnv(filterOnEnvCheckBox.getSelection()); + } + + private Link createLink(Composite parent, IAction action, String text) { + Link link = new Link(parent, SWT.PUSH); + link.setText(text); + + link.addListener(SWT.Selection, event -> { + IAction linkAction = getLinkAction(event.widget); + if (linkAction != null) { + linkAction.runWithEvent(event); + } + }); + link.setToolTipText(action.getToolTipText()); + link.setData(LINKACTION, action); + return link; + } + + IAction getLinkAction(Widget widget) { + Object data = widget.getData(LINKACTION); + if (data == null || !(data instanceof IAction)) { + return null; + } + return (IAction) data; + } + + private void setDropTarget(Control control) { + if (getPolicy().getRepositoriesVisible()) { + DropTarget target = new DropTarget(control, DND.DROP_MOVE | DND.DROP_COPY | DND.DROP_LINK); + target.setTransfer(URLTransfer.getInstance(), FileTransfer.getInstance()); + target.addDropListener(new RepositoryManipulatorDropTarget(getProvisioningUI(), control)); + } + + } + + private void initializeWidgetState() { + // Set widgets according to query context + hideInstalledCheckbox.setSelection(queryContext.getHideAlreadyInstalled()); + showLatestVersionsCheckbox.setSelection(queryContext.getShowLatestVersionsOnly()); + useCategoriesCheckbox.setSelection(queryContext.shouldGroupByCategories()); + filterOnEnvCheckBox.setSelection(queryContext.getFilterOnEnv()); + availableIUGroup.updateAvailableViewState(); + if (initialSelections != null) { + availableIUGroup.setChecked(initialSelections); + } + + // Focus should go on site combo unless it's not there. In that case, go to the filter text. + Control focusControl = null; + if (repoSelector != null) { + focusControl = repoSelector.getDefaultFocusControl(); + } else { + focusControl = availableIUGroup.getDefaultFocusControl(); + } + if (focusControl != null) { + focusControl.setFocus(); + } + updateDetails(); + iuDetailsGroup.enablePropertyLink(availableIUGroup.getSelectedIUElements().length == 1); + updateSelection(); + + if (repoSelector != null) { + repoSelector.setRepositorySelection(AvailableIUGroup.AVAILABLE_NONE, null); + setDescription(ProvUIMessages.AvailableIUsPage_SelectASite); + } + + if (resolveAllCheckbox != null) { + IDialogSettings settings = ProvUIActivator.getDefault().getDialogSettings(); + IDialogSettings section = settings.getSection(DIALOG_SETTINGS_SECTION); + String value = null; + + if (section != null) { + value = section.get(RESOLVE_ALL); + resolveAllCheckbox.setSelection(section.getBoolean(RESOLVE_ALL)); + } + // no section or no value in the section + if (value == null) { + resolveAllCheckbox.setSelection(getPolicy().getContactAllSites()); + } + } + } + + private void makeQueryContext() { + queryContext = ProvUI.getQueryContext(getPolicy()); + queryContext.setInstalledProfileId(getProfileId()); + + // Now check for saved away dialog settings + IDialogSettings settings = ProvUIActivator.getDefault().getDialogSettings(); + IDialogSettings section = settings.getSection(DIALOG_SETTINGS_SECTION); + if (section != null) { + // View by... + try { + if (section.get(AVAILABLE_VIEW_TYPE) != null) { + queryContext.setViewType(section.getInt(AVAILABLE_VIEW_TYPE)); + } + } catch (NumberFormatException e) { + // Ignore if there actually was a value that didn't parse. + } + // We no longer (in 3.5) show a view by site, so ignore any older dialog setting that + // instructs us to do this. + if (queryContext.getViewType() == IUViewQueryContext.AVAILABLE_VIEW_BY_REPO) { + queryContext.setViewType(IUViewQueryContext.AVAILABLE_VIEW_BY_CATEGORY); + } + + // Show latest versions + if (section.get(SHOW_LATEST_VERSIONS_ONLY) != null) { + queryContext.setShowLatestVersionsOnly(section.getBoolean(SHOW_LATEST_VERSIONS_ONLY)); + } + + // Hide installed content + if (section.get(HIDE_INSTALLED_IUS) != null) { + queryContext.setHideAlreadyInstalled(section.getBoolean(HIDE_INSTALLED_IUS)); + } + + if (section.get(FILTER_ON_ENV) != null) { + queryContext.setFilterOnEnv(section.getBoolean(FILTER_ON_ENV)); + } + } + } + + private void getColumnWidthsFromSettings() { + IDialogSettings settings = ProvUIActivator.getDefault().getDialogSettings(); + IDialogSettings section = settings.getSection(DIALOG_SETTINGS_SECTION); + if (section != null) { + try { + if (section.get(NAME_COLUMN_WIDTH) != null) { + nameColumn.setWidthInPixels(section.getInt(NAME_COLUMN_WIDTH)); + } + if (section.get(VERSION_COLUMN_WIDTH) != null) { + versionColumn.setWidthInPixels(section.getInt(VERSION_COLUMN_WIDTH)); + } + } catch (NumberFormatException e) { + // Ignore if there actually was a value that didn't parse. + } + } + } + + private int[] getSashWeights() { + IDialogSettings settings = ProvUIActivator.getDefault().getDialogSettings(); + IDialogSettings section = settings.getSection(DIALOG_SETTINGS_SECTION); + if (section != null) { + try { + int[] weights = new int[2]; + if (section.get(LIST_WEIGHT) != null) { + weights[0] = section.getInt(LIST_WEIGHT); + if (section.get(DETAILS_WEIGHT) != null) { + weights[1] = section.getInt(DETAILS_WEIGHT); + return weights; + } + } + } catch (NumberFormatException e) { + // Ignore if there actually was a value that didn't parse. + } + } + return ILayoutConstants.IUS_TO_DETAILS_WEIGHTS; + } + + @Override + public void saveBoundsRelatedSettings() { + if (getShell().isDisposed()) { + return; + } + IDialogSettings settings = ProvUIActivator.getDefault().getDialogSettings(); + IDialogSettings section = settings.getSection(DIALOG_SETTINGS_SECTION); + if (section == null) { + section = settings.addNewSection(DIALOG_SETTINGS_SECTION); + } + section.put(AVAILABLE_VIEW_TYPE, queryContext.getViewType()); + section.put(SHOW_LATEST_VERSIONS_ONLY, showLatestVersionsCheckbox.getSelection()); + section.put(HIDE_INSTALLED_IUS, hideInstalledCheckbox.getSelection()); + if (resolveAllCheckbox != null) { + section.put(RESOLVE_ALL, resolveAllCheckbox.getSelection()); + } + section.put(FILTER_ON_ENV, filterOnEnvCheckBox.getSelection()); + + TreeColumn col = availableIUGroup.getCheckboxTreeViewer().getTree().getColumn(0); + section.put(NAME_COLUMN_WIDTH, col.getWidth()); + col = availableIUGroup.getCheckboxTreeViewer().getTree().getColumn(1); + section.put(VERSION_COLUMN_WIDTH, col.getWidth()); + + int[] weights = sashForm.getWeights(); + section.put(LIST_WEIGHT, weights[0]); + section.put(DETAILS_WEIGHT, weights[1]); + } + + void updateDetails() { + // First look for an empty explanation. + Object[] elements = availableIUGroup.getStructuredViewer().getStructuredSelection().toArray(); + if (elements.length == 1 && elements[0] instanceof EmptyElementExplanation) { + String description = ((EmptyElementExplanation) elements[0]).getDescription(); + if (description != null) { + iuDetailsGroup.setDetailText(description); + return; + } + } + + // Now look for IU's + java.util.List selected = getSelectedIUs(); + if (selected.size() == 1) { + StringBuilder result = new StringBuilder(); + String filterString = availableIUGroup.getFilterString(); + String description = selected.get(0).getProperty(IInstallableUnit.PROP_DESCRIPTION, null); + if (description != null) { + result.append(description); + } else { + String name = selected.get(0).getProperty(IInstallableUnit.PROP_NAME, null); + if (name != null) { + result.append(name); + } else { + result.append(selected.get(0).getId()); + } + result.append(" "); //$NON-NLS-1$ + result.append(selected.get(0).getVersion().toString()); + } + + iuDetailsGroup.setDetailText(result.toString()); + if (result.length() > 0) { + iuDetailsGroup.setDetailHighlight(filterString); + } + return; + } + iuDetailsGroup.setDetailText(""); //$NON-NLS-1$ + } + + public java.util.List getSelectedIUs() { + return availableIUGroup.getSelectedIUs(); + } + + /* + * This method is provided only for automated testing. + */ + public AvailableIUGroup testGetAvailableIUGroup() { + return availableIUGroup; + } + + public IInstallableUnit[] getCheckedIUs() { + return availableIUGroup.getCheckedLeafIUs(); + } + + /* + * Overridden so that we don't call getNextPage(). + * We use getNextPage() to start resolving the install so + * we only want to do that when the next button is pressed. + */ + @Override + public boolean canFlipToNextPage() { + return isPageComplete(); + } + + @Override + public Object[] getCheckedIUElements() { + return availableIUGroup.getCheckedLeafIUs(); + } + + @Override + public Object[] getSelectedIUElements() { + return availableIUGroup.getSelectedIUElements(); + } + + /** + * Set the selections to be used in this page. This method only changes the + * selections of items that are already visible. It does not expand items + * or change the repository elements in order to make the selections valid. + * + * @param elements + */ + @Override + public void setCheckedElements(Object[] elements) { + if (availableIUGroup == null) { + initialSelections = elements; + } else { + availableIUGroup.setChecked(elements); + } + } + + void addViewerProvisioningListeners() { + // We might need to adjust the content of the available IU group's viewer + // according to installation changes. We want to be very selective about refreshing, + // because the viewer has its own listeners installed. + profileListener = new StructuredViewerProvisioningListener(getClass().getName(), availableIUGroup.getStructuredViewer(), ProvUIProvisioningListener.PROV_EVENT_PROFILE, getProvisioningUI().getOperationRunner()) { + @Override + protected void profileAdded(String id) { + // do nothing + } + + @Override + protected void profileRemoved(String id) { + // do nothing + } + + @Override + protected void profileChanged(String id) { + if (id.equals(getProfileId())) { + safeRefresh(); + } + } + }; + + ProvUI.getProvisioningEventBus(getProvisioningUI().getSession()).addListener(profileListener); + } + + void removeProvisioningListeners() { + if (profileListener != null) { + ProvUI.getProvisioningEventBus(getProvisioningUI().getSession()).removeListener(profileListener); + profileListener = null; + } + } + + @Override + protected String getClipboardText(Control control) { + // The default label provider constructor uses the default column config. + // since we passed the default column config to the available iu group, + // we know that this label provider matches the one used there. + return CopyUtils.getIndentedClipboardText(getSelectedIUElements(), new IUDetailsLabelProvider()); + } + + public ProvisioningContext getProvisioningContext() { + // If the user can't manipulate repos, always resolve against everything + if (!getPolicy().getRepositoriesVisible() || repoSelector == null) { + return new ProvisioningContext(getProvisioningUI().getSession().getProvisioningAgent()); + } + // Consult the checkbox to see if we should resolve against everything, + // or use the combo to determine what to do. + if (resolveAllCheckbox.getSelection()) { + return new ProvisioningContext(getProvisioningUI().getSession().getProvisioningAgent()); + } + // Use the contents of the combo to determine the context + return repoSelector.getProvisioningContext(); + } +} diff --git a/tycho-its/projects/api-tools/missing-bin/org.eclipse.equinox.p2.ui/src/org/eclipse/equinox/internal/p2/ui/dialogs/ComboAutoCompleteField.java b/tycho-its/projects/api-tools/missing-bin/org.eclipse.equinox.p2.ui/src/org/eclipse/equinox/internal/p2/ui/dialogs/ComboAutoCompleteField.java new file mode 100644 index 0000000000..7f6249e022 --- /dev/null +++ b/tycho-its/projects/api-tools/missing-bin/org.eclipse.equinox.p2.ui/src/org/eclipse/equinox/internal/p2/ui/dialogs/ComboAutoCompleteField.java @@ -0,0 +1,104 @@ +/******************************************************************************* + * Copyright (c) 2009, 2020 IBM Corporation and others. + * + * This program and the accompanying materials + * are made available under the terms of the Eclipse Public License 2.0 + * which accompanies this distribution, and is available at + * https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + * + * Contributors: + * IBM Corporation - initial API and implementation + ******************************************************************************/ + +package org.eclipse.equinox.internal.p2.ui.dialogs; + +import java.util.ArrayList; +import org.eclipse.core.text.StringMatcher; +import org.eclipse.jface.fieldassist.*; +import org.eclipse.swt.widgets.Combo; + +/** + * ComboAutoCompleteField is an auto complete field appropriate for + * pattern matching the text in a combo to the contents of the combo. + * If the proposals should include items outside of the combo, then + * clients can set their own proposal strings. + * + * @since 3.5 + */ +public class ComboAutoCompleteField { + + ContentProposalAdapter adapter; + Combo combo; + String[] proposalStrings = null; + + public ComboAutoCompleteField(Combo c) { + this.combo = c; + adapter = new ContentProposalAdapter(combo, new ComboContentAdapter(), getProposalProvider(), null, null); + adapter.setPropagateKeys(true); + adapter.setProposalAcceptanceStyle(ContentProposalAdapter.PROPOSAL_REPLACE); + } + + public void setProposalStrings(String[] proposals) { + proposalStrings = proposals; + } + + String[] getStringItems() { + if (proposalStrings == null) + return combo.getItems(); + return proposalStrings; + } + + IContentProposalProvider getProposalProvider() { + return (contents, position) -> { + String[] items = getStringItems(); + if (contents.length() == 0 || items.length == 0) + return new IContentProposal[0]; + StringMatcher matcher = new StringMatcher("*" + contents + "*", true, false); //$NON-NLS-1$ //$NON-NLS-2$ + ArrayList matches = new ArrayList<>(); + for (String item : items) + if (matcher.match(item)) + matches.add(item); + + // We don't want to autoactivate if the only proposal exactly matches + // what is in the combo. This prevents the popup from + // opening when the user is merely scrolling through the combo values or + // has accepted a combo value. + if (matches.size() == 1 && matches.get(0).equals(combo.getText())) + return new IContentProposal[0]; + + if (matches.isEmpty()) + return new IContentProposal[0]; + + // Make the proposals + IContentProposal[] proposals = new IContentProposal[matches.size()]; + for (int i2 = 0; i2 < matches.size(); i2++) { + final String proposal = matches.get(i2); + proposals[i2] = new IContentProposal() { + + @Override + public String getContent() { + return proposal; + } + + @Override + public int getCursorPosition() { + return proposal.length(); + } + + @Override + public String getDescription() { + return null; + } + + @Override + public String getLabel() { + return null; + } + }; + } + return proposals; + }; + } +} \ No newline at end of file diff --git a/tycho-its/projects/api-tools/missing-bin/org.eclipse.equinox.p2.ui/src/org/eclipse/equinox/internal/p2/ui/dialogs/ContainerCheckedTreeViewer.java b/tycho-its/projects/api-tools/missing-bin/org.eclipse.equinox.p2.ui/src/org/eclipse/equinox/internal/p2/ui/dialogs/ContainerCheckedTreeViewer.java new file mode 100644 index 0000000000..827d046800 --- /dev/null +++ b/tycho-its/projects/api-tools/missing-bin/org.eclipse.equinox.p2.ui/src/org/eclipse/equinox/internal/p2/ui/dialogs/ContainerCheckedTreeViewer.java @@ -0,0 +1,301 @@ +/******************************************************************************* + * Copyright (c) 2005, 2018 IBM Corporation and others. + * + * This program and the accompanying materials + * are made available under the terms of the Eclipse Public License 2.0 + * which accompanies this distribution, and is available at + * https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + * + * Contributors: + * IBM Corporation - initial API and implementation + *******************************************************************************/ +package org.eclipse.equinox.internal.p2.ui.dialogs; + +import java.util.ArrayList; +import java.util.Iterator; +import org.eclipse.equinox.internal.p2.ui.model.QueriedElement; +import org.eclipse.jface.viewers.*; +import org.eclipse.swt.widgets.*; + +/** + * Copy of ContainerCheckedTreeViewer which is specialized for use with + * DeferredFetchFilteredTree. Originally copied from org.eclipse.ui.dialogs and + * altered to achieve the following: + * + * (1)checking a parent will expand it when we know it's a long running + * operation that involves a placeholder. The modified method is + * doCheckStateChanged(). + * + * (2)when preserving selection, we do not want the check state to be rippled + * through the child and parent nodes. Since we know that + * preservingSelection(Runnable) isn't working properly, no need to do a bunch + * of work here. The added methods is preservingSelection(Runnable). Modified + * methods are updateChildrenItems(TreeItem parent) and + * updateParentItems(TreeItem parent). + * + * (3)we correct the problem with preservingSelection(Runnable) by remembering + * the check state and restoring it after a refresh. We fire a check state event + * so clients monitoring the selection will know what's going on. Added methods + * are internalRefresh(Object, boolean), saveCheckedState(), + * restoreCheckedState(), and fireCheckStateChanged(Object, boolean). That last + * method is public so that DeferredFetchFilteredTree can do the same thing when + * it remembers selections. + * + * This class does not correct the general problem reported in + * https://bugs.eclipse.org/bugs/show_bug.cgi?id=170521 That is handled by + * preserving selections additively in DeferredFetchFilteredTree. This class + * simply provides the API needed by that class and manages the parent state + * according to the children. + */ +public class ContainerCheckedTreeViewer extends CheckboxTreeViewer { + + private boolean rippleCheckMarks = true; + private ArrayList savedCheckState; + + /** + * Constructor for ContainerCheckedTreeViewer. + * + * @see CheckboxTreeViewer#CheckboxTreeViewer(Composite) + */ + public ContainerCheckedTreeViewer(Composite parent) { + super(parent); + initViewer(); + } + + /** + * Constructor for ContainerCheckedTreeViewer. + * + * @see CheckboxTreeViewer#CheckboxTreeViewer(Composite,int) + */ + public ContainerCheckedTreeViewer(Composite parent, int style) { + super(parent, style); + initViewer(); + } + + /** + * Constructor for ContainerCheckedTreeViewer. + * + * @see CheckboxTreeViewer#CheckboxTreeViewer(Tree) + */ + public ContainerCheckedTreeViewer(Tree tree) { + super(tree); + initViewer(); + } + + private void initViewer() { + setUseHashlookup(true); + addCheckStateListener(event -> doCheckStateChanged(event.getElement())); + addTreeListener(new ITreeViewerListener() { + @Override + public void treeCollapsed(TreeExpansionEvent event) { + } + + @Override + public void treeExpanded(TreeExpansionEvent event) { + Widget item = findItem(event.getElement()); + if (item instanceof TreeItem) { + initializeItem((TreeItem) item); + } + } + }); + } + + /** + * Update element after a checkstate change. + * + * @param element + */ + protected void doCheckStateChanged(Object element) { + Widget item = findItem(element); + if (item instanceof TreeItem) { + TreeItem treeItem = (TreeItem) item; + treeItem.setGrayed(false); + // BEGIN MODIFICATION OF COPIED CLASS + if (element instanceof QueriedElement && treeItem.getChecked()) { + if (!((QueriedElement) element).hasQueryable()) { + // We have checked an element that will take some time + // to get its children. Use this opportunity to auto-expand + // the tree so that the check mark is not misleading. Don't + // update the check state because it will just be a pending + // placeholder. + expandToLevel(element, 1); + return; + } + } + // END MODIFICATION OF COPIED CLASS + updateChildrenItems(treeItem); + updateParentItems(treeItem.getParentItem()); + } + } + + /** + * The item has expanded. Updates the checked state of its children. + */ + private void initializeItem(TreeItem item) { + if (item.getChecked() && !item.getGrayed()) { + updateChildrenItems(item); + } + } + + /** + * Updates the check state of all created children + */ + // MODIFIED to ignore parent state when in the middle of a + // selection preserving refresh. + private void updateChildrenItems(TreeItem parent) { + // We are in the middle of preserving selections, don't + // update any children according to parent + if (!rippleCheckMarks) + return; + Item[] children = getChildren(parent); + boolean state = parent.getChecked(); + for (Item element : children) { + TreeItem curr = (TreeItem) element; + if (curr.getData() != null && ((curr.getChecked() != state) || curr.getGrayed())) { + curr.setChecked(state); + curr.setGrayed(false); + updateChildrenItems(curr); + } + } + } + + /** + * Updates the check / gray state of all parent items + */ + private void updateParentItems(TreeItem item) { + // We are in the middle of preserving selections, don't + // update any parents according to children + if (!rippleCheckMarks) + return; + if (item != null) { + Item[] children = getChildren(item); + boolean containsChecked = false; + boolean containsUnchecked = false; + for (Item element : children) { + TreeItem curr = (TreeItem) element; + containsChecked |= curr.getChecked(); + containsUnchecked |= (!curr.getChecked() || curr.getGrayed()); + } + item.setChecked(containsChecked); + item.setGrayed(containsChecked && containsUnchecked); + updateParentItems(item.getParentItem()); + } + } + + @Override + public boolean setChecked(Object element, boolean state) { + if (super.setChecked(element, state)) { + doCheckStateChanged(element); + return true; + } + return false; + } + + @Override + public void setCheckedElements(Object[] elements) { + super.setCheckedElements(elements); + for (Object element : elements) { + doCheckStateChanged(element); + } + } + + @Override + protected void setExpanded(Item item, boolean expand) { + super.setExpanded(item, expand); + if (expand && item instanceof TreeItem) { + initializeItem((TreeItem) item); + } + } + + @Override + public Object[] getCheckedElements() { + Object[] checked = super.getCheckedElements(); + // add all items that are children of a checked node but not created yet + ArrayList result = new ArrayList<>(); + for (Object curr : checked) { + result.add(curr); + Widget item = findItem(curr); + if (item != null) { + Item[] children = getChildren(item); + // check if contains the dummy node + if (children.length == 1 && children[0].getData() == null) { + // not yet created + collectChildren(curr, result); + } + } + } + return result.toArray(); + } + + /** + * Recursively add the filtered children of element to the result. + * + * @param element + * @param result + */ + private void collectChildren(Object element, ArrayList result) { + Object[] filteredChildren = getFilteredChildren(element); + for (Object curr : filteredChildren) { + result.add(curr); + collectChildren(curr, result); + } + } + + // The super implementation doesn't really work because the + // non-expanded items are not holding their real elements yet. + // Yet the code that records the checked state uses the + // elements to remember what checkmarks should be restored. + // The result is that non-expanded elements are not up to date + // and if anything in there should have been checked, it + // won't be. The best we can do is at least turn off all the + // rippling checks that happen during this method since we are going + // to reset all the checkmarks anyway. + @Override + protected void preservingSelection(Runnable updateCode) { + rippleCheckMarks = false; + super.preservingSelection(updateCode); + rippleCheckMarks = true; + } + + @Override + protected void internalRefresh(Object element, boolean updateLabels) { + saveCheckedState(); + super.internalRefresh(element, updateLabels); + restoreCheckedState(); + } + + // We only remember the leaves. This is specific to our + // use case, not necessarily a good idea for fixing the general + // problem. + private void saveCheckedState() { + Object[] checked = getCheckedElements(); + savedCheckState = new ArrayList<>(checked.length); + for (Object element : checked) + if (!isExpandable(element) && !getGrayed(element)) + savedCheckState.add(element); + } + + // Now we restore checked state. + private void restoreCheckedState() { + setCheckedElements(new Object[0]); + setGrayedElements(new Object[0]); + Object element = null; + // We are assuming that once a leaf, always a leaf. + Iterator iter = savedCheckState.iterator(); + while (iter.hasNext()) { + element = iter.next(); + setChecked(element, true); + } + // Listeners need to know something changed. + if (element != null) + fireCheckStateChanged(element, true); + } + + // This method is public so that the DeferredFetchFilteredTree can also + // call it. + public void fireCheckStateChanged(Object element, boolean state) { + fireCheckStateChanged(new CheckStateChangedEvent(this, element, state)); + } +} diff --git a/tycho-its/projects/api-tools/missing-bin/org.eclipse.equinox.p2.ui/src/org/eclipse/equinox/internal/p2/ui/dialogs/CopyHandler.java b/tycho-its/projects/api-tools/missing-bin/org.eclipse.equinox.p2.ui/src/org/eclipse/equinox/internal/p2/ui/dialogs/CopyHandler.java new file mode 100644 index 0000000000..8fbfcfc612 --- /dev/null +++ b/tycho-its/projects/api-tools/missing-bin/org.eclipse.equinox.p2.ui/src/org/eclipse/equinox/internal/p2/ui/dialogs/CopyHandler.java @@ -0,0 +1,40 @@ +/******************************************************************************* + * Copyright (c) 2009, 2010 IBM Corporation and others. + * + * This program and the accompanying materials + * are made available under the terms of the Eclipse Public License 2.0 + * which accompanies this distribution, and is available at + * https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + * + * Contributors: + * IBM Corporation - initial API and implementation + ******************************************************************************/ + +package org.eclipse.equinox.internal.p2.ui.dialogs; + +import org.eclipse.core.commands.AbstractHandler; +import org.eclipse.core.commands.ExecutionEvent; +import org.eclipse.equinox.p2.ui.ICopyable; +import org.eclipse.swt.widgets.Control; +import org.eclipse.ui.ISources; +import org.eclipse.ui.handlers.HandlerUtil; + +public class CopyHandler extends AbstractHandler { + + public static final String ID = "org.eclipse.ui.edit.copy"; //$NON-NLS-1$ + ICopyable copySource; + + public CopyHandler(ICopyable copyable) { + this.copySource = copyable; + } + + @Override + public Object execute(ExecutionEvent event) { + Object control = HandlerUtil.getVariable(event, ISources.ACTIVE_FOCUS_CONTROL_NAME); + if (control instanceof Control) + copySource.copyToClipboard((Control) control); + return null; + } +} \ No newline at end of file diff --git a/tycho-its/projects/api-tools/missing-bin/org.eclipse.equinox.p2.ui/src/org/eclipse/equinox/internal/p2/ui/dialogs/CopyPopup.java b/tycho-its/projects/api-tools/missing-bin/org.eclipse.equinox.p2.ui/src/org/eclipse/equinox/internal/p2/ui/dialogs/CopyPopup.java new file mode 100644 index 0000000000..21ab9b2688 --- /dev/null +++ b/tycho-its/projects/api-tools/missing-bin/org.eclipse.equinox.p2.ui/src/org/eclipse/equinox/internal/p2/ui/dialogs/CopyPopup.java @@ -0,0 +1,50 @@ +/******************************************************************************* + * Copyright (c) 2009, 2010 IBM Corporation and others. + * + * This program and the accompanying materials + * are made available under the terms of the Eclipse Public License 2.0 + * which accompanies this distribution, and is available at + * https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + * + * Contributors: + * IBM Corporation - initial API and implementation + ******************************************************************************/ + +package org.eclipse.equinox.internal.p2.ui.dialogs; + +import org.eclipse.equinox.internal.p2.ui.ProvUIImages; +import org.eclipse.equinox.p2.ui.ICopyable; +import org.eclipse.jface.resource.JFaceResources; +import org.eclipse.swt.SWT; +import org.eclipse.swt.events.SelectionEvent; +import org.eclipse.swt.events.SelectionListener; +import org.eclipse.swt.widgets.*; + +public class CopyPopup { + + ICopyable copySource; + Control control; + + public CopyPopup(ICopyable copyable, final Control control) { + this.copySource = copyable; + this.control = control; + Menu copyMenu = new Menu(control); + MenuItem copyItem = new MenuItem(copyMenu, SWT.NONE); + copyItem.setImage(ProvUIImages.getImage(ProvUIImages.IMG_COPY)); + copyItem.addSelectionListener(new SelectionListener() { + @Override + public void widgetSelected(SelectionEvent e) { + copySource.copyToClipboard(control); + } + + @Override + public void widgetDefaultSelected(SelectionEvent e) { + copySource.copyToClipboard(control); + } + }); + copyItem.setText(JFaceResources.getString("copy")); //$NON-NLS-1$ + control.setMenu(copyMenu); + } +} \ No newline at end of file diff --git a/tycho-its/projects/api-tools/missing-bin/org.eclipse.equinox.p2.ui/src/org/eclipse/equinox/internal/p2/ui/dialogs/CopyUtils.java b/tycho-its/projects/api-tools/missing-bin/org.eclipse.equinox.p2.ui/src/org/eclipse/equinox/internal/p2/ui/dialogs/CopyUtils.java new file mode 100644 index 0000000000..96c02c1944 --- /dev/null +++ b/tycho-its/projects/api-tools/missing-bin/org.eclipse.equinox.p2.ui/src/org/eclipse/equinox/internal/p2/ui/dialogs/CopyUtils.java @@ -0,0 +1,91 @@ +/******************************************************************************* + * Copyright (c) 2009, 2018 IBM Corporation and others. + * + * This program and the accompanying materials + * are made available under the terms of the Eclipse Public License 2.0 + * which accompanies this distribution, and is available at + * https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + * + * Contributors: + * IBM Corporation - initial API and implementation + * Red Hat Inc. - Bug 460967 + ******************************************************************************/ + +package org.eclipse.equinox.internal.p2.ui.dialogs; + +import org.eclipse.core.expressions.*; +import org.eclipse.equinox.internal.p2.ui.model.ProvElement; +import org.eclipse.equinox.internal.p2.ui.viewers.IUDetailsLabelProvider; +import org.eclipse.equinox.p2.ui.ICopyable; +import org.eclipse.swt.widgets.Control; +import org.eclipse.ui.ISources; +import org.eclipse.ui.PlatformUI; +import org.eclipse.ui.handlers.IHandlerActivation; +import org.eclipse.ui.handlers.IHandlerService; +import org.eclipse.ui.swt.IFocusService; + +public class CopyUtils { + public static final String NEWLINE = System.lineSeparator(); + public static final String DELIMITER = "\t"; //$NON-NLS-1$ + private static final String NESTING_INDENT = " "; //$NON-NLS-1$ + + // We never test the control ID so we can use the same ID for all controls + private static final String CONTROL_ID = "org.eclipse.equinox.p2.ui.CopyControlId"; //$NON-NLS-1$ + + public static String getIndentedClipboardText(Object[] elements, IUDetailsLabelProvider labelProvider) { + StringBuilder buffer = new StringBuilder(); + for (int i = 0; i < elements.length; i++) { + if (i > 0) + buffer.append(NEWLINE); + appendIndention(buffer, elements[i]); + buffer.append(labelProvider.getClipboardText(elements[i], DELIMITER)); + } + return buffer.toString(); + } + + /** + * Install a copy popup menu on the specified control and activate the copy + * handler for the control when the control has focus. The handler will be + * deactivated when the control is disposed. + * + * @param copyable the copyable that will perform the copy + * @param control the control on which to install the menu and handler + */ + public static void activateCopy(ICopyable copyable, final Control control) { + new CopyPopup(copyable, control); + if (PlatformUI.isWorkbenchRunning()) { + final IFocusService fs = PlatformUI.getWorkbench().getService(IFocusService.class); + final IHandlerService hs = PlatformUI.getWorkbench().getService(IHandlerService.class); + if (fs != null && hs != null) { + fs.addFocusTracker(control, CONTROL_ID); + final IHandlerActivation handlerActivation = hs.activateHandler(CopyHandler.ID, + new CopyHandler(copyable), new Expression() { + @Override + public EvaluationResult evaluate(IEvaluationContext context) { + return context.getVariable(ISources.ACTIVE_FOCUS_CONTROL_NAME) == control + ? EvaluationResult.TRUE + : EvaluationResult.FALSE; + } + + @Override + public void collectExpressionInfo(final ExpressionInfo info) { + info.addVariableNameAccess(ISources.ACTIVE_FOCUS_CONTROL_NAME); + } + + }); + control.addDisposeListener(e -> hs.deactivateHandler(handlerActivation)); + } + } + } + + private static void appendIndention(StringBuilder buffer, Object element) { + Object parent; + while (element instanceof ProvElement && (parent = ((ProvElement) element).getParent(element)) != null) { + buffer.append(NESTING_INDENT); + element = parent; + } + + } +} \ No newline at end of file diff --git a/tycho-its/projects/api-tools/missing-bin/org.eclipse.equinox.p2.ui/src/org/eclipse/equinox/internal/p2/ui/dialogs/DelayedFilterCheckboxTree.java b/tycho-its/projects/api-tools/missing-bin/org.eclipse.equinox.p2.ui/src/org/eclipse/equinox/internal/p2/ui/dialogs/DelayedFilterCheckboxTree.java new file mode 100644 index 0000000000..21f0266080 --- /dev/null +++ b/tycho-its/projects/api-tools/missing-bin/org.eclipse.equinox.p2.ui/src/org/eclipse/equinox/internal/p2/ui/dialogs/DelayedFilterCheckboxTree.java @@ -0,0 +1,353 @@ +/******************************************************************************* + * Copyright (c) 2008, 2018 IBM Corporation and others. + * + * This program and the accompanying materials + * are made available under the terms of the Eclipse Public License 2.0 + * which accompanies this distribution, and is available at + * https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + * + * Contributors: + * IBM Corporation - initial API and implementation + *******************************************************************************/ +package org.eclipse.equinox.internal.p2.ui.dialogs; + +import java.util.*; +import org.eclipse.core.runtime.jobs.*; +import org.eclipse.equinox.internal.p2.ui.viewers.DeferredQueryContentProvider; +import org.eclipse.jface.viewers.TreeViewer; +import org.eclipse.swt.widgets.*; +import org.eclipse.ui.dialogs.FilteredTree; +import org.eclipse.ui.dialogs.PatternFilter; +import org.eclipse.ui.progress.WorkbenchJob; + +/** + * FilteredTree extension that creates a ContainerCheckedTreeViewer, manages the + * check state across filtering (working around bugs in ContainerCheckedTreeViewer), + * and preloads all metadata repositories before allowing filtering, in order to + * coordinate background fetch and filtering. It also manages a cache of expanded + * elements that can survive a change of input. + * + * @since 3.4 + * + */ +public class DelayedFilterCheckboxTree extends FilteredTree { + + private static final long FILTER_DELAY = 800; + + public static final Object ALL_ITEMS_HACK = new Object(); + + ToolBar toolBar; + Display display; + PatternFilter patternFilter; + IPreFilterJobProvider jobProvider; + DeferredQueryContentProvider contentProvider; + String savedFilterText; + Job preFilterJob; + WorkbenchJob filterJob; + boolean ignoreFiltering = true; + Object viewerInput; + HashSet checkState = new HashSet<>(); + Set expanded = new HashSet<>(); + ContainerCheckedTreeViewer checkboxViewer; + + public DelayedFilterCheckboxTree(Composite parent, int treeStyle, PatternFilter filter, IPreFilterJobProvider jobProvider) { + super(parent, true); + this.display = parent.getDisplay(); + this.patternFilter = filter; + init(treeStyle, filter); + } + + @Override + protected TreeViewer doCreateTreeViewer(Composite composite, int style) { + checkboxViewer = new ContainerCheckedTreeViewer(composite, style); + checkboxViewer.addCheckStateListener(event -> { + // We use an additive check state cache so we need to remove + // previously checked items if the user unchecked them. + if (!event.getChecked() && checkState != null) { + if (event.getElement() == ALL_ITEMS_HACK) { + clearCheckStateCache(); + } else { + ArrayList toRemove = new ArrayList<>(1); + // See bug 258117. Ideally we would get check state changes + // for children when the parent state changed, but we aren't, so + // we need to remove all children from the additive check state + // cache. + if (contentProvider.hasChildren(event.getElement())) { + Set unchecked = new HashSet<>(); + // See bug 533655, We should uncheck all of the children + // of the triggering element, not just the direct descendants. + uncheckAllChildren(unchecked, event.getElement()); + + Iterator iter = checkState.iterator(); + while (iter.hasNext()) { + Object current = iter.next(); + if (current != null && unchecked.contains(current)) { + toRemove.add(current); + } + } + } else { + for (Object element2 : checkState) { + if (checkboxViewer.getComparer().equals(element2, event.getElement())) { + toRemove.add(element2); + // Do not break out of the loop. We may have duplicate equal + // elements in the cache. Since the cache is additive, we want + // to be sure we've gotten everything. + } + } + } + checkState.removeAll(toRemove); + } + } else if (event.getChecked()) { + rememberLeafCheckState(); + } + }); + return checkboxViewer; + } + + private void uncheckAllChildren(Set unchecked, Object element) { + for (Object child : contentProvider.getChildren(element)) { + unchecked.add(child); + if (contentProvider.getChildren(child).length > 0) { + uncheckAllChildren(unchecked, child); + } + } + } + + @Override + protected Composite createFilterControls(Composite filterParent) { + super.createFilterControls(filterParent); + filterParent.addDisposeListener(e -> cancelPreFilterJob()); + return filterParent; + } + + public void contentProviderSet(final DeferredQueryContentProvider deferredProvider) { + this.contentProvider = deferredProvider; + deferredProvider.addListener((v, oldInput, newInput) -> { + if (newInput == null) { + return; + } + // Store the input because it's not reset in the viewer until + // after this listener is run. + viewerInput = newInput; + + // If we were loading repos, we want to cancel because there may be more. + cancelPreFilterJob(); + // Cancel any filtering + cancelAndResetFilterJob(); + contentProvider.setSynchronous(false); + // Remember any previous expansions + rememberExpansions(); + // If there are remembered check states, try to restore them. + // Must be done in an async because we are in the middle of a buggy + // selection preserving viewer refresh. + checkboxViewer.getTree().setRedraw(false); + display.asyncExec(() -> { + if (checkboxViewer.getTree().isDisposed()) { + return; + } + rememberExpansions(); + restoreLeafCheckState(); + rememberExpansions(); + restoreExpansions(); + checkboxViewer.getTree().setRedraw(true); + }); + }); + } + + public void clearCheckStateCache() { + checkState = null; + } + + /* + * Overridden to hook a listener on the job and set the deferred content provider + * to synchronous mode before a filter is done. + * @see org.eclipse.ui.dialogs.FilteredTree#doCreateRefreshJob() + */ + @Override + protected WorkbenchJob doCreateRefreshJob() { + filterJob = super.doCreateRefreshJob(); + + filterJob.addJobChangeListener(new JobChangeAdapter() { + @Override + public void aboutToRun(final IJobChangeEvent event) { + // If we know we've already filtered and loaded repos, nothing more to do + if (!ignoreFiltering) { + return; + } + final boolean[] shouldPreFilter = new boolean[1]; + shouldPreFilter[0] = false; + display.syncExec(() -> { + if (filterText != null && !filterText.isDisposed()) { + String text = getFilterString(); + // If we are about to filter and there is + // actually filtering to do, check for a prefilter + // job and the content provider to synchronous mode. + // We want the prefilter job to complete before continuing with filtering. + if (text == null || (initialText != null && initialText.equals(text))) { + return; + } + if (!contentProvider.getSynchronous() && preFilterJob == null) { + if (filterText != null && !filterText.isDisposed()) { + shouldPreFilter[0] = true; + } + } + } + }); + if (shouldPreFilter[0]) { + event.getJob().sleep(); + schedulePreFilterJob(); + } else if (ignoreFiltering) { + event.getJob().sleep(); + } else { + // shouldn't get here unless the prefilter job finished + // and ignoreFiltering became false since we entered this listener. + rememberLeafCheckState(); + } + } + + @Override + public void running(IJobChangeEvent event) { + display.syncExec(() -> rememberLeafCheckState()); + } + + @Override + public void done(IJobChangeEvent event) { + if (event.getResult().isOK()) { + display.asyncExec(() -> { + if (checkboxViewer.getTree().isDisposed()) { + return; + } + + checkboxViewer.getTree().setRedraw(false); + // remember things expanded by the filter + rememberExpansions(); + restoreLeafCheckState(); + // now restore expansions because we may have + // had others + restoreExpansions(); + checkboxViewer.getTree().setRedraw(true); + }); + } + } + }); + return filterJob; + } + + void schedulePreFilterJob() { + // cancel any existing jobs + cancelPreFilterJob(); + ignoreFiltering = false; + preFilterJob = jobProvider == null ? null : jobProvider.getPreFilterJob(); + if (preFilterJob == null) { + if (filterJob != null) { + filterJob.wakeUp(); + } + return; + } + ignoreFiltering = true; + preFilterJob.addJobChangeListener(new JobChangeAdapter() { + @Override + public void done(IJobChangeEvent event) { + ignoreFiltering = false; + contentProvider.setSynchronous(true); + if (filterJob != null) { + filterJob.wakeUp(); + } + preFilterJob = null; + } + }); + preFilterJob.setSystem(true); + preFilterJob.setUser(false); + preFilterJob.schedule(); + } + + void cancelPreFilterJob() { + if (preFilterJob != null) { + preFilterJob.cancel(); + preFilterJob = null; + } + } + + void cancelAndResetFilterJob() { + if (filterJob != null) { + filterJob.cancel(); + } + } + + void rememberLeafCheckState() { + ContainerCheckedTreeViewer v = (ContainerCheckedTreeViewer) getViewer(); + Object[] checked = v.getCheckedElements(); + if (checkState == null) { + checkState = new HashSet<>(checked.length); + } + for (Object element : checked) { + if (!v.getGrayed(element) && contentProvider.getChildren(element).length == 0) { + if (!checkState.contains(element)) { + checkState.add(element); + } + } + } + } + + void restoreLeafCheckState() { + if (checkboxViewer == null || checkboxViewer.getTree().isDisposed()) { + return; + } + if (checkState == null) { + return; + } + + checkboxViewer.setCheckedElements(new Object[0]); + checkboxViewer.setGrayedElements(new Object[0]); + // Now we are only going to set the check state of the leaf nodes + // and rely on our container checked code to update the parents properly. + Iterator iter = checkState.iterator(); + Object element = null; + if (iter.hasNext()) { + checkboxViewer.expandAll(); + } + while (iter.hasNext()) { + element = iter.next(); + checkboxViewer.setChecked(element, true); + } + // We are only firing one event, knowing that this is enough for our listeners. + if (element != null) { + checkboxViewer.fireCheckStateChanged(element, true); + } + } + + void rememberExpansions() { + // The expansions are additive, but we are using a set to keep out + // duplicates. In practice, this means expanded items from different + // inputs will remain expanded, such as categories with the same name + // in different repos. + expanded.addAll(Arrays.asList(getViewer().getExpandedElements())); + } + + void restoreExpansions() { + getViewer().setExpandedElements(expanded.toArray()); + } + + public ContainerCheckedTreeViewer getCheckboxTreeViewer() { + return checkboxViewer; + } + + @Override + protected long getRefreshJobDelay() { + return FILTER_DELAY; + } + + public Object[] getCheckedElements() { + if (this.checkState != null) { + return this.checkState.toArray(); + } + return new Object[0]; + } + + @Override + protected String getFilterString() { + return super.getFilterString(); + } +} diff --git a/tycho-its/projects/api-tools/missing-bin/org.eclipse.equinox.p2.ui/src/org/eclipse/equinox/internal/p2/ui/dialogs/ILayoutConstants.java b/tycho-its/projects/api-tools/missing-bin/org.eclipse.equinox.p2.ui/src/org/eclipse/equinox/internal/p2/ui/dialogs/ILayoutConstants.java new file mode 100644 index 0000000000..14659810e1 --- /dev/null +++ b/tycho-its/projects/api-tools/missing-bin/org.eclipse.equinox.p2.ui/src/org/eclipse/equinox/internal/p2/ui/dialogs/ILayoutConstants.java @@ -0,0 +1,37 @@ +/******************************************************************************* + * Copyright (c) 2008, 2009 IBM Corporation and others. + * + * This program and the accompanying materials + * are made available under the terms of the Eclipse Public License 2.0 + * which accompanies this distribution, and is available at + * https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + * + * Contributors: + * IBM Corporation - initial API and implementation + *******************************************************************************/ +package org.eclipse.equinox.internal.p2.ui.dialogs; + +/** + * ILayoutConstants defines common dialog constants used when laying + * out dialogs. Units of measurement are character widths and heights + * unless otherwise specified. + * + * This interface is not intended to be implemented + * + * @noimplement This interface is not intended to be implemented by clients. + * @noextend This interface is not intended to be extended by clients. + * @since 3.5 + */ +public interface ILayoutConstants { + public static final int DEFAULT_DESCRIPTION_HEIGHT = 4; + public static final int MINIMUM_DESCRIPTION_HEIGHT = 1; + public static final int DEFAULT_SITEDETAILS_HEIGHT = 2; + public static final int DEFAULT_PRIMARY_COLUMN_WIDTH = 60; + public static final int DEFAULT_COLUMN_WIDTH = 40; + public static final int DEFAULT_SMALL_COLUMN_WIDTH = 20; + public static final int DEFAULT_TABLE_HEIGHT = 10; + public static final int DEFAULT_TABLE_WIDTH = 80; + public static final int[] IUS_TO_DETAILS_WEIGHTS = new int[] {80, 20}; +} diff --git a/tycho-its/projects/api-tools/missing-bin/org.eclipse.equinox.p2.ui/src/org/eclipse/equinox/internal/p2/ui/dialogs/IPreFilterJobProvider.java b/tycho-its/projects/api-tools/missing-bin/org.eclipse.equinox.p2.ui/src/org/eclipse/equinox/internal/p2/ui/dialogs/IPreFilterJobProvider.java new file mode 100644 index 0000000000..9cf44cf0c7 --- /dev/null +++ b/tycho-its/projects/api-tools/missing-bin/org.eclipse.equinox.p2.ui/src/org/eclipse/equinox/internal/p2/ui/dialogs/IPreFilterJobProvider.java @@ -0,0 +1,26 @@ +/******************************************************************************* + * Copyright (c) 2010 IBM Corporation and others. + * + * This program and the accompanying materials + * are made available under the terms of the Eclipse Public License 2.0 + * which accompanies this distribution, and is available at + * https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + * + * Contributors: + * IBM Corporation - initial API and implementation + *******************************************************************************/ +package org.eclipse.equinox.internal.p2.ui.dialogs; + +import org.eclipse.core.runtime.jobs.Job; + +/** + * IPreFilterJobProvider provides an optional job that must be run before + * filtering can be allowed to occur in a filtered tree. The client is assumed + * to have set the expected job priority. + * + */ +public interface IPreFilterJobProvider { + public Job getPreFilterJob(); +} diff --git a/tycho-its/projects/api-tools/missing-bin/org.eclipse.equinox.p2.ui/src/org/eclipse/equinox/internal/p2/ui/dialogs/IRepositoryManipulationHook.java b/tycho-its/projects/api-tools/missing-bin/org.eclipse.equinox.p2.ui/src/org/eclipse/equinox/internal/p2/ui/dialogs/IRepositoryManipulationHook.java new file mode 100644 index 0000000000..6786991483 --- /dev/null +++ b/tycho-its/projects/api-tools/missing-bin/org.eclipse.equinox.p2.ui/src/org/eclipse/equinox/internal/p2/ui/dialogs/IRepositoryManipulationHook.java @@ -0,0 +1,25 @@ +/******************************************************************************* + * Copyright (c) 2010 IBM Corporation and others. + * + * This program and the accompanying materials + * are made available under the terms of the Eclipse Public License 2.0 + * which accompanies this distribution, and is available at + * https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + * + * Contributors: + * IBM Corporation - initial API and implementation + *******************************************************************************/ +package org.eclipse.equinox.internal.p2.ui.dialogs; + + +/** + * IRepositoryManipulationHood defines callbacks that are called when the + * UI is manipulating repositories. + */ +public interface IRepositoryManipulationHook { + public void preManipulateRepositories(); + + public void postManipulateRepositories(); +} diff --git a/tycho-its/projects/api-tools/missing-bin/org.eclipse.equinox.p2.ui/src/org/eclipse/equinox/internal/p2/ui/dialogs/IRepositorySelectionListener.java b/tycho-its/projects/api-tools/missing-bin/org.eclipse.equinox.p2.ui/src/org/eclipse/equinox/internal/p2/ui/dialogs/IRepositorySelectionListener.java new file mode 100644 index 0000000000..d64f317424 --- /dev/null +++ b/tycho-its/projects/api-tools/missing-bin/org.eclipse.equinox.p2.ui/src/org/eclipse/equinox/internal/p2/ui/dialogs/IRepositorySelectionListener.java @@ -0,0 +1,32 @@ +/******************************************************************************* + * Copyright (c) 2009, 2010 IBM Corporation and others. + * + * This program and the accompanying materials + * are made available under the terms of the Eclipse Public License 2.0 + * which accompanies this distribution, and is available at + * https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + * + * Contributors: + * IBM Corporation - initial API and implementation + *******************************************************************************/ +package org.eclipse.equinox.internal.p2.ui.dialogs; + +import java.net.URI; + +/** + * Listener for the repository selection combo. Whenever the selected repository changes (menu selection, + * text modified, new repo added) this listener will be notified. + * + * @since 3.5 + */ +public interface IRepositorySelectionListener { + /** + * Called whenever the selected repository in the combo changes. + * + * @param repoChoice one of AvailableIUGroup.AVAILABLE_NONE, AvailableIUGroup.AVAILABLE_ALL, AvailableIUGroup.AVAILABLE_LOCAL, AvailableIUGroup.AVAILABLE_SPECIFIED + * @param repoLocation if the repoChoice is set to AvailableIUGroup.AVAILABLE_SPECIFIED, this field will contain the URI of the selected repo, otherwise null + */ + public void repositorySelectionChanged(int repoChoice, URI repoLocation); +} \ No newline at end of file diff --git a/tycho-its/projects/api-tools/missing-bin/org.eclipse.equinox.p2.ui/src/org/eclipse/equinox/internal/p2/ui/dialogs/IResolutionErrorReportingPage.java b/tycho-its/projects/api-tools/missing-bin/org.eclipse.equinox.p2.ui/src/org/eclipse/equinox/internal/p2/ui/dialogs/IResolutionErrorReportingPage.java new file mode 100644 index 0000000000..8430bad7b2 --- /dev/null +++ b/tycho-its/projects/api-tools/missing-bin/org.eclipse.equinox.p2.ui/src/org/eclipse/equinox/internal/p2/ui/dialogs/IResolutionErrorReportingPage.java @@ -0,0 +1,30 @@ +/******************************************************************************* + * Copyright (c) 2009, 2010 IBM Corporation and others. + * + * This program and the accompanying materials + * are made available under the terms of the Eclipse Public License 2.0 + * which accompanies this distribution, and is available at + * https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + * + * Contributors: + * IBM Corporation - initial API and implementation + ******************************************************************************/ + +package org.eclipse.equinox.internal.p2.ui.dialogs; + +import org.eclipse.equinox.internal.p2.ui.model.IUElementListRoot; +import org.eclipse.equinox.p2.operations.ProfileChangeOperation; + +/** + * + * IErrorReportingPage is used to report resolution + * errors on a wizard page. + * + * @since 3.5 + * + */ +public interface IResolutionErrorReportingPage extends ISelectableIUsPage { + public void updateStatus(IUElementListRoot root, ProfileChangeOperation operation); +} diff --git a/tycho-its/projects/api-tools/missing-bin/org.eclipse.equinox.p2.ui/src/org/eclipse/equinox/internal/p2/ui/dialogs/ISelectableIUsPage.java b/tycho-its/projects/api-tools/missing-bin/org.eclipse.equinox.p2.ui/src/org/eclipse/equinox/internal/p2/ui/dialogs/ISelectableIUsPage.java new file mode 100644 index 0000000000..561cb2b13c --- /dev/null +++ b/tycho-its/projects/api-tools/missing-bin/org.eclipse.equinox.p2.ui/src/org/eclipse/equinox/internal/p2/ui/dialogs/ISelectableIUsPage.java @@ -0,0 +1,33 @@ +/******************************************************************************* + * Copyright (c) 2008, 2009 IBM Corporation and others. + * + * This program and the accompanying materials + * are made available under the terms of the Eclipse Public License 2.0 + * which accompanies this distribution, and is available at + * https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + * + * Contributors: + * IBM Corporation - initial API and implementation + *******************************************************************************/ + +package org.eclipse.equinox.internal.p2.ui.dialogs; + +import org.eclipse.jface.wizard.IWizardPage; + +/** + * + * ISelectableIUsPage is used to get the selected or checked IUs in a + * wizard page. + * + * @since 3.5 + * + */ +public interface ISelectableIUsPage extends IWizardPage { + public Object[] getCheckedIUElements(); + + public Object[] getSelectedIUElements(); + + public void setCheckedElements(Object[] elements); +} diff --git a/tycho-its/projects/api-tools/missing-bin/org.eclipse.equinox.p2.ui/src/org/eclipse/equinox/internal/p2/ui/dialogs/IUCopyrightPropertyPage.java b/tycho-its/projects/api-tools/missing-bin/org.eclipse.equinox.p2.ui/src/org/eclipse/equinox/internal/p2/ui/dialogs/IUCopyrightPropertyPage.java new file mode 100644 index 0000000000..07accd86b6 --- /dev/null +++ b/tycho-its/projects/api-tools/missing-bin/org.eclipse.equinox.p2.ui/src/org/eclipse/equinox/internal/p2/ui/dialogs/IUCopyrightPropertyPage.java @@ -0,0 +1,81 @@ +/******************************************************************************* + * Copyright (c) 2007, 2018 IBM Corporation and others. + * + * This program and the accompanying materials + * are made available under the terms of the Eclipse Public License 2.0 + * which accompanies this distribution, and is available at + * https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + * + * Contributors: + * IBM Corporation - initial API and implementation + *******************************************************************************/ +package org.eclipse.equinox.internal.p2.ui.dialogs; + +import java.net.MalformedURLException; +import org.eclipse.core.runtime.URIUtil; +import org.eclipse.equinox.internal.p2.ui.ProvUIMessages; +import org.eclipse.equinox.p2.metadata.ICopyright; +import org.eclipse.equinox.p2.metadata.IInstallableUnit; +import org.eclipse.osgi.util.NLS; +import org.eclipse.swt.SWT; +import org.eclipse.swt.events.SelectionListener; +import org.eclipse.swt.layout.GridData; +import org.eclipse.swt.layout.GridLayout; +import org.eclipse.swt.widgets.*; + +/** + * PropertyPage that shows an IU's copyright + * + * @since 3.4 + */ +public class IUCopyrightPropertyPage extends IUPropertyPage { + + @Override + protected Control createIUPage(Composite parent, IInstallableUnit iu) { + // Get the copyright in the current locale + final ICopyright copyright = iu.getCopyright(null); + if (copyright != null && copyright.getBody().length() > 0) { + Composite composite = new Composite(parent, SWT.NONE); + GridLayout layout = new GridLayout(); + layout.marginWidth = 0; + layout.marginHeight = 0; + composite.setLayout(layout); + + Text text = new Text(composite, SWT.MULTI | SWT.V_SCROLL | SWT.H_SCROLL | SWT.BORDER | SWT.WRAP); + GridData gd = new GridData(SWT.FILL, SWT.FILL, true, true); + gd.widthHint = computeWidthLimit(text, 80); + gd.grabExcessVerticalSpace = true; + text.setLayoutData(gd); + text.setText(copyright.getBody()); + text.setEditable(false); + + // If an URL was specified, provide a link to it + String filename = (copyright.getLocation() != null) ? copyright.getLocation().getPath() : null; + if (filename != null && (filename.endsWith(".htm") || filename.endsWith(".html"))) { //$NON-NLS-1$ //$NON-NLS-2$ + Label label = new Label(composite, SWT.NONE); + label.setText(ProvUIMessages.IUCopyrightPropertyPage_ViewLinkLabel); + // Create a link to the copyright URL + Link link = new Link(composite, SWT.LEFT | SWT.WRAP); + link.setText(NLS.bind("{0}", URIUtil.toUnencodedString(copyright.getLocation()))); //$NON-NLS-1$ + gd = new GridData(GridData.FILL_HORIZONTAL | GridData.VERTICAL_ALIGN_BEGINNING); + gd.widthHint = computeWidthLimit(link, 80); + link.setLayoutData(gd); + link.addSelectionListener(SelectionListener.widgetSelectedAdapter(e -> { + try { + showURL(copyright.getLocation().toURL()); + } catch (MalformedURLException e1) { + //cannot show this URL + } + })); + } + + return composite; + } + Label label = new Label(parent, SWT.NULL); + label.setText(ProvUIMessages.IUCopyrightPropertyPage_NoCopyright); + return label; + + } +} diff --git a/tycho-its/projects/api-tools/missing-bin/org.eclipse.equinox.p2.ui/src/org/eclipse/equinox/internal/p2/ui/dialogs/IUDetailsGroup.java b/tycho-its/projects/api-tools/missing-bin/org.eclipse.equinox.p2.ui/src/org/eclipse/equinox/internal/p2/ui/dialogs/IUDetailsGroup.java new file mode 100644 index 0000000000..c33c880c09 --- /dev/null +++ b/tycho-its/projects/api-tools/missing-bin/org.eclipse.equinox.p2.ui/src/org/eclipse/equinox/internal/p2/ui/dialogs/IUDetailsGroup.java @@ -0,0 +1,164 @@ +/******************************************************************************* +* Copyright (c) 2009, 2020 EclipseSource and others. + * + * This +* program and the accompanying materials are made available under the terms of +* the Eclipse Public License 2.0 which accompanies this distribution, and is +* available at + * https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 +* +* Contributors: +* EclipseSource - initial API and implementation +* IBM Corporation - ongoing development +******************************************************************************/ +package org.eclipse.equinox.internal.p2.ui.dialogs; + +import org.eclipse.core.text.StringMatcher; +import org.eclipse.equinox.internal.p2.ui.ProvUIMessages; +import org.eclipse.equinox.internal.p2.ui.actions.PropertyDialogAction; +import org.eclipse.jface.action.IAction; +import org.eclipse.jface.dialogs.Dialog; +import org.eclipse.jface.dialogs.IDialogConstants; +import org.eclipse.jface.resource.JFaceResources; +import org.eclipse.jface.viewers.ISelectionProvider; +import org.eclipse.jface.window.SameShellProvider; +import org.eclipse.swt.SWT; +import org.eclipse.swt.custom.StyleRange; +import org.eclipse.swt.custom.StyledText; +import org.eclipse.swt.graphics.FontMetrics; +import org.eclipse.swt.graphics.GC; +import org.eclipse.swt.layout.GridData; +import org.eclipse.swt.layout.GridLayout; +import org.eclipse.swt.widgets.*; + +/** + * Creates a details group for a list of IUs. + */ +public class IUDetailsGroup { + + private static final String LINKACTION = "linkAction"; //$NON-NLS-1$ + + private GridLayout layout; + private StyledText detailsArea; + private GridData gd; + private Link propLink; + private ISelectionProvider selectionProvider; + private int widthHint; + private boolean scrollable; + private String lastText; + + /** + * + */ + public IUDetailsGroup(Composite parent, ISelectionProvider selectionProvider, int widthHint, boolean scrollable) { + this.selectionProvider = selectionProvider; + this.widthHint = widthHint; + this.scrollable = scrollable; + createGroupComposite(parent); + } + + /** + * Creates the group composite that holds the details area + * @param parent The parent composite + */ + void createGroupComposite(Composite parent) { + Group detailsComposite = new Group(parent, SWT.NONE); + GC gc = new GC(parent); + gc.setFont(JFaceResources.getDialogFont()); + FontMetrics fontMetrics = gc.getFontMetrics(); + gc.dispose(); + + detailsComposite.setText(ProvUIMessages.ProfileModificationWizardPage_DetailsLabel); + layout = new GridLayout(); + layout.marginWidth = 0; + layout.marginHeight = 0; + detailsComposite.setLayout(layout); + gd = new GridData(SWT.FILL, SWT.FILL, true, true); + detailsComposite.setLayoutData(gd); + + gd = new GridData(SWT.FILL, SWT.FILL, true, true); + gd.verticalIndent = Dialog.convertVerticalDLUsToPixels(fontMetrics, IDialogConstants.VERTICAL_SPACING); + gd.heightHint = Dialog.convertHeightInCharsToPixels(fontMetrics, ILayoutConstants.DEFAULT_DESCRIPTION_HEIGHT); + gd.minimumHeight = Dialog.convertHeightInCharsToPixels(fontMetrics, ILayoutConstants.MINIMUM_DESCRIPTION_HEIGHT); + gd.widthHint = widthHint; + if (scrollable) + detailsArea = new StyledText(detailsComposite, SWT.WRAP | SWT.READ_ONLY | SWT.V_SCROLL); + else + detailsArea = new StyledText(detailsComposite, SWT.WRAP | SWT.READ_ONLY); + detailsArea.setLayoutData(gd); + + gd = new GridData(SWT.END, SWT.BOTTOM, true, false); + gd.horizontalIndent = Dialog.convertHorizontalDLUsToPixels(fontMetrics, IDialogConstants.HORIZONTAL_MARGIN); + propLink = createLink(detailsComposite, new PropertyDialogAction(new SameShellProvider(parent.getShell()), selectionProvider), ProvUIMessages.AvailableIUsPage_GotoProperties); + propLink.setLayoutData(gd); + + // set the initial state based on selection + propLink.setVisible(!selectionProvider.getSelection().isEmpty()); + + } + + /** + * Set the detail text + */ + public void setDetailText(String text) { + // If the string is the same but the user has scrolled, the text + // widget will reset the selection. This makes it look like the text + // has changed when it hasn't. For this reason, we check equality first. + if (lastText == null || !lastText.equals(text)) { + detailsArea.setText(text); + } + lastText = text; + } + + /** + * Set the pattern to highlight in the detail text + */ + public void setDetailHighlight(String pattern) { + detailsArea.setStyleRanges(new StyleRange[0]); + if (pattern != null && !pattern.isEmpty()) { + StringMatcher matcher = new StringMatcher(pattern, true, false); + int i = 0; + StringMatcher.Position match = null; + do { + match = matcher.find(lastText, i, lastText.length()); + if (match != null) { + i = match.getEnd(); + detailsArea.setStyleRange(new StyleRange(match.getStart(), match.getEnd() - match.getStart(), null, null, SWT.BOLD)); + } + } while (match != null); + } + } + + /** + * Toggles the property link for the details area. + */ + public void enablePropertyLink(boolean enable) { + propLink.setVisible(enable); + } + + private Link createLink(Composite parent, IAction action, String text) { + Link link = new Link(parent, SWT.PUSH); + link.setText(text); + + link.addListener(SWT.Selection, event -> { + IAction linkAction = getLinkAction(event.widget); + if (linkAction != null) { + linkAction.runWithEvent(event); + } + }); + link.setToolTipText(action.getToolTipText()); + link.setData(LINKACTION, action); + return link; + } + + IAction getLinkAction(Widget widget) { + Object data = widget.getData(LINKACTION); + if (data == null || !(data instanceof IAction)) { + return null; + } + return (IAction) data; + } + +} diff --git a/tycho-its/projects/api-tools/missing-bin/org.eclipse.equinox.p2.ui/src/org/eclipse/equinox/internal/p2/ui/dialogs/IUGeneralInfoPropertyPage.java b/tycho-its/projects/api-tools/missing-bin/org.eclipse.equinox.p2.ui/src/org/eclipse/equinox/internal/p2/ui/dialogs/IUGeneralInfoPropertyPage.java new file mode 100644 index 0000000000..050d66ab2f --- /dev/null +++ b/tycho-its/projects/api-tools/missing-bin/org.eclipse.equinox.p2.ui/src/org/eclipse/equinox/internal/p2/ui/dialogs/IUGeneralInfoPropertyPage.java @@ -0,0 +1,126 @@ +/******************************************************************************* + * Copyright (c) 2007, 2018 IBM Corporation and others. + * + * This program and the accompanying materials + * are made available under the terms of the Eclipse Public License 2.0 + * which accompanies this distribution, and is available at + * https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + * + * Contributors: + * IBM Corporation - initial API and implementation + *******************************************************************************/ +package org.eclipse.equinox.internal.p2.ui.dialogs; + +import java.net.MalformedURLException; +import java.net.URL; +import org.eclipse.equinox.internal.p2.ui.ProvUIMessages; +import org.eclipse.equinox.p2.metadata.IInstallableUnit; +import org.eclipse.osgi.util.NLS; +import org.eclipse.swt.SWT; +import org.eclipse.swt.events.SelectionListener; +import org.eclipse.swt.layout.GridData; +import org.eclipse.swt.layout.GridLayout; +import org.eclipse.swt.widgets.*; + +/** + * PropertyPage that shows an IU's properties + * + * @since 3.4 + */ +public class IUGeneralInfoPropertyPage extends IUPropertyPage { + + @Override + protected Control createIUPage(Composite parent, IInstallableUnit iu) { + Composite composite = new Composite(parent, SWT.NONE); + GridLayout layout = new GridLayout(); + layout.marginWidth = 0; + layout.marginHeight = 0; + composite.setLayout(layout); + + createGeneralSection(composite, iu); + createDescriptionSection(composite, iu); + createDocumentationSection(composite, iu); + + return composite; + } + + private void createGeneralSection(Composite parent, IInstallableUnit iu) { + Composite composite = new Composite(parent, SWT.NONE); + GridLayout layout = new GridLayout(); + layout.numColumns = 2; + layout.marginWidth = 0; + layout.marginHeight = 0; + composite.setLayout(layout); + composite.setLayoutData(new GridData(GridData.FILL_HORIZONTAL)); + // Get general info in the default locale + addField(composite, ProvUIMessages.IUGeneralInfoPropertyPage_NameLabel, iu.getProperty(IInstallableUnit.PROP_NAME, null)); + addField(composite, ProvUIMessages.IUGeneralInfoPropertyPage_IdentifierLabel, iu.getId()); + addField(composite, ProvUIMessages.IUGeneralInfoPropertyPage_VersionLabel, iu.getVersion().toString()); + addField(composite, ProvUIMessages.IUGeneralInfoPropertyPage_ProviderLabel, iu.getProperty(IInstallableUnit.PROP_PROVIDER, null)); + addField(composite, ProvUIMessages.IUGeneralInfoPropertyPage_ContactLabel, iu.getProperty(IInstallableUnit.PROP_CONTACT, null)); + + } + + private void createDescriptionSection(Composite parent, IInstallableUnit iu) { + // Get the iu description in the default locale + String description = iu.getProperty(IInstallableUnit.PROP_DESCRIPTION, null); + if (description != null && description.length() > 0) { + Group group = new Group(parent, SWT.NONE); + group.setText(ProvUIMessages.IUGeneralInfoPropertyPage_DescriptionLabel); + group.setLayout(new GridLayout()); + group.setLayoutData(new GridData(GridData.FILL_BOTH)); + + Text text = new Text(group, SWT.MULTI | SWT.WRAP | SWT.READ_ONLY | SWT.V_SCROLL); + GridData gd = new GridData(SWT.FILL, SWT.FILL, true, true); + gd.widthHint = computeWidthLimit(text, 80); + gd.heightHint = 200; + text.setEditable(false); + text.setText(description); + text.setLayoutData(gd); + } + + } + + private void createDocumentationSection(Composite parent, IInstallableUnit iu) { + String docURL = iu.getProperty(IInstallableUnit.PROP_DOC_URL); + if (docURL != null && docURL.length() > 0) { + final URL url; + try { + url = new URL(docURL); + } catch (MalformedURLException e) { + return; + } + String filename = (url != null) ? url.getFile() : null; + if (filename != null && (filename.endsWith(".htm") || filename.endsWith(".html"))) { //$NON-NLS-1$ //$NON-NLS-2$ + // create some space + new Label(parent, SWT.NONE); + // Now create a link to the documentation + Label label = new Label(parent, SWT.NONE); + label.setText(ProvUIMessages.IUGeneralInfoPropertyPage_DocumentationLink); + Link link = new Link(parent, SWT.LEFT | SWT.WRAP); + link.setText(NLS.bind("{0}", url.toExternalForm())); //$NON-NLS-1$ + GridData gd = new GridData(GridData.FILL_HORIZONTAL | GridData.VERTICAL_ALIGN_BEGINNING); + gd.widthHint = computeWidthLimit(link, 80); + link.setLayoutData(gd); + link.addSelectionListener(SelectionListener.widgetSelectedAdapter(e -> showURL(url))); + } + } + } + + private void addField(Composite parent, String property, String value) { + if (value != null && value.length() > 0) { + Label label = new Label(parent, SWT.NONE); + label.setText(property); + + Text text = new Text(parent, SWT.WRAP | SWT.READ_ONLY); + text.setText(value); + // Needed to get the right color on the Mac. + // See https://bugs.eclipse.org/bugs/show_bug.cgi?id=258112 + text.setBackground(text.getDisplay().getSystemColor(SWT.COLOR_WIDGET_BACKGROUND)); + GridData gd = new GridData(SWT.FILL, SWT.FILL, true, true); + text.setLayoutData(gd); + } + } +} diff --git a/tycho-its/projects/api-tools/missing-bin/org.eclipse.equinox.p2.ui/src/org/eclipse/equinox/internal/p2/ui/dialogs/IULicensePropertyPage.java b/tycho-its/projects/api-tools/missing-bin/org.eclipse.equinox.p2.ui/src/org/eclipse/equinox/internal/p2/ui/dialogs/IULicensePropertyPage.java new file mode 100644 index 0000000000..a5a69935a6 --- /dev/null +++ b/tycho-its/projects/api-tools/missing-bin/org.eclipse.equinox.p2.ui/src/org/eclipse/equinox/internal/p2/ui/dialogs/IULicensePropertyPage.java @@ -0,0 +1,83 @@ +/******************************************************************************* + * Copyright (c) 2007, 2018 IBM Corporation and others. + * + * This program and the accompanying materials + * are made available under the terms of the Eclipse Public License 2.0 + * which accompanies this distribution, and is available at + * https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + * + * Contributors: + * IBM Corporation - initial API and implementation + *******************************************************************************/ +package org.eclipse.equinox.internal.p2.ui.dialogs; + +import java.util.Iterator; +import org.eclipse.core.runtime.URIUtil; +import org.eclipse.equinox.internal.p2.ui.ProvUIMessages; +import org.eclipse.equinox.p2.metadata.IInstallableUnit; +import org.eclipse.equinox.p2.metadata.ILicense; +import org.eclipse.osgi.util.NLS; +import org.eclipse.swt.SWT; +import org.eclipse.swt.events.SelectionListener; +import org.eclipse.swt.layout.GridData; +import org.eclipse.swt.layout.GridLayout; +import org.eclipse.swt.widgets.*; + +/** + * PropertyPage that shows an IU's license + * + * @since 3.4 + */ +public class IULicensePropertyPage extends IUPropertyPage { + + @Override + protected Control createIUPage(Composite parent, IInstallableUnit iu) { + // Get the license in the default locale + Iterator licenses = iu.getLicenses(null).iterator(); + final ILicense license = licenses.hasNext() ? licenses.next() : null; + //FIXME + if (license != null && license.getBody().length() > 0) { + Composite composite = new Composite(parent, SWT.NONE); + GridLayout layout = new GridLayout(); + layout.marginWidth = 0; + layout.marginHeight = 0; + composite.setLayout(layout); + + Text text = new Text(composite, SWT.MULTI | SWT.V_SCROLL | SWT.H_SCROLL | SWT.BORDER | SWT.WRAP); + GridData gd = new GridData(SWT.FILL, SWT.FILL, true, true); + gd.widthHint = computeWidthLimit(text, 80); + gd.heightHint = computeHeightLimit(text, 20); + text.setLayoutData(gd); + text.setText(license.getBody()); + text.setEditable(false); + + // If an URL was specified, provide a link to it + String filename = (license.getLocation() != null) ? license.getLocation().getPath() : null; + if (filename != null && (filename.endsWith(".htm") || filename.endsWith(".html"))) { //$NON-NLS-1$ //$NON-NLS-2$ + Label label = new Label(composite, SWT.NONE); + label.setText(ProvUIMessages.IULicensePropertyPage_ViewLicenseLabel); + // Create a link to the license URL + Link link = new Link(composite, SWT.LEFT | SWT.WRAP); + link.setText(NLS.bind("{0}", URIUtil.toUnencodedString(license.getLocation()))); //$NON-NLS-1$ + gd = new GridData(GridData.FILL_HORIZONTAL | GridData.VERTICAL_ALIGN_BEGINNING); + gd.widthHint = computeWidthLimit(link, 80); + link.setLayoutData(gd); + link.addSelectionListener(SelectionListener.widgetSelectedAdapter(e -> { + try { + showURL(license.getLocation().toURL()); + } catch (Exception e1) { + //can't browse invalid location + } + })); + } + + return composite; + } + Label label = new Label(parent, SWT.NULL); + label.setText(ProvUIMessages.IULicensePropertyPage_NoLicense); + return label; + + } +} diff --git a/tycho-its/projects/api-tools/missing-bin/org.eclipse.equinox.p2.ui/src/org/eclipse/equinox/internal/p2/ui/dialogs/IUPropertyPage.java b/tycho-its/projects/api-tools/missing-bin/org.eclipse.equinox.p2.ui/src/org/eclipse/equinox/internal/p2/ui/dialogs/IUPropertyPage.java new file mode 100644 index 0000000000..9802086600 --- /dev/null +++ b/tycho-its/projects/api-tools/missing-bin/org.eclipse.equinox.p2.ui/src/org/eclipse/equinox/internal/p2/ui/dialogs/IUPropertyPage.java @@ -0,0 +1,81 @@ +/******************************************************************************* + * Copyright (c) 2007, 2010 IBM Corporation and others. + * + * This program and the accompanying materials + * are made available under the terms of the Eclipse Public License 2.0 + * which accompanies this distribution, and is available at + * https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + * + * Contributors: + * IBM Corporation - initial API and implementation + *******************************************************************************/ +package org.eclipse.equinox.internal.p2.ui.dialogs; + +import java.net.URL; +import org.eclipse.equinox.internal.p2.ui.ProvUI; +import org.eclipse.equinox.internal.p2.ui.ProvUIMessages; +import org.eclipse.equinox.p2.metadata.IInstallableUnit; +import org.eclipse.jface.dialogs.Dialog; +import org.eclipse.swt.SWT; +import org.eclipse.swt.graphics.FontMetrics; +import org.eclipse.swt.graphics.GC; +import org.eclipse.swt.widgets.*; +import org.eclipse.ui.PartInitException; +import org.eclipse.ui.PlatformUI; +import org.eclipse.ui.browser.IWebBrowser; +import org.eclipse.ui.browser.IWorkbenchBrowserSupport; +import org.eclipse.ui.dialogs.PropertyPage; +import org.eclipse.ui.statushandlers.StatusManager; + +/** + * PropertyPage that shows an IU's properties + * + * @since 3.4 + */ +public abstract class IUPropertyPage extends PropertyPage { + + @Override + protected Control createContents(Composite parent) { + noDefaultAndApplyButton(); + IInstallableUnit iu = ProvUI.getAdapter(getElement(), IInstallableUnit.class); + Control control; + if (iu == null) { + Label label = new Label(parent, SWT.DEFAULT); + label.setText(ProvUIMessages.IUPropertyPage_NoIUSelected); + control = label; + } + control = createIUPage(parent, iu); + Dialog.applyDialogFont(parent); + return control; + } + + protected int computeWidthLimit(Control control, int nchars) { + GC gc = new GC(control); + gc.setFont(control.getFont()); + FontMetrics fontMetrics = gc.getFontMetrics(); + gc.dispose(); + return Dialog.convertWidthInCharsToPixels(fontMetrics, nchars); + } + + protected int computeHeightLimit(Control control, int nchars) { + GC gc = new GC(control); + gc.setFont(control.getFont()); + FontMetrics fontMetrics = gc.getFontMetrics(); + gc.dispose(); + return Dialog.convertHeightInCharsToPixels(fontMetrics, nchars); + } + + protected abstract Control createIUPage(Composite parent, IInstallableUnit iu); + + protected void showURL(URL url) { + IWorkbenchBrowserSupport support = PlatformUI.getWorkbench().getBrowserSupport(); + try { + IWebBrowser browser = support.getExternalBrowser(); + browser.openURL(url); + } catch (PartInitException e) { + ProvUI.handleException(e, ProvUIMessages.IUGeneralInfoPropertyPage_CouldNotOpenBrowser, StatusManager.LOG | StatusManager.BLOCK); + } + } +} diff --git a/tycho-its/projects/api-tools/missing-bin/org.eclipse.equinox.p2.ui/src/org/eclipse/equinox/internal/p2/ui/dialogs/IViewMenuProvider.java b/tycho-its/projects/api-tools/missing-bin/org.eclipse.equinox.p2.ui/src/org/eclipse/equinox/internal/p2/ui/dialogs/IViewMenuProvider.java new file mode 100644 index 0000000000..62b72b14f7 --- /dev/null +++ b/tycho-its/projects/api-tools/missing-bin/org.eclipse.equinox.p2.ui/src/org/eclipse/equinox/internal/p2/ui/dialogs/IViewMenuProvider.java @@ -0,0 +1,27 @@ +/******************************************************************************* + * Copyright (c) 2008 IBM Corporation and others. + * + * This program and the accompanying materials + * are made available under the terms of the Eclipse Public License 2.0 + * which accompanies this distribution, and is available at + * https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + * + * Contributors: + * IBM Corporation - initial API and implementation + ******************************************************************************/ + +package org.eclipse.equinox.internal.p2.ui.dialogs; + +import org.eclipse.jface.action.IMenuManager; + +/** + * + * IViewMenuProvider is used to fill a view menu in dialog groups that support them. + * @since 3.4 + * + */ +public interface IViewMenuProvider { + public void fillViewMenu(IMenuManager viewMenu); +} diff --git a/tycho-its/projects/api-tools/missing-bin/org.eclipse.equinox.p2.ui/src/org/eclipse/equinox/internal/p2/ui/dialogs/InstallWizard.java b/tycho-its/projects/api-tools/missing-bin/org.eclipse.equinox.p2.ui/src/org/eclipse/equinox/internal/p2/ui/dialogs/InstallWizard.java new file mode 100644 index 0000000000..1275b3ecd3 --- /dev/null +++ b/tycho-its/projects/api-tools/missing-bin/org.eclipse.equinox.p2.ui/src/org/eclipse/equinox/internal/p2/ui/dialogs/InstallWizard.java @@ -0,0 +1,253 @@ +/******************************************************************************* + * Copyright (c) 2007, 2018 IBM Corporation and others. + * + * This program and the accompanying materials + * are made available under the terms of the Eclipse Public License 2.0 + * which accompanies this distribution, and is available at + * https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + * + * Contributors: + * IBM Corporation - initial API and implementation + * Sonatype, Inc. - ongoing development + * Red Hat, Inc. - support for remediation page + * Lars Vogel - Bug 479145 + *******************************************************************************/ +package org.eclipse.equinox.internal.p2.ui.dialogs; + +import java.util.ArrayList; +import java.util.Collection; +import org.eclipse.core.runtime.IStatus; +import org.eclipse.equinox.internal.p2.ui.*; +import org.eclipse.equinox.internal.p2.ui.model.*; +import org.eclipse.equinox.p2.engine.ProvisioningContext; +import org.eclipse.equinox.p2.metadata.IInstallableUnit; +import org.eclipse.equinox.p2.operations.*; +import org.eclipse.equinox.p2.ui.LoadMetadataRepositoryJob; +import org.eclipse.equinox.p2.ui.ProvisioningUI; +import org.eclipse.jface.dialogs.IDialogConstants; +import org.eclipse.jface.dialogs.MessageDialog; +import org.eclipse.jface.wizard.IWizardPage; +import org.eclipse.jface.wizard.WizardPage; +import org.eclipse.swt.custom.BusyIndicator; +import org.eclipse.swt.widgets.Shell; +import org.eclipse.ui.PlatformUI; + +/** + * An install wizard that allows the users to browse all of the repositories and + * search/select for items to install. + * + * @since 3.6 + */ +public class InstallWizard extends WizardWithLicenses { + + SelectableIUsPage errorReportingPage; + boolean ignoreSelectionChanges = false; + IStatus installHandlerStatus; + + public InstallWizard(ProvisioningUI ui, InstallOperation operation, Collection initialSelections, + LoadMetadataRepositoryJob preloadJob) { + super(ui, operation, initialSelections == null ? null : initialSelections.toArray(), preloadJob); + setWindowTitle(ProvUIMessages.InstallIUOperationLabel); + setDefaultPageImageDescriptor(ProvUIImages.getImageDescriptor(ProvUIImages.WIZARD_BANNER_INSTALL)); + } + + @Override + protected ResolutionResultsWizardPage createResolutionPage() { + return new InstallWizardPage(ui, this, root, operation); + } + + @Override + protected ISelectableIUsPage createMainPage(IUElementListRoot input, Object[] selections) { + mainPage = new AvailableIUsPage(ui, this); + if (selections != null && selections.length > 0) + mainPage.setCheckedElements(selections); + return mainPage; + + } + + @Override + protected void initializeResolutionModelElements(Object[] selectedElements) { + if (selectedElements == null) + return; + root = new IUElementListRoot(ui); + if (operation instanceof RemediationOperation) { + AvailableIUElement[] elements = ElementUtils + .requestToElement(((RemediationOperation) operation).getCurrentRemedy(), true); + root.setChildren(elements); + planSelections = elements; + } else { + ArrayList list = new ArrayList<>(selectedElements.length); + ArrayList selections = new ArrayList<>(selectedElements.length); + for (Object selectedElement : selectedElements) { + IInstallableUnit iu = ElementUtils.getIU(selectedElement); + if (iu != null) { + AvailableIUElement element = new AvailableIUElement(root, iu, getProfileId(), + shouldShowProvisioningPlanChildren()); + list.add(element); + selections.add(element); + } + } + root.setChildren(list.toArray()); + planSelections = selections.toArray(); + } + } + + /* + * Overridden to dynamically determine which page to get selections from. + */ + @Override + protected Object[] getOperationSelections() { + return getOperationSelectionsPage().getCheckedIUElements(); + } + + /* + * Get the page that is driving operation selections. This is usually the main + * page, but it could be error page if there was a resolution error and the user + * decides to change selections and try again without going back. + */ + protected ISelectableIUsPage getOperationSelectionsPage() { + IWizardPage page = getContainer().getCurrentPage(); + if (page instanceof ISelectableIUsPage) + return (ISelectableIUsPage) page; + // return the main page if we weren't on main or error page + return mainPage; + } + + @Override + protected ProvisioningContext getProvisioningContext() { + return ((AvailableIUsPage) mainPage).getProvisioningContext(); + } + + @Override + protected IResolutionErrorReportingPage createErrorReportingPage() { + if (root == null) + errorReportingPage = new SelectableIUsPage(ui, this, null, null); + else + errorReportingPage = new SelectableIUsPage(ui, this, root, root.getChildren(root)); + errorReportingPage.setTitle(ProvUIMessages.InstallWizardPage_Title); + errorReportingPage.setDescription(ProvUIMessages.PreselectedIUInstallWizard_Description); + errorReportingPage.updateStatus(root, operation); + return errorReportingPage; + } + + @Override + protected RemediationPage createRemediationPage() { + remediationPage = new RemediationPage(ui, this, root, operation); + return remediationPage; + } + + @Override + protected ProfileChangeOperation getProfileChangeOperation(Object[] elements) { + InstallOperation op = new InstallOperation(ui.getSession(), ElementUtils.elementsToIUs(elements)); + op.setProfileId(getProfileId()); + // op.setRootMarkerKey(getRootMarkerKey()); + return op; + } + + @Override + protected boolean shouldUpdateErrorPageModelOnPlanChange() { + // We don't want the root of the error page to change unless we are on the + // main page. For example, if we are on the error page, change checkmarks, and + // resolve again with an error, we wouldn't want the root items to change in the + // error page. + return getContainer().getCurrentPage() == mainPage && super.shouldUpdateErrorPageModelOnPlanChange(); + } + + @Override + protected void planChanged() { + super.planChanged(); + synchSelections(getOperationSelectionsPage()); + } + + /* + * overridden to ensure that the main page selections stay in synch with changes + * to the error page. + */ + @Override + public void operationSelectionsChanged(ISelectableIUsPage page) { + if (ignoreSelectionChanges) + return; + super.operationSelectionsChanged(page); + // If we are on the error page, resolution has failed. + // Our ability to move on depends on whether the selections have changed. + // If they are the same selections, then we are not complete until selections + // are changed. + if (getOperationSelectionsPage() == errorPage) + ((WizardPage) errorPage).setPageComplete( + pageSelectionsHaveChanged(errorPage) && errorPage.getCheckedIUElements().length > 0); + synchSelections(page); + } + + private void synchSelections(ISelectableIUsPage triggeringPage) { + // We don't want our programmatic changes to cause all this to happen again + ignoreSelectionChanges = true; + try { + if (triggeringPage == errorReportingPage) { + mainPage.setCheckedElements(triggeringPage.getCheckedIUElements()); + } else if (triggeringPage == mainPage) { + errorReportingPage.setCheckedElements(triggeringPage.getCheckedIUElements()); + } + } finally { + ignoreSelectionChanges = false; + } + } + + /* + * Overridden to check whether there are UpdateManager install handlers in the + * item to be installed. Operations don't know about this compatibility issue. + */ + @Override + public IStatus getCurrentStatus() { + IStatus originalStatus = super.getCurrentStatus(); + int sev = originalStatus.getSeverity(); + // Use the previously computed status if the user cancelled or if we were + // already in error. + // If we don't have an operation or a plan, we can't check this condition + // either, so just + // use the normal status. + if (sev == IStatus.CANCEL || sev == IStatus.ERROR || operation == null + || operation.getProvisioningPlan() == null) { + return originalStatus; + } + // Does the plan require install handler support? + installHandlerStatus = UpdateManagerCompatibility.getInstallHandlerStatus(operation.getProvisioningPlan()); + if (!installHandlerStatus.isOK()) { + // Set the status into the wizard. This ensures future calls to this method + // won't + // repeat the work (and prompting). + couldNotResolveStatus = installHandlerStatus; + + // Is the update manager installer present? If so, offer to open it. + // In either case, the failure will be reported in this wizard. + if (ProvUI.isUpdateManagerInstallerPresent()) { + PlatformUI.getWorkbench().getDisplay().asyncExec(() -> { + Shell shell = ProvUI.getDefaultParentShell(); + MessageDialog dialog = new MessageDialog(shell, ProvUIMessages.Policy_RequiresUpdateManagerTitle, + null, ProvUIMessages.Policy_RequiresUpdateManagerMessage, MessageDialog.WARNING, + new String[] { ProvUIMessages.LaunchUpdateManagerButton, IDialogConstants.CANCEL_LABEL }, + 0); + if (dialog.open() == 0) + BusyIndicator.showWhile(shell.getDisplay(), UpdateManagerCompatibility::openInstaller); + }); + } + return installHandlerStatus; + } + return originalStatus; + } + + /* + * When we've found an install handler, that status trumps anything that the + * operation might have determined. We are relying here on the knowledge that + * the wizard's couldNotResolveStatus is reset on every new resolution, so that + * status only holds the installHandler status when it is the current status. + * The installHandlerStatus must be non-OK for it to matter at all. + * + */ + @Override + public boolean statusOverridesOperation() { + return super.statusOverridesOperation() || (installHandlerStatus != null && !installHandlerStatus.isOK() + && couldNotResolveStatus == installHandlerStatus); + } +} diff --git a/tycho-its/projects/api-tools/missing-bin/org.eclipse.equinox.p2.ui/src/org/eclipse/equinox/internal/p2/ui/dialogs/InstallWizardPage.java b/tycho-its/projects/api-tools/missing-bin/org.eclipse.equinox.p2.ui/src/org/eclipse/equinox/internal/p2/ui/dialogs/InstallWizardPage.java new file mode 100644 index 0000000000..a1d93bb47a --- /dev/null +++ b/tycho-its/projects/api-tools/missing-bin/org.eclipse.equinox.p2.ui/src/org/eclipse/equinox/internal/p2/ui/dialogs/InstallWizardPage.java @@ -0,0 +1,40 @@ +/******************************************************************************* + * Copyright (c) 2007, 2013 IBM Corporation and others. + * + * This program and the accompanying materials + * are made available under the terms of the Eclipse Public License 2.0 + * which accompanies this distribution, and is available at + * https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + * + * Contributors: + * IBM Corporation - initial API and implementation + * Red Hat, Inc. - support for remediation page + *******************************************************************************/ +package org.eclipse.equinox.internal.p2.ui.dialogs; + +import org.eclipse.equinox.internal.p2.ui.ProvUIMessages; +import org.eclipse.equinox.internal.p2.ui.model.IUElementListRoot; +import org.eclipse.equinox.p2.operations.ProfileChangeOperation; +import org.eclipse.equinox.p2.ui.ProvisioningUI; + +public class InstallWizardPage extends SizeComputingWizardPage { + + public InstallWizardPage(ProvisioningUI ui, ProvisioningOperationWizard wizard, IUElementListRoot root, ProfileChangeOperation operation) { + super(ui, wizard, root, operation); + setTitle(ProvUIMessages.InstallWizardPage_Title); + setDescription(ProvUIMessages.InstallWizardPage_NoCheckboxDescription); + } + + @Override + protected String getOperationLabel() { + return ProvUIMessages.InstallIUOperationLabel; + } + + @Override + protected String getOperationTaskName() { + return ProvUIMessages.InstallIUOperationTask; + } + +} diff --git a/tycho-its/projects/api-tools/missing-bin/org.eclipse.equinox.p2.ui/src/org/eclipse/equinox/internal/p2/ui/dialogs/InstalledIUGroup.java b/tycho-its/projects/api-tools/missing-bin/org.eclipse.equinox.p2.ui/src/org/eclipse/equinox/internal/p2/ui/dialogs/InstalledIUGroup.java new file mode 100644 index 0000000000..291e66aed0 --- /dev/null +++ b/tycho-its/projects/api-tools/missing-bin/org.eclipse.equinox.p2.ui/src/org/eclipse/equinox/internal/p2/ui/dialogs/InstalledIUGroup.java @@ -0,0 +1,204 @@ +/******************************************************************************* + * Copyright (c) 2007, 2018 IBM Corporation and others. + * + * This program and the accompanying materials + * are made available under the terms of the Eclipse Public License 2.0 + * which accompanies this distribution, and is available at + * https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + * + * Contributors: + * IBM Corporation - initial API and implementation + *******************************************************************************/ +package org.eclipse.equinox.internal.p2.ui.dialogs; + +import java.util.*; +import org.eclipse.e4.ui.dialogs.filteredtree.FilteredTree; +import org.eclipse.e4.ui.dialogs.filteredtree.PatternFilter; +import org.eclipse.equinox.internal.p2.ui.ProvUI; +import org.eclipse.equinox.internal.p2.ui.ProvUIProvisioningListener; +import org.eclipse.equinox.internal.p2.ui.model.InstalledIUElement; +import org.eclipse.equinox.internal.p2.ui.model.ProfileElement; +import org.eclipse.equinox.internal.p2.ui.viewers.*; +import org.eclipse.equinox.p2.metadata.IInstallableUnit; +import org.eclipse.equinox.p2.ui.ProvisioningUI; +import org.eclipse.jface.viewers.StructuredViewer; +import org.eclipse.jface.viewers.TreeViewer; +import org.eclipse.swt.SWT; +import org.eclipse.swt.graphics.Font; +import org.eclipse.swt.widgets.*; + +/** + * An InstalledIUGroup is a reusable UI component that displays the IU's in a + * given profile. + * + * @since 3.4 + */ +public class InstalledIUGroup extends StructuredIUGroup { + + private String profileId; + + /** + * Create a group that represents the installed IU's. + * + * @param parent the parent composite for the group + * @param font The font to use for calculating pixel sizes. This font is + * not managed by the receiver. + * @param profileId the id of the profile whose content is being shown. + * @param columnConfig the columns to be shown + */ + public InstalledIUGroup(ProvisioningUI ui, final Composite parent, Font font, String profileId, + IUColumnConfig[] columnConfig) { + super(ui, parent, font, columnConfig); + if (profileId == null) + this.profileId = ui.getProfileId(); + else + this.profileId = profileId; + createGroupComposite(parent); + } + + @Override + protected StructuredViewer createViewer(Composite parent) { + // Table of installed IU's + FilteredTree filteredTree = new FilteredTree(parent, + SWT.MULTI | SWT.FULL_SELECTION | SWT.H_SCROLL | SWT.V_SCROLL | SWT.BORDER, new PatternFilter()); + filteredTree.getFilterControl().setFocus(); // Steal focus, consistent with + // org.eclipse.ui.internal.about.AboutPluginsPage + TreeViewer installedIUViewer = filteredTree.getViewer(); + + // Filters and sorters before establishing content, so we don't refresh + // unnecessarily. + IUComparator comparator = new IUComparator(IUComparator.IU_NAME); + comparator.useColumnConfig(getColumnConfig()); + installedIUViewer.setComparator(comparator); + installedIUViewer.setComparer(new ProvElementComparer()); + + // Now the content. + // Specialize the content provider for performance optimization. + // See https://bugs.eclipse.org/bugs/show_bug.cgi?id=550265 + installedIUViewer.setContentProvider(new DeferredQueryContentProvider() { + /** + * A cache for mapping each element to its children. + */ + private final Map elementChildren = new HashMap<>(); + + /** + * A cache for mapping each IU to that IU's children. + */ + private final Map> iuChildren = new HashMap<>(); + + @Override + public boolean hasChildren(Object element) { + // Delegate to getChildren so that all children are always cached. + return getChildren(element).length != 0; + } + + @Override + public Object[] getChildren(Object element) { + Object[] objects = elementChildren.get(element); + if (objects == null) { + if (element instanceof InstalledIUElement) { + // Special case handling. + InstalledIUElement installedIUElement = (InstalledIUElement) element; + if (!installedIUElement.shouldShowChildren()) { + // If the element shouldn't show children because that would create a cycle, + // don't show any. + objects = new Object[0]; + elementChildren.put(element, objects); + return objects; + } + + // If the children for this IU have already been computed. + String localProfileId = installedIUElement.getProfileId(); + IInstallableUnit iu = installedIUElement.getIU(); + Set children = iuChildren.get(iu); + if (children != null) { + // Bypass the expensive query computation because we already know the IU + // children from a previous expensive computation. + Set elementIUChildren = new LinkedHashSet<>(); + for (IInstallableUnit childIU : children) { + elementIUChildren.add(new InstalledIUElement(element, localProfileId, childIU)); + } + + objects = elementIUChildren.toArray(); + elementChildren.put(element, objects); + return objects; + } + } + + // Get the children the normal ways and cache them. + objects = super.getChildren(element); + elementChildren.put(element, objects); + + // If there are children and this is an InstalledIUElement, cache the mapping + // from the IU to the child IUs for reuse above. + if (objects.length != 0 && element instanceof InstalledIUElement) { + InstalledIUElement installedIUElement = (InstalledIUElement) element; + IInstallableUnit iu = installedIUElement.getIU(); + Set children = new LinkedHashSet<>(); + for (Object object : objects) { + if (object instanceof InstalledIUElement) { + InstalledIUElement childInstalledIUElement = (InstalledIUElement) object; + IInstallableUnit childIU = childInstalledIUElement.getIU(); + children.add(childIU); + } else { + // In case all the children are not also InstalledIUElement, which shouldn't + // happen. + return objects; + } + } + iuChildren.put(iu, children); + } + } + return objects; + } + }); + + // Now the visuals, columns before labels. + setTreeColumns(installedIUViewer.getTree()); + installedIUViewer.setLabelProvider(new IUDetailsLabelProvider(null, getColumnConfig(), null)); + + // Input last. + installedIUViewer.setInput(getInput()); + + final StructuredViewerProvisioningListener listener = new StructuredViewerProvisioningListener( + getClass().getName(), installedIUViewer, + ProvUIProvisioningListener.PROV_EVENT_IU | ProvUIProvisioningListener.PROV_EVENT_PROFILE, + getProvisioningUI().getOperationRunner()); + ProvUI.getProvisioningEventBus(getProvisioningUI().getSession()).addListener(listener); + installedIUViewer.getControl().addDisposeListener( + e -> ProvUI.getProvisioningEventBus(getProvisioningUI().getSession()).removeListener(listener)); + return installedIUViewer; + } + + private void setTreeColumns(Tree tree) { + IUColumnConfig[] columns = getColumnConfig(); + tree.setHeaderVisible(true); + + for (int i = 0; i < columns.length; i++) { + TreeColumn tc = new TreeColumn(tree, SWT.NONE, i); + tc.setResizable(true); + tc.setText(columns[i].getColumnTitle()); + tc.setWidth(columns[i].getWidthInPixels(tree)); + } + } + + Object getInput() { + ProfileElement element = new ProfileElement(null, profileId); + return element; + } + + /** + * Get the viewer used to represent the installed IU's + */ + @Override + public StructuredViewer getStructuredViewer() { + return super.getStructuredViewer(); + } + + @Override + public Control getDefaultFocusControl() { + return super.getDefaultFocusControl(); + } +} diff --git a/tycho-its/projects/api-tools/missing-bin/org.eclipse.equinox.p2.ui/src/org/eclipse/equinox/internal/p2/ui/dialogs/PGPPublicKeyViewDialog.java b/tycho-its/projects/api-tools/missing-bin/org.eclipse.equinox.p2.ui/src/org/eclipse/equinox/internal/p2/ui/dialogs/PGPPublicKeyViewDialog.java new file mode 100644 index 0000000000..17a8e0a3df --- /dev/null +++ b/tycho-its/projects/api-tools/missing-bin/org.eclipse.equinox.p2.ui/src/org/eclipse/equinox/internal/p2/ui/dialogs/PGPPublicKeyViewDialog.java @@ -0,0 +1,251 @@ +/******************************************************************************* + * Copyright (c) 2022 Eclipse contributors and others. + * + * This program and the accompanying materials + * are made available under the terms of the Eclipse Public License 2.0 + * which accompanies this distribution, and is available at + * https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + *******************************************************************************/ +package org.eclipse.equinox.internal.p2.ui.dialogs; + +import java.time.Instant; +import java.time.ZoneOffset; +import java.time.format.DateTimeFormatter; +import java.util.*; +import java.util.List; +import org.bouncycastle.bcpg.*; +import org.bouncycastle.openpgp.PGPPublicKey; +import org.bouncycastle.openpgp.PGPSignature; +import org.eclipse.core.runtime.*; +import org.eclipse.core.runtime.jobs.Job; +import org.eclipse.equinox.internal.p2.ui.ProvUIMessages; +import org.eclipse.equinox.p2.repository.spi.PGPPublicKeyService; +import org.eclipse.jface.dialogs.IDialogConstants; +import org.eclipse.jface.dialogs.TitleAreaDialog; +import org.eclipse.jface.resource.JFaceResources; +import org.eclipse.jface.viewers.StyledString; +import org.eclipse.swt.SWT; +import org.eclipse.swt.custom.StyledText; +import org.eclipse.swt.graphics.*; +import org.eclipse.swt.layout.GridData; +import org.eclipse.swt.widgets.*; + +/** + * Presents information about a key in a format similar to what key servers + * display. + * + * @since 1.2.4 + */ +public class PGPPublicKeyViewDialog extends TitleAreaDialog { + + private static final DateTimeFormatter DATE_FORMAT = DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH:mm:ss'Z'") //$NON-NLS-1$ + .withZone(ZoneOffset.UTC); + + final private PGPPublicKey originalKey; + + final private PGPPublicKeyService keyService; + + private StyledText styledText; + + public PGPPublicKeyViewDialog(Shell parentShell, PGPPublicKey key, PGPPublicKeyService keyService) { + super(parentShell); + this.originalKey = key; + this.keyService = keyService; + } + + @Override + protected void configureShell(Shell newShell) { + super.configureShell(newShell); + newShell.setText(ProvUIMessages.PGPPublicKeyViewDialog_Title); + if (keyService != null) { + computeVerifiedCertifications(newShell); + } + } + + @Override + protected void setShellStyle(int newShellStyle) { + super.setShellStyle(newShellStyle | SWT.RESIZE | SWT.DIALOG_TRIM); + } + + @Override + protected Control createDialogArea(Composite parent) { + Composite composite = (Composite) super.createDialogArea(parent); + GridData data = new GridData(SWT.FILL, SWT.FILL, true, true); + composite.setLayoutData(data); + + styledText = new StyledText(composite, SWT.READ_ONLY | SWT.BORDER | SWT.V_SCROLL | SWT.H_SCROLL); + styledText.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true)); + + // Create a sightly smaller text (mono-space) font. + FontData[] fontData = JFaceResources.getTextFont().getFontData(); + for (FontData fontDataElement : fontData) { + fontDataElement.setHeight(fontDataElement.getHeight() - 1); + } + Font font = new Font(styledText.getDisplay(), fontData); + styledText.setFont(font); + styledText.addDisposeListener(e -> font.dispose()); + + GC gc = new GC(styledText); + gc.setFont(font); + data.widthHint = convertWidthInCharsToPixels(gc.getFontMetrics(), 110); + gc.dispose(); + + update(originalKey, Set.of()); + return composite; + } + + @Override + protected void createButtonsForButtonBar(Composite parent) { + createButton(parent, IDialogConstants.CANCEL_ID, IDialogConstants.CLOSE_LABEL, true).setFocus(); + } + + @SuppressWarnings("nls") + protected void update(PGPPublicKey key, Set verifiedCertifications) { + StyledString content = new StyledString(); + String fingerprint = PGPPublicKeyService.toHexFingerprint(key); + + PublicKeyPacket publicKeyPacket = key.getPublicKeyPacket(); + publicKeyPacket.getAlgorithm(); + content.append(" "); + content.append(publicKeyPacket instanceof PublicSubkeyPacket ? "sub" : "pub", StyledString.QUALIFIER_STYLER); + content.append(" "); + + int algorithm = publicKeyPacket.getAlgorithm(); + switch (algorithm) { + case PublicKeyAlgorithmTags.RSA_GENERAL: + case PublicKeyAlgorithmTags.RSA_ENCRYPT: + case PublicKeyAlgorithmTags.RSA_SIGN: { + content.append("rsa"); + break; + } + case PublicKeyAlgorithmTags.DSA: { + content.append("dsa"); + break; + } + case PublicKeyAlgorithmTags.ELGAMAL_ENCRYPT: + case PublicKeyAlgorithmTags.ELGAMAL_GENERAL: { + content.append("elgamal"); + break; + } + default: { + content.append("["); + content.append(Integer.toString(algorithm)); + content.append("]"); + break; + } + + } + int bitStrength = key.getBitStrength(); + content.append(Integer.toString(bitStrength)); + content.append("/"); + content.append(fingerprint); + + content.append(" "); + content.append(DATE_FORMAT.format(key.getCreationTime().toInstant())); + + content.append(" "); + content.append("\n"); + + List users = new ArrayList<>(); + key.getUserIDs().forEachRemaining(users::add); + if (!users.isEmpty()) { + for (String user : users) { + content.append(" "); + content.append("uid", StyledString.QUALIFIER_STYLER); + content.append(" "); + content.append(user, StyledString.COUNTER_STYLER); + content.append("\n"); + } + } + + Long subKeyOf = null; + + for (Iterator signatures = key.getSignatures(); signatures.hasNext();) { + PGPSignature signature = signatures.next(); + long keyID = signature.getKeyID(); + + if (signature.getSignatureType() == PGPSignature.SUBKEY_BINDING) { + subKeyOf = keyID; + } + + content.append(" "); + content.append("sig", StyledString.QUALIFIER_STYLER); + content.append(" "); + content.append(PGPPublicKeyService.toHex(keyID)); + content.append(" "); + Date creationTime = signature.getCreationTime(); + String formattedCreationTime = DATE_FORMAT.format(creationTime.toInstant()); + content.append(formattedCreationTime); + long signatureExpirationTime = signature.getHashedSubPackets().getSignatureExpirationTime(); + content.append(" "); + content.append(signatureExpirationTime == 0 ? formattedCreationTime.replaceAll(".", "_") + : DATE_FORMAT + .format(Instant.ofEpochMilli(creationTime.getTime() + 1000 * signatureExpirationTime))); + + content.append(" "); + Optional resolvedKey = verifiedCertifications.stream().filter(k -> k.getKeyID() == keyID) + .findFirst(); + + long keyExpirationTime = signature.getHashedSubPackets().getKeyExpirationTime(); + content.append(keyExpirationTime == 0 || resolvedKey == null || !resolvedKey.isPresent() + ? formattedCreationTime.replaceAll(".", "_") + : DATE_FORMAT.format(Instant + .ofEpochMilli(resolvedKey.get().getCreationTime().getTime() + 1000 * keyExpirationTime))); + + if (resolvedKey != null && resolvedKey.isPresent()) { + content.append(" "); + content.append(getLabel(resolvedKey.get()), StyledString.COUNTER_STYLER); + } + + content.append("\n"); + } + + styledText.setText(content.getString()); + styledText.setStyleRanges(content.getStyleRanges()); + + List title = new ArrayList<>(); + if (subKeyOf != null) { + long keyID = subKeyOf; + verifiedCertifications.stream().filter(k -> k.getKeyID() == keyID).findFirst() + .ifPresentOrElse(k -> title.add(getLabel(k)), () -> title.add(PGPPublicKeyService.toHex(keyID))); + } + title.add((subKeyOf == null ? "" : "sub ") + (users.isEmpty() ? fingerprint : users.get(0))); + + setTitle(String.join("\n", title)); + } + + private String getLabel(PGPPublicKey key) { + Iterator userIDs = key.getUserIDs(); + if (userIDs.hasNext()) { + return userIDs.next(); + + } + return PGPPublicKeyService.toHexFingerprint(key); + } + + private void computeVerifiedCertifications(Shell shell) { + Display display = shell.getDisplay(); + new Job(PGPPublicKeyViewDialog.class.getName()) { + { + setSystem(true); + setPriority(Job.SHORT); + } + + @Override + protected IStatus run(IProgressMonitor monitor) { + synchronized (keyService) { + PGPPublicKey enhancedKey = keyService.addKey(originalKey); + Set verifiedCertifications = keyService.getVerifiedCertifications(originalKey); + display.asyncExec(() -> { + if (!shell.isDisposed()) { + update(enhancedKey, verifiedCertifications); + } + }); + } + return Status.OK_STATUS; + } + }.schedule(); + } +} diff --git a/tycho-its/projects/api-tools/missing-bin/org.eclipse.equinox.p2.ui/src/org/eclipse/equinox/internal/p2/ui/dialogs/PreselectedIUInstallWizard.java b/tycho-its/projects/api-tools/missing-bin/org.eclipse.equinox.p2.ui/src/org/eclipse/equinox/internal/p2/ui/dialogs/PreselectedIUInstallWizard.java new file mode 100644 index 0000000000..0c92f10610 --- /dev/null +++ b/tycho-its/projects/api-tools/missing-bin/org.eclipse.equinox.p2.ui/src/org/eclipse/equinox/internal/p2/ui/dialogs/PreselectedIUInstallWizard.java @@ -0,0 +1,107 @@ +/******************************************************************************* + * Copyright (c) 2009, 2018 IBM Corporation and others. + * + * This program and the accompanying materials + * are made available under the terms of the Eclipse Public License 2.0 + * which accompanies this distribution, and is available at + * https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + * + * Contributors: + * IBM Corporation - initial API and implementation + * Sonatype, Inc. - ongoing development + * Red Hat, Inc. - support for remediation page + *******************************************************************************/ +package org.eclipse.equinox.internal.p2.ui.dialogs; + +import java.util.ArrayList; +import java.util.Collection; +import org.eclipse.core.runtime.Status; +import org.eclipse.equinox.internal.p2.ui.*; +import org.eclipse.equinox.internal.p2.ui.model.*; +import org.eclipse.equinox.p2.metadata.IInstallableUnit; +import org.eclipse.equinox.p2.operations.InstallOperation; +import org.eclipse.equinox.p2.operations.ProfileChangeOperation; +import org.eclipse.equinox.p2.ui.LoadMetadataRepositoryJob; +import org.eclipse.equinox.p2.ui.ProvisioningUI; +import org.eclipse.jface.wizard.IWizardPage; + +/** + * An Install wizard that is invoked when the user has already selected which + * IUs should be installed and does not need to browse the available software. + * + * @since 3.5 + */ +public class PreselectedIUInstallWizard extends WizardWithLicenses { + + QueryableMetadataRepositoryManager manager; + + public PreselectedIUInstallWizard(ProvisioningUI ui, InstallOperation operation, Collection initialSelections, LoadMetadataRepositoryJob job) { + super(ui, operation, initialSelections.toArray(), job); + setWindowTitle(ProvUIMessages.InstallIUOperationLabel); + setDefaultPageImageDescriptor(ProvUIImages.getImageDescriptor(ProvUIImages.WIZARD_BANNER_INSTALL)); + } + + @Override + public IWizardPage getStartingPage() { + if (remediationOperation != null && remediationOperation.getResolutionResult() == Status.OK_STATUS) { + return getNextPage(mainPage); + } + return super.getStartingPage(); + } + + @Override + protected ISelectableIUsPage createMainPage(IUElementListRoot input, Object[] selections) { + mainPage = new SelectableIUsPage(ui, this, input, selections); + mainPage.setTitle(ProvUIMessages.PreselectedIUInstallWizard_Title); + mainPage.setDescription(ProvUIMessages.PreselectedIUInstallWizard_Description); + ((SelectableIUsPage) mainPage).updateStatus(input, operation); + return mainPage; + } + + @Override + protected ResolutionResultsWizardPage createResolutionPage() { + return new InstallWizardPage(ui, this, root, operation); + } + + @Override + protected void initializeResolutionModelElements(Object[] selectedElements) { + root = new IUElementListRoot(ui); + ArrayList list = new ArrayList<>(selectedElements.length); + ArrayList selected = new ArrayList<>(selectedElements.length); + for (Object selectedElement : selectedElements) { + IInstallableUnit iu = ElementUtils.getIU(selectedElement); + if (iu != null) { + AvailableIUElement element = new AvailableIUElement(root, iu, getProfileId(), shouldShowProvisioningPlanChildren()); + list.add(element); + selected.add(element); + } + } + root.setChildren(list.toArray()); + planSelections = selected.toArray(); + if (licensePage != null) { + licensePage.update(ElementUtils.elementsToIUs(planSelections).toArray(new IInstallableUnit[0]), operation); + } + } + + @Override + protected IResolutionErrorReportingPage createErrorReportingPage() { + return (IResolutionErrorReportingPage) mainPage; + } + + @Override + protected ProfileChangeOperation getProfileChangeOperation(Object[] elements) { + InstallOperation op = new InstallOperation(ui.getSession(), ElementUtils.elementsToIUs(elements)); + op.setProfileId(getProfileId()); + // op.setRootMarkerKey(getRootMarkerKey()); + return op; + } + + @Override + protected RemediationPage createRemediationPage() { + remediationPage = new RemediationPage(ui, this, root, operation); + return remediationPage; + } + +} diff --git a/tycho-its/projects/api-tools/missing-bin/org.eclipse.equinox.p2.ui/src/org/eclipse/equinox/internal/p2/ui/dialogs/ProvisioningOperationWizard.java b/tycho-its/projects/api-tools/missing-bin/org.eclipse.equinox.p2.ui/src/org/eclipse/equinox/internal/p2/ui/dialogs/ProvisioningOperationWizard.java new file mode 100644 index 0000000000..4ea759c118 --- /dev/null +++ b/tycho-its/projects/api-tools/missing-bin/org.eclipse.equinox.p2.ui/src/org/eclipse/equinox/internal/p2/ui/dialogs/ProvisioningOperationWizard.java @@ -0,0 +1,515 @@ +/******************************************************************************* + * Copyright (c) 2008, 2018 IBM Corporation and others. + * + * This program and the accompanying materials + * are made available under the terms of the Eclipse Public License 2.0 + * which accompanies this distribution, and is available at + * https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + * + * Contributors: + * IBM Corporation - initial API and implementation + * Sonatype, Inc. - ongoing development + * Red Hat, Inc. - support for remediation page + * Ericsson (AB) - bug 409073 + *******************************************************************************/ +package org.eclipse.equinox.internal.p2.ui.dialogs; + +import java.lang.reflect.InvocationTargetException; +import java.util.HashSet; +import java.util.stream.Stream; +import org.eclipse.core.runtime.*; +import org.eclipse.core.runtime.jobs.*; +import org.eclipse.equinox.internal.p2.ui.*; +import org.eclipse.equinox.internal.p2.ui.model.ElementUtils; +import org.eclipse.equinox.internal.p2.ui.model.IUElementListRoot; +import org.eclipse.equinox.p2.engine.IProvisioningPlan; +import org.eclipse.equinox.p2.engine.ProvisioningContext; +import org.eclipse.equinox.p2.metadata.IInstallableUnit; +import org.eclipse.equinox.p2.operations.ProfileChangeOperation; +import org.eclipse.equinox.p2.operations.RemediationOperation; +import org.eclipse.equinox.p2.ui.*; +import org.eclipse.jface.operation.IRunnableContext; +import org.eclipse.jface.wizard.*; +import org.eclipse.swt.widgets.Composite; +import org.eclipse.ui.PlatformUI; +import org.eclipse.ui.statushandlers.StatusManager; + +/** + * Common superclass for a wizard that performs a provisioning operation. + * + * @since 3.5 + */ +public abstract class ProvisioningOperationWizard extends Wizard { + + private static final String WIZARD_SETTINGS_SECTION = "WizardSettings"; //$NON-NLS-1$ + protected ProvisioningUI ui; + protected IUElementListRoot root; + protected ProfileChangeOperation operation; + protected Object[] planSelections; + protected RemediationPage remediationPage; + protected ISelectableIUsPage mainPage; + protected IResolutionErrorReportingPage errorPage; + protected ResolutionResultsWizardPage resolutionPage; + private ProvisioningContext provisioningContext; + protected LoadMetadataRepositoryJob repoPreloadJob; + IStatus couldNotResolveStatus = Status.OK_STATUS; // we haven't tried and failed + boolean resolveWithRelaxedConstraints = false; + boolean waitingForOtherJobs = false; + protected RemediationOperation remediationOperation; + private IProvisioningPlan localJRECheckPlan; + + public ProvisioningOperationWizard(ProvisioningUI ui, ProfileChangeOperation operation, Object[] initialSelections, + LoadMetadataRepositoryJob job) { + super(); + this.ui = ui; + this.operation = operation; + initializeResolutionModelElements(initialSelections); + this.repoPreloadJob = job; + setForcePreviousAndNextButtons(true); + setNeedsProgressMonitor(true); + if (operation != null) { + provisioningContext = operation.getProvisioningContext(); + } + } + + public void setRemediationOperation(RemediationOperation remediationOperation) { + this.remediationOperation = remediationOperation; + } + + public RemediationOperation getRemediationOperation() { + return remediationOperation; + } + + @Override + public void addPages() { + mainPage = createMainPage(root, planSelections); + addPage(mainPage); + errorPage = createErrorReportingPage(); + if (errorPage != mainPage) + addPage(errorPage); + remediationPage = createRemediationPage(); + if (remediationPage != null) + addPage(remediationPage); + resolutionPage = createResolutionPage(); + addPage(resolutionPage); + } + + protected abstract RemediationPage createRemediationPage(); + + protected abstract IResolutionErrorReportingPage createErrorReportingPage(); + + protected abstract ISelectableIUsPage createMainPage(IUElementListRoot input, Object[] selections); + + protected abstract ResolutionResultsWizardPage createResolutionPage(); + + @Override + public boolean performFinish() { + return resolutionPage.performFinish(); + } + + protected LoadMetadataRepositoryJob getRepositoryPreloadJob() { + return repoPreloadJob; + } + + @Override + public IWizardPage getPreviousPage(IWizardPage page) { + if (page == errorPage) { + return mainPage; + } + return super.getPreviousPage(page); + } + + @Override + public IWizardPage getNextPage(IWizardPage page) { + // If we are moving from the main page or error page, we may need to resolve + // before + // advancing. + + if (page == remediationPage) { + try { + getContainer().run(true, true, monitor -> { + remediationOperation.setCurrentRemedy(remediationPage.getRemediationGroup().getCurrentRemedy()); + remediationOperation.resolveModal(monitor); + if (getPolicy().getCheckAgainstCurrentExecutionEnvironment()) { + this.localJRECheckPlan = ProvUI + .toCompabilityWithCurrentJREProvisioningPlan(remediationOperation, monitor); + if (!compatibleWithCurrentEE()) { + couldNotResolveStatus = localJRECheckPlan.getStatus(); + } + } + }); + } catch (InterruptedException e) { + // Nothing to report if thread was interrupted + } catch (InvocationTargetException e) { + ProvUI.handleException(e.getCause(), null, StatusManager.SHOW | StatusManager.LOG); + couldNotResolve(null); + } + operation = remediationOperation; + initializeResolutionModelElements(ElementUtils.requestToElement( + ((RemediationOperation) operation).getCurrentRemedy(), !(this instanceof UpdateWizard))); + planChanged(); + if (getPolicy().getCheckAgainstCurrentExecutionEnvironment() && !compatibleWithCurrentEE()) { + return errorPage; + } + return resolutionPage; + } else if (page == mainPage || page == errorPage) { + ISelectableIUsPage currentPage = (ISelectableIUsPage) page; + // Do we need to resolve? + if (operation == null || (operation != null && shouldRecomputePlan(currentPage))) { + recomputePlan(getContainer(), true); + } else { + // the selections have not changed from an IU point of view, but we want + // to reinitialize the resolution model elements to ensure they are up to + // date. + initializeResolutionModelElements(planSelections); + } + IStatus status = operation.getResolutionResult(); + if (getPolicy().getCheckAgainstCurrentExecutionEnvironment() && !compatibleWithCurrentEE()) { + // skip remediation for EE compatibility issues + return errorPage; + } + if (status == null || status.getSeverity() == IStatus.ERROR) { + if (page == mainPage) { + if (remediationOperation != null && remediationOperation.getResolutionResult() == Status.OK_STATUS + && remediationOperation.getRemedyConfigs().length == 1) { + planChanged(); + return getNextPage(remediationPage); + } + if (remediationOperation != null + && remediationOperation.getResolutionResult() == Status.OK_STATUS) { + planChanged(); + return remediationPage; + } + return errorPage; + } + } else if (status.getSeverity() == IStatus.CANCEL) { + return page; + } else { + if (remediationPage != null) + remediationPage.setPageComplete(true); + return resolutionPage; + } + } + return super.getNextPage(page); + } + + private boolean compatibleWithCurrentEE() { + if (operation == null || !getPolicy().getCheckAgainstCurrentExecutionEnvironment()) { + return true; + } + if (localJRECheckPlan == null) { + try { + getContainer().run(true, true, monitor -> { + if (!operation.hasResolved()) { + operation.resolveModal(monitor); + } + if (operation.getProfileChangeRequest() != null) { + this.localJRECheckPlan = ProvUI.toCompabilityWithCurrentJREProvisioningPlan(operation, null); + if (!compatibleWithCurrentEE()) { + couldNotResolveStatus = localJRECheckPlan.getStatus(); + } + } + }); + } catch (InvocationTargetException | InterruptedException e) { + return false; + } + } + if (localJRECheckPlan == null) { + return true; + } + + IStatus currentEEPlanStatus = localJRECheckPlan.getStatus(); + if (currentEEPlanStatus.getSeverity() != IStatus.ERROR) { + return true; + } + return Stream.of(currentEEPlanStatus).filter(status -> status.getSeverity() == IStatus.ERROR) + .flatMap(status -> status.isMultiStatus() ? Stream.of(status.getChildren()) : Stream.of(status)) + .filter(status -> status.getSeverity() == IStatus.ERROR) + .flatMap(status -> status.isMultiStatus() ? Stream.of(status.getChildren()) : Stream.of(status)) + .filter(status -> status.getSeverity() == IStatus.ERROR) + .flatMap(status -> status.isMultiStatus() ? Stream.of(status.getChildren()) : Stream.of(status)) + .map(IStatus::getMessage).noneMatch(message -> message.contains("osgi.ee")); //$NON-NLS-1$ + } + + /** + * The selections that drive the provisioning operation have changed. We might + * need to change the completion state of the resolution page. + */ + public void operationSelectionsChanged(ISelectableIUsPage page) { + if (resolutionPage != null) { + // If the page selections are different than what we may have resolved + // against, then this page is not complete. + boolean old = resolutionPage.isPageComplete(); + resolutionPage + .setPageComplete(page.getCheckedIUElements() != null && page.getCheckedIUElements().length > 0); + // If the state has truly changed, update the buttons. + if (old != resolutionPage.isPageComplete()) { + IWizardContainer container = getContainer(); + if (container != null && container.getCurrentPage() != null) + getContainer().updateButtons(); + } + } + } + + private boolean shouldRecomputePlan(ISelectableIUsPage page) { + boolean previouslyWaiting = waitingForOtherJobs; + boolean previouslyCanceled = getCurrentStatus().getSeverity() == IStatus.CANCEL; + waitingForOtherJobs = ui.hasScheduledOperations(); + return waitingForOtherJobs || previouslyWaiting || previouslyCanceled || pageSelectionsHaveChanged(page) + || provisioningContextChanged(); + } + + protected boolean pageSelectionsHaveChanged(ISelectableIUsPage page) { + HashSet selectedIUs = new HashSet<>(); + Object[] currentSelections = page.getCheckedIUElements(); + selectedIUs.addAll(ElementUtils.elementsToIUs(currentSelections)); + HashSet lastIUSelections = new HashSet<>(); + if (planSelections != null) + lastIUSelections.addAll(ElementUtils.elementsToIUs(planSelections)); + return !(selectedIUs.equals(lastIUSelections)); + } + + private boolean provisioningContextChanged() { + ProvisioningContext currentProvisioningContext = getProvisioningContext(); + if (currentProvisioningContext == null && provisioningContext == null) + return false; + if (currentProvisioningContext != null && provisioningContext != null) + return !currentProvisioningContext.equals(provisioningContext); + // One is null and the other is not + return true; + } + + protected void planChanged() { + IWizardPage currentPage = getContainer().getCurrentPage(); + if ((currentPage == null || currentPage == mainPage) && remediationPage != null && remediationOperation != null + && remediationOperation.getResolutionResult() == Status.OK_STATUS) { + remediationPage.updateStatus(root, operation, planSelections); + } + resolutionPage.updateStatus(root, operation); + if (errorPage != resolutionPage) { + IUElementListRoot newRoot = shouldUpdateErrorPageModelOnPlanChange() ? root : null; + errorPage.updateStatus(newRoot, operation); + } + } + + protected boolean shouldUpdateErrorPageModelOnPlanChange() { + return errorPage != mainPage; + } + + protected abstract void initializeResolutionModelElements(Object[] selectedElements); + + protected ProvisioningContext getProvisioningContext() { + if (operation != null) { + return operation.getProvisioningContext(); + } + return new ProvisioningContext(ui.getSession().getProvisioningAgent()); + } + + public void recomputePlan(IRunnableContext runnableContext) { + recomputePlan(runnableContext, false); + } + + public void computeRemediationOperation(ProfileChangeOperation op, ProvisioningUI ui, IProgressMonitor monitor) { + monitor.setTaskName(ProvUIMessages.ProvisioningOperationWizard_Remediation_Operation); + remediationOperation = new RemediationOperation(ui.getSession(), op.getProfileChangeRequest()); + remediationOperation.resolveModal(monitor); + monitor.done(); + } + + /** + * Recompute the provisioning plan based on the items in the IUElementListRoot + * and the given provisioning context. Report progress using the specified + * runnable context. This method may be called before the page is created. + * + * @param runnableContext + */ + public void recomputePlan(IRunnableContext runnableContext, final boolean withRemediation) { + couldNotResolveStatus = Status.OK_STATUS; + provisioningContext = getProvisioningContext(); + operation = null; + localJRECheckPlan = null; + remediationOperation = null; + initializeResolutionModelElements(getOperationSelections()); + if (planSelections.length == 0) { + couldNotResolve(ProvUIMessages.ResolutionWizardPage_NoSelections); + } else { + operation = getProfileChangeOperation(planSelections); + operation.setProvisioningContext(provisioningContext); + try { + runnableContext.run(true, true, monitor -> { + operation.resolveModal(monitor); + if (operation.getProfileChangeRequest() != null + && getPolicy().getCheckAgainstCurrentExecutionEnvironment()) { + this.localJRECheckPlan = ProvUI.toCompabilityWithCurrentJREProvisioningPlan(operation, monitor); + if (!compatibleWithCurrentEE()) { + couldNotResolveStatus = localJRECheckPlan.getStatus(); + } + } + if (withRemediation) { + IStatus status = operation.getResolutionResult(); + if (remediationPage != null && shouldRemediate(status)) { + computeRemediationOperation(operation, ui, monitor); + } + } + }); + } catch (InterruptedException e) { + // Nothing to report if thread was interrupted + } catch (InvocationTargetException e) { + ProvUI.handleException(e.getCause(), null, StatusManager.SHOW | StatusManager.LOG); + couldNotResolve(null); + } + } + planChanged(); + } + + public boolean shouldRemediate(IStatus status) { + return status == null || status.getSeverity() == IStatus.ERROR; + } + + /* + * Get the selections that drive the provisioning operation. + */ + protected Object[] getOperationSelections() { + return mainPage.getCheckedIUElements(); + } + + protected abstract ProfileChangeOperation getProfileChangeOperation(Object[] elements); + + void couldNotResolve(String message) { + if (message != null) { + couldNotResolveStatus = new Status(IStatus.ERROR, ProvUIActivator.PLUGIN_ID, message, null); + } else { + couldNotResolveStatus = new Status(IStatus.ERROR, ProvUIActivator.PLUGIN_ID, + ProvUIMessages.ProvisioningOperationWizard_UnexpectedFailureToResolve, null); + } + StatusManager.getManager().handle(couldNotResolveStatus, StatusManager.LOG); + } + + public IStatus getCurrentStatus() { + if (statusOverridesOperation()) + return couldNotResolveStatus; + if (operation != null && operation.getResolutionResult() != null) { + if (!operation.getResolutionResult().isOK() || localJRECheckPlan == null || compatibleWithCurrentEE()) { + return operation.getResolutionResult(); + } else if (!compatibleWithCurrentEE()) { + return localJRECheckPlan.getStatus(); + } + } + return couldNotResolveStatus; + } + + public String getDialogSettingsSectionName() { + return getClass().getName() + "." + WIZARD_SETTINGS_SECTION; //$NON-NLS-1$ + } + + public void saveBoundsRelatedSettings() { + IWizardPage[] pages = getPages(); + for (IWizardPage page : pages) { + if (page instanceof ProvisioningWizardPage) + ((ProvisioningWizardPage) page).saveBoundsRelatedSettings(); + } + } + + protected Policy getPolicy() { + return ui.getPolicy(); + } + + protected String getProfileId() { + return ui.getProfileId(); + } + + protected boolean shouldShowProvisioningPlanChildren() { + return ProvUI.getQueryContext(getPolicy()).getShowProvisioningPlanChildren(); + } + + /* + * Overridden to start the preload job after page control creation. This allows + * any listeners on repo events to be set up before a batch load occurs. The job + * creator uses a property to indicate if the job needs scheduling (the client + * may have already completed the job before the UI was opened). + */ + @Override + public void createPageControls(Composite pageContainer) { + // We call this so that wizards ignore all repository eventing that occurs while + // the wizard is + // open. Otherwise, we can get an add event when a repository loads its + // references that we + // don't want to respond to. Since repo discovery events can be received + // asynchronously by the + // manager, the subsequent add events generated by the manager aren't guaranteed + // to be synchronous, + // even if our listener is synchronous. Thus, we can't fine-tune + // the "ignore" window to a specific operation. + // see https://bugs.eclipse.org/bugs/show_bug.cgi?id=277265#c38 + ui.signalRepositoryOperationStart(); + super.createPageControls(pageContainer); + if (repoPreloadJob != null) { + if (repoPreloadJob.getProperty(LoadMetadataRepositoryJob.WIZARD_CLIENT_SHOULD_SCHEDULE) != null) { + // job has not been scheduled. Set a listener so we can report accumulated + // errors and + // schedule it. + repoPreloadJob.addJobChangeListener(new JobChangeAdapter() { + @Override + public void done(IJobChangeEvent e) { + asyncReportLoadFailures(); + } + }); + repoPreloadJob.schedule(); + } else { + // job has been scheduled, might already be done. + if (repoPreloadJob.getState() == Job.NONE) { + // job is done, report failures found so far + // do it asynchronously since we are in the middle of creation + asyncReportLoadFailures(); + } else { + // job is waiting, sleeping, running, report failures when + // it's done + repoPreloadJob.addJobChangeListener(new JobChangeAdapter() { + + @Override + public void done(IJobChangeEvent e) { + asyncReportLoadFailures(); + } + + }); + } + + } + } + } + + @Override + public void dispose() { + ui.signalRepositoryOperationComplete(null, false); + super.dispose(); + } + + void asyncReportLoadFailures() { + if (repoPreloadJob != null && getShell() != null && !getShell().isDisposed()) { + getShell().getDisplay().asyncExec(() -> { + if (PlatformUI.isWorkbenchRunning() && getShell() != null && !getShell().isDisposed()) + repoPreloadJob.reportAccumulatedStatus(); + }); + } + } + + /* + * Return a boolean indicating whether the wizard's current status should + * override any detail reported by the operation. + */ + public boolean statusOverridesOperation() { + return operation != null && operation.getResolutionResult() != null + && operation.getResolutionResult().getSeverity() < IStatus.ERROR + && (localJRECheckPlan != null && !compatibleWithCurrentEE()); + } + + public void setRelaxedResolution(boolean value) { + this.resolveWithRelaxedConstraints = value; + } + + public boolean getRelaxedResoltion() { + return this.resolveWithRelaxedConstraints; + } +} diff --git a/tycho-its/projects/api-tools/missing-bin/org.eclipse.equinox.p2.ui/src/org/eclipse/equinox/internal/p2/ui/dialogs/ProvisioningWizardDialog.java b/tycho-its/projects/api-tools/missing-bin/org.eclipse.equinox.p2.ui/src/org/eclipse/equinox/internal/p2/ui/dialogs/ProvisioningWizardDialog.java new file mode 100644 index 0000000000..d1d1aaf10d --- /dev/null +++ b/tycho-its/projects/api-tools/missing-bin/org.eclipse.equinox.p2.ui/src/org/eclipse/equinox/internal/p2/ui/dialogs/ProvisioningWizardDialog.java @@ -0,0 +1,67 @@ +/******************************************************************************* + * Copyright (c) 2009, 2010 IBM Corporation and others. + * + * This program and the accompanying materials + * are made available under the terms of the Eclipse Public License 2.0 + * which accompanies this distribution, and is available at + * https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + * + * Contributors: + * IBM Corporation - initial API and implementation + ******************************************************************************/ + +package org.eclipse.equinox.internal.p2.ui.dialogs; + +import org.eclipse.equinox.internal.p2.ui.ProvUIActivator; +import org.eclipse.jface.dialogs.IDialogSettings; +import org.eclipse.jface.wizard.WizardDialog; +import org.eclipse.swt.SWT; +import org.eclipse.swt.widgets.Button; +import org.eclipse.swt.widgets.Shell; + +/** + * Subclass of WizardDialog that provides bounds saving behavior. + * @since 3.5 + * + */ +public class ProvisioningWizardDialog extends WizardDialog { + private ProvisioningOperationWizard wizard; + + public ProvisioningWizardDialog(Shell parent, ProvisioningOperationWizard wizard) { + super(parent, wizard); + this.wizard = wizard; + setShellStyle(getShellStyle() | SWT.RESIZE); + } + + @Override + protected IDialogSettings getDialogBoundsSettings() { + IDialogSettings settings = ProvUIActivator.getDefault().getDialogSettings(); + IDialogSettings section = settings.getSection(wizard.getDialogSettingsSectionName()); + if (section == null) { + section = settings.addNewSection(wizard.getDialogSettingsSectionName()); + } + return section; + } + + /** + * @see org.eclipse.jface.window.Window#close() + */ + @Override + public boolean close() { + if (getShell() != null && !getShell().isDisposed()) { + wizard.saveBoundsRelatedSettings(); + } + return super.close(); + } + + /** + * This method is provided only for automated testing. + * + * @noreference This method is not intended to be referenced by clients. + */ + public Button testGetButton(int id) { + return getButton(id); + } +} diff --git a/tycho-its/projects/api-tools/missing-bin/org.eclipse.equinox.p2.ui/src/org/eclipse/equinox/internal/p2/ui/dialogs/ProvisioningWizardPage.java b/tycho-its/projects/api-tools/missing-bin/org.eclipse.equinox.p2.ui/src/org/eclipse/equinox/internal/p2/ui/dialogs/ProvisioningWizardPage.java new file mode 100644 index 0000000000..01b61863bd --- /dev/null +++ b/tycho-its/projects/api-tools/missing-bin/org.eclipse.equinox.p2.ui/src/org/eclipse/equinox/internal/p2/ui/dialogs/ProvisioningWizardPage.java @@ -0,0 +1,73 @@ +/******************************************************************************* + * Copyright (c) 2009, 2010 IBM Corporation and others. + * + * This program and the accompanying materials + * are made available under the terms of the Eclipse Public License 2.0 + * which accompanies this distribution, and is available at + * https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + * + * Contributors: + * IBM Corporation - initial API and implementation + *******************************************************************************/ +package org.eclipse.equinox.internal.p2.ui.dialogs; + +import org.eclipse.equinox.p2.ui.*; +import org.eclipse.jface.wizard.WizardPage; +import org.eclipse.swt.dnd.*; +import org.eclipse.swt.widgets.Control; +import org.eclipse.ui.PlatformUI; + +abstract class ProvisioningWizardPage extends WizardPage implements ICopyable { + + private ProvisioningUI ui; + private ProvisioningOperationWizard wizard; + + protected ProvisioningWizardPage(String pageName, ProvisioningUI ui, ProvisioningOperationWizard wizard) { + super(pageName); + this.wizard = wizard; + this.ui = ui; + } + + protected void activateCopy(Control control) { + CopyUtils.activateCopy(this, control); + + } + + protected ProvisioningOperationWizard getProvisioningWizard() { + return wizard; + } + + @Override + public void copyToClipboard(Control activeControl) { + String text = getClipboardText(activeControl); + if (text.length() == 0) + return; + Clipboard clipboard = new Clipboard(PlatformUI.getWorkbench().getDisplay()); + clipboard.setContents(new Object[] {text}, new Transfer[] {TextTransfer.getInstance()}); + clipboard.dispose(); + } + + protected abstract String getClipboardText(Control control); + + /** + * Save any settings that are related to the bounds of the wizard. + * This method is called when the wizard is about to close. + */ + public void saveBoundsRelatedSettings() { + // Default is to do nothing + } + + protected ProvisioningUI getProvisioningUI() { + return ui; + } + + protected Policy getPolicy() { + return ui.getPolicy(); + } + + String getProfileId() { + return ui.getProfileId(); + } +} \ No newline at end of file diff --git a/tycho-its/projects/api-tools/missing-bin/org.eclipse.equinox.p2.ui/src/org/eclipse/equinox/internal/p2/ui/dialogs/RemediationGroup.java b/tycho-its/projects/api-tools/missing-bin/org.eclipse.equinox.p2.ui/src/org/eclipse/equinox/internal/p2/ui/dialogs/RemediationGroup.java new file mode 100644 index 0000000000..7dceef7f03 --- /dev/null +++ b/tycho-its/projects/api-tools/missing-bin/org.eclipse.equinox.p2.ui/src/org/eclipse/equinox/internal/p2/ui/dialogs/RemediationGroup.java @@ -0,0 +1,504 @@ +/******************************************************************************* + * Copyright (c) 2013, 2018 Red Hat, Inc. and others + * + * This program and the accompanying materials + * are made available under the terms of the Eclipse Public License 2.0 + * which accompanies this distribution, and is available at + * https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + * + * Contributors: + * Red Hat, Inc. - initial API and implementation + * Karsten Thoms, itemis - Bug#448789 + *******************************************************************************/ +package org.eclipse.equinox.internal.p2.ui.dialogs; + +import java.util.*; +import java.util.List; +import org.eclipse.core.runtime.*; +import org.eclipse.equinox.internal.p2.ui.*; +import org.eclipse.equinox.internal.p2.ui.model.*; +import org.eclipse.equinox.p2.metadata.IInstallableUnit; +import org.eclipse.equinox.p2.metadata.Version; +import org.eclipse.equinox.p2.operations.*; +import org.eclipse.jface.resource.ImageDescriptor; +import org.eclipse.jface.viewers.*; +import org.eclipse.jface.wizard.WizardPage; +import org.eclipse.swt.SWT; +import org.eclipse.swt.custom.StackLayout; +import org.eclipse.swt.events.SelectionListener; +import org.eclipse.swt.graphics.Image; +import org.eclipse.swt.layout.GridData; +import org.eclipse.swt.layout.GridLayout; +import org.eclipse.swt.widgets.*; + +public class RemediationGroup { + static final int ALLOWPARTIALINSTALL_INDEX = 0; + static final int ALLOWDIFFERENTVERSION_INDEX = 1; + static final int ALLOWINSTALLEDUPDATE_INDEX = 2; + static final int ALLOWINSTALLEDREMOVAL_INDEX = 3; + + private RemediationOperation remediationOperation; + Composite remediationComposite; + private Button bestBeingInstalledRelaxedButton; + private Button bestInstalledRelaxedButton; + Button buildMyOwnSolution; + final ArrayList