Bug 543351 - [Error Log Move] Tracking of Platform UI changes
Added error log view to platform
Change-Id: Id3acb728c84d7175eb1ad2dfbe3ac467597fc6a8
Signed-off-by: Wim Jongman <wim.jongman@remainsoftware.com>
diff --git a/bundles/org.eclipse.ui.views.log/.classpath b/bundles/org.eclipse.ui.views.log/.classpath
new file mode 100644
index 0000000..01836c4
--- /dev/null
+++ b/bundles/org.eclipse.ui.views.log/.classpath
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<classpath>
+ <classpathentry kind="src" path="src"/>
+ <classpathentry kind="con" path="org.eclipse.pde.core.requiredPlugins"/>
+ <classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.8"/>
+ <classpathentry kind="output" path="bin"/>
+</classpath>
diff --git a/bundles/org.eclipse.ui.views.log/.project b/bundles/org.eclipse.ui.views.log/.project
new file mode 100644
index 0000000..8de6b90
--- /dev/null
+++ b/bundles/org.eclipse.ui.views.log/.project
@@ -0,0 +1,34 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<projectDescription>
+ <name>org.eclipse.ui.views.log</name>
+ <comment></comment>
+ <projects>
+ </projects>
+ <buildSpec>
+ <buildCommand>
+ <name>org.eclipse.jdt.core.javabuilder</name>
+ <arguments>
+ </arguments>
+ </buildCommand>
+ <buildCommand>
+ <name>org.eclipse.pde.ManifestBuilder</name>
+ <arguments>
+ </arguments>
+ </buildCommand>
+ <buildCommand>
+ <name>org.eclipse.pde.SchemaBuilder</name>
+ <arguments>
+ </arguments>
+ </buildCommand>
+ <buildCommand>
+ <name>org.eclipse.pde.api.tools.apiAnalysisBuilder</name>
+ <arguments>
+ </arguments>
+ </buildCommand>
+ </buildSpec>
+ <natures>
+ <nature>org.eclipse.pde.PluginNature</nature>
+ <nature>org.eclipse.jdt.core.javanature</nature>
+ <nature>org.eclipse.pde.api.tools.apiAnalysisNature</nature>
+ </natures>
+</projectDescription>
diff --git a/bundles/org.eclipse.ui.views.log/.settings/org.eclipse.core.resources.prefs b/bundles/org.eclipse.ui.views.log/.settings/org.eclipse.core.resources.prefs
new file mode 100644
index 0000000..fc21a08
--- /dev/null
+++ b/bundles/org.eclipse.ui.views.log/.settings/org.eclipse.core.resources.prefs
@@ -0,0 +1,6 @@
+eclipse.preferences.version=1
+encoding//core/framework/org/eclipse/osgi/framework/internal/core/default.permissions=UTF-8
+encoding//core/framework/org/eclipse/osgi/framework/internal/core/implied.permissions=UTF-8
+encoding//core/framework/org/eclipse/osgi/framework/internal/core/osname.aliases=UTF-8
+encoding//core/framework/org/eclipse/osgi/framework/internal/core/processor.aliases=UTF-8
+encoding/<project>=UTF-8
diff --git a/bundles/org.eclipse.ui.views.log/.settings/org.eclipse.core.runtime.prefs b/bundles/org.eclipse.ui.views.log/.settings/org.eclipse.core.runtime.prefs
new file mode 100644
index 0000000..5a0ad22
--- /dev/null
+++ b/bundles/org.eclipse.ui.views.log/.settings/org.eclipse.core.runtime.prefs
@@ -0,0 +1,2 @@
+eclipse.preferences.version=1
+line.separator=\n
diff --git a/bundles/org.eclipse.ui.views.log/.settings/org.eclipse.jdt.core.prefs b/bundles/org.eclipse.ui.views.log/.settings/org.eclipse.jdt.core.prefs
new file mode 100644
index 0000000..654cc26
--- /dev/null
+++ b/bundles/org.eclipse.ui.views.log/.settings/org.eclipse.jdt.core.prefs
@@ -0,0 +1,424 @@
+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.recreateModifiedClassFileInOutputFolder=ignore
+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.classpath.outputOverlappingAnotherSource=error
+org.eclipse.jdt.core.codeComplete.argumentPrefixes=
+org.eclipse.jdt.core.codeComplete.argumentSuffixes=
+org.eclipse.jdt.core.codeComplete.fieldPrefixes=
+org.eclipse.jdt.core.codeComplete.fieldSuffixes=
+org.eclipse.jdt.core.codeComplete.localPrefixes=
+org.eclipse.jdt.core.codeComplete.localSuffixes=
+org.eclipse.jdt.core.codeComplete.staticFieldPrefixes=
+org.eclipse.jdt.core.codeComplete.staticFieldSuffixes=
+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=1.8
+org.eclipse.jdt.core.compiler.codegen.unusedLocal=preserve
+org.eclipse.jdt.core.compiler.compliance=1.8
+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=warning
+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.enumIdentifier=error
+org.eclipse.jdt.core.compiler.problem.explicitlyClosedAutoCloseable=warning
+org.eclipse.jdt.core.compiler.problem.fallthroughCase=ignore
+org.eclipse.jdt.core.compiler.problem.fatalOptionalError=enabled
+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=error
+org.eclipse.jdt.core.compiler.problem.indirectStaticAccess=warning
+org.eclipse.jdt.core.compiler.problem.invalidJavadoc=warning
+org.eclipse.jdt.core.compiler.problem.invalidJavadocTagsVisibility=private
+org.eclipse.jdt.core.compiler.problem.localVariableHiding=ignore
+org.eclipse.jdt.core.compiler.problem.methodWithConstructorName=warning
+org.eclipse.jdt.core.compiler.problem.missingDefaultCase=ignore
+org.eclipse.jdt.core.compiler.problem.missingDeprecatedAnnotation=warning
+org.eclipse.jdt.core.compiler.problem.missingEnumCaseDespiteDefault=disabled
+org.eclipse.jdt.core.compiler.problem.missingHashCodeMethod=ignore
+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=warning
+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=ignore
+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=warning
+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.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=ignore
+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.unsafeTypeOperation=warning
+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.source=1.8
+org.eclipse.jdt.core.formatter.align_type_members_on_columns=false
+org.eclipse.jdt.core.formatter.alignment_for_arguments_in_allocation_expression=16
+org.eclipse.jdt.core.formatter.alignment_for_arguments_in_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_binary_expression=16
+org.eclipse.jdt.core.formatter.alignment_for_compact_if=16
+org.eclipse.jdt.core.formatter.alignment_for_conditional_expression=80
+org.eclipse.jdt.core.formatter.alignment_for_enum_constants=0
+org.eclipse.jdt.core.formatter.alignment_for_expressions_in_array_initializer=16
+org.eclipse.jdt.core.formatter.alignment_for_method_declaration=0
+org.eclipse.jdt.core.formatter.alignment_for_multiple_fields=16
+org.eclipse.jdt.core.formatter.alignment_for_parameters_in_constructor_declaration=16
+org.eclipse.jdt.core.formatter.alignment_for_parameters_in_method_declaration=16
+org.eclipse.jdt.core.formatter.alignment_for_resources_in_try=80
+org.eclipse.jdt.core.formatter.alignment_for_selector_in_method_invocation=16
+org.eclipse.jdt.core.formatter.alignment_for_superclass_in_type_declaration=16
+org.eclipse.jdt.core.formatter.alignment_for_superinterfaces_in_enum_declaration=16
+org.eclipse.jdt.core.formatter.alignment_for_superinterfaces_in_type_declaration=16
+org.eclipse.jdt.core.formatter.alignment_for_throws_clause_in_constructor_declaration=16
+org.eclipse.jdt.core.formatter.alignment_for_throws_clause_in_method_declaration=16
+org.eclipse.jdt.core.formatter.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.clear_blank_lines_in_block_comment=false
+org.eclipse.jdt.core.formatter.comment.clear_blank_lines_in_javadoc_comment=false
+org.eclipse.jdt.core.formatter.comment.format_block_comments=true
+org.eclipse.jdt.core.formatter.comment.format_header=false
+org.eclipse.jdt.core.formatter.comment.format_html=true
+org.eclipse.jdt.core.formatter.comment.format_javadoc_comments=true
+org.eclipse.jdt.core.formatter.comment.format_line_comments=true
+org.eclipse.jdt.core.formatter.comment.format_source_code=true
+org.eclipse.jdt.core.formatter.comment.indent_parameter_description=true
+org.eclipse.jdt.core.formatter.comment.indent_root_tags=true
+org.eclipse.jdt.core.formatter.comment.insert_new_line_before_root_tags=insert
+org.eclipse.jdt.core.formatter.comment.insert_new_line_for_parameter=insert
+org.eclipse.jdt.core.formatter.comment.line_length=80
+org.eclipse.jdt.core.formatter.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=true
+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_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=insert
+org.eclipse.jdt.core.formatter.insert_new_line_in_empty_block=insert
+org.eclipse.jdt.core.formatter.insert_new_line_in_empty_enum_constant=insert
+org.eclipse.jdt.core.formatter.insert_new_line_in_empty_enum_declaration=insert
+org.eclipse.jdt.core.formatter.insert_new_line_in_empty_method_body=insert
+org.eclipse.jdt.core.formatter.insert_new_line_in_empty_type_declaration=insert
+org.eclipse.jdt.core.formatter.insert_space_after_and_in_type_parameter=insert
+org.eclipse.jdt.core.formatter.insert_space_after_assignment_operator=insert
+org.eclipse.jdt.core.formatter.insert_space_after_at_in_annotation=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_at_in_annotation_type_declaration=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_binary_operator=insert
+org.eclipse.jdt.core.formatter.insert_space_after_closing_angle_bracket_in_type_arguments=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_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_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_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_unary_operator=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_and_in_type_parameter=insert
+org.eclipse.jdt.core.formatter.insert_space_before_assignment_operator=insert
+org.eclipse.jdt.core.formatter.insert_space_before_at_in_annotation_type_declaration=insert
+org.eclipse.jdt.core.formatter.insert_space_before_binary_operator=insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_angle_bracket_in_parameterized_type_reference=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_angle_bracket_in_type_arguments=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_angle_bracket_in_type_parameters=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_brace_in_array_initializer=insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_bracket_in_array_allocation_expression=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_bracket_in_array_reference=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_annotation=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_cast=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_catch=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_constructor_declaration=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_enum_constant=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_for=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_if=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_method_declaration=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_method_invocation=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_parenthesized_expression=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_switch=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_synchronized=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_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_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_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_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_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_else_statement_on_same_line=false
+org.eclipse.jdt.core.formatter.keep_empty_array_initializer_on_one_line=false
+org.eclipse.jdt.core.formatter.keep_imple_if_on_one_line=false
+org.eclipse.jdt.core.formatter.keep_then_statement_on_same_line=false
+org.eclipse.jdt.core.formatter.lineSplit=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.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_binary_operator=true
+org.eclipse.jdt.core.formatter.wrap_before_or_operator_multicatch=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/bundles/org.eclipse.ui.views.log/.settings/org.eclipse.jdt.ui.prefs b/bundles/org.eclipse.ui.views.log/.settings/org.eclipse.jdt.ui.prefs
new file mode 100644
index 0000000..5625e784
--- /dev/null
+++ b/bundles/org.eclipse.ui.views.log/.settings/org.eclipse.jdt.ui.prefs
@@ -0,0 +1,71 @@
+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=12
+org.eclipse.jdt.ui.exception.name=e
+org.eclipse.jdt.ui.gettersetter.use.is=true
+org.eclipse.jdt.ui.ignorelowercasenames=true
+org.eclipse.jdt.ui.importorder=;
+org.eclipse.jdt.ui.keywordthis=false
+org.eclipse.jdt.ui.ondemandthreshold=3
+org.eclipse.jdt.ui.overrideannotation=false
+org.eclipse.jdt.ui.staticondemandthreshold=99
+org.eclipse.jdt.ui.text.custom_code_templates=<?xml version\="1.0" encoding\="UTF-8" standalone\="no"?><templates/>
+sp_cleanup.add_default_serial_version_id=true
+sp_cleanup.add_generated_serial_version_id=false
+sp_cleanup.add_missing_annotations=false
+sp_cleanup.add_missing_deprecated_annotations=true
+sp_cleanup.add_missing_methods=false
+sp_cleanup.add_missing_nls_tags=false
+sp_cleanup.add_missing_override_annotations=true
+sp_cleanup.add_missing_override_annotations_interface_methods=false
+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=false
+sp_cleanup.convert_to_enhanced_for_loop=false
+sp_cleanup.correct_indentation=false
+sp_cleanup.format_source_code=true
+sp_cleanup.format_source_code_changes_only=true
+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=true
+sp_cleanup.never_use_blocks=false
+sp_cleanup.never_use_parentheses_in_expressions=true
+sp_cleanup.on_save_use_additional_actions=false
+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_type_arguments=false
+sp_cleanup.remove_trailing_whitespaces=false
+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=false
+sp_cleanup.remove_unused_local_variables=false
+sp_cleanup.remove_unused_private_fields=true
+sp_cleanup.remove_unused_private_members=false
+sp_cleanup.remove_unused_private_methods=true
+sp_cleanup.remove_unused_private_types=true
+sp_cleanup.sort_members=false
+sp_cleanup.sort_members_all=false
+sp_cleanup.use_anonymous_class_creation=false
+sp_cleanup.use_blocks=false
+sp_cleanup.use_blocks_only_for_return_and_throw=false
+sp_cleanup.use_lambda=false
+sp_cleanup.use_parentheses_in_expressions=false
+sp_cleanup.use_this_for_non_static_field_access=false
+sp_cleanup.use_this_for_non_static_field_access_only_if_necessary=true
+sp_cleanup.use_this_for_non_static_method_access=false
+sp_cleanup.use_this_for_non_static_method_access_only_if_necessary=true
+sp_cleanup.use_type_arguments=false
diff --git a/bundles/org.eclipse.ui.views.log/.settings/org.eclipse.pde.api.tools.prefs b/bundles/org.eclipse.ui.views.log/.settings/org.eclipse.pde.api.tools.prefs
new file mode 100644
index 0000000..3cf0ccb
--- /dev/null
+++ b/bundles/org.eclipse.ui.views.log/.settings/org.eclipse.pde.api.tools.prefs
@@ -0,0 +1,97 @@
+ANNOTATION_ELEMENT_TYPE_ADDED_METHOD_WITHOUT_DEFAULT_VALUE=Error
+ANNOTATION_ELEMENT_TYPE_CHANGED_TYPE_CONVERSION=Error
+ANNOTATION_ELEMENT_TYPE_REMOVED_FIELD=Error
+ANNOTATION_ELEMENT_TYPE_REMOVED_METHOD=Error
+ANNOTATION_ELEMENT_TYPE_REMOVED_TYPE_MEMBER=Error
+API_COMPONENT_ELEMENT_TYPE_REMOVED_API_TYPE=Error
+API_COMPONENT_ELEMENT_TYPE_REMOVED_REEXPORTED_API_TYPE=Error
+API_COMPONENT_ELEMENT_TYPE_REMOVED_REEXPORTED_TYPE=Error
+API_COMPONENT_ELEMENT_TYPE_REMOVED_TYPE=Error
+API_USE_SCAN_FIELD_SEVERITY=Error
+API_USE_SCAN_METHOD_SEVERITY=Error
+API_USE_SCAN_TYPE_SEVERITY=Error
+CLASS_ELEMENT_TYPE_ADDED_METHOD=Error
+CLASS_ELEMENT_TYPE_ADDED_RESTRICTIONS=Error
+CLASS_ELEMENT_TYPE_ADDED_TYPE_PARAMETER=Error
+CLASS_ELEMENT_TYPE_CHANGED_CONTRACTED_SUPERINTERFACES_SET=Error
+CLASS_ELEMENT_TYPE_CHANGED_DECREASE_ACCESS=Error
+CLASS_ELEMENT_TYPE_CHANGED_NON_ABSTRACT_TO_ABSTRACT=Error
+CLASS_ELEMENT_TYPE_CHANGED_NON_FINAL_TO_FINAL=Error
+CLASS_ELEMENT_TYPE_CHANGED_TYPE_CONVERSION=Error
+CLASS_ELEMENT_TYPE_REMOVED_CONSTRUCTOR=Error
+CLASS_ELEMENT_TYPE_REMOVED_FIELD=Error
+CLASS_ELEMENT_TYPE_REMOVED_METHOD=Error
+CLASS_ELEMENT_TYPE_REMOVED_SUPERCLASS=Error
+CLASS_ELEMENT_TYPE_REMOVED_TYPE_MEMBER=Error
+CLASS_ELEMENT_TYPE_REMOVED_TYPE_PARAMETER=Error
+CONSTRUCTOR_ELEMENT_TYPE_ADDED_TYPE_PARAMETER=Error
+CONSTRUCTOR_ELEMENT_TYPE_CHANGED_DECREASE_ACCESS=Error
+CONSTRUCTOR_ELEMENT_TYPE_CHANGED_VARARGS_TO_ARRAY=Error
+CONSTRUCTOR_ELEMENT_TYPE_REMOVED_TYPE_PARAMETER=Error
+ENUM_ELEMENT_TYPE_CHANGED_CONTRACTED_SUPERINTERFACES_SET=Error
+ENUM_ELEMENT_TYPE_CHANGED_TYPE_CONVERSION=Error
+ENUM_ELEMENT_TYPE_REMOVED_ENUM_CONSTANT=Error
+ENUM_ELEMENT_TYPE_REMOVED_FIELD=Error
+ENUM_ELEMENT_TYPE_REMOVED_METHOD=Error
+ENUM_ELEMENT_TYPE_REMOVED_TYPE_MEMBER=Error
+FIELD_ELEMENT_TYPE_ADDED_VALUE=Error
+FIELD_ELEMENT_TYPE_CHANGED_DECREASE_ACCESS=Error
+FIELD_ELEMENT_TYPE_CHANGED_FINAL_TO_NON_FINAL_STATIC_CONSTANT=Error
+FIELD_ELEMENT_TYPE_CHANGED_NON_FINAL_TO_FINAL=Error
+FIELD_ELEMENT_TYPE_CHANGED_NON_STATIC_TO_STATIC=Error
+FIELD_ELEMENT_TYPE_CHANGED_STATIC_TO_NON_STATIC=Error
+FIELD_ELEMENT_TYPE_CHANGED_TYPE=Error
+FIELD_ELEMENT_TYPE_CHANGED_VALUE=Error
+FIELD_ELEMENT_TYPE_REMOVED_TYPE_ARGUMENT=Error
+FIELD_ELEMENT_TYPE_REMOVED_VALUE=Error
+ILLEGAL_EXTEND=Warning
+ILLEGAL_IMPLEMENT=Warning
+ILLEGAL_INSTANTIATE=Warning
+ILLEGAL_OVERRIDE=Warning
+ILLEGAL_REFERENCE=Warning
+INTERFACE_ELEMENT_TYPE_ADDED_FIELD=Error
+INTERFACE_ELEMENT_TYPE_ADDED_METHOD=Error
+INTERFACE_ELEMENT_TYPE_ADDED_RESTRICTIONS=Error
+INTERFACE_ELEMENT_TYPE_ADDED_SUPER_INTERFACE_WITH_METHODS=Error
+INTERFACE_ELEMENT_TYPE_ADDED_TYPE_PARAMETER=Error
+INTERFACE_ELEMENT_TYPE_CHANGED_CONTRACTED_SUPERINTERFACES_SET=Error
+INTERFACE_ELEMENT_TYPE_CHANGED_TYPE_CONVERSION=Error
+INTERFACE_ELEMENT_TYPE_REMOVED_FIELD=Error
+INTERFACE_ELEMENT_TYPE_REMOVED_METHOD=Error
+INTERFACE_ELEMENT_TYPE_REMOVED_TYPE_MEMBER=Error
+INTERFACE_ELEMENT_TYPE_REMOVED_TYPE_PARAMETER=Error
+INVALID_JAVADOC_TAG=Warning
+INVALID_REFERENCE_IN_SYSTEM_LIBRARIES=Warning
+LEAK_EXTEND=Warning
+LEAK_FIELD_DECL=Warning
+LEAK_IMPLEMENT=Warning
+LEAK_METHOD_PARAM=Warning
+LEAK_METHOD_RETURN_TYPE=Warning
+METHOD_ELEMENT_TYPE_ADDED_RESTRICTIONS=Error
+METHOD_ELEMENT_TYPE_ADDED_TYPE_PARAMETER=Error
+METHOD_ELEMENT_TYPE_CHANGED_DECREASE_ACCESS=Error
+METHOD_ELEMENT_TYPE_CHANGED_NON_ABSTRACT_TO_ABSTRACT=Error
+METHOD_ELEMENT_TYPE_CHANGED_NON_FINAL_TO_FINAL=Error
+METHOD_ELEMENT_TYPE_CHANGED_NON_STATIC_TO_STATIC=Error
+METHOD_ELEMENT_TYPE_CHANGED_STATIC_TO_NON_STATIC=Error
+METHOD_ELEMENT_TYPE_CHANGED_VARARGS_TO_ARRAY=Error
+METHOD_ELEMENT_TYPE_REMOVED_ANNOTATION_DEFAULT_VALUE=Error
+METHOD_ELEMENT_TYPE_REMOVED_TYPE_PARAMETER=Error
+MISSING_EE_DESCRIPTIONS=Warning
+TYPE_PARAMETER_ELEMENT_TYPE_ADDED_CLASS_BOUND=Error
+TYPE_PARAMETER_ELEMENT_TYPE_ADDED_INTERFACE_BOUND=Error
+TYPE_PARAMETER_ELEMENT_TYPE_CHANGED_CLASS_BOUND=Error
+TYPE_PARAMETER_ELEMENT_TYPE_CHANGED_INTERFACE_BOUND=Error
+TYPE_PARAMETER_ELEMENT_TYPE_REMOVED_CLASS_BOUND=Error
+TYPE_PARAMETER_ELEMENT_TYPE_REMOVED_INTERFACE_BOUND=Error
+UNUSED_PROBLEM_FILTERS=Warning
+automatically_removed_unused_problem_filters=false
+eclipse.preferences.version=1
+incompatible_api_component_version=Error
+incompatible_api_component_version_include_major_without_breaking_change=Disabled
+incompatible_api_component_version_include_minor_without_api_change=Disabled
+invalid_since_tag_version=Error
+malformed_since_tag=Error
+missing_since_tag=Error
+report_api_breakage_when_major_version_incremented=Disabled
+report_resolution_errors_api_component=Warning
diff --git a/bundles/org.eclipse.ui.views.log/.settings/org.eclipse.pde.prefs b/bundles/org.eclipse.ui.views.log/.settings/org.eclipse.pde.prefs
new file mode 100644
index 0000000..88a12c6
--- /dev/null
+++ b/bundles/org.eclipse.ui.views.log/.settings/org.eclipse.pde.prefs
@@ -0,0 +1,34 @@
+compilers.f.unresolved-features=1
+compilers.f.unresolved-plugins=1
+compilers.incompatible-environment=0
+compilers.p.build=1
+compilers.p.build.bin.includes=1
+compilers.p.build.encodings=2
+compilers.p.build.java.compiler=2
+compilers.p.build.java.compliance=1
+compilers.p.build.missing.output=1
+compilers.p.build.output.library=1
+compilers.p.build.source.library=1
+compilers.p.build.src.includes=1
+compilers.p.deprecated=1
+compilers.p.discouraged-class=1
+compilers.p.internal=1
+compilers.p.matching-pom-version=0
+compilers.p.missing-packages=0
+compilers.p.missing-version-export-package=2
+compilers.p.missing-version-import-package=2
+compilers.p.missing-version-require-bundle=2
+compilers.p.no-required-att=0
+compilers.p.not-externalized-att=1
+compilers.p.unknown-attribute=1
+compilers.p.unknown-class=1
+compilers.p.unknown-element=1
+compilers.p.unknown-identifier=1
+compilers.p.unknown-resource=1
+compilers.p.unresolved-ex-points=0
+compilers.p.unresolved-import=0
+compilers.s.create-docs=false
+compilers.s.doc-folder=doc
+compilers.s.open-tags=1
+compilers.use-project=true
+eclipse.preferences.version=1
diff --git a/bundles/org.eclipse.ui.views.log/META-INF/MANIFEST.MF b/bundles/org.eclipse.ui.views.log/META-INF/MANIFEST.MF
new file mode 100644
index 0000000..ed15d5f
--- /dev/null
+++ b/bundles/org.eclipse.ui.views.log/META-INF/MANIFEST.MF
@@ -0,0 +1,18 @@
+Manifest-Version: 1.0
+Bundle-ManifestVersion: 2
+Bundle-Name: %name
+Bundle-SymbolicName: org.eclipse.ui.views.log;singleton:=true
+Bundle-Version: 1.2.500.qualifier
+Bundle-Activator: org.eclipse.ui.internal.views.log.Activator
+Bundle-Vendor: %provider-name
+Require-Bundle: org.eclipse.core.runtime;bundle-version="[3.2.0,4.0.0)",
+ org.eclipse.core.filesystem;bundle-version="[1.1.0,2.0.0)";resolution:=optional,
+ org.eclipse.ui;bundle-version="[3.3.0,4.0.0)",
+ org.eclipse.ui.ide;bundle-version="[3.3.0,4.0.0)";resolution:=optional
+Import-Package: com.ibm.icu.text
+Eclipse-LazyStart: true
+Bundle-RequiredExecutionEnvironment: JavaSE-1.8
+Bundle-Localization: plugin
+Export-Package: org.eclipse.ui.internal.views.log;x-friends:="org.eclipse.pde.ui"
+Bundle-ActivationPolicy: lazy
+Automatic-Module-Name: org.eclipse.ui.views.log
diff --git a/bundles/org.eclipse.ui.views.log/about.html b/bundles/org.eclipse.ui.views.log/about.html
new file mode 100644
index 0000000..164f781
--- /dev/null
+++ b/bundles/org.eclipse.ui.views.log/about.html
@@ -0,0 +1,36 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
+ "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1" />
+<title>About</title>
+</head>
+<body lang="EN-US">
+ <h2>About This Content</h2>
+
+ <p>November 30, 2017</p>
+ <h3>License</h3>
+
+ <p>
+ The Eclipse Foundation makes available all content in this plug-in
+ ("Content"). Unless otherwise indicated below, the Content
+ is provided to you under the terms and conditions of the Eclipse
+ Public License Version 2.0 ("EPL"). A copy of the EPL is
+ available at <a href="http://www.eclipse.org/legal/epl-2.0">http://www.eclipse.org/legal/epl-2.0</a>.
+ For purposes of the EPL, "Program" will mean the Content.
+ </p>
+
+ <p>
+ If you did not receive this Content directly from the Eclipse
+ Foundation, the Content is being redistributed by another party
+ ("Redistributor") and different terms and conditions may
+ apply to your use of any object code in the Content. Check the
+ Redistributor's license that was provided with the Content. If no such
+ license exists, contact the Redistributor. Unless otherwise indicated
+ below, the terms and conditions of the EPL still apply to any source
+ code in the Content and such source code may be obtained at <a
+ href="http://www.eclipse.org/">http://www.eclipse.org</a>.
+ </p>
+
+</body>
+</html>
\ No newline at end of file
diff --git a/bundles/org.eclipse.ui.views.log/build.properties b/bundles/org.eclipse.ui.views.log/build.properties
new file mode 100644
index 0000000..188b6ee
--- /dev/null
+++ b/bundles/org.eclipse.ui.views.log/build.properties
@@ -0,0 +1,22 @@
+###############################################################################
+# Copyright (c) 2005, 2007 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
+###############################################################################
+source.. = src/
+output.. = bin/
+bin.includes = META-INF/,\
+ .,\
+ plugin.xml,\
+ plugin.properties,\
+ icons/,\
+ about.html
+src.includes = about.html
diff --git a/bundles/org.eclipse.ui.views.log/forceQualifierUpdate.txt b/bundles/org.eclipse.ui.views.log/forceQualifierUpdate.txt
new file mode 100644
index 0000000..02430ce
--- /dev/null
+++ b/bundles/org.eclipse.ui.views.log/forceQualifierUpdate.txt
@@ -0,0 +1 @@
+Bug 534597 - Unanticipated comparator errors in I20180511-2000
diff --git a/bundles/org.eclipse.ui.views.log/icons/dlcl16/clear.png b/bundles/org.eclipse.ui.views.log/icons/dlcl16/clear.png
new file mode 100644
index 0000000..5848f39
--- /dev/null
+++ b/bundles/org.eclipse.ui.views.log/icons/dlcl16/clear.png
Binary files differ
diff --git a/bundles/org.eclipse.ui.views.log/icons/dlcl16/clear@2x.png b/bundles/org.eclipse.ui.views.log/icons/dlcl16/clear@2x.png
new file mode 100644
index 0000000..132562e
--- /dev/null
+++ b/bundles/org.eclipse.ui.views.log/icons/dlcl16/clear@2x.png
Binary files differ
diff --git a/bundles/org.eclipse.ui.views.log/icons/dlcl16/collapseall.png b/bundles/org.eclipse.ui.views.log/icons/dlcl16/collapseall.png
new file mode 100644
index 0000000..957f394
--- /dev/null
+++ b/bundles/org.eclipse.ui.views.log/icons/dlcl16/collapseall.png
Binary files differ
diff --git a/bundles/org.eclipse.ui.views.log/icons/dlcl16/collapseall@2x.png b/bundles/org.eclipse.ui.views.log/icons/dlcl16/collapseall@2x.png
new file mode 100644
index 0000000..ee8e649
--- /dev/null
+++ b/bundles/org.eclipse.ui.views.log/icons/dlcl16/collapseall@2x.png
Binary files differ
diff --git a/bundles/org.eclipse.ui.views.log/icons/dlcl16/export_log.png b/bundles/org.eclipse.ui.views.log/icons/dlcl16/export_log.png
new file mode 100644
index 0000000..5e0ae37
--- /dev/null
+++ b/bundles/org.eclipse.ui.views.log/icons/dlcl16/export_log.png
Binary files differ
diff --git a/bundles/org.eclipse.ui.views.log/icons/dlcl16/export_log@2x.png b/bundles/org.eclipse.ui.views.log/icons/dlcl16/export_log@2x.png
new file mode 100644
index 0000000..9a40417
--- /dev/null
+++ b/bundles/org.eclipse.ui.views.log/icons/dlcl16/export_log@2x.png
Binary files differ
diff --git a/bundles/org.eclipse.ui.views.log/icons/dlcl16/filter_ps.png b/bundles/org.eclipse.ui.views.log/icons/dlcl16/filter_ps.png
new file mode 100644
index 0000000..e54535c
--- /dev/null
+++ b/bundles/org.eclipse.ui.views.log/icons/dlcl16/filter_ps.png
Binary files differ
diff --git a/bundles/org.eclipse.ui.views.log/icons/dlcl16/filter_ps@2x.png b/bundles/org.eclipse.ui.views.log/icons/dlcl16/filter_ps@2x.png
new file mode 100644
index 0000000..4717078
--- /dev/null
+++ b/bundles/org.eclipse.ui.views.log/icons/dlcl16/filter_ps@2x.png
Binary files differ
diff --git a/bundles/org.eclipse.ui.views.log/icons/dlcl16/find_obj.png b/bundles/org.eclipse.ui.views.log/icons/dlcl16/find_obj.png
new file mode 100644
index 0000000..93170f9
--- /dev/null
+++ b/bundles/org.eclipse.ui.views.log/icons/dlcl16/find_obj.png
Binary files differ
diff --git a/bundles/org.eclipse.ui.views.log/icons/dlcl16/find_obj@2x.png b/bundles/org.eclipse.ui.views.log/icons/dlcl16/find_obj@2x.png
new file mode 100644
index 0000000..92c125a
--- /dev/null
+++ b/bundles/org.eclipse.ui.views.log/icons/dlcl16/find_obj@2x.png
Binary files differ
diff --git a/bundles/org.eclipse.ui.views.log/icons/dlcl16/import_log.png b/bundles/org.eclipse.ui.views.log/icons/dlcl16/import_log.png
new file mode 100644
index 0000000..17c54f5
--- /dev/null
+++ b/bundles/org.eclipse.ui.views.log/icons/dlcl16/import_log.png
Binary files differ
diff --git a/bundles/org.eclipse.ui.views.log/icons/dlcl16/import_log@2x.png b/bundles/org.eclipse.ui.views.log/icons/dlcl16/import_log@2x.png
new file mode 100644
index 0000000..ad3a3a1
--- /dev/null
+++ b/bundles/org.eclipse.ui.views.log/icons/dlcl16/import_log@2x.png
Binary files differ
diff --git a/bundles/org.eclipse.ui.views.log/icons/dlcl16/open_log.png b/bundles/org.eclipse.ui.views.log/icons/dlcl16/open_log.png
new file mode 100644
index 0000000..a04a1bb
--- /dev/null
+++ b/bundles/org.eclipse.ui.views.log/icons/dlcl16/open_log.png
Binary files differ
diff --git a/bundles/org.eclipse.ui.views.log/icons/dlcl16/open_log@2x.png b/bundles/org.eclipse.ui.views.log/icons/dlcl16/open_log@2x.png
new file mode 100644
index 0000000..b739e75
--- /dev/null
+++ b/bundles/org.eclipse.ui.views.log/icons/dlcl16/open_log@2x.png
Binary files differ
diff --git a/bundles/org.eclipse.ui.views.log/icons/dlcl16/properties.png b/bundles/org.eclipse.ui.views.log/icons/dlcl16/properties.png
new file mode 100644
index 0000000..0bf3902
--- /dev/null
+++ b/bundles/org.eclipse.ui.views.log/icons/dlcl16/properties.png
Binary files differ
diff --git a/bundles/org.eclipse.ui.views.log/icons/dlcl16/properties@2x.png b/bundles/org.eclipse.ui.views.log/icons/dlcl16/properties@2x.png
new file mode 100644
index 0000000..a514381
--- /dev/null
+++ b/bundles/org.eclipse.ui.views.log/icons/dlcl16/properties@2x.png
Binary files differ
diff --git a/bundles/org.eclipse.ui.views.log/icons/dlcl16/refresh.png b/bundles/org.eclipse.ui.views.log/icons/dlcl16/refresh.png
new file mode 100644
index 0000000..a8670b4
--- /dev/null
+++ b/bundles/org.eclipse.ui.views.log/icons/dlcl16/refresh.png
Binary files differ
diff --git a/bundles/org.eclipse.ui.views.log/icons/dlcl16/refresh@2x.png b/bundles/org.eclipse.ui.views.log/icons/dlcl16/refresh@2x.png
new file mode 100644
index 0000000..dd6787d
--- /dev/null
+++ b/bundles/org.eclipse.ui.views.log/icons/dlcl16/refresh@2x.png
Binary files differ
diff --git a/bundles/org.eclipse.ui.views.log/icons/dlcl16/remove.png b/bundles/org.eclipse.ui.views.log/icons/dlcl16/remove.png
new file mode 100644
index 0000000..a67bf4b
--- /dev/null
+++ b/bundles/org.eclipse.ui.views.log/icons/dlcl16/remove.png
Binary files differ
diff --git a/bundles/org.eclipse.ui.views.log/icons/dlcl16/remove@2x.png b/bundles/org.eclipse.ui.views.log/icons/dlcl16/remove@2x.png
new file mode 100644
index 0000000..5d68209
--- /dev/null
+++ b/bundles/org.eclipse.ui.views.log/icons/dlcl16/remove@2x.png
Binary files differ
diff --git a/bundles/org.eclipse.ui.views.log/icons/dlcl16/restore_log.png b/bundles/org.eclipse.ui.views.log/icons/dlcl16/restore_log.png
new file mode 100644
index 0000000..8632759
--- /dev/null
+++ b/bundles/org.eclipse.ui.views.log/icons/dlcl16/restore_log.png
Binary files differ
diff --git a/bundles/org.eclipse.ui.views.log/icons/dlcl16/restore_log@2x.png b/bundles/org.eclipse.ui.views.log/icons/dlcl16/restore_log@2x.png
new file mode 100644
index 0000000..ba2ab52
--- /dev/null
+++ b/bundles/org.eclipse.ui.views.log/icons/dlcl16/restore_log@2x.png
Binary files differ
diff --git a/bundles/org.eclipse.ui.views.log/icons/elcl16/clear.png b/bundles/org.eclipse.ui.views.log/icons/elcl16/clear.png
new file mode 100644
index 0000000..9f0b9af
--- /dev/null
+++ b/bundles/org.eclipse.ui.views.log/icons/elcl16/clear.png
Binary files differ
diff --git a/bundles/org.eclipse.ui.views.log/icons/elcl16/clear@2x.png b/bundles/org.eclipse.ui.views.log/icons/elcl16/clear@2x.png
new file mode 100644
index 0000000..24e08ac
--- /dev/null
+++ b/bundles/org.eclipse.ui.views.log/icons/elcl16/clear@2x.png
Binary files differ
diff --git a/bundles/org.eclipse.ui.views.log/icons/elcl16/collapseall.png b/bundles/org.eclipse.ui.views.log/icons/elcl16/collapseall.png
new file mode 100644
index 0000000..92cc578
--- /dev/null
+++ b/bundles/org.eclipse.ui.views.log/icons/elcl16/collapseall.png
Binary files differ
diff --git a/bundles/org.eclipse.ui.views.log/icons/elcl16/collapseall@2x.png b/bundles/org.eclipse.ui.views.log/icons/elcl16/collapseall@2x.png
new file mode 100644
index 0000000..8769e04
--- /dev/null
+++ b/bundles/org.eclipse.ui.views.log/icons/elcl16/collapseall@2x.png
Binary files differ
diff --git a/bundles/org.eclipse.ui.views.log/icons/elcl16/export_log.png b/bundles/org.eclipse.ui.views.log/icons/elcl16/export_log.png
new file mode 100644
index 0000000..1ae7c09
--- /dev/null
+++ b/bundles/org.eclipse.ui.views.log/icons/elcl16/export_log.png
Binary files differ
diff --git a/bundles/org.eclipse.ui.views.log/icons/elcl16/export_log@2x.png b/bundles/org.eclipse.ui.views.log/icons/elcl16/export_log@2x.png
new file mode 100644
index 0000000..961bd21
--- /dev/null
+++ b/bundles/org.eclipse.ui.views.log/icons/elcl16/export_log@2x.png
Binary files differ
diff --git a/bundles/org.eclipse.ui.views.log/icons/elcl16/filter_ps.png b/bundles/org.eclipse.ui.views.log/icons/elcl16/filter_ps.png
new file mode 100644
index 0000000..50b14d8
--- /dev/null
+++ b/bundles/org.eclipse.ui.views.log/icons/elcl16/filter_ps.png
Binary files differ
diff --git a/bundles/org.eclipse.ui.views.log/icons/elcl16/filter_ps@2x.png b/bundles/org.eclipse.ui.views.log/icons/elcl16/filter_ps@2x.png
new file mode 100644
index 0000000..3d8cbe3
--- /dev/null
+++ b/bundles/org.eclipse.ui.views.log/icons/elcl16/filter_ps@2x.png
Binary files differ
diff --git a/bundles/org.eclipse.ui.views.log/icons/elcl16/find_obj.png b/bundles/org.eclipse.ui.views.log/icons/elcl16/find_obj.png
new file mode 100644
index 0000000..b3f0921
--- /dev/null
+++ b/bundles/org.eclipse.ui.views.log/icons/elcl16/find_obj.png
Binary files differ
diff --git a/bundles/org.eclipse.ui.views.log/icons/elcl16/find_obj@2x.png b/bundles/org.eclipse.ui.views.log/icons/elcl16/find_obj@2x.png
new file mode 100644
index 0000000..f3aec94
--- /dev/null
+++ b/bundles/org.eclipse.ui.views.log/icons/elcl16/find_obj@2x.png
Binary files differ
diff --git a/bundles/org.eclipse.ui.views.log/icons/elcl16/import_log.png b/bundles/org.eclipse.ui.views.log/icons/elcl16/import_log.png
new file mode 100644
index 0000000..5603bac
--- /dev/null
+++ b/bundles/org.eclipse.ui.views.log/icons/elcl16/import_log.png
Binary files differ
diff --git a/bundles/org.eclipse.ui.views.log/icons/elcl16/import_log@2x.png b/bundles/org.eclipse.ui.views.log/icons/elcl16/import_log@2x.png
new file mode 100644
index 0000000..dee9d50
--- /dev/null
+++ b/bundles/org.eclipse.ui.views.log/icons/elcl16/import_log@2x.png
Binary files differ
diff --git a/bundles/org.eclipse.ui.views.log/icons/elcl16/open_log.png b/bundles/org.eclipse.ui.views.log/icons/elcl16/open_log.png
new file mode 100644
index 0000000..c22d381
--- /dev/null
+++ b/bundles/org.eclipse.ui.views.log/icons/elcl16/open_log.png
Binary files differ
diff --git a/bundles/org.eclipse.ui.views.log/icons/elcl16/open_log@2x.png b/bundles/org.eclipse.ui.views.log/icons/elcl16/open_log@2x.png
new file mode 100644
index 0000000..9e32f88
--- /dev/null
+++ b/bundles/org.eclipse.ui.views.log/icons/elcl16/open_log@2x.png
Binary files differ
diff --git a/bundles/org.eclipse.ui.views.log/icons/elcl16/properties.png b/bundles/org.eclipse.ui.views.log/icons/elcl16/properties.png
new file mode 100644
index 0000000..9eee9b5
--- /dev/null
+++ b/bundles/org.eclipse.ui.views.log/icons/elcl16/properties.png
Binary files differ
diff --git a/bundles/org.eclipse.ui.views.log/icons/elcl16/properties@2x.png b/bundles/org.eclipse.ui.views.log/icons/elcl16/properties@2x.png
new file mode 100644
index 0000000..4dbe2c0
--- /dev/null
+++ b/bundles/org.eclipse.ui.views.log/icons/elcl16/properties@2x.png
Binary files differ
diff --git a/bundles/org.eclipse.ui.views.log/icons/elcl16/refresh.png b/bundles/org.eclipse.ui.views.log/icons/elcl16/refresh.png
new file mode 100644
index 0000000..79df522
--- /dev/null
+++ b/bundles/org.eclipse.ui.views.log/icons/elcl16/refresh.png
Binary files differ
diff --git a/bundles/org.eclipse.ui.views.log/icons/elcl16/refresh@2x.png b/bundles/org.eclipse.ui.views.log/icons/elcl16/refresh@2x.png
new file mode 100644
index 0000000..8bac975
--- /dev/null
+++ b/bundles/org.eclipse.ui.views.log/icons/elcl16/refresh@2x.png
Binary files differ
diff --git a/bundles/org.eclipse.ui.views.log/icons/elcl16/remove.png b/bundles/org.eclipse.ui.views.log/icons/elcl16/remove.png
new file mode 100644
index 0000000..a0259cc
--- /dev/null
+++ b/bundles/org.eclipse.ui.views.log/icons/elcl16/remove.png
Binary files differ
diff --git a/bundles/org.eclipse.ui.views.log/icons/elcl16/remove@2x.png b/bundles/org.eclipse.ui.views.log/icons/elcl16/remove@2x.png
new file mode 100644
index 0000000..0c8137f
--- /dev/null
+++ b/bundles/org.eclipse.ui.views.log/icons/elcl16/remove@2x.png
Binary files differ
diff --git a/bundles/org.eclipse.ui.views.log/icons/elcl16/restore_log.png b/bundles/org.eclipse.ui.views.log/icons/elcl16/restore_log.png
new file mode 100644
index 0000000..a2b2fbc
--- /dev/null
+++ b/bundles/org.eclipse.ui.views.log/icons/elcl16/restore_log.png
Binary files differ
diff --git a/bundles/org.eclipse.ui.views.log/icons/elcl16/restore_log@2x.png b/bundles/org.eclipse.ui.views.log/icons/elcl16/restore_log@2x.png
new file mode 100644
index 0000000..c235313
--- /dev/null
+++ b/bundles/org.eclipse.ui.views.log/icons/elcl16/restore_log@2x.png
Binary files differ
diff --git a/bundles/org.eclipse.ui.views.log/icons/eview16/error_log.gif b/bundles/org.eclipse.ui.views.log/icons/eview16/error_log.gif
new file mode 100644
index 0000000..58873a1
--- /dev/null
+++ b/bundles/org.eclipse.ui.views.log/icons/eview16/error_log.gif
Binary files differ
diff --git a/bundles/org.eclipse.ui.views.log/icons/eview16/error_log.png b/bundles/org.eclipse.ui.views.log/icons/eview16/error_log.png
new file mode 100644
index 0000000..3f794a7
--- /dev/null
+++ b/bundles/org.eclipse.ui.views.log/icons/eview16/error_log.png
Binary files differ
diff --git a/bundles/org.eclipse.ui.views.log/icons/eview16/error_log@2x.png b/bundles/org.eclipse.ui.views.log/icons/eview16/error_log@2x.png
new file mode 100644
index 0000000..997545c
--- /dev/null
+++ b/bundles/org.eclipse.ui.views.log/icons/eview16/error_log@2x.png
Binary files differ
diff --git a/bundles/org.eclipse.ui.views.log/icons/eview16/event_next.png b/bundles/org.eclipse.ui.views.log/icons/eview16/event_next.png
new file mode 100644
index 0000000..9fcc646
--- /dev/null
+++ b/bundles/org.eclipse.ui.views.log/icons/eview16/event_next.png
Binary files differ
diff --git a/bundles/org.eclipse.ui.views.log/icons/eview16/event_next@2x.png b/bundles/org.eclipse.ui.views.log/icons/eview16/event_next@2x.png
new file mode 100644
index 0000000..d46b3a0
--- /dev/null
+++ b/bundles/org.eclipse.ui.views.log/icons/eview16/event_next@2x.png
Binary files differ
diff --git a/bundles/org.eclipse.ui.views.log/icons/eview16/event_prev.png b/bundles/org.eclipse.ui.views.log/icons/eview16/event_prev.png
new file mode 100644
index 0000000..f2e6a03
--- /dev/null
+++ b/bundles/org.eclipse.ui.views.log/icons/eview16/event_prev.png
Binary files differ
diff --git a/bundles/org.eclipse.ui.views.log/icons/eview16/event_prev@2x.png b/bundles/org.eclipse.ui.views.log/icons/eview16/event_prev@2x.png
new file mode 100644
index 0000000..8e26ea4
--- /dev/null
+++ b/bundles/org.eclipse.ui.views.log/icons/eview16/event_prev@2x.png
Binary files differ
diff --git a/bundles/org.eclipse.ui.views.log/icons/obj16/error_st_obj.png b/bundles/org.eclipse.ui.views.log/icons/obj16/error_st_obj.png
new file mode 100644
index 0000000..66b2e49
--- /dev/null
+++ b/bundles/org.eclipse.ui.views.log/icons/obj16/error_st_obj.png
Binary files differ
diff --git a/bundles/org.eclipse.ui.views.log/icons/obj16/error_st_obj@2x.png b/bundles/org.eclipse.ui.views.log/icons/obj16/error_st_obj@2x.png
new file mode 100644
index 0000000..027b467
--- /dev/null
+++ b/bundles/org.eclipse.ui.views.log/icons/obj16/error_st_obj@2x.png
Binary files differ
diff --git a/bundles/org.eclipse.ui.views.log/icons/obj16/error_stack.png b/bundles/org.eclipse.ui.views.log/icons/obj16/error_stack.png
new file mode 100644
index 0000000..3f794a7
--- /dev/null
+++ b/bundles/org.eclipse.ui.views.log/icons/obj16/error_stack.png
Binary files differ
diff --git a/bundles/org.eclipse.ui.views.log/icons/obj16/error_stack@2x.png b/bundles/org.eclipse.ui.views.log/icons/obj16/error_stack@2x.png
new file mode 100644
index 0000000..997545c
--- /dev/null
+++ b/bundles/org.eclipse.ui.views.log/icons/obj16/error_stack@2x.png
Binary files differ
diff --git a/bundles/org.eclipse.ui.views.log/icons/obj16/hierarchical.png b/bundles/org.eclipse.ui.views.log/icons/obj16/hierarchical.png
new file mode 100644
index 0000000..665aa5c
--- /dev/null
+++ b/bundles/org.eclipse.ui.views.log/icons/obj16/hierarchical.png
Binary files differ
diff --git a/bundles/org.eclipse.ui.views.log/icons/obj16/hierarchical@2x.png b/bundles/org.eclipse.ui.views.log/icons/obj16/hierarchical@2x.png
new file mode 100644
index 0000000..84039be
--- /dev/null
+++ b/bundles/org.eclipse.ui.views.log/icons/obj16/hierarchical@2x.png
Binary files differ
diff --git a/bundles/org.eclipse.ui.views.log/icons/obj16/info_st_obj.png b/bundles/org.eclipse.ui.views.log/icons/obj16/info_st_obj.png
new file mode 100644
index 0000000..05ff6dc
--- /dev/null
+++ b/bundles/org.eclipse.ui.views.log/icons/obj16/info_st_obj.png
Binary files differ
diff --git a/bundles/org.eclipse.ui.views.log/icons/obj16/info_st_obj@2x.png b/bundles/org.eclipse.ui.views.log/icons/obj16/info_st_obj@2x.png
new file mode 100644
index 0000000..1390383
--- /dev/null
+++ b/bundles/org.eclipse.ui.views.log/icons/obj16/info_st_obj@2x.png
Binary files differ
diff --git a/bundles/org.eclipse.ui.views.log/icons/obj16/ok_st_obj.png b/bundles/org.eclipse.ui.views.log/icons/obj16/ok_st_obj.png
new file mode 100644
index 0000000..381e07b
--- /dev/null
+++ b/bundles/org.eclipse.ui.views.log/icons/obj16/ok_st_obj.png
Binary files differ
diff --git a/bundles/org.eclipse.ui.views.log/icons/obj16/ok_st_obj@2x.png b/bundles/org.eclipse.ui.views.log/icons/obj16/ok_st_obj@2x.png
new file mode 100644
index 0000000..22ebad1
--- /dev/null
+++ b/bundles/org.eclipse.ui.views.log/icons/obj16/ok_st_obj@2x.png
Binary files differ
diff --git a/bundles/org.eclipse.ui.views.log/icons/obj16/warning_st_obj.png b/bundles/org.eclipse.ui.views.log/icons/obj16/warning_st_obj.png
new file mode 100644
index 0000000..f9f5457
--- /dev/null
+++ b/bundles/org.eclipse.ui.views.log/icons/obj16/warning_st_obj.png
Binary files differ
diff --git a/bundles/org.eclipse.ui.views.log/icons/obj16/warning_st_obj@2x.png b/bundles/org.eclipse.ui.views.log/icons/obj16/warning_st_obj@2x.png
new file mode 100644
index 0000000..97339df
--- /dev/null
+++ b/bundles/org.eclipse.ui.views.log/icons/obj16/warning_st_obj@2x.png
Binary files differ
diff --git a/bundles/org.eclipse.ui.views.log/plugin.properties b/bundles/org.eclipse.ui.views.log/plugin.properties
new file mode 100644
index 0000000..d6be850
--- /dev/null
+++ b/bundles/org.eclipse.ui.views.log/plugin.properties
@@ -0,0 +1,20 @@
+###############################################################################
+# Copyright (c) 2000, 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
+###############################################################################
+
+name = Log View
+provider-name = Eclipse.org
+
+views.errorLog.name= Error Log
+content-type.name.log = Runtime log files
+
diff --git a/bundles/org.eclipse.ui.views.log/plugin.xml b/bundles/org.eclipse.ui.views.log/plugin.xml
new file mode 100644
index 0000000..27dbfc4
--- /dev/null
+++ b/bundles/org.eclipse.ui.views.log/plugin.xml
@@ -0,0 +1,91 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<?eclipse version="3.2"?><!--
+ Copyright (c) 2005, 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
+ -->
+
+<plugin>
+ <extension
+ point="org.eclipse.ui.views">
+ <view
+ name="%views.errorLog.name"
+ icon="$nl$/icons/eview16/error_log.png"
+ category="org.eclipse.ui"
+ class="org.eclipse.ui.internal.views.log.LogView"
+ id="org.eclipse.pde.runtime.LogView">
+ </view>
+ </extension>
+ <extension
+ point="org.eclipse.ui.perspectiveExtensions">
+ <perspectiveExtension
+ targetID="org.eclipse.ui.resourcePerspective">
+ <viewShortcut
+ id="org.eclipse.pde.runtime.LogView">
+ </viewShortcut>
+ </perspectiveExtension>
+ <perspectiveExtension
+ targetID="org.eclipse.pde.ui.PDEPerspective">
+ <viewShortcut
+ id="org.eclipse.pde.runtime.LogView">
+ </viewShortcut>
+ </perspectiveExtension>
+ <perspectiveExtension
+ targetID="org.eclipse.debug.ui.DebugPerspective">
+ <view
+ relative="org.eclipse.ui.console.ConsoleView"
+ visible="false"
+ id="org.eclipse.pde.runtime.LogView"
+ relationship="stack">
+ </view>
+ <viewShortcut
+ id="org.eclipse.pde.runtime.LogView">
+ </viewShortcut>
+ </perspectiveExtension>
+ </extension>
+ <extension
+ point="org.eclipse.ui.bindings">
+ <key
+ commandId="org.eclipse.ui.views.showView"
+ schemeId="org.eclipse.ui.defaultAcceleratorConfiguration"
+ sequence="M2+M3+Q L">
+ <parameter
+ id="org.eclipse.ui.views.showView.viewId"
+ value="org.eclipse.pde.runtime.LogView">
+ </parameter>
+ </key>
+ <key
+ platform="carbon"
+ schemeId="org.eclipse.ui.defaultAcceleratorConfiguration"
+ sequence="M2+M3+Q L">
+ </key>
+ <key
+ platform="carbon"
+ commandId="org.eclipse.ui.views.showView"
+ schemeId="org.eclipse.ui.defaultAcceleratorConfiguration"
+ sequence="M1+M3+Q L">
+ <parameter
+ id="org.eclipse.ui.views.showView.viewId"
+ value="org.eclipse.pde.runtime.LogView">
+ </parameter>
+ </key>
+ </extension>
+ <extension
+ point="org.eclipse.core.contenttype.contentTypes">
+ <content-type
+ base-type="org.eclipse.core.runtime.text"
+ file-extensions="log"
+ id="log"
+ name="%content-type.name.log"
+ priority="high">
+ </content-type>
+ </extension>
+</plugin>
diff --git a/bundles/org.eclipse.ui.views.log/pom.xml b/bundles/org.eclipse.ui.views.log/pom.xml
new file mode 100644
index 0000000..835be53
--- /dev/null
+++ b/bundles/org.eclipse.ui.views.log/pom.xml
@@ -0,0 +1,30 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ Copyright (c) 2012, 2016 Eclipse Foundation and others.
+ All rights reserved. This program and the accompanying materials
+ are made available under the terms of the Eclipse Distribution License v1.0
+ which accompanies this distribution, and is available at
+ http://www.eclipse.org/org/documents/edl-v10.php
+
+ Contributors:
+ Igor Fedorenko - initial implementation
+-->
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+ <parent>
+ <artifactId>eclipse.platform.ui</artifactId>
+ <groupId>eclipse.platform.ui</groupId>
+ <version>4.11.0-SNAPSHOT</version>
+ <relativePath>../../</relativePath>
+ </parent>
+
+ <groupId>org.eclipse.ui</groupId>
+ <artifactId>org.eclipse.ui.views.log</artifactId>
+ <version>1.2.500-SNAPSHOT</version>
+ <packaging>eclipse-plugin</packaging>
+
+ <properties>
+ <code.ignoredWarnings>-warn:-deprecation,raw,unchecked</code.ignoredWarnings>
+ </properties>
+
+</project>
diff --git a/bundles/org.eclipse.ui.views.log/src/org/eclipse/ui/internal/views/log/AbstractEntry.java b/bundles/org.eclipse.ui.views.log/src/org/eclipse/ui/internal/views/log/AbstractEntry.java
new file mode 100644
index 0000000..c121c95
--- /dev/null
+++ b/bundles/org.eclipse.ui.views.log/src/org/eclipse/ui/internal/views/log/AbstractEntry.java
@@ -0,0 +1,114 @@
+/*******************************************************************************
+ * 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
+ * Jacek Pospychala <jacek.pospychala@pl.ibm.com> - bug 207344
+ *******************************************************************************/
+package org.eclipse.ui.internal.views.log;
+
+import java.io.PrintWriter;
+import java.util.ArrayList;
+import java.util.List;
+import org.eclipse.core.runtime.PlatformObject;
+import org.eclipse.jface.resource.ImageDescriptor;
+import org.eclipse.ui.model.IWorkbenchAdapter;
+
+/**
+ * Everything that appears in LogView is Abstract Entry. It provides composite pattern.
+ */
+public abstract class AbstractEntry extends PlatformObject implements IWorkbenchAdapter {
+
+ /**
+ * The collection of direct children of this entry
+ */
+ private List<AbstractEntry> children = new ArrayList<>();
+ protected Object parent;
+
+ /**
+ * Adds the specified child entry to the listing of children.
+ * If the specified child is <code>null</code>, no work is done
+ *
+ * @param child
+ */
+ public void addChild(AbstractEntry child) {
+ if (child != null) {
+ children.add(0, child);
+ child.setParent(this);
+ }
+ }
+
+ @Override
+ public Object[] getChildren(Object parent) {
+ return children.toArray();
+ }
+
+ /**
+ * @return true if this entry has children, false otherwise
+ */
+ public boolean hasChildren() {
+ return children.size() > 0;
+ }
+
+ /**
+ * @return the size of the child array
+ *
+ * TODO rename to getChildCount(), or something more meaningful
+ */
+ public int size() {
+ return children.size();
+ }
+
+ @Override
+ public ImageDescriptor getImageDescriptor(Object object) {
+ return null;
+ }
+
+ @Override
+ public String getLabel(Object o) {
+ return null;
+ }
+
+ @Override
+ public Object getParent(Object o) {
+ return parent;
+ }
+
+ /**
+ * Sets the parent of this entry
+ * @param parent
+ */
+ public void setParent(AbstractEntry parent) {
+ this.parent = parent;
+ }
+
+ /**
+ * removes all of the children specified in the given listing
+ *
+ * @param list the list of children to remove
+ */
+ public void removeChildren(List<AbstractEntry> list) {
+ children.removeAll(list);
+ }
+
+ /**
+ * Removes all of the children from this entry
+ */
+ public void removeAllChildren() {
+ children.clear();
+ }
+
+ /**
+ * Writes this entry information into the given {@link PrintWriter}
+ *
+ * @param writer
+ */
+ public abstract void write(PrintWriter writer);
+}
diff --git a/bundles/org.eclipse.ui.views.log/src/org/eclipse/ui/internal/views/log/Activator.java b/bundles/org.eclipse.ui.views.log/src/org/eclipse/ui/internal/views/log/Activator.java
new file mode 100644
index 0000000..3e69a69
--- /dev/null
+++ b/bundles/org.eclipse.ui.views.log/src/org/eclipse/ui/internal/views/log/Activator.java
@@ -0,0 +1,90 @@
+/*******************************************************************************
+ * Copyright (c) 2007, 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
+ * Jacek Pospychala <jacek.pospychala@pl.ibm.com> - bug 202583
+ *******************************************************************************/
+package org.eclipse.ui.internal.views.log;
+
+import org.eclipse.jface.resource.ImageDescriptor;
+import org.eclipse.jface.resource.ImageRegistry;
+import org.eclipse.ui.plugin.AbstractUIPlugin;
+import org.osgi.framework.BundleContext;
+
+/**
+ * The activator class controls the plug-in life cycle
+ */
+public class Activator extends AbstractUIPlugin {
+
+ // The plug-in ID
+ public static final String PLUGIN_ID = "org.eclipse.ui.views.log"; //$NON-NLS-1$
+
+ // The shared instance
+ private static Activator plugin;
+
+ /**
+ * The constructor
+ */
+ public Activator() { // do nothing
+ }
+
+ @Override
+ public void start(BundleContext context) throws Exception {
+ super.start(context);
+ plugin = this;
+ }
+
+ @Override
+ public void stop(BundleContext context) throws Exception {
+ plugin = null;
+ super.stop(context);
+ }
+
+ public static Activator getDefault() {
+ return plugin;
+ }
+
+ @Override
+ protected void initializeImageRegistry(ImageRegistry registry) {
+ registry.put(SharedImages.DESC_PREV_EVENT, createImageDescriptor(SharedImages.DESC_PREV_EVENT));
+ registry.put(SharedImages.DESC_NEXT_EVENT, createImageDescriptor(SharedImages.DESC_NEXT_EVENT));
+
+ registry.put(SharedImages.DESC_ERROR_ST_OBJ, createImageDescriptor(SharedImages.DESC_ERROR_ST_OBJ));
+ registry.put(SharedImages.DESC_ERROR_STACK_OBJ, createImageDescriptor(SharedImages.DESC_ERROR_STACK_OBJ));
+ registry.put(SharedImages.DESC_INFO_ST_OBJ, createImageDescriptor(SharedImages.DESC_INFO_ST_OBJ));
+ registry.put(SharedImages.DESC_OK_ST_OBJ, createImageDescriptor(SharedImages.DESC_OK_ST_OBJ));
+ registry.put(SharedImages.DESC_WARNING_ST_OBJ, createImageDescriptor(SharedImages.DESC_WARNING_ST_OBJ));
+ registry.put(SharedImages.DESC_HIERARCHICAL_LAYOUT_OBJ, createImageDescriptor(SharedImages.DESC_HIERARCHICAL_LAYOUT_OBJ));
+
+ registry.put(SharedImages.DESC_CLEAR, createImageDescriptor(SharedImages.DESC_CLEAR));
+ registry.put(SharedImages.DESC_CLEAR_DISABLED, createImageDescriptor(SharedImages.DESC_CLEAR_DISABLED));
+ registry.put(SharedImages.DESC_OPEN_CONSOLE, createImageDescriptor(SharedImages.DESC_OPEN_CONSOLE));
+ registry.put(SharedImages.DESC_REMOVE_LOG, createImageDescriptor(SharedImages.DESC_REMOVE_LOG));
+ registry.put(SharedImages.DESC_REMOVE_LOG_DISABLED, createImageDescriptor(SharedImages.DESC_REMOVE_LOG_DISABLED));
+ registry.put(SharedImages.DESC_EXPORT, createImageDescriptor(SharedImages.DESC_EXPORT));
+ registry.put(SharedImages.DESC_EXPORT_DISABLED, createImageDescriptor(SharedImages.DESC_EXPORT_DISABLED));
+ registry.put(SharedImages.DESC_FILTER, createImageDescriptor(SharedImages.DESC_FILTER));
+ registry.put(SharedImages.DESC_FILTER_DISABLED, createImageDescriptor(SharedImages.DESC_FILTER_DISABLED));
+ registry.put(SharedImages.DESC_IMPORT, createImageDescriptor(SharedImages.DESC_IMPORT));
+ registry.put(SharedImages.DESC_IMPORT_DISABLED, createImageDescriptor(SharedImages.DESC_IMPORT_DISABLED));
+ registry.put(SharedImages.DESC_OPEN_LOG, createImageDescriptor(SharedImages.DESC_OPEN_LOG));
+ registry.put(SharedImages.DESC_OPEN_LOG_DISABLED, createImageDescriptor(SharedImages.DESC_OPEN_LOG_DISABLED));
+ registry.put(SharedImages.DESC_PROPERTIES, createImageDescriptor(SharedImages.DESC_PROPERTIES));
+ registry.put(SharedImages.DESC_PROPERTIES_DISABLED, createImageDescriptor(SharedImages.DESC_PROPERTIES_DISABLED));
+ registry.put(SharedImages.DESC_READ_LOG, createImageDescriptor(SharedImages.DESC_READ_LOG));
+ registry.put(SharedImages.DESC_READ_LOG_DISABLED, createImageDescriptor(SharedImages.DESC_READ_LOG_DISABLED));
+ }
+
+ private ImageDescriptor createImageDescriptor(String id) {
+ return imageDescriptorFromPlugin(PLUGIN_ID, id);
+ }
+
+}
diff --git a/bundles/org.eclipse.ui.views.log/src/org/eclipse/ui/internal/views/log/EventDetailsDialog.java b/bundles/org.eclipse.ui.views.log/src/org/eclipse/ui/internal/views/log/EventDetailsDialog.java
new file mode 100644
index 0000000..02d3d82
--- /dev/null
+++ b/bundles/org.eclipse.ui.views.log/src/org/eclipse/ui/internal/views/log/EventDetailsDialog.java
@@ -0,0 +1,873 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 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
+ * Jacek Pospychala <jacek.pospychala@pl.ibm.com> - bugs 202583, 207466, 207344
+ * Remy Chi Jian Suen <remy.suen@gmail.com> - bug 272985
+ * Lars Vogel <Lars.Vogel@vogella.com> - Bug 485843
+ *******************************************************************************/
+package org.eclipse.ui.internal.views.log;
+
+import com.ibm.icu.text.DateFormat;
+import java.io.*;
+import java.text.Collator;
+import java.util.*;
+import java.util.List;
+import org.eclipse.core.runtime.IAdaptable;
+import org.eclipse.jface.dialogs.*;
+import org.eclipse.jface.dialogs.Dialog;
+import org.eclipse.jface.viewers.*;
+import org.eclipse.jface.window.Window;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.accessibility.AccessibleAdapter;
+import org.eclipse.swt.accessibility.AccessibleEvent;
+import org.eclipse.swt.custom.SashForm;
+import org.eclipse.swt.dnd.*;
+import org.eclipse.swt.events.SelectionAdapter;
+import org.eclipse.swt.events.SelectionEvent;
+import org.eclipse.swt.graphics.Point;
+import org.eclipse.swt.layout.GridData;
+import org.eclipse.swt.layout.GridLayout;
+import org.eclipse.swt.widgets.*;
+import org.eclipse.ui.*;
+
+/**
+ * Displays details about Log Entry. Event information is split in three
+ * sections: details, stack trace and session. Details contain event date,
+ * message and severity. Stack trace is displayed if an exception is bound to
+ * event. Stack trace entries can be filtered.
+ */
+public class EventDetailsDialog extends TrayDialog {
+
+ public static final String FILTER_ENABLED = "detailsStackFilterEnabled"; //$NON-NLS-1$
+ public static final String FILTER_LIST = "detailsStackFilterList"; //$NON-NLS-1$
+
+ private LogView logView;
+ private IMemento memento;
+
+ private AbstractEntry entry;
+ private AbstractEntry parentEntry; // parent of the entry
+ private AbstractEntry[] entryChildren; // children of the entry
+
+ private LogViewLabelProvider labelProvider;
+ private TreeViewer provider;
+
+ private static int COPY_ID = 22;
+
+ private int childIndex = 0;
+ private boolean isOpen;
+ private boolean isLastChild;
+ private boolean isAtEndOfLog;
+
+ private Label plugInIdLabel;
+ private Label severityImageLabel;
+ private Label severityLabel;
+ private Label dateLabel;
+ private Text msgText;
+ private Text stackTraceText;
+ private Text sessionDataText;
+ private Clipboard clipboard;
+ private Button copyButton;
+ private Button backButton;
+ private Button nextButton;
+ private SashForm sashForm;
+
+ // sorting
+ private Comparator comparator = null;
+ Collator collator;
+
+ // patterns for filtering stack traces
+ private String[] stackFilterPatterns = null;
+
+ // location configuration
+ private Point dialogLocation;
+ private Point dialogSize;
+ private int[] sashWeights;
+
+ private DateFormat dateFormat = DateFormat.getDateTimeInstance(DateFormat.SHORT, DateFormat.SHORT);
+
+ /**
+ *
+ * @param parentShell
+ * shell in which dialog is displayed
+ * @param selection
+ * entry initially selected and to be displayed
+ * @param provider
+ * viewer
+ * @param comparator
+ * comparator used to order all entries
+ */
+ protected EventDetailsDialog(Shell parentShell, LogView logView, IAdaptable selection, ISelectionProvider provider,
+ Comparator comparator, IMemento memento) {
+ super(parentShell);
+ this.logView = logView;
+ this.provider = (TreeViewer) provider;
+ labelProvider = (LogViewLabelProvider) this.provider.getLabelProvider();
+ labelProvider.connect(this);
+ this.entry = (AbstractEntry) selection;
+ this.comparator = comparator;
+ this.memento = memento;
+ setShellStyle(SWT.MODELESS | SWT.MIN | SWT.MAX | SWT.RESIZE | SWT.CLOSE | SWT.BORDER | SWT.TITLE);
+ clipboard = new Clipboard(parentShell.getDisplay());
+ initialize();
+ collator = Collator.getInstance();
+ readConfiguration();
+ isLastChild = false;
+ isAtEndOfLog = false;
+ stackFilterPatterns = getFilters();
+ }
+
+ @Override
+ protected void configureShell(Shell newShell) {
+ super.configureShell(newShell);
+ PlatformUI.getWorkbench().getHelpSystem().setHelp(newShell, IHelpContextIds.LOG_EVENTDETAILS);
+ }
+
+ private void initialize() {
+ parentEntry = (AbstractEntry) entry.getParent(entry);
+ if (isChild(entry)) {
+ setEntryChildren(parentEntry);
+ } else {
+ setEntryChildren();
+ }
+ resetChildIndex();
+ isLastChild = false;
+ isAtEndOfLog = false;
+ }
+
+ private void resetChildIndex() {
+ if (entryChildren == null)
+ return;
+
+ LogEntry thisEntry = (LogEntry) entry;
+
+ for (int i = 0; i < entryChildren.length; i++) {
+ if (entryChildren[i] instanceof LogEntry) {
+
+ LogEntry logEntry = (LogEntry) entryChildren[i];
+
+ if (logEntry == thisEntry) {
+ childIndex = i;
+ return;
+ }
+ }
+ }
+
+ childIndex = 0;
+ }
+
+ private boolean isChild(AbstractEntry entry) {
+ return entry.getParent(entry) != null;
+ }
+
+ public boolean isOpen() {
+ return isOpen;
+ }
+
+ @Override
+ public int open() {
+ isOpen = true;
+ if (sashWeights == null) {
+ int a, b, c;
+ int height = getSashForm().getClientArea().height;
+ if (height < 250) {
+ a = b = c = height / 3;
+ } else {
+ a = 100; // Details section needs about 100
+ c = 100; // Text area gets 100
+ b = height - a - c; // Stack trace should take up majority of room
+ }
+ sashWeights = new int[] { a, b, c };
+ }
+ getSashForm().setWeights(sashWeights);
+ return super.open();
+ }
+
+ @Override
+ public boolean close() {
+ if (clipboard != null) {
+ clipboard.dispose();
+ clipboard = null;
+ }
+ storeSettings();
+ isOpen = false;
+ labelProvider.disconnect(this);
+ return super.close();
+ }
+
+ @Override
+ public void create() {
+ super.create();
+
+ // dialog location
+ if (dialogLocation != null)
+ getShell().setLocation(dialogLocation);
+
+ // dialog size
+ if (dialogSize != null)
+ getShell().setSize(dialogSize);
+ else
+ getShell().setSize(500, 550);
+
+ applyDialogFont(buttonBar);
+ getButton(IDialogConstants.OK_ID).setFocus();
+ }
+
+ @Override
+ protected void buttonPressed(int buttonId) {
+ if (IDialogConstants.OK_ID == buttonId)
+ okPressed();
+ else if (IDialogConstants.CANCEL_ID == buttonId)
+ cancelPressed();
+ else if (IDialogConstants.BACK_ID == buttonId)
+ backPressed();
+ else if (IDialogConstants.NEXT_ID == buttonId)
+ nextPressed();
+ else if (COPY_ID == buttonId)
+ copyPressed();
+ }
+
+ protected void backPressed() {
+ if (childIndex > 0) {
+ if (isLastChild && (isChild(entry))) {
+ setEntryChildren(parentEntry);
+ isLastChild = false;
+ }
+ childIndex--;
+ entry = entryChildren[childIndex];
+ } else {
+ if (parentEntry instanceof LogEntry) {
+ entry = parentEntry;
+ if (isChild(entry)) {
+ setEntryChildren((AbstractEntry) entry.getParent(entry));
+ } else {
+ setEntryChildren();
+ }
+ resetChildIndex();
+ }
+ }
+ setEntrySelectionInTable();
+ }
+
+ protected void nextPressed() {
+ if (childIndex < entryChildren.length - 1) {
+ childIndex++;
+ entry = entryChildren[childIndex];
+ isLastChild = childIndex == entryChildren.length - 1;
+ } else if (isChild(entry) && isLastChild && !isAtEndOfLog) {
+ findNextSelectedChild(entry);
+ } else { // at end of list but can branch into child elements - bug 58083
+ setEntryChildren(entry);
+ isAtEndOfLog = entryChildren.length == 0;
+ isLastChild = entryChildren.length == 0;
+ if (entryChildren.length > 0) {
+ entry = entryChildren[0];
+ }
+ }
+ setEntrySelectionInTable();
+ }
+
+ protected void copyPressed() {
+ try (StringWriter writer = new StringWriter(); PrintWriter pwriter = new PrintWriter(writer)) {
+ entry.write(pwriter);
+ pwriter.flush();
+ String textVersion = writer.toString();
+ // set the clipboard contents
+ clipboard.setContents(new Object[] { textVersion }, new Transfer[] { TextTransfer.getInstance() });
+ } catch (IOException e) {
+ // do nothing
+ }
+ }
+
+ public void setComparator(Comparator comparator) {
+ this.comparator = comparator;
+ updateProperties();
+ }
+
+ private void setComparator(byte sortType, final int sortOrder) {
+ if (sortType == LogView.DATE) {
+ comparator = (e1, e2) -> {
+ Date date1 = ((LogEntry) e1).getDate();
+ Date date2 = ((LogEntry) e2).getDate();
+ if (sortOrder == LogView.ASCENDING)
+ return date1.getTime() < date2.getTime() ? LogView.DESCENDING : LogView.ASCENDING;
+ return date1.getTime() > date2.getTime() ? LogView.DESCENDING : LogView.ASCENDING;
+ };
+ } else if (sortType == LogView.PLUGIN) {
+ comparator = (e1, e2) -> {
+ LogEntry entry1 = (LogEntry) e1;
+ LogEntry entry2 = (LogEntry) e2;
+ return collator.compare(entry1.getPluginId(), entry2.getPluginId()) * sortOrder;
+ };
+ } else {
+ comparator = (e1, e2) -> {
+ LogEntry entry1 = (LogEntry) e1;
+ LogEntry entry2 = (LogEntry) e2;
+ return collator.compare(entry1.getMessage(), entry2.getMessage()) * sortOrder;
+ };
+ }
+ }
+
+ public void resetSelection(IAdaptable selectedEntry, byte sortType, int sortOrder) {
+ setComparator(sortType, sortOrder);
+ resetSelection(selectedEntry);
+ }
+
+ public void resetSelection(IAdaptable selectedEntry) {
+ if (entry.equals(selectedEntry)) {
+ updateProperties();
+ return;
+ }
+ if (selectedEntry instanceof AbstractEntry) {
+ entry = (AbstractEntry) selectedEntry;
+ initialize();
+ updateProperties();
+ }
+ }
+
+ public void resetButtons() {
+ backButton.setEnabled(false);
+ nextButton.setEnabled(false);
+ }
+
+ private void setEntrySelectionInTable() {
+ ISelection selection = new StructuredSelection(entry);
+ provider.setSelection(selection);
+ }
+
+ public void updateProperties() {
+ if (isChild(entry)) {
+ parentEntry = (AbstractEntry) entry.getParent(entry);
+ setEntryChildren(parentEntry);
+ resetChildIndex();
+ if (childIndex == entryChildren.length - 1)
+ isLastChild = true;
+ }
+
+ if (entry instanceof LogEntry) {
+ LogEntry logEntry = (LogEntry) entry;
+
+ String strDate = dateFormat.format(logEntry.getDate());
+ dateLabel.setText(strDate);
+ plugInIdLabel.setText(logEntry.getPluginId());
+ severityImageLabel.setImage(labelProvider.getColumnImage(entry, 0));
+ severityLabel.setText(logEntry.getSeverityText());
+ msgText.setText(logEntry.getMessage() != null ? logEntry.getMessage() : ""); //$NON-NLS-1$
+ String stack = logEntry.getStack();
+
+ if (stack != null) {
+ stack = filterStack(stack);
+ stackTraceText.setText(stack);
+ } else {
+ stackTraceText.setText(Messages.EventDetailsDialog_noStack);
+ }
+
+ if (logEntry.getSession() != null) {
+ String session = logEntry.getSession().getSessionData();
+ if (session != null) {
+ sessionDataText.setText(session);
+ }
+ }
+
+ } else {
+ dateLabel.setText(""); //$NON-NLS-1$
+ severityImageLabel.setImage(null);
+ severityLabel.setText(""); //$NON-NLS-1$
+ msgText.setText(""); //$NON-NLS-1$
+ stackTraceText.setText(""); //$NON-NLS-1$
+ sessionDataText.setText(""); //$NON-NLS-1$
+ }
+
+ updateButtons();
+ }
+
+ private void updateButtons() {
+ boolean isAtEnd = childIndex == entryChildren.length - 1;
+ if (isChild(entry)) {
+ boolean canGoToParent = (entry.getParent(entry) instanceof LogEntry);
+ backButton.setEnabled((childIndex > 0) || canGoToParent);
+ nextButton.setEnabled(nextChildExists(entry, parentEntry, entryChildren) || entry.hasChildren()
+ || !isLastChild || !isAtEnd);
+ } else {
+ backButton.setEnabled(childIndex != 0);
+ nextButton.setEnabled(!isAtEnd || entry.hasChildren());
+ }
+ }
+
+ private void findNextSelectedChild(AbstractEntry originalEntry) {
+ if (isChild(parentEntry)) {
+ // we're at the end of the child list; find next parent
+ // to select. If the parent is a child at the end of the child
+ // list, find its next parent entry to select, etc.
+
+ entry = parentEntry;
+ setEntryChildren((AbstractEntry) parentEntry.getParent(parentEntry));
+ parentEntry = (AbstractEntry) parentEntry.getParent(parentEntry);
+ resetChildIndex();
+ isLastChild = childIndex == entryChildren.length - 1;
+ if (isLastChild) {
+ findNextSelectedChild(originalEntry);
+ } else {
+ nextPressed();
+ }
+ } else if (parentEntry instanceof LogEntry) {
+ entry = parentEntry;
+ setEntryChildren();
+ resetChildIndex();
+ isLastChild = childIndex == entryChildren.length - 1;
+ if (isLastChild) {
+ if (isChild(entry)) {
+ findNextSelectedChild(originalEntry);
+ } else {
+ entry = originalEntry;
+ isAtEndOfLog = true;
+ nextPressed();
+ }
+ } else {
+ nextPressed();
+ }
+ } else {
+ entry = originalEntry;
+ isAtEndOfLog = true;
+ nextPressed();
+ }
+ }
+
+ private boolean nextChildExists(AbstractEntry originalEntry, AbstractEntry originalParent,
+ AbstractEntry[] originalEntries) {
+ if (isChild(parentEntry)) {
+ // we're at the end of the child list; find next parent
+ // to select. If the parent is a child at the end of the child
+ // list, find its next parent entry to select, etc.
+
+ entry = parentEntry;
+ parentEntry = (AbstractEntry) entry.getParent(entry);
+ setEntryChildren(parentEntry);
+ resetChildIndex();
+ if (childIndex == entryChildren.length - 1) {
+ return nextChildExists(originalEntry, originalParent, originalEntries);
+ }
+ entry = originalEntry;
+ parentEntry = originalParent;
+ entryChildren = originalEntries;
+ resetChildIndex();
+ return true;
+ } else if (parentEntry instanceof LogEntry) {
+ entry = parentEntry;
+ setEntryChildren();
+ childIndex = -1;
+ resetChildIndex();
+ if ((childIndex != -1) && (childIndex < entryChildren.length - 1)) {
+ entry = originalEntry;
+ parentEntry = originalParent;
+ entryChildren = originalEntries;
+ resetChildIndex();
+ return true;
+ }
+ }
+ entry = originalEntry;
+ parentEntry = originalParent;
+ entryChildren = originalEntries;
+ resetChildIndex();
+ return false;
+
+ }
+
+ /**
+ * Sets entry children (Prev-Next navigable) to top-level elements
+ */
+ private void setEntryChildren() {
+ AbstractEntry[] children = getElements();
+
+ if (comparator != null)
+ Arrays.sort(children, comparator);
+ entryChildren = new AbstractEntry[children.length];
+
+ System.arraycopy(children, 0, entryChildren, 0, children.length);
+ }
+
+ /**
+ * Sets entry children (Prev-Next navigable) to children of given entry
+ */
+ private void setEntryChildren(AbstractEntry entry) {
+ Object[] children = entry.getChildren(entry);
+
+ if (comparator != null)
+ Arrays.sort(children, comparator);
+
+ List<AbstractEntry> result = new ArrayList<>();
+ for (Object element : children) {
+ if (element instanceof AbstractEntry) {
+ result.add((AbstractEntry) element);
+ }
+ }
+
+ entryChildren = result.toArray(new AbstractEntry[result.size()]);
+ }
+
+ public SashForm getSashForm() {
+ return sashForm;
+ }
+
+ @Override
+ protected Control createDialogArea(Composite parent) {
+ Composite container = new Composite(parent, SWT.NONE);
+ GridLayout layout = new GridLayout();
+ layout.numColumns = 1;
+ container.setLayout(layout);
+ GridData gd = new GridData(GridData.FILL_BOTH);
+ container.setLayoutData(gd);
+
+ createSashForm(container);
+ createDetailsSection(getSashForm());
+ createStackSection(getSashForm());
+ createSessionSection(getSashForm());
+
+ updateProperties();
+ Dialog.applyDialogFont(container);
+ return container;
+ }
+
+ private void createSashForm(Composite parent) {
+ sashForm = new SashForm(parent, SWT.VERTICAL);
+ GridLayout layout = new GridLayout();
+ layout.marginHeight = layout.marginWidth = 0;
+ sashForm.setLayout(layout);
+ sashForm.setLayoutData(new GridData(GridData.FILL_BOTH));
+ sashForm.setSashWidth(10);
+ }
+
+ private void createToolbarButtonBar(Composite parent) {
+ Composite comp = new Composite(parent, SWT.NONE);
+ GridLayout layout = new GridLayout();
+ layout.marginWidth = layout.marginHeight = 0;
+ // layout.numColumns = 1;
+ comp.setLayout(layout);
+ comp.setLayoutData(new GridData(GridData.FILL_VERTICAL));
+ ((GridData) comp.getLayoutData()).verticalAlignment = SWT.BOTTOM;
+
+ Composite container = new Composite(comp, SWT.NONE);
+ layout = new GridLayout();
+ layout.marginWidth = 0;
+ layout.marginHeight = 0;
+ container.setLayout(layout);
+ container.setLayoutData(new GridData(GridData.FILL_BOTH));
+
+ backButton = createButton(container, IDialogConstants.BACK_ID, "", false); //$NON-NLS-1$
+ GridData gd = new GridData(GridData.FILL_HORIZONTAL);
+ backButton.setLayoutData(gd);
+ backButton.setToolTipText(Messages.EventDetailsDialog_previous);
+ backButton.setImage(SharedImages.getImage(SharedImages.DESC_PREV_EVENT));
+ backButton.getAccessible().addAccessibleListener(new AccessibleAdapter() {
+ @Override
+ public void getName(AccessibleEvent e) {
+ e.result = Messages.EventDetailsDialog_previous;
+ }
+ });
+
+ copyButton = createButton(container, COPY_ID, "", false); //$NON-NLS-1$
+ gd = new GridData();
+ copyButton.setLayoutData(gd);
+ copyButton.setImage(PlatformUI.getWorkbench().getSharedImages().getImage(ISharedImages.IMG_TOOL_COPY));
+ copyButton.setToolTipText(Messages.EventDetailsDialog_copy);
+ copyButton.getAccessible().addAccessibleListener(new AccessibleAdapter() {
+ @Override
+ public void getName(AccessibleEvent e) {
+ e.result = Messages.EventDetailsDialog_copy;
+ }
+ });
+
+ nextButton = createButton(container, IDialogConstants.NEXT_ID, "", false); //$NON-NLS-1$
+ gd = new GridData();
+ nextButton.setLayoutData(gd);
+ nextButton.setToolTipText(Messages.EventDetailsDialog_next);
+ nextButton.setImage(SharedImages.getImage(SharedImages.DESC_NEXT_EVENT));
+ nextButton.getAccessible().addAccessibleListener(new AccessibleAdapter() {
+ @Override
+ public void getName(AccessibleEvent e) {
+ e.result = Messages.EventDetailsDialog_next;
+ }
+ });
+
+ Button button = new Button(container, SWT.NONE);
+ button.setToolTipText(Messages.EventDetailsDialog_ShowFilterDialog);
+ button.setImage(SharedImages.getImage(SharedImages.DESC_FILTER));
+ gd = new GridData();
+ gd.horizontalAlignment = SWT.RIGHT;
+ button.setLayoutData(gd);
+ button.addSelectionListener(new SelectionAdapter() {
+ @Override
+ public void widgetSelected(SelectionEvent e) {
+ FilterDialog dialog = new FilterDialog(getShell(), memento);
+ dialog.create();
+ dialog.getShell().setText(Messages.EventDetailsDialog_FilterDialog);
+ if (dialog.open() == Window.OK) {
+ // update filters and currently displayed stack trace
+ stackFilterPatterns = getFilters();
+ logView.reloadLog();
+ initialize();
+ }
+ updateProperties();
+ }
+ });
+ button.getAccessible().addAccessibleListener(new AccessibleAdapter() {
+ @Override
+ public void getName(AccessibleEvent e) {
+ e.result = Messages.EventDetailsDialog_FilterDialog;
+ }
+ });
+
+ // set numColumns at the end, after all createButton() calls, which change this
+ // value
+ layout.numColumns = 2;
+ }
+
+ @Override
+ protected void createButtonsForButtonBar(Composite parent) {
+ // create OK button only by default
+ createButton(parent, IDialogConstants.OK_ID, IDialogConstants.OK_LABEL, true);
+ }
+
+ private void createDetailsSection(Composite parent) {
+ Composite container = new Composite(parent, SWT.NONE);
+ GridLayout layout = new GridLayout();
+ layout.marginWidth = layout.marginHeight = 0;
+ layout.numColumns = 2;
+ container.setLayout(layout);
+ GridData data = new GridData(GridData.FILL_HORIZONTAL);
+ data.heightHint = 200;
+ container.setLayoutData(data);
+
+ createTextSection(container);
+ createToolbarButtonBar(container);
+ }
+
+ private void createTextSection(Composite parent) {
+ Composite textContainer = new Composite(parent, SWT.NONE);
+ GridLayout layout = new GridLayout();
+ layout.numColumns = 3;
+ layout.marginHeight = layout.marginWidth = 0;
+ textContainer.setLayout(layout);
+ textContainer.setLayoutData(new GridData(GridData.FILL_BOTH));
+
+ Label label = new Label(textContainer, SWT.NONE);
+ label.setText(Messages.EventDetailsDialog_plugIn);
+ plugInIdLabel = new Label(textContainer, SWT.NONE);
+ GridData gd = new GridData(GridData.FILL_HORIZONTAL);
+ gd.horizontalSpan = 2;
+ plugInIdLabel.setLayoutData(gd);
+
+ label = new Label(textContainer, SWT.NONE);
+ label.setText(Messages.EventDetailsDialog_severity);
+ severityImageLabel = new Label(textContainer, SWT.NONE);
+ severityLabel = new Label(textContainer, SWT.NONE);
+ gd = new GridData(GridData.FILL_HORIZONTAL);
+ severityLabel.setLayoutData(gd);
+
+ label = new Label(textContainer, SWT.NONE);
+ label.setText(Messages.EventDetailsDialog_date);
+ dateLabel = new Label(textContainer, SWT.NONE);
+ gd = new GridData(GridData.FILL_HORIZONTAL);
+ gd.horizontalSpan = 2;
+ dateLabel.setLayoutData(gd);
+
+ label = new Label(textContainer, SWT.NONE);
+ label.setText(Messages.EventDetailsDialog_message);
+ gd = new GridData(GridData.VERTICAL_ALIGN_BEGINNING);
+ label.setLayoutData(gd);
+ msgText = new Text(textContainer, SWT.MULTI | SWT.V_SCROLL | SWT.H_SCROLL | SWT.BORDER);
+ msgText.setEditable(false);
+ gd = new GridData(GridData.FILL_BOTH | GridData.GRAB_HORIZONTAL);
+ gd.horizontalSpan = 2;
+ gd.grabExcessVerticalSpace = true;
+ msgText.setLayoutData(gd);
+ }
+
+ private void createStackSection(Composite parent) {
+ Composite container = new Composite(parent, SWT.NONE);
+ GridLayout layout = new GridLayout(2, false);
+ layout.marginHeight = 0;
+ layout.marginWidth = 0;
+ container.setLayout(layout);
+ GridData gd = new GridData(GridData.FILL_BOTH);
+ gd.heightHint = 200;
+ container.setLayoutData(gd);
+
+ Label label = new Label(container, SWT.NONE);
+ label.setText(Messages.EventDetailsDialog_exception);
+ gd = new GridData();
+ gd.verticalAlignment = SWT.BOTTOM;
+ label.setLayoutData(gd);
+
+ stackTraceText = new Text(container, SWT.MULTI | SWT.V_SCROLL | SWT.H_SCROLL | SWT.BORDER);
+ gd = new GridData(GridData.FILL_BOTH | GridData.GRAB_HORIZONTAL);
+ gd.grabExcessHorizontalSpace = true;
+ gd.horizontalSpan = 2;
+ stackTraceText.setLayoutData(gd);
+ stackTraceText.setEditable(false);
+ }
+
+ private void createSessionSection(Composite parent) {
+ Composite container = new Composite(parent, SWT.NONE);
+ GridLayout layout = new GridLayout();
+ layout.marginHeight = 0;
+ layout.marginWidth = 0;
+ container.setLayout(layout);
+ GridData gd = new GridData(GridData.FILL_HORIZONTAL);
+ gd.heightHint = 100;
+ container.setLayoutData(gd);
+
+ Label label = new Label(container, SWT.NONE);
+ label.setText(Messages.EventDetailsDialog_session);
+ gd = new GridData(GridData.FILL_HORIZONTAL);
+ label.setLayoutData(gd);
+ sessionDataText = new Text(container, SWT.BORDER | SWT.V_SCROLL | SWT.H_SCROLL);
+ gd = new GridData(GridData.FILL_BOTH | GridData.GRAB_HORIZONTAL);
+ gd.grabExcessHorizontalSpace = true;
+ sessionDataText.setLayoutData(gd);
+ sessionDataText.setEditable(false);
+ }
+
+ /**
+ * Loads filters from preferences.
+ *
+ * @return filters from preferences or empty array
+ *
+ * @since 3.4
+ */
+ private String[] getFilters() {
+
+ Boolean filterEnabled = memento.getBoolean(FILTER_ENABLED);
+
+ String filtersString = memento.getString(FILTER_LIST);
+
+ if ((filterEnabled == null) || (filterEnabled.booleanValue() == false) || filtersString == null) {
+ return new String[0];
+ }
+
+ StringTokenizer st = new StringTokenizer(filtersString, ";"); //$NON-NLS-1$
+ List<String> filters = new ArrayList<>();
+ while (st.hasMoreElements()) {
+ String filter = st.nextToken();
+ filters.add(filter);
+ }
+
+ return filters.toArray(new String[filters.size()]);
+ }
+
+ /**
+ * Filters stack trace. Every stack trace line is compared against all patterns.
+ * If line contains any of pattern strings, it's excluded from output.
+ *
+ * @returns filtered stack trace
+ * @since 3.4
+ */
+ private String filterStack(String stack) {
+ if (stackFilterPatterns.length == 0) {
+ return stack;
+ }
+
+ StringTokenizer st = new StringTokenizer(stack, "\n"); //$NON-NLS-1$
+ StringBuilder result = new StringBuilder();
+ while (st.hasMoreTokens()) {
+ String stackElement = st.nextToken();
+
+ boolean filtered = false;
+ int i = 0;
+ while ((!filtered) && (i < stackFilterPatterns.length)) {
+ filtered = stackElement.indexOf(stackFilterPatterns[i]) >= 0;
+ i++;
+ }
+
+ if (!filtered) {
+ result.append(stackElement).append("\n"); //$NON-NLS-1$
+ }
+ }
+
+ return result.toString();
+ }
+
+ // --------------- configuration handling --------------
+
+ /**
+ * Stores the current state in the dialog settings.
+ *
+ * @since 2.0
+ */
+ private void storeSettings() {
+ writeConfiguration();
+ }
+
+ /**
+ * Returns the dialog settings object used to share state between several event
+ * detail dialogs.
+ *
+ * @return the dialog settings to be used
+ */
+ private IDialogSettings getDialogSettings() {
+ IDialogSettings settings = Activator.getDefault().getDialogSettings();
+ IDialogSettings dialogSettings = settings.getSection(getClass().getName());
+ if (dialogSettings == null)
+ dialogSettings = settings.addNewSection(getClass().getName());
+ return dialogSettings;
+ }
+
+ /**
+ * Initializes itself from the dialog settings with the same state as at the
+ * previous invocation.
+ */
+ private void readConfiguration() {
+ IDialogSettings s = getDialogSettings();
+ try {
+ int x = s.getInt("x"); //$NON-NLS-1$
+ int y = s.getInt("y"); //$NON-NLS-1$
+ dialogLocation = new Point(x, y);
+
+ x = s.getInt("width"); //$NON-NLS-1$
+ y = s.getInt("height"); //$NON-NLS-1$
+ dialogSize = new Point(x, y);
+
+ sashWeights = new int[3];
+ sashWeights[0] = s.getInt("sashWidth1"); //$NON-NLS-1$
+ sashWeights[1] = s.getInt("sashWidth2"); //$NON-NLS-1$
+ sashWeights[2] = s.getInt("sashWidth3"); //$NON-NLS-1$
+ } catch (NumberFormatException e) {
+ dialogLocation = null;
+ dialogSize = null;
+ sashWeights = null;
+ }
+ }
+
+ private void writeConfiguration() {
+ IDialogSettings s = getDialogSettings();
+ Point location = getShell().getLocation();
+ s.put("x", location.x); //$NON-NLS-1$
+ s.put("y", location.y); //$NON-NLS-1$
+
+ Point size = getShell().getSize();
+ s.put("width", size.x); //$NON-NLS-1$
+ s.put("height", size.y); //$NON-NLS-1$
+
+ sashWeights = getSashForm().getWeights();
+ s.put("sashWidth1", sashWeights[0]); //$NON-NLS-1$
+ s.put("sashWidth2", sashWeights[1]); //$NON-NLS-1$
+ s.put("sashWidth3", sashWeights[2]); //$NON-NLS-1$
+ }
+
+ /**
+ * Utility method to get all top level elements of the Log View
+ *
+ * @return top level elements of the Log View
+ */
+ private AbstractEntry[] getElements() {
+ return (AbstractEntry[]) ((ITreeContentProvider) provider.getContentProvider()).getElements(null);
+ }
+}
diff --git a/bundles/org.eclipse.ui.views.log/src/org/eclipse/ui/internal/views/log/EventDetailsDialogAction.java b/bundles/org.eclipse.ui.views.log/src/org/eclipse/ui/internal/views/log/EventDetailsDialogAction.java
new file mode 100644
index 0000000..ede8fa3
--- /dev/null
+++ b/bundles/org.eclipse.ui.views.log/src/org/eclipse/ui/internal/views/log/EventDetailsDialogAction.java
@@ -0,0 +1,104 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 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
+ * Jacek Pospychala <jacek.pospychala@pl.ibm.com> - bugs 202583, 207344
+ *******************************************************************************/
+package org.eclipse.ui.internal.views.log;
+
+import java.util.Comparator;
+import org.eclipse.core.runtime.Assert;
+import org.eclipse.core.runtime.IAdaptable;
+import org.eclipse.jface.viewers.ISelectionProvider;
+import org.eclipse.swt.widgets.Control;
+import org.eclipse.ui.IMemento;
+import org.eclipse.ui.actions.SelectionProviderAction;
+
+/**
+ * Opens EventDetailsDialog
+ */
+public class EventDetailsDialogAction extends SelectionProviderAction {
+
+ private LogView logView;
+ /**
+ * The control that the dialog should appear on top of.
+ */
+ private Control control;
+ private ISelectionProvider provider;
+ private EventDetailsDialog propertyDialog;
+ private Comparator comparator;
+ private IMemento memento;
+
+ /**
+ * Creates a new action for opening a property dialog
+ * on the elements from the given selection provider
+ * @param control - the control that the details dialog should show up on
+ * @param provider - the selection provider whose elements
+ * @param memento - memento with EventDetails dialog options
+ * the property dialog will describe
+ */
+ public EventDetailsDialogAction(LogView logView, Control control, ISelectionProvider provider, IMemento memento) {
+ super(provider, Messages.EventDetailsDialog_title);
+ this.logView = logView;
+ Assert.isNotNull(control);
+ this.control = control;
+ this.provider = provider;
+ this.memento = memento;
+ }
+
+ public boolean resetSelection(byte sortType, int sortOrder) {
+ IAdaptable element = (IAdaptable) getStructuredSelection().getFirstElement();
+ if (element == null)
+ return false;
+ if (propertyDialog != null && propertyDialog.isOpen()) {
+ propertyDialog.resetSelection(element, sortType, sortOrder);
+ return true;
+ }
+ return false;
+ }
+
+ public void resetSelection() {
+ IAdaptable element = (IAdaptable) getStructuredSelection().getFirstElement();
+ if ((element == null) || (!(element instanceof LogEntry)))
+ return;
+ if (propertyDialog != null && propertyDialog.isOpen())
+ propertyDialog.resetSelection(element);
+ }
+
+ public void resetDialogButtons() {
+ if (propertyDialog != null && propertyDialog.isOpen())
+ propertyDialog.resetButtons();
+ }
+
+ public void setComparator(Comparator comparator) {
+ this.comparator = comparator;
+ if (propertyDialog != null && propertyDialog.isOpen())
+ propertyDialog.setComparator(comparator);
+ }
+
+ @Override
+ public void run() {
+ if (propertyDialog != null && propertyDialog.isOpen()) {
+ resetSelection();
+ return;
+ }
+
+ //get initial selection
+ IAdaptable element = (IAdaptable) getStructuredSelection().getFirstElement();
+ if ((element == null) || (!(element instanceof LogEntry)))
+ return;
+
+ propertyDialog = new EventDetailsDialog(control.getShell(), logView, element, provider, comparator, memento);
+ propertyDialog.create();
+ propertyDialog.getShell().setText(Messages.EventDetailsDialog_title);
+ propertyDialog.open();
+ }
+}
diff --git a/bundles/org.eclipse.ui.views.log/src/org/eclipse/ui/internal/views/log/FilterDialog.java b/bundles/org.eclipse.ui.views.log/src/org/eclipse/ui/internal/views/log/FilterDialog.java
new file mode 100644
index 0000000..533cacf
--- /dev/null
+++ b/bundles/org.eclipse.ui.views.log/src/org/eclipse/ui/internal/views/log/FilterDialog.java
@@ -0,0 +1,326 @@
+/*******************************************************************************
+ * Copyright (c) 2003, 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
+ * Lars Vogel <Lars.Vogel@vogella.com> - Bug 485843
+ *******************************************************************************/
+package org.eclipse.ui.internal.views.log;
+
+import java.util.StringTokenizer;
+import org.eclipse.jface.dialogs.*;
+import org.eclipse.jface.dialogs.Dialog;
+import org.eclipse.jface.window.Window;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.events.SelectionAdapter;
+import org.eclipse.swt.events.SelectionEvent;
+import org.eclipse.swt.layout.GridData;
+import org.eclipse.swt.layout.GridLayout;
+import org.eclipse.swt.widgets.*;
+import org.eclipse.swt.widgets.Group;
+import org.eclipse.ui.IMemento;
+import org.eclipse.ui.PlatformUI;
+
+public class FilterDialog extends TrayDialog {
+
+ Button okButton;
+
+ // entries count limit
+ private Button limit;
+ Text limitText;
+ Text maxLogTailSizeText;
+
+ // entry types filter
+ private Button errorCheckbox;
+ private Button warningCheckbox;
+ private Button infoCheckbox;
+ private Button okCheckbox;
+
+ // show all sessions
+ private Button showAllButton;
+
+ // filter stack trace elements in EventDetailsDialog
+ private Button filterEnabled;
+ private Button addFilter;
+ private Button removeFilter;
+ private List filterList;
+
+ private IMemento memento;
+
+ public FilterDialog(Shell parentShell, IMemento memento) {
+ super(parentShell);
+ this.memento = memento;
+ }
+
+ @Override
+ protected void configureShell(Shell newShell) {
+ super.configureShell(newShell);
+ PlatformUI.getWorkbench().getHelpSystem().setHelp(newShell, IHelpContextIds.LOG_FILTER);
+ }
+
+ @Override
+ protected Control createDialogArea(Composite parent) {
+ Composite container = (Composite) super.createDialogArea(parent);
+ createEventTypesGroup(container);
+ createLimitSection(container);
+ createSessionSection(container);
+ createFilterSection(container);
+
+ Dialog.applyDialogFont(container);
+ return container;
+ }
+
+ private void createEventTypesGroup(Composite parent) {
+ Group group = new Group(parent, SWT.NONE);
+ group.setLayout(new GridLayout());
+ GridData gd = new GridData(GridData.FILL_HORIZONTAL);
+ gd.widthHint = 275;
+ group.setLayoutData(gd);
+ group.setText(Messages.LogView_FilterDialog_eventTypes);
+
+ okCheckbox = new Button(group, SWT.CHECK);
+ okCheckbox.setText(Messages.LogView_FilterDialog_ok);
+ okCheckbox.setSelection(memento.getString(LogView.P_LOG_OK).equals("true")); //$NON-NLS-1$
+
+ infoCheckbox = new Button(group, SWT.CHECK);
+ infoCheckbox.setText(Messages.LogView_FilterDialog_information);
+ infoCheckbox.setSelection(memento.getString(LogView.P_LOG_INFO).equals("true")); //$NON-NLS-1$
+
+ warningCheckbox = new Button(group, SWT.CHECK);
+ warningCheckbox.setText(Messages.LogView_FilterDialog_warning);
+ warningCheckbox.setSelection(memento.getString(LogView.P_LOG_WARNING).equals("true")); //$NON-NLS-1$
+
+ errorCheckbox = new Button(group, SWT.CHECK);
+ errorCheckbox.setText(Messages.LogView_FilterDialog_error);
+ errorCheckbox.setSelection(memento.getString(LogView.P_LOG_ERROR).equals("true")); //$NON-NLS-1$
+ }
+
+ private void createLimitSection(Composite parent) {
+ Composite comp = new Composite(parent, SWT.NONE);
+ GridLayout layout = new GridLayout();
+ layout.numColumns = 2;
+ comp.setLayout(layout);
+ comp.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
+
+ limit = new Button(comp, SWT.CHECK);
+ limit.setText(Messages.LogView_FilterDialog_limitTo);
+ limit.setSelection(memento.getString(LogView.P_USE_LIMIT).equals("true")); //$NON-NLS-1$
+ limit.addSelectionListener(new SelectionAdapter() {
+ @Override
+ public void widgetSelected(SelectionEvent e) {
+ limitText.setEnabled(((Button) e.getSource()).getSelection());
+ }
+ });
+
+ limitText = new Text(comp, SWT.BORDER);
+ limitText.addVerifyListener(e -> {
+ if (Character.isLetter(e.character)) {
+ e.doit = false;
+ }
+ });
+ limitText.addModifyListener(e -> {
+ try {
+ if (okButton == null)
+ return;
+ int value = Integer.parseInt(limitText.getText());
+ okButton.setEnabled(value > 0);
+ } catch (NumberFormatException e1) {
+ okButton.setEnabled(false);
+ }
+ });
+ limitText.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
+ limitText.setText(memento.getString(LogView.P_LOG_LIMIT));
+ limitText.setEnabled(limit.getSelection());
+
+ Label maxLogTailSizeLabel = new Label(comp, SWT.NONE);
+ maxLogTailSizeLabel.setText(Messages.LogView_FilterDialog_maxLogTailSize);
+
+ maxLogTailSizeText = new Text(comp, SWT.BORDER);
+ maxLogTailSizeText.addVerifyListener(e -> {
+ if (Character.isLetter(e.character)) {
+ e.doit = false;
+ }
+ });
+
+ maxLogTailSizeText.addModifyListener(e -> {
+ try {
+ if (okButton == null)
+ return;
+ int value = Integer.parseInt(maxLogTailSizeText.getText());
+ okButton.setEnabled(value > 0);
+ } catch (NumberFormatException e1) {
+ okButton.setEnabled(false);
+ }
+ });
+ maxLogTailSizeText.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
+ maxLogTailSizeText.setText(memento.getString(LogView.P_LOG_MAX_TAIL_SIZE));
+ maxLogTailSizeText.setEnabled(limit.getSelection());
+ }
+
+ private void createSessionSection(Composite parent) {
+ Composite container = new Composite(parent, SWT.NONE);
+ container.setLayout(new GridLayout());
+ container.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
+
+ Label label = new Label(container, SWT.NONE);
+ label.setText(Messages.LogView_FilterDialog_eventsLogged);
+
+ showAllButton = new Button(container, SWT.RADIO);
+ showAllButton.setText(Messages.LogView_FilterDialog_allSessions);
+ GridData gd = new GridData();
+ gd.horizontalIndent = 20;
+ showAllButton.setLayoutData(gd);
+
+ Button button = new Button(container, SWT.RADIO);
+ button.setText(Messages.LogView_FilterDialog_recentSession);
+ gd = new GridData();
+ gd.horizontalIndent = 20;
+ button.setLayoutData(gd);
+
+ if (memento.getString(LogView.P_SHOW_ALL_SESSIONS).equals("true")) { //$NON-NLS-1$
+ showAllButton.setSelection(true);
+ } else {
+ button.setSelection(true);
+ }
+ }
+
+ private void createFilterSection(Composite parent) {
+ Composite comp = new Composite(parent, SWT.NONE);
+ GridLayout layout = new GridLayout(2, false);
+ comp.setLayout(layout);
+ comp.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
+
+ filterEnabled = new Button(comp, SWT.CHECK);
+ filterEnabled.setText(Messages.FilterDialog_EnableFiltersCheckbox);
+ GridData gd = new GridData();
+ gd.horizontalSpan = 2;
+ filterEnabled.setLayoutData(gd);
+ filterEnabled.addSelectionListener(new SelectionAdapter() {
+ @Override
+ public void widgetSelected(SelectionEvent e) {
+ setStackTraceFilterEnabled(filterEnabled.getSelection());
+ }
+
+ });
+
+ filterList = new List(comp, SWT.BORDER | SWT.MULTI);
+ gd = new GridData(GridData.FILL_HORIZONTAL | GridData.FILL_VERTICAL);
+ gd.verticalSpan = 3;
+ gd.widthHint = 280;
+ gd.horizontalIndent = 20;
+ filterList.setLayoutData(gd);
+ filterList.addSelectionListener(new SelectionAdapter() {
+ @Override
+ public void widgetSelected(SelectionEvent e) {
+ removeFilter.setEnabled(true);
+ }
+ });
+
+ addFilter = new Button(comp, SWT.NONE);
+ gd = new GridData(GridData.FILL_HORIZONTAL);
+ addFilter.setLayoutData(gd);
+ addFilter.setText(Messages.FilterDialog_Add);
+ addFilter.addSelectionListener(new SelectionAdapter() {
+ @Override
+ public void widgetSelected(SelectionEvent e) {
+ addFilter();
+ }
+ });
+
+ removeFilter = new Button(comp, SWT.NONE);
+ gd = new GridData(GridData.FILL_HORIZONTAL);
+ removeFilter.setLayoutData(gd);
+ removeFilter.setText(Messages.FilterDialog_Remove);
+ removeFilter.setEnabled(false);
+ removeFilter.addSelectionListener(new SelectionAdapter() {
+ @Override
+ public void widgetSelected(SelectionEvent e) {
+ removeFilter();
+ }
+ });
+
+ // load preferences
+ Boolean enable = memento.getBoolean(EventDetailsDialog.FILTER_ENABLED);
+ enable = enable == null ? Boolean.FALSE : enable;
+
+ filterEnabled.setSelection(enable.booleanValue());
+ setStackTraceFilterEnabled(enable.booleanValue());
+
+ String filters = memento.getString(EventDetailsDialog.FILTER_LIST);
+ if (filters != null) {
+ StringTokenizer st = new StringTokenizer(filters, ";"); //$NON-NLS-1$
+ while (st.hasMoreElements()) {
+ filterList.add(st.nextToken());
+ }
+ }
+ }
+
+ private void addFilter() {
+ IInputValidator validator = newText -> newText.indexOf(';') >= 0
+ ? Messages.FilterDialog_FilterShouldntContainSemicolon
+ : null;
+ InputDialog dialog = new InputDialog(getShell(), Messages.FilterDialog_AddFilterTitle, Messages.FilterDialog_AddFliterLabel, null, validator);
+ if (dialog.open() == Window.OK) {
+ String value = dialog.getValue().trim();
+
+ if (value.length() > 0) {
+ filterList.add(value);
+ }
+ }
+ }
+
+ private void removeFilter() {
+ String[] selected = filterList.getSelection();
+ for (String element : selected) {
+ filterList.remove(element);
+ }
+ removeFilter.setEnabled(false);
+ }
+
+ private void setStackTraceFilterEnabled(boolean enabled) {
+ filterList.setEnabled(enabled);
+ addFilter.setEnabled(enabled);
+ removeFilter.setEnabled(enabled && filterList.getSelectionIndex() != -1);
+ }
+
+ @Override
+ protected void createButtonsForButtonBar(Composite parent) {
+ okButton = createButton(parent, IDialogConstants.OK_ID, IDialogConstants.OK_LABEL, true);
+ createButton(parent, IDialogConstants.CANCEL_ID, IDialogConstants.CANCEL_LABEL, false);
+ }
+
+ @Override
+ protected void okPressed() {
+ memento.putString(LogView.P_LOG_OK, okCheckbox.getSelection() ? "true" : "false"); //$NON-NLS-1$ //$NON-NLS-2$
+ memento.putString(LogView.P_LOG_INFO, infoCheckbox.getSelection() ? "true" : "false"); //$NON-NLS-1$ //$NON-NLS-2$
+ memento.putString(LogView.P_LOG_WARNING, warningCheckbox.getSelection() ? "true" : "false"); //$NON-NLS-1$ //$NON-NLS-2$
+ memento.putString(LogView.P_LOG_ERROR, errorCheckbox.getSelection() ? "true" : "false"); //$NON-NLS-1$ //$NON-NLS-2$
+ memento.putString(LogView.P_LOG_LIMIT, limitText.getText());
+ memento.putString(LogView.P_USE_LIMIT, limit.getSelection() ? "true" : "false"); //$NON-NLS-1$ //$NON-NLS-2$
+ memento.putString(LogView.P_LOG_MAX_TAIL_SIZE, maxLogTailSizeText.getText());
+ memento.putString(LogView.P_SHOW_ALL_SESSIONS, showAllButton.getSelection() ? "true" : "false"); //$NON-NLS-1$ //$NON-NLS-2$
+
+ // store Event Dialog stack trace filter preferences
+ memento.putBoolean(EventDetailsDialog.FILTER_ENABLED, filterEnabled.getSelection());
+
+ StringBuilder sb = new StringBuilder();
+ String[] items = filterList.getItems();
+ for (int i = 0; i < items.length; i++) {
+ sb.append(items[i]);
+ if (i < items.length - 1) {
+ sb.append(";"); //$NON-NLS-1$
+ }
+ }
+ memento.putString(EventDetailsDialog.FILTER_LIST, sb.toString());
+
+ super.okPressed();
+ }
+
+}
diff --git a/bundles/org.eclipse.ui.views.log/src/org/eclipse/ui/internal/views/log/Group.java b/bundles/org.eclipse.ui.views.log/src/org/eclipse/ui/internal/views/log/Group.java
new file mode 100644
index 0000000..a6f1de2
--- /dev/null
+++ b/bundles/org.eclipse.ui.views.log/src/org/eclipse/ui/internal/views/log/Group.java
@@ -0,0 +1,47 @@
+/*******************************************************************************
+ * Copyright (c) 2007, 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
+ * Jacek Pospychala <jacek.pospychala@pl.ibm.com> - bugs 202583, 207344
+ * Benjamin Cabe <benjamin.cabe@anyware-tech.com> - bug 218648
+ * Lars Vogel <Lars.Vogel@vogella.com> - Bug 485843
+ *******************************************************************************/
+package org.eclipse.ui.internal.views.log;
+
+import java.io.PrintWriter;
+
+/**
+ * Groups other Abstract Entries under given name.
+ */
+public class Group extends AbstractEntry {
+
+ private String name;
+
+ public Group(String name) {
+ this.name = name;
+ }
+
+ @Override
+ public void write(PrintWriter writer) {
+ Object[] children = getChildren(null);
+ for (Object element : children) {
+ AbstractEntry entry = (AbstractEntry) element;
+ entry.write(writer);
+ writer.println();
+ }
+ }
+
+ @Override
+ public String toString() {
+ return name;
+ }
+
+}
\ No newline at end of file
diff --git a/bundles/org.eclipse.ui.views.log/src/org/eclipse/ui/internal/views/log/IHelpContextIds.java b/bundles/org.eclipse.ui.views.log/src/org/eclipse/ui/internal/views/log/IHelpContextIds.java
new file mode 100644
index 0000000..7936c18
--- /dev/null
+++ b/bundles/org.eclipse.ui.views.log/src/org/eclipse/ui/internal/views/log/IHelpContextIds.java
@@ -0,0 +1,23 @@
+/*******************************************************************************
+ * 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
+ *******************************************************************************/
+package org.eclipse.ui.internal.views.log;
+
+public interface IHelpContextIds {
+
+ public static final String PREFIX = "org.eclipse.ui."; //$NON-NLS-1$
+ public static final String LOG_VIEW = PREFIX + "error_log"; //$NON-NLS-1$
+ public static final String LOG_EVENTDETAILS = PREFIX + "log_eventdetails"; //$NON-NLS-1$
+ public static final String LOG_FILTER = PREFIX + "log_filter"; //$NON-NLS-1$
+
+}
diff --git a/bundles/org.eclipse.ui.views.log/src/org/eclipse/ui/internal/views/log/ILogFileProvider.java b/bundles/org.eclipse.ui.views.log/src/org/eclipse/ui/internal/views/log/ILogFileProvider.java
new file mode 100644
index 0000000..5ae1232
--- /dev/null
+++ b/bundles/org.eclipse.ui.views.log/src/org/eclipse/ui/internal/views/log/ILogFileProvider.java
@@ -0,0 +1,30 @@
+/*******************************************************************************
+ * 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.ui.internal.views.log;
+
+import java.util.Map;
+
+/**
+ * Provides log files.
+ */
+public interface ILogFileProvider {
+
+ /**
+ * Returns a Map of java.io.File log files indexed by String names.
+ *
+ * @return Map of java.io.File log files index by String names.
+ * @since 3.4
+ */
+ Map<String, String> getLogSources();
+}
\ No newline at end of file
diff --git a/bundles/org.eclipse.ui.views.log/src/org/eclipse/ui/internal/views/log/ImportLogAction.java b/bundles/org.eclipse.ui.views.log/src/org/eclipse/ui/internal/views/log/ImportLogAction.java
new file mode 100644
index 0000000..33ef3c4
--- /dev/null
+++ b/bundles/org.eclipse.ui.views.log/src/org/eclipse/ui/internal/views/log/ImportLogAction.java
@@ -0,0 +1,214 @@
+/*******************************************************************************
+ * 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
+ * Benjamin Cabe <benjamin.cabe@anyware-tech.com> - bug 218293
+ * Lars Vogel <Lars.Vogel@vogella.com> - Bug 485843
+ *******************************************************************************/
+package org.eclipse.ui.internal.views.log;
+
+import java.util.*;
+import java.util.Map.Entry;
+import org.eclipse.core.runtime.Platform;
+import org.eclipse.jface.action.*;
+import org.eclipse.swt.widgets.Control;
+import org.eclipse.swt.widgets.Menu;
+import org.eclipse.ui.IMemento;
+
+/**
+ * Imports log to Log View from such sources as file in local file system, file in workspace,
+ * files from log files manager.
+ */
+public class ImportLogAction extends Action implements IMenuCreator {
+
+ private Menu toolbarMenu = null;
+ private Menu popupMenu = null;
+
+ /**
+ * View to import logs to.
+ */
+ private final LogView logView;
+ private ImportConfigurationLogAction[] actions;
+ private IMemento fMemento;
+
+ /**
+ * Action imports log file from given location to Log View.
+ */
+ private class ImportConfigurationLogAction extends Action {
+ private String name;
+ private String location;
+
+ public ImportConfigurationLogAction(String name, String location) {
+ super(name, AS_RADIO_BUTTON);
+ this.name = name;
+ this.location = location;
+ setId(name + "#" + location); //$NON-NLS-1$
+ }
+
+ protected void doRun() {
+ logView.handleImportPath(location);
+ }
+
+ @Override
+ public void run() {
+ doRun();
+
+ // remember we clicked on that item
+ if (isChecked()) {
+ fMemento.putString(LogView.P_IMPORT_LOG, getId());
+ }
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (o instanceof ImportConfigurationLogAction) {
+ ImportConfigurationLogAction action = (ImportConfigurationLogAction) o;
+ return name.equals(action.name) && location.equals(action.name);
+ }
+
+ return false;
+ }
+ }
+
+ public ImportLogAction(LogView logView, String text, IMemento memento) {
+ super(text);
+ this.logView = logView;
+ this.fMemento = memento;
+ setMenuCreator(this);
+ }
+
+ @Override
+ public void run() {
+ // by default import file selected by user
+ logView.handleImport();
+ }
+
+ @Override
+ public Menu getMenu(Control parent) {
+ if (menuUpdateNeeded(toolbarMenu)) {
+ toolbarMenu = new Menu(parent);
+ createMenuItems(toolbarMenu);
+ }
+ return toolbarMenu;
+ }
+
+ @Override
+ public Menu getMenu(Menu parent) {
+ if (menuUpdateNeeded(popupMenu)) {
+ popupMenu = new Menu(parent);
+ createMenuItems(popupMenu);
+ }
+ return popupMenu;
+ }
+
+ /**
+ * Returns whether menu should be updated or not. Menu should be updated
+ * if either number of actions or any of actions has been changed.
+ * @return true if menu should be updated, false otherwise
+ */
+ private boolean menuUpdateNeeded(Menu menu) {
+ boolean result = false;
+
+ ImportConfigurationLogAction[] currActions = getLogActions();
+
+ if (menu == null) {
+ result = true;
+ } else if (actions == null) {
+ result = true;
+ } else if (currActions.length != actions.length) {
+ result = true;
+ } else {
+ for (int i = 0; i < currActions.length; i++) {
+ if (!currActions[i].equals(actions[i])) {
+ result = true;
+ }
+ }
+ }
+
+ if (result == true) {
+ actions = currActions;
+
+ if (toolbarMenu != null) {
+ toolbarMenu.dispose();
+ toolbarMenu = null;
+ }
+ if (popupMenu != null) {
+ popupMenu.dispose();
+ popupMenu = null;
+ }
+ }
+
+ return result;
+ }
+
+ /**
+ * Returns list of all actions from LogFilesManager.
+ * @return list of all actions from LogFilesManager
+ */
+ private ImportConfigurationLogAction[] getLogActions() {
+ List<ImportConfigurationLogAction> result = new ArrayList<>();
+ Map<String, String> sources = LogFilesManager.getLogSources();
+ for (Entry<String, String> entry : sources.entrySet()) {
+ String name = entry.getKey();
+ String location = entry.getValue();
+ result.add(new ImportConfigurationLogAction(name, location));
+ }
+ return result.toArray(new ImportConfigurationLogAction[result.size()]);
+ }
+
+ /**
+ * Builds menu of ImportLogAction actions from log files provided by LogFilesManager.
+ *
+ * @see IMenuCreator#getMenu(Control)
+ */
+ private void createMenuItems(Menu menu) {
+ String previouslyCheckedActionId = fMemento.getString(LogView.P_IMPORT_LOG);
+ if (actions.length == 0) {
+ Action action = new Action(Messages.ImportLogAction_noLaunchHistory) {
+ // dummy action
+ };
+ action.setEnabled(false);
+ ActionContributionItem actionItem = new ActionContributionItem(action);
+ actionItem.fill(menu, -1);
+ } else {
+ for (ImportConfigurationLogAction action : actions) {
+ action.setChecked(action.getId().equals(previouslyCheckedActionId) && !logView.isPlatformLogOpen());
+ ActionContributionItem item = new ActionContributionItem(action);
+ item.fill(menu, -1);
+ }
+ }
+
+ (new Separator()).fill(menu, -1);
+ ImportConfigurationLogAction importWorkspaceLogAction = new ImportConfigurationLogAction(Messages.ImportLogAction_reloadWorkspaceLog, Platform.getLogFileLocation().toFile().getAbsolutePath()) {
+
+ @Override
+ public void doRun() {
+ logView.setPlatformLog();
+ }
+
+ };
+ importWorkspaceLogAction.setChecked(logView.isPlatformLogOpen());
+ ActionContributionItem item = new ActionContributionItem(importWorkspaceLogAction);
+ item.fill(menu, -1);
+ }
+
+ @Override
+ public void dispose() {
+ if (toolbarMenu != null) {
+ toolbarMenu.dispose();
+ toolbarMenu = null;
+ }
+ if (popupMenu != null) {
+ popupMenu.dispose();
+ popupMenu = null;
+ }
+ }
+}
diff --git a/bundles/org.eclipse.ui.views.log/src/org/eclipse/ui/internal/views/log/LogEntry.java b/bundles/org.eclipse.ui.views.log/src/org/eclipse/ui/internal/views/log/LogEntry.java
new file mode 100644
index 0000000..fa7f2c9
--- /dev/null
+++ b/bundles/org.eclipse.ui.views.log/src/org/eclipse/ui/internal/views/log/LogEntry.java
@@ -0,0 +1,388 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2017 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
+ * Jacek Pospychala <jacek.pospychala@pl.ibm.com> - bugs 209474, 207344
+ * Eike Stepper <stepper@esc-net.de> - bug 429372
+ * Lars Vogel <Lars.Vogel@vogella.com> - Bug 485843
+ *******************************************************************************/
+package org.eclipse.ui.internal.views.log;
+
+import com.ibm.icu.text.DateFormat;
+import com.ibm.icu.text.SimpleDateFormat;
+import java.io.PrintWriter;
+import java.io.StringWriter;
+import java.text.ParseException;
+import java.util.*;
+import org.eclipse.core.runtime.IStatus;
+
+/**
+ * Represents a given entry in the Error view
+ */
+public class LogEntry extends AbstractEntry {
+
+ public static final String SPACE = " "; //$NON-NLS-1$
+ public static final String F_DATE_FORMAT = "yyyy-MM-dd HH:mm:ss.SSS"; //$NON-NLS-1$
+ private static final DateFormat GREGORIAN_SDF = new SimpleDateFormat(F_DATE_FORMAT, Locale.ENGLISH);
+ private static final DateFormat LOCAL_SDF = new SimpleDateFormat(F_DATE_FORMAT);
+
+ private String pluginId;
+ private int severity;
+ private int code;
+ private String fDateString;
+ private Date fDate;
+ private String message;
+ private String stack;
+ private LogSession session;
+
+ /**
+ * Constructor
+ */
+ public LogEntry() {
+ //do nothing
+ }
+
+ /**
+ * Constructor - creates a new entry from the given status
+ * @param status an existing status to create a new entry from
+ */
+ public LogEntry(IStatus status) {
+ this(status, null);
+ }
+
+ /**
+ * Constructor - creates a new entry from the given status
+ * @param status an existing status to create a new entry from
+ */
+ public LogEntry(IStatus status, LogSession session) {
+ processStatus(status, session);
+ }
+
+ /**
+ * Returns the {@link LogSession} for this entry or the parent {@link LogSession}
+ * iff:
+ * <ul>
+ * <li>The session is <code>null</code> for this entry</li>
+ * <li>The parent of this entry is not <code>null</code> and is a {@link LogEntry}</li>
+ * </ul>
+ * @return the {@link LogSession} for this entry
+ */
+ public LogSession getSession() {
+ if ((session == null) && (parent != null) && (parent instanceof LogEntry)) {
+ return ((LogEntry) parent).getSession();
+ }
+ return session;
+ }
+
+ /**
+ * Sets the {@link LogSession} for this entry. No validation is done on the new session.
+ * @param session the session to set.
+ */
+ void setSession(LogSession session) {
+ this.session = session;
+ }
+
+ /**
+ * Returns the severity of this entry.
+ * @return the severity
+ * @see IStatus#OK
+ * @see IStatus#WARNING
+ * @see IStatus#INFO
+ * @see IStatus#ERROR
+ */
+ public int getSeverity() {
+ return severity;
+ }
+
+ /**
+ * Returns if the severity of this entry is {@link IStatus#OK}
+ * @return if the entry is OK or not
+ */
+ public boolean isOK() {
+ return severity == IStatus.OK;
+ }
+
+ /**
+ * Returns the code for this entry
+ * @return the code for this entry
+ */
+ public int getCode() {
+ return code;
+ }
+
+ /**
+ * Returns the id of the plugin that generated this entry
+ * @return the plugin id of this entry
+ */
+ public String getPluginId() {
+ return pluginId;
+ }
+
+ /**
+ * Returns the message for this entry or <code>null</code> if there is no message
+ * @return the message or <code>null</code>
+ */
+ public String getMessage() {
+ return message;
+ }
+
+ /**
+ * Returns the stack trace for this entry or <code>null</code> if there is no stack trace
+ * @return the stack trace or <code>null</code>
+ */
+ public String getStack() {
+ return stack;
+ }
+
+ /**
+ * Returns a pretty-print formatting for the date for this entry
+ * @return the formatted date for this entry
+ */
+ public String getFormattedDate() {
+ if (fDateString == null) {
+ fDateString = LOCAL_SDF.format(getDate());
+ }
+ return fDateString;
+ }
+
+ /**
+ * Returns the date for this entry or the epoch if the current date value is <code>null</code>
+ * @return the entry date or the epoch if there is no date entry
+ */
+ public Date getDate() {
+ if (fDate == null) {
+ fDate = new Date(0); // unknown date - return epoch
+ }
+ return fDate;
+ }
+
+ /**
+ * Returns the human-readable text representation of the integer
+ * severity value or '<code>?</code>' if the severity is unknown.
+ * @return the text representation of the severity
+ */
+ public String getSeverityText() {
+ switch (severity) {
+ case IStatus.ERROR : {
+ return Messages.LogView_severity_error;
+ }
+ case IStatus.WARNING : {
+ return Messages.LogView_severity_warning;
+ }
+ case IStatus.INFO : {
+ return Messages.LogView_severity_info;
+ }
+ case IStatus.OK : {
+ return Messages.LogView_severity_ok;
+ }
+ }
+ return "?"; //$NON-NLS-1$
+ }
+
+ @Override
+ public String toString() {
+ return getSeverityText();
+ }
+
+ @Override
+ public String getLabel(Object obj) {
+ return getSeverityText();
+ }
+
+ /**
+ * Processes a given line from the log file
+ * @param line
+ * @throws ParseException
+ */
+ public void processEntry(String line) throws ParseException {
+ //!ENTRY <pluginID> <severity> <code> <date>
+ //!ENTRY <pluginID> <date> if logged by the framework!!!
+ StringTokenizer stok = new StringTokenizer(line, SPACE);
+ severity = 0;
+ code = 0;
+ StringBuilder dateBuffer = new StringBuilder();
+ int tokens = stok.countTokens();
+ String token = null;
+ for (int i = 0; i < tokens; i++) {
+ token = stok.nextToken();
+ switch (i) {
+ case 0 : {
+ break;
+ }
+ case 1 : {
+ pluginId = token;
+ break;
+ }
+ case 2 : {
+ try {
+ severity = Integer.parseInt(token);
+ } catch (NumberFormatException nfe) {
+ appendToken(dateBuffer, token);
+ }
+ break;
+ }
+ case 3 : {
+ try {
+ code = Integer.parseInt(token);
+ } catch (NumberFormatException nfe) {
+ appendToken(dateBuffer, token);
+ }
+ break;
+ }
+ default : {
+ appendToken(dateBuffer, token);
+ }
+ }
+ }
+ Date date = GREGORIAN_SDF.parse(dateBuffer.toString());
+ if (date != null) {
+ fDate = date;
+ fDateString = LOCAL_SDF.format(fDate);
+ }
+ }
+
+ /**
+ * Adds the given token to the given buffer, adding a space as needed
+ * @param buffer
+ * @param token
+ *
+ * @since 3.6
+ */
+ void appendToken(StringBuilder buffer, String token) {
+ if (buffer.length() > 0) {
+ buffer.append(SPACE);
+ }
+ buffer.append(token);
+ }
+
+ /**
+ * Processes the given sub-entry from the log
+ * @param line
+ * @return the depth of the sub-entry
+ * @throws ParseException
+ */
+ public int processSubEntry(String line) throws ParseException {
+ //!SUBENTRY <depth> <pluginID> <severity> <code> <date>
+ //!SUBENTRY <depth> <pluginID> <date>if logged by the framework!!!
+ StringTokenizer stok = new StringTokenizer(line, SPACE);
+ StringBuilder dateBuffer = new StringBuilder();
+ int depth = 0;
+ String token = null;
+ int tokens = stok.countTokens();
+ for (int i = 0; i < tokens; i++) {
+ token = stok.nextToken();
+ switch (i) {
+ case 0 : {
+ break;
+ }
+ case 1 : {
+ depth = Integer.parseInt(token);
+ break;
+ }
+ case 2 : {
+ pluginId = token;
+ break;
+ }
+ case 3 : {
+ try {
+ severity = Integer.parseInt(token);
+ } catch (NumberFormatException nfe) {
+ appendToken(dateBuffer, token);
+ }
+ break;
+ }
+ case 4 : {
+ try {
+ code = Integer.parseInt(token);
+ } catch (NumberFormatException nfe) {
+ appendToken(dateBuffer, token);
+ }
+ break;
+ }
+ default : {
+ appendToken(dateBuffer, token);
+ }
+ }
+ }
+ Date date = GREGORIAN_SDF.parse(dateBuffer.toString());
+ if (date != null) {
+ fDate = date;
+ fDateString = LOCAL_SDF.format(fDate);
+ }
+ return depth;
+ }
+
+ /**
+ * Sets the stack to the given stack value.
+ * No validation is performed on the new value.
+ * @param stack
+ */
+ void setStack(String stack) {
+ this.stack = stack;
+ }
+
+ /**
+ * Sets the message to the given message value.
+ * No validation is performed on the new value
+ * @param message
+ */
+ void setMessage(String message) {
+ this.message = message;
+ }
+
+ /**
+ * Process the given status and sub-statuses to fill this entry
+ * @param status
+ */
+ private void processStatus(IStatus status, LogSession session) {
+ pluginId = status.getPlugin();
+ severity = status.getSeverity();
+ code = status.getCode();
+ fDate = new Date();
+ fDateString = LOCAL_SDF.format(fDate);
+ message = status.getMessage();
+ this.session = session;
+ Throwable throwable = status.getException();
+ if (throwable != null) {
+ StringWriter swriter = new StringWriter();
+ try (PrintWriter pwriter = new PrintWriter(swriter)) {
+ throwable.printStackTrace(pwriter);
+ pwriter.flush();
+ }
+ stack = swriter.toString();
+ }
+ IStatus[] schildren = status.getChildren();
+ if (schildren.length > 0) {
+ for (IStatus element : schildren) {
+ addChild(new LogEntry(element, session));
+ }
+ }
+ }
+
+ @Override
+ public void write(PrintWriter writer) {
+ if (session != null) {
+ writer.println(session.getSessionData());
+ }
+ writer.println(pluginId);
+ writer.println(getSeverityText());
+ if (fDate != null) {
+ writer.println(getDate());
+ }
+ if (message != null) {
+ writer.println(getMessage());
+ }
+ if (stack != null) {
+ writer.println();
+ writer.println(stack);
+ }
+ }
+}
diff --git a/bundles/org.eclipse.ui.views.log/src/org/eclipse/ui/internal/views/log/LogFilesManager.java b/bundles/org.eclipse.ui.views.log/src/org/eclipse/ui/internal/views/log/LogFilesManager.java
new file mode 100644
index 0000000..31d8422
--- /dev/null
+++ b/bundles/org.eclipse.ui.views.log/src/org/eclipse/ui/internal/views/log/LogFilesManager.java
@@ -0,0 +1,59 @@
+/*******************************************************************************
+ * 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
+ * Lars Vogel <Lars.Vogel@vogella.com> - Bug 485843
+ *******************************************************************************/
+package org.eclipse.ui.internal.views.log;
+
+import java.util.*;
+
+/**
+ * Manages the log file providers.
+ * One adds log file provider to let Log View know where to find log files.
+ */
+public class LogFilesManager {
+
+ private static List<ILogFileProvider> logFileProviders = new ArrayList<>();
+
+ /**
+ * Adds log file provider.
+ * Has no effect if an identical provider is already registered.
+ */
+ public static void addLogFileProvider(ILogFileProvider provider) {
+ if (!logFileProviders.contains(provider)) {
+ logFileProviders.add(provider);
+ }
+ }
+
+ /**
+ * Removes log file provider.
+ * Has no effect if an identical provider is already removed.
+ */
+ public static void removeLogFileProvider(ILogFileProvider provider) {
+ logFileProviders.remove(provider);
+ }
+
+ /**
+ * Returns the list of logs.
+ */
+ static Map<String, String> getLogSources() {
+ ILogFileProvider[] providers = logFileProviders.toArray(new ILogFileProvider[logFileProviders.size()]);
+ Map<String, String> result = new HashMap<>(providers.length);
+
+ for (ILogFileProvider provider : providers) {
+ Map<String, String> sources = provider.getLogSources();
+ result.putAll(sources);
+ }
+
+ return result;
+ }
+}
diff --git a/bundles/org.eclipse.ui.views.log/src/org/eclipse/ui/internal/views/log/LogReader.java b/bundles/org.eclipse.ui.views.log/src/org/eclipse/ui/internal/views/log/LogReader.java
new file mode 100644
index 0000000..61df87a
--- /dev/null
+++ b/bundles/org.eclipse.ui.views.log/src/org/eclipse/ui/internal/views/log/LogReader.java
@@ -0,0 +1,255 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 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
+ * Jacek Pospychala <jacek.pospychala@pl.ibm.com> - bugs 202583, 207061
+ * Jacek Pospychala <jacek.pospychala@pl.ibm.com> - bugs 207312, 100715
+ * Jacek Pospychala <jacek.pospychala@pl.ibm.com> - bugs 207344
+ *******************************************************************************/
+package org.eclipse.ui.internal.views.log;
+
+import java.io.*;
+import java.nio.charset.StandardCharsets;
+import java.text.ParseException;
+import java.util.*;
+import org.eclipse.core.runtime.IStatus;
+import org.eclipse.core.runtime.Status;
+import org.eclipse.osgi.util.NLS;
+import org.eclipse.ui.IMemento;
+
+class LogReader {
+ private static final int SESSION_STATE = 10;
+ public static final long MAX_FILE_LENGTH = 1024 * 1024;
+ private static final int ONE_MEGA_BYTE_IN_BYTES = 1024 * 1024;
+ private static final int ENTRY_STATE = 20;
+ private static final int SUBENTRY_STATE = 30;
+ private static final int MESSAGE_STATE = 40;
+ private static final int STACK_STATE = 50;
+ private static final int TEXT_STATE = 60;
+ private static final int UNKNOWN_STATE = 70;
+
+ public static LogSession parseLogFile(File file, long maxLogTailSizeInMegaByte, List<LogEntry> entries,
+ IMemento memento) {
+ if (!file.exists())
+ return null;
+
+ if (memento.getString(LogView.P_USE_LIMIT).equals("true") //$NON-NLS-1$
+ && memento.getInteger(LogView.P_LOG_LIMIT).intValue() == 0)
+ return null;
+
+ ArrayList<LogEntry> parents = new ArrayList<>();
+ LogEntry current = null;
+ LogSession session = null;
+ int writerState = UNKNOWN_STATE;
+ StringWriter swriter = null;
+ PrintWriter writer = null;
+ int state = UNKNOWN_STATE;
+ LogSession currentSession = null;
+ long maxTailSizeInBytes = maxLogTailSizeInMegaByte > 0 ? maxLogTailSizeInMegaByte * ONE_MEGA_BYTE_IN_BYTES
+ : ONE_MEGA_BYTE_IN_BYTES;
+ try (BufferedReader reader = new BufferedReader(
+ new InputStreamReader(new TailInputStream(file, maxTailSizeInBytes), StandardCharsets.UTF_8))) {
+ for (;;) {
+ String line0 = reader.readLine();
+ if (line0 == null)
+ break;
+ String line = line0.trim();
+
+ if (line.startsWith(LogSession.SESSION)) {
+ state = SESSION_STATE;
+ } else if (line.startsWith("!ENTRY")) { //$NON-NLS-1$
+ state = ENTRY_STATE;
+ } else if (line.startsWith("!SUBENTRY")) { //$NON-NLS-1$
+ state = SUBENTRY_STATE;
+ } else if (line.startsWith("!MESSAGE")) { //$NON-NLS-1$
+ state = MESSAGE_STATE;
+ } else if (line.startsWith("!STACK")) { //$NON-NLS-1$
+ state = STACK_STATE;
+ } else
+ state = TEXT_STATE;
+
+ if (state == TEXT_STATE) {
+ if (writer != null) {
+ if (swriter.getBuffer().length() > 0)
+ writer.println();
+ writer.print(line0);
+ }
+ continue;
+ }
+
+ if (writer != null) {
+ setData(current, session, writerState, swriter);
+ writerState = UNKNOWN_STATE;
+ swriter = null;
+ writer.close();
+ writer = null;
+ }
+
+ if (state == STACK_STATE) {
+ swriter = new StringWriter();
+ writer = new PrintWriter(swriter, true);
+ writerState = STACK_STATE;
+ } else if (state == SESSION_STATE) {
+ session = new LogSession();
+ session.processLogLine(line);
+ swriter = new StringWriter();
+ writer = new PrintWriter(swriter, true);
+ writerState = SESSION_STATE;
+ currentSession = updateCurrentSession(currentSession, session);
+ // if current session is most recent and not showing all sessions
+ if (currentSession.equals(session) && !memento.getString(LogView.P_SHOW_ALL_SESSIONS).equals("true")) //$NON-NLS-1$
+ entries.clear();
+ } else if (state == ENTRY_STATE) {
+ if (currentSession == null) { // create fake session if there was no any
+ currentSession = new LogSession();
+ }
+ try {
+ LogEntry entry = new LogEntry();
+ entry.setSession(currentSession);
+ entry.processEntry(line);
+ setNewParent(parents, entry, 0);
+ current = entry;
+ addEntry(current, entries, memento);
+ } catch (ParseException pe) {
+ //do nothing, just toss the entry
+ }
+ } else if (state == SUBENTRY_STATE) {
+ if (parents.size() > 0) {
+ try {
+ LogEntry entry = new LogEntry();
+ entry.setSession(session);
+ int depth = entry.processSubEntry(line);
+ setNewParent(parents, entry, depth);
+ current = entry;
+ LogEntry parent = parents.get(depth - 1);
+ parent.addChild(entry);
+ } catch (ParseException pe) {
+ //do nothing, just toss the bad entry
+ }
+ }
+ } else if (state == MESSAGE_STATE) {
+ swriter = new StringWriter();
+ writer = new PrintWriter(swriter, true);
+ String message = ""; //$NON-NLS-1$
+ if (line.length() > 8)
+ message = line.substring(9);
+ if (current != null)
+ current.setMessage(message);
+ writerState = MESSAGE_STATE;
+ }
+ }
+
+ if (swriter != null && current != null && writerState == STACK_STATE) {
+ writerState = UNKNOWN_STATE;
+ current.setStack(swriter.toString());
+ }
+ } catch (IOException e) { // do nothing
+ } finally {
+ if (file.length() > maxLogTailSizeInMegaByte && entries.isEmpty()) {
+ LogEntry entry = new LogEntry(new Status(IStatus.WARNING, Activator.PLUGIN_ID, NLS.bind(
+ Messages.LogReader_warn_noEntryWithinMaxLogTailSize, Long.valueOf(maxLogTailSizeInMegaByte))));
+ entry.setSession(currentSession == null ? new LogSession() : currentSession);
+ entries.add(entry);
+ }
+ if (writer != null) {
+ setData(current, session, writerState, swriter);
+ writer.close();
+ }
+ }
+
+ return currentSession;
+ }
+
+ public static LogSession parseLogFile(File file, List<LogEntry> entries, IMemento memento) {
+ return parseLogFile(file, ONE_MEGA_BYTE_IN_BYTES, entries, memento);
+ }
+
+ /**
+ * Assigns data from writer to appropriate field of current Log Entry or Session,
+ * depending on writer state.
+ */
+ private static void setData(LogEntry current, LogSession session, int writerState, StringWriter swriter) {
+ if (writerState == STACK_STATE && current != null) {
+ current.setStack(swriter.toString());
+ } else if (writerState == SESSION_STATE && session != null) {
+ session.setSessionData(swriter.toString());
+ } else if (writerState == MESSAGE_STATE && current != null) {
+ StringBuilder sb = new StringBuilder(current.getMessage());
+ String continuation = swriter.toString();
+ if (continuation.length() > 0)
+ sb.append(System.getProperty("line.separator")).append(continuation); //$NON-NLS-1$
+ current.setMessage(sb.toString());
+ }
+ }
+
+ /**
+ * Updates the currentSession to be the one that is not null or has most recent date.
+ */
+ private static LogSession updateCurrentSession(LogSession currentSession, LogSession session) {
+ if (currentSession == null) {
+ return session;
+ }
+ Date currentDate = currentSession.getDate();
+ Date sessionDate = session.getDate();
+ if (currentDate == null && sessionDate != null)
+ return session;
+ else if (currentDate != null && sessionDate == null)
+ return session;
+ else if (currentDate != null && sessionDate != null && sessionDate.after(currentDate))
+ return session;
+
+ return currentSession;
+ }
+
+ /**
+ * Adds entry to the list if it's not filtered. Removes entries exceeding the count limit.
+ */
+ private static void addEntry(LogEntry entry, List<LogEntry> entries, IMemento memento) {
+
+ if (isLogged(entry, memento)) {
+ entries.add(entry);
+
+ if (memento.getString(LogView.P_USE_LIMIT).equals("true")) {//$NON-NLS-1$
+ int limit = memento.getInteger(LogView.P_LOG_LIMIT).intValue();
+ if (entries.size() > limit) {
+ entries.remove(0);
+ }
+ }
+ }
+ }
+
+ /**
+ * Returns whether given entry is logged (true) or filtered (false).
+ * @return is entry logged or filtered
+ */
+ public static boolean isLogged(LogEntry entry, IMemento memento) {
+ int severity = entry.getSeverity();
+ switch (severity) {
+ case IStatus.INFO :
+ return memento.getString(LogView.P_LOG_INFO).equals("true"); //$NON-NLS-1$
+ case IStatus.WARNING :
+ return memento.getString(LogView.P_LOG_WARNING).equals("true"); //$NON-NLS-1$
+ case IStatus.ERROR :
+ return memento.getString(LogView.P_LOG_ERROR).equals("true"); //$NON-NLS-1$
+ case IStatus.OK :
+ return memento.getString(LogView.P_LOG_OK).equals("true"); //$NON-NLS-1$
+ }
+
+ return false;
+ }
+
+ private static void setNewParent(ArrayList<LogEntry> parents, LogEntry entry, int depth) {
+ if (depth + 1 > parents.size())
+ parents.add(entry);
+ else
+ parents.set(depth, entry);
+ }
+}
diff --git a/bundles/org.eclipse.ui.views.log/src/org/eclipse/ui/internal/views/log/LogSession.java b/bundles/org.eclipse.ui.views.log/src/org/eclipse/ui/internal/views/log/LogSession.java
new file mode 100644
index 0000000..d4e74f8
--- /dev/null
+++ b/bundles/org.eclipse.ui.views.log/src/org/eclipse/ui/internal/views/log/LogSession.java
@@ -0,0 +1,80 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 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
+ * Jacek Pospychala <jacek.pospychala@pl.ibm.com> - bugs 202583, 207344
+ * Benjamin Cabe <benjamin.cabe@anyware-tech.com> - bug 218648
+ *******************************************************************************/
+package org.eclipse.ui.internal.views.log;
+
+import com.ibm.icu.text.SimpleDateFormat;
+import java.io.PrintWriter;
+import java.text.ParseException;
+import java.util.Date;
+
+/**
+ * Group of entries with additional Session data.
+ */
+public class LogSession extends Group {
+
+ /**
+ * Describes the !SESSION header name
+ *
+ * @since 3.5
+ */
+ public static final String SESSION = "!SESSION"; //$NON-NLS-1$
+ private String sessionData;
+ private Date date;
+
+ public LogSession() {
+ super(Messages.LogViewLabelProvider_Session);
+ }
+
+ public Date getDate() {
+ return date;
+ }
+
+ public void setDate(String dateString) {
+ SimpleDateFormat formatter = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS"); //$NON-NLS-1$
+ try {
+ date = formatter.parse(dateString);
+ } catch (ParseException e) { // do nothing
+ }
+ }
+
+ public String getSessionData() {
+ return sessionData;
+ }
+
+ void setSessionData(String data) {
+ this.sessionData = data;
+ }
+
+ public void processLogLine(String line) {
+ // process "!SESSION <dateUnknownFormat> ----------------------------"
+ if (line.startsWith(SESSION)) {
+ line = line.substring(SESSION.length()).trim(); // strip "!SESSION "
+ int delim = line.indexOf("----"); //$NON-NLS-1$ // single "-" may be in date, so take few for sure
+ if (delim == -1) {
+ return;
+ }
+ String dateBuffer = line.substring(0, delim).trim();
+ setDate(dateBuffer);
+ }
+ }
+
+ @Override
+ public void write(PrintWriter writer) {
+ writer.write(sessionData);
+ writer.println();
+ super.write(writer);
+ }
+}
diff --git a/bundles/org.eclipse.ui.views.log/src/org/eclipse/ui/internal/views/log/LogView.java b/bundles/org.eclipse.ui.views.log/src/org/eclipse/ui/internal/views/log/LogView.java
new file mode 100644
index 0000000..c5e5edf
--- /dev/null
+++ b/bundles/org.eclipse.ui.views.log/src/org/eclipse/ui/internal/views/log/LogView.java
@@ -0,0 +1,1739 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 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
+ * Jacek Pospychala <jacek.pospychala@pl.ibm.com> - bugs 202583, 202584, 207344
+ * bugs 207323, 207931, 207101
+ * bugs 172658, 216341, 216657
+ * Benjamin Cabe <benjamin.cabe@anyware-tech.com> - bug 218648
+ * Tuukka Lehtonen <tuukka.lehtonen@semantum.fi> - bug 247907
+ * Eike Stepper <stepper@esc-net.de> - bug 429372
+ * Lars Vogel <Lars.Vogel@vogella.com> - Bug 485843
+ * Patrik Suzzi <psuzzi@gmail.com> - Bug 501586
+ *******************************************************************************/
+
+package org.eclipse.ui.internal.views.log;
+
+import com.ibm.icu.text.DateFormat;
+import com.ibm.icu.text.SimpleDateFormat;
+import java.io.*;
+import java.lang.reflect.InvocationTargetException;
+import java.nio.charset.StandardCharsets;
+import java.util.*;
+import java.util.List;
+import java.util.Map.Entry;
+import org.eclipse.core.runtime.*;
+import org.eclipse.core.runtime.Path;
+import org.eclipse.core.runtime.jobs.Job;
+import org.eclipse.core.runtime.preferences.DefaultScope;
+import org.eclipse.core.runtime.preferences.InstanceScope;
+import org.eclipse.jface.action.*;
+import org.eclipse.jface.dialogs.*;
+import org.eclipse.jface.operation.IRunnableWithProgress;
+import org.eclipse.jface.util.Policy;
+import org.eclipse.jface.viewers.*;
+import org.eclipse.jface.window.Window;
+import org.eclipse.osgi.util.NLS;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.custom.BusyIndicator;
+import org.eclipse.swt.dnd.*;
+import org.eclipse.swt.events.*;
+import org.eclipse.swt.graphics.*;
+import org.eclipse.swt.layout.GridData;
+import org.eclipse.swt.layout.GridLayout;
+import org.eclipse.swt.program.Program;
+import org.eclipse.swt.widgets.*;
+import org.eclipse.ui.*;
+import org.eclipse.ui.actions.ActionFactory;
+import org.eclipse.ui.dialogs.FilteredTree;
+import org.eclipse.ui.dialogs.PatternFilter;
+import org.eclipse.ui.part.ViewPart;
+import org.osgi.service.prefs.BackingStoreException;
+import org.osgi.service.prefs.Preferences;
+
+public class LogView extends ViewPart implements ILogListener {
+ public static final String P_LOG_WARNING = "warning"; //$NON-NLS-1$
+ public static final String P_LOG_ERROR = "error"; //$NON-NLS-1$
+ public static final String P_LOG_INFO = "info"; //$NON-NLS-1$
+ public static final String P_LOG_OK = "ok"; //$NON-NLS-1$
+
+ /**
+ * Maximum tail size of the log file in Mega Bytes (1024 * 1024 Bytes) considers the last XYZ MB of the log file to create log entries.
+ * This value should be increased if the size of the sub elements of the last (most recent) log entry in the log file exceeds the maximum tail size.
+ **/
+ public static final String P_LOG_MAX_TAIL_SIZE = "maxLogTailSize"; //$NON-NLS-1$
+ public static final String P_LOG_LIMIT = "limit"; //$NON-NLS-1$
+ public static final String P_USE_LIMIT = "useLimit"; //$NON-NLS-1$
+ public static final String P_SHOW_ALL_SESSIONS = "allSessions"; //$NON-NLS-1$
+ protected static final String P_COLUMN_1 = "column2"; //$NON-NLS-1$
+ protected static final String P_COLUMN_2 = "column3"; //$NON-NLS-1$
+ protected static final String P_COLUMN_3 = "column4"; //$NON-NLS-1$
+ public static final String P_ACTIVATE = "activate"; //$NON-NLS-1$
+ public static final String P_SHOW_FILTER_TEXT = "show_filter_text"; //$NON-NLS-1$
+ public static final String P_ORDER_TYPE = "orderType"; //$NON-NLS-1$
+ public static final String P_ORDER_VALUE = "orderValue"; //$NON-NLS-1$
+ public static final String P_IMPORT_LOG = "importLog"; //$NON-NLS-1$
+ public static final String P_GROUP_BY = "groupBy"; //$NON-NLS-1$
+
+ private static final String LOG_ENTRY_GROUP = "logEntryGroup"; //$NON-NLS-1$
+
+ /** default values **/
+ private static final int DEFAULT_LOG_MAX_TAIL_SIZE = 1; // 1 Mega Byte
+
+ private int MESSAGE_ORDER;
+ private int PLUGIN_ORDER;
+ private int DATE_ORDER;
+
+ public final static byte MESSAGE = 0x0;
+ public final static byte PLUGIN = 0x1;
+ public final static byte DATE = 0x2;
+ public static int ASCENDING = 1;
+ public static int DESCENDING = -1;
+
+ public static final int GROUP_BY_NONE = 0;
+ public static final int GROUP_BY_SESSION = 1;
+ public static final int GROUP_BY_PLUGIN = 2;
+
+ private List<AbstractEntry> elements;
+ private Map<Object, Group> groups;
+ private LogSession currentSession;
+
+ private List<LogEntry> batchedEntries;
+ private boolean batchEntries;
+
+ private Clipboard fClipboard;
+
+ private IMemento fMemento;
+ private File fInputFile;
+ private String fDirectory;
+
+ private Comparator fComparator;
+
+ // hover text
+ private boolean fCanOpenTextShell;
+ private Text fTextLabel;
+ private Shell fTextShell;
+
+ private boolean fFirstEvent = true;
+
+ private TreeColumn fColumn1;
+ private TreeColumn fColumn2;
+ private TreeColumn fColumn3;
+
+ private Tree fTree;
+ private FilteredTree fFilteredTree;
+ private LogViewLabelProvider fLabelProvider;
+ private String fSelectedStack;
+
+ private Action fPropertiesAction;
+ private Action fDeleteLogAction;
+ private Action fReadLogAction;
+ private Action fCopyAction;
+ private Action fActivateViewAction;
+ private Action fOpenLogAction;
+ private Action fExportLogAction;
+ private Action fExportLogEntryAction;
+
+ /**
+ * Action called when user selects "Group by -> ..." from menu.
+ */
+ class GroupByAction extends Action {
+ private int groupBy;
+
+ public GroupByAction(String text, int groupBy) {
+ super(text, IAction.AS_RADIO_BUTTON);
+
+ this.groupBy = groupBy;
+
+ if (fMemento.getInteger(LogView.P_GROUP_BY).intValue() == groupBy) {
+ setChecked(true);
+ }
+ }
+
+ @Override
+ public void run() {
+ if (fMemento.getInteger(LogView.P_GROUP_BY).intValue() != groupBy) {
+ fMemento.putInteger(LogView.P_GROUP_BY, groupBy);
+ reloadLog();
+ }
+ }
+ }
+
+ /**
+ * Constructor
+ */
+ public LogView() {
+ elements = new ArrayList<>();
+ groups = new HashMap<>();
+ batchedEntries = new ArrayList<>();
+ fInputFile = Platform.getLogFileLocation().toFile();
+ }
+
+ @Override
+ public void createPartControl(Composite parent) {
+ Composite composite = new Composite(parent, SWT.NONE);
+ GridLayout layout = new GridLayout();
+ layout.horizontalSpacing = 0;
+ layout.verticalSpacing = 0;
+ layout.marginWidth = 0;
+ layout.marginHeight = 0;
+ composite.setLayout(layout);
+ composite.setLayoutData(new GridData(GridData.FILL_BOTH));
+
+ readLogFile();
+ createViewer(composite);
+ getSite().setSelectionProvider(fFilteredTree.getViewer());
+ createActions();
+ fClipboard = new Clipboard(fTree.getDisplay());
+ fTree.setToolTipText(""); //$NON-NLS-1$
+ initializeViewerSorter();
+
+ makeHoverShell();
+
+ Platform.addLogListener(this);
+ PlatformUI.getWorkbench().getHelpSystem().setHelp(fFilteredTree, IHelpContextIds.LOG_VIEW);
+ getSite().getWorkbenchWindow().addPerspectiveListener(new IPerspectiveListener2() {
+
+ @Override
+ public void perspectiveChanged(IWorkbenchPage page, IPerspectiveDescriptor perspective, IWorkbenchPartReference partRef, String changeId) {
+ if (!(partRef instanceof IViewReference))
+ return;
+
+ IWorkbenchPart part = partRef.getPart(false);
+ if (part == null) {
+ return;
+ }
+
+ if (part.equals(LogView.this)) {
+ if (changeId.equals(IWorkbenchPage.CHANGE_VIEW_SHOW)) {
+ if (!batchedEntries.isEmpty()) {
+ pushBatchedEntries();
+ }
+
+ batchEntries = false;
+ } else if (changeId.equals(IWorkbenchPage.CHANGE_VIEW_HIDE)) {
+ batchEntries = true;
+ }
+ }
+ }
+
+ @Override
+ public void perspectiveActivated(IWorkbenchPage page, IPerspectiveDescriptor perspective) {
+ // empty
+ }
+
+ @Override
+ public void perspectiveChanged(IWorkbenchPage page, IPerspectiveDescriptor perspective, String changeId) {
+ // empty
+ }
+
+ });
+ }
+
+ /**
+ * Creates the actions for the viewsite action bars
+ */
+ private void createActions() {
+ IActionBars bars = getViewSite().getActionBars();
+
+ fCopyAction = createCopyAction();
+ bars.setGlobalActionHandler(ActionFactory.COPY.getId(), fCopyAction);
+
+ IToolBarManager toolBarManager = bars.getToolBarManager();
+
+ fExportLogAction = createExportLogAction();
+ toolBarManager.add(fExportLogAction);
+
+ fExportLogEntryAction = createExportLogEntryAction();
+
+ final Action importLogAction = createImportLogAction();
+ toolBarManager.add(importLogAction);
+
+ toolBarManager.add(new Separator(IWorkbenchActionConstants.MB_ADDITIONS));
+
+ final Action clearAction = createClearAction();
+ toolBarManager.add(clearAction);
+
+ fDeleteLogAction = createDeleteLogAction();
+ toolBarManager.add(fDeleteLogAction);
+
+ fOpenLogAction = createOpenLogAction();
+ toolBarManager.add(fOpenLogAction);
+
+ fReadLogAction = createReadLogAction();
+ toolBarManager.add(fReadLogAction);
+
+ toolBarManager.add(new Separator());
+
+ IMenuManager mgr = bars.getMenuManager();
+
+ mgr.add(createGroupByAction());
+ mgr.add(new Separator());
+ mgr.add(createFilterAction());
+ mgr.add(new Separator());
+
+ fActivateViewAction = createActivateViewAction();
+ mgr.add(fActivateViewAction);
+ if (fFilteredTree.getFilterControl() != null)
+ mgr.add(createShowTextFilter());
+
+ fPropertiesAction = createPropertiesAction();
+
+ MenuManager popupMenuManager = new MenuManager("#PopupMenu"); //$NON-NLS-1$
+ IMenuListener listener = manager -> {
+ manager.add(fCopyAction);
+ manager.add(new Separator(LOG_ENTRY_GROUP));
+ clearAction.setEnabled(!(elements.isEmpty() && groups.isEmpty()));
+ manager.add(clearAction);
+ manager.add(fDeleteLogAction);
+ manager.add(fOpenLogAction);
+ manager.add(fReadLogAction);
+ manager.add(new Separator());
+ manager.add(fExportLogAction);
+ manager.add(createImportLogAction());
+ manager.add(new Separator());
+ manager.add(fExportLogEntryAction);
+ manager.add(new Separator());
+
+ ((EventDetailsDialogAction) fPropertiesAction).setComparator(fComparator);
+ TreeItem[] selection = fTree.getSelection();
+ if ((selection.length > 0) && (selection[0].getData() instanceof LogEntry)) {
+ manager.add(fPropertiesAction);
+ }
+
+ manager.add(new Separator(IWorkbenchActionConstants.MB_ADDITIONS));
+ };
+ popupMenuManager.addMenuListener(listener);
+ popupMenuManager.setRemoveAllWhenShown(true);
+ getSite().registerContextMenu(popupMenuManager, getSite().getSelectionProvider());
+ Menu menu = popupMenuManager.createContextMenu(fTree);
+ fTree.setMenu(menu);
+ }
+
+ private Action createActivateViewAction() {
+ Action action = new Action(Messages.LogView_activate) { //
+ @Override
+ public void run() {
+ fMemento.putString(P_ACTIVATE, isChecked() ? "true" : "false"); //$NON-NLS-1$ //$NON-NLS-2$
+ }
+ };
+ action.setChecked(fMemento.getString(P_ACTIVATE).equals("true")); //$NON-NLS-1$
+ return action;
+ }
+
+ private Action createClearAction() {
+ Action action = new Action(Messages.LogView_clear) {
+ @Override
+ public void run() {
+ handleClear();
+ }
+ };
+ action.setImageDescriptor(SharedImages.getImageDescriptor(SharedImages.DESC_CLEAR));
+ action.setDisabledImageDescriptor(SharedImages.getImageDescriptor(SharedImages.DESC_CLEAR_DISABLED));
+ action.setToolTipText(Messages.LogView_clear_tooltip);
+ action.setText(Messages.LogView_clear);
+ return action;
+ }
+
+ private Action createCopyAction() {
+ Action action = new Action(Messages.LogView_copy) {
+ @Override
+ public void run() {
+ copyToClipboard(fFilteredTree.getViewer().getStructuredSelection());
+ }
+ };
+ action.setImageDescriptor(PlatformUI.getWorkbench().getSharedImages().getImageDescriptor(ISharedImages.IMG_TOOL_COPY));
+ return action;
+ }
+
+ private Action createDeleteLogAction() {
+ Action action = new Action(Messages.LogView_delete) {
+ @Override
+ public void run() {
+ doDeleteLog();
+ }
+ };
+ action.setToolTipText(Messages.LogView_delete_tooltip);
+ action.setImageDescriptor(SharedImages.getImageDescriptor(SharedImages.DESC_REMOVE_LOG));
+ action.setDisabledImageDescriptor(SharedImages.getImageDescriptor(SharedImages.DESC_REMOVE_LOG_DISABLED));
+ action.setEnabled(fInputFile.exists() && fInputFile.equals(Platform.getLogFileLocation().toFile()));
+ return action;
+ }
+
+ private Action createExportLogAction() {
+ Action action = new Action(Messages.LogView_export) {
+ @Override
+ public void run() {
+ handleExport(true);
+ }
+ };
+ action.setToolTipText(Messages.LogView_export_tooltip);
+ action.setImageDescriptor(SharedImages.getImageDescriptor(SharedImages.DESC_EXPORT));
+ action.setDisabledImageDescriptor(SharedImages.getImageDescriptor(SharedImages.DESC_EXPORT_DISABLED));
+ action.setEnabled(fInputFile.exists());
+ return action;
+ }
+
+ private Action createExportLogEntryAction() {
+ Action action = new Action(Messages.LogView_exportEntry) {
+ @Override
+ public void run() {
+ handleExport(false);
+ }
+ };
+ action.setToolTipText(Messages.LogView_exportEntry_tooltip);
+ action.setImageDescriptor(SharedImages.getImageDescriptor(SharedImages.DESC_EXPORT));
+ action.setDisabledImageDescriptor(SharedImages.getImageDescriptor(SharedImages.DESC_EXPORT_DISABLED));
+ action.setEnabled(!fFilteredTree.getViewer().getSelection().isEmpty());
+ return action;
+ }
+
+ private Action createFilterAction() {
+ Action action = new Action(Messages.LogView_filter) {
+ @Override
+ public void run() {
+ handleFilter();
+ }
+ };
+ action.setToolTipText(Messages.LogView_filter);
+ action.setImageDescriptor(SharedImages.getImageDescriptor(SharedImages.DESC_FILTER));
+ action.setDisabledImageDescriptor(SharedImages.getImageDescriptor(SharedImages.DESC_FILTER_DISABLED));
+ return action;
+ }
+
+ private Action createImportLogAction() {
+ Action action = new ImportLogAction(this, Messages.LogView_import, fMemento);
+ action.setToolTipText(Messages.LogView_import_tooltip);
+ action.setImageDescriptor(SharedImages.getImageDescriptor(SharedImages.DESC_IMPORT));
+ action.setDisabledImageDescriptor(SharedImages.getImageDescriptor(SharedImages.DESC_IMPORT_DISABLED));
+ return action;
+ }
+
+ private Action createOpenLogAction() {
+ Action action = null;
+ try {
+ // TODO this isn't the best way to check... we should be smarter and use package admin
+ // check to see if org.eclipse.ui.ide is available
+ Class.forName("org.eclipse.ui.ide.IDE"); //$NON-NLS-1$
+ // check to see if org.eclipse.core.filesystem is available
+ Class.forName("org.eclipse.core.filesystem.IFileStore"); //$NON-NLS-1$
+ action = new OpenIDELogFileAction(this);
+ } catch (ClassNotFoundException e) {
+ action = new Action() {
+ @Override
+ public void run() {
+ if (fInputFile.exists()) {
+ Job job = getOpenLogFileJob();
+ job.setUser(false);
+ job.setPriority(Job.SHORT);
+ job.schedule();
+ }
+ }
+ };
+ }
+ action.setText(Messages.LogView_view_currentLog);
+ action.setImageDescriptor(SharedImages.getImageDescriptor(SharedImages.DESC_OPEN_LOG));
+ action.setDisabledImageDescriptor(SharedImages.getImageDescriptor(SharedImages.DESC_OPEN_LOG_DISABLED));
+ action.setEnabled(fInputFile.exists());
+ action.setToolTipText(Messages.LogView_view_currentLog_tooltip);
+ return action;
+ }
+
+ private Action createPropertiesAction() {
+ Action action = new EventDetailsDialogAction(this, fTree, fFilteredTree.getViewer(), fMemento);
+ action.setImageDescriptor(SharedImages.getImageDescriptor(SharedImages.DESC_PROPERTIES));
+ action.setDisabledImageDescriptor(SharedImages.getImageDescriptor(SharedImages.DESC_PROPERTIES_DISABLED));
+ action.setToolTipText(Messages.LogView_properties_tooltip);
+ action.setEnabled(false);
+ return action;
+ }
+
+ private Action createReadLogAction() {
+ Action action = new Action(Messages.LogView_readLog_restore) {
+ @Override
+ public void run() {
+ fInputFile = Platform.getLogFileLocation().toFile();
+ reloadLog();
+ }
+ };
+ action.setToolTipText(Messages.LogView_readLog_restore_tooltip);
+ action.setImageDescriptor(SharedImages.getImageDescriptor(SharedImages.DESC_READ_LOG));
+ action.setDisabledImageDescriptor(SharedImages.getImageDescriptor(SharedImages.DESC_READ_LOG_DISABLED));
+ return action;
+ }
+
+ /**
+ * Creates the Show Text Filter view menu action
+ * @return the new action for the Show Text Filter
+ */
+ private Action createShowTextFilter() {
+ Action action = new Action(Messages.LogView_show_filter_text) {
+ @Override
+ public void run() {
+ showFilterText(isChecked());
+ }
+ };
+ boolean visible = fMemento.getBoolean(P_SHOW_FILTER_TEXT).booleanValue();
+ action.setChecked(visible);
+ showFilterText(visible);
+ return action;
+ }
+
+ /**
+ * Shows/hides the filter text control from the filtered tree. This method also sets the
+ * P_SHOW_FILTER_TEXT preference to the visible state
+ *
+ * @param visible if the filter text control should be shown or not
+ */
+ private void showFilterText(boolean visible) {
+ fMemento.putBoolean(P_SHOW_FILTER_TEXT, visible);
+
+ Text filterControl = fFilteredTree.getFilterControl();
+ Composite filterComposite = filterControl.getParent(); // FilteredTree new look lays filter Text on additional composite
+
+ GridData gd = (GridData) filterComposite.getLayoutData();
+ gd.exclude = !visible;
+ filterComposite.setVisible(visible);
+
+ // reset control if we aren't visible and if we get visible again
+ filterControl.setText(Messages.LogView_show_filter_initialText);
+
+ if (visible) {
+ filterControl.selectAll();
+ setFocus();
+ }
+
+ fFilteredTree.layout(false);
+ }
+
+ private IContributionItem createGroupByAction() {
+ IMenuManager manager = new MenuManager(Messages.LogView_GroupBy);
+ manager.add(new GroupByAction(Messages.LogView_GroupBySession, LogView.GROUP_BY_SESSION));
+ manager.add(new GroupByAction(Messages.LogView_GroupByPlugin, LogView.GROUP_BY_PLUGIN));
+ manager.add(new GroupByAction(Messages.LogView_GroupByNone, LogView.GROUP_BY_NONE));
+ return manager;
+ }
+
+ private void createViewer(Composite parent) {
+ PatternFilter filter = new PatternFilter() {
+ @Override
+ protected boolean isLeafMatch(Viewer viewer, Object element) {
+ if (element instanceof LogEntry) {
+ LogEntry logEntry = (LogEntry) element;
+ String message = logEntry.getMessage();
+ String plugin = logEntry.getPluginId();
+ DateFormat dateFormat = DateFormat.getDateTimeInstance(DateFormat.SHORT, DateFormat.SHORT);
+ String date = dateFormat.format(logEntry.getDate());
+ return wordMatches(message) || wordMatches(plugin) || wordMatches(date);
+ }
+ return false;
+ }
+ };
+ filter.setIncludeLeadingWildcard(true);
+ fFilteredTree = new FilteredTree(parent, SWT.FULL_SELECTION, filter, true);
+ // need to give filter Textbox some space from the border
+ if (fFilteredTree.getFilterControl() != null) {
+ Composite filterComposite = fFilteredTree.getFilterControl().getParent(); // FilteredTree new look lays filter Text on additional composite
+ GridData gd = (GridData) filterComposite.getLayoutData();
+ gd.verticalIndent = 2;
+ gd.horizontalIndent = 1;
+ }
+ fFilteredTree.setLayoutData(new GridData(GridData.FILL_BOTH));
+ fFilteredTree.setInitialText(Messages.LogView_show_filter_initialText);
+ fTree = fFilteredTree.getViewer().getTree();
+ fTree.setLinesVisible(true);
+ createColumns(fTree);
+ fFilteredTree.getViewer().setAutoExpandLevel(2);
+ fFilteredTree.getViewer().setContentProvider(new LogViewContentProvider(this));
+ fFilteredTree.getViewer().setLabelProvider(fLabelProvider = new LogViewLabelProvider(this));
+ fLabelProvider.connect(this);
+ fFilteredTree.getViewer().addSelectionChangedListener(e -> {
+ handleSelectionChanged(e.getStructuredSelection());
+ if (fPropertiesAction.isEnabled())
+ ((EventDetailsDialogAction) fPropertiesAction).resetSelection();
+ });
+ fFilteredTree.getViewer().addDoubleClickListener(event -> {
+ ((EventDetailsDialogAction) fPropertiesAction).setComparator(fComparator);
+ fPropertiesAction.run();
+ });
+ fFilteredTree.getViewer().setInput(this);
+ addMouseListeners();
+ addDragSource();
+ }
+
+ private void createColumns(Tree tree) {
+ fColumn1 = new TreeColumn(tree, SWT.LEFT);
+ fColumn1.setText(Messages.LogView_column_message);
+ fColumn1.setWidth(fMemento.getInteger(P_COLUMN_1).intValue());
+ fColumn1.addSelectionListener(new SelectionAdapter() {
+ @Override
+ public void widgetSelected(SelectionEvent e) {
+ MESSAGE_ORDER *= -1;
+ ViewerComparator comparator = getViewerComparator(MESSAGE);
+ fFilteredTree.getViewer().setComparator(comparator);
+ boolean isComparatorSet = ((EventDetailsDialogAction) fPropertiesAction).resetSelection(MESSAGE, MESSAGE_ORDER);
+ setComparator(MESSAGE);
+ if (!isComparatorSet)
+ ((EventDetailsDialogAction) fPropertiesAction).setComparator(fComparator);
+ fMemento.putInteger(P_ORDER_VALUE, MESSAGE_ORDER);
+ fMemento.putInteger(P_ORDER_TYPE, MESSAGE);
+ setColumnSorting(fColumn1, MESSAGE_ORDER);
+ }
+ });
+
+ fColumn2 = new TreeColumn(tree, SWT.LEFT);
+ fColumn2.setText(Messages.LogView_column_plugin);
+ fColumn2.setWidth(fMemento.getInteger(P_COLUMN_2).intValue());
+ fColumn2.addSelectionListener(new SelectionAdapter() {
+ @Override
+ public void widgetSelected(SelectionEvent e) {
+ PLUGIN_ORDER *= -1;
+ ViewerComparator comparator = getViewerComparator(PLUGIN);
+ fFilteredTree.getViewer().setComparator(comparator);
+ boolean isComparatorSet = ((EventDetailsDialogAction) fPropertiesAction).resetSelection(PLUGIN, PLUGIN_ORDER);
+ setComparator(PLUGIN);
+ if (!isComparatorSet)
+ ((EventDetailsDialogAction) fPropertiesAction).setComparator(fComparator);
+ fMemento.putInteger(P_ORDER_VALUE, PLUGIN_ORDER);
+ fMemento.putInteger(P_ORDER_TYPE, PLUGIN);
+ setColumnSorting(fColumn2, PLUGIN_ORDER);
+ }
+ });
+
+ fColumn3 = new TreeColumn(tree, SWT.LEFT);
+ fColumn3.setText(Messages.LogView_column_date);
+ fColumn3.setWidth(fMemento.getInteger(P_COLUMN_3).intValue());
+ fColumn3.addSelectionListener(new SelectionAdapter() {
+ @Override
+ public void widgetSelected(SelectionEvent e) {
+ DATE_ORDER *= -1;
+ ViewerComparator comparator = getViewerComparator(DATE);
+ fFilteredTree.getViewer().setComparator(comparator);
+ setComparator(DATE);
+ ((EventDetailsDialogAction) fPropertiesAction).setComparator(fComparator);
+ fMemento.putInteger(P_ORDER_VALUE, DATE_ORDER);
+ fMemento.putInteger(P_ORDER_TYPE, DATE);
+ setColumnSorting(fColumn3, DATE_ORDER);
+ }
+ });
+
+ tree.setHeaderVisible(true);
+ }
+
+ private void initializeViewerSorter() {
+ byte orderType = fMemento.getInteger(P_ORDER_TYPE).byteValue();
+ ViewerComparator comparator = getViewerComparator(orderType);
+ fFilteredTree.getViewer().setComparator(comparator);
+ if (orderType == MESSAGE)
+ setColumnSorting(fColumn1, MESSAGE_ORDER);
+ else if (orderType == PLUGIN)
+ setColumnSorting(fColumn2, PLUGIN_ORDER);
+ else if (orderType == DATE)
+ setColumnSorting(fColumn3, DATE_ORDER);
+ }
+
+ private void setColumnSorting(TreeColumn column, int order) {
+ fTree.setSortColumn(column);
+ fTree.setSortDirection(order == ASCENDING ? SWT.UP : SWT.DOWN);
+ }
+
+ @Override
+ public void dispose() {
+ writeSettings();
+ Platform.removeLogListener(this);
+ fClipboard.dispose();
+ if (fTextShell != null)
+ fTextShell.dispose();
+ fLabelProvider.disconnect(this);
+ fFilteredTree.dispose();
+ super.dispose();
+ }
+
+ /**
+ * Import log from file selected in FileDialog.
+ */
+ void handleImport() {
+ FileDialog dialog = new FileDialog(getViewSite().getShell());
+ dialog.setFilterExtensions(new String[] {"*.log"}); //$NON-NLS-1$
+ if (fDirectory != null)
+ dialog.setFilterPath(fDirectory);
+ String path = dialog.open();
+ if (path == null) { // cancel
+ return;
+ }
+
+ File file = new Path(path).toFile();
+ if (file.exists()) {
+ handleImportPath(path);
+ } else {
+ String msg = NLS.bind(Messages.LogView_FileCouldNotBeFound, file.getName());
+ MessageDialog.openError(getViewSite().getShell(), Messages.LogView_OpenFile, msg);
+ }
+ }
+
+ /**
+ * Import log from given file path. Do nothing if file not exists.
+ * @param path path to log file.
+ */
+ public void handleImportPath(String path) {
+ File file = new File(path);
+ if (path != null && file.exists()) {
+ setLogFile(file);
+ }
+ }
+
+ /**
+ * Import log from given file path.
+ * @param path path to log file.
+ */
+ protected void setLogFile(File path) {
+ fInputFile = path;
+ fDirectory = fInputFile.getParent();
+ IRunnableWithProgress op = monitor -> {
+ monitor.beginTask(Messages.LogView_operation_importing, IProgressMonitor.UNKNOWN);
+ readLogFile();
+ };
+ ProgressMonitorDialog pmd = new ProgressMonitorDialog(getViewSite().getShell());
+ try {
+ pmd.run(true, true, op);
+ } catch (InvocationTargetException e) { // do nothing
+ } catch (InterruptedException e) { // do nothing
+ } finally {
+ fReadLogAction.setText(Messages.LogView_readLog_reload);
+ fReadLogAction.setToolTipText(Messages.LogView_readLog_reload);
+ asyncRefresh(false);
+ resetDialogButtons();
+ }
+ }
+
+ private void handleExport(boolean exportWholeLog) {
+ FileDialog dialog = new FileDialog(getViewSite().getShell(), SWT.SAVE);
+ dialog.setFilterExtensions(new String[] {"*.log"}); //$NON-NLS-1$
+ if (fDirectory != null)
+ dialog.setFilterPath(fDirectory);
+ String path = dialog.open();
+ if (path != null) {
+ if (path.indexOf('.') == -1 && !path.endsWith(".log")) //$NON-NLS-1$
+ path += ".log"; //$NON-NLS-1$
+ File outputFile = new Path(path).toFile();
+ fDirectory = outputFile.getParent();
+ if (outputFile.exists()) {
+ String message = NLS.bind(Messages.LogView_confirmOverwrite_message, outputFile.toString());
+ if (!MessageDialog.openQuestion(getViewSite().getShell(), (exportWholeLog ? Messages.LogView_exportLog : Messages.LogView_exportLogEntry), message))
+ return;
+ }
+
+ BufferedReader in = null;
+ try (BufferedWriter out = new BufferedWriter(
+ new OutputStreamWriter(new FileOutputStream(outputFile), StandardCharsets.UTF_8));) {
+ // $NON-NLS-1$
+ if (exportWholeLog) {
+ in = new BufferedReader(
+ new InputStreamReader(new FileInputStream(fInputFile), StandardCharsets.UTF_8));
+ } else {
+ String selectedEntryAsString = selectionToString(
+ fFilteredTree.getViewer().getStructuredSelection());
+ in = new BufferedReader(new StringReader(selectedEntryAsString));
+ }
+ copy(in, out);
+ } catch (IOException ex) {
+ // do nothing
+ } finally {
+ try {
+ if (in != null)
+ in.close();
+ } catch (IOException e) {
+ // do nothing
+ }
+ }
+ }
+ }
+
+ private void copy(BufferedReader reader, BufferedWriter writer) throws IOException {
+ String line;
+ while (reader.ready() && ((line = reader.readLine()) != null)) {
+ writer.write(line);
+ writer.newLine();
+ }
+ }
+
+ private void handleFilter() {
+ FilterDialog dialog = new FilterDialog(getSite().getShell(), fMemento);
+ dialog.create();
+ dialog.getShell().setText(Messages.LogView_FilterDialog_title);
+ if (dialog.open() == Window.OK)
+ reloadLog();
+ }
+
+
+ private void doDeleteLog() {
+ String title = Messages.LogView_confirmDelete_title;
+ String message = Messages.LogView_confirmDelete_message;
+ int open = MessageDialog.open(MessageDialog.CONFIRM, fTree.getShell(), title, message, SWT.NONE,
+ Messages.LogView_confirmDelete_deleteButton, IDialogConstants.CANCEL_LABEL);
+
+ if (open != Window.OK) {
+ return;
+ }
+ if (fInputFile.delete() || elements.size() > 0) {
+ handleClear();
+ }
+ }
+
+ public void fillContextMenu(IMenuManager manager) { // nothing
+ }
+
+ public synchronized AbstractEntry[] getElements() {
+ return elements.toArray(new AbstractEntry[elements.size()]);
+ }
+
+ protected void handleClear() {
+ BusyIndicator.showWhile(fTree.getDisplay(), () -> {
+ synchronized (this) {
+ elements.clear();
+ groups.clear();
+ }
+ if (currentSession != null) {
+ currentSession.removeAllChildren();
+ }
+ asyncRefresh(false);
+ resetDialogButtons();
+ });
+ }
+
+ /**
+ * Reloads the log
+ */
+ protected void reloadLog() {
+ IRunnableWithProgress op = monitor -> {
+ monitor.beginTask(Messages.LogView_operation_reloading, IProgressMonitor.UNKNOWN);
+ readLogFile();
+ };
+ ProgressMonitorDialog pmd = new ProgressMonitorDialog(getViewSite().getShell());
+ try {
+ pmd.run(true, true, op);
+ } catch (InvocationTargetException e) { // do nothing
+ } catch (InterruptedException e) { // do nothing
+ } finally {
+ fReadLogAction.setText(Messages.LogView_readLog_restore);
+ fReadLogAction.setToolTipText(Messages.LogView_readLog_restore);
+ asyncRefresh(false);
+ resetDialogButtons();
+ }
+ }
+
+ /**
+ * Reads the chosen backing log file
+ */
+ void readLogFile() {
+ synchronized (this) {
+ elements.clear();
+ groups.clear();
+ }
+
+ List<LogEntry> result = new ArrayList<>();
+ LogSession lastLogSession = LogReader.parseLogFile(this.fInputFile, getLogMaxTailSize(), result, this.fMemento);
+ if (lastLogSession != null && (lastLogSession.getDate() == null || isEclipseStartTime(lastLogSession.getDate()))) {
+ currentSession = lastLogSession;
+ } else {
+ currentSession = null;
+ }
+
+ group(result);
+ limitEntriesCount();
+
+ getSite().getShell().getDisplay().asyncExec(() -> setContentDescription(getTitleSummary()));
+
+ }
+
+ private boolean isEclipseStartTime(Date date) {
+ String ts = System.getProperty("eclipse.startTime"); //$NON-NLS-1$
+ try {
+ return (ts != null && date.getTime() == Long.parseLong(ts));
+ } catch (NumberFormatException e) {
+ // empty
+ }
+ return false;
+ }
+
+ private String getTitleSummary() {
+ String path = ""; //$NON-NLS-1$
+ try {
+ path = fInputFile.getCanonicalPath();
+ } catch (IOException e) { // log nothing
+ }
+
+ if (isPlatformLogOpen()) {
+ return Messages.LogView_WorkspaceLogFile;
+ }
+
+ Map<String, String> sources = LogFilesManager.getLogSources();
+ if (sources.containsValue(path)) {
+ for (Entry<String, String> entry : sources.entrySet()) {
+ String key = entry.getKey();
+ if (entry.getValue().equals(path)) {
+ return NLS.bind(Messages.LogView_LogFileTitle, new String[] {key, path});
+ }
+ }
+ }
+
+ return path;
+ }
+
+ /**
+ * Add new entries to correct groups in the view.
+ * @param entries new entries to show up in groups in the view.
+ */
+ private void group(List<LogEntry> entries) {
+ if (fMemento.getInteger(P_GROUP_BY).intValue() == GROUP_BY_NONE) {
+ elements.addAll(entries);
+ } else {
+ for (Iterator<LogEntry> i = entries.iterator(); i.hasNext();) {
+ LogEntry entry = i.next();
+ Group group = getGroup(entry);
+ group.addChild(entry);
+ }
+ }
+ }
+
+ /**
+ * Limits the number of entries according to the max entries limit set in
+ * memento.
+ */
+ private synchronized void limitEntriesCount() {
+ int limit = Integer.MAX_VALUE;
+ if (fMemento.getString(LogView.P_USE_LIMIT).equals("true")) {//$NON-NLS-1$
+ limit = fMemento.getInteger(LogView.P_LOG_LIMIT).intValue();
+ }
+
+ int entriesCount = getEntriesCount();
+
+ if (entriesCount <= limit) {
+ return;
+ }
+ Comparator<LogEntry> dateComparator = (o1, o2) -> {
+ Date l1 = o1.getDate();
+ Date l2 = o2.getDate();
+ if ((l1 != null) && (l2 != null)) {
+ return l1.before(l2) ? -1 : 1;
+ } else if ((l1 == null) && (l2 == null)) {
+ return 0;
+ } else
+ return (l1 == null) ? -1 : 1;
+ };
+
+ if (fMemento.getInteger(P_GROUP_BY).intValue() == GROUP_BY_NONE) {
+ elements.subList(0, elements.size() - limit).clear();
+ } else {
+ List copy = new ArrayList(entriesCount);
+ for (Iterator<AbstractEntry> i = elements.iterator(); i.hasNext();) {
+ AbstractEntry group = i.next();
+ copy.addAll(Arrays.asList(group.getChildren(group)));
+ }
+
+ Collections.sort(copy, dateComparator);
+ List toRemove = copy.subList(0, copy.size() - limit);
+
+ for (Iterator<AbstractEntry> i = elements.iterator(); i.hasNext();) {
+ AbstractEntry group = i.next();
+ group.removeChildren(toRemove);
+ }
+ }
+
+ }
+
+ private int getEntriesCount() {
+ if (fMemento.getInteger(P_GROUP_BY).intValue() == GROUP_BY_NONE) {
+ return elements.size();
+ }
+ int size = 0;
+ for (Iterator<AbstractEntry> i = elements.iterator(); i.hasNext();) {
+ AbstractEntry group = i.next();
+ size += group.size();
+ }
+ return size;
+ }
+
+ /**
+ * Returns group appropriate for the entry. Group depends on P_GROUP_BY
+ * preference, or is null if grouping is disabled (GROUP_BY_NONE), or group
+ * could not be determined. May create group if it haven't existed before.
+ *
+ * @param entry entry to be grouped
+ * @return group or null if grouping is disabled
+ */
+ protected Group getGroup(LogEntry entry) {
+ int groupBy = fMemento.getInteger(P_GROUP_BY).intValue();
+ Object elementGroupId = null;
+ String groupName = null;
+
+ switch (groupBy) {
+ case GROUP_BY_PLUGIN :
+ groupName = entry.getPluginId();
+ elementGroupId = groupName;
+ break;
+
+ case GROUP_BY_SESSION :
+ elementGroupId = entry.getSession();
+ break;
+
+ default : // grouping is disabled
+ return null;
+ }
+
+ if (elementGroupId == null) { // could not determine group
+ return null;
+ }
+
+ Group group = groups.get(elementGroupId);
+ if (group == null) {
+ if (groupBy == GROUP_BY_SESSION) {
+ group = entry.getSession();
+ } else {
+ group = new Group(groupName);
+ }
+ groups.put(elementGroupId, group);
+ elements.add(group);
+ }
+
+ return group;
+ }
+
+ @Override
+ public void logging(IStatus status, String plugin) {
+ if (!isPlatformLogOpen())
+ return;
+
+ if (batchEntries) {
+ // create LogEntry immediately to don't loose IStatus creation date.
+ LogEntry entry = createLogEntry(status);
+ batchedEntries.add(entry);
+ return;
+ }
+
+ if (fFirstEvent || (currentSession == null)) {
+ readLogFile();
+ asyncRefresh(true);
+ fFirstEvent = false;
+ } else {
+ LogEntry entry = createLogEntry(status);
+
+ if (!batchedEntries.isEmpty()) {
+ // batch new entry as well, to have only one asyncRefresh()
+ batchedEntries.add(entry);
+ pushBatchedEntries();
+ } else {
+ pushEntry(entry);
+ asyncRefresh(true);
+ }
+ }
+ }
+
+ /**
+ * Push batched entries to log view.
+ */
+ private void pushBatchedEntries() {
+ Job job = new Job(Messages.LogView_AddingBatchedEvents) {
+ @Override
+ protected IStatus run(IProgressMonitor monitor) {
+ for (int i = 0; i < batchedEntries.size(); i++) {
+ if (!monitor.isCanceled()) {
+ LogEntry entry = batchedEntries.get(i);
+ pushEntry(entry);
+ batchedEntries.remove(i);
+ }
+ }
+ asyncRefresh(true);
+ return Status.OK_STATUS;
+ }
+ };
+ job.schedule();
+ }
+
+ private LogEntry createLogEntry(IStatus status) {
+ LogEntry entry = new LogEntry(status, currentSession);
+
+ if (status.getException() instanceof CoreException) {
+ IStatus coreStatus = ((CoreException) status.getException()).getStatus();
+ if (coreStatus != null) {
+ LogEntry childEntry = createLogEntry(coreStatus);
+ entry.addChild(childEntry);
+ }
+ }
+
+ return entry;
+ }
+
+ private synchronized void pushEntry(LogEntry entry) {
+ if (LogReader.isLogged(entry, fMemento)) {
+ group(Collections.singletonList(entry));
+ limitEntriesCount();
+ }
+ asyncRefresh(true);
+ }
+
+ private void asyncRefresh(final boolean activate) {
+ if (fTree.isDisposed())
+ return;
+ Display display = fTree.getDisplay();
+ final ViewPart view = this;
+ if (display != null) {
+ display.asyncExec(() -> {
+ if (!fTree.isDisposed()) {
+ TreeViewer viewer = fFilteredTree.getViewer();
+ viewer.refresh();
+ viewer.expandToLevel(2);
+ fDeleteLogAction.setEnabled(
+ fInputFile.exists() && fInputFile.equals(Platform.getLogFileLocation().toFile()));
+ fOpenLogAction.setEnabled(fInputFile.exists());
+ fExportLogAction.setEnabled(fInputFile.exists());
+ fExportLogEntryAction.setEnabled(!viewer.getSelection().isEmpty());
+ if (activate && fActivateViewAction.isChecked()) {
+ IWorkbenchWindow window = PlatformUI.getWorkbench().getActiveWorkbenchWindow();
+ if (window != null) {
+ IWorkbenchPage page = window.getActivePage();
+ if (page != null) {
+ page.bringToTop(view);
+ }
+ }
+ }
+ }
+ });
+ }
+ }
+
+ @Override
+ public void setFocus() {
+ if (fFilteredTree != null) {
+ if (fMemento.getBoolean(P_SHOW_FILTER_TEXT).booleanValue()) {
+ Text filterControl = fFilteredTree.getFilterControl();
+ if (filterControl != null && !filterControl.isDisposed()) {
+ filterControl.setFocus();
+ }
+ } else if (!fFilteredTree.isDisposed()) {
+ fFilteredTree.setFocus();
+ }
+ }
+ }
+
+ private void handleSelectionChanged(IStructuredSelection selection) {
+ updateStatus(selection);
+ updateSelectionStack(selection);
+ fCopyAction.setEnabled((!selection.isEmpty()) && selection.getFirstElement() != null);
+ fPropertiesAction.setEnabled(!selection.isEmpty());
+ fExportLogEntryAction.setEnabled(!selection.isEmpty());
+ }
+
+ private void updateSelectionStack(IStructuredSelection selection) {
+ fSelectedStack = null;
+ Object firstObject = selection.getFirstElement();
+ if (firstObject instanceof LogEntry) {
+ String stack = ((LogEntry) firstObject).getStack();
+ if (stack != null && stack.length() > 0) {
+ fSelectedStack = stack;
+ }
+ }
+ }
+
+ private void updateStatus(IStructuredSelection selection) {
+ IStatusLineManager status = getViewSite().getActionBars().getStatusLineManager();
+ if (selection.isEmpty())
+ status.setMessage(null);
+ else {
+ Object element = selection.getFirstElement();
+ status.setMessage(((LogViewLabelProvider) fFilteredTree.getViewer().getLabelProvider()).getColumnText(element, 0));
+ }
+ }
+
+ /**
+ * Converts selected log view element to string.
+ * @return textual log entry representation or null if selection doesn't contain log entry
+ */
+ private static String selectionToString(IStructuredSelection selection) {
+ String textVersion = null;
+ try (StringWriter writer = new StringWriter(); PrintWriter pwriter = new PrintWriter(writer)) {
+ if (selection.isEmpty())
+ return null;
+ AbstractEntry entry = (AbstractEntry) selection.getFirstElement();
+ entry.write(pwriter);
+ pwriter.flush();
+ textVersion = writer.toString();
+ } catch (IOException e) {
+ // empty
+ }
+ return textVersion;
+ }
+
+ /**
+ * Copies selected element to clipboard.
+ */
+ private void copyToClipboard(IStructuredSelection selection) {
+ String textVersion = selectionToString(selection);
+ if ((textVersion != null) && (textVersion.trim().length() > 0)) {
+ // set the clipboard contents
+ fClipboard.setContents(new Object[] {textVersion}, new Transfer[] {TextTransfer.getInstance()});
+ }
+ }
+
+ @Override
+ public void init(IViewSite site, IMemento memento) throws PartInitException {
+ super.init(site, memento);
+ if (memento == null)
+ this.fMemento = XMLMemento.createWriteRoot("LOGVIEW"); //$NON-NLS-1$
+ else
+ this.fMemento = memento;
+ readSettings();
+
+ // initialize column ordering
+ final byte type = this.fMemento.getInteger(P_ORDER_TYPE).byteValue();
+ switch (type) {
+ case DATE :
+ DATE_ORDER = this.fMemento.getInteger(P_ORDER_VALUE).intValue();
+ MESSAGE_ORDER = DESCENDING;
+ PLUGIN_ORDER = DESCENDING;
+ break;
+ case MESSAGE :
+ MESSAGE_ORDER = this.fMemento.getInteger(P_ORDER_VALUE).intValue();
+ DATE_ORDER = DESCENDING;
+ PLUGIN_ORDER = DESCENDING;
+ break;
+ case PLUGIN :
+ PLUGIN_ORDER = this.fMemento.getInteger(P_ORDER_VALUE).intValue();
+ MESSAGE_ORDER = DESCENDING;
+ DATE_ORDER = DESCENDING;
+ break;
+ default :
+ DATE_ORDER = DESCENDING;
+ MESSAGE_ORDER = DESCENDING;
+ PLUGIN_ORDER = DESCENDING;
+ }
+ setComparator(fMemento.getInteger(P_ORDER_TYPE).byteValue());
+ }
+
+ private void initializeMemento() {
+ if (fMemento.getString(P_USE_LIMIT) == null) {
+ fMemento.putString(P_USE_LIMIT, "true"); //$NON-NLS-1$
+ }
+ if (fMemento.getInteger(P_LOG_LIMIT) == null) {
+ fMemento.putInteger(P_LOG_LIMIT, 50);
+ }
+ if (fMemento.getString(P_LOG_INFO) == null) {
+ fMemento.putString(P_LOG_INFO, "true"); //$NON-NLS-1$
+ }
+ if (fMemento.getString(P_LOG_OK) == null) {
+ fMemento.putString(P_LOG_OK, "true"); //$NON-NLS-1$
+ }
+ if (fMemento.getString(P_LOG_WARNING) == null) {
+ fMemento.putString(P_LOG_WARNING, "true"); //$NON-NLS-1$
+ }
+ if (fMemento.getString(P_LOG_ERROR) == null) {
+ fMemento.putString(P_LOG_ERROR, "true"); //$NON-NLS-1$
+ }
+ if (fMemento.getString(P_SHOW_ALL_SESSIONS) == null) {
+ fMemento.putString(P_SHOW_ALL_SESSIONS, "true"); //$NON-NLS-1$
+ }
+ }
+
+ @Override
+ public void saveState(IMemento memento) {
+ if (this.fMemento == null || memento == null)
+ return;
+ //store some sane values to prevent the view from being broken
+ this.fMemento.putInteger(P_COLUMN_1, getColumnWidth(fColumn1, 300));
+ this.fMemento.putInteger(P_COLUMN_2, getColumnWidth(fColumn2, 150));
+ this.fMemento.putInteger(P_COLUMN_3, getColumnWidth(fColumn3, 150));
+ this.fMemento.putString(P_ACTIVATE, fActivateViewAction.isChecked() ? "true" : "false"); //$NON-NLS-1$ //$NON-NLS-2$
+ memento.putMemento(this.fMemento);
+ writeSettings();
+ }
+
+ /**
+ * Returns the width of the column or the default value if the column has been resized to be not visible
+ * @param column the column to get the width from
+ * @param defaultwidth the width to return if the column has been resized to not be visible
+ * @return the width of the column or the default value
+ *
+ * @since 3.6
+ */
+ int getColumnWidth(TreeColumn column, int defaultwidth) {
+ int width = column.getWidth();
+ return width < 1 ? defaultwidth : width;
+ }
+
+ private void addMouseListeners() {
+ Listener tableListener = e -> {
+ switch (e.type) {
+ case SWT.MouseExit:
+ case SWT.MouseMove:
+ onMouseMove(e);
+ break;
+ case SWT.MouseHover:
+ onMouseHover(e);
+ break;
+ case SWT.MouseDown:
+ onMouseDown(e);
+ break;
+ }
+ };
+ int[] tableEvents = new int[] {SWT.MouseDown, SWT.MouseMove, SWT.MouseHover, SWT.MouseExit};
+ for (int tableEvent : tableEvents) {
+ fTree.addListener(tableEvent, tableListener);
+ }
+ }
+
+ /**
+ * Adds drag source support to error log tree.
+ */
+ private void addDragSource() {
+ DragSource source = new DragSource(fTree, DND.DROP_COPY);
+ Transfer[] types = new Transfer[] {TextTransfer.getInstance()};
+ source.setTransfer(types);
+
+ source.addDragListener(new DragSourceAdapter() {
+
+ @Override
+ public void dragStart(DragSourceEvent event) {
+ ISelection selection = fFilteredTree.getViewer().getSelection();
+ if (selection.isEmpty()) {
+ event.doit = false;
+ return;
+ }
+
+ AbstractEntry entry = (AbstractEntry) ((TreeSelection) selection).getFirstElement();
+ if (!(entry instanceof LogEntry)) {
+ event.doit = false;
+ return;
+ }
+ }
+
+ @Override
+ public void dragSetData(DragSourceEvent event) {
+ if (!TextTransfer.getInstance().isSupportedType(event.dataType)) {
+ return;
+ }
+
+ IStructuredSelection selection = fFilteredTree.getViewer().getStructuredSelection();
+ String textVersion = selectionToString(selection);
+ event.data = textVersion;
+ }
+ });
+ }
+
+ private void makeHoverShell() {
+ // parent it off the workbench window's shell so it will be valid regardless of whether the view is a detached window or not
+ fTextShell = new Shell(getSite().getWorkbenchWindow().getShell(), SWT.NO_FOCUS | SWT.ON_TOP | SWT.TOOL);
+ GridLayout layout = new GridLayout(1, false);
+ int border = ((fTree.getShell().getStyle() & SWT.NO_TRIM) == 0) ? 0 : 1;
+ layout.marginHeight = border;
+ layout.marginWidth = border;
+ fTextShell.setLayout(layout);
+ fTextShell.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
+ Composite shellComposite = new Composite(fTextShell, SWT.NONE);
+ layout = new GridLayout();
+ layout.marginHeight = 0;
+ layout.marginWidth = 0;
+ shellComposite.setLayout(layout);
+ shellComposite.setLayoutData(new GridData(GridData.FILL_BOTH | GridData.VERTICAL_ALIGN_BEGINNING));
+ fTextLabel = new Text(shellComposite, SWT.WRAP | SWT.MULTI | SWT.READ_ONLY);
+ GridData gd = new GridData(GridData.FILL_BOTH);
+ gd.widthHint = 100;
+ gd.grabExcessHorizontalSpace = true;
+ fTextLabel.setLayoutData(gd);
+ fTextLabel.setEditable(false);
+ fTextShell.addDisposeListener(e -> onTextShellDispose(e));
+ }
+
+ void onTextShellDispose(DisposeEvent e) {
+ fCanOpenTextShell = true;
+ setFocus();
+ }
+
+ void onMouseDown(Event e) {
+ if (fTextShell != null && !fTextShell.isDisposed() && !fTextShell.isFocusControl()) {
+ fTextShell.setVisible(false);
+ fCanOpenTextShell = true;
+ }
+ }
+
+ void onMouseHover(Event e) {
+ if (!fCanOpenTextShell || fTextShell == null || fTextShell.isDisposed())
+ return;
+ fCanOpenTextShell = false;
+ Point point = new Point(e.x, e.y);
+ TreeItem item = fTree.getItem(point);
+ if (item == null)
+ return;
+
+ String message = null;
+ if (item.getData() instanceof LogEntry) {
+ message = ((LogEntry) item.getData()).getStack();
+ } else if (item.getData() instanceof LogSession) {
+ LogSession session = ((LogSession) item.getData());
+ message = Messages.LogView_SessionStarted;
+ if (session.getDate() != null) {
+ DateFormat formatter = new SimpleDateFormat(LogEntry.F_DATE_FORMAT);
+ message += formatter.format(session.getDate());
+ }
+ }
+
+ if (message == null)
+ return;
+
+ fTextLabel.setText(message);
+ Rectangle bounds = fTree.getDisplay().getBounds();
+ Point cursorPoint = fTree.getDisplay().getCursorLocation();
+ int x = point.x;
+ int y = point.y + 25;
+ int width = fTree.getColumn(0).getWidth();
+ int height = 125;
+ if (cursorPoint.x + width > bounds.width)
+ x -= width;
+ if (cursorPoint.y + height + 25 > bounds.height)
+ y -= height + 27;
+
+ fTextShell.setLocation(fTree.toDisplay(x, y));
+ fTextShell.setSize(width, height);
+ fTextShell.setVisible(true);
+ }
+
+ void onMouseMove(Event e) {
+ if (fTextShell != null && !fTextShell.isDisposed() && fTextShell.isVisible())
+ fTextShell.setVisible(false);
+
+ Point point = new Point(e.x, e.y);
+ TreeItem item = fTree.getItem(point);
+ if (item == null)
+ return;
+ Image image = item.getImage();
+ Object data = item.getData();
+ if (data instanceof LogEntry) {
+ LogEntry entry = (LogEntry) data;
+ int parentCount = getNumberOfParents(entry);
+ int startRange = 20 + Math.max(image.getBounds().width + 2, 7 + 2) * parentCount;
+ int endRange = startRange + 16;
+ fCanOpenTextShell = e.x >= startRange && e.x <= endRange;
+ }
+ }
+
+ private int getNumberOfParents(AbstractEntry entry) {
+ AbstractEntry parent = (AbstractEntry) entry.getParent(entry);
+ if (parent == null)
+ return 0;
+ return 1 + getNumberOfParents(parent);
+ }
+
+ public Comparator getComparator() {
+ return fComparator;
+ }
+
+ private void setComparator(byte sortType) {
+ if (sortType == DATE) {
+ fComparator = (e1, e2) -> {
+ long date1 = 0;
+ long date2 = 0;
+ if ((e1 instanceof LogEntry) && (e2 instanceof LogEntry)) {
+ date1 = ((LogEntry) e1).getDate().getTime();
+ date2 = ((LogEntry) e2).getDate().getTime();
+ } else if ((e1 instanceof LogSession) && (e2 instanceof LogSession)) {
+ date1 = ((LogSession) e1).getDate() == null ? 0 : ((LogSession) e1).getDate().getTime();
+ date2 = ((LogSession) e2).getDate() == null ? 0 : ((LogSession) e2).getDate().getTime();
+ }
+ if (date1 == date2) {
+ int result = elements.indexOf(e2) - elements.indexOf(e1);
+ if (DATE_ORDER == DESCENDING)
+ result *= DESCENDING;
+ return result;
+ }
+ if (DATE_ORDER == DESCENDING)
+ return date1 > date2 ? DESCENDING : ASCENDING;
+ return date1 < date2 ? DESCENDING : ASCENDING;
+ };
+ } else if (sortType == PLUGIN) {
+ fComparator = (e1, e2) -> {
+ if ((e1 instanceof LogEntry) && (e2 instanceof LogEntry)) {
+ LogEntry entry1 = (LogEntry) e1;
+ LogEntry entry2 = (LogEntry) e2;
+ return getDefaultComparator().compare(entry1.getPluginId(), entry2.getPluginId()) * PLUGIN_ORDER;
+ }
+ return 0;
+ };
+ } else {
+ fComparator = (e1, e2) -> {
+ if ((e1 instanceof LogEntry) && (e2 instanceof LogEntry)) {
+ LogEntry entry1 = (LogEntry) e1;
+ LogEntry entry2 = (LogEntry) e2;
+ return getDefaultComparator().compare(entry1.getMessage(), entry2.getMessage()) * MESSAGE_ORDER;
+ }
+ return 0;
+ };
+ }
+ }
+
+ private Comparator<Object> getDefaultComparator() {
+ return Policy.getComparator();
+ }
+
+ private ViewerComparator getViewerComparator(byte sortType) {
+ if (sortType == PLUGIN) {
+ return new ViewerComparator() {
+ @Override
+ public int compare(Viewer viewer, Object e1, Object e2) {
+ if ((e1 instanceof LogEntry) && (e2 instanceof LogEntry)) {
+ LogEntry entry1 = (LogEntry) e1;
+ LogEntry entry2 = (LogEntry) e2;
+ return getComparator().compare(entry1.getPluginId(), entry2.getPluginId()) * PLUGIN_ORDER;
+ }
+ return 0;
+ }
+ };
+ } else if (sortType == MESSAGE) {
+ return new ViewerComparator() {
+ @Override
+ public int compare(Viewer viewer, Object e1, Object e2) {
+ if ((e1 instanceof LogEntry) && (e2 instanceof LogEntry)) {
+ LogEntry entry1 = (LogEntry) e1;
+ LogEntry entry2 = (LogEntry) e2;
+ return getComparator().compare(entry1.getMessage(), entry2.getMessage()) * MESSAGE_ORDER;
+ }
+ return 0;
+ }
+ };
+ } else {
+ return new ViewerComparator() {
+ private int indexOf(Object[] array, Object o) {
+ if (o == null)
+ return -1;
+ for (int i = 0; i < array.length; ++i)
+ if (o.equals(array[i]))
+ return i;
+ return -1;
+ }
+
+ @Override
+ public int compare(Viewer viewer, Object e1, Object e2) {
+ long date1 = 0;
+ long date2 = 0;
+ if ((e1 instanceof LogEntry) && (e2 instanceof LogEntry)) {
+ date1 = ((LogEntry) e1).getDate().getTime();
+ date2 = ((LogEntry) e2).getDate().getTime();
+ } else if ((e1 instanceof LogSession) && (e2 instanceof LogSession)) {
+ date1 = ((LogSession) e1).getDate() == null ? 0 : ((LogSession) e1).getDate().getTime();
+ date2 = ((LogSession) e2).getDate() == null ? 0 : ((LogSession) e2).getDate().getTime();
+ }
+
+ if (date1 == date2) {
+ // Everything that appears in LogView should be an AbstractEntry.
+ AbstractEntry parent = (AbstractEntry) ((AbstractEntry) e1).getParent(null);
+ Object[] children = null;
+ if (parent != null)
+ children = parent.getChildren(parent);
+
+ int result = 0;
+ if (children != null) {
+ // The elements in children seem to be in reverse order,
+ // i.e. latest log message first, therefore index(e2)-index(e1)
+ result = indexOf(children, e2) - indexOf(children, e1);
+ } else {
+ result = elements.indexOf(e1) - elements.indexOf(e2);
+ }
+ if (DATE_ORDER == DESCENDING)
+ result *= DESCENDING;
+ return result;
+ }
+ if (DATE_ORDER == DESCENDING)
+ return date1 > date2 ? DESCENDING : ASCENDING;
+ return date1 < date2 ? DESCENDING : ASCENDING;
+ }
+ };
+ }
+ }
+
+ private void resetDialogButtons() {
+ ((EventDetailsDialogAction) fPropertiesAction).resetDialogButtons();
+ }
+
+ /**
+ * Returns the filter dialog settings object used to maintain
+ * state between filter dialogs
+ * @return the dialog settings to be used
+ */
+ private IDialogSettings getLogSettings() {
+ IDialogSettings settings = Activator.getDefault().getDialogSettings();
+ return settings.getSection(getClass().getName());
+ }
+
+ /**
+ * Loads any saved {@link IDialogSettings} into the backing view memento
+ */
+ private void readSettings() {
+ IDialogSettings s = getLogSettings();
+ if (s == null) {
+ initializeMemento();
+ } else {
+ fMemento.putString(P_USE_LIMIT, s.getBoolean(P_USE_LIMIT) ? "true" : "false"); //$NON-NLS-1$ //$NON-NLS-2$
+ fMemento.putString(P_LOG_INFO, s.getBoolean(P_LOG_INFO) ? "true" : "false"); //$NON-NLS-1$ //$NON-NLS-2$
+ fMemento.putString(P_LOG_OK, s.getBoolean(P_LOG_OK) ? "true" : "false"); //$NON-NLS-1$ //$NON-NLS-2$
+ fMemento.putString(P_LOG_WARNING, s.getBoolean(P_LOG_WARNING) ? "true" : "false"); //$NON-NLS-1$ //$NON-NLS-2$
+ fMemento.putString(P_LOG_ERROR, s.getBoolean(P_LOG_ERROR) ? "true" : "false"); //$NON-NLS-1$ //$NON-NLS-2$
+ fMemento.putString(P_SHOW_ALL_SESSIONS, s.getBoolean(P_SHOW_ALL_SESSIONS) ? "true" : "false"); //$NON-NLS-1$ //$NON-NLS-2$
+ try {
+ fMemento.putInteger(P_LOG_LIMIT, s.getInt(P_LOG_LIMIT));
+ } catch (NumberFormatException e) {
+ fMemento.putInteger(P_LOG_LIMIT, 50);
+ }
+ }
+
+ Preferences instancePrefs = InstanceScope.INSTANCE.getNode(Activator.PLUGIN_ID);
+ Preferences defaultPrefs = DefaultScope.INSTANCE.getNode(Activator.PLUGIN_ID);
+ fMemento.putInteger(P_COLUMN_1, getColumnWidthPreference(instancePrefs, defaultPrefs, P_COLUMN_1, 300));
+ fMemento.putInteger(P_COLUMN_2, getColumnWidthPreference(instancePrefs, defaultPrefs, P_COLUMN_2, 150));
+ fMemento.putInteger(P_COLUMN_3, getColumnWidthPreference(instancePrefs, defaultPrefs, P_COLUMN_3, 150));
+ fMemento.putBoolean(P_ACTIVATE, instancePrefs.getBoolean(P_ACTIVATE, defaultPrefs.getBoolean(P_ACTIVATE, true)));
+ fMemento.putInteger(P_ORDER_VALUE, instancePrefs.getInt(P_ORDER_VALUE, defaultPrefs.getInt(P_ORDER_VALUE, DESCENDING)));
+ fMemento.putInteger(P_ORDER_TYPE, instancePrefs.getInt(P_ORDER_TYPE, defaultPrefs.getInt(P_ORDER_TYPE, LogView.DATE)));
+ fMemento.putBoolean(P_SHOW_FILTER_TEXT, instancePrefs.getBoolean(P_SHOW_FILTER_TEXT, defaultPrefs.getBoolean(P_SHOW_FILTER_TEXT, true)));
+ fMemento.putInteger(P_GROUP_BY, instancePrefs.getInt(P_GROUP_BY, defaultPrefs.getInt(P_GROUP_BY, LogView.GROUP_BY_NONE)));
+ fMemento.putString(P_LOG_MAX_TAIL_SIZE, String.valueOf(getLogMaxTailSizePreference(instancePrefs, defaultPrefs, DEFAULT_LOG_MAX_TAIL_SIZE)));
+ }
+
+ private long getLogMaxTailSizePreference(Preferences instancePrefs, Preferences defaultPrefs, long defaultMaxLogTailSize) {
+ try {
+ return instancePrefs.getLong(P_LOG_MAX_TAIL_SIZE, defaultPrefs.getLong(P_LOG_MAX_TAIL_SIZE, defaultMaxLogTailSize));
+ } catch (IllegalStateException ex) {
+ return defaultMaxLogTailSize;
+ }
+ }
+
+ private long getLogMaxTailSize() {
+ return Long.valueOf(this.fMemento.getString(P_LOG_MAX_TAIL_SIZE)).longValue();
+ }
+
+ /**
+ * Returns the width to use for the column represented by the given key. The default width
+ * is returned iff:
+ * <ul>
+ * <li>There is no preference for the given key</li>
+ * <li>The returned preference value is too small, making the columns invisible by width.</li>
+ * </ul>
+ * @param instancePrefs
+ * @param defaultPrefs
+ * @param key
+ * @param defaultwidth
+ * @return the stored width for the a column described by the given key or the default width
+ *
+ * @since 3.6
+ */
+ int getColumnWidthPreference(Preferences instancePrefs, Preferences defaultPrefs, String key, int defaultwidth) {
+ int width = instancePrefs.getInt(key, defaultPrefs.getInt(key, defaultwidth));
+ return width < 1 ? defaultwidth : width;
+ }
+
+ private void writeSettings() {
+ writeViewSettings();
+ writeFilterSettings();
+ }
+
+ private void writeFilterSettings() {
+ IDialogSettings settings = getLogSettings();
+ if (settings == null)
+ settings = Activator.getDefault().getDialogSettings().addNewSection(getClass().getName());
+ settings.put(P_USE_LIMIT, fMemento.getString(P_USE_LIMIT).equals("true")); //$NON-NLS-1$
+ settings.put(P_LOG_LIMIT, fMemento.getInteger(P_LOG_LIMIT).intValue());
+ settings.put(P_LOG_INFO, fMemento.getString(P_LOG_INFO).equals("true")); //$NON-NLS-1$
+ settings.put(P_LOG_OK, fMemento.getString(P_LOG_OK).equals("true")); //$NON-NLS-1$
+ settings.put(P_LOG_WARNING, fMemento.getString(P_LOG_WARNING).equals("true")); //$NON-NLS-1$
+ settings.put(P_LOG_ERROR, fMemento.getString(P_LOG_ERROR).equals("true")); //$NON-NLS-1$
+ settings.put(P_SHOW_ALL_SESSIONS, fMemento.getString(P_SHOW_ALL_SESSIONS).equals("true")); //$NON-NLS-1$
+ }
+
+ private void writeViewSettings() {
+ Preferences instancePrefs = (InstanceScope.INSTANCE).getNode(Activator.PLUGIN_ID);
+ instancePrefs.putInt(P_COLUMN_1, fMemento.getInteger(P_COLUMN_1).intValue());
+ instancePrefs.putInt(P_COLUMN_2, fMemento.getInteger(P_COLUMN_2).intValue());
+ instancePrefs.putInt(P_COLUMN_3, fMemento.getInteger(P_COLUMN_3).intValue());
+ instancePrefs.putBoolean(P_ACTIVATE, fMemento.getBoolean(P_ACTIVATE).booleanValue());
+ instancePrefs.putInt(P_ORDER_VALUE, fMemento.getInteger(P_ORDER_VALUE).intValue());
+ instancePrefs.putInt(P_ORDER_TYPE, fMemento.getInteger(P_ORDER_TYPE).intValue());
+ instancePrefs.putBoolean(P_SHOW_FILTER_TEXT, fMemento.getBoolean(P_SHOW_FILTER_TEXT).booleanValue());
+ instancePrefs.putInt(P_GROUP_BY, fMemento.getInteger(P_GROUP_BY).intValue());
+ instancePrefs.putLong(P_LOG_MAX_TAIL_SIZE, getLogMaxTailSize());
+ try {
+ instancePrefs.flush();
+ } catch (BackingStoreException e) {
+ // empty
+ }
+ }
+
+ public void sortByDateDescending() {
+ setColumnSorting(fColumn3, DESCENDING);
+ }
+
+ protected Job getOpenLogFileJob() {
+ final Shell shell = getViewSite().getShell();
+ return new Job(Messages.OpenLogDialog_message) {
+ @Override
+ protected IStatus run(IProgressMonitor monitor) {
+ boolean failed = false;
+ if (fInputFile.length() <= LogReader.MAX_FILE_LENGTH) {
+ failed = !Program.launch(fInputFile.getAbsolutePath());
+ if (failed) {
+ Program p = Program.findProgram(".txt"); //$NON-NLS-1$
+ if (p != null) {
+ p.execute(fInputFile.getAbsolutePath());
+ return Status.OK_STATUS;
+ }
+ }
+ }
+ if (failed) {
+ final OpenLogDialog openDialog = new OpenLogDialog(shell, fInputFile);
+ Display.getDefault().asyncExec(() -> {
+ openDialog.create();
+ openDialog.open();
+ });
+ }
+ return Status.OK_STATUS;
+ }
+ };
+ }
+
+ protected File getLogFile() {
+ return fInputFile;
+ }
+
+ /**
+ * Returns whether given session equals to currently displayed in LogView.
+ * @param session LogSession
+ * @return true if given session equals to currently displayed in LogView
+ */
+ public boolean isCurrentLogSession(LogSession session) {
+ return isPlatformLogOpen() && (currentSession != null) && (currentSession.equals(session));
+ }
+
+ /**
+ * Returns whether currently open log is platform log or imported file.
+ * @return true if currently open log is platform log, false otherwise
+ */
+ public boolean isPlatformLogOpen() {
+ return (fInputFile.equals(Platform.getLogFileLocation().toFile()));
+ }
+
+ /**
+ *
+ */
+ public void setPlatformLog() {
+ setLogFile(Platform.getLogFileLocation().toFile());
+ }
+
+ public String getSelectedStack() {
+ return fSelectedStack;
+ }
+
+}
diff --git a/bundles/org.eclipse.ui.views.log/src/org/eclipse/ui/internal/views/log/LogViewContentProvider.java b/bundles/org.eclipse.ui.views.log/src/org/eclipse/ui/internal/views/log/LogViewContentProvider.java
new file mode 100644
index 0000000..59f9a2f
--- /dev/null
+++ b/bundles/org.eclipse.ui.views.log/src/org/eclipse/ui/internal/views/log/LogViewContentProvider.java
@@ -0,0 +1,53 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2007 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
+ * Jacek Pospychala <jacek.pospychala@pl.ibm.com> - bugs 202583,207344
+ *******************************************************************************/
+package org.eclipse.ui.internal.views.log;
+
+import org.eclipse.jface.viewers.ITreeContentProvider;
+
+public class LogViewContentProvider implements ITreeContentProvider {
+ private LogView logView;
+
+ public LogViewContentProvider(LogView logView) {
+ this.logView = logView;
+ }
+
+
+ @Override
+ public Object[] getChildren(Object element) {
+ return ((AbstractEntry) element).getChildren(element);
+ }
+
+ @Override
+ public Object[] getElements(Object element) {
+ return logView.getElements();
+ }
+
+ @Override
+ public Object getParent(Object element) {
+ if (element instanceof LogSession) {
+ return null;
+ }
+ return ((AbstractEntry) element).getParent(element);
+ }
+
+ @Override
+ public boolean hasChildren(Object element) {
+ return ((AbstractEntry) element).getChildren(element).length > 0;
+ }
+
+ public boolean isDeleted(Object element) {
+ return false;
+ }
+}
diff --git a/bundles/org.eclipse.ui.views.log/src/org/eclipse/ui/internal/views/log/LogViewLabelProvider.java b/bundles/org.eclipse.ui.views.log/src/org/eclipse/ui/internal/views/log/LogViewLabelProvider.java
new file mode 100644
index 0000000..7eadb3a
--- /dev/null
+++ b/bundles/org.eclipse.ui.views.log/src/org/eclipse/ui/internal/views/log/LogViewLabelProvider.java
@@ -0,0 +1,140 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 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 Corporation - ongoing enhancements
+ * Jacek Pospychala <jacek.pospychala@pl.ibm.com> - bugs 202583, 207344, 207101
+ *******************************************************************************/
+package org.eclipse.ui.internal.views.log;
+
+import com.ibm.icu.text.DateFormat;
+import java.util.ArrayList;
+import org.eclipse.core.runtime.IStatus;
+import org.eclipse.jface.resource.JFaceResources;
+import org.eclipse.jface.viewers.*;
+import org.eclipse.swt.graphics.Font;
+import org.eclipse.swt.graphics.Image;
+
+public class LogViewLabelProvider extends LabelProvider implements ITableLabelProvider, ITableFontProvider {
+
+ private static int MAX_LABEL_LENGTH = 200;
+
+ private Image infoImage;
+ private Image okImage;
+ private Image errorImage;
+ private Image warningImage;
+ private Image errorWithStackImage;
+ private Image hierarchicalImage;
+ ArrayList<Object> consumers = new ArrayList<>();
+ private DateFormat dateFormat = DateFormat.getDateTimeInstance(DateFormat.SHORT, DateFormat.SHORT);
+
+ private LogView logView;
+
+ public LogViewLabelProvider(LogView logView) {
+ errorImage = SharedImages.getImage(SharedImages.DESC_ERROR_ST_OBJ);
+ warningImage = SharedImages.getImage(SharedImages.DESC_WARNING_ST_OBJ);
+ infoImage = SharedImages.getImage(SharedImages.DESC_INFO_ST_OBJ);
+ okImage = SharedImages.getImage(SharedImages.DESC_OK_ST_OBJ);
+ errorWithStackImage = SharedImages.getImage(SharedImages.DESC_ERROR_STACK_OBJ);
+ hierarchicalImage = SharedImages.getImage(SharedImages.DESC_HIERARCHICAL_LAYOUT_OBJ);
+
+ this.logView = logView;
+ }
+
+ @Override
+ public void dispose() {
+ if (consumers.isEmpty()) {
+ super.dispose();
+ }
+ }
+
+ @Override
+ public Image getColumnImage(Object element, int columnIndex) {
+ if (element instanceof Group) {
+ return (columnIndex == 0) ? hierarchicalImage : null;
+ }
+
+ LogEntry entry = (LogEntry) element;
+ if (columnIndex == 0) {
+ switch (entry.getSeverity()) {
+ case IStatus.INFO :
+ return infoImage;
+ case IStatus.OK :
+ return okImage;
+ case IStatus.WARNING :
+ return warningImage;
+ default :
+ return (entry.getStack() == null ? errorImage : errorWithStackImage);
+ }
+ }
+ return null;
+ }
+
+ @Override
+ public String getColumnText(Object element, int columnIndex) {
+ if ((element instanceof LogSession) && (columnIndex == 2)) {
+ LogSession session = (LogSession) element;
+ if (session.getDate() == null)
+ return ""; //$NON-NLS-1$
+
+ return dateFormat.format(session.getDate());
+ }
+
+ if ((element instanceof Group) && (columnIndex == 0)) {
+ return element.toString();
+ }
+
+ if (element instanceof LogEntry) {
+ LogEntry entry = (LogEntry) element;
+ switch (columnIndex) {
+ case 0 :
+ if (entry.getMessage() != null) {
+ String message = entry.getMessage();
+ if (message.length() > MAX_LABEL_LENGTH) {
+ String warning = Messages.LogViewLabelProvider_truncatedMessage;
+ StringBuilder sb = new StringBuilder(message.substring(0, MAX_LABEL_LENGTH - warning.length()));
+ sb.append(warning);
+ return sb.toString();
+ }
+ return entry.getMessage();
+ }
+ case 1 :
+ if (entry.getPluginId() != null)
+ return entry.getPluginId();
+ case 2 :
+ return dateFormat.format(entry.getDate());
+ }
+ }
+
+ return ""; //$NON-NLS-1$
+ }
+
+ public void connect(Object consumer) {
+ if (!consumers.contains(consumer))
+ consumers.add(consumer);
+ }
+
+ public void disconnect(Object consumer) {
+ consumers.remove(consumer);
+ if (consumers.isEmpty()) {
+ dispose();
+ }
+ }
+
+ @Override
+ public Font getFont(Object element, int columnIndex) {
+ if ((element instanceof LogSession) && (logView.isCurrentLogSession((LogSession) element))) {
+ return JFaceResources.getFontRegistry().getBold(JFaceResources.DEFAULT_FONT);
+ }
+
+ return null;
+ }
+}
diff --git a/bundles/org.eclipse.ui.views.log/src/org/eclipse/ui/internal/views/log/Messages.java b/bundles/org.eclipse.ui.views.log/src/org/eclipse/ui/internal/views/log/Messages.java
new file mode 100644
index 0000000..e0d3d67
--- /dev/null
+++ b/bundles/org.eclipse.ui.views.log/src/org/eclipse/ui/internal/views/log/Messages.java
@@ -0,0 +1,121 @@
+/*******************************************************************************
+ * Copyright (c) 2007, 2014 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
+ * Jacek Pospychala <jacek.pospychala@pl.ibm.com> - bugs 202583, 207344
+ * Benjamin Cabe <benjamin.cabe@anyware-tech.com> - bug 218648
+ *******************************************************************************/
+package org.eclipse.ui.internal.views.log;
+
+import org.eclipse.osgi.util.NLS;
+
+public class Messages extends NLS {
+
+ public static String LogReader_warn_noEntryWithinMaxLogTailSize;
+
+ public static String LogView_column_message;
+ public static String LogView_column_plugin;
+ public static String LogView_column_date;
+ public static String LogView_clear;
+ public static String LogView_clear_tooltip;
+ public static String LogView_copy;
+ public static String LogView_delete;
+ public static String LogView_delete_tooltip;
+ public static String LogView_export;
+ public static String LogView_exportLog;
+ public static String LogView_export_tooltip;
+ public static String LogView_exportEntry;
+ public static String LogView_exportLogEntry;
+ public static String LogView_exportEntry_tooltip;
+ public static String LogView_import;
+ public static String LogView_import_tooltip;
+ public static String LogView_filter;
+ public static String LogView_readLog_reload;
+ public static String LogView_readLog_restore;
+ public static String LogView_readLog_restore_tooltip;
+ public static String LogView_show_filter_text;
+ public static String LogView_show_filter_initialText;
+
+ public static String LogView_SessionStarted;
+ public static String LogView_severity_error;
+ public static String LogView_severity_warning;
+ public static String LogView_severity_info;
+ public static String LogView_severity_ok;
+ public static String LogView_confirmDelete_title;
+ public static String LogView_confirmDelete_message;
+ public static String LogView_confirmDelete_deleteButton;
+ public static String LogView_confirmOverwrite_message;
+ public static String LogView_operation_importing;
+ public static String LogView_operation_reloading;
+ public static String LogView_activate;
+ public static String LogView_AddingBatchedEvents;
+ public static String LogView_view_currentLog;
+ public static String LogView_view_currentLog_tooltip;
+ public static String LogView_properties_tooltip;
+
+ public static String LogView_FileCouldNotBeFound;
+ public static String LogView_FilterDialog_title;
+ public static String LogView_FilterDialog_eventTypes;
+ public static String LogView_FilterDialog_information;
+ public static String LogView_FilterDialog_warning;
+ public static String LogView_FilterDialog_error;
+ public static String LogView_FilterDialog_limitTo;
+ public static String LogView_FilterDialog_maxLogTailSize;
+ public static String LogView_FilterDialog_eventsLogged;
+ public static String LogView_FilterDialog_allSessions;
+ public static String LogView_FilterDialog_ok;
+ public static String LogView_FilterDialog_recentSession;
+ public static String LogView_GroupBy;
+ public static String LogView_GroupByNone;
+ public static String LogView_GroupByPlugin;
+ public static String LogView_GroupBySession;
+ public static String LogView_LogFileTitle;
+ public static String LogView_OpenFile;
+ public static String LogView_WorkspaceLogFile;
+
+ public static String LogViewLabelProvider_Session;
+ public static String LogViewLabelProvider_truncatedMessage;
+
+ public static String EventDetailsDialog_title;
+ public static String EventDetailsDialog_plugIn;
+ public static String EventDetailsDialog_severity;
+ public static String EventDetailsDialog_date;
+ public static String EventDetailsDialog_message;
+ public static String EventDetailsDialog_exception;
+ public static String EventDetailsDialog_session;
+ public static String EventDetailsDialog_noStack;
+ public static String EventDetailsDialog_previous;
+ public static String EventDetailsDialog_next;
+ public static String EventDetailsDialog_copy;
+ public static String EventDetailsDialog_FilterDialog;
+ public static String EventDetailsDialog_ShowFilterDialog;
+
+ public static String FilterDialog_Add;
+ public static String FilterDialog_AddFilterTitle;
+ public static String FilterDialog_AddFliterLabel;
+ public static String FilterDialog_EnableFiltersCheckbox;
+ public static String FilterDialog_FilterShouldntContainSemicolon;
+ public static String FilterDialog_Remove;
+
+ public static String OpenLogDialog_title;
+ public static String OpenLogDialog_message;
+ public static String OpenLogDialog_cannotDisplay;
+
+ public static String ImportLogAction_noLaunchHistory;
+ public static String ImportLogAction_reloadWorkspaceLog;
+
+ private static final String BUNDLE_NAME = "org.eclipse.ui.internal.views.log.messages"; //$NON-NLS-1$
+
+ static {
+ NLS.initializeMessages(BUNDLE_NAME, Messages.class);
+ }
+
+}
diff --git a/bundles/org.eclipse.ui.views.log/src/org/eclipse/ui/internal/views/log/OpenIDELogFileAction.java b/bundles/org.eclipse.ui.views.log/src/org/eclipse/ui/internal/views/log/OpenIDELogFileAction.java
new file mode 100644
index 0000000..814569a
--- /dev/null
+++ b/bundles/org.eclipse.ui.views.log/src/org/eclipse/ui/internal/views/log/OpenIDELogFileAction.java
@@ -0,0 +1,52 @@
+/*******************************************************************************
+ * Copyright (c) 2007, 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.ui.internal.views.log;
+
+import org.eclipse.core.filesystem.EFS;
+import org.eclipse.core.filesystem.IFileStore;
+import org.eclipse.core.runtime.IPath;
+import org.eclipse.core.runtime.Path;
+import org.eclipse.jface.action.Action;
+import org.eclipse.ui.*;
+import org.eclipse.ui.ide.IDE;
+
+/*
+ * This action is used to Open the Log File from the LogView if both org.eclipse.ui.ide and
+ * org.eclipse.core.filesystem are available. If both plugins are resolved, we will open
+ * the log file through the IDE's file association preferences. Otherwise,
+ * LogView.getOpenLogJob() is called to open the file.
+ */
+public class OpenIDELogFileAction extends Action {
+
+ private LogView fView;
+
+ public OpenIDELogFileAction(LogView logView) {
+ fView = logView;
+ }
+
+ @Override
+ public void run() {
+ IPath logPath = new Path(fView.getLogFile().getAbsolutePath());
+ IFileStore fileStore = EFS.getLocalFileSystem().getStore(logPath);
+ if (!fileStore.fetchInfo().isDirectory() && fileStore.fetchInfo().exists()) {
+ IWorkbenchWindow ww = PlatformUI.getWorkbench().getActiveWorkbenchWindow();
+ IWorkbenchPage page = ww.getActivePage();
+ try {
+ IDE.openEditorOnFileStore(page, fileStore);
+ } catch (PartInitException e) { // do nothing
+ }
+ }
+ }
+
+}
diff --git a/bundles/org.eclipse.ui.views.log/src/org/eclipse/ui/internal/views/log/OpenLogDialog.java b/bundles/org.eclipse.ui.views.log/src/org/eclipse/ui/internal/views/log/OpenLogDialog.java
new file mode 100644
index 0000000..a07c1c1
--- /dev/null
+++ b/bundles/org.eclipse.ui.views.log/src/org/eclipse/ui/internal/views/log/OpenLogDialog.java
@@ -0,0 +1,226 @@
+/*******************************************************************************
+ * Copyright (c) 2003, 2017 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
+ * Lars Vogel <Lars.Vogel@gmail.com> - Bug 424111
+ *******************************************************************************/
+
+package org.eclipse.ui.internal.views.log;
+
+import java.io.*;
+import java.lang.reflect.InvocationTargetException;
+import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.jface.dialogs.*;
+import org.eclipse.jface.operation.IRunnableWithProgress;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.graphics.Point;
+import org.eclipse.swt.layout.GridData;
+import org.eclipse.swt.widgets.*;
+
+/**
+ * Displays the error log in non-Win32 platforms - see bug 55314.
+ */
+public final class OpenLogDialog extends TrayDialog {
+ // input log file
+ private File logFile;
+ // location/size configuration
+ private IDialogSettings dialogSettings;
+ private Point dialogLocation;
+ private Point dialogSize;
+ private int DEFAULT_WIDTH = 750;
+ private int DEFAULT_HEIGHT = 800;
+
+ public OpenLogDialog(Shell parentShell, File logFile) {
+ super(parentShell);
+ this.logFile = logFile;
+ setShellStyle(SWT.DIALOG_TRIM | SWT.RESIZE | SWT.MAX | SWT.MIN | SWT.MODELESS);
+
+ }
+
+ @Override
+ protected void configureShell(Shell newShell) {
+ super.configureShell(newShell);
+ newShell.setText(Messages.OpenLogDialog_title);
+ readConfiguration();
+ }
+
+ @Override
+ protected void createButtonsForButtonBar(Composite parent) {
+ createButton(parent, IDialogConstants.CLOSE_ID, IDialogConstants.CLOSE_LABEL, true);
+ }
+
+ @Override
+ public void create() {
+ super.create();
+ // dialog location
+ if (dialogLocation != null)
+ getShell().setLocation(dialogLocation);
+ // dialog size
+ if (dialogSize != null)
+ getShell().setSize(dialogSize);
+ else
+ getShell().setSize(DEFAULT_WIDTH, DEFAULT_HEIGHT);
+ getButton(IDialogConstants.CLOSE_ID).setFocus();
+ }
+
+ @Override
+ protected Control createDialogArea(Composite parent) {
+ Composite outer = (Composite) super.createDialogArea(parent);
+ Text text = new Text(outer, SWT.MULTI | SWT.BORDER | SWT.READ_ONLY | SWT.V_SCROLL | SWT.NO_FOCUS | SWT.H_SCROLL);
+ text.setBackground(parent.getDisplay().getSystemColor(SWT.COLOR_LIST_BACKGROUND));
+ GridData gridData = new GridData(GridData.HORIZONTAL_ALIGN_FILL | GridData.VERTICAL_ALIGN_FILL);
+ gridData.grabExcessVerticalSpace = true;
+ gridData.grabExcessHorizontalSpace = true;
+ text.setLayoutData(gridData);
+ text.setText(getLogSummary());
+ return outer;
+ }
+
+ private String getLogSummary() {
+ StringWriter out = new StringWriter();
+ try (PrintWriter writer = new PrintWriter(out)) {
+ if (logFile.length() > LogReader.MAX_FILE_LENGTH) {
+ readLargeFileWithMonitor(writer);
+ } else {
+ readFileWithMonitor(writer);
+ }
+ }
+ return out.toString();
+ }
+
+ @Override
+ protected void buttonPressed(int buttonId) {
+ if (buttonId == IDialogConstants.CLOSE_ID) {
+ storeSettings();
+ close();
+ }
+ super.buttonPressed(buttonId);
+ }
+
+ //--------------- configuration handling --------------
+ /**
+ * Stores the current state in the dialog settings.
+ *
+ * @since 2.0
+ */
+ private void storeSettings() {
+ writeConfiguration();
+ }
+
+ /**
+ * Returns the dialog settings object used to share state between several
+ * event detail dialogs.
+ *
+ * @return the dialog settings to be used
+ */
+ private IDialogSettings getDialogSettings() {
+ IDialogSettings settings = Activator.getDefault().getDialogSettings();
+ dialogSettings = settings.getSection(getClass().getName());
+ if (dialogSettings == null)
+ dialogSettings = settings.addNewSection(getClass().getName());
+ return dialogSettings;
+ }
+
+ /**
+ * Initializes itself from the dialog settings with the same state as at the
+ * previous invocation.
+ */
+ private void readConfiguration() {
+ IDialogSettings s = getDialogSettings();
+ try {
+ int x = s.getInt("x"); //$NON-NLS-1$
+ int y = s.getInt("y"); //$NON-NLS-1$
+ dialogLocation = new Point(x, y);
+ x = s.getInt("width"); //$NON-NLS-1$
+ y = s.getInt("height"); //$NON-NLS-1$
+ dialogSize = new Point(x, y);
+ } catch (NumberFormatException e) {
+ dialogLocation = null;
+ dialogSize = null;
+ }
+ }
+
+ private void writeConfiguration() {
+ IDialogSettings s = getDialogSettings();
+ Point location = getShell().getLocation();
+ s.put("x", location.x); //$NON-NLS-1$
+ s.put("y", location.y); //$NON-NLS-1$
+ Point size = getShell().getSize();
+ s.put("width", size.x); //$NON-NLS-1$
+ s.put("height", size.y); //$NON-NLS-1$
+ }
+
+ // reading file within MAX_FILE_LENGTH size
+ void readFile(PrintWriter writer) throws FileNotFoundException, IOException {
+ try (BufferedReader bReader = new BufferedReader(new FileReader(logFile))) {
+
+ while (bReader.ready()) {
+ writer.println(bReader.readLine());
+ }
+ }
+ }
+
+ // reading large files
+ void readLargeFile(PrintWriter writer) throws FileNotFoundException, IOException {
+ boolean hasStarted = false;
+ try (RandomAccessFile random = new RandomAccessFile(logFile, "r");) { //$NON-NLS-1$
+
+ random.seek(logFile.length() - LogReader.MAX_FILE_LENGTH);
+ for (;;) {
+ String line = random.readLine();
+ if (line == null)
+ break;
+ line = line.trim();
+ if (line.length() == 0)
+ continue;
+ if (!hasStarted && (line.startsWith("!ENTRY") || line.startsWith(LogSession.SESSION))) //$NON-NLS-1$
+ hasStarted = true;
+ if (hasStarted)
+ writer.println(line);
+ continue;
+ }
+ }
+ }
+
+ private void readLargeFileWithMonitor(final PrintWriter writer) {
+ IRunnableWithProgress runnable = monitor -> {
+ monitor.beginTask(Messages.OpenLogDialog_message, IProgressMonitor.UNKNOWN);
+ try {
+ readLargeFile(writer);
+ } catch (IOException e) {
+ writer.println(Messages.OpenLogDialog_cannotDisplay);
+ }
+ };
+ ProgressMonitorDialog dialog = new ProgressMonitorDialog(getParentShell());
+ try {
+ dialog.run(true, true, runnable);
+ } catch (InvocationTargetException e) { // do nothing
+ } catch (InterruptedException e) { // do nothing
+ }
+ }
+
+ private void readFileWithMonitor(final PrintWriter writer) {
+ IRunnableWithProgress runnable = monitor -> {
+ monitor.beginTask(Messages.OpenLogDialog_message, IProgressMonitor.UNKNOWN);
+ try {
+ readFile(writer);
+ } catch (IOException e) {
+ writer.println(Messages.OpenLogDialog_cannotDisplay);
+ }
+ };
+ ProgressMonitorDialog dialog = new ProgressMonitorDialog(getParentShell());
+ try {
+ dialog.run(true, true, runnable);
+ } catch (InvocationTargetException e) { // do nothing
+ } catch (InterruptedException e) { // do nothing
+ }
+ }
+}
diff --git a/bundles/org.eclipse.ui.views.log/src/org/eclipse/ui/internal/views/log/SharedImages.java b/bundles/org.eclipse.ui.views.log/src/org/eclipse/ui/internal/views/log/SharedImages.java
new file mode 100644
index 0000000..ac2a167
--- /dev/null
+++ b/bundles/org.eclipse.ui.views.log/src/org/eclipse/ui/internal/views/log/SharedImages.java
@@ -0,0 +1,69 @@
+/*******************************************************************************
+ * Copyright (c) 2007, 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
+ * Jacek Pospychala <jacek.pospychala@pl.ibm.com> - bug 202583
+ *******************************************************************************/
+package org.eclipse.ui.internal.views.log;
+
+import org.eclipse.jface.resource.ImageDescriptor;
+import org.eclipse.swt.graphics.Image;
+
+public final class SharedImages {
+
+ private SharedImages() { // do nothing
+ }
+
+ public final static String ICONS_PATH = "icons/"; //$NON-NLS-1$
+
+ private static final String PATH_OBJ = ICONS_PATH + "obj16/"; //$NON-NLS-1$
+ private static final String PATH_LCL = ICONS_PATH + "elcl16/"; //$NON-NLS-1$
+ private static final String PATH_LCL_DISABLED = ICONS_PATH + "dlcl16/"; //$NON-NLS-1$
+ private static final String PATH_EVENTS = ICONS_PATH + "eview16/"; //$NON-NLS-1$
+
+ /* Event Details */
+ public static final String DESC_PREV_EVENT = PATH_EVENTS + "event_prev.png"; //$NON-NLS-1$
+ public static final String DESC_NEXT_EVENT = PATH_EVENTS + "event_next.png"; //$NON-NLS-1$
+
+ public static final String DESC_CLEAR = PATH_LCL + "clear.png"; //$NON-NLS-1$
+ public static final String DESC_CLEAR_DISABLED = PATH_LCL_DISABLED + "clear.png"; //$NON-NLS-1$
+ public static final String DESC_OPEN_CONSOLE = PATH_LCL + "open_console_obj.png"; //$NON-NLS-1$
+ public static final String DESC_REMOVE_LOG = PATH_LCL + "remove.png"; //$NON-NLS-1$
+ public static final String DESC_REMOVE_LOG_DISABLED = PATH_LCL_DISABLED + "remove.png"; //$NON-NLS-1$
+ public static final String DESC_EXPORT = PATH_LCL + "export_log.png"; //$NON-NLS-1$
+ public static final String DESC_EXPORT_DISABLED = PATH_LCL_DISABLED + "export_log.png"; //$NON-NLS-1$
+ public static final String DESC_FILTER = PATH_LCL + "filter_ps.png"; //$NON-NLS-1$
+ public static final String DESC_FILTER_DISABLED = PATH_LCL_DISABLED + "filter_ps.png"; //$NON-NLS-1$
+ public static final String DESC_IMPORT = PATH_LCL + "import_log.png"; //$NON-NLS-1$
+ public static final String DESC_IMPORT_DISABLED = PATH_LCL_DISABLED + "import_log.png"; //$NON-NLS-1$
+ public static final String DESC_OPEN_LOG = PATH_LCL + "open_log.png"; //$NON-NLS-1$
+ public static final String DESC_OPEN_LOG_DISABLED = PATH_LCL_DISABLED + "open_log.png"; //$NON-NLS-1$
+ public static final String DESC_PROPERTIES = PATH_LCL + "properties.png"; //$NON-NLS-1$
+ public static final String DESC_PROPERTIES_DISABLED = PATH_LCL_DISABLED + "properties.png"; //$NON-NLS-1$
+ public static final String DESC_READ_LOG = PATH_LCL + "restore_log.png"; //$NON-NLS-1$
+ public static final String DESC_READ_LOG_DISABLED = PATH_LCL_DISABLED + "restore_log.png"; //$NON-NLS-1$
+
+ public static final String DESC_ERROR_ST_OBJ = PATH_OBJ + "error_st_obj.png"; //$NON-NLS-1$
+ public static final String DESC_ERROR_STACK_OBJ = PATH_OBJ + "error_stack.png"; //$NON-NLS-1$
+ public static final String DESC_INFO_ST_OBJ = PATH_OBJ + "info_st_obj.png"; //$NON-NLS-1$
+ public static final String DESC_OK_ST_OBJ = PATH_OBJ + "ok_st_obj.png"; //$NON-NLS-1$
+ public static final String DESC_WARNING_ST_OBJ = PATH_OBJ + "warning_st_obj.png"; //$NON-NLS-1$
+ public static final String DESC_HIERARCHICAL_LAYOUT_OBJ = PATH_OBJ + "hierarchical.png"; //$NON-NLS-1$
+
+ public static ImageDescriptor getImageDescriptor(String key) {
+ return Activator.getDefault().getImageRegistry().getDescriptor(key);
+ }
+
+ public static Image getImage(String key) {
+ return Activator.getDefault().getImageRegistry().get(key);
+ }
+
+}
diff --git a/bundles/org.eclipse.ui.views.log/src/org/eclipse/ui/internal/views/log/TailInputStream.java b/bundles/org.eclipse.ui.views.log/src/org/eclipse/ui/internal/views/log/TailInputStream.java
new file mode 100644
index 0000000..cb4f34b
--- /dev/null
+++ b/bundles/org.eclipse.ui.views.log/src/org/eclipse/ui/internal/views/log/TailInputStream.java
@@ -0,0 +1,68 @@
+/*******************************************************************************
+ * Copyright (c) 2005, 2014 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.ui.internal.views.log;
+
+import java.io.*;
+
+public class TailInputStream extends InputStream {
+
+ private RandomAccessFile fRaf;
+
+ private long fTail;
+
+ public TailInputStream(File file, long maxLength) throws IOException {
+ super();
+ fTail = maxLength;
+ fRaf = new RandomAccessFile(file, "r"); //$NON-NLS-1$
+ skipHead(file);
+ }
+
+ private void skipHead(File file) throws IOException {
+ if (file.length() > fTail) {
+ fRaf.seek(file.length() - fTail);
+ // skip bytes until a new line to be sure we start from a beginning of valid UTF-8 character
+ int c = read();
+ while (c != '\n' && c != '\r' && c != -1) {
+ c = read();
+ }
+
+ }
+ }
+
+ @Override
+ public int read() throws IOException {
+ byte[] b = new byte[1];
+ int len = fRaf.read(b, 0, 1);
+ if (len < 0) {
+ return len;
+ }
+ return b[0];
+ }
+
+ @Override
+ public int read(byte[] b) throws IOException {
+ return fRaf.read(b, 0, b.length);
+ }
+
+ @Override
+ public int read(byte[] b, int off, int len) throws IOException {
+ return fRaf.read(b, off, len);
+ }
+
+ @Override
+ public void close() throws IOException {
+ fRaf.close();
+ }
+
+}
diff --git a/bundles/org.eclipse.ui.views.log/src/org/eclipse/ui/internal/views/log/messages.properties b/bundles/org.eclipse.ui.views.log/src/org/eclipse/ui/internal/views/log/messages.properties
new file mode 100644
index 0000000..989795d
--- /dev/null
+++ b/bundles/org.eclipse.ui.views.log/src/org/eclipse/ui/internal/views/log/messages.properties
@@ -0,0 +1,102 @@
+###############################################################################
+# Copyright (c) 2007, 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
+# Jacek Pospychala <jacek.pospychala@pl.ibm.com> - bug 202583, 217201
+# Benjamin Cabe <benjamin.cabe@anyware-tech.com> - bug 218648
+###############################################################################
+
+LogReader_warn_noEntryWithinMaxLogTailSize = No log entry found within maximum log size ''{0}'' MB. Please increase the maximum log size using the ''Filters...'' menu.
+LogView_column_message = Message
+LogView_column_plugin = Plug-in
+LogView_column_date = Date
+LogView_clear = C&lear Log Viewer
+LogView_clear_tooltip = Clear Log Viewer
+LogView_copy = &Copy
+LogView_delete = &Delete Log
+LogView_delete_tooltip = Delete Log
+LogView_export = &Export Log...
+LogView_exportLog=Export Log
+LogView_export_tooltip = Export Log
+LogView_exportEntry = &Export Entry...
+LogView_exportEntry_tooltip = Export Entry
+LogView_exportLogEntry=Export Log Entry
+LogView_import = &Import Log...
+LogView_import_tooltip = Import Log
+LogView_filter = &Filters...
+LogView_readLog_reload = &Reload Workspace Log
+LogView_readLog_restore = &Restore Log
+LogView_readLog_restore_tooltip = Restore Log
+LogView_severity_error = Error
+LogView_SessionStarted=Session started
+LogView_severity_warning = Warning
+LogView_severity_info = Info
+LogView_severity_ok = OK
+LogView_confirmDelete_title = Confirm Delete
+LogView_confirmDelete_message = Are you sure you want to permanently delete all logged events?
+LogView_confirmOverwrite_message = File " {0}" exists. Would you like to overwrite it?
+LogView_confirmDelete_deleteButton = &Delete All Events
+LogView_operation_importing = Importing log...
+LogView_operation_reloading = Reloading...
+LogView_activate = &Activate on new events
+LogView_AddingBatchedEvents=Adding batched log events...
+LogView_view_currentLog = &Open Log
+LogView_view_currentLog_tooltip = Open Log
+LogView_properties_tooltip = Event Details
+LogView_show_filter_text=&Show text filter
+LogView_show_filter_initialText = type filter text
+
+LogView_FileCouldNotBeFound=The file "{0}" could not be found.
+LogView_FilterDialog_title = Log Filters
+LogView_FilterDialog_eventTypes = Event Types
+LogView_FilterDialog_information = &Information
+LogView_FilterDialog_warning = &Warning
+LogView_FilterDialog_error = &Error
+LogView_FilterDialog_limitTo = &Limit visible events to:
+LogView_FilterDialog_maxLogTailSize = Maximum log size in MB:
+LogView_FilterDialog_eventsLogged = Show events logged during:
+LogView_FilterDialog_allSessions = &All sessions
+LogView_FilterDialog_ok=&OK
+LogView_FilterDialog_recentSession = &Most recent session
+LogView_GroupBy=Group By
+LogView_GroupByNone=None
+LogView_GroupByPlugin=Plug-in
+LogView_GroupBySession=Session
+LogView_LogFileTitle={0} [{1}]
+LogView_OpenFile=Open File
+LogView_WorkspaceLogFile=Workspace Log
+LogViewLabelProvider_truncatedMessage=... (Open log entry details for full message)
+LogViewLabelProvider_Session=Session
+
+EventDetailsDialog_title= Event Details
+EventDetailsDialog_plugIn= Plug-in:
+EventDetailsDialog_severity=Severity:
+EventDetailsDialog_date=Date:
+EventDetailsDialog_message=Message:
+EventDetailsDialog_exception=Exception Stack Trace:
+EventDetailsDialog_session=Session Data:
+EventDetailsDialog_noStack = An exception stack trace is not available.
+EventDetailsDialog_previous=View Details Of Previous Event
+EventDetailsDialog_next=View Details Of Next Event
+EventDetailsDialog_copy=Copy Event Details To Clipboard
+EventDetailsDialog_FilterDialog=Filters
+EventDetailsDialog_ShowFilterDialog=Show Filter Dialog
+FilterDialog_Add=A&dd...
+FilterDialog_AddFilterTitle=Add filter
+FilterDialog_AddFliterLabel=Add stack trace filter:
+FilterDialog_EnableFiltersCheckbox=E&nable filters to hide stack trace elements
+FilterDialog_FilterShouldntContainSemicolon=A semicolon isn't a legal character within a filter
+FilterDialog_Remove=&Remove
+OpenLogDialog_title=Error Log
+OpenLogDialog_message=Opening log...
+OpenLogDialog_cannotDisplay=Log file cannot be displayed.
+ImportLogAction_reloadWorkspaceLog = &Workspace Log
+ImportLogAction_noLaunchHistory=(no logs available)
\ No newline at end of file
diff --git a/bundles/pom.xml b/bundles/pom.xml
index d1e1f86..5f62c79 100644
--- a/bundles/pom.xml
+++ b/bundles/pom.xml
@@ -51,6 +51,7 @@
<module>org.eclipse.ui.browser</module>
<module>org.eclipse.ui.forms</module>
<module>org.eclipse.ui.views</module>
+ <module>org.eclipse.ui.views.log</module>
<module>org.eclipse.ui.views.properties.tabbed</module>
<module>org.eclipse.ui.workbench</module>
<module>org.eclipse.ui.monitoring</module>