mirror of
https://github.com/Alfresco/alfresco-community-repo.git
synced 2025-10-08 14:51:49 +00:00
Compare commits
47 Commits
Author | SHA1 | Date | |
---|---|---|---|
|
b2c749f850 | ||
|
0174949fbf | ||
|
65ee4c725a | ||
|
8e33924701 | ||
|
2f8ea7bff1 | ||
|
263337c720 | ||
|
226aaf8503 | ||
|
86f971f713 | ||
|
0958e866b0 | ||
|
ad6caede9c | ||
|
44a2d5e6e3 | ||
|
858f839ee0 | ||
|
5908e9f4c1 | ||
|
453326c4d8 | ||
|
0aaa9bcbba | ||
|
0870a8cacf | ||
|
8176f82e78 | ||
|
7fc6463c78 | ||
|
4555dd3939 | ||
|
41c8488634 | ||
|
439a17302a | ||
|
c1ee9467c8 | ||
|
3443ea9eb7 | ||
|
4fb14adfd9 | ||
|
dded4a461b | ||
|
93dedd01c2 | ||
|
eb0a064b31 | ||
|
db30d7fbfe | ||
|
ba5f94b848 | ||
|
4a9eef0356 | ||
|
0c681258e9 | ||
|
2c28b04efa | ||
|
8027a579ab | ||
|
81768de342 | ||
|
6bec0c84fe | ||
|
9efdb7aeb1 | ||
|
51f669bd48 | ||
|
51092c7d4f | ||
|
4ae12096ab | ||
|
ce829f9ebb | ||
|
1222326741 | ||
|
d9ce80ab31 | ||
|
bcf7df9e48 | ||
|
094e3189cb | ||
|
d22936a36a | ||
|
66b3c95837 | ||
|
a40e10cd12 |
13
.github/workflows/ci.yml
vendored
13
.github/workflows/ci.yml
vendored
@@ -36,8 +36,16 @@ jobs:
|
|||||||
!contains(github.event.head_commit.message, '[force')
|
!contains(github.event.head_commit.message, '[force')
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v4
|
- uses: actions/checkout@v4
|
||||||
- uses: Alfresco/alfresco-build-tools/.github/actions/get-build-info@v7.0.0
|
with:
|
||||||
- uses: Alfresco/alfresco-build-tools/.github/actions/setup-java-build@v7.0.0
|
fetch-depth: 0
|
||||||
|
- uses: Alfresco/alfresco-build-tools/.github/actions/get-build-info@v8.2.0
|
||||||
|
- uses: Alfresco/alfresco-build-tools/.github/actions/free-hosted-runner-disk-space@v8.2.0
|
||||||
|
- uses: Alfresco/alfresco-build-tools/.github/actions/setup-java-build@v8.2.0
|
||||||
|
- id: changed-files
|
||||||
|
uses: Alfresco/alfresco-build-tools/.github/actions/github-list-changes@v8.2.0
|
||||||
|
with:
|
||||||
|
write-list-to-env: true
|
||||||
|
- uses: Alfresco/alfresco-build-tools/.github/actions/pre-commit@v8.2.0
|
||||||
- name: "Init"
|
- name: "Init"
|
||||||
run: bash ./scripts/ci/init.sh
|
run: bash ./scripts/ci/init.sh
|
||||||
- name: "Prepare maven cache and check compilation"
|
- name: "Prepare maven cache and check compilation"
|
||||||
@@ -45,6 +53,7 @@ jobs:
|
|||||||
- name: "Clean Maven cache"
|
- name: "Clean Maven cache"
|
||||||
run: bash ./scripts/ci/cleanup_cache.sh
|
run: bash ./scripts/ci/cleanup_cache.sh
|
||||||
|
|
||||||
|
|
||||||
veracode:
|
veracode:
|
||||||
name: "Source Clear Scan (SCA)"
|
name: "Source Clear Scan (SCA)"
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
|
14
.pre-commit-config.yaml
Normal file
14
.pre-commit-config.yaml
Normal file
@@ -0,0 +1,14 @@
|
|||||||
|
repos:
|
||||||
|
- repo: https://github.com/Yelp/detect-secrets
|
||||||
|
rev: v1.5.0
|
||||||
|
hooks:
|
||||||
|
- id: detect-secrets
|
||||||
|
args: ["--baseline", ".secrets.baseline"]
|
||||||
|
- repo: local
|
||||||
|
hooks:
|
||||||
|
- id: check-format-and-headers
|
||||||
|
name: Check format and headers and fix if necessary
|
||||||
|
entry: ./scripts/hooks/check-format-and-headers.sh
|
||||||
|
language: script
|
||||||
|
files: ".*.java"
|
||||||
|
pass_filenames: false
|
1864
.secrets.baseline
Normal file
1864
.secrets.baseline
Normal file
File diff suppressed because it is too large
Load Diff
@@ -3,9 +3,53 @@ Thanks for your interest in contributing to this project!
|
|||||||
|
|
||||||
The following is a set of guidelines for contributing to this library. Most of them will make the life of the reviewer easier and therefore decrease the time required for the patch be included in the next version.
|
The following is a set of guidelines for contributing to this library. Most of them will make the life of the reviewer easier and therefore decrease the time required for the patch be included in the next version.
|
||||||
|
|
||||||
Because this project forms a part of Alfresco Content Services, the guidelines are hosted in the [Alfresco Social Community](http://community.alfresco.com/community/ecm) where they can be referenced from multiple projects.
|
The project uses [pre-commit](https://pre-commit.com/) to format code (with [Spotless](https://github.com/diffplug/spotless)), validate license headers and check for secrets (with [detect-secrets](https://github.com/Yelp/detect-secrets)). To install the pre-commit hooks then first install pre-commit and then run:
|
||||||
|
```shell
|
||||||
|
pre-commit install
|
||||||
|
```
|
||||||
|
When you make a commit then these hooks will run and check the modified files. If it makes changes then you can review them and then `git commit` again to accept the changes.
|
||||||
|
|
||||||
Read an [overview on how this project is goverened](https://community.alfresco.com/docs/DOC-6385-project-overview-repository).
|
#### Code Quality
|
||||||
|
This project uses `spotless` that enforces `alfresco-formatter.xml` to ensure code quality.
|
||||||
|
|
||||||
|
To check code-style violations you can use:
|
||||||
|
```bash
|
||||||
|
mvn spotless:check
|
||||||
|
```
|
||||||
|
To reformat files you can use:
|
||||||
|
```bash
|
||||||
|
mvn spotless:apply
|
||||||
|
```
|
||||||
|
|
||||||
|
#### Secret Detection
|
||||||
|
|
||||||
|
We are using [detect-secrets](https://github.com/Yelp/detect-secrets) to try to avoid accidentally publishing secret keys.
|
||||||
|
If you have pre-commit installed then this should run automatically when making a commit. Usually there should be no issues,
|
||||||
|
but if it finds a potential issue (e.g. a high entropy string) then you will see the following:
|
||||||
|
|
||||||
|
```shell
|
||||||
|
Detect secrets...........................................................Failed
|
||||||
|
- hook id: detect-secrets
|
||||||
|
- exit code: 1
|
||||||
|
|
||||||
|
ERROR: Potential secrets about to be committed to git repo!
|
||||||
|
|
||||||
|
Secret Type: Secret Keyword
|
||||||
|
Location: test.txt:1
|
||||||
|
```
|
||||||
|
|
||||||
|
If this is a false positive and you actually want to commit the string then run these two commands:
|
||||||
|
|
||||||
|
```shell
|
||||||
|
detect-secrets scan --baseline .secrets.baseline
|
||||||
|
detect-secrets audit .secrets.baseline
|
||||||
|
```
|
||||||
|
|
||||||
|
This will update the baseline file to include your new code and then allow you to review the detected secret and mark it as a false positive.
|
||||||
|
Once you are finished then you can add `.secrets.baseline` to the staged changes and you should be able to create a commit.
|
||||||
|
|
||||||
|
|
||||||
|
Because this project forms a part of Alfresco Content Services, the guidelines are hosted in the [Alfresco Social Community](https://hub.alfresco.com/t5/alfresco-content-services-ecm/ct-p/ECM-software) where they can be referenced from multiple projects.
|
||||||
|
|
||||||
You can report an issue in the ALF project of the [Alfresco issue tracker](http://issues.alfresco.com).
|
You can report an issue in the ALF project of the [Alfresco issue tracker](http://issues.alfresco.com).
|
||||||
|
|
||||||
|
401
alfresco-formatter.xml
Normal file
401
alfresco-formatter.xml
Normal file
@@ -0,0 +1,401 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||||
|
<profiles version="23">
|
||||||
|
<profile kind="CodeFormatterProfile" name="Spotless" version="23">
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_ellipsis" value="insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_enum_declarations" value="insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_allocation_expression" value="do not insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.parentheses_positions_in_for_statment" value="common_lines"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.comment.new_lines_at_block_boundaries" value="false"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_constructor_declaration_parameters" value="insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.comment.insert_new_line_for_parameter" value="insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_package" value="insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_enum_constant" value="do not insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_while" value="do not insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_annotation_type_member_declaration" value="do not insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.comment.format_javadoc_comments" value="true"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.indentation.size" value="4"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.parentheses_positions_in_enum_constant_declaration" value="common_lines"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_semicolon_in_for" value="insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.align_with_spaces" value="false"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.continuation_indentation" value="2"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.number_of_blank_lines_before_code_block" value="0"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_switch_case_expressions" value="do not insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.blank_lines_after_package" value="1"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_multiple_local_declarations" value="insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.alignment_for_arguments_in_enum_constant" value="16"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_angle_bracket_in_parameterized_type_reference" value="do not insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.comment.indent_root_tags" value="true"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.wrap_before_or_operator_multicatch" value="true"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.enabling_tag" value="@formatter:on"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.comment.count_line_length_from_starting_position" value="false"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.alignment_for_record_components" value="16"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.alignment_for_throws_clause_in_method_declaration" value="16"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_parameter" value="do not insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.wrap_before_multiplicative_operator" value="true"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.keep_then_statement_on_same_line" value="false"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_explicitconstructorcall_arguments" value="insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_prefix_operator" value="do not insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_brace_in_array_initializer" value="do not insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_angle_bracket_in_type_arguments" value="do not insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_method" value="insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.alignment_for_parameterized_type_references" value="0"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.alignment_for_logical_operator" value="16"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_parenthesized_expression" value="do not insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.keep_annotation_declaration_on_one_line" value="one_line_if_empty"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_record_declaration" value="do not insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_enum_constant" value="insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_multiplicative_operator" value="insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_and_in_type_parameter" value="insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_method_invocation" value="do not insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_assignment_operator" value="insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_type_declaration" value="insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_for" value="do not insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.comment.preserve_white_space_between_code_and_line_comments" value="false"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_local_variable" value="insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.blank_lines_before_abstract_method" value="1"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.keep_enum_constant_declaration_on_one_line" value="one_line_if_empty"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.align_variable_declarations_on_columns" value="false"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_method_invocation" value="do not insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.alignment_for_union_type_in_multicatch" value="16"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.number_of_blank_lines_at_beginning_of_method_body" value="0"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.keep_else_statement_on_same_line" value="false"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.parentheses_positions_in_catch_clause" value="common_lines"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_parameterized_type_reference" value="insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_array_initializer" value="do not insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_annotation" value="do not insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.alignment_for_arguments_in_explicit_constructor_call" value="16"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.alignment_for_multiplicative_operator" value="16"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.keep_anonymous_type_declaration_on_one_line" value="one_line_if_empty"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_switch_case_expressions" value="insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.wrap_before_shift_operator" value="true"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_annotation_declaration_header" value="true"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.brace_position_for_block" value="next_line"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.number_of_blank_lines_at_end_of_code_block" value="0"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_bitwise_operator" value="insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.put_empty_statement_on_new_line" value="true"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.alignment_for_parameters_in_constructor_declaration" value="16"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.alignment_for_type_parameters" value="0"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.alignment_for_compact_loops" value="16"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.comment.clear_blank_lines_in_block_comment" value="false"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.keep_simple_for_body_on_same_line" value="false"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_at_end_of_file_if_missing" value="insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.wrap_before_switch_case_arrow_operator" value="false"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_array_initializer" value="insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_unary_operator" value="do not insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.format_line_comment_starting_on_first_column" value="true"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.parentheses_positions_in_annotation" value="common_lines"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_ellipsis" value="do not insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_semicolon_in_try_resources" value="do not insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_colon_in_assert" value="insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.alignment_for_annotations_on_enum_constant" value="0"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_and_in_type_parameter" value="insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_parenthesized_expression" value="do not insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.text_block_indentation" value="0"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.align_type_members_on_columns" value="false"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.alignment_for_assignment" value="0"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.alignment_for_module_statements" value="16"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_type_header" value="true"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_method_declaration" value="do not insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.comment.align_tags_names_descriptions" value="false"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_enum_constant" value="do not insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.keep_if_then_body_block_on_one_line" value="one_line_if_empty"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.blank_lines_before_first_class_body_declaration" value="0"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_before_closing_brace_in_array_initializer" value="do not insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_constructor_declaration_parameters" value="do not insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.format_guardian_clause_on_one_line" value="false"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_if" value="insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.align_assignment_statements_on_columns" value="false"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_permitted_types" value="do not insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.brace_position_for_block_in_case" value="next_line"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_constructor_declaration" value="do not insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.alignment_for_conditional_expression_chain" value="0"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.comment.format_header" value="false"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.alignment_for_type_annotations" value="0"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.alignment_for_arguments_in_allocation_expression" value="16"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.wrap_before_assertion_message_operator" value="true"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_switch" value="do not insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.alignment_for_method_declaration" value="0"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.align_fields_grouping_blank_lines" value="2147483647"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.comment.new_lines_at_javadoc_boundaries" value="true"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.alignment_for_bitwise_operator" value="16"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.brace_position_for_annotation_type_declaration" value="next_line"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_colon_in_for" value="insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.alignment_for_resources_in_try" value="80"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.alignment_for_selector_in_method_invocation" value="16"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.never_indent_block_comments_on_first_column" value="false"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_synchronized" value="do not insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_allocation_expression" value="insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.comment.format_source_code" value="true"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_array_initializer" value="do not insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.blank_lines_before_field" value="0"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_at_in_annotation" value="do not insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.blank_lines_before_method" value="1"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.alignment_for_superclass_in_type_declaration" value="16"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_parenthesized_expression_in_throw" value="insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_not_operator" value="do not insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_after_type_annotation" value="do not insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_brace_in_array_initializer" value="do not insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_parenthesized_expression" value="do not insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.comment.format_html" value="true"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_at_in_annotation_type_declaration" value="do not insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.parentheses_positions_in_method_delcaration" value="common_lines"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.alignment_for_compact_if" value="16"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.indent_empty_lines" value="false"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.alignment_for_type_arguments" value="0"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_unary_operator" value="do not insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_enum_constant" value="do not insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.alignment_for_arguments_in_annotation" value="16"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_enum_declarations" value="do not insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.alignment_for_annotations_on_package" value="49"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.indent_switchstatements_compare_to_switch" value="false"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_before_else_in_if_statement" value="insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_assignment_operator" value="insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_after_label" value="do not insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_enum_declaration_header" value="true"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_colon_in_conditional" value="insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_method_declaration_parameters" value="do not insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_cast" value="do not insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_arrow_in_switch_case" value="insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_before_while_in_do_statement" value="do not insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_bracket_in_array_type_reference" value="do not insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.alignment_for_permitted_types_in_type_declaration" value="16"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_record_header" value="true"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_angle_bracket_in_parameterized_type_reference" value="do not insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_after_opening_brace_in_array_initializer" value="do not insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.indent_breaks_compare_to_cases" value="true"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_method_declaration" value="do not insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.wrap_before_bitwise_operator" value="true"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.comment.javadoc_do_not_separate_block_tags" value="false"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_try" value="do not insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_lambda_arrow" value="insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_method_declaration" value="do not insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.comment.indent_tag_description" value="false"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.keep_imple_if_on_one_line" value="false"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.brace_position_for_record_constructor" value="next_line"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_enum_declaration" value="insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_between_brackets_in_array_type_reference" value="do not insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_angle_bracket_in_type_parameters" value="do not insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.alignment_for_string_concatenation" value="16"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_semicolon_in_for" value="do not insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_bracket_in_array_allocation_expression" value="do not insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.alignment_for_multiple_fields" value="16"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_enum_constant_arguments" value="insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_prefix_operator" value="do not insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.brace_position_for_array_initializer" value="end_of_line"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_shift_operator" value="insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_method_declaration" value="insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_type_parameters" value="insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_catch" value="do not insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_shift_operator" value="insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_between_empty_braces_in_array_initializer" value="do not insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_multiple_local_declarations" value="do not insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.keep_simple_do_while_body_on_same_line" value="false"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_annotation_type_declaration" value="insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_record_components" value="do not insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.wrap_outer_expressions_when_nested" value="true"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_closing_paren_in_cast" value="insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_synchronized" value="insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_annotation_type_member_declaration" value="do not insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.alignment_for_expressions_in_for_loop_header" value="0"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.wrap_before_additive_operator" value="true"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.keep_simple_getter_setter_on_one_line" value="false"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_while" value="do not insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_angle_bracket_in_type_parameters" value="do not insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_string_concatenation" value="insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_lambda_arrow" value="insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.join_lines_in_comments" value="true"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_record_declaration" value="do not insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_relational_operator" value="insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_multiple_field_declarations" value="do not insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.blank_lines_between_import_groups" value="1"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_at_in_annotation_type_declaration" value="insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_logical_operator" value="insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.parentheses_positions_in_method_invocation" value="common_lines"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.blank_lines_after_imports" value="1"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.comment.insert_new_line_before_root_tags" value="insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.parentheses_positions_in_record_declaration" value="common_lines"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_method_declaration_throws" value="do not insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.parentheses_positions_in_switch_statement" value="common_lines"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_postfix_operator" value="do not insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_for_increments" value="insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_type_arguments" value="insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_arrow_in_switch_default" value="insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_for_inits" value="do not insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.disabling_tag" value="@formatter:off"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.alignment_for_enum_constants" value="0"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.blank_lines_before_imports" value="1"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.number_of_blank_lines_at_end_of_method_body" value="0"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.parentheses_positions_in_if_while_statement" value="common_lines"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_closing_brace_in_block" value="insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_parenthesized_expression_in_return" value="insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_arrow_in_switch_case" value="insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_field" value="insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.blank_lines_between_type_declarations" value="1"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.keep_switch_body_block_on_one_line" value="one_line_never"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_for" value="do not insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_catch" value="do not insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_switch" value="do not insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_anonymous_type_declaration" value="insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.never_indent_line_comments_on_first_column" value="false"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_for_inits" value="insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.indent_statements_compare_to_block" value="true"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.brace_position_for_anonymous_type_declaration" value="end_of_line"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_question_in_wildcard" value="do not insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_annotation" value="do not insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_method_invocation_arguments" value="do not insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.alignment_for_expressions_in_switch_case_with_arrow" value="0"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_switch" value="insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.comment.align_tags_descriptions_grouped" value="false"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.comment.line_length" value="999"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.use_on_off_tags" value="true"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.keep_method_body_on_one_line" value="one_line_if_empty"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_between_empty_brackets_in_array_allocation_expression" value="do not insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.keep_loop_body_block_on_one_line" value="one_line_if_empty"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_enum_constant" value="insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.brace_position_for_method_declaration" value="next_line"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_colon_in_for" value="insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.keep_type_declaration_on_one_line" value="one_line_if_empty"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_closing_angle_bracket_in_type_arguments" value="insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.alignment_for_additive_operator" value="16"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_multiple_field_declarations" value="insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_record_constructor" value="insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_relational_operator" value="insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_superinterfaces" value="insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.keep_record_declaration_on_one_line" value="one_line_if_empty"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_colon_in_default" value="do not insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_question_in_conditional" value="insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.brace_position_for_constructor_declaration" value="next_line"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.brace_position_for_lambda_body" value="end_of_line"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.compact_else_if" value="true"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_type_parameters" value="do not insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_catch" value="insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_method_invocation" value="do not insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_method_invocation_arguments" value="insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.alignment_for_arguments_in_method_invocation" value="16"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.alignment_for_throws_clause_in_constructor_declaration" value="16"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_before_catch_in_try_statement" value="insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_try" value="insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.alignment_for_annotations_on_parameter" value="0"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.comment.clear_blank_lines_in_javadoc_comment" value="false"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.alignment_for_relational_operator" value="0"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.alignment_for_expressions_in_array_initializer" value="16"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.number_of_empty_lines_to_preserve" value="1"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_colon_in_case" value="insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_additive_operator" value="insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_if" value="do not insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_type_arguments" value="do not insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_string_concatenation" value="insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.comment.format_line_comments" value="true"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.align_selector_in_method_invocation_on_expression_first_line" value="false"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.brace_position_for_record_declaration" value="next_line"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_colon_in_labeled_statement" value="insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.keep_switch_case_with_arrow_on_one_line" value="one_line_never"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.alignment_for_expressions_in_switch_case_with_colon" value="0"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.number_of_blank_lines_after_code_block" value="0"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.alignment_for_superinterfaces_in_type_declaration" value="16"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.alignment_for_conditional_expression" value="80"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_type" value="insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.alignment_for_annotations_on_type" value="49"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_block" value="insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.alignment_for_annotations_on_local_variable" value="49"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.brace_position_for_enum_declaration" value="next_line"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_arrow_in_switch_default" value="insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.comment.insert_new_line_between_different_tags" value="do not insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_additive_operator" value="insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_method_invocation" value="do not insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_while" value="insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.join_wrapped_lines" value="false"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_constructor_declaration" value="do not insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.alignment_for_annotations_on_field" value="49"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.wrap_before_conditional_operator" value="true"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.indent_switchstatements_compare_to_cases" value="true"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_bracket_in_array_allocation_expression" value="do not insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_synchronized" value="do not insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.alignment_for_shift_operator" value="0"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.use_tabs_only_for_leading_indentations" value="false"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.parentheses_positions_in_try_clause" value="common_lines"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.keep_code_block_on_one_line" value="one_line_if_empty"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_constructor_declaration_throws" value="insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_record_components" value="insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.tabulation.size" value="4"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_bitwise_operator" value="insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_bracket_in_array_reference" value="do not insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_colon_in_conditional" value="insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_try" value="do not insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_semicolon_in_try_resources" value="insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.continuation_indentation_for_array_initializer" value="2"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_question_in_wildcard" value="do not insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_record_declaration" value="do not insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.alignment_for_superinterfaces_in_enum_declaration" value="16"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.wrap_before_assignment_operator" value="false"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_colon_in_labeled_statement" value="do not insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.brace_position_for_switch" value="next_line"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_superinterfaces" value="do not insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_method_declaration_parameters" value="insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_closing_angle_bracket_in_type_parameters" value="insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.alignment_for_switch_case_with_arrow" value="0"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.keep_lambda_body_block_on_one_line" value="one_line_if_empty"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.alignment_for_annotations_on_method" value="49"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_parameterized_type_reference" value="do not insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.keep_record_constructor_on_one_line" value="one_line_if_empty"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_record_declaration" value="insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.keep_empty_array_initializer_on_one_line" value="true"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.alignment_for_assertion_message" value="0"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_constructor_declaration" value="do not insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.blank_lines_before_new_chunk" value="1"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_bracket_in_array_allocation_expression" value="do not insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_constructor_declaration" value="do not insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_angle_bracket_in_parameterized_type_reference" value="do not insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_angle_bracket_in_type_arguments" value="do not insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_colon_in_assert" value="insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.blank_lines_before_member_type" value="1"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_logical_operator" value="insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.alignment_for_arguments_in_qualified_allocation_expression" value="16"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.alignment_for_superinterfaces_in_record_declaration" value="16"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_if" value="do not insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_semicolon" value="do not insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.wrap_before_relational_operator" value="true"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_postfix_operator" value="do not insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_angle_bracket_in_type_arguments" value="do not insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_cast" value="do not insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.comment.format_block_comments" value="true"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.alignment_for_parameters_in_method_declaration" value="16"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_method_declaration_throws" value="insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.blank_lines_after_last_class_body_declaration" value="0"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.indent_statements_compare_to_body" value="true"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.keep_simple_while_body_on_same_line" value="false"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.wrap_before_logical_operator" value="true"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.blank_lines_between_statement_group_in_switch" value="0"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_bracket_in_array_reference" value="do not insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_annotation" value="insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_enum_constant_arguments" value="do not insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.parentheses_positions_in_lambda_declaration" value="common_lines"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_colon_in_case" value="do not insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_permitted_types" value="insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_bracket_in_array_reference" value="do not insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.keep_enum_declaration_on_one_line" value="one_line_if_empty"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_method_declaration" value="do not insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.brace_position_for_enum_constant" value="next_line"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.brace_position_for_type_declaration" value="next_line"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_multiplicative_operator" value="insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.blank_lines_before_package" value="0"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_for" value="insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_for_increments" value="do not insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_enum_constant" value="do not insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_explicitconstructorcall_arguments" value="do not insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_annotation" value="do not insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_enum_constant_header" value="true"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_constructor_declaration" value="insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_constructor_declaration_throws" value="do not insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_angle_bracket_in_type_parameters" value="do not insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_question_in_conditional" value="insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.comment.indent_parameter_description" value="true"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.number_of_blank_lines_at_beginning_of_code_block" value="0"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_before_finally_in_try_statement" value="insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.tabulation.char" value="space"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.wrap_before_string_concatenation" value="true"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.lineSplit" value="999"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_annotation" value="do not insert"/>
|
||||||
|
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_switch" value="insert"/>
|
||||||
|
</profile>
|
||||||
|
</profiles>
|
@@ -7,7 +7,7 @@
|
|||||||
<parent>
|
<parent>
|
||||||
<groupId>org.alfresco</groupId>
|
<groupId>org.alfresco</groupId>
|
||||||
<artifactId>alfresco-community-repo-amps</artifactId>
|
<artifactId>alfresco-community-repo-amps</artifactId>
|
||||||
<version>22.108</version>
|
<version>22.36</version>
|
||||||
</parent>
|
</parent>
|
||||||
|
|
||||||
<modules>
|
<modules>
|
||||||
|
@@ -7,7 +7,7 @@
|
|||||||
<parent>
|
<parent>
|
||||||
<groupId>org.alfresco</groupId>
|
<groupId>org.alfresco</groupId>
|
||||||
<artifactId>alfresco-governance-services-community-parent</artifactId>
|
<artifactId>alfresco-governance-services-community-parent</artifactId>
|
||||||
<version>22.108</version>
|
<version>22.36</version>
|
||||||
</parent>
|
</parent>
|
||||||
|
|
||||||
<modules>
|
<modules>
|
||||||
|
@@ -7,7 +7,7 @@
|
|||||||
<parent>
|
<parent>
|
||||||
<groupId>org.alfresco</groupId>
|
<groupId>org.alfresco</groupId>
|
||||||
<artifactId>alfresco-governance-services-automation-community-repo</artifactId>
|
<artifactId>alfresco-governance-services-automation-community-repo</artifactId>
|
||||||
<version>22.108</version>
|
<version>22.36</version>
|
||||||
</parent>
|
</parent>
|
||||||
|
|
||||||
<build>
|
<build>
|
||||||
|
@@ -7,7 +7,7 @@
|
|||||||
<parent>
|
<parent>
|
||||||
<groupId>org.alfresco</groupId>
|
<groupId>org.alfresco</groupId>
|
||||||
<artifactId>alfresco-governance-services-community-parent</artifactId>
|
<artifactId>alfresco-governance-services-community-parent</artifactId>
|
||||||
<version>22.108</version>
|
<version>22.36</version>
|
||||||
</parent>
|
</parent>
|
||||||
|
|
||||||
<modules>
|
<modules>
|
||||||
|
@@ -8,7 +8,7 @@
|
|||||||
<parent>
|
<parent>
|
||||||
<groupId>org.alfresco</groupId>
|
<groupId>org.alfresco</groupId>
|
||||||
<artifactId>alfresco-governance-services-community-repo-parent</artifactId>
|
<artifactId>alfresco-governance-services-community-repo-parent</artifactId>
|
||||||
<version>22.108</version>
|
<version>22.36</version>
|
||||||
</parent>
|
</parent>
|
||||||
|
|
||||||
<properties>
|
<properties>
|
||||||
|
@@ -5,7 +5,7 @@
|
|||||||
# Version label
|
# Version label
|
||||||
version.major=7
|
version.major=7
|
||||||
version.minor=4
|
version.minor=4
|
||||||
version.revision=3
|
version.revision=2
|
||||||
version.label=
|
version.label=
|
||||||
|
|
||||||
# Edition label
|
# Edition label
|
||||||
|
@@ -7,7 +7,7 @@
|
|||||||
<parent>
|
<parent>
|
||||||
<groupId>org.alfresco</groupId>
|
<groupId>org.alfresco</groupId>
|
||||||
<artifactId>alfresco-governance-services-community-repo-parent</artifactId>
|
<artifactId>alfresco-governance-services-community-repo-parent</artifactId>
|
||||||
<version>22.108</version>
|
<version>22.36</version>
|
||||||
</parent>
|
</parent>
|
||||||
|
|
||||||
<build>
|
<build>
|
||||||
|
@@ -7,7 +7,7 @@
|
|||||||
<parent>
|
<parent>
|
||||||
<groupId>org.alfresco</groupId>
|
<groupId>org.alfresco</groupId>
|
||||||
<artifactId>alfresco-community-repo</artifactId>
|
<artifactId>alfresco-community-repo</artifactId>
|
||||||
<version>22.108</version>
|
<version>22.36</version>
|
||||||
</parent>
|
</parent>
|
||||||
|
|
||||||
<modules>
|
<modules>
|
||||||
|
@@ -8,7 +8,7 @@
|
|||||||
<parent>
|
<parent>
|
||||||
<groupId>org.alfresco</groupId>
|
<groupId>org.alfresco</groupId>
|
||||||
<artifactId>alfresco-community-repo-amps</artifactId>
|
<artifactId>alfresco-community-repo-amps</artifactId>
|
||||||
<version>22.108</version>
|
<version>22.36</version>
|
||||||
</parent>
|
</parent>
|
||||||
|
|
||||||
<properties>
|
<properties>
|
||||||
|
@@ -7,7 +7,7 @@
|
|||||||
<parent>
|
<parent>
|
||||||
<groupId>org.alfresco</groupId>
|
<groupId>org.alfresco</groupId>
|
||||||
<artifactId>alfresco-community-repo</artifactId>
|
<artifactId>alfresco-community-repo</artifactId>
|
||||||
<version>22.108</version>
|
<version>22.36</version>
|
||||||
</parent>
|
</parent>
|
||||||
|
|
||||||
<dependencies>
|
<dependencies>
|
||||||
|
@@ -7,7 +7,7 @@
|
|||||||
<parent>
|
<parent>
|
||||||
<groupId>org.alfresco</groupId>
|
<groupId>org.alfresco</groupId>
|
||||||
<artifactId>alfresco-community-repo</artifactId>
|
<artifactId>alfresco-community-repo</artifactId>
|
||||||
<version>22.108</version>
|
<version>22.36</version>
|
||||||
</parent>
|
</parent>
|
||||||
|
|
||||||
<properties>
|
<properties>
|
||||||
|
@@ -7,7 +7,7 @@
|
|||||||
<parent>
|
<parent>
|
||||||
<groupId>org.alfresco</groupId>
|
<groupId>org.alfresco</groupId>
|
||||||
<artifactId>alfresco-community-repo</artifactId>
|
<artifactId>alfresco-community-repo</artifactId>
|
||||||
<version>22.108</version>
|
<version>22.36</version>
|
||||||
</parent>
|
</parent>
|
||||||
|
|
||||||
<dependencies>
|
<dependencies>
|
||||||
|
@@ -9,6 +9,6 @@
|
|||||||
<parent>
|
<parent>
|
||||||
<groupId>org.alfresco</groupId>
|
<groupId>org.alfresco</groupId>
|
||||||
<artifactId>alfresco-community-repo-packaging</artifactId>
|
<artifactId>alfresco-community-repo-packaging</artifactId>
|
||||||
<version>22.108</version>
|
<version>22.36</version>
|
||||||
</parent>
|
</parent>
|
||||||
</project>
|
</project>
|
||||||
|
@@ -7,7 +7,7 @@
|
|||||||
<parent>
|
<parent>
|
||||||
<groupId>org.alfresco</groupId>
|
<groupId>org.alfresco</groupId>
|
||||||
<artifactId>alfresco-community-repo-packaging</artifactId>
|
<artifactId>alfresco-community-repo-packaging</artifactId>
|
||||||
<version>22.108</version>
|
<version>22.36</version>
|
||||||
</parent>
|
</parent>
|
||||||
|
|
||||||
<properties>
|
<properties>
|
||||||
|
@@ -7,7 +7,7 @@
|
|||||||
<parent>
|
<parent>
|
||||||
<groupId>org.alfresco</groupId>
|
<groupId>org.alfresco</groupId>
|
||||||
<artifactId>alfresco-community-repo</artifactId>
|
<artifactId>alfresco-community-repo</artifactId>
|
||||||
<version>22.108</version>
|
<version>22.36</version>
|
||||||
</parent>
|
</parent>
|
||||||
|
|
||||||
<modules>
|
<modules>
|
||||||
|
@@ -6,7 +6,7 @@
|
|||||||
<parent>
|
<parent>
|
||||||
<groupId>org.alfresco</groupId>
|
<groupId>org.alfresco</groupId>
|
||||||
<artifactId>alfresco-community-repo-packaging</artifactId>
|
<artifactId>alfresco-community-repo-packaging</artifactId>
|
||||||
<version>22.108</version>
|
<version>22.36</version>
|
||||||
</parent>
|
</parent>
|
||||||
|
|
||||||
<modules>
|
<modules>
|
||||||
|
@@ -7,7 +7,7 @@
|
|||||||
<parent>
|
<parent>
|
||||||
<groupId>org.alfresco</groupId>
|
<groupId>org.alfresco</groupId>
|
||||||
<artifactId>alfresco-community-repo-tests</artifactId>
|
<artifactId>alfresco-community-repo-tests</artifactId>
|
||||||
<version>22.108</version>
|
<version>22.36</version>
|
||||||
</parent>
|
</parent>
|
||||||
|
|
||||||
<organization>
|
<organization>
|
||||||
|
@@ -9,7 +9,7 @@
|
|||||||
<parent>
|
<parent>
|
||||||
<groupId>org.alfresco</groupId>
|
<groupId>org.alfresco</groupId>
|
||||||
<artifactId>alfresco-community-repo-tests</artifactId>
|
<artifactId>alfresco-community-repo-tests</artifactId>
|
||||||
<version>22.108</version>
|
<version>22.36</version>
|
||||||
</parent>
|
</parent>
|
||||||
|
|
||||||
<developers>
|
<developers>
|
||||||
|
@@ -9,7 +9,7 @@
|
|||||||
<parent>
|
<parent>
|
||||||
<groupId>org.alfresco</groupId>
|
<groupId>org.alfresco</groupId>
|
||||||
<artifactId>alfresco-community-repo-tests</artifactId>
|
<artifactId>alfresco-community-repo-tests</artifactId>
|
||||||
<version>22.108</version>
|
<version>22.36</version>
|
||||||
</parent>
|
</parent>
|
||||||
|
|
||||||
<developers>
|
<developers>
|
||||||
|
@@ -8,7 +8,7 @@
|
|||||||
<parent>
|
<parent>
|
||||||
<groupId>org.alfresco</groupId>
|
<groupId>org.alfresco</groupId>
|
||||||
<artifactId>alfresco-community-repo-tests</artifactId>
|
<artifactId>alfresco-community-repo-tests</artifactId>
|
||||||
<version>22.108</version>
|
<version>22.36</version>
|
||||||
</parent>
|
</parent>
|
||||||
|
|
||||||
<properties>
|
<properties>
|
||||||
|
@@ -9,7 +9,7 @@
|
|||||||
<parent>
|
<parent>
|
||||||
<groupId>org.alfresco</groupId>
|
<groupId>org.alfresco</groupId>
|
||||||
<artifactId>alfresco-community-repo-tests</artifactId>
|
<artifactId>alfresco-community-repo-tests</artifactId>
|
||||||
<version>22.108</version>
|
<version>22.36</version>
|
||||||
</parent>
|
</parent>
|
||||||
|
|
||||||
<developers>
|
<developers>
|
||||||
|
@@ -7,7 +7,7 @@
|
|||||||
<parent>
|
<parent>
|
||||||
<groupId>org.alfresco</groupId>
|
<groupId>org.alfresco</groupId>
|
||||||
<artifactId>alfresco-community-repo-packaging</artifactId>
|
<artifactId>alfresco-community-repo-packaging</artifactId>
|
||||||
<version>22.108</version>
|
<version>22.36</version>
|
||||||
</parent>
|
</parent>
|
||||||
|
|
||||||
<properties>
|
<properties>
|
||||||
|
39
pom.xml
39
pom.xml
@@ -2,7 +2,7 @@
|
|||||||
<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">
|
<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>
|
<modelVersion>4.0.0</modelVersion>
|
||||||
<artifactId>alfresco-community-repo</artifactId>
|
<artifactId>alfresco-community-repo</artifactId>
|
||||||
<version>22.108</version>
|
<version>22.36</version>
|
||||||
<packaging>pom</packaging>
|
<packaging>pom</packaging>
|
||||||
<name>Alfresco Community Repo Parent</name>
|
<name>Alfresco Community Repo Parent</name>
|
||||||
|
|
||||||
@@ -25,7 +25,7 @@
|
|||||||
<properties>
|
<properties>
|
||||||
<acs.version.major>7</acs.version.major>
|
<acs.version.major>7</acs.version.major>
|
||||||
<acs.version.minor>4</acs.version.minor>
|
<acs.version.minor>4</acs.version.minor>
|
||||||
<acs.version.revision>3</acs.version.revision>
|
<acs.version.revision>2</acs.version.revision>
|
||||||
<acs.version.label />
|
<acs.version.label />
|
||||||
<amp.min.version>${acs.version.major}.0.0</amp.min.version>
|
<amp.min.version>${acs.version.major}.0.0</amp.min.version>
|
||||||
|
|
||||||
@@ -52,12 +52,12 @@
|
|||||||
<dependency.alfresco-messaging-repo.version>1.2.20</dependency.alfresco-messaging-repo.version>
|
<dependency.alfresco-messaging-repo.version>1.2.20</dependency.alfresco-messaging-repo.version>
|
||||||
<dependency.activiti-engine.version>5.23.0</dependency.activiti-engine.version>
|
<dependency.activiti-engine.version>5.23.0</dependency.activiti-engine.version>
|
||||||
<dependency.activiti.version>5.23.0</dependency.activiti.version>
|
<dependency.activiti.version>5.23.0</dependency.activiti.version>
|
||||||
<dependency.alfresco-transform-core.version>5.1.5</dependency.alfresco-transform-core.version>
|
<dependency.alfresco-transform-service.version>4.1.3</dependency.alfresco-transform-service.version>
|
||||||
<dependency.alfresco-transform-service.version>4.1.5</dependency.alfresco-transform-service.version>
|
<dependency.alfresco-transform-core.version>5.1.3</dependency.alfresco-transform-core.version>
|
||||||
<dependency.alfresco-greenmail.version>6.5</dependency.alfresco-greenmail.version>
|
<dependency.alfresco-greenmail.version>6.5</dependency.alfresco-greenmail.version>
|
||||||
<dependency.acs-event-model.version>0.0.18</dependency.acs-event-model.version>
|
<dependency.acs-event-model.version>0.0.18</dependency.acs-event-model.version>
|
||||||
|
|
||||||
<dependency.spring.version>5.3.34</dependency.spring.version>
|
<dependency.spring.version>5.3.39</dependency.spring.version>
|
||||||
<dependency.antlr.version>3.5.3</dependency.antlr.version>
|
<dependency.antlr.version>3.5.3</dependency.antlr.version>
|
||||||
<dependency.jackson.version>2.15.4</dependency.jackson.version>
|
<dependency.jackson.version>2.15.4</dependency.jackson.version>
|
||||||
<dependency.cxf.version>3.5.5</dependency.cxf.version>
|
<dependency.cxf.version>3.5.5</dependency.cxf.version>
|
||||||
@@ -118,6 +118,9 @@
|
|||||||
|
|
||||||
<alfresco.maven-plugin.version>2.2.0</alfresco.maven-plugin.version>
|
<alfresco.maven-plugin.version>2.2.0</alfresco.maven-plugin.version>
|
||||||
<license-maven-plugin.version>2.0.1.alfresco-2</license-maven-plugin.version>
|
<license-maven-plugin.version>2.0.1.alfresco-2</license-maven-plugin.version>
|
||||||
|
<spotless-plugin.version>2.43.0</spotless-plugin.version>
|
||||||
|
<!-- Do not match any files by default, but this can be overridden from the command line. -->
|
||||||
|
<spotless-include-list>NO_AUTOMATED_FORMATTING</spotless-include-list>
|
||||||
|
|
||||||
<dependency.postgresql.version>42.5.2</dependency.postgresql.version>
|
<dependency.postgresql.version>42.5.2</dependency.postgresql.version>
|
||||||
<dependency.mysql.version>8.0.30</dependency.mysql.version>
|
<dependency.mysql.version>8.0.30</dependency.mysql.version>
|
||||||
@@ -151,7 +154,7 @@
|
|||||||
<connection>scm:git:https://github.com/Alfresco/alfresco-community-repo.git</connection>
|
<connection>scm:git:https://github.com/Alfresco/alfresco-community-repo.git</connection>
|
||||||
<developerConnection>scm:git:https://github.com/Alfresco/alfresco-community-repo.git</developerConnection>
|
<developerConnection>scm:git:https://github.com/Alfresco/alfresco-community-repo.git</developerConnection>
|
||||||
<url>https://github.com/Alfresco/alfresco-community-repo</url>
|
<url>https://github.com/Alfresco/alfresco-community-repo</url>
|
||||||
<tag>22.108</tag>
|
<tag>22.36</tag>
|
||||||
</scm>
|
</scm>
|
||||||
|
|
||||||
<distributionManagement>
|
<distributionManagement>
|
||||||
@@ -1021,6 +1024,26 @@
|
|||||||
<skipDeploy>true</skipDeploy>
|
<skipDeploy>true</skipDeploy>
|
||||||
</configuration>
|
</configuration>
|
||||||
</plugin>
|
</plugin>
|
||||||
|
<plugin>
|
||||||
|
<groupId>com.diffplug.spotless</groupId>
|
||||||
|
<artifactId>spotless-maven-plugin</artifactId>
|
||||||
|
<version>${spotless-plugin.version}</version>
|
||||||
|
<configuration>
|
||||||
|
<java>
|
||||||
|
<includes>
|
||||||
|
${spotless-include-list}
|
||||||
|
</includes>
|
||||||
|
<eclipse>
|
||||||
|
<file>alfresco-formatter.xml</file>
|
||||||
|
</eclipse>
|
||||||
|
<importOrder>
|
||||||
|
<order>\#java|\#javax|\#jakarta,\#,\#org.alfresco,java|javax|jakarta,,org.alfresco</order>
|
||||||
|
</importOrder>
|
||||||
|
<removeUnusedImports />
|
||||||
|
<formatAnnotations />
|
||||||
|
</java>
|
||||||
|
</configuration>
|
||||||
|
</plugin>
|
||||||
</plugins>
|
</plugins>
|
||||||
</pluginManagement>
|
</pluginManagement>
|
||||||
<plugins>
|
<plugins>
|
||||||
@@ -1028,6 +1051,10 @@
|
|||||||
<groupId>org.codehaus.mojo</groupId>
|
<groupId>org.codehaus.mojo</groupId>
|
||||||
<artifactId>license-maven-plugin</artifactId>
|
<artifactId>license-maven-plugin</artifactId>
|
||||||
</plugin>
|
</plugin>
|
||||||
|
<plugin>
|
||||||
|
<groupId>com.diffplug.spotless</groupId>
|
||||||
|
<artifactId>spotless-maven-plugin</artifactId>
|
||||||
|
</plugin>
|
||||||
</plugins>
|
</plugins>
|
||||||
</build>
|
</build>
|
||||||
</project>
|
</project>
|
||||||
|
@@ -7,7 +7,7 @@
|
|||||||
<parent>
|
<parent>
|
||||||
<groupId>org.alfresco</groupId>
|
<groupId>org.alfresco</groupId>
|
||||||
<artifactId>alfresco-community-repo</artifactId>
|
<artifactId>alfresco-community-repo</artifactId>
|
||||||
<version>22.108</version>
|
<version>22.36</version>
|
||||||
</parent>
|
</parent>
|
||||||
|
|
||||||
<dependencies>
|
<dependencies>
|
||||||
|
@@ -7,7 +7,7 @@
|
|||||||
<parent>
|
<parent>
|
||||||
<groupId>org.alfresco</groupId>
|
<groupId>org.alfresco</groupId>
|
||||||
<artifactId>alfresco-community-repo</artifactId>
|
<artifactId>alfresco-community-repo</artifactId>
|
||||||
<version>22.108</version>
|
<version>22.36</version>
|
||||||
</parent>
|
</parent>
|
||||||
|
|
||||||
<dependencies>
|
<dependencies>
|
||||||
|
@@ -28,30 +28,26 @@ package org.alfresco.repo.cache.lookup;
|
|||||||
import java.io.Serializable;
|
import java.io.Serializable;
|
||||||
import java.sql.Savepoint;
|
import java.sql.Savepoint;
|
||||||
|
|
||||||
|
import org.springframework.dao.ConcurrencyFailureException;
|
||||||
|
import org.springframework.extensions.surf.util.ParameterCheck;
|
||||||
|
|
||||||
import org.alfresco.repo.cache.SimpleCache;
|
import org.alfresco.repo.cache.SimpleCache;
|
||||||
import org.alfresco.repo.domain.control.ControlDAO;
|
import org.alfresco.repo.domain.control.ControlDAO;
|
||||||
import org.alfresco.repo.transaction.RetryingTransactionHelper;
|
import org.alfresco.repo.transaction.RetryingTransactionHelper;
|
||||||
import org.alfresco.util.Pair;
|
import org.alfresco.util.Pair;
|
||||||
import org.springframework.dao.ConcurrencyFailureException;
|
|
||||||
import org.springframework.extensions.surf.util.ParameterCheck;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A cache for two-way lookups of database entities. These are characterized by having a unique
|
* A cache for two-way lookups of database entities. These are characterized by having a unique key (perhaps a database ID) and a separate unique key that identifies the object. If no cache is given, then all calls are passed through to the backing DAO.
|
||||||
* key (perhaps a database ID) and a separate unique key that identifies the object. If no cache
|
|
||||||
* is given, then all calls are passed through to the backing DAO.
|
|
||||||
* <p>
|
* <p>
|
||||||
* The keys must have good <code>equals</code> and <code>hashCode</code> implementations and
|
* The keys must have good <code>equals</code> and <code>hashCode</code> implementations and must respect the case-sensitivity of the use-case.
|
||||||
* must respect the case-sensitivity of the use-case.
|
|
||||||
* <p>
|
* <p>
|
||||||
* All keys will be unique to the given cache region, allowing the cache to be shared
|
* All keys will be unique to the given cache region, allowing the cache to be shared between instances of this class.
|
||||||
* between instances of this class.
|
|
||||||
* <p>
|
* <p>
|
||||||
* Generics:
|
* Generics:
|
||||||
* <ul>
|
* <ul>
|
||||||
* <li>K: The database unique identifier.</li>
|
* <li>K: The database unique identifier.</li>
|
||||||
* <li>V: The value stored against K.</li>
|
* <li>V: The value stored against K.</li>
|
||||||
* <li>VK: The a value-derived key that will be used as a cache key when caching K for lookups by V.
|
* <li>VK: The a value-derived key that will be used as a cache key when caching K for lookups by V. This can be the value itself if it is itself a good key.</li>
|
||||||
* This can be the value itself if it is itself a good key.</li>
|
|
||||||
* </ul>
|
* </ul>
|
||||||
*
|
*
|
||||||
* @author Derek Hulley
|
* @author Derek Hulley
|
||||||
@@ -65,60 +61,47 @@ public class EntityLookupCache<K extends Serializable, V extends Object, VK exte
|
|||||||
public static interface EntityLookupCallbackDAO<K1 extends Serializable, V1 extends Object, VK1 extends Serializable>
|
public static interface EntityLookupCallbackDAO<K1 extends Serializable, V1 extends Object, VK1 extends Serializable>
|
||||||
{
|
{
|
||||||
/**
|
/**
|
||||||
* Resolve the given value into a unique value key that can be used to find the entity's ID.
|
* Resolve the given value into a unique value key that can be used to find the entity's ID. A return value should be small and efficient; don't return a value if this is not possible.
|
||||||
* A return value should be small and efficient; don't return a value if this is not possible.
|
|
||||||
* <p/>
|
* <p/>
|
||||||
* Implementations will often return the value itself, provided that the value is both
|
* Implementations will often return the value itself, provided that the value is both serializable and has a good <code>equals</code> and <code>hashCode</code>.
|
||||||
* serializable and has a good <code>equals</code> and <code>hashCode</code>.
|
|
||||||
* <p/>
|
* <p/>
|
||||||
* Were no adequate key can be generated for the value, then <tt>null</tt> can be returned.
|
* Were no adequate key can be generated for the value, then <tt>null</tt> can be returned. In this case, the {@link #findByValue(Object) findByValue} method might not even do a search and just return <tt>null</tt> itself i.e. if it is difficult to look the value up in storage then it is probably difficult to generate a cache key from it, too.. In this scenario, the cache will be purely for key-based lookups
|
||||||
* In this case, the {@link #findByValue(Object) findByValue} method might not even do a search
|
|
||||||
* and just return <tt>null</tt> itself i.e. if it is difficult to look the value up in storage
|
|
||||||
* then it is probably difficult to generate a cache key from it, too.. In this scenario, the
|
|
||||||
* cache will be purely for key-based lookups
|
|
||||||
*
|
*
|
||||||
* @param value the full value being keyed (never <tt>null</tt>)
|
* @param value
|
||||||
* @return Returns the business key representing the entity, or <tt>null</tt>
|
* the full value being keyed (never <tt>null</tt>)
|
||||||
* if an economical key cannot be generated.
|
* @return Returns the business key representing the entity, or <tt>null</tt> if an economical key cannot be generated.
|
||||||
*/
|
*/
|
||||||
VK1 getValueKey(V1 value);
|
VK1 getValueKey(V1 value);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Find an entity for a given key.
|
* Find an entity for a given key.
|
||||||
*
|
*
|
||||||
* @param key the key (ID) used to identify the entity (never <tt>null</tt>)
|
* @param key
|
||||||
|
* the key (ID) used to identify the entity (never <tt>null</tt>)
|
||||||
* @return Return the entity or <tt>null</tt> if no entity is exists for the ID
|
* @return Return the entity or <tt>null</tt> if no entity is exists for the ID
|
||||||
*/
|
*/
|
||||||
Pair<K1, V1> findByKey(K1 key);
|
Pair<K1, V1> findByKey(K1 key);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Find and entity using the given value key. The <code>equals</code> and <code>hashCode</code>
|
* Find and entity using the given value key. The <code>equals</code> and <code>hashCode</code> methods of the value object should respect case-sensitivity in the same way that this lookup treats case-sensitivity i.e. if the <code>equals</code> method is <b>case-sensitive</b> then this method should look the entity up using a <b>case-sensitive</b> search.
|
||||||
* methods of the value object should respect case-sensitivity in the same way that this
|
|
||||||
* lookup treats case-sensitivity i.e. if the <code>equals</code> method is <b>case-sensitive</b>
|
|
||||||
* then this method should look the entity up using a <b>case-sensitive</b> search.
|
|
||||||
* <p/>
|
* <p/>
|
||||||
* Since this is a cache backed by some sort of database, <tt>null</tt> values are allowed by the
|
* Since this is a cache backed by some sort of database, <tt>null</tt> values are allowed by the cache. The implementation of this method can throw an exception if <tt>null</tt> is not appropriate for the use-case.
|
||||||
* cache. The implementation of this method can throw an exception if <tt>null</tt> is not
|
|
||||||
* appropriate for the use-case.
|
|
||||||
* <p/>
|
* <p/>
|
||||||
* If the search is impossible or expensive, this method should just return <tt>null</tt>. This
|
* If the search is impossible or expensive, this method should just return <tt>null</tt>. This would usually be the case if the {@link #getValueKey(Object) getValueKey} method also returned <tt>null</tt> i.e. if it is difficult to look the value up in storage then it is probably difficult to generate a cache key from it, too.
|
||||||
* would usually be the case if the {@link #getValueKey(Object) getValueKey} method also returned
|
|
||||||
* <tt>null</tt> i.e. if it is difficult to look the value up in storage then it is probably
|
|
||||||
* difficult to generate a cache key from it, too.
|
|
||||||
*
|
*
|
||||||
* @param value the value (business object) used to identify the entity (<tt>null</tt> allowed).
|
* @param value
|
||||||
|
* the value (business object) used to identify the entity (<tt>null</tt> allowed).
|
||||||
* @return Return the entity or <tt>null</tt> if no entity matches the given value
|
* @return Return the entity or <tt>null</tt> if no entity matches the given value
|
||||||
*/
|
*/
|
||||||
Pair<K1, V1> findByValue(V1 value);
|
Pair<K1, V1> findByValue(V1 value);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Create an entity using the given values. It is valid to assume that the entity does not exist
|
* Create an entity using the given values. It is valid to assume that the entity does not exist within the current transaction at least.
|
||||||
* within the current transaction at least.
|
|
||||||
* <p/>
|
* <p/>
|
||||||
* Since persistence mechanisms often allow <tt>null</tt> values, these can be expected here. The
|
* Since persistence mechanisms often allow <tt>null</tt> values, these can be expected here. The implementation must throw an exception if <tt>null</tt> is not allowed for the specific use-case.
|
||||||
* implementation must throw an exception if <tt>null</tt> is not allowed for the specific use-case.
|
|
||||||
*
|
*
|
||||||
* @param value the value (business object) used to identify the entity (<tt>null</tt> allowed).
|
* @param value
|
||||||
|
* the value (business object) used to identify the entity (<tt>null</tt> allowed).
|
||||||
* @return Return the newly-created entity ID-value pair
|
* @return Return the newly-created entity ID-value pair
|
||||||
*/
|
*/
|
||||||
Pair<K1, V1> createValue(V1 value);
|
Pair<K1, V1> createValue(V1 value);
|
||||||
@@ -126,44 +109,47 @@ public class EntityLookupCache<K extends Serializable, V extends Object, VK exte
|
|||||||
/**
|
/**
|
||||||
* Update the entity identified by the given key.
|
* Update the entity identified by the given key.
|
||||||
* <p/>
|
* <p/>
|
||||||
* It is up to the client code to decide if a <tt>0</tt> return value indicates a concurrency violation
|
* It is up to the client code to decide if a <tt>0</tt> return value indicates a concurrency violation or not.
|
||||||
* or not.
|
|
||||||
*
|
*
|
||||||
* @param key the existing key (ID) used to identify the entity (never <tt>null</tt>)
|
* @param key
|
||||||
* @param value the new value
|
* the existing key (ID) used to identify the entity (never <tt>null</tt>)
|
||||||
|
* @param value
|
||||||
|
* the new value
|
||||||
* @return Returns the row update count.
|
* @return Returns the row update count.
|
||||||
* @throws UnsupportedOperationException if entity updates are not supported
|
* @throws UnsupportedOperationException
|
||||||
|
* if entity updates are not supported
|
||||||
*/
|
*/
|
||||||
int updateValue(K1 key, V1 value);
|
int updateValue(K1 key, V1 value);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Delete an entity for the given key.
|
* Delete an entity for the given key.
|
||||||
* <p/>
|
* <p/>
|
||||||
* It is up to the client code to decide if a <tt>0</tt> return value indicates a concurrency violation
|
* It is up to the client code to decide if a <tt>0</tt> return value indicates a concurrency violation or not.
|
||||||
* or not.
|
|
||||||
*
|
*
|
||||||
* @param key the key (ID) used to identify the entity (never <tt>null</tt>)
|
* @param key
|
||||||
|
* the key (ID) used to identify the entity (never <tt>null</tt>)
|
||||||
* @return Returns the row deletion count.
|
* @return Returns the row deletion count.
|
||||||
* @throws UnsupportedOperationException if entity deletion is not supported
|
* @throws UnsupportedOperationException
|
||||||
|
* if entity deletion is not supported
|
||||||
*/
|
*/
|
||||||
int deleteByKey(K1 key);
|
int deleteByKey(K1 key);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Delete an entity for the given value.
|
* Delete an entity for the given value.
|
||||||
* <p/>
|
* <p/>
|
||||||
* It is up to the client code to decide if a <tt>0</tt> return value indicates a concurrency violation
|
* It is up to the client code to decide if a <tt>0</tt> return value indicates a concurrency violation or not.
|
||||||
* or not.
|
|
||||||
*
|
*
|
||||||
* @param value the value (business object) used to identify the enitity (<tt>null</tt> allowed)
|
* @param value
|
||||||
|
* the value (business object) used to identify the enitity (<tt>null</tt> allowed)
|
||||||
* @return Returns the row deletion count.
|
* @return Returns the row deletion count.
|
||||||
* @throws UnsupportedOperationException if entity deletion is not supported
|
* @throws UnsupportedOperationException
|
||||||
|
* if entity deletion is not supported
|
||||||
*/
|
*/
|
||||||
int deleteByValue(V1 value);
|
int deleteByValue(V1 value);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Adaptor for implementations that support immutable entities. The update and delete operations
|
* Adaptor for implementations that support immutable entities. The update and delete operations throw {@link UnsupportedOperationException}.
|
||||||
* throw {@link UnsupportedOperationException}.
|
|
||||||
*
|
*
|
||||||
* @author Derek Hulley
|
* @author Derek Hulley
|
||||||
* @since 3.2
|
* @since 3.2
|
||||||
@@ -194,7 +180,8 @@ public class EntityLookupCache<K extends Serializable, V extends Object, VK exte
|
|||||||
/**
|
/**
|
||||||
* Disallows the operation.
|
* Disallows the operation.
|
||||||
*
|
*
|
||||||
* @throws UnsupportedOperationException always
|
* @throws UnsupportedOperationException
|
||||||
|
* always
|
||||||
*/
|
*/
|
||||||
public int updateValue(K2 key, V2 value)
|
public int updateValue(K2 key, V2 value)
|
||||||
{
|
{
|
||||||
@@ -204,7 +191,8 @@ public class EntityLookupCache<K extends Serializable, V extends Object, VK exte
|
|||||||
/**
|
/**
|
||||||
* Disallows the operation.
|
* Disallows the operation.
|
||||||
*
|
*
|
||||||
* @throws UnsupportedOperationException always
|
* @throws UnsupportedOperationException
|
||||||
|
* always
|
||||||
*/
|
*/
|
||||||
public int deleteByKey(K2 key)
|
public int deleteByKey(K2 key)
|
||||||
{
|
{
|
||||||
@@ -214,7 +202,8 @@ public class EntityLookupCache<K extends Serializable, V extends Object, VK exte
|
|||||||
/**
|
/**
|
||||||
* Disallows the operation.
|
* Disallows the operation.
|
||||||
*
|
*
|
||||||
* @throws UnsupportedOperationException always
|
* @throws UnsupportedOperationException
|
||||||
|
* always
|
||||||
*/
|
*/
|
||||||
public int deleteByValue(V2 value)
|
public int deleteByValue(V2 value)
|
||||||
{
|
{
|
||||||
@@ -240,10 +229,10 @@ public class EntityLookupCache<K extends Serializable, V extends Object, VK exte
|
|||||||
private final String cacheRegion;
|
private final String cacheRegion;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Construct the lookup cache <b>without any cache</b>. All calls are passed directly to the
|
* Construct the lookup cache <b>without any cache</b>. All calls are passed directly to the underlying DAO entity lookup.
|
||||||
* underlying DAO entity lookup.
|
|
||||||
*
|
*
|
||||||
* @param entityLookup the instance that is able to find and persist entities
|
* @param entityLookup
|
||||||
|
* the instance that is able to find and persist entities
|
||||||
*/
|
*/
|
||||||
public EntityLookupCache(EntityLookupCallbackDAO<K, V, VK> entityLookup)
|
public EntityLookupCache(EntityLookupCallbackDAO<K, V, VK> entityLookup)
|
||||||
{
|
{
|
||||||
@@ -253,8 +242,10 @@ public class EntityLookupCache<K extends Serializable, V extends Object, VK exte
|
|||||||
/**
|
/**
|
||||||
* Construct the lookup cache, using the {@link #CACHE_REGION_DEFAULT default cache region}.
|
* Construct the lookup cache, using the {@link #CACHE_REGION_DEFAULT default cache region}.
|
||||||
*
|
*
|
||||||
* @param cache the cache that will back the two-way lookups
|
* @param cache
|
||||||
* @param entityLookup the instance that is able to find and persist entities
|
* the cache that will back the two-way lookups
|
||||||
|
* @param entityLookup
|
||||||
|
* the instance that is able to find and persist entities
|
||||||
*/
|
*/
|
||||||
@SuppressWarnings("rawtypes")
|
@SuppressWarnings("rawtypes")
|
||||||
public EntityLookupCache(SimpleCache cache, EntityLookupCallbackDAO<K, V, VK> entityLookup)
|
public EntityLookupCache(SimpleCache cache, EntityLookupCallbackDAO<K, V, VK> entityLookup)
|
||||||
@@ -265,13 +256,14 @@ public class EntityLookupCache<K extends Serializable, V extends Object, VK exte
|
|||||||
/**
|
/**
|
||||||
* Construct the lookup cache, using the given cache region.
|
* Construct the lookup cache, using the given cache region.
|
||||||
* <p>
|
* <p>
|
||||||
* All keys will be unique to the given cache region, allowing the cache to be shared
|
* All keys will be unique to the given cache region, allowing the cache to be shared between instances of this class.
|
||||||
* between instances of this class.
|
|
||||||
*
|
*
|
||||||
* @param cache the cache that will back the two-way lookups; <tt>null</tt> to have no backing
|
* @param cache
|
||||||
* in a cache.
|
* the cache that will back the two-way lookups; <tt>null</tt> to have no backing in a cache.
|
||||||
* @param cacheRegion the region within the cache to use.
|
* @param cacheRegion
|
||||||
* @param entityLookup the instance that is able to find and persist entities
|
* the region within the cache to use.
|
||||||
|
* @param entityLookup
|
||||||
|
* the instance that is able to find and persist entities
|
||||||
*/
|
*/
|
||||||
@SuppressWarnings({"rawtypes", "unchecked"})
|
@SuppressWarnings({"rawtypes", "unchecked"})
|
||||||
public EntityLookupCache(SimpleCache cache, String cacheRegion, EntityLookupCallbackDAO<K, V, VK> entityLookup)
|
public EntityLookupCache(SimpleCache cache, String cacheRegion, EntityLookupCallbackDAO<K, V, VK> entityLookup)
|
||||||
@@ -284,14 +276,12 @@ public class EntityLookupCache<K extends Serializable, V extends Object, VK exte
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Find the entity associated with the given key.
|
* Find the entity associated with the given key. The {@link EntityLookupCallbackDAO#findByKey(Serializable) entity callback} will be used if necessary.
|
||||||
* The {@link EntityLookupCallbackDAO#findByKey(Serializable) entity callback} will be used if necessary.
|
|
||||||
* <p/>
|
* <p/>
|
||||||
* It is up to the client code to decide if a <tt>null</tt> return value indicates a concurrency violation
|
* It is up to the client code to decide if a <tt>null</tt> return value indicates a concurrency violation or not; the former would normally result in a concurrency-related exception such as {@link ConcurrencyFailureException}.
|
||||||
* or not; the former would normally result in a concurrency-related exception such as
|
|
||||||
* {@link ConcurrencyFailureException}.
|
|
||||||
*
|
*
|
||||||
* @param key The entity key, which may be valid or invalid (<tt>null</tt> not allowed)
|
* @param key
|
||||||
|
* The entity key, which may be valid or invalid (<tt>null</tt> not allowed)
|
||||||
* @return Returns the key-value pair or <tt>null</tt> if the key doesn't reference an entity
|
* @return Returns the key-value pair or <tt>null</tt> if the key doesn't reference an entity
|
||||||
*/
|
*/
|
||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings("unchecked")
|
||||||
@@ -354,14 +344,12 @@ public class EntityLookupCache<K extends Serializable, V extends Object, VK exte
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Find the entity associated with the given value.
|
* Find the entity associated with the given value. The {@link EntityLookupCallbackDAO#findByValue(Object) entity callback} will be used if no entry exists in the cache.
|
||||||
* The {@link EntityLookupCallbackDAO#findByValue(Object) entity callback} will be used if no entry exists in the cache.
|
|
||||||
* <p/>
|
* <p/>
|
||||||
* It is up to the client code to decide if a <tt>null</tt> return value indicates a concurrency violation
|
* It is up to the client code to decide if a <tt>null</tt> return value indicates a concurrency violation or not; the former would normally result in a concurrency-related exception such as {@link ConcurrencyFailureException}.
|
||||||
* or not; the former would normally result in a concurrency-related exception such as
|
|
||||||
* {@link ConcurrencyFailureException}.
|
|
||||||
*
|
*
|
||||||
* @param value The entity value, which may be valid or invalid (<tt>null</tt> is allowed)
|
* @param value
|
||||||
|
* The entity value, which may be valid or invalid (<tt>null</tt> is allowed)
|
||||||
* @return Returns the key-value pair or <tt>null</tt> if the value doesn't reference an entity
|
* @return Returns the key-value pair or <tt>null</tt> if the value doesn't reference an entity
|
||||||
*/
|
*/
|
||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings("unchecked")
|
||||||
@@ -423,15 +411,14 @@ public class EntityLookupCache<K extends Serializable, V extends Object, VK exte
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Attempt to create the entity and, failing that, look it up.<br/>
|
* Attempt to create the entity and, failing that, look it up.<br/>
|
||||||
* This method takes the opposite approach to {@link #getOrCreateByValue(Object)}, which assumes the entity's
|
* This method takes the opposite approach to {@link #getOrCreateByValue(Object)}, which assumes the entity's existence: in this case the entity is assumed to NOT exist. The {@link EntityLookupCallbackDAO#createValue(Object)} and {@link EntityLookupCallbackDAO#findByValue(Object)} will be used if necessary.<br/>
|
||||||
* existence: in this case the entity is assumed to NOT exist.
|
|
||||||
* The {@link EntityLookupCallbackDAO#createValue(Object)} and {@link EntityLookupCallbackDAO#findByValue(Object)}
|
|
||||||
* will be used if necessary.<br/>
|
|
||||||
* <p/>
|
* <p/>
|
||||||
* Use this method when the data involved is seldom reused.
|
* Use this method when the data involved is seldom reused.
|
||||||
*
|
*
|
||||||
* @param value The entity value (<tt>null</tt> is allowed)
|
* @param value
|
||||||
* @param controlDAO an essential DAO required in order to ensure a transactionally-safe attempt at data creation
|
* The entity value (<tt>null</tt> is allowed)
|
||||||
|
* @param controlDAO
|
||||||
|
* an essential DAO required in order to ensure a transactionally-safe attempt at data creation
|
||||||
* @return Returns the key-value pair (new or existing and never <tt>null</tt>)
|
* @return Returns the key-value pair (new or existing and never <tt>null</tt>)
|
||||||
*/
|
*/
|
||||||
public Pair<K, V> createOrGetByValue(V value, ControlDAO controlDAO)
|
public Pair<K, V> createOrGetByValue(V value, ControlDAO controlDAO)
|
||||||
@@ -448,6 +435,8 @@ public class EntityLookupCache<K extends Serializable, V extends Object, VK exte
|
|||||||
// Cache it
|
// Cache it
|
||||||
if (cache != null)
|
if (cache != null)
|
||||||
{
|
{
|
||||||
|
VK valueKey = (value == null) ? (VK) VALUE_NULL : entityLookup.getValueKey(value);
|
||||||
|
cache.put(new CacheRegionValueKey(cacheRegion, valueKey), entityPair.getFirst());
|
||||||
cache.put(
|
cache.put(
|
||||||
new CacheRegionKey(cacheRegion, entityPair.getFirst()),
|
new CacheRegionKey(cacheRegion, entityPair.getFirst()),
|
||||||
(entityPair.getSecond() == null ? VALUE_NULL : entityPair.getSecond()));
|
(entityPair.getSecond() == null ? VALUE_NULL : entityPair.getSecond()));
|
||||||
@@ -464,11 +453,10 @@ public class EntityLookupCache<K extends Serializable, V extends Object, VK exte
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Find the entity associated with the given value and create it if it doesn't exist.
|
* Find the entity associated with the given value and create it if it doesn't exist. The {@link EntityLookupCallbackDAO#findByValue(Object)} and {@link EntityLookupCallbackDAO#createValue(Object)} will be used if necessary.
|
||||||
* The {@link EntityLookupCallbackDAO#findByValue(Object)} and {@link EntityLookupCallbackDAO#createValue(Object)}
|
|
||||||
* will be used if necessary.
|
|
||||||
*
|
*
|
||||||
* @param value The entity value (<tt>null</tt> is allowed)
|
* @param value
|
||||||
|
* The entity value (<tt>null</tt> is allowed)
|
||||||
* @return Returns the key-value pair (new or existing and never <tt>null</tt>)
|
* @return Returns the key-value pair (new or existing and never <tt>null</tt>)
|
||||||
*/
|
*/
|
||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings("unchecked")
|
||||||
@@ -530,16 +518,14 @@ public class EntityLookupCache<K extends Serializable, V extends Object, VK exte
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Update the entity associated with the given key.
|
* Update the entity associated with the given key. The {@link EntityLookupCallbackDAO#updateValue(Serializable, Object)} callback will be used if necessary.
|
||||||
* The {@link EntityLookupCallbackDAO#updateValue(Serializable, Object)} callback
|
|
||||||
* will be used if necessary.
|
|
||||||
* <p/>
|
* <p/>
|
||||||
* It is up to the client code to decide if a <tt>0</tt> return value indicates a concurrency violation
|
* It is up to the client code to decide if a <tt>0</tt> return value indicates a concurrency violation or not; usually the former will generate {@link ConcurrencyFailureException} or something recognised by the {@link RetryingTransactionHelper#RETRY_EXCEPTIONS RetryingTransactionHelper}.
|
||||||
* or not; usually the former will generate {@link ConcurrencyFailureException} or something recognised
|
|
||||||
* by the {@link RetryingTransactionHelper#RETRY_EXCEPTIONS RetryingTransactionHelper}.
|
|
||||||
*
|
*
|
||||||
* @param key The entity key, which may be valid or invalid (<tt>null</tt> not allowed)
|
* @param key
|
||||||
* @param value The new entity value (may be <tt>null</tt>)
|
* The entity key, which may be valid or invalid (<tt>null</tt> not allowed)
|
||||||
|
* @param value
|
||||||
|
* The new entity value (may be <tt>null</tt>)
|
||||||
* @return Returns the row update count.
|
* @return Returns the row update count.
|
||||||
*/
|
*/
|
||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings("unchecked")
|
||||||
@@ -580,10 +566,44 @@ public class EntityLookupCache<K extends Serializable, V extends Object, VK exte
|
|||||||
return updateCount;
|
return updateCount;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Find the entity associated with the given value if its cached
|
||||||
|
*
|
||||||
|
* @param value
|
||||||
|
* The entity value (<tt>null</tt> is not allowed)
|
||||||
|
* @return Returns the key-value pair (existing or <tt>null</tt>)
|
||||||
|
*/
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
|
public Pair<K, V> getCachedEntityByValue(V value)
|
||||||
|
{
|
||||||
|
if (cache == null || value == null)
|
||||||
|
{
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
VK valueKey = entityLookup.getValueKey(value);
|
||||||
|
if (valueKey == null)
|
||||||
|
{
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Retrieve the cached value
|
||||||
|
CacheRegionValueKey valueCacheKey = new CacheRegionValueKey(cacheRegion, valueKey);
|
||||||
|
K key = (K) cache.get(valueCacheKey);
|
||||||
|
|
||||||
|
if (key != null && !key.equals(VALUE_NOT_FOUND))
|
||||||
|
{
|
||||||
|
return getByKey(key);
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Cache-only operation: Get the key for a given value key (note: not 'value' but 'value key').
|
* Cache-only operation: Get the key for a given value key (note: not 'value' but 'value key').
|
||||||
*
|
*
|
||||||
* @param valueKey The entity value key, which must be valid (<tt>null</tt> not allowed)
|
* @param valueKey
|
||||||
|
* The entity value key, which must be valid (<tt>null</tt> not allowed)
|
||||||
* @return The entity key (may be <tt>null</tt>)
|
* @return The entity key (may be <tt>null</tt>)
|
||||||
*/
|
*/
|
||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings("unchecked")
|
||||||
@@ -603,7 +623,8 @@ public class EntityLookupCache<K extends Serializable, V extends Object, VK exte
|
|||||||
/**
|
/**
|
||||||
* Cache-only operation: Get the value for a given key
|
* Cache-only operation: Get the value for a given key
|
||||||
*
|
*
|
||||||
* @param key The entity key, which may be valid or invalid (<tt>null</tt> not allowed)
|
* @param key
|
||||||
|
* The entity key, which may be valid or invalid (<tt>null</tt> not allowed)
|
||||||
* @return The entity value (may be <tt>null</tt>)
|
* @return The entity value (may be <tt>null</tt>)
|
||||||
*/
|
*/
|
||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings("unchecked")
|
||||||
@@ -634,8 +655,10 @@ public class EntityLookupCache<K extends Serializable, V extends Object, VK exte
|
|||||||
/**
|
/**
|
||||||
* Cache-only operation: Update the cache's value
|
* Cache-only operation: Update the cache's value
|
||||||
*
|
*
|
||||||
* @param key The entity key, which may be valid or invalid (<tt>null</tt> not allowed)
|
* @param key
|
||||||
* @param value The new entity value (may be <tt>null</tt>)
|
* The entity key, which may be valid or invalid (<tt>null</tt> not allowed)
|
||||||
|
* @param value
|
||||||
|
* The new entity value (may be <tt>null</tt>)
|
||||||
*/
|
*/
|
||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings("unchecked")
|
||||||
public void setValue(K key, V value)
|
public void setValue(K key, V value)
|
||||||
@@ -667,14 +690,12 @@ public class EntityLookupCache<K extends Serializable, V extends Object, VK exte
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Delete the entity associated with the given key.
|
* Delete the entity associated with the given key. The {@link EntityLookupCallbackDAO#deleteByKey(Serializable)} callback will be used if necessary.
|
||||||
* The {@link EntityLookupCallbackDAO#deleteByKey(Serializable)} callback will be used if necessary.
|
|
||||||
* <p/>
|
* <p/>
|
||||||
* It is up to the client code to decide if a <tt>0</tt> return value indicates a concurrency violation
|
* It is up to the client code to decide if a <tt>0</tt> return value indicates a concurrency violation or not; usually the former will generate {@link ConcurrencyFailureException} or something recognised by the {@link RetryingTransactionHelper#RETRY_EXCEPTIONS RetryingTransactionHelper}.
|
||||||
* or not; usually the former will generate {@link ConcurrencyFailureException} or something recognised
|
|
||||||
* by the {@link RetryingTransactionHelper#RETRY_EXCEPTIONS RetryingTransactionHelper}.
|
|
||||||
*
|
*
|
||||||
* @param key the entity key, which may be valid or invalid (<tt>null</tt> not allowed)
|
* @param key
|
||||||
|
* the entity key, which may be valid or invalid (<tt>null</tt> not allowed)
|
||||||
* @return Returns the row deletion count
|
* @return Returns the row deletion count
|
||||||
*/
|
*/
|
||||||
public int deleteByKey(K key)
|
public int deleteByKey(K key)
|
||||||
@@ -693,14 +714,12 @@ public class EntityLookupCache<K extends Serializable, V extends Object, VK exte
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Delete the entity having the given value..
|
* Delete the entity having the given value.. The {@link EntityLookupCallbackDAO#deleteByValue(Object)} callback will be used if necessary.
|
||||||
* The {@link EntityLookupCallbackDAO#deleteByValue(Object)} callback will be used if necessary.
|
|
||||||
* <p/>
|
* <p/>
|
||||||
* It is up to the client code to decide if a <tt>0</tt> return value indicates a concurrency violation
|
* It is up to the client code to decide if a <tt>0</tt> return value indicates a concurrency violation or not; usually the former will generate {@link ConcurrencyFailureException} or something recognised by the {@link RetryingTransactionHelper#RETRY_EXCEPTIONS RetryingTransactionHelper}.
|
||||||
* or not; usually the former will generate {@link ConcurrencyFailureException} or something recognised
|
|
||||||
* by the {@link RetryingTransactionHelper#RETRY_EXCEPTIONS RetryingTransactionHelper}.
|
|
||||||
*
|
*
|
||||||
* @param value the entity value, which may be valid or invalid (<tt>null</tt> allowed)
|
* @param value
|
||||||
|
* the entity value, which may be valid or invalid (<tt>null</tt> allowed)
|
||||||
* @return Returns the row deletion count
|
* @return Returns the row deletion count
|
||||||
*/
|
*/
|
||||||
public int deleteByValue(V value)
|
public int deleteByValue(V value)
|
||||||
@@ -735,7 +754,8 @@ public class EntityLookupCache<K extends Serializable, V extends Object, VK exte
|
|||||||
/**
|
/**
|
||||||
* Cache-only operation: Remove all cache values associated with the given key.
|
* Cache-only operation: Remove all cache values associated with the given key.
|
||||||
*
|
*
|
||||||
* @param removeKey <tt>true</tt> to remove the given key's entry
|
* @param removeKey
|
||||||
|
* <tt>true</tt> to remove the given key's entry
|
||||||
*/
|
*/
|
||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings("unchecked")
|
||||||
private void removeByKey(K key, boolean removeKey)
|
private void removeByKey(K key, boolean removeKey)
|
||||||
@@ -761,7 +781,8 @@ public class EntityLookupCache<K extends Serializable, V extends Object, VK exte
|
|||||||
/**
|
/**
|
||||||
* Cache-only operation: Remove all cache values associated with the given value
|
* Cache-only operation: Remove all cache values associated with the given value
|
||||||
*
|
*
|
||||||
* @param value The entity value (<tt>null</tt> is allowed)
|
* @param value
|
||||||
|
* The entity value (<tt>null</tt> is allowed)
|
||||||
*/
|
*/
|
||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings("unchecked")
|
||||||
public void removeByValue(V value)
|
public void removeByValue(V value)
|
||||||
|
@@ -33,6 +33,9 @@ import java.util.concurrent.locks.ReentrantReadWriteLock;
|
|||||||
import java.util.concurrent.locks.ReentrantReadWriteLock.ReadLock;
|
import java.util.concurrent.locks.ReentrantReadWriteLock.ReadLock;
|
||||||
import java.util.concurrent.locks.ReentrantReadWriteLock.WriteLock;
|
import java.util.concurrent.locks.ReentrantReadWriteLock.WriteLock;
|
||||||
|
|
||||||
|
import org.apache.commons.logging.Log;
|
||||||
|
import org.apache.commons.logging.LogFactory;
|
||||||
|
|
||||||
import org.alfresco.error.AlfrescoRuntimeException;
|
import org.alfresco.error.AlfrescoRuntimeException;
|
||||||
import org.alfresco.repo.cache.SimpleCache;
|
import org.alfresco.repo.cache.SimpleCache;
|
||||||
import org.alfresco.service.cmr.repository.ContentIOException;
|
import org.alfresco.service.cmr.repository.ContentIOException;
|
||||||
@@ -40,12 +43,9 @@ import org.alfresco.service.cmr.repository.ContentReader;
|
|||||||
import org.alfresco.service.cmr.repository.ContentWriter;
|
import org.alfresco.service.cmr.repository.ContentWriter;
|
||||||
import org.alfresco.util.GUID;
|
import org.alfresco.util.GUID;
|
||||||
import org.alfresco.util.Pair;
|
import org.alfresco.util.Pair;
|
||||||
import org.apache.commons.logging.Log;
|
|
||||||
import org.apache.commons.logging.LogFactory;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A store providing support for content store implementations that provide
|
* A store providing support for content store implementations that provide routing of content read and write requests based on context.
|
||||||
* routing of content read and write requests based on context.
|
|
||||||
*
|
*
|
||||||
* @see ContentContext
|
* @see ContentContext
|
||||||
*
|
*
|
||||||
@@ -69,7 +69,8 @@ public abstract class AbstractRoutingContentStore implements ContentStore
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param storesCache cache of stores used to access URLs
|
* @param storesCache
|
||||||
|
* cache of stores used to access URLs
|
||||||
*/
|
*/
|
||||||
public void setStoresCache(SimpleCache<Pair<String, String>, ContentStore> storesCache)
|
public void setStoresCache(SimpleCache<Pair<String, String>, ContentStore> storesCache)
|
||||||
{
|
{
|
||||||
@@ -82,21 +83,19 @@ public abstract class AbstractRoutingContentStore implements ContentStore
|
|||||||
protected abstract List<ContentStore> getAllStores();
|
protected abstract List<ContentStore> getAllStores();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get a content store based on the context provided. The applicability of the
|
* Get a content store based on the context provided. The applicability of the context and even the types of context allowed are up to the implementation, but normally there should be a fallback case for when the parameters are not adequate to make a decision.
|
||||||
* context and even the types of context allowed are up to the implementation, but
|
|
||||||
* normally there should be a fallback case for when the parameters are not adequate
|
|
||||||
* to make a decision.
|
|
||||||
*
|
*
|
||||||
* @param ctx the context to use to make the choice
|
* @param ctx
|
||||||
* @return Returns the store most appropriate for the given context and
|
* the context to use to make the choice
|
||||||
* <b>never <tt>null</tt></b>
|
* @return Returns the store most appropriate for the given context and <b>never <tt>null</tt></b>
|
||||||
*/
|
*/
|
||||||
protected abstract ContentStore selectWriteStore(ContentContext ctx);
|
protected abstract ContentStore selectWriteStore(ContentContext ctx);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Checks the cache for the store and ensures that the URL is in the store.
|
* Checks the cache for the store and ensures that the URL is in the store.
|
||||||
*
|
*
|
||||||
* @param contentUrl the content URL to search for
|
* @param contentUrl
|
||||||
|
* the content URL to search for
|
||||||
* @return Returns the store matching the content URL
|
* @return Returns the store matching the content URL
|
||||||
*/
|
*/
|
||||||
private ContentStore selectReadStore(String contentUrl)
|
private ContentStore selectReadStore(String contentUrl)
|
||||||
@@ -288,8 +287,7 @@ public abstract class AbstractRoutingContentStore implements ContentStore
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return Returns a valid reader from one of the stores otherwise
|
* @return Returns a valid reader from one of the stores otherwise a {@link EmptyContentReader} is returned.
|
||||||
* a {@link EmptyContentReader} is returned.
|
|
||||||
*/
|
*/
|
||||||
public ContentReader getReader(String contentUrl) throws ContentIOException
|
public ContentReader getReader(String contentUrl) throws ContentIOException
|
||||||
{
|
{
|
||||||
@@ -335,13 +333,7 @@ public abstract class AbstractRoutingContentStore implements ContentStore
|
|||||||
{
|
{
|
||||||
throw new ContentExistsException(this, contentUrl);
|
throw new ContentExistsException(this, contentUrl);
|
||||||
}
|
}
|
||||||
/*
|
/* We could go further and check each store for the existence of the URL, but that would be overkill. The main problem we need to prevent is the simultaneous access of the same store. The router represents a single store and therefore if the URL is present in any of the stores, it is effectively present in all of them. */
|
||||||
* We could go further and check each store for the existence of the URL,
|
|
||||||
* but that would be overkill. The main problem we need to prevent is
|
|
||||||
* the simultaneous access of the same store. The router represents
|
|
||||||
* a single store and therefore if the URL is present in any of the stores,
|
|
||||||
* it is effectively present in all of them.
|
|
||||||
*/
|
|
||||||
}
|
}
|
||||||
finally
|
finally
|
||||||
{
|
{
|
||||||
@@ -396,8 +388,7 @@ public abstract class AbstractRoutingContentStore implements ContentStore
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This operation has to be performed on all the stores in order to maintain the
|
* This operation has to be performed on all the stores in order to maintain the {@link ContentStore#exists(String)} contract.
|
||||||
* {@link ContentStore#exists(String)} contract.
|
|
||||||
*/
|
*/
|
||||||
public boolean delete(String contentUrl) throws ContentIOException
|
public boolean delete(String contentUrl) throws ContentIOException
|
||||||
{
|
{
|
||||||
@@ -470,7 +461,7 @@ public abstract class AbstractRoutingContentStore implements ContentStore
|
|||||||
}
|
}
|
||||||
final String message = "Restoring content from archive: ";
|
final String message = "Restoring content from archive: ";
|
||||||
logExecution(contentUrl, contentStore, message);
|
logExecution(contentUrl, contentStore, message);
|
||||||
return ContentStore.super.requestRestoreContentFromArchive(contentUrl, restoreParams);
|
return contentStore.requestRestoreContentFromArchive(contentUrl, restoreParams);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void logExecution(final String contentUrl, final ContentStore contentStore, final String message)
|
private void logExecution(final String contentUrl, final ContentStore contentStore, final String message)
|
||||||
|
@@ -31,6 +31,11 @@ import java.util.List;
|
|||||||
import java.util.Locale;
|
import java.util.Locale;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
|
||||||
|
import org.apache.commons.logging.Log;
|
||||||
|
import org.apache.commons.logging.LogFactory;
|
||||||
|
import org.springframework.dao.ConcurrencyFailureException;
|
||||||
|
import org.springframework.dao.DataIntegrityViolationException;
|
||||||
|
|
||||||
import org.alfresco.repo.cache.SimpleCache;
|
import org.alfresco.repo.cache.SimpleCache;
|
||||||
import org.alfresco.repo.cache.lookup.EntityLookupCache;
|
import org.alfresco.repo.cache.lookup.EntityLookupCache;
|
||||||
import org.alfresco.repo.cache.lookup.EntityLookupCache.EntityLookupCallbackDAOAdaptor;
|
import org.alfresco.repo.cache.lookup.EntityLookupCache.EntityLookupCallbackDAOAdaptor;
|
||||||
@@ -45,19 +50,13 @@ import org.alfresco.service.cmr.repository.ContentData;
|
|||||||
import org.alfresco.util.EqualsHelper;
|
import org.alfresco.util.EqualsHelper;
|
||||||
import org.alfresco.util.Pair;
|
import org.alfresco.util.Pair;
|
||||||
import org.alfresco.util.transaction.TransactionListenerAdapter;
|
import org.alfresco.util.transaction.TransactionListenerAdapter;
|
||||||
import org.apache.commons.logging.Log;
|
|
||||||
import org.apache.commons.logging.LogFactory;
|
|
||||||
import org.springframework.dao.ConcurrencyFailureException;
|
|
||||||
import org.springframework.dao.DataIntegrityViolationException;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Abstract implementation for ContentData DAO.
|
* Abstract implementation for ContentData DAO.
|
||||||
* <p>
|
* <p>
|
||||||
* This provides basic services such as caching, but defers to the underlying implementation
|
* This provides basic services such as caching, but defers to the underlying implementation for CRUD operations.
|
||||||
* for CRUD operations.
|
|
||||||
* <p>
|
* <p>
|
||||||
* The DAO deals in {@link ContentData} instances. The cache is primarily present to decode
|
* The DAO deals in {@link ContentData} instances. The cache is primarily present to decode IDs into <code>ContentData</code> instances.
|
||||||
* IDs into <code>ContentData</code> instances.
|
|
||||||
*
|
*
|
||||||
* @author Derek Hulley
|
* @author Derek Hulley
|
||||||
* @author sglover
|
* @author sglover
|
||||||
@@ -127,7 +126,8 @@ public abstract class AbstractContentDataDAOImpl implements ContentDataDAO
|
|||||||
/**
|
/**
|
||||||
* Set this property to enable eager cleanup of orphaned content.
|
* Set this property to enable eager cleanup of orphaned content.
|
||||||
*
|
*
|
||||||
* @param contentStoreCleaner an eager cleaner (may be <tt>null</tt>)
|
* @param contentStoreCleaner
|
||||||
|
* an eager cleaner (may be <tt>null</tt>)
|
||||||
*/
|
*/
|
||||||
public void setContentStoreCleaner(EagerContentStoreCleaner contentStoreCleaner)
|
public void setContentStoreCleaner(EagerContentStoreCleaner contentStoreCleaner)
|
||||||
{
|
{
|
||||||
@@ -135,7 +135,8 @@ public abstract class AbstractContentDataDAOImpl implements ContentDataDAO
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param contentDataCache the cache of IDs to ContentData and vice versa
|
* @param contentDataCache
|
||||||
|
* the cache of IDs to ContentData and vice versa
|
||||||
*/
|
*/
|
||||||
public void setContentDataCache(SimpleCache<Long, ContentData> contentDataCache)
|
public void setContentDataCache(SimpleCache<Long, ContentData> contentDataCache)
|
||||||
{
|
{
|
||||||
@@ -154,8 +155,7 @@ public abstract class AbstractContentDataDAOImpl implements ContentDataDAO
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A <b>content_url</b> entity was dereferenced. This makes no assumptions about the
|
* A <b>content_url</b> entity was dereferenced. This makes no assumptions about the current references - dereference deletion is handled in the commit phase.
|
||||||
* current references - dereference deletion is handled in the commit phase.
|
|
||||||
*/
|
*/
|
||||||
protected void registerDereferencedContentUrl(String contentUrl)
|
protected void registerDereferencedContentUrl(String contentUrl)
|
||||||
{
|
{
|
||||||
@@ -470,7 +470,15 @@ public abstract class AbstractContentDataDAOImpl implements ContentDataDAO
|
|||||||
ContentUrlEntity contentUrlEntity = new ContentUrlEntity();
|
ContentUrlEntity contentUrlEntity = new ContentUrlEntity();
|
||||||
contentUrlEntity.setContentUrl(contentUrl);
|
contentUrlEntity.setContentUrl(contentUrl);
|
||||||
contentUrlEntity.setSize(size);
|
contentUrlEntity.setSize(size);
|
||||||
Pair<Long, ContentUrlEntity> pair = contentUrlCache.createOrGetByValue(contentUrlEntity, controlDAO);
|
|
||||||
|
// Attempt to get the data from cache
|
||||||
|
Pair<Long, ContentUrlEntity> pair = contentUrlCache.getCachedEntityByValue(contentUrlEntity);
|
||||||
|
|
||||||
|
if (pair == null)
|
||||||
|
{
|
||||||
|
pair = contentUrlCache.createOrGetByValue(contentUrlEntity, controlDAO);
|
||||||
|
}
|
||||||
|
|
||||||
contentUrlId = pair.getFirst();
|
contentUrlId = pair.getFirst();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -638,32 +646,36 @@ public abstract class AbstractContentDataDAOImpl implements ContentDataDAO
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param contentUrl the content URL to create or search for
|
* @param contentUrl
|
||||||
|
* the content URL to create or search for
|
||||||
*/
|
*/
|
||||||
protected abstract ContentUrlEntity createContentUrlEntity(String contentUrl, long size, ContentUrlKeyEntity contentUrlKey);
|
protected abstract ContentUrlEntity createContentUrlEntity(String contentUrl, long size, ContentUrlKeyEntity contentUrlKey);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param id the ID of the <b>content url</b> entity
|
* @param id
|
||||||
|
* the ID of the <b>content url</b> entity
|
||||||
* @return Return the entity or <tt>null</tt> if it doesn't exist
|
* @return Return the entity or <tt>null</tt> if it doesn't exist
|
||||||
*/
|
*/
|
||||||
protected abstract ContentUrlEntity getContentUrlEntity(Long id);
|
protected abstract ContentUrlEntity getContentUrlEntity(Long id);
|
||||||
|
|
||||||
protected abstract ContentUrlEntity getContentUrlEntity(String contentUrl);
|
protected abstract ContentUrlEntity getContentUrlEntity(String contentUrl);
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param contentUrl the URL of the <b>content url</b> entity
|
* @param contentUrl
|
||||||
* @return Return the entity or <tt>null</tt> if it doesn't exist or is still
|
* the URL of the <b>content url</b> entity
|
||||||
* referenced by a <b>content_data</b> entity
|
* @return Return the entity or <tt>null</tt> if it doesn't exist or is still referenced by a <b>content_data</b> entity
|
||||||
*/
|
*/
|
||||||
protected abstract ContentUrlEntity getContentUrlEntityUnreferenced(String contentUrl);
|
protected abstract ContentUrlEntity getContentUrlEntityUnreferenced(String contentUrl);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Update a content URL with the given orphan time
|
* Update a content URL with the given orphan time
|
||||||
*
|
*
|
||||||
* @param id the unique ID of the entity
|
* @param id
|
||||||
* @param orphanTime the time (ms since epoch) that the entity was orphaned
|
* the unique ID of the entity
|
||||||
* @param oldOrphanTime the orphan time we expect to update for optimistic locking (may be <tt>null</tt>)
|
* @param orphanTime
|
||||||
|
* the time (ms since epoch) that the entity was orphaned
|
||||||
|
* @param oldOrphanTime
|
||||||
|
* the orphan time we expect to update for optimistic locking (may be <tt>null</tt>)
|
||||||
* @return Returns the number of rows updated
|
* @return Returns the number of rows updated
|
||||||
*/
|
*/
|
||||||
protected abstract int updateContentUrlOrphanTime(Long id, Long orphanTime, Long oldOrphanTime);
|
protected abstract int updateContentUrlOrphanTime(Long id, Long orphanTime, Long oldOrphanTime);
|
||||||
@@ -678,13 +690,15 @@ public abstract class AbstractContentDataDAOImpl implements ContentDataDAO
|
|||||||
Long localeId);
|
Long localeId);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param id the entity ID
|
* @param id
|
||||||
|
* the entity ID
|
||||||
* @return Returns the entity or <tt>null</tt> if it doesn't exist
|
* @return Returns the entity or <tt>null</tt> if it doesn't exist
|
||||||
*/
|
*/
|
||||||
protected abstract ContentDataEntity getContentDataEntity(Long id);
|
protected abstract ContentDataEntity getContentDataEntity(Long id);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param nodeIds the node ID
|
* @param nodeIds
|
||||||
|
* the node ID
|
||||||
* @return Returns the associated entities or <tt>null</tt> if none exist
|
* @return Returns the associated entities or <tt>null</tt> if none exist
|
||||||
*/
|
*/
|
||||||
protected abstract List<ContentDataEntity> getContentDataEntitiesForNodes(Set<Long> nodeIds);
|
protected abstract List<ContentDataEntity> getContentDataEntitiesForNodes(Set<Long> nodeIds);
|
||||||
@@ -692,7 +706,8 @@ public abstract class AbstractContentDataDAOImpl implements ContentDataDAO
|
|||||||
/**
|
/**
|
||||||
* Update an existing <b>alf_content_data</b> entity
|
* Update an existing <b>alf_content_data</b> entity
|
||||||
*
|
*
|
||||||
* @param entity the existing entity that will be updated
|
* @param entity
|
||||||
|
* the existing entity that will be updated
|
||||||
* @return Returns the number of rows updated (should be 1)
|
* @return Returns the number of rows updated (should be 1)
|
||||||
*/
|
*/
|
||||||
protected abstract int updateContentDataEntity(ContentDataEntity entity);
|
protected abstract int updateContentDataEntity(ContentDataEntity entity);
|
||||||
@@ -705,6 +720,7 @@ public abstract class AbstractContentDataDAOImpl implements ContentDataDAO
|
|||||||
protected abstract int deleteContentDataEntity(Long id);
|
protected abstract int deleteContentDataEntity(Long id);
|
||||||
|
|
||||||
protected abstract int deleteContentUrlEntity(long id);
|
protected abstract int deleteContentUrlEntity(long id);
|
||||||
|
|
||||||
protected abstract int updateContentUrlEntity(ContentUrlEntity existing, ContentUrlEntity entity);
|
protected abstract int updateContentUrlEntity(ContentUrlEntity existing, ContentUrlEntity entity);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@@ -2,7 +2,7 @@
|
|||||||
* #%L
|
* #%L
|
||||||
* Alfresco Repository
|
* Alfresco Repository
|
||||||
* %%
|
* %%
|
||||||
* Copyright (C) 2005 - 2023 Alfresco Software Limited
|
* Copyright (C) 2005 - 2025 Alfresco Software Limited
|
||||||
* %%
|
* %%
|
||||||
* This file is part of the Alfresco software.
|
* This file is part of the Alfresco software.
|
||||||
* If the software was purchased under a paid Alfresco license, the terms of
|
* If the software was purchased under a paid Alfresco license, the terms of
|
||||||
@@ -40,6 +40,9 @@ import java.util.Objects;
|
|||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
|
||||||
import com.google.common.collect.Sets;
|
import com.google.common.collect.Sets;
|
||||||
|
import org.apache.commons.logging.Log;
|
||||||
|
import org.apache.commons.logging.LogFactory;
|
||||||
|
import org.springframework.beans.factory.InitializingBean;
|
||||||
|
|
||||||
import org.alfresco.model.ContentModel;
|
import org.alfresco.model.ContentModel;
|
||||||
import org.alfresco.repo.event.v1.model.ContentInfo;
|
import org.alfresco.repo.event.v1.model.ContentInfo;
|
||||||
@@ -48,6 +51,7 @@ import org.alfresco.repo.event.v1.model.UserInfo;
|
|||||||
import org.alfresco.repo.event2.filter.EventFilterRegistry;
|
import org.alfresco.repo.event2.filter.EventFilterRegistry;
|
||||||
import org.alfresco.repo.event2.filter.NodeAspectFilter;
|
import org.alfresco.repo.event2.filter.NodeAspectFilter;
|
||||||
import org.alfresco.repo.event2.filter.NodePropertyFilter;
|
import org.alfresco.repo.event2.filter.NodePropertyFilter;
|
||||||
|
import org.alfresco.repo.event2.mapper.PropertyMapper;
|
||||||
import org.alfresco.repo.node.MLPropertyInterceptor;
|
import org.alfresco.repo.node.MLPropertyInterceptor;
|
||||||
import org.alfresco.repo.security.authentication.AuthenticationUtil;
|
import org.alfresco.repo.security.authentication.AuthenticationUtil;
|
||||||
import org.alfresco.repo.security.permissions.AccessDeniedException;
|
import org.alfresco.repo.security.permissions.AccessDeniedException;
|
||||||
@@ -66,9 +70,6 @@ import org.alfresco.service.namespace.NamespaceService;
|
|||||||
import org.alfresco.service.namespace.QName;
|
import org.alfresco.service.namespace.QName;
|
||||||
import org.alfresco.util.PathUtil;
|
import org.alfresco.util.PathUtil;
|
||||||
import org.alfresco.util.PropertyCheck;
|
import org.alfresco.util.PropertyCheck;
|
||||||
import org.apache.commons.logging.Log;
|
|
||||||
import org.apache.commons.logging.LogFactory;
|
|
||||||
import org.springframework.beans.factory.InitializingBean;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Helper for {@link NodeResource} objects.
|
* Helper for {@link NodeResource} objects.
|
||||||
@@ -85,6 +86,7 @@ public class NodeResourceHelper implements InitializingBean
|
|||||||
protected EventFilterRegistry eventFilterRegistry;
|
protected EventFilterRegistry eventFilterRegistry;
|
||||||
protected NamespaceService namespaceService;
|
protected NamespaceService namespaceService;
|
||||||
protected PermissionService permissionService;
|
protected PermissionService permissionService;
|
||||||
|
protected PropertyMapper propertyMapper;
|
||||||
|
|
||||||
private NodeAspectFilter nodeAspectFilter;
|
private NodeAspectFilter nodeAspectFilter;
|
||||||
private NodePropertyFilter nodePropertyFilter;
|
private NodePropertyFilter nodePropertyFilter;
|
||||||
@@ -98,6 +100,7 @@ public class NodeResourceHelper implements InitializingBean
|
|||||||
PropertyCheck.mandatory(this, "eventFilterRegistry", eventFilterRegistry);
|
PropertyCheck.mandatory(this, "eventFilterRegistry", eventFilterRegistry);
|
||||||
PropertyCheck.mandatory(this, "namespaceService", namespaceService);
|
PropertyCheck.mandatory(this, "namespaceService", namespaceService);
|
||||||
PropertyCheck.mandatory(this, "permissionService", permissionService);
|
PropertyCheck.mandatory(this, "permissionService", permissionService);
|
||||||
|
PropertyCheck.mandatory(this, "propertyMapper", propertyMapper);
|
||||||
|
|
||||||
this.nodeAspectFilter = eventFilterRegistry.getNodeAspectFilter();
|
this.nodeAspectFilter = eventFilterRegistry.getNodeAspectFilter();
|
||||||
this.nodePropertyFilter = eventFilterRegistry.getNodePropertyFilter();
|
this.nodePropertyFilter = eventFilterRegistry.getNodePropertyFilter();
|
||||||
@@ -135,6 +138,11 @@ public class NodeResourceHelper implements InitializingBean
|
|||||||
this.namespaceService = namespaceService;
|
this.namespaceService = namespaceService;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void setPropertyMapper(PropertyMapper propertyMapper)
|
||||||
|
{
|
||||||
|
this.propertyMapper = propertyMapper;
|
||||||
|
}
|
||||||
|
|
||||||
public NodeResource.Builder createNodeResourceBuilder(NodeRef nodeRef)
|
public NodeResource.Builder createNodeResourceBuilder(NodeRef nodeRef)
|
||||||
{
|
{
|
||||||
final QName type = nodeService.getType(nodeRef);
|
final QName type = nodeService.getType(nodeRef);
|
||||||
@@ -177,7 +185,8 @@ public class NodeResourceHelper implements InitializingBean
|
|||||||
{
|
{
|
||||||
result = primaryParent.getQName().getPrefixedQName(namespaceService).getPrefixString();
|
result = primaryParent.getQName().getPrefixedQName(namespaceService).getPrefixString();
|
||||||
}
|
}
|
||||||
} catch (NamespaceException namespaceException)
|
}
|
||||||
|
catch (NamespaceException namespaceException)
|
||||||
{
|
{
|
||||||
LOGGER.error("Cannot return a valid primary association QName: " + namespaceException.getMessage());
|
LOGGER.error("Cannot return a valid primary association QName: " + namespaceException.getMessage());
|
||||||
}
|
}
|
||||||
@@ -211,8 +220,8 @@ public class NodeResourceHelper implements InitializingBean
|
|||||||
{
|
{
|
||||||
v = ((MLText) v).getDefaultValue();
|
v = ((MLText) v).getDefaultValue();
|
||||||
}
|
}
|
||||||
|
Serializable mappedValue = propertyMapper.map(k, v);
|
||||||
filteredProps.put(getQNamePrefixString(k), v);
|
filteredProps.put(getQNamePrefixString(k), mappedValue);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -228,7 +237,10 @@ public class NodeResourceHelper implements InitializingBean
|
|||||||
{
|
{
|
||||||
final MLText mlTextValue = (MLText) v;
|
final MLText mlTextValue = (MLText) v;
|
||||||
final HashMap<String, String> localizedValues = new HashMap<>(mlTextValue.size());
|
final HashMap<String, String> localizedValues = new HashMap<>(mlTextValue.size());
|
||||||
mlTextValue.forEach((locale, text) -> localizedValues.put(locale.toString(), text));
|
mlTextValue.forEach((locale, text) -> {
|
||||||
|
Serializable mappedValue = propertyMapper.map(k, text);
|
||||||
|
localizedValues.put(locale.toString(), (String) mappedValue);
|
||||||
|
});
|
||||||
filteredProps.put(getQNamePrefixString(k), localizedValues);
|
filteredProps.put(getQNamePrefixString(k), localizedValues);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@@ -302,10 +314,10 @@ public class NodeResourceHelper implements InitializingBean
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the QName in the format prefix:local, but in the exceptional case where there is no registered prefix
|
* Returns the QName in the format prefix:local, but in the exceptional case where there is no registered prefix returns it in the form {uri}local.
|
||||||
* returns it in the form {uri}local.
|
|
||||||
*
|
*
|
||||||
* @param k QName
|
* @param k
|
||||||
|
* QName
|
||||||
* @return a String representing the QName in the format prefix:local or {uri}local.
|
* @return a String representing the QName in the format prefix:local or {uri}local.
|
||||||
*/
|
*/
|
||||||
public String getQNamePrefixString(QName k)
|
public String getQNamePrefixString(QName k)
|
||||||
@@ -354,7 +366,8 @@ public class NodeResourceHelper implements InitializingBean
|
|||||||
try
|
try
|
||||||
{
|
{
|
||||||
return nodeService.getProperties(nodeRef);
|
return nodeService.getProperties(nodeRef);
|
||||||
} finally
|
}
|
||||||
|
finally
|
||||||
{
|
{
|
||||||
MLPropertyInterceptor.setMLAware(toRestore);
|
MLPropertyInterceptor.setMLAware(toRestore);
|
||||||
}
|
}
|
||||||
|
@@ -2,7 +2,7 @@
|
|||||||
* #%L
|
* #%L
|
||||||
* Alfresco Repository
|
* Alfresco Repository
|
||||||
* %%
|
* %%
|
||||||
* Copyright (C) 2005 - 2022 Alfresco Software Limited
|
* Copyright (C) 2005 - 2025 Alfresco Software Limited
|
||||||
* %%
|
* %%
|
||||||
* This file is part of the Alfresco software.
|
* This file is part of the Alfresco software.
|
||||||
* If the software was purchased under a paid Alfresco license, the terms of
|
* If the software was purchased under a paid Alfresco license, the terms of
|
||||||
@@ -26,160 +26,50 @@
|
|||||||
package org.alfresco.repo.event2.filter;
|
package org.alfresco.repo.event2.filter;
|
||||||
|
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
import java.util.Collections;
|
|
||||||
import java.util.HashSet;
|
|
||||||
import java.util.LinkedList;
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
import java.util.StringTokenizer;
|
|
||||||
|
|
||||||
import org.alfresco.service.cmr.dictionary.DictionaryService;
|
import org.alfresco.repo.event2.shared.CSVStringToListParser;
|
||||||
import org.alfresco.service.namespace.NamespaceException;
|
import org.alfresco.repo.event2.shared.QNameMatcher;
|
||||||
import org.alfresco.service.namespace.NamespaceService;
|
import org.alfresco.repo.event2.shared.TypeDefExpander;
|
||||||
import org.alfresco.service.namespace.QName;
|
import org.alfresco.service.namespace.QName;
|
||||||
import org.slf4j.Logger;
|
|
||||||
import org.slf4j.LoggerFactory;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Abstract {@link EventFilter} implementation, containing common event filtering
|
* Abstract {@link EventFilter} implementation, containing common event filtering functionality for the {@link QName} type.
|
||||||
* functionality for the {@link QName} type.
|
|
||||||
*
|
*
|
||||||
* @author Jamal Kaabi-Mofrad
|
* @author Jamal Kaabi-Mofrad
|
||||||
*/
|
*/
|
||||||
public abstract class AbstractNodeEventFilter implements EventFilter<QName>
|
public abstract class AbstractNodeEventFilter implements EventFilter<QName>
|
||||||
{
|
{
|
||||||
private static final Logger LOGGER = LoggerFactory.getLogger(AbstractNodeEventFilter.class);
|
protected TypeDefExpander typeDefExpander;
|
||||||
|
|
||||||
private static final String MARKER_INCLUDE_SUBTYPES = "include_subtypes";
|
private QNameMatcher qNameMatcher;
|
||||||
private static final String WILDCARD = "*";
|
|
||||||
|
|
||||||
protected DictionaryService dictionaryService;
|
|
||||||
protected NamespaceService namespaceService;
|
|
||||||
|
|
||||||
private Set<QName> excludedTypes;
|
|
||||||
private Set<String> excludedNamespaceURI;
|
|
||||||
|
|
||||||
public AbstractNodeEventFilter()
|
|
||||||
{
|
|
||||||
this.excludedTypes = new HashSet<>();
|
|
||||||
this.excludedNamespaceURI = new HashSet<>();
|
|
||||||
}
|
|
||||||
|
|
||||||
public final void init()
|
public final void init()
|
||||||
{
|
{
|
||||||
preprocessExcludedTypes(getExcludedTypes());
|
qNameMatcher = new QNameMatcher(getExcludedTypes());
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setDictionaryService(DictionaryService dictionaryService)
|
public void setTypeDefExpander(TypeDefExpander typeDefExpander)
|
||||||
{
|
{
|
||||||
this.dictionaryService = dictionaryService;
|
this.typeDefExpander = typeDefExpander;
|
||||||
}
|
|
||||||
|
|
||||||
public void setNamespaceService(NamespaceService namespaceService)
|
|
||||||
{
|
|
||||||
this.namespaceService = namespaceService;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean isExcluded(QName qName)
|
public boolean isExcluded(QName qName)
|
||||||
{
|
{
|
||||||
if (qName != null)
|
return qNameMatcher.isMatching(qName);
|
||||||
{
|
|
||||||
return excludedTypes.contains(qName) || excludedNamespaceURI.contains(qName.getNamespaceURI());
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
protected abstract Set<QName> getExcludedTypes();
|
protected abstract Set<QName> getExcludedTypes();
|
||||||
|
|
||||||
protected List<String> parseFilterList(String unparsedFilterList)
|
protected List<String> parseFilterList(String unparsedFilterList)
|
||||||
{
|
{
|
||||||
List<String> list = new LinkedList<>();
|
return CSVStringToListParser.parse(unparsedFilterList);
|
||||||
|
|
||||||
StringTokenizer st = new StringTokenizer(unparsedFilterList, ",");
|
|
||||||
while (st.hasMoreTokens())
|
|
||||||
{
|
|
||||||
String entry = st.nextToken().trim();
|
|
||||||
if (!entry.isEmpty())
|
|
||||||
{
|
|
||||||
if (!entry.equals("none") && !entry.contains("${"))
|
|
||||||
{
|
|
||||||
list.add(entry);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return list;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Processes the user-defined list of types into valid QNames. It
|
|
||||||
* validates them against the dictionary and also supports wildcards
|
|
||||||
*/
|
|
||||||
private void preprocessExcludedTypes(Set<QName> excluded)
|
|
||||||
{
|
|
||||||
excluded.forEach(qName -> {
|
|
||||||
if (WILDCARD.equals(qName.getLocalName()))
|
|
||||||
{
|
|
||||||
//excludedPrefixes.add(getPrefix(qName));
|
|
||||||
excludedNamespaceURI.add(qName.getNamespaceURI());
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
excludedTypes.add(qName);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
if (LOGGER.isDebugEnabled())
|
|
||||||
{
|
|
||||||
LOGGER.debug("Excluded namespace URIs:" + excludedNamespaceURI);
|
|
||||||
LOGGER.debug("Excluded types:" + excludedTypes);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private QName getQName(String type)
|
|
||||||
{
|
|
||||||
return QName.createQName(type, namespaceService);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
protected Collection<QName> expandTypeDef(String typeDef)
|
protected Collection<QName> expandTypeDef(String typeDef)
|
||||||
{
|
{
|
||||||
if ((typeDef == null) || typeDef.isEmpty() || typeDef.equals("none") || typeDef.contains("${"))
|
return typeDefExpander.expand(typeDef);
|
||||||
{
|
|
||||||
return Collections.emptyList();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (typeDef.indexOf(' ') < 0)
|
|
||||||
{
|
|
||||||
return Collections.singleton(getQName(typeDef));
|
|
||||||
}
|
|
||||||
|
|
||||||
String[] typeDefParts = typeDef.split(" ");
|
|
||||||
if (typeDefParts.length != 2)
|
|
||||||
{
|
|
||||||
LOGGER.warn("Ignoring invalid blacklist type pattern: " + typeDef);
|
|
||||||
return Collections.emptyList();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (typeDefParts[1].equals(MARKER_INCLUDE_SUBTYPES))
|
|
||||||
{
|
|
||||||
if (typeDefParts[0].indexOf('*') >= 0)
|
|
||||||
{
|
|
||||||
LOGGER.warn("Ignoring invalid blacklist type pattern: " + typeDef);
|
|
||||||
return Collections.emptyList();
|
|
||||||
}
|
|
||||||
QName baseType;
|
|
||||||
try
|
|
||||||
{
|
|
||||||
baseType = getQName(typeDefParts[0]);
|
|
||||||
}
|
|
||||||
catch (NamespaceException ne)
|
|
||||||
{
|
|
||||||
return Collections.emptyList();
|
|
||||||
}
|
|
||||||
return dictionaryService.getSubTypes(baseType, true);
|
|
||||||
}
|
|
||||||
|
|
||||||
LOGGER.warn("Ignoring invalid blacklist type pattern: " + typeDef);
|
|
||||||
return Collections.emptyList();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -2,7 +2,7 @@
|
|||||||
* #%L
|
* #%L
|
||||||
* Alfresco Repository
|
* Alfresco Repository
|
||||||
* %%
|
* %%
|
||||||
* Copyright (C) 2005 - 2020 Alfresco Software Limited
|
* Copyright (C) 2005 - 2025 Alfresco Software Limited
|
||||||
* %%
|
* %%
|
||||||
* This file is part of the Alfresco software.
|
* This file is part of the Alfresco software.
|
||||||
* If the software was purchased under a paid Alfresco license, the terms of
|
* If the software was purchased under a paid Alfresco license, the terms of
|
||||||
@@ -25,6 +25,7 @@
|
|||||||
*/
|
*/
|
||||||
package org.alfresco.repo.event2.filter;
|
package org.alfresco.repo.event2.filter;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
import java.util.HashSet;
|
import java.util.HashSet;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
@@ -49,18 +50,20 @@ public class NodePropertyFilter extends AbstractNodeEventFilter
|
|||||||
ContentModel.PROP_CREATED,
|
ContentModel.PROP_CREATED,
|
||||||
ContentModel.PROP_CONTENT);
|
ContentModel.PROP_CONTENT);
|
||||||
|
|
||||||
private final List<String> nodeAspectsBlackList;
|
private final List<String> nodePropertiesBlackList = new ArrayList<>();
|
||||||
|
|
||||||
public NodePropertyFilter()
|
public NodePropertyFilter(String userConfiguredProperties)
|
||||||
{
|
{
|
||||||
this.nodeAspectsBlackList = parseFilterList(FILTERED_PROPERTIES);
|
super();
|
||||||
|
nodePropertiesBlackList.addAll(parseFilterList(FILTERED_PROPERTIES));
|
||||||
|
nodePropertiesBlackList.addAll(parseFilterList(userConfiguredProperties));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Set<QName> getExcludedTypes()
|
public Set<QName> getExcludedTypes()
|
||||||
{
|
{
|
||||||
Set<QName> result = new HashSet<>(EXCLUDED_TOP_LEVEL_PROPS);
|
Set<QName> result = new HashSet<>(EXCLUDED_TOP_LEVEL_PROPS);
|
||||||
nodeAspectsBlackList.forEach(nodeAspect -> result.addAll(expandTypeDef(nodeAspect)));
|
nodePropertiesBlackList.forEach(nodeProperty -> result.addAll(expandTypeDef(nodeProperty)));
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -2,7 +2,7 @@
|
|||||||
* #%L
|
* #%L
|
||||||
* Alfresco Repository
|
* Alfresco Repository
|
||||||
* %%
|
* %%
|
||||||
* Copyright (C) 2005 - 2020 Alfresco Software Limited
|
* Copyright (C) 2005 - 2025 Alfresco Software Limited
|
||||||
* %%
|
* %%
|
||||||
* This file is part of the Alfresco software.
|
* This file is part of the Alfresco software.
|
||||||
* If the software was purchased under a paid Alfresco license, the terms of
|
* If the software was purchased under a paid Alfresco license, the terms of
|
||||||
@@ -31,6 +31,7 @@ import java.util.List;
|
|||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
|
||||||
import org.alfresco.model.ContentModel;
|
import org.alfresco.model.ContentModel;
|
||||||
|
import org.alfresco.service.cmr.dictionary.DictionaryService;
|
||||||
import org.alfresco.service.namespace.QName;
|
import org.alfresco.service.namespace.QName;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -41,10 +42,13 @@ import org.alfresco.service.namespace.QName;
|
|||||||
public class NodeTypeFilter extends AbstractNodeEventFilter
|
public class NodeTypeFilter extends AbstractNodeEventFilter
|
||||||
{
|
{
|
||||||
private final List<String> nodeTypesBlackList;
|
private final List<String> nodeTypesBlackList;
|
||||||
|
private final DictionaryService dictionaryService;
|
||||||
|
|
||||||
public NodeTypeFilter(String filteredNodeTypes)
|
public NodeTypeFilter(String filteredNodeTypes, DictionaryService dictionaryService)
|
||||||
{
|
{
|
||||||
|
super();
|
||||||
this.nodeTypesBlackList = parseFilterList(filteredNodeTypes);
|
this.nodeTypesBlackList = parseFilterList(filteredNodeTypes);
|
||||||
|
this.dictionaryService = dictionaryService;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@@ -0,0 +1,37 @@
|
|||||||
|
/*
|
||||||
|
* #%L
|
||||||
|
* Alfresco Repository
|
||||||
|
* %%
|
||||||
|
* Copyright (C) 2025 - 2025 Alfresco Software Limited
|
||||||
|
* %%
|
||||||
|
* This file is part of the Alfresco software.
|
||||||
|
* If the software was purchased under a paid Alfresco license, the terms of
|
||||||
|
* the paid license agreement will prevail. Otherwise, the software is
|
||||||
|
* provided under the following open source license terms:
|
||||||
|
*
|
||||||
|
* Alfresco is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU Lesser General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* Alfresco is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU Lesser General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Lesser General Public License
|
||||||
|
* along with Alfresco. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
* #L%
|
||||||
|
*/
|
||||||
|
package org.alfresco.repo.event2.mapper;
|
||||||
|
|
||||||
|
import java.io.Serializable;
|
||||||
|
|
||||||
|
import org.alfresco.service.namespace.QName;
|
||||||
|
|
||||||
|
public interface PropertyMapper
|
||||||
|
{
|
||||||
|
PropertyMapper NO_OP = (propertyQName, value) -> value;
|
||||||
|
|
||||||
|
Serializable map(QName propertyQName, Serializable value);
|
||||||
|
}
|
@@ -0,0 +1,58 @@
|
|||||||
|
/*
|
||||||
|
* #%L
|
||||||
|
* Alfresco Repository
|
||||||
|
* %%
|
||||||
|
* Copyright (C) 2025 - 2025 Alfresco Software Limited
|
||||||
|
* %%
|
||||||
|
* This file is part of the Alfresco software.
|
||||||
|
* If the software was purchased under a paid Alfresco license, the terms of
|
||||||
|
* the paid license agreement will prevail. Otherwise, the software is
|
||||||
|
* provided under the following open source license terms:
|
||||||
|
*
|
||||||
|
* Alfresco is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU Lesser General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* Alfresco is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU Lesser General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Lesser General Public License
|
||||||
|
* along with Alfresco. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
* #L%
|
||||||
|
*/
|
||||||
|
package org.alfresco.repo.event2.mapper;
|
||||||
|
|
||||||
|
import java.util.Optional;
|
||||||
|
import java.util.Set;
|
||||||
|
import java.util.function.Predicate;
|
||||||
|
|
||||||
|
import org.alfresco.repo.event2.shared.CSVStringToListParser;
|
||||||
|
import org.alfresco.repo.event2.shared.TypeDefExpander;
|
||||||
|
import org.alfresco.service.namespace.QName;
|
||||||
|
|
||||||
|
public class PropertyMapperFactory
|
||||||
|
{
|
||||||
|
private final TypeDefExpander typeDefExpander;
|
||||||
|
|
||||||
|
public PropertyMapperFactory(TypeDefExpander typeDefExpander)
|
||||||
|
{
|
||||||
|
this.typeDefExpander = typeDefExpander;
|
||||||
|
}
|
||||||
|
|
||||||
|
public PropertyMapper createPropertyMapper(String enabled, String userConfiguredSensitiveProperties, String userConfiguredReplacementText)
|
||||||
|
{
|
||||||
|
if ("false".equalsIgnoreCase(enabled))
|
||||||
|
{
|
||||||
|
return PropertyMapper.NO_OP;
|
||||||
|
}
|
||||||
|
Set<QName> sensitiveProperties = Optional.ofNullable(userConfiguredSensitiveProperties)
|
||||||
|
.filter(Predicate.not(String::isEmpty))
|
||||||
|
.map(CSVStringToListParser::parse)
|
||||||
|
.map(typeDefExpander::expand)
|
||||||
|
.orElse(Set.of());
|
||||||
|
return new ReplaceSensitivePropertyWithTextMapper(sensitiveProperties, userConfiguredReplacementText);
|
||||||
|
}
|
||||||
|
}
|
@@ -0,0 +1,72 @@
|
|||||||
|
/*
|
||||||
|
* #%L
|
||||||
|
* Alfresco Repository
|
||||||
|
* %%
|
||||||
|
* Copyright (C) 2025 - 2025 Alfresco Software Limited
|
||||||
|
* %%
|
||||||
|
* This file is part of the Alfresco software.
|
||||||
|
* If the software was purchased under a paid Alfresco license, the terms of
|
||||||
|
* the paid license agreement will prevail. Otherwise, the software is
|
||||||
|
* provided under the following open source license terms:
|
||||||
|
*
|
||||||
|
* Alfresco is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU Lesser General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* Alfresco is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU Lesser General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Lesser General Public License
|
||||||
|
* along with Alfresco. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
* #L%
|
||||||
|
*/
|
||||||
|
package org.alfresco.repo.event2.mapper;
|
||||||
|
|
||||||
|
import java.io.Serializable;
|
||||||
|
import java.util.Collection;
|
||||||
|
import java.util.Optional;
|
||||||
|
import java.util.Set;
|
||||||
|
import java.util.function.Predicate;
|
||||||
|
|
||||||
|
import org.alfresco.model.ContentModel;
|
||||||
|
import org.alfresco.repo.event2.shared.QNameMatcher;
|
||||||
|
import org.alfresco.repo.transfer.TransferModel;
|
||||||
|
import org.alfresco.service.namespace.QName;
|
||||||
|
|
||||||
|
public class ReplaceSensitivePropertyWithTextMapper implements PropertyMapper
|
||||||
|
{
|
||||||
|
private static final Set<QName> DEFAULT_SENSITIVE_PROPERTIES = Set.of(
|
||||||
|
ContentModel.PROP_PASSWORD,
|
||||||
|
ContentModel.PROP_SALT,
|
||||||
|
ContentModel.PROP_PASSWORD_HASH,
|
||||||
|
TransferModel.PROP_PASSWORD);
|
||||||
|
private static final String DEFAULT_REPLACEMENT_TEXT = "SENSITIVE_DATA_REMOVED";
|
||||||
|
|
||||||
|
private final QNameMatcher qNameMatcher;
|
||||||
|
private final String replacementText;
|
||||||
|
|
||||||
|
public ReplaceSensitivePropertyWithTextMapper(Set<QName> userConfiguredSensitiveProperties, String userConfiguredReplacementText)
|
||||||
|
{
|
||||||
|
Set<QName> sensitiveProperties = Optional.ofNullable(userConfiguredSensitiveProperties)
|
||||||
|
.filter(Predicate.not(Collection::isEmpty))
|
||||||
|
.orElse(DEFAULT_SENSITIVE_PROPERTIES);
|
||||||
|
qNameMatcher = new QNameMatcher(sensitiveProperties);
|
||||||
|
replacementText = Optional.ofNullable(userConfiguredReplacementText)
|
||||||
|
.filter(Predicate.not(String::isEmpty))
|
||||||
|
.filter(userInput -> !userInput.contains("${"))
|
||||||
|
.orElse(DEFAULT_REPLACEMENT_TEXT);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Serializable map(QName propertyQName, Serializable value)
|
||||||
|
{
|
||||||
|
if (qNameMatcher.isMatching(propertyQName))
|
||||||
|
{
|
||||||
|
return replacementText;
|
||||||
|
}
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
}
|
@@ -0,0 +1,52 @@
|
|||||||
|
/*
|
||||||
|
* #%L
|
||||||
|
* Alfresco Repository
|
||||||
|
* %%
|
||||||
|
* Copyright (C) 2025 - 2025 Alfresco Software Limited
|
||||||
|
* %%
|
||||||
|
* This file is part of the Alfresco software.
|
||||||
|
* If the software was purchased under a paid Alfresco license, the terms of
|
||||||
|
* the paid license agreement will prevail. Otherwise, the software is
|
||||||
|
* provided under the following open source license terms:
|
||||||
|
*
|
||||||
|
* Alfresco is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU Lesser General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* Alfresco is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU Lesser General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Lesser General Public License
|
||||||
|
* along with Alfresco. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
* #L%
|
||||||
|
*/
|
||||||
|
package org.alfresco.repo.event2.shared;
|
||||||
|
|
||||||
|
import java.util.LinkedList;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.StringTokenizer;
|
||||||
|
|
||||||
|
public final class CSVStringToListParser
|
||||||
|
{
|
||||||
|
private CSVStringToListParser()
|
||||||
|
{}
|
||||||
|
|
||||||
|
public static List<String> parse(String userInputCSV)
|
||||||
|
{
|
||||||
|
List<String> list = new LinkedList<>();
|
||||||
|
|
||||||
|
StringTokenizer st = new StringTokenizer(userInputCSV, ",");
|
||||||
|
while (st.hasMoreTokens())
|
||||||
|
{
|
||||||
|
String entry = st.nextToken().trim();
|
||||||
|
if (!entry.isEmpty() && !entry.equals("none") && !entry.contains("${"))
|
||||||
|
{
|
||||||
|
list.add(entry);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return list;
|
||||||
|
}
|
||||||
|
}
|
@@ -0,0 +1,75 @@
|
|||||||
|
/*
|
||||||
|
* #%L
|
||||||
|
* Alfresco Repository
|
||||||
|
* %%
|
||||||
|
* Copyright (C) 2025 - 2025 Alfresco Software Limited
|
||||||
|
* %%
|
||||||
|
* This file is part of the Alfresco software.
|
||||||
|
* If the software was purchased under a paid Alfresco license, the terms of
|
||||||
|
* the paid license agreement will prevail. Otherwise, the software is
|
||||||
|
* provided under the following open source license terms:
|
||||||
|
*
|
||||||
|
* Alfresco is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU Lesser General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* Alfresco is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU Lesser General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Lesser General Public License
|
||||||
|
* along with Alfresco. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
* #L%
|
||||||
|
*/
|
||||||
|
package org.alfresco.repo.event2.shared;
|
||||||
|
|
||||||
|
import java.util.HashSet;
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
|
import org.alfresco.service.namespace.QName;
|
||||||
|
|
||||||
|
public class QNameMatcher
|
||||||
|
{
|
||||||
|
private static final Logger LOGGER = LoggerFactory.getLogger(QNameMatcher.class);
|
||||||
|
private static final String WILDCARD = "*";
|
||||||
|
|
||||||
|
private final Set<QName> matchingTypes;
|
||||||
|
private final Set<String> matchingNamespaceURIs;
|
||||||
|
|
||||||
|
public QNameMatcher(Set<QName> qNamesToMatch)
|
||||||
|
{
|
||||||
|
matchingTypes = new HashSet<>();
|
||||||
|
matchingNamespaceURIs = new HashSet<>();
|
||||||
|
|
||||||
|
qNamesToMatch.forEach(qName -> {
|
||||||
|
if (WILDCARD.equals(qName.getLocalName()))
|
||||||
|
{
|
||||||
|
matchingNamespaceURIs.add(qName.getNamespaceURI());
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
matchingTypes.add(qName);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
if (LOGGER.isDebugEnabled())
|
||||||
|
{
|
||||||
|
LOGGER.debug("Matching namespace URIs:" + matchingNamespaceURIs);
|
||||||
|
LOGGER.debug("Matching types:" + matchingTypes);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isMatching(QName qName)
|
||||||
|
{
|
||||||
|
if (qName != null)
|
||||||
|
{
|
||||||
|
return matchingTypes.contains(qName) || matchingNamespaceURIs.contains(qName.getNamespaceURI());
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
@@ -0,0 +1,108 @@
|
|||||||
|
/*
|
||||||
|
* #%L
|
||||||
|
* Alfresco Repository
|
||||||
|
* %%
|
||||||
|
* Copyright (C) 2025 - 2025 Alfresco Software Limited
|
||||||
|
* %%
|
||||||
|
* This file is part of the Alfresco software.
|
||||||
|
* If the software was purchased under a paid Alfresco license, the terms of
|
||||||
|
* the paid license agreement will prevail. Otherwise, the software is
|
||||||
|
* provided under the following open source license terms:
|
||||||
|
*
|
||||||
|
* Alfresco is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU Lesser General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* Alfresco is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU Lesser General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Lesser General Public License
|
||||||
|
* along with Alfresco. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
* #L%
|
||||||
|
*/
|
||||||
|
package org.alfresco.repo.event2.shared;
|
||||||
|
|
||||||
|
import java.util.Collection;
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.HashSet;
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
|
import org.alfresco.service.cmr.dictionary.DictionaryService;
|
||||||
|
import org.alfresco.service.namespace.NamespaceException;
|
||||||
|
import org.alfresco.service.namespace.NamespaceService;
|
||||||
|
import org.alfresco.service.namespace.QName;
|
||||||
|
|
||||||
|
public class TypeDefExpander
|
||||||
|
{
|
||||||
|
private static final Logger LOGGER = LoggerFactory.getLogger(TypeDefExpander.class);
|
||||||
|
private static final String MARKER_INCLUDE_SUBTYPES = "include_subtypes";
|
||||||
|
|
||||||
|
private final DictionaryService dictionaryService;
|
||||||
|
private final NamespaceService namespaceService;
|
||||||
|
|
||||||
|
public TypeDefExpander(DictionaryService dictionaryService, NamespaceService namespaceService)
|
||||||
|
{
|
||||||
|
this.dictionaryService = dictionaryService;
|
||||||
|
this.namespaceService = namespaceService;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Set<QName> expand(Collection<String> types)
|
||||||
|
{
|
||||||
|
Set<QName> result = new HashSet<>();
|
||||||
|
types.forEach(type -> result.addAll(expand(type)));
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Collection<QName> expand(String typeDef)
|
||||||
|
{
|
||||||
|
if ((typeDef == null) || typeDef.isEmpty() || typeDef.equals("none") || typeDef.contains("${"))
|
||||||
|
{
|
||||||
|
return Collections.emptyList();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (typeDef.indexOf(' ') < 0)
|
||||||
|
{
|
||||||
|
return Collections.singleton(getQName(typeDef));
|
||||||
|
}
|
||||||
|
|
||||||
|
String[] typeDefParts = typeDef.split(" ");
|
||||||
|
if (typeDefParts.length != 2)
|
||||||
|
{
|
||||||
|
LOGGER.warn("Ignoring invalid type pattern: " + typeDef);
|
||||||
|
return Collections.emptyList();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (typeDefParts[1].equals(MARKER_INCLUDE_SUBTYPES))
|
||||||
|
{
|
||||||
|
if (typeDefParts[0].indexOf('*') >= 0)
|
||||||
|
{
|
||||||
|
LOGGER.warn("Ignoring invalid type pattern: " + typeDef);
|
||||||
|
return Collections.emptyList();
|
||||||
|
}
|
||||||
|
QName baseType;
|
||||||
|
try
|
||||||
|
{
|
||||||
|
baseType = getQName(typeDefParts[0]);
|
||||||
|
}
|
||||||
|
catch (NamespaceException ne)
|
||||||
|
{
|
||||||
|
return Collections.emptyList();
|
||||||
|
}
|
||||||
|
return dictionaryService.getSubTypes(baseType, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
LOGGER.warn("Ignoring invalid type pattern: " + typeDef);
|
||||||
|
return Collections.emptyList();
|
||||||
|
}
|
||||||
|
|
||||||
|
private QName getQName(String type)
|
||||||
|
{
|
||||||
|
return QName.createQName(type, namespaceService);
|
||||||
|
}
|
||||||
|
}
|
@@ -1,112 +0,0 @@
|
|||||||
/*
|
|
||||||
* #%L
|
|
||||||
* Alfresco Repository
|
|
||||||
* %%
|
|
||||||
* Copyright (C) 2024 Alfresco Software Limited
|
|
||||||
* %%
|
|
||||||
* This file is part of the Alfresco software.
|
|
||||||
* If the software was purchased under a paid Alfresco license, the terms of
|
|
||||||
* the paid license agreement will prevail. Otherwise, the software is
|
|
||||||
* provided under the following open source license terms:
|
|
||||||
*
|
|
||||||
* Alfresco is free software: you can redistribute it and/or modify
|
|
||||||
* it under the terms of the GNU Lesser General Public License as published by
|
|
||||||
* the Free Software Foundation, either version 3 of the License, or
|
|
||||||
* (at your option) any later version.
|
|
||||||
*
|
|
||||||
* Alfresco is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
* GNU Lesser General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU Lesser General Public License
|
|
||||||
* along with Alfresco. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
* #L%
|
|
||||||
*/
|
|
||||||
package org.alfresco.repo.rendition2.script;
|
|
||||||
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
import org.alfresco.repo.jscript.BaseScopableProcessorExtension;
|
|
||||||
import org.alfresco.repo.jscript.ScriptNode;
|
|
||||||
import org.alfresco.repo.rendition2.RenditionService2;
|
|
||||||
import org.alfresco.service.ServiceRegistry;
|
|
||||||
import org.alfresco.service.cmr.repository.ChildAssociationRef;
|
|
||||||
import org.apache.commons.logging.Log;
|
|
||||||
import org.apache.commons.logging.LogFactory;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The {@code ScriptRenditionService2} class provides a scripting interface for working with Rendition Service 2.
|
|
||||||
* It allows rendering source nodes with specified rendition definitions and retrieving renditions associated with a node.
|
|
||||||
*/
|
|
||||||
@SuppressWarnings({"PMD.ProperLogger", "PMD.FieldNamingConventions"})
|
|
||||||
public class ScriptRenditionService2 extends BaseScopableProcessorExtension
|
|
||||||
{
|
|
||||||
private static final Log logger = LogFactory.getLog(ScriptRenditionService2.class);
|
|
||||||
|
|
||||||
private ServiceRegistry serviceRegistry;
|
|
||||||
private RenditionService2 renditionService;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Sets the {@link ServiceRegistry} to be used by this script object.
|
|
||||||
*
|
|
||||||
* @param serviceRegistry The ServiceRegistry to be set.
|
|
||||||
*/
|
|
||||||
public void setServiceRegistry(ServiceRegistry serviceRegistry)
|
|
||||||
{
|
|
||||||
this.serviceRegistry = serviceRegistry;
|
|
||||||
this.renditionService = serviceRegistry.getRenditionService2();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Renders the specified source node with the given rendition definition.
|
|
||||||
* Since renditionService2 is designed to asynchronous, no result is returned.
|
|
||||||
*
|
|
||||||
* @param sourceNode The source node to be rendered.
|
|
||||||
* @param renditionName The name of the rendition definition, like "pdf".
|
|
||||||
*/
|
|
||||||
public void render(ScriptNode sourceNode, String renditionName)
|
|
||||||
{
|
|
||||||
if (logger.isDebugEnabled())
|
|
||||||
{
|
|
||||||
String msg = "Rendering source node '" +
|
|
||||||
sourceNode +
|
|
||||||
"' with renditionDef '" + renditionName +
|
|
||||||
"'";
|
|
||||||
logger.debug(msg);
|
|
||||||
}
|
|
||||||
this.renditionService.render(sourceNode.getNodeRef(), renditionName);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Retrieves an array of {@link ScriptNode} objects representing renditions associated with the specified node.
|
|
||||||
*
|
|
||||||
* @param node The node for which to retrieve renditions.
|
|
||||||
* @return An array of {@code ScriptNode} objects representing renditions.
|
|
||||||
*/
|
|
||||||
public ScriptNode[] getRenditions(ScriptNode node)
|
|
||||||
{
|
|
||||||
List<ChildAssociationRef> renditions = this.renditionService.getRenditions(node.getNodeRef());
|
|
||||||
|
|
||||||
ScriptNode[] renditionObjs = new ScriptNode[renditions.size()];
|
|
||||||
for (int i = 0; i < renditions.size(); i++)
|
|
||||||
{
|
|
||||||
renditionObjs[i] = new ScriptNode(renditions.get(i).getChildRef(), serviceRegistry);
|
|
||||||
}
|
|
||||||
|
|
||||||
return renditionObjs;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Retrieves a {@link ScriptNode} object representing the rendition with the specified name associated with the given node.
|
|
||||||
*
|
|
||||||
* @param node The node for which to retrieve the rendition.
|
|
||||||
* @param renditionName The name of the rendition.
|
|
||||||
* @return A {@code ScriptNode} object representing the specified rendition, or {@code null} if not found.
|
|
||||||
*/
|
|
||||||
public ScriptNode getRenditionByName(ScriptNode node, String renditionName)
|
|
||||||
{
|
|
||||||
ChildAssociationRef result = this.renditionService.getRenditionByName(node.getNodeRef(), renditionName);
|
|
||||||
return result == null ? null : new ScriptNode(result.getChildRef(), serviceRegistry);
|
|
||||||
}
|
|
||||||
}
|
|
@@ -3,23 +3,30 @@
|
|||||||
|
|
||||||
<beans>
|
<beans>
|
||||||
|
|
||||||
|
<bean id="event2TypeDefExpander" class="org.alfresco.repo.event2.shared.TypeDefExpander">
|
||||||
|
<constructor-arg ref="dictionaryService"/>
|
||||||
|
<constructor-arg ref="namespaceService"/>
|
||||||
|
</bean>
|
||||||
|
|
||||||
<!-- Event2 Filters -->
|
<!-- Event2 Filters -->
|
||||||
<bean id="event2FilterRegistry" class="org.alfresco.repo.event2.filter.EventFilterRegistry"/>
|
<bean id="event2FilterRegistry" class="org.alfresco.repo.event2.filter.EventFilterRegistry"/>
|
||||||
|
|
||||||
<bean id="abstractNodeEventFilter" class="org.alfresco.repo.event2.filter.AbstractNodeEventFilter" abstract="true" init-method="init">
|
<bean id="abstractNodeEventFilter" class="org.alfresco.repo.event2.filter.AbstractNodeEventFilter" abstract="true" init-method="init">
|
||||||
<property name="dictionaryService" ref="dictionaryService"/>
|
<property name="typeDefExpander" ref="event2TypeDefExpander"/>
|
||||||
<property name="namespaceService" ref="namespaceService"/>
|
|
||||||
</bean>
|
</bean>
|
||||||
|
|
||||||
<bean id="event2NodeTypeFilter" class="org.alfresco.repo.event2.filter.NodeTypeFilter" parent="abstractNodeEventFilter">
|
<bean id="event2NodeTypeFilter" class="org.alfresco.repo.event2.filter.NodeTypeFilter" parent="abstractNodeEventFilter">
|
||||||
<constructor-arg value="${repo.event2.filter.nodeTypes}"/>
|
<constructor-arg value="${repo.event2.filter.nodeTypes}"/>
|
||||||
|
<constructor-arg ref="dictionaryService"/>
|
||||||
</bean>
|
</bean>
|
||||||
|
|
||||||
<bean id="event2NodeAspectFilter" class="org.alfresco.repo.event2.filter.NodeAspectFilter" parent="abstractNodeEventFilter">
|
<bean id="event2NodeAspectFilter" class="org.alfresco.repo.event2.filter.NodeAspectFilter" parent="abstractNodeEventFilter">
|
||||||
<constructor-arg value="${repo.event2.filter.nodeAspects}"/>
|
<constructor-arg value="${repo.event2.filter.nodeAspects}"/>
|
||||||
</bean>
|
</bean>
|
||||||
|
|
||||||
<bean id="event2NodePropertyFilter" class="org.alfresco.repo.event2.filter.NodePropertyFilter" parent="abstractNodeEventFilter"/>
|
<bean id="event2NodePropertyFilter" class="org.alfresco.repo.event2.filter.NodePropertyFilter" parent="abstractNodeEventFilter">
|
||||||
|
<constructor-arg value="${repo.event2.filter.nodeProperties}"/>
|
||||||
|
</bean>
|
||||||
|
|
||||||
<bean id="event2UserFilter" class="org.alfresco.repo.event2.filter.EventUserFilter">
|
<bean id="event2UserFilter" class="org.alfresco.repo.event2.filter.EventUserFilter">
|
||||||
<constructor-arg value="${repo.event2.filter.users}"/>
|
<constructor-arg value="${repo.event2.filter.users}"/>
|
||||||
@@ -31,6 +38,16 @@
|
|||||||
</bean>
|
</bean>
|
||||||
<!-- End of Event2 Filters -->
|
<!-- End of Event2 Filters -->
|
||||||
|
|
||||||
|
<bean id="event2PropertyMapperFactory" class="org.alfresco.repo.event2.mapper.PropertyMapperFactory">
|
||||||
|
<constructor-arg ref="event2TypeDefExpander"/>
|
||||||
|
</bean>
|
||||||
|
|
||||||
|
<bean id="event2PropertyMapper" factory-bean="event2PropertyMapperFactory" factory-method="createPropertyMapper">
|
||||||
|
<constructor-arg value="${repo.event2.mapper.enabled}"/>
|
||||||
|
<constructor-arg value="${repo.event2.mapper.overrideDefaultProperties}"/>
|
||||||
|
<constructor-arg value="${repo.event2.mapper.overrideReplacementText}"/>
|
||||||
|
</bean>
|
||||||
|
|
||||||
<bean id="baseEventGeneratorV2" abstract="true">
|
<bean id="baseEventGeneratorV2" abstract="true">
|
||||||
<property name="policyComponent" ref="policyComponent"/>
|
<property name="policyComponent" ref="policyComponent"/>
|
||||||
<property name="nodeService" ref="nodeService"/>
|
<property name="nodeService" ref="nodeService"/>
|
||||||
@@ -55,6 +72,7 @@
|
|||||||
<property name="eventFilterRegistry" ref="event2FilterRegistry"/>
|
<property name="eventFilterRegistry" ref="event2FilterRegistry"/>
|
||||||
<property name="namespaceService" ref="namespaceService"/>
|
<property name="namespaceService" ref="namespaceService"/>
|
||||||
<property name="permissionService" ref="permissionService"/>
|
<property name="permissionService" ref="permissionService"/>
|
||||||
|
<property name="propertyMapper" ref="event2PropertyMapper"/>
|
||||||
</bean>
|
</bean>
|
||||||
|
|
||||||
<bean id="nodeResourceHelper" class="org.alfresco.repo.event2.NodeResourceHelper" parent="baseNodeResourceHelper"/>
|
<bean id="nodeResourceHelper" class="org.alfresco.repo.event2.NodeResourceHelper" parent="baseNodeResourceHelper"/>
|
||||||
|
@@ -176,11 +176,4 @@
|
|||||||
|
|
||||||
<!-- The definitions are read from json files (possibly added to a volume via k8 ConfigMaps) -->
|
<!-- The definitions are read from json files (possibly added to a volume via k8 ConfigMaps) -->
|
||||||
|
|
||||||
<!-- JavaScript API support -->
|
|
||||||
<bean id="renditionService2Script"
|
|
||||||
class="org.alfresco.repo.rendition2.script.ScriptRenditionService2"
|
|
||||||
parent="baseJavaScriptExtension">
|
|
||||||
<property name="extensionName" value="renditionService2" />
|
|
||||||
<property name="serviceRegistry" ref="ServiceRegistry" />
|
|
||||||
</bean>
|
|
||||||
</beans>
|
</beans>
|
@@ -3,7 +3,7 @@
|
|||||||
repository.name=Main Repository
|
repository.name=Main Repository
|
||||||
|
|
||||||
# Schema number
|
# Schema number
|
||||||
version.schema=18300
|
version.schema=18200
|
||||||
|
|
||||||
# Directory configuration
|
# Directory configuration
|
||||||
|
|
||||||
@@ -1227,6 +1227,10 @@ repo.event2.filter.childAssocTypes=rn:rendition
|
|||||||
# Comma separated list of users which should be excluded
|
# Comma separated list of users which should be excluded
|
||||||
# Note: username's case-sensitivity depends on the {user.name.caseSensitive} setting
|
# Note: username's case-sensitivity depends on the {user.name.caseSensitive} setting
|
||||||
repo.event2.filter.users=
|
repo.event2.filter.users=
|
||||||
|
repo.event2.filter.nodeProperties=
|
||||||
|
repo.event2.mapper.enabled=true
|
||||||
|
repo.event2.mapper.overrideDefaultProperties=
|
||||||
|
repo.event2.mapper.overrideReplacementText=
|
||||||
# Topic name
|
# Topic name
|
||||||
repo.event2.topic.endpoint=amqp:topic:alfresco.repo.event2
|
repo.event2.topic.endpoint=amqp:topic:alfresco.repo.event2
|
||||||
# Thread pool for async enqueue of repo events
|
# Thread pool for async enqueue of repo events
|
||||||
|
@@ -25,12 +25,16 @@
|
|||||||
*/
|
*/
|
||||||
package org.alfresco.repo.cache.lookup;
|
package org.alfresco.repo.cache.lookup;
|
||||||
|
|
||||||
|
import static org.junit.Assert.*;
|
||||||
|
|
||||||
import java.sql.Savepoint;
|
import java.sql.Savepoint;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.TreeMap;
|
import java.util.TreeMap;
|
||||||
|
|
||||||
import junit.framework.AssertionFailedError;
|
import org.junit.Before;
|
||||||
import junit.framework.TestCase;
|
import org.junit.Test;
|
||||||
|
import org.mockito.Mockito;
|
||||||
|
import org.springframework.dao.DuplicateKeyException;
|
||||||
|
|
||||||
import org.alfresco.repo.cache.MemoryCache;
|
import org.alfresco.repo.cache.MemoryCache;
|
||||||
import org.alfresco.repo.cache.SimpleCache;
|
import org.alfresco.repo.cache.SimpleCache;
|
||||||
@@ -38,20 +42,16 @@ import org.alfresco.repo.cache.lookup.EntityLookupCache.EntityLookupCallbackDAO;
|
|||||||
import org.alfresco.repo.domain.control.ControlDAO;
|
import org.alfresco.repo.domain.control.ControlDAO;
|
||||||
import org.alfresco.util.EqualsHelper;
|
import org.alfresco.util.EqualsHelper;
|
||||||
import org.alfresco.util.Pair;
|
import org.alfresco.util.Pair;
|
||||||
import org.mockito.Mockito;
|
|
||||||
import org.springframework.dao.DuplicateKeyException;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A cache for two-way lookups of database entities. These are characterized by having a unique
|
* A cache for two-way lookups of database entities. These are characterized by having a unique key (perhaps a database ID) and a separate unique key that identifies the object.
|
||||||
* key (perhaps a database ID) and a separate unique key that identifies the object.
|
|
||||||
* <p>
|
* <p>
|
||||||
* The keys must have good <code>equals</code> and </code>hashCode</code> implementations and
|
* The keys must have good <code>equals</code> and </code>hashCode</code> implementations and must respect the case-sensitivity of the use-case.
|
||||||
* must respect the case-sensitivity of the use-case.
|
|
||||||
*
|
*
|
||||||
* @author Derek Hulley
|
* @author Derek Hulley
|
||||||
* @since 3.2
|
* @since 3.2
|
||||||
*/
|
*/
|
||||||
public class EntityLookupCacheTest extends TestCase implements EntityLookupCallbackDAO<Long, Object, String>
|
public class EntityLookupCacheTest implements EntityLookupCallbackDAO<Long, Object, String>
|
||||||
{
|
{
|
||||||
SimpleCache<Long, Object> cache;
|
SimpleCache<Long, Object> cache;
|
||||||
private EntityLookupCache<Long, Object, String> entityLookupCacheA;
|
private EntityLookupCache<Long, Object, String> entityLookupCacheA;
|
||||||
@@ -59,8 +59,8 @@ public class EntityLookupCacheTest extends TestCase implements EntityLookupCallb
|
|||||||
private TreeMap<Long, String> database;
|
private TreeMap<Long, String> database;
|
||||||
private ControlDAO controlDAO;
|
private ControlDAO controlDAO;
|
||||||
|
|
||||||
@Override
|
@Before
|
||||||
protected void setUp() throws Exception
|
public void setUp() throws Exception
|
||||||
{
|
{
|
||||||
cache = new MemoryCache<Long, Object>();
|
cache = new MemoryCache<Long, Object>();
|
||||||
entityLookupCacheA = new EntityLookupCache<Long, Object, String>(cache, "A", this);
|
entityLookupCacheA = new EntityLookupCache<Long, Object, String>(cache, "A", this);
|
||||||
@@ -71,6 +71,7 @@ public class EntityLookupCacheTest extends TestCase implements EntityLookupCallb
|
|||||||
Mockito.when(controlDAO.createSavepoint(Mockito.anyString())).thenReturn(Mockito.mock(Savepoint.class));
|
Mockito.when(controlDAO.createSavepoint(Mockito.anyString())).thenReturn(Mockito.mock(Savepoint.class));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
public void testLookupsUsingIncorrectValue() throws Exception
|
public void testLookupsUsingIncorrectValue() throws Exception
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
@@ -78,12 +79,13 @@ public class EntityLookupCacheTest extends TestCase implements EntityLookupCallb
|
|||||||
// Keep the "database" empty
|
// Keep the "database" empty
|
||||||
entityLookupCacheA.getByValue(this);
|
entityLookupCacheA.getByValue(this);
|
||||||
}
|
}
|
||||||
catch (AssertionFailedError e)
|
catch (AssertionError e)
|
||||||
{
|
{
|
||||||
// Expected
|
// Expected
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
public void testLookupAgainstEmpty() throws Exception
|
public void testLookupAgainstEmpty() throws Exception
|
||||||
{
|
{
|
||||||
TestValue value = new TestValue("AAA");
|
TestValue value = new TestValue("AAA");
|
||||||
@@ -114,6 +116,7 @@ public class EntityLookupCacheTest extends TestCase implements EntityLookupCallb
|
|||||||
assertEquals("Looked-up type value incorrect", value, entityPair.getSecond());
|
assertEquals("Looked-up type value incorrect", value, entityPair.getSecond());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
public void testLookupAgainstExisting() throws Exception
|
public void testLookupAgainstExisting() throws Exception
|
||||||
{
|
{
|
||||||
// Put some values in the "database"
|
// Put some values in the "database"
|
||||||
@@ -136,6 +139,7 @@ public class EntityLookupCacheTest extends TestCase implements EntityLookupCallb
|
|||||||
assertEquals("ID is incorrect", new Long(3), entityPair.getFirst());
|
assertEquals("ID is incorrect", new Long(3), entityPair.getFirst());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
public void testRegions() throws Exception
|
public void testRegions() throws Exception
|
||||||
{
|
{
|
||||||
TestValue valueAAA = new TestValue("AAA");
|
TestValue valueAAA = new TestValue("AAA");
|
||||||
@@ -157,6 +161,7 @@ public class EntityLookupCacheTest extends TestCase implements EntityLookupCallb
|
|||||||
assertEquals(8, cache.getKeys().size());
|
assertEquals(8, cache.getKeys().size());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
public void testNullLookups() throws Exception
|
public void testNullLookups() throws Exception
|
||||||
{
|
{
|
||||||
TestValue valueNull = null;
|
TestValue valueNull = null;
|
||||||
@@ -174,9 +179,10 @@ public class EntityLookupCacheTest extends TestCase implements EntityLookupCallb
|
|||||||
assertEquals(entityPairNull, entityPairCheck);
|
assertEquals(entityPairNull, entityPairCheck);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
public void testGetOrCreate() throws Exception
|
public void testGetOrCreate() throws Exception
|
||||||
{
|
{
|
||||||
TestValue valueOne = new TestValue(getName() + "-ONE");
|
TestValue valueOne = new TestValue(getClass().getName() + "-ONE");
|
||||||
Pair<Long, Object> entityPairOne = entityLookupCacheA.getOrCreateByValue(valueOne);
|
Pair<Long, Object> entityPairOne = entityLookupCacheA.getOrCreateByValue(valueOne);
|
||||||
assertNotNull(entityPairOne);
|
assertNotNull(entityPairOne);
|
||||||
Long id = entityPairOne.getFirst();
|
Long id = entityPairOne.getFirst();
|
||||||
@@ -188,24 +194,27 @@ public class EntityLookupCacheTest extends TestCase implements EntityLookupCallb
|
|||||||
assertEquals(id, entityPairOneCheck.getFirst());
|
assertEquals(id, entityPairOneCheck.getFirst());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
public void testCreateOrGet() throws Exception
|
public void testCreateOrGet() throws Exception
|
||||||
{
|
{
|
||||||
TestValue valueOne = new TestValue(getName() + "-ONE");
|
TestValue valueOne = new TestValue(getClass().getName() + "-ONE");
|
||||||
Pair<Long, Object> entityPairOne = entityLookupCacheA.createOrGetByValue(valueOne, controlDAO);
|
Pair<Long, Object> entityPairOne = entityLookupCacheA.createOrGetByValue(valueOne, controlDAO);
|
||||||
assertNotNull(entityPairOne);
|
assertNotNull(entityPairOne);
|
||||||
Long id = entityPairOne.getFirst();
|
Long id = entityPairOne.getFirst();
|
||||||
assertEquals(valueOne.val, database.get(id));
|
assertEquals(valueOne.val, database.get(id));
|
||||||
assertEquals(1, cache.getKeys().size());
|
// We cache both by value and by key, so we should have 2 entries
|
||||||
|
assertEquals(2, cache.getKeys().size());
|
||||||
|
|
||||||
Pair<Long, Object> entityPairOneCheck = entityLookupCacheA.createOrGetByValue(valueOne, controlDAO);
|
Pair<Long, Object> entityPairOneCheck = entityLookupCacheA.createOrGetByValue(valueOne, controlDAO);
|
||||||
assertNotNull(entityPairOneCheck);
|
assertNotNull(entityPairOneCheck);
|
||||||
assertEquals(id, entityPairOneCheck.getFirst());
|
assertEquals(id, entityPairOneCheck.getFirst());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
public void testUpdate() throws Exception
|
public void testUpdate() throws Exception
|
||||||
{
|
{
|
||||||
TestValue valueOne = new TestValue(getName() + "-ONE");
|
TestValue valueOne = new TestValue(getClass().getName() + "-ONE");
|
||||||
TestValue valueTwo = new TestValue(getName() + "-TWO");
|
TestValue valueTwo = new TestValue(getClass().getName() + "-TWO");
|
||||||
Pair<Long, Object> entityPairOne = entityLookupCacheA.getOrCreateByValue(valueOne);
|
Pair<Long, Object> entityPairOne = entityLookupCacheA.getOrCreateByValue(valueOne);
|
||||||
assertNotNull(entityPairOne);
|
assertNotNull(entityPairOne);
|
||||||
Long id = entityPairOne.getFirst();
|
Long id = entityPairOne.getFirst();
|
||||||
@@ -219,9 +228,10 @@ public class EntityLookupCacheTest extends TestCase implements EntityLookupCallb
|
|||||||
assertEquals(2, cache.getKeys().size());
|
assertEquals(2, cache.getKeys().size());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
public void testDeleteByKey() throws Exception
|
public void testDeleteByKey() throws Exception
|
||||||
{
|
{
|
||||||
TestValue valueOne = new TestValue(getName() + "-ONE");
|
TestValue valueOne = new TestValue(getClass().getName() + "-ONE");
|
||||||
Pair<Long, Object> entityPairOne = entityLookupCacheA.getOrCreateByValue(valueOne);
|
Pair<Long, Object> entityPairOne = entityLookupCacheA.getOrCreateByValue(valueOne);
|
||||||
assertNotNull(entityPairOne);
|
assertNotNull(entityPairOne);
|
||||||
Long id = entityPairOne.getFirst();
|
Long id = entityPairOne.getFirst();
|
||||||
@@ -235,9 +245,10 @@ public class EntityLookupCacheTest extends TestCase implements EntityLookupCallb
|
|||||||
assertEquals(0, cache.getKeys().size());
|
assertEquals(0, cache.getKeys().size());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
public void testDeleteByValue() throws Exception
|
public void testDeleteByValue() throws Exception
|
||||||
{
|
{
|
||||||
TestValue valueOne = new TestValue(getName() + "-ONE");
|
TestValue valueOne = new TestValue(getClass().getName() + "-ONE");
|
||||||
Pair<Long, Object> entityPairOne = entityLookupCacheA.getOrCreateByValue(valueOne);
|
Pair<Long, Object> entityPairOne = entityLookupCacheA.getOrCreateByValue(valueOne);
|
||||||
assertNotNull(entityPairOne);
|
assertNotNull(entityPairOne);
|
||||||
Long id = entityPairOne.getFirst();
|
Long id = entityPairOne.getFirst();
|
||||||
@@ -251,9 +262,10 @@ public class EntityLookupCacheTest extends TestCase implements EntityLookupCallb
|
|||||||
assertEquals(0, cache.getKeys().size());
|
assertEquals(0, cache.getKeys().size());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
public void testClear() throws Exception
|
public void testClear() throws Exception
|
||||||
{
|
{
|
||||||
TestValue valueOne = new TestValue(getName() + "-ONE");
|
TestValue valueOne = new TestValue(getClass().getName() + "-ONE");
|
||||||
Pair<Long, Object> entityPairOne = entityLookupCacheA.getOrCreateByValue(valueOne);
|
Pair<Long, Object> entityPairOne = entityLookupCacheA.getOrCreateByValue(valueOne);
|
||||||
assertNotNull(entityPairOne);
|
assertNotNull(entityPairOne);
|
||||||
Long id = entityPairOne.getFirst();
|
Long id = entityPairOne.getFirst();
|
||||||
@@ -266,16 +278,42 @@ public class EntityLookupCacheTest extends TestCase implements EntityLookupCallb
|
|||||||
assertEquals(0, cache.getKeys().size()); // ... but cache must be empty
|
assertEquals(0, cache.getKeys().size()); // ... but cache must be empty
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testGetCachedValue() throws Exception
|
||||||
|
{
|
||||||
|
// Create a new value
|
||||||
|
TestValue valueCached = new TestValue(getClass().getName() + "-CACHED");
|
||||||
|
Pair<Long, Object> entityPairOne = entityLookupCacheA.createOrGetByValue(valueCached, controlDAO);
|
||||||
|
assertNotNull(entityPairOne);
|
||||||
|
Long id = entityPairOne.getFirst();
|
||||||
|
// We cache both by value and by key, so we should have 2 entries
|
||||||
|
assertEquals(2, cache.getKeys().size());
|
||||||
|
|
||||||
|
// Check the cache for the previously created value
|
||||||
|
Pair<Long, Object> entityPairCacheCheck = entityLookupCacheA.getCachedEntityByValue(valueCached);
|
||||||
|
assertNotNull(entityPairCacheCheck);
|
||||||
|
assertEquals(id, entityPairCacheCheck.getFirst());
|
||||||
|
|
||||||
|
// Clear the cache and attempt to retrieve it again
|
||||||
|
entityLookupCacheA.clear();
|
||||||
|
entityPairCacheCheck = entityLookupCacheA.getCachedEntityByValue(valueCached);
|
||||||
|
|
||||||
|
// Since we are only retrieving from cache, the value should not be found
|
||||||
|
assertNull(entityPairCacheCheck);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Helper class to represent business object
|
* Helper class to represent business object
|
||||||
*/
|
*/
|
||||||
private static class TestValue
|
private static class TestValue
|
||||||
{
|
{
|
||||||
private final String val;
|
private final String val;
|
||||||
|
|
||||||
private TestValue(String val)
|
private TestValue(String val)
|
||||||
{
|
{
|
||||||
this.val = val;
|
this.val = val;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean equals(Object obj)
|
public boolean equals(Object obj)
|
||||||
{
|
{
|
||||||
@@ -285,6 +323,7 @@ public class EntityLookupCacheTest extends TestCase implements EntityLookupCallb
|
|||||||
}
|
}
|
||||||
return val.equals(((TestValue) obj).val);
|
return val.equals(((TestValue) obj).val);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int hashCode()
|
public int hashCode()
|
||||||
{
|
{
|
||||||
|
@@ -0,0 +1,48 @@
|
|||||||
|
/*
|
||||||
|
* #%L
|
||||||
|
* Alfresco Repository
|
||||||
|
* %%
|
||||||
|
* Copyright (C) 2025 - 2025 Alfresco Software Limited
|
||||||
|
* %%
|
||||||
|
* This file is part of the Alfresco software.
|
||||||
|
* If the software was purchased under a paid Alfresco license, the terms of
|
||||||
|
* the paid license agreement will prevail. Otherwise, the software is
|
||||||
|
* provided under the following open source license terms:
|
||||||
|
*
|
||||||
|
* Alfresco is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU Lesser General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* Alfresco is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU Lesser General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Lesser General Public License
|
||||||
|
* along with Alfresco. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
* #L%
|
||||||
|
*/
|
||||||
|
package org.alfresco.repo.event2;
|
||||||
|
|
||||||
|
import static org.junit.Assert.assertEquals;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import org.junit.Test;
|
||||||
|
|
||||||
|
import org.alfresco.repo.event2.shared.CSVStringToListParser;
|
||||||
|
|
||||||
|
public class CSVStringToListParserUnitTest
|
||||||
|
{
|
||||||
|
@Test
|
||||||
|
public void shouldIgnoreEmptySpacesAndNoneValueAndTemplateStringsAndParseTheRest()
|
||||||
|
{
|
||||||
|
String userInputCSV = "a,,none,2,${test}, ,*";
|
||||||
|
|
||||||
|
List<String> result = CSVStringToListParser.parse(userInputCSV);
|
||||||
|
|
||||||
|
List<String> expected = List.of("a", "2", "*");
|
||||||
|
assertEquals(expected, result);
|
||||||
|
}
|
||||||
|
}
|
@@ -2,7 +2,7 @@
|
|||||||
* #%L
|
* #%L
|
||||||
* Alfresco Repository
|
* Alfresco Repository
|
||||||
* %%
|
* %%
|
||||||
* Copyright (C) 2005 - 2020 Alfresco Software Limited
|
* Copyright (C) 2005 - 2025 Alfresco Software Limited
|
||||||
* %%
|
* %%
|
||||||
* This file is part of the Alfresco software.
|
* This file is part of the Alfresco software.
|
||||||
* If the software was purchased under a paid Alfresco license, the terms of
|
* If the software was purchased under a paid Alfresco license, the terms of
|
||||||
@@ -35,6 +35,10 @@ import static org.mockito.Mockito.when;
|
|||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
|
|
||||||
|
import org.junit.BeforeClass;
|
||||||
|
import org.junit.Test;
|
||||||
|
import org.mockito.stubbing.Answer;
|
||||||
|
|
||||||
import org.alfresco.model.ContentModel;
|
import org.alfresco.model.ContentModel;
|
||||||
import org.alfresco.model.ForumModel;
|
import org.alfresco.model.ForumModel;
|
||||||
import org.alfresco.model.RenditionModel;
|
import org.alfresco.model.RenditionModel;
|
||||||
@@ -43,14 +47,12 @@ import org.alfresco.repo.event2.filter.EventUserFilter;
|
|||||||
import org.alfresco.repo.event2.filter.NodeAspectFilter;
|
import org.alfresco.repo.event2.filter.NodeAspectFilter;
|
||||||
import org.alfresco.repo.event2.filter.NodePropertyFilter;
|
import org.alfresco.repo.event2.filter.NodePropertyFilter;
|
||||||
import org.alfresco.repo.event2.filter.NodeTypeFilter;
|
import org.alfresco.repo.event2.filter.NodeTypeFilter;
|
||||||
|
import org.alfresco.repo.event2.shared.TypeDefExpander;
|
||||||
import org.alfresco.service.cmr.dictionary.DictionaryService;
|
import org.alfresco.service.cmr.dictionary.DictionaryService;
|
||||||
import org.alfresco.service.namespace.NamespaceException;
|
import org.alfresco.service.namespace.NamespaceException;
|
||||||
import org.alfresco.service.namespace.NamespaceService;
|
import org.alfresco.service.namespace.NamespaceService;
|
||||||
import org.alfresco.service.namespace.QName;
|
import org.alfresco.service.namespace.QName;
|
||||||
import org.alfresco.util.OneToManyHashBiMap;
|
import org.alfresco.util.OneToManyHashBiMap;
|
||||||
import org.junit.BeforeClass;
|
|
||||||
import org.junit.Test;
|
|
||||||
import org.mockito.stubbing.Answer;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Tests event filters.
|
* Tests event filters.
|
||||||
@@ -85,25 +87,25 @@ public class EventFilterUnitTest
|
|||||||
NamespaceService.FORUMS_MODEL_1_0_URI);
|
NamespaceService.FORUMS_MODEL_1_0_URI);
|
||||||
namespaceService.registerNamespace(NamespaceService.RENDITION_MODEL_PREFIX,
|
namespaceService.registerNamespace(NamespaceService.RENDITION_MODEL_PREFIX,
|
||||||
NamespaceService.RENDITION_MODEL_1_0_URI);
|
NamespaceService.RENDITION_MODEL_1_0_URI);
|
||||||
|
namespaceService.registerNamespace(ContentModel.USER_MODEL_PREFIX,
|
||||||
|
ContentModel.USER_MODEL_URI);
|
||||||
|
|
||||||
propertyFilter = new NodePropertyFilter();
|
TypeDefExpander typeDefExpander = new TypeDefExpander(dictionaryService, namespaceService);
|
||||||
propertyFilter.setNamespaceService(namespaceService);
|
|
||||||
propertyFilter.setDictionaryService(dictionaryService);
|
propertyFilter = new NodePropertyFilter("usr:password");
|
||||||
|
propertyFilter.setTypeDefExpander(typeDefExpander);
|
||||||
propertyFilter.init();
|
propertyFilter.init();
|
||||||
|
|
||||||
typeFilter = new NodeTypeFilter("sys:*, fm:*, cm:thumbnail");
|
typeFilter = new NodeTypeFilter("sys:*, fm:*, cm:thumbnail", dictionaryService);
|
||||||
typeFilter.setNamespaceService(namespaceService);
|
typeFilter.setTypeDefExpander(typeDefExpander);
|
||||||
typeFilter.setDictionaryService(dictionaryService);
|
|
||||||
typeFilter.init();
|
typeFilter.init();
|
||||||
|
|
||||||
aspectFilter = new NodeAspectFilter("cm:workingcopy");
|
aspectFilter = new NodeAspectFilter("cm:workingcopy");
|
||||||
aspectFilter.setNamespaceService(namespaceService);
|
aspectFilter.setTypeDefExpander(typeDefExpander);
|
||||||
aspectFilter.setDictionaryService(dictionaryService);
|
|
||||||
aspectFilter.init();
|
aspectFilter.init();
|
||||||
|
|
||||||
childAssociationTypeFilter = new ChildAssociationTypeFilter("rn:rendition");
|
childAssociationTypeFilter = new ChildAssociationTypeFilter("rn:rendition");
|
||||||
childAssociationTypeFilter.setNamespaceService(namespaceService);
|
childAssociationTypeFilter.setTypeDefExpander(typeDefExpander);
|
||||||
childAssociationTypeFilter.setDictionaryService(dictionaryService);
|
|
||||||
childAssociationTypeFilter.init();
|
childAssociationTypeFilter.init();
|
||||||
|
|
||||||
caseInsensitive_userFilter = new EventUserFilter("System, john.doe, null", false);
|
caseInsensitive_userFilter = new EventUserFilter("System, john.doe, null", false);
|
||||||
@@ -119,6 +121,8 @@ public class EventFilterUnitTest
|
|||||||
assertTrue("System properties are excluded by default.",
|
assertTrue("System properties are excluded by default.",
|
||||||
propertyFilter.isExcluded(ContentModel.PROP_NODE_DBID));
|
propertyFilter.isExcluded(ContentModel.PROP_NODE_DBID));
|
||||||
|
|
||||||
|
assertTrue("User configured properties are excluded.", propertyFilter.isExcluded(ContentModel.PROP_PASSWORD));
|
||||||
|
|
||||||
assertFalse(propertyFilter.isExcluded(ContentModel.PROP_TITLE));
|
assertFalse(propertyFilter.isExcluded(ContentModel.PROP_TITLE));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -0,0 +1,80 @@
|
|||||||
|
/*
|
||||||
|
* #%L
|
||||||
|
* Alfresco Repository
|
||||||
|
* %%
|
||||||
|
* Copyright (C) 2025 - 2025 Alfresco Software Limited
|
||||||
|
* %%
|
||||||
|
* This file is part of the Alfresco software.
|
||||||
|
* If the software was purchased under a paid Alfresco license, the terms of
|
||||||
|
* the paid license agreement will prevail. Otherwise, the software is
|
||||||
|
* provided under the following open source license terms:
|
||||||
|
*
|
||||||
|
* Alfresco is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU Lesser General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* Alfresco is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU Lesser General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Lesser General Public License
|
||||||
|
* along with Alfresco. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
* #L%
|
||||||
|
*/
|
||||||
|
package org.alfresco.repo.event2;
|
||||||
|
|
||||||
|
import static org.junit.Assert.assertEquals;
|
||||||
|
|
||||||
|
import java.util.Set;
|
||||||
|
import java.util.UUID;
|
||||||
|
|
||||||
|
import org.junit.Test;
|
||||||
|
|
||||||
|
import org.alfresco.model.ContentModel;
|
||||||
|
import org.alfresco.repo.event2.mapper.PropertyMapper;
|
||||||
|
import org.alfresco.repo.event2.mapper.ReplaceSensitivePropertyWithTextMapper;
|
||||||
|
import org.alfresco.repo.transfer.TransferModel;
|
||||||
|
|
||||||
|
public class PropertyMapperUnitTest
|
||||||
|
{
|
||||||
|
private static final String DEFAULT_REPLACEMENT_TEXT = "SENSITIVE_DATA_REMOVED";
|
||||||
|
private static final String USER_CONFIGURED_REPLACEMENT_TEXT = "HIDDEN_BY_SECURITY_CONFIG";
|
||||||
|
|
||||||
|
private final PropertyMapper defaultPropertyMapper = new ReplaceSensitivePropertyWithTextMapper(null, null);
|
||||||
|
private final PropertyMapper userConfiguredpropertyMapper = new ReplaceSensitivePropertyWithTextMapper(
|
||||||
|
Set.of(ContentModel.PROP_PASSWORD, TransferModel.PROP_PASSWORD),
|
||||||
|
USER_CONFIGURED_REPLACEMENT_TEXT);
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void shouldReplacePropertyValueWhenItsOneOfTheDefaultSensitivePropertiesWhenUsingDefaultConfig()
|
||||||
|
{
|
||||||
|
assertEquals(DEFAULT_REPLACEMENT_TEXT, defaultPropertyMapper.map(ContentModel.PROP_PASSWORD, "test_pass"));
|
||||||
|
assertEquals(DEFAULT_REPLACEMENT_TEXT, defaultPropertyMapper.map(ContentModel.PROP_SALT, UUID.randomUUID().toString()));
|
||||||
|
assertEquals(DEFAULT_REPLACEMENT_TEXT, defaultPropertyMapper.map(ContentModel.PROP_PASSWORD_HASH, "r4nD0M_h4sH"));
|
||||||
|
assertEquals(DEFAULT_REPLACEMENT_TEXT, defaultPropertyMapper.map(TransferModel.PROP_PASSWORD, "pyramid"));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void shouldNotReplacePropertyValueWhenItsNotOneOfTheDefaultSensitivePropertiesWhenUsingDefaultConfig()
|
||||||
|
{
|
||||||
|
assertEquals("Bob", defaultPropertyMapper.map(ContentModel.PROP_USERNAME, "Bob"));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void shouldReplacePropertyValueWhenItsOneOfTheDefaultSensitivePropertiesWhenUsingUserConfig()
|
||||||
|
{
|
||||||
|
assertEquals(USER_CONFIGURED_REPLACEMENT_TEXT, userConfiguredpropertyMapper.map(ContentModel.PROP_PASSWORD, "test_pass"));
|
||||||
|
|
||||||
|
assertEquals(USER_CONFIGURED_REPLACEMENT_TEXT, userConfiguredpropertyMapper.map(TransferModel.PROP_PASSWORD, "pyramid"));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void shouldNotReplacePropertyValueWhenItsNotOneOfTheDefaultSensitivePropertiesWhenUsingUserConfig()
|
||||||
|
{
|
||||||
|
String randomUuid = UUID.randomUUID().toString();
|
||||||
|
assertEquals(randomUuid, userConfiguredpropertyMapper.map(ContentModel.PROP_SALT, randomUuid));
|
||||||
|
assertEquals("r4nD0M_h4sH", userConfiguredpropertyMapper.map(ContentModel.PROP_PASSWORD_HASH, "r4nD0M_h4sH"));
|
||||||
|
}
|
||||||
|
}
|
@@ -0,0 +1,65 @@
|
|||||||
|
/*
|
||||||
|
* #%L
|
||||||
|
* Alfresco Repository
|
||||||
|
* %%
|
||||||
|
* Copyright (C) 2025 - 2025 Alfresco Software Limited
|
||||||
|
* %%
|
||||||
|
* This file is part of the Alfresco software.
|
||||||
|
* If the software was purchased under a paid Alfresco license, the terms of
|
||||||
|
* the paid license agreement will prevail. Otherwise, the software is
|
||||||
|
* provided under the following open source license terms:
|
||||||
|
*
|
||||||
|
* Alfresco is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU Lesser General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* Alfresco is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU Lesser General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Lesser General Public License
|
||||||
|
* along with Alfresco. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
* #L%
|
||||||
|
*/
|
||||||
|
package org.alfresco.repo.event2;
|
||||||
|
|
||||||
|
import static org.junit.Assert.assertFalse;
|
||||||
|
import static org.junit.Assert.assertTrue;
|
||||||
|
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
|
import org.junit.Test;
|
||||||
|
|
||||||
|
import org.alfresco.model.ContentModel;
|
||||||
|
import org.alfresco.repo.event2.shared.QNameMatcher;
|
||||||
|
import org.alfresco.repo.transfer.TransferModel;
|
||||||
|
import org.alfresco.service.namespace.QName;
|
||||||
|
|
||||||
|
public class QNameMatcherUnitTest
|
||||||
|
{
|
||||||
|
@Test
|
||||||
|
public void shouldMatchOnlyQNamesFromUserModelURI()
|
||||||
|
{
|
||||||
|
QNameMatcher qNameMatcher = new QNameMatcher(Set.of(QName.createQName(ContentModel.USER_MODEL_URI, "*")));
|
||||||
|
|
||||||
|
assertTrue(qNameMatcher.isMatching(ContentModel.PROP_USER_USERNAME));
|
||||||
|
assertTrue(qNameMatcher.isMatching(ContentModel.TYPE_USER));
|
||||||
|
assertFalse(qNameMatcher.isMatching(ContentModel.PROP_TITLE));
|
||||||
|
assertFalse(qNameMatcher.isMatching(TransferModel.PROP_USERNAME));
|
||||||
|
assertFalse(qNameMatcher.isMatching(null));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void shouldOnlyMatchSpecificQName()
|
||||||
|
{
|
||||||
|
QNameMatcher qNameMatcher = new QNameMatcher(Set.of(ContentModel.PROP_USER_USERNAME));
|
||||||
|
|
||||||
|
assertTrue(qNameMatcher.isMatching(ContentModel.PROP_USER_USERNAME));
|
||||||
|
assertFalse(qNameMatcher.isMatching(ContentModel.PROP_NAME));
|
||||||
|
assertFalse(qNameMatcher.isMatching(ContentModel.PROP_USERNAME));
|
||||||
|
assertFalse(qNameMatcher.isMatching(TransferModel.PROP_USERNAME));
|
||||||
|
assertFalse(qNameMatcher.isMatching(null));
|
||||||
|
}
|
||||||
|
}
|
@@ -2,7 +2,7 @@
|
|||||||
* #%L
|
* #%L
|
||||||
* Alfresco Repository
|
* Alfresco Repository
|
||||||
* %%
|
* %%
|
||||||
* Copyright (C) 2005 - 2023 Alfresco Software Limited
|
* Copyright (C) 2005 - 2025 Alfresco Software Limited
|
||||||
* %%
|
* %%
|
||||||
* This file is part of the Alfresco software.
|
* This file is part of the Alfresco software.
|
||||||
* If the software was purchased under a paid Alfresco license, the terms of
|
* If the software was purchased under a paid Alfresco license, the terms of
|
||||||
@@ -23,7 +23,6 @@
|
|||||||
* along with Alfresco. If not, see <http://www.gnu.org/licenses/>.
|
* along with Alfresco. If not, see <http://www.gnu.org/licenses/>.
|
||||||
* #L%
|
* #L%
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package org.alfresco.repo.event2;
|
package org.alfresco.repo.event2;
|
||||||
|
|
||||||
import org.junit.runner.RunWith;
|
import org.junit.runner.RunWith;
|
||||||
@@ -35,8 +34,11 @@ import org.junit.runners.Suite.SuiteClasses;
|
|||||||
EventConsolidatorUnitTest.class,
|
EventConsolidatorUnitTest.class,
|
||||||
EventJSONSchemaUnitTest.class,
|
EventJSONSchemaUnitTest.class,
|
||||||
EventGeneratorQueueUnitTest.class,
|
EventGeneratorQueueUnitTest.class,
|
||||||
NodeResourceHelperUnitTest.class
|
NodeResourceHelperUnitTest.class,
|
||||||
|
PropertyMapperUnitTest.class,
|
||||||
|
QNameMatcherUnitTest.class,
|
||||||
|
CSVStringToListParserUnitTest.class,
|
||||||
|
TypeDefExpanderUnitTest.class
|
||||||
})
|
})
|
||||||
public class RepoEvent2UnitSuite
|
public class RepoEvent2UnitSuite
|
||||||
{
|
{}
|
||||||
}
|
|
||||||
|
@@ -0,0 +1,98 @@
|
|||||||
|
/*
|
||||||
|
* #%L
|
||||||
|
* Alfresco Repository
|
||||||
|
* %%
|
||||||
|
* Copyright (C) 2025 - 2025 Alfresco Software Limited
|
||||||
|
* %%
|
||||||
|
* This file is part of the Alfresco software.
|
||||||
|
* If the software was purchased under a paid Alfresco license, the terms of
|
||||||
|
* the paid license agreement will prevail. Otherwise, the software is
|
||||||
|
* provided under the following open source license terms:
|
||||||
|
*
|
||||||
|
* Alfresco is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU Lesser General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* Alfresco is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU Lesser General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Lesser General Public License
|
||||||
|
* along with Alfresco. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
* #L%
|
||||||
|
*/
|
||||||
|
package org.alfresco.repo.event2;
|
||||||
|
|
||||||
|
import static org.junit.Assert.assertEquals;
|
||||||
|
import static org.junit.Assert.assertTrue;
|
||||||
|
import static org.mockito.Mockito.mock;
|
||||||
|
import static org.mockito.Mockito.when;
|
||||||
|
|
||||||
|
import java.util.Collection;
|
||||||
|
import java.util.Set;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
import java.util.stream.Stream;
|
||||||
|
|
||||||
|
import org.junit.Before;
|
||||||
|
import org.junit.Test;
|
||||||
|
|
||||||
|
import org.alfresco.model.ContentModel;
|
||||||
|
import org.alfresco.model.DataListModel;
|
||||||
|
import org.alfresco.repo.event2.shared.TypeDefExpander;
|
||||||
|
import org.alfresco.repo.transfer.TransferModel;
|
||||||
|
import org.alfresco.repo.workflow.WorkflowModel;
|
||||||
|
import org.alfresco.service.cmr.dictionary.DictionaryService;
|
||||||
|
import org.alfresco.service.namespace.NamespaceService;
|
||||||
|
import org.alfresco.service.namespace.QName;
|
||||||
|
|
||||||
|
public class TypeDefExpanderUnitTest
|
||||||
|
{
|
||||||
|
private DictionaryService dictionaryService;
|
||||||
|
private NamespaceService namespaceService;
|
||||||
|
private TypeDefExpander typeDefExpander;
|
||||||
|
|
||||||
|
@Before
|
||||||
|
public void setUp()
|
||||||
|
{
|
||||||
|
dictionaryService = mock(DictionaryService.class);
|
||||||
|
namespaceService = mock(NamespaceService.class);
|
||||||
|
typeDefExpander = new TypeDefExpander(dictionaryService, namespaceService);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testExpandWithValidType()
|
||||||
|
{
|
||||||
|
String input = "usr:username";
|
||||||
|
when(namespaceService.getNamespaceURI("usr")).thenReturn(ContentModel.USER_MODEL_URI);
|
||||||
|
|
||||||
|
Collection<QName> result = typeDefExpander.expand(input);
|
||||||
|
|
||||||
|
QName expected = ContentModel.PROP_USER_USERNAME;
|
||||||
|
assertEquals(expected, result.iterator().next());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testExpandWithValidTypeIncludingSubtypes()
|
||||||
|
{
|
||||||
|
String input = "cm:content include_subtypes";
|
||||||
|
when(namespaceService.getNamespaceURI("cm")).thenReturn(NamespaceService.CONTENT_MODEL_1_0_URI);
|
||||||
|
Set<QName> subtypes = Set.of(TransferModel.TYPE_TRANSFER_RECORD, DataListModel.TYPE_EVENT, WorkflowModel.TYPE_TASK);
|
||||||
|
when(dictionaryService.getSubTypes(ContentModel.TYPE_CONTENT, true)).thenReturn(subtypes);
|
||||||
|
|
||||||
|
Collection<QName> result = typeDefExpander.expand(input);
|
||||||
|
|
||||||
|
assertEquals(subtypes, result);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testExpandWithInvalidTypes()
|
||||||
|
{
|
||||||
|
Set<String> input = Stream.of(null, " ", "none", "${test.prop}").collect(Collectors.toSet());
|
||||||
|
|
||||||
|
Collection<QName> result = typeDefExpander.expand(input);
|
||||||
|
|
||||||
|
assertTrue(result.isEmpty());
|
||||||
|
}
|
||||||
|
}
|
@@ -43,7 +43,7 @@ identity-service.enable-pkce=true
|
|||||||
identity-service.ignore-oauth-query-parameter=true
|
identity-service.ignore-oauth-query-parameter=true
|
||||||
identity-service.credentials.secret=11111
|
identity-service.credentials.secret=11111
|
||||||
identity-service.credentials.provider=secret
|
identity-service.credentials.provider=secret
|
||||||
identity-service.client-socket-timeout=1000
|
identity-service.client-socket-timeout=3000
|
||||||
identity-service.client-connection-timeout=3000
|
identity-service.client-connection-timeout=3000
|
||||||
identity-service.authentication.enable-username-password-authentication=false
|
identity-service.authentication.enable-username-password-authentication=false
|
||||||
|
|
||||||
|
@@ -59,11 +59,11 @@ services:
|
|||||||
CLIENT_SSL_TRUST_STORE_TYPE: "JCEKS"
|
CLIENT_SSL_TRUST_STORE_TYPE: "JCEKS"
|
||||||
keycloak:
|
keycloak:
|
||||||
profiles: ["with-sso"]
|
profiles: ["with-sso"]
|
||||||
image: quay.io/keycloak/keycloak:25.0.6
|
image: quay.io/keycloak/keycloak:26.1.0
|
||||||
environment:
|
environment:
|
||||||
- KEYCLOAK_ADMIN=admin
|
- KC_BOOTSTRAP_ADMIN_USERNAME=admin
|
||||||
- KEYCLOAK_ADMIN_PASSWORD=admin
|
- KC_BOOTSTRAP_ADMIN_PASSWORD=admin
|
||||||
- KC_DB=dev-mem
|
- KC_DB=dev-file
|
||||||
command: ["start-dev", "--import-realm", "--http-relative-path=/auth", "--hostname=localhost", "--http-enabled=true"]
|
command: ["start-dev", "--import-realm", "--http-relative-path=/auth", "--hostname=localhost", "--http-enabled=true"]
|
||||||
volumes:
|
volumes:
|
||||||
- ../../../repository/src/test/resources/realms/alfresco-realm.json:/opt/keycloak/data/import/alfresco-realm.json
|
- ../../../repository/src/test/resources/realms/alfresco-realm.json:/opt/keycloak/data/import/alfresco-realm.json
|
||||||
|
21
scripts/hooks/check-format-and-headers.sh
Executable file
21
scripts/hooks/check-format-and-headers.sh
Executable file
@@ -0,0 +1,21 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
|
||||||
|
set +x
|
||||||
|
|
||||||
|
if [[ -z ${GITHUB_MODIFIED_FILES} ]]
|
||||||
|
then
|
||||||
|
modified_files=$(git diff --cached --name-only --diff-filter=ACMR)
|
||||||
|
else
|
||||||
|
modified_files=${GITHUB_MODIFIED_FILES}
|
||||||
|
fi
|
||||||
|
|
||||||
|
include_list=""
|
||||||
|
for file in ${modified_files}
|
||||||
|
do
|
||||||
|
include_list="${include_list},${file}"
|
||||||
|
done
|
||||||
|
include_list=${include_list:1}
|
||||||
|
|
||||||
|
mvn spotless:apply validate -DlicenseUpdateHeaders=true -Pags,all-tas-tests -Dspotless-include-list="${include_list}" > /dev/null || true
|
||||||
|
|
||||||
|
set -x
|
Reference in New Issue
Block a user