├── .gitignore ├── LICENSE ├── README.md ├── alfresco-kafka-model ├── .gitignore ├── pom.xml └── src │ └── main │ └── java │ └── com │ └── metaversant │ └── kafka │ └── model │ ├── NodeEvent.java │ ├── NodePermission.java │ └── NodePermissions.java ├── alfresco-kafka-repo ├── .gitignore ├── README.md ├── docker │ └── docker-compose.yml ├── pom.xml └── src │ └── main │ ├── assembly │ ├── amp.xml │ ├── file-mapping.properties │ └── web │ │ └── README.md │ ├── docker │ ├── Dockerfile │ ├── alfresco-global.properties │ ├── dev-log4j.properties │ ├── disable-webscript-caching-context.xml │ ├── hotswap-agent.properties │ └── license │ │ └── README.md │ ├── java │ └── com │ │ └── metaversant │ │ └── kafka │ │ ├── behavior │ │ ├── GenerateNodeEvent.java │ │ └── GenerateNodePermissionEvent.java │ │ ├── service │ │ ├── MessageService.java │ │ └── MessageServiceScopedObject.java │ │ └── transform │ │ ├── NodeRefToNodeEvent.java │ │ └── NodeRefToNodePermissions.java │ └── resources │ ├── META-INF │ └── resources │ │ └── test.html │ ├── alfresco │ ├── extension │ │ └── templates │ │ │ └── webscripts │ │ │ └── com │ │ │ └── metaversant │ │ │ └── alfresco │ │ │ └── kafka │ │ │ ├── ping.get.desc.xml │ │ │ ├── ping.get.js │ │ │ └── ping.get.json.ftl │ └── module │ │ └── alfresco-kafka-repo │ │ ├── alfresco-global.properties │ │ ├── context │ │ ├── bootstrap-context.xml │ │ └── service-context.xml │ │ ├── log4j.properties │ │ ├── module-context.xml │ │ └── module.properties │ └── examples │ ├── enable_inherit.json │ ├── revoke.json │ └── update.json ├── pom.xml ├── run.bat └── run.sh /.gitignore: -------------------------------------------------------------------------------- 1 | .idea 2 | alf_data_dev 3 | /target 4 | /.classpath 5 | /.project 6 | /.settings 7 | /*.log* 8 | /data/ 9 | /logs/ -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | 2 | Apache License 3 | Version 2.0, January 2004 4 | http://www.apache.org/licenses/ 5 | 6 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 7 | 8 | 1. Definitions. 9 | 10 | "License" shall mean the terms and conditions for use, reproduction, 11 | and distribution as defined by Sections 1 through 9 of this document. 12 | 13 | "Licensor" shall mean the copyright owner or entity authorized by 14 | the copyright owner that is granting the License. 15 | 16 | "Legal Entity" shall mean the union of the acting entity and all 17 | other entities that control, are controlled by, or are under common 18 | control with that entity. For the purposes of this definition, 19 | "control" means (i) the power, direct or indirect, to cause the 20 | direction or management of such entity, whether by contract or 21 | otherwise, or (ii) ownership of fifty percent (50%) or more of the 22 | outstanding shares, or (iii) beneficial ownership of such entity. 23 | 24 | "You" (or "Your") shall mean an individual or Legal Entity 25 | exercising permissions granted by this License. 26 | 27 | "Source" form shall mean the preferred form for making modifications, 28 | including but not limited to software source code, documentation 29 | source, and configuration files. 30 | 31 | "Object" form shall mean any form resulting from mechanical 32 | transformation or translation of a Source form, including but 33 | not limited to compiled object code, generated documentation, 34 | and conversions to other media types. 35 | 36 | "Work" shall mean the work of authorship, whether in Source or 37 | Object form, made available under the License, as indicated by a 38 | copyright notice that is included in or attached to the work 39 | (an example is provided in the Appendix below). 40 | 41 | "Derivative Works" shall mean any work, whether in Source or Object 42 | form, that is based on (or derived from) the Work and for which the 43 | editorial revisions, annotations, elaborations, or other modifications 44 | represent, as a whole, an original work of authorship. For the purposes 45 | of this License, Derivative Works shall not include works that remain 46 | separable from, or merely link (or bind by name) to the interfaces of, 47 | the Work and Derivative Works thereof. 48 | 49 | "Contribution" shall mean any work of authorship, including 50 | the original version of the Work and any modifications or additions 51 | to that Work or Derivative Works thereof, that is intentionally 52 | submitted to Licensor for inclusion in the Work by the copyright owner 53 | or by an individual or Legal Entity authorized to submit on behalf of 54 | the copyright owner. For the purposes of this definition, "submitted" 55 | means any form of electronic, verbal, or written communication sent 56 | to the Licensor or its representatives, including but not limited to 57 | communication on electronic mailing lists, source code control systems, 58 | and issue tracking systems that are managed by, or on behalf of, the 59 | Licensor for the purpose of discussing and improving the Work, but 60 | excluding communication that is conspicuously marked or otherwise 61 | designated in writing by the copyright owner as "Not a Contribution." 62 | 63 | "Contributor" shall mean Licensor and any individual or Legal Entity 64 | on behalf of whom a Contribution has been received by Licensor and 65 | subsequently incorporated within the Work. 66 | 67 | 2. Grant of Copyright License. Subject to the terms and conditions of 68 | this License, each Contributor hereby grants to You a perpetual, 69 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 70 | copyright license to reproduce, prepare Derivative Works of, 71 | publicly display, publicly perform, sublicense, and distribute the 72 | Work and such Derivative Works in Source or Object form. 73 | 74 | 3. Grant of Patent License. Subject to the terms and conditions of 75 | this License, each Contributor hereby grants to You a perpetual, 76 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 77 | (except as stated in this section) patent license to make, have made, 78 | use, offer to sell, sell, import, and otherwise transfer the Work, 79 | where such license applies only to those patent claims licensable 80 | by such Contributor that are necessarily infringed by their 81 | Contribution(s) alone or by combination of their Contribution(s) 82 | with the Work to which such Contribution(s) was submitted. If You 83 | institute patent litigation against any entity (including a 84 | cross-claim or counterclaim in a lawsuit) alleging that the Work 85 | or a Contribution incorporated within the Work constitutes direct 86 | or contributory patent infringement, then any patent licenses 87 | granted to You under this License for that Work shall terminate 88 | as of the date such litigation is filed. 89 | 90 | 4. Redistribution. You may reproduce and distribute copies of the 91 | Work or Derivative Works thereof in any medium, with or without 92 | modifications, and in Source or Object form, provided that You 93 | meet the following conditions: 94 | 95 | (a) You must give any other recipients of the Work or 96 | Derivative Works a copy of this License; and 97 | 98 | (b) You must cause any modified files to carry prominent notices 99 | stating that You changed the files; and 100 | 101 | (c) You must retain, in the Source form of any Derivative Works 102 | that You distribute, all copyright, patent, trademark, and 103 | attribution notices from the Source form of the Work, 104 | excluding those notices that do not pertain to any part of 105 | the Derivative Works; and 106 | 107 | (d) If the Work includes a "NOTICE" text file as part of its 108 | distribution, then any Derivative Works that You distribute must 109 | include a readable copy of the attribution notices contained 110 | within such NOTICE file, excluding those notices that do not 111 | pertain to any part of the Derivative Works, in at least one 112 | of the following places: within a NOTICE text file distributed 113 | as part of the Derivative Works; within the Source form or 114 | documentation, if provided along with the Derivative Works; or, 115 | within a display generated by the Derivative Works, if and 116 | wherever such third-party notices normally appear. The contents 117 | of the NOTICE file are for informational purposes only and 118 | do not modify the License. You may add Your own attribution 119 | notices within Derivative Works that You distribute, alongside 120 | or as an addendum to the NOTICE text from the Work, provided 121 | that such additional attribution notices cannot be construed 122 | as modifying the License. 123 | 124 | You may add Your own copyright statement to Your modifications and 125 | may provide additional or different license terms and conditions 126 | for use, reproduction, or distribution of Your modifications, or 127 | for any such Derivative Works as a whole, provided Your use, 128 | reproduction, and distribution of the Work otherwise complies with 129 | the conditions stated in this License. 130 | 131 | 5. Submission of Contributions. Unless You explicitly state otherwise, 132 | any Contribution intentionally submitted for inclusion in the Work 133 | by You to the Licensor shall be under the terms and conditions of 134 | this License, without any additional terms or conditions. 135 | Notwithstanding the above, nothing herein shall supersede or modify 136 | the terms of any separate license agreement you may have executed 137 | with Licensor regarding such Contributions. 138 | 139 | 6. Trademarks. This License does not grant permission to use the trade 140 | names, trademarks, service marks, or product names of the Licensor, 141 | except as required for reasonable and customary use in describing the 142 | origin of the Work and reproducing the content of the NOTICE file. 143 | 144 | 7. Disclaimer of Warranty. Unless required by applicable law or 145 | agreed to in writing, Licensor provides the Work (and each 146 | Contributor provides its Contributions) on an "AS IS" BASIS, 147 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 148 | implied, including, without limitation, any warranties or conditions 149 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A 150 | PARTICULAR PURPOSE. You are solely responsible for determining the 151 | appropriateness of using or redistributing the Work and assume any 152 | risks associated with Your exercise of permissions under this License. 153 | 154 | 8. Limitation of Liability. In no event and under no legal theory, 155 | whether in tort (including negligence), contract, or otherwise, 156 | unless required by applicable law (such as deliberate and grossly 157 | negligent acts) or agreed to in writing, shall any Contributor be 158 | liable to You for damages, including any direct, indirect, special, 159 | incidental, or consequential damages of any character arising as a 160 | result of this License or out of the use or inability to use the 161 | Work (including but not limited to damages for loss of goodwill, 162 | work stoppage, computer failure or malfunction, or any and all 163 | other commercial damages or losses), even if such Contributor 164 | has been advised of the possibility of such damages. 165 | 166 | 9. Accepting Warranty or Additional Liability. While redistributing 167 | the Work or Derivative Works thereof, You may choose to offer, 168 | and charge a fee for, acceptance of support, warranty, indemnity, 169 | or other liability obligations and/or rights consistent with this 170 | License. However, in accepting such obligations, You may act only 171 | on Your own behalf and on Your sole responsibility, not on behalf 172 | of any other Contributor, and only if You agree to indemnify, 173 | defend, and hold each Contributor harmless for any liability 174 | incurred by, or claims asserted against, such Contributor by reason 175 | of your accepting any such warranty or additional liability. 176 | 177 | END OF TERMS AND CONDITIONS 178 | 179 | APPENDIX: How to apply the Apache License to your work. 180 | 181 | To apply the Apache License to your work, attach the following 182 | boilerplate notice, with the fields enclosed by brackets "[]" 183 | replaced with your own identifying information. (Don't include 184 | the brackets!) The text should be enclosed in the appropriate 185 | comment syntax for the file format. We also recommend that a 186 | file or class name and description of purpose be included on the 187 | same "printed page" as the copyright notice for easier 188 | identification within third-party archives. 189 | 190 | Copyright 2017-2023 Jeffrey T. Potts 191 | 192 | Licensed under the Apache License, Version 2.0 (the "License"); 193 | you may not use this file except in compliance with the License. 194 | You may obtain a copy of the License at 195 | 196 | http://www.apache.org/licenses/LICENSE-2.0 197 | 198 | Unless required by applicable law or agreed to in writing, software 199 | distributed under the License is distributed on an "AS IS" BASIS, 200 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 201 | See the License for the specific language governing permissions and 202 | limitations under the License. 203 | 204 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Alfresco Kafka Integration 2 | 3 | This is an Alfresco repository tier AMP that will publish events to an Apache 4 | Kafka topic when nodes are created, updated, or deleted. Events are also 5 | produced for permission changes, including when inheritance is enabled and 6 | disabled. 7 | 8 | Events are generated using an Alfresco behavior that is bound to various class 9 | policies such as: `onCreateNode`, `onUpdateProperties`, and `beforeDeleteNode`. 10 | 11 | ## Build 12 | 13 | This project uses the Alfresco Maven SDK to build. The output is an AMP that can 14 | be installed into your Alfresco WAR using the Alfresco Module Management Tool 15 | (MMT). 16 | 17 | ## Configure 18 | 19 | There are two configurable settings: 20 | 21 | * Topic: Set the topic that the events should be published to. (Default: alfresco-node-events) 22 | * Bootstrap Servers: Set the Kafka servers to publish to. (Default: kafka:9092). Here 'kafka' is the name of service. 23 | 24 | Both of these settings can be configured by setting the following in alfresco-global.properties: 25 | 26 | kafka.topic=alfresco-node-events 27 | kafka.server=kafka:9092 28 | 29 | See docker-compose.yml file for details. 30 | 31 | ## Example 32 | 33 | This section includes an example of the event JSON. The events are all the same format with the exception of the event 34 | type, which can be one of: 35 | 36 | * CREATE 37 | * UPDATE 38 | * DELETE 39 | * PING 40 | * GRANT 41 | * REVOKE 42 | * ENABLE_INHERIT 43 | * DISABLE_INHERIT 44 | 45 | Here is what an event looks like: 46 | 47 | { 48 | "nodeRef": "70c60aea-d390-4fc7-b836-210c2778035d", 49 | "eventType": "CREATE", 50 | "path": "/{http://www.alfresco.org/model/application/1.0}company_home/{http://www.alfresco.org/model/site/1.0}sites/{http://www.alfresco.org/model/content/1.0}jtp-test-site-1/{http://www.alfresco.org/model/content/1.0}documentLibrary/{http://www.alfresco.org/model/content/1.0}test2.txt", 51 | "created": 1567086666248, 52 | "modified": 1567086666248, 53 | "creator": "admin", 54 | "modifier": "admin", 55 | "mimetype": "text/plain", 56 | "contentType": "content", 57 | "siteId": "jtp-test-site-1", 58 | "size": 4, 59 | "parent": "244a089b-17ad-4a49-81f4-c8b17b7322a6", 60 | "permissions": { 61 | "permissions": [ 62 | { 63 | "authority": "GROUP_site_jtp-test-site-1_SiteConsumer", 64 | "authorityType": "GROUP", 65 | "permission": "SiteConsumer", 66 | "inherited": true 67 | }, 68 | { 69 | "authority": "GROUP_site_jtp-test-site-1_SiteCollaborator", 70 | "authorityType": "GROUP", 71 | "permission": "SiteCollaborator", 72 | "inherited": true 73 | }, 74 | { 75 | "authority": "GROUP_site_jtp-test-site-1_SiteContributor", 76 | "authorityType": "GROUP", 77 | "permission": "SiteContributor", 78 | "inherited": true 79 | }, 80 | { 81 | "authority": "GROUP_site_jtp-test-site-1_SiteManager", 82 | "authorityType": "GROUP", 83 | "permission": "SiteManager", 84 | "inherited": true 85 | } 86 | ], 87 | "inheritanceEnabled": true 88 | } 89 | } 90 | 91 | For folders, the size and mimetype are null and are not included in the JSON. 92 | 93 | { 94 | "nodeRef": "8d8396a1-b9f8-444d-b9ea-f3a1e6971285", 95 | "eventType": "UPDATE", 96 | "path": "/{http://www.alfresco.org/model/application/1.0}company_home/{http://www.alfresco.org/model/site/1.0}sites/{http://www.alfresco.org/model/content/1.0}jtp-test-site-1/{http://www.alfresco.org/model/content/1.0}documentLibrary/{http://www.alfresco.org/model/content/1.0}testfolder4", 97 | "created": 1567086551982, 98 | "modified": 1567088364629, 99 | "creator": "admin", 100 | "modifier": "admin", 101 | "contentType": "folder", 102 | "siteId": "jtp-test-site-1", 103 | "parent": "244a089b-17ad-4a49-81f4-c8b17b7322a6", 104 | "permissions": { 105 | "permissions": [ 106 | { 107 | "authority": "GROUP_site_jtp-test-site-1_SiteConsumer", 108 | "authorityType": "GROUP", 109 | "permission": "SiteConsumer", 110 | "inherited": true 111 | }, 112 | { 113 | "authority": "GROUP_site_jtp-test-site-1_SiteContributor", 114 | "authorityType": "GROUP", 115 | "permission": "SiteContributor", 116 | "inherited": true 117 | }, 118 | { 119 | "authority": "GROUP_site_jtp-test-site-1_SiteCollaborator", 120 | "authorityType": "GROUP", 121 | "permission": "SiteCollaborator", 122 | "inherited": true 123 | }, 124 | { 125 | "authority": "GROUP_site_jtp-test-site-1_SiteManager", 126 | "authorityType": "GROUP", 127 | "permission": "SiteManager", 128 | "inherited": true 129 | } 130 | ], 131 | "inheritanceEnabled": true 132 | }, 133 | "tags": [ 134 | "test1", 135 | "test2", 136 | "test3" 137 | ] 138 | } 139 | 140 | Permissions-related events are smaller. For GRANT, REVOKE, ENABLE_INHERIT, and 141 | DISABLE_INHERIT, the event contains only the node reference and the current 142 | access control list: 143 | 144 | { 145 | "nodeRef": "953e16c4-d1f7-421e-bbe1-4f1123429c2a", 146 | "eventType": "DISABLE_INHERIT", 147 | "permissions": { 148 | "permissions": [ 149 | { 150 | "authority": "GROUP_site_jtp-test-site-1_SiteManager", 151 | "authorityType": "GROUP", 152 | "permission": "SiteManager", 153 | "inherited": false 154 | }, 155 | { 156 | "authority": "tuser1", 157 | "authorityType": "USER", 158 | "permission": "SiteContributor", 159 | "inherited": false 160 | }, 161 | { 162 | "authority": "tuser3", 163 | "authorityType": "USER", 164 | "permission": "SiteContributor", 165 | "inherited": false 166 | } 167 | ], 168 | "inheritanceEnabled": false 169 | } 170 | } 171 | 172 | In the example above, inheritance was turned off for a folder, which left the 173 | object with only locally-set permissions. 174 | 175 | ## Running via docker 176 | 177 | 1- Launch containers using `./run.sh build_start` or `./run.bat build_start` and verify that it 178 | 179 | * Runs Alfresco Content Service (ACS) 180 | * (Optional) Runs Alfresco Share 181 | * Runs Alfresco Search Service (ASS) 182 | * Runs PostgreSQL database 183 | * Deploys the JAR assembled module 184 | * Runs Zookeeper 185 | * Runs Kafka 186 | 187 | Additionally, you can use `docker ps` command to checked whether all containers are up and running correctly. 188 | 189 | 2- If you want to watch the messages as they are sent to Kafka, then from $KAFKA_HOME, run: 190 | 191 | `bin/kafka-console-consumer.sh --bootstrap-server localhost:9093 --topic alfresco-node-events --from-beginning` 192 | 193 | For windows: 194 | 195 | `bin\windows\kafka-console-consumer.bat --bootstrap-server localhost:9093 --topic alfresco-node-events --from-beginning` 196 | 197 | ## Consuming Events 198 | 199 | For an example showing how to consume these events from a Spring Boot app, see 200 | [this project](https://github.com/jpotts/alfresco-kafka-listener-example) on 201 | GitHub. 202 | -------------------------------------------------------------------------------- /alfresco-kafka-model/.gitignore: -------------------------------------------------------------------------------- 1 | /target 2 | /.classpath 3 | /.project 4 | /.settings 5 | /*.log* 6 | /data/ 7 | /logs/ 8 | -------------------------------------------------------------------------------- /alfresco-kafka-model/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 4.0.0 6 | 7 | 8 | alfresco-kafka 9 | com.metaversant 10 | 0.0.3-SNAPSHOT 11 | 12 | 13 | alfresco-kafka-model 14 | jar 15 | -------------------------------------------------------------------------------- /alfresco-kafka-model/src/main/java/com/metaversant/kafka/model/NodeEvent.java: -------------------------------------------------------------------------------- 1 | package com.metaversant.kafka.model; 2 | 3 | import java.util.Date; 4 | import java.util.List; 5 | 6 | import com.fasterxml.jackson.annotation.JsonInclude; 7 | 8 | import lombok.AllArgsConstructor; 9 | import lombok.Builder; 10 | import lombok.Data; 11 | import lombok.NoArgsConstructor; 12 | 13 | 14 | /** 15 | * Created by jpotts, Metaversant on 6/9/17. 16 | */ 17 | @Data 18 | @Builder 19 | @AllArgsConstructor 20 | @NoArgsConstructor 21 | @JsonInclude(JsonInclude.Include.NON_NULL) 22 | public class NodeEvent { 23 | 24 | /** 25 | * The Enum EventType. 26 | */ 27 | public enum EventType { 28 | 29 | /** The create. */ 30 | CREATE, 31 | 32 | /** The update. */ 33 | UPDATE, 34 | 35 | /** The delete. */ 36 | DELETE, 37 | 38 | /** The ping. */ 39 | PING, 40 | 41 | /** The grant. */ 42 | GRANT, 43 | 44 | /** The revoke. */ 45 | REVOKE, 46 | 47 | /** The enable inherit. */ 48 | ENABLE_INHERIT, 49 | 50 | /** The disable inherit. */ 51 | DISABLE_INHERIT 52 | } 53 | 54 | /** The node ref. */ 55 | private String nodeRef; 56 | 57 | /** The event type. */ 58 | private NodeEvent.EventType eventType; 59 | 60 | /** The path. */ 61 | private String path; 62 | 63 | /** The created. */ 64 | private Date created; 65 | 66 | /** The modified. */ 67 | private Date modified; 68 | 69 | /** The creator. */ 70 | private String creator; 71 | 72 | /** The modifier. */ 73 | private String modifier; 74 | 75 | /** The mimetype. */ 76 | private String mimetype; 77 | 78 | /** The content type. */ 79 | private String contentType; 80 | 81 | /** The site id. */ 82 | private String siteId; 83 | 84 | /** The size. */ 85 | private Long size; 86 | 87 | /** The parent. */ 88 | private String parent; 89 | 90 | /** The authority. */ 91 | private String authority; 92 | 93 | /** The permission. */ 94 | private String permission; 95 | 96 | /** The permissions. */ 97 | private NodePermissions permissions; 98 | 99 | /** The tags. */ 100 | private List tags; 101 | } 102 | -------------------------------------------------------------------------------- /alfresco-kafka-model/src/main/java/com/metaversant/kafka/model/NodePermission.java: -------------------------------------------------------------------------------- 1 | package com.metaversant.kafka.model; 2 | 3 | import com.fasterxml.jackson.annotation.JsonInclude; 4 | 5 | import lombok.AllArgsConstructor; 6 | import lombok.Builder; 7 | import lombok.Data; 8 | import lombok.NoArgsConstructor; 9 | 10 | /** 11 | * Created by jpotts, Metaversant on 6/9/17. 12 | */ 13 | @Data 14 | @Builder 15 | @AllArgsConstructor 16 | @NoArgsConstructor 17 | @JsonInclude(JsonInclude.Include.NON_NULL) 18 | public class NodePermission { 19 | 20 | /** The authority. */ 21 | private String authority; 22 | 23 | /** The authority type. */ 24 | private String authorityType; 25 | 26 | /** The permission. */ 27 | private String permission; 28 | 29 | /** The is inherited. */ 30 | private boolean isInherited; 31 | } 32 | 33 | 34 | 35 | -------------------------------------------------------------------------------- /alfresco-kafka-model/src/main/java/com/metaversant/kafka/model/NodePermissions.java: -------------------------------------------------------------------------------- 1 | package com.metaversant.kafka.model; 2 | 3 | import java.util.Set; 4 | 5 | import com.fasterxml.jackson.annotation.JsonInclude; 6 | 7 | import lombok.AllArgsConstructor; 8 | import lombok.Builder; 9 | import lombok.Data; 10 | import lombok.NoArgsConstructor; 11 | 12 | /** 13 | * Created by jpotts, Metaversant on 6/9/17. 14 | */ 15 | @Data 16 | @Builder 17 | @AllArgsConstructor 18 | @NoArgsConstructor 19 | @JsonInclude(JsonInclude.Include.NON_NULL) 20 | public class NodePermissions { 21 | 22 | /** The permissions. */ 23 | private Set permissions; 24 | 25 | /** The is inheritance enabled. */ 26 | private boolean isInheritanceEnabled; 27 | } 28 | 29 | 30 | 31 | -------------------------------------------------------------------------------- /alfresco-kafka-repo/.gitignore: -------------------------------------------------------------------------------- 1 | /target 2 | /.classpath 3 | /.project 4 | /.settings 5 | /*.log* 6 | /data/ 7 | /logs/ 8 | -------------------------------------------------------------------------------- /alfresco-kafka-repo/README.md: -------------------------------------------------------------------------------- 1 | # Alfresco ACS JAR Module - SDK 4.1 2 | 3 | This is an ACS project for Alfresco SDK 4.1. 4 | 5 | Run with `./run.sh build_start` or `./run.bat build_start` and verify that it 6 | 7 | * Runs Alfresco Content Service (ACS) 8 | * (Optional) Runs Alfresco Share 9 | * Runs Alfresco Search Service (ASS) 10 | * Runs PostgreSQL database 11 | * Deploys the JAR assembled module 12 | * Runs Zookeeper 13 | * Runs Kafka 14 | 15 | All the services of the project are now run as docker containers. The run script offers the next tasks: 16 | 17 | * `build_start`. Build the whole project, recreate the ACS docker image, start the dockerised environment composed by ACS, Share (optional), ASS 18 | and PostgreSQL and tail the logs of all the containers. 19 | * `build_start_it_supported`. Build the whole project including dependencies required for IT execution, recreate the ACS docker image, start the dockerised environment 20 | composed by ACS, Share (optional), ASS and PostgreSQL and tail the logs of all the containers. 21 | * `start`. Start the dockerised environment without building the project and tail the logs of all the containers. 22 | * `stop`. Stop the dockerised environment. 23 | * `purge`. Stop the dockerised container and delete all the persistent data (docker volumes). 24 | * `tail`. Tail the logs of all the containers. 25 | * `reload_acs`. Build the ACS module, recreate the ACS docker image and restart the ACS container. 26 | * `build_test`. Build the whole project, recreate the ACS docker image, start the dockerised environment, execute the integration tests and stop 27 | the environment. 28 | * `test`. Execute the integration tests (the environment must be already started). 29 | -------------------------------------------------------------------------------- /alfresco-kafka-repo/docker/docker-compose.yml: -------------------------------------------------------------------------------- 1 | version: '3.4' 2 | services: 3 | 4 | #Optional service to launch share interface 5 | alfresco-kafka-repo-share: 6 | image: ${docker.share.image}:${alfresco.share.version} 7 | environment: 8 | REPO_HOST: alfresco-kafka-repo-acs 9 | REPO_PORT: 8080 10 | ports: 11 | - "${share.port}:8080" 12 | 13 | alfresco-kafka-repo-acs: 14 | image: alfresco-content-services-alfresco-kafka-repo:development 15 | build: 16 | dockerfile: ./Dockerfile 17 | context: ../../../target 18 | environment: 19 | CATALINA_OPTS: "-agentlib:jdwp=transport=dt_socket,server=y,suspend=n,address=0.0.0.0:8888" 20 | JAVA_OPTS: " 21 | -Dkafka.topic=alfresco-node-events 22 | -Dkafka.server=kafka:9092 23 | " 24 | ports: 25 | - "${acs.port}:8080" 26 | - "${acs.debug.port}:8888" 27 | volumes: 28 | - alfresco-kafka-repo-acs-volume:/usr/local/tomcat/alf_data 29 | - ../../../../logs/alfresco:/usr/local/tomcat/logs 30 | depends_on: 31 | - kafka 32 | - alfresco-kafka-repo-postgres 33 | 34 | alfresco-kafka-repo-postgres: 35 | image: postgres:11.7 36 | environment: 37 | POSTGRES_DB: alfresco 38 | POSTGRES_USER: alfresco 39 | POSTGRES_PASSWORD: alfresco 40 | command: postgres -c max_connections=300 -c log_min_messages=LOG 41 | ports: 42 | - "${postgres.port}:5432" 43 | volumes: 44 | - alfresco-kafka-repo-db-volume:/var/lib/postgresql/data 45 | 46 | alfresco-kafka-repo-ass: 47 | image: alfresco/alfresco-search-services:2.0.0.1 48 | environment: 49 | #Solr needs to know how to register itself with Alfresco 50 | - SOLR_ALFRESCO_HOST=alfresco-kafka-repo-acs 51 | - SOLR_ALFRESCO_PORT=8080 52 | #Alfresco needs to know how to call solr 53 | - SOLR_SOLR_HOST=alfresco-kafka-repo-ass 54 | - SOLR_SOLR_PORT=8983 55 | #Create the default alfresco and archive cores 56 | - SOLR_CREATE_ALFRESCO_DEFAULTS=alfresco,archive 57 | #HTTP by default 58 | - ALFRESCO_SECURE_COMMS=none 59 | ports: 60 | - "8983:8983" 61 | volumes: 62 | - alfresco-kafka-repo-ass-volume:/opt/alfresco-search-services/data 63 | 64 | zookeeper: 65 | image: bitnami/zookeeper:3.6.2 66 | environment: 67 | - ALLOW_ANONYMOUS_LOGIN=yes 68 | ports: 69 | - "2181:2181" 70 | volumes: 71 | - ../../../../data/alfresco-zk:/bitnami/zookeeper 72 | - ../../../../data/alfresco-zk-logs:/opt/bitnami/zookeeper/logs 73 | 74 | kafka: 75 | image: bitnami/kafka:2.6.0 76 | environment: 77 | KAFKA_ADVERTISED_LISTENERS: INSIDE://kafka:9092,OUTSIDE://localhost:9093 78 | KAFKA_LISTENER_SECURITY_PROTOCOL_MAP: INSIDE:PLAINTEXT,OUTSIDE:PLAINTEXT 79 | KAFKA_LISTENERS: INSIDE://0.0.0.0:9092,OUTSIDE://0.0.0.0:9093 80 | KAFKA_ZOOKEEPER_CONNECT: zookeeper:2181 81 | ALLOW_PLAINTEXT_LISTENER: "yes" 82 | KAFKA_INTER_BROKER_LISTENER_NAME: INSIDE 83 | ports: 84 | - "9092:9092" 85 | - "9093:9093" 86 | volumes: 87 | - ../../../../data/alfresco-kafka:/bitnami/kafka 88 | - ../../../../data/alfresco-kafka-logs:/opt/bitnami/kafka/logs 89 | depends_on: 90 | - zookeeper 91 | 92 | volumes: 93 | alfresco-kafka-repo-acs-volume: 94 | external: true 95 | alfresco-kafka-repo-db-volume: 96 | external: true 97 | alfresco-kafka-repo-ass-volume: 98 | external: true -------------------------------------------------------------------------------- /alfresco-kafka-repo/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 4.0.0 5 | 6 | 7 | alfresco-kafka 8 | com.metaversant 9 | 0.0.3-SNAPSHOT 10 | 11 | 12 | alfresco-kafka-repo 13 | alfresco-kafka-repo Platform/Repository JAR Module 14 | Platform/Repo JAR Module (to be included in the alfresco.war) 15 | jar 16 | 17 | 18 | 19 | com.metaversant 20 | alfresco-kafka-model 21 | 0.0.3-SNAPSHOT 22 | 23 | 24 | 25 | 26 | 27 | 28 | org.apache.maven.plugins 29 | maven-assembly-plugin 30 | 31 | 32 | 33 | -------------------------------------------------------------------------------- /alfresco-kafka-repo/src/main/assembly/amp.xml: -------------------------------------------------------------------------------- 1 | 5 | 6 | 18 | 19 | build-amp-file 20 | 21 | 22 | amp 23 | 24 | 25 | false 26 | 27 | 28 | 29 | 30 | src/main/resources/alfresco/module/${project.artifactId}/module.properties 31 | true 32 | 33 | 34 | 35 | src/main/assembly/file-mapping.properties 36 | false 37 | 38 | 39 | 40 | src/main/resources/alfresco/module/${project.artifactId}/log4j.properties 41 | false 42 | 43 | 44 | 45 | 46 | 47 | 48 | src/main/assembly/web 49 | web 50 | true 51 | 52 | README.md 53 | 54 | 55 | 56 | 57 | 60 | 61 | 62 | lib 63 | 64 | 65 | 66 | -------------------------------------------------------------------------------- /alfresco-kafka-repo/src/main/assembly/file-mapping.properties: -------------------------------------------------------------------------------- 1 | # Custom AMP to WAR location mappings 2 | 3 | # 4 | # The following property can be used to include the standard set of mappings. 5 | # The contents of this file will override any defaults. The default is 6 | # 'true', i.e. the default mappings will be augmented or modified by values in 7 | # this file. 8 | # 9 | # Default mappings are: 10 | # 11 | # /config=/WEB-INF/classes 12 | # /lib=/WEB-INF/lib 13 | # /licenses=/WEB-INF/licenses 14 | # /web/jsp=/jsp 15 | # /web/css=/css 16 | # /web/images=/images 17 | # /web/scripts=/scripts 18 | # /web/php=/php 19 | # 20 | include.default=true 21 | 22 | # 23 | # Custom mappings. If 'include.default' is false, then this is the complete set. 24 | # Map /web to / in AMP so we can override things like favicon.ico 25 | # 26 | /web=/ 27 | 28 | -------------------------------------------------------------------------------- /alfresco-kafka-repo/src/main/assembly/web/README.md: -------------------------------------------------------------------------------- 1 | # Web resources that should override out-of-the-box files 2 | 3 | Put here any web resources that should override out-of-the-box 4 | web resources, such as favicon.ico. They will then end up in the 5 | */web* directory in the AMP, and applied to the WAR, and override 6 | any existing web resources in the Alfresco.WAR. 7 | 8 | **Note**. Module dependency needs to be set to amp for the web resources to be applied by MMT: 9 | 10 | ` 11 | 12 | ${project.groupId} 13 | some-platform-jar 14 | ${project.version} 15 | amp 16 | 17 | ` 18 | 19 | **Important**. New web resources should not be located here, but instead 20 | in the usual place in the *src/main/resources/META-INF/resources* directory. 21 | 22 | 23 | -------------------------------------------------------------------------------- /alfresco-kafka-repo/src/main/docker/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM ${docker.acs.image}:${alfresco.platform.version} 2 | 3 | ARG TOMCAT_DIR=/usr/local/tomcat 4 | 5 | USER root 6 | 7 | # Copy Dockerfile to avoid an error if no JARs exist 8 | COPY Dockerfile extensions/*.jar $TOMCAT_DIR/webapps/alfresco/WEB-INF/lib/ 9 | 10 | # Copy Dockerfile to avoid an error if no AMPs exist 11 | COPY Dockerfile extensions/*.amp $TOMCAT_DIR/amps/ 12 | RUN java -jar $TOMCAT_DIR/alfresco-mmt/alfresco-mmt*.jar install \ 13 | $TOMCAT_DIR/amps $TOMCAT_DIR/webapps/alfresco -directory -nobackup -force 14 | 15 | COPY alfresco-global.properties $TOMCAT_DIR/shared/classes/alfresco-global.properties 16 | COPY dev-log4j.properties $TOMCAT_DIR/shared/classes/alfresco/extension 17 | COPY disable-webscript-caching-context.xml $TOMCAT_DIR/shared/classes/alfresco/extension 18 | 19 | COPY hotswap-agent.properties $TOMCAT_DIR/webapps/alfresco/WEB-INF/classes 20 | 21 | # Copy Dockerfile to avoid an error if no license file exists 22 | COPY Dockerfile license/*.* $TOMCAT_DIR/webapps/alfresco/WEB-INF/classes/alfresco/extension/license/ 23 | 24 | USER ${USERNAME} -------------------------------------------------------------------------------- /alfresco-kafka-repo/src/main/docker/alfresco-global.properties: -------------------------------------------------------------------------------- 1 | # Licensed to the Apache Software Foundation (ASF) under one or more 2 | # contributor license agreements. See the NOTICE file distributed with 3 | # this work for additional information regarding copyright ownership. 4 | # The ASF licenses this file to You under the Apache License, Version 2.0 5 | # (the "License"); you may not use this file except in compliance with 6 | # the License. You may obtain a copy of the License at 7 | # 8 | # http://www.apache.org/licenses/LICENSE-2.0 9 | # 10 | # Unless required by applicable law or agreed to in writing, software 11 | # distributed under the License is distributed on an "AS IS" BASIS, 12 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | # See the License for the specific language governing permissions and 14 | # limitations under the License. 15 | # RUN TIME PROPERTIES 16 | # ------------------- 17 | 18 | # 19 | # Alfresco configuration for running locally with PostgreSQL Database 20 | # 21 | # Configuration when running Tomcat embedded from Maven. 22 | # Property values from the POM but it can also be edited here. 23 | # 24 | 25 | # Alfresco Repo Webapp (alfresco.war) context, ports etc 26 | alfresco.context=alfresco 27 | alfresco.host=localhost 28 | alfresco.port=8080 29 | alfresco.protocol=http 30 | 31 | # Alfresco Share Webapp (share.war) context, ports etc 32 | share.context=share 33 | share.host=localhost 34 | share.port=8180 35 | share.protocol=http 36 | 37 | # Don't try and recover any index 38 | index.recovery.mode=NONE 39 | 40 | # These jobs seem to require Lucene (Unsupported Operation with Solr) so we disable them / set to future date 41 | # See https://forums.alfresco.com/en/viewtopic.php?f=52&t=41597 42 | # If you want to enable them (and so full WQS functionality), please also set index.subsystem.name=lucene 43 | wcmqs.dynamicCollectionProcessor.schedule=0 30 2 * * ? 2060 44 | wcmqs.feedbackProcessor.schedule=0 40 2 * * ? 2060 45 | wcmqs.publishQueueProcessor.schedule=0 50 2 * * ? 2060 46 | 47 | # Fail or not when there are node integrity checker errors 48 | integrity.failOnError=true 49 | 50 | # Alfresco Repository PostgreSQL Database configuration. 51 | # The PostgreSQL Driver is brought in via the tomcat7-maven-plugin as a dependency. 52 | db.driver=org.postgresql.Driver 53 | 54 | # This Alfresco Platform Configuration file should be used for custom properties that are introduced by this module. 55 | # Define default values for all properties here. 56 | # System Administrators can override these values in environment specific configurations in 57 | # alfresco/tomcat/shared/classes/alfresco-global.properties. 58 | # 59 | index.subsystem.name=solr6 60 | solr.host=alfresco-kafka-repo-ass 61 | solr.port=8983 62 | solr.secureComms=none 63 | 64 | db.username=alfresco 65 | db.password=alfresco 66 | db.pool.initial=10 67 | db.pool.max=100 68 | 69 | db.url=jdbc:postgresql://alfresco-kafka-repo-postgres:5432/alfresco 70 | 71 | # File servers related properties 72 | # For local runs we disable CIFS and FTP 73 | cifs.enabled=false 74 | ftp.enabled=false 75 | 76 | csrf.filter.enabled=false 77 | 78 | # Embedded broker without persistence 79 | messaging.broker.url=vm://localhost?broker.persistent=false 80 | 81 | # Disable ATS 82 | transform.service.enabled=false 83 | local.transform.service.enabled=false 84 | legacy.transform.service.enabled=false -------------------------------------------------------------------------------- /alfresco-kafka-repo/src/main/docker/dev-log4j.properties: -------------------------------------------------------------------------------- 1 | # Set root logger level to error 2 | log4j.rootLogger=error,Console,File 3 | 4 | 5 | # All outputs currently set to be a ConsoleAppender. 6 | log4j.appender.Console=org.apache.log4j.ConsoleAppender 7 | log4j.appender.Console.layout=org.apache.log4j.PatternLayout 8 | 9 | # use log4j NDC to replace %x with tenant domain / username 10 | log4j.appender.Console.layout.ConversionPattern=%d{ISO8601} %x %-5p [%c{3}] [%t] %m%n 11 | #log4j.appender.Console.layout.ConversionPattern=%d{ABSOLUTE} %-5p [%c] %m%n 12 | 13 | log4j.appender.File=org.apache.log4j.DailyRollingFileAppender 14 | log4j.appender.File.File=/usr/local/tomcat/logs/alfresco.log 15 | log4j.appender.File.Append=true 16 | log4j.appender.File.DatePattern='.'yyyy-MM-dd 17 | log4j.appender.File.layout=org.apache.log4j.PatternLayout 18 | log4j.appender.File.layout.ConversionPattern=%d{yyyy-MM-dd} %d{ABSOLUTE} %-5p [%c] [%t] %m%n 19 | 20 | #log4j.appender.file=org.apache.log4j.FileAppender 21 | #log4j.appender.file.File=hibernate.log 22 | #log4j.appender.file.layout=org.apache.log4j.PatternLayout 23 | #log4j.appender.file.layout.ConversionPattern=%d{ABSOLUTE} %5p %c{1}:%L - %m%n 24 | 25 | 26 | # Commented-in loggers will be exposed as JMX MBeans (refer to org.alfresco.repo.admin.Log4JHierarchyInit) 27 | # Hence, generally useful loggers should be listed with at least ERROR level to allow simple runtime 28 | # control of the level via a suitable JMX Console. Also, any other loggers can be added transiently via 29 | # Log4j addLoggerMBean as long as the logger exists and has been loaded. 30 | 31 | # Hibernate 32 | log4j.logger.org.hibernate=error 33 | log4j.logger.org.hibernate.util.JDBCExceptionReporter=fatal 34 | log4j.logger.org.hibernate.event.def.AbstractFlushingEventListener=fatal 35 | log4j.logger.org.hibernate.type=warn 36 | log4j.logger.org.hibernate.cfg.SettingsFactory=warn 37 | 38 | # Spring 39 | log4j.logger.org.springframework=warn 40 | # Turn off Spring remoting warnings that should really be info or debug. 41 | log4j.logger.org.springframework.remoting.support=error 42 | log4j.logger.org.springframework.util=error 43 | 44 | # Axis/WSS4J 45 | log4j.logger.org.apache.axis=info 46 | log4j.logger.org.apache.ws=info 47 | 48 | # CXF 49 | log4j.logger.org.apache.cxf=error 50 | 51 | # MyFaces 52 | log4j.logger.org.apache.myfaces.util.DebugUtils=info 53 | log4j.logger.org.apache.myfaces.el.VariableResolverImpl=error 54 | log4j.logger.org.apache.myfaces.application.jsp.JspViewHandlerImpl=error 55 | log4j.logger.org.apache.myfaces.taglib=error 56 | 57 | # OpenOfficeConnection 58 | log4j.logger.net.sf.jooreports.openoffice.connection=fatal 59 | 60 | # log prepared statement cache activity log4j.logger.org.hibernate.ps.PreparedStatementCache=info 61 | 62 | # Alfresco 63 | log4j.logger.org.alfresco=error 64 | log4j.logger.org.alfresco.repo.admin=info 65 | log4j.logger.org.alfresco.repo.transaction=warn 66 | log4j.logger.org.alfresco.repo.cache.TransactionalCache=warn 67 | log4j.logger.org.alfresco.repo.model.filefolder=warn 68 | log4j.logger.org.alfresco.repo.tenant=info 69 | log4j.logger.org.alfresco.config=warn 70 | log4j.logger.org.alfresco.config.JndiObjectFactoryBean=warn 71 | log4j.logger.org.alfresco.config.JBossEnabledWebApplicationContext=warn 72 | log4j.logger.org.alfresco.repo.management.subsystems=warn 73 | log4j.logger.org.alfresco.repo.management.subsystems.ChildApplicationContextFactory=info 74 | log4j.logger.org.alfresco.repo.management.subsystems.ChildApplicationContextFactory$ChildApplicationContext=warn 75 | log4j.logger.org.alfresco.repo.security.sync=info 76 | log4j.logger.org.alfresco.repo.security.person=info 77 | 78 | log4j.logger.org.alfresco.sample=info 79 | log4j.logger.org.alfresco.web=info 80 | #log4j.logger.org.alfresco.web.app.AlfrescoNavigationHandler=debug 81 | #log4j.logger.org.alfresco.web.ui.repo.component.UIActions=debug 82 | #log4j.logger.org.alfresco.web.ui.repo.tag.PageTag=debug 83 | #log4j.logger.org.alfresco.web.bean.clipboard=debug 84 | log4j.logger.org.alfresco.service.descriptor.DescriptorService=info 85 | #log4j.logger.org.alfresco.web.page=debug 86 | 87 | log4j.logger.org.alfresco.repo.importer.ImporterBootstrap=error 88 | #log4j.logger.org.alfresco.repo.importer.ImporterBootstrap=info 89 | 90 | log4j.logger.org.alfresco.repo.admin.patch.PatchExecuter=info 91 | log4j.logger.org.alfresco.repo.domain.patch.ibatis.PatchDAOImpl=info 92 | 93 | # Specific patches 94 | log4j.logger.org.alfresco.repo.admin.patch.impl.DeploymentMigrationPatch=info 95 | log4j.logger.org.alfresco.repo.version.VersionMigrator=info 96 | 97 | log4j.logger.org.alfresco.repo.module.ModuleServiceImpl=info 98 | log4j.logger.org.alfresco.repo.domain.schema.SchemaBootstrap=info 99 | log4j.logger.org.alfresco.repo.admin.ConfigurationChecker=info 100 | log4j.logger.org.alfresco.repo.node.index.AbstractReindexComponent=warn 101 | log4j.logger.org.alfresco.repo.node.index.IndexTransactionTracker=warn 102 | log4j.logger.org.alfresco.repo.node.index.FullIndexRecoveryComponent=info 103 | log4j.logger.org.alfresco.util.OpenOfficeConnectionTester=info 104 | log4j.logger.org.alfresco.repo.node.db.hibernate.HibernateNodeDaoServiceImpl=warn 105 | log4j.logger.org.alfresco.repo.domain.hibernate.DirtySessionMethodInterceptor=warn 106 | log4j.logger.org.alfresco.repo.transaction.RetryingTransactionHelper=warn 107 | log4j.logger.org.alfresco.util.transaction.SpringAwareUserTransaction.trace=warn 108 | log4j.logger.org.alfresco.util.AbstractTriggerBean=warn 109 | log4j.logger.org.alfresco.enterprise.repo.cluster=info 110 | log4j.logger.org.alfresco.repo.version.Version2ServiceImpl=warn 111 | 112 | #log4j.logger.org.alfresco.web.app.DebugPhaseListener=debug 113 | log4j.logger.org.alfresco.repo.node.db.NodeStringLengthWorker=info 114 | 115 | log4j.logger.org.alfresco.repo.workflow=info 116 | 117 | # CIFS server debugging 118 | log4j.logger.org.alfresco.smb.protocol=error 119 | #log4j.logger.org.alfresco.smb.protocol.auth=debug 120 | #log4j.logger.org.alfresco.acegi=debug 121 | 122 | # FTP server debugging 123 | log4j.logger.org.alfresco.ftp.protocol=error 124 | #log4j.logger.org.alfresco.ftp.server=debug 125 | 126 | # WebDAV debugging 127 | #log4j.logger.org.alfresco.webdav.protocol=debug 128 | log4j.logger.org.alfresco.webdav.protocol=info 129 | 130 | # NTLM servlet filters 131 | #log4j.logger.org.alfresco.web.app.servlet.NTLMAuthenticationFilter=debug 132 | #log4j.logger.org.alfresco.repo.webdav.auth.NTLMAuthenticationFilter=debug 133 | 134 | # Kerberos servlet filters 135 | #log4j.logger.org.alfresco.web.app.servlet.KerberosAuthenticationFilter=debug 136 | #log4j.logger.org.alfresco.repo.webdav.auth.KerberosAuthenticationFilter=debug 137 | 138 | # File servers 139 | log4j.logger.org.alfresco.fileserver=warn 140 | 141 | # Repo filesystem debug logging 142 | #log4j.logger.org.alfresco.filesys.repo.ContentDiskDriver=debug 143 | 144 | # Integrity message threshold - if 'failOnViolation' is off, then WARNINGS are generated 145 | log4j.logger.org.alfresco.repo.node.integrity=ERROR 146 | 147 | # Indexer debugging 148 | log4j.logger.org.alfresco.repo.search.Indexer=error 149 | #log4j.logger.org.alfresco.repo.search.Indexer=debug 150 | 151 | log4j.logger.org.alfresco.repo.search.impl.lucene.index=error 152 | log4j.logger.org.alfresco.repo.search.impl.lucene.fts.FullTextSearchIndexerImpl=warn 153 | #log4j.logger.org.alfresco.repo.search.impl.lucene.index=DEBUG 154 | 155 | # Audit debugging 156 | # log4j.logger.org.alfresco.repo.audit=DEBUG 157 | # log4j.logger.org.alfresco.repo.audit.model=DEBUG 158 | 159 | # Property sheet and modelling debugging 160 | # change to error to hide the warnings about missing properties and associations 161 | log4j.logger.alfresco.missingProperties=warn 162 | 163 | # Dictionary/Model debugging 164 | log4j.logger.org.alfresco.repo.dictionary=warn 165 | log4j.logger.org.alfresco.repo.dictionary.types.period=warn 166 | 167 | # Virtualization Server Registry 168 | log4j.logger.org.alfresco.mbeans.VirtServerRegistry=error 169 | 170 | # Spring context runtime property setter 171 | log4j.logger.org.alfresco.util.RuntimeSystemPropertiesSetter=info 172 | 173 | # Debugging options for clustering 174 | log4j.logger.org.alfresco.repo.content.ReplicatingContentStore=error 175 | log4j.logger.org.alfresco.repo.content.replication=error 176 | 177 | #log4j.logger.org.alfresco.repo.deploy.DeploymentServiceImpl=debug 178 | 179 | # Activity service 180 | log4j.logger.org.alfresco.repo.activities=warn 181 | 182 | # User usage tracking 183 | log4j.logger.org.alfresco.repo.usage=info 184 | 185 | # Sharepoint 186 | log4j.logger.org.alfresco.module.vti=info 187 | 188 | # Forms Engine 189 | log4j.logger.org.alfresco.web.config.forms=info 190 | log4j.logger.org.alfresco.web.scripts.forms=info 191 | 192 | # CMIS 193 | log4j.logger.org.alfresco.opencmis=error 194 | log4j.logger.org.alfresco.opencmis.AlfrescoCmisServiceInterceptor=error 195 | log4j.logger.org.alfresco.cmis=error 196 | log4j.logger.org.alfresco.cmis.dictionary=warn 197 | log4j.logger.org.apache.chemistry.opencmis=info 198 | log4j.logger.org.apache.chemistry.opencmis.server.impl.browser.CmisBrowserBindingServlet=OFF 199 | log4j.logger.org.apache.chemistry.opencmis.server.impl.atompub.CmisAtomPubServlet=OFF 200 | 201 | # IMAP 202 | log4j.logger.org.alfresco.repo.imap=info 203 | 204 | # JBPM 205 | # Note: non-fatal errors (eg. logged during job execution) should be handled by Alfresco's retrying transaction handler 206 | log4j.logger.org.jbpm.graph.def.GraphElement=fatal 207 | 208 | #log4j.logger.org.alfresco.repo.googledocs=debug 209 | 210 | 211 | # Web Framework 212 | log4j.logger.org.springframework.extensions.webscripts=info 213 | log4j.logger.org.springframework.extensions.webscripts.ScriptLogger=warn 214 | log4j.logger.org.springframework.extensions.webscripts.ScriptDebugger=off 215 | 216 | # Repository 217 | log4j.logger.org.alfresco.repo.web.scripts=warn 218 | log4j.logger.org.alfresco.repo.web.scripts.BaseWebScriptTest=info 219 | log4j.logger.org.alfresco.repo.web.scripts.AlfrescoRhinoScriptDebugger=off 220 | log4j.logger.org.alfresco.repo.jscript=error 221 | log4j.logger.org.alfresco.repo.jscript.ScriptLogger=debug 222 | log4j.logger.org.alfresco.repo.cmis.rest.CMISTest=info 223 | 224 | log4j.logger.org.alfresco.repo.domain.schema.script.ScriptBundleExecutorImpl=off 225 | log4j.logger.org.alfresco.repo.domain.schema.script.ScriptExecutorImpl=info 226 | 227 | log4j.logger.org.alfresco.repo.search.impl.solr.facet.SolrFacetServiceImpl=info 228 | 229 | # Bulk Filesystem Import Tool 230 | log4j.logger.org.alfresco.repo.bulkimport=warn 231 | 232 | # Freemarker 233 | # Note the freemarker.runtime logger is used to log non-fatal errors that are handled by Alfresco's retrying transaction handler 234 | log4j.logger.freemarker.runtime= 235 | 236 | # Metadata extraction 237 | log4j.logger.org.alfresco.repo.content.metadata.AbstractMappingMetadataExtracter=info 238 | 239 | 240 | # Reduces PDFont error level due to ALF-7105 241 | log4j.logger.org.apache.pdfbox.pdmodel.font.PDSimpleFont=fatal 242 | log4j.logger.org.apache.pdfbox.pdmodel.font.PDFont=fatal 243 | log4j.logger.org.apache.pdfbox.pdmodel.font.PDCIDFont=fatal 244 | 245 | # no index support 246 | log4j.logger.org.alfresco.repo.search.impl.noindex.NoIndexIndexer=fatal 247 | log4j.logger.org.alfresco.repo.search.impl.noindex.NoIndexSearchService=fatal 248 | 249 | # lucene index warnings 250 | log4j.logger.org.alfresco.repo.search.impl.lucene.index.IndexInfo=warn 251 | 252 | # Warn about RMI socket bind retries. 253 | log4j.logger.org.alfresco.util.remote.server.socket.HostConfigurableSocketFactory=warn 254 | 255 | log4j.logger.org.alfresco.repo.usage.RepoUsageMonitor=info 256 | 257 | # Authorization 258 | log4j.logger.org.alfresco.enterprise.repo.authorization.AuthorizationService=info 259 | log4j.logger.org.alfresco.enterprise.repo.authorization.AuthorizationsConsistencyMonitor=warn 260 | 261 | #----------------------------------------------------------------------- 262 | # Platform module logging 263 | #----------------------------------------------------------------------- 264 | log4j.logger.com.metaversant.kafka=debug,alfkafka 265 | 266 | #Solr specific logs 267 | log4j.logger.org.alfresco.solr.query.AbstractQParser=DEBUG,alfkafka 268 | log4j.logger.org.alfresco.repo.search.impl.solr.SolrQueryHTTPClient=DEBUG,alfkafka 269 | 270 | #Kafka logs 271 | log4j.logger.org.apache.kafka.clients.producer.KafkaProducer=debug,alfkafka 272 | log4j.logger.org.apache.kafka.clients.producer.ProducerRecord=debug,alfkafka 273 | 274 | log4j.appender.alfkafka=org.apache.log4j.DailyRollingFileAppender 275 | log4j.appender.alfkafka.File=/usr/local/tomcat/logs/alfresco-kafka.log 276 | log4j.appender.alfkafka.Append=true 277 | log4j.appender.alfkafka.DatePattern='.'yyyy-MM-dd 278 | log4j.appender.alfkafka.layout=org.apache.log4j.PatternLayout 279 | log4j.appender.alfkafka.layout.ConversionPattern=%d{yyyy-MM-dd} %d{ABSOLUTE} %-5p [%c] [%t] %m%n 280 | -------------------------------------------------------------------------------- /alfresco-kafka-repo/src/main/docker/disable-webscript-caching-context.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 19 | 20 | 31 | 32 | 33 | javascript 34 | 35 | 36 | js 37 | 38 | 39 | 40 | false 41 | 42 | 43 | 44 | 45 | true 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | ${spaces.store} 56 | 57 | 58 | ${spaces.company_home.childname} 59 | 60 | 61 | 62 | 63 | 64 | -------------------------------------------------------------------------------- /alfresco-kafka-repo/src/main/docker/hotswap-agent.properties: -------------------------------------------------------------------------------- 1 | # Enable hotswap so that changes in this module will be automatically reloaded 2 | # Watch for changed class files on watchResources path and reload class definition in the running application. 3 | autoHotswap=true 4 | #autoHotswap.port=8000 5 | 6 | # Add a directory prior to application classpath (load classes and resources). 7 | # 8 | # This may be useful for example in multi module maven project to load class changes from upstream project 9 | # classes. Set extraClasspath to upstream project compiler output and .class file will have precedence to 10 | # classes from built JAR file. 11 | # i.e. monitor /target/classes 12 | # should work with extraClasspath=${project.build.outputDirectory} 13 | # If not try 14 | extraClasspath=/usr/local/tomcat/hotswap-agent 15 | 16 | # Comma separated list of disabled plugins 17 | # Use plugin name - e.g. 18 | # Hotswapper, AnonymousClassPatch, WatchResources, Hibernate, Spring, Jersey2, Jetty, Tomcat, 19 | # ZK, Logback, JSF, Seam, ELResolver, OsgiEquinox, Proxy, WebObjects, Weld, JBossModules, Resteasy, Gae 20 | disabledPlugins=Hibernate,Spring 21 | 22 | # Add a directory prior to webapp path (load webapp resources). 23 | # 24 | # Load web application resources (such as HTML, JSP, CSS, ...) from this directory prior to default processing. 25 | # Use this setting to set to serve resources from source directory directly (e.g. src/main/webapp). 26 | extraWebappContext=/usr/local/tomcat/hotswap-agent/alfresco-kafka-repo/target/classes/META-INF/resources; 27 | 28 | # Load static web resources from different directory. 29 | # 30 | # This setting is dependent on application server plugin(Jetty, Tomcat, JBoss, ...) 31 | webappDir=/usr/local/tomcat/hotswap-agent/alfresco-kafka-repo/target/classes/META-INF/resources; 32 | 33 | # Watch for changes in a directory (resources only). 34 | # 35 | # Similar to extraClasspath this property adds classpath when searching for resources (not classes). 36 | # While extra classpath just modifies the classloader, this setting does nothing until the resource 37 | # is really changed. 38 | # 39 | # Sometimes it is not possible to point extraClasspath to your i.e. src/main/resources, because there are multiple 40 | # replacements of resources in a building step (maven filtering resource option). 41 | # This setting will leave i.e. src/target/classes as default source for resources, but after the resource is modified 42 | # in src/main/resources, the new changed resource is served instead. 43 | # watchResources= 44 | 45 | LOGGER.org.hotswap.agent=DEBUG 46 | #LOGGER.org.hotswap.agent.plugin=TRACE 47 | #LOGGER.org.hotswap.agent.watch=TRACE 48 | #LOGGER.org.hotswap.agent.command=TRACE -------------------------------------------------------------------------------- /alfresco-kafka-repo/src/main/docker/license/README.md: -------------------------------------------------------------------------------- 1 | # Enterprise License location 2 | 3 | Put the Alfresco Enterprise license file in this directory. 4 | It will then be copied into the ACS container in the 5 | $TOMCAT_DIR/WEB-INF/classes/alfresco/extension/license directory. 6 | 7 | -------------------------------------------------------------------------------- /alfresco-kafka-repo/src/main/java/com/metaversant/kafka/behavior/GenerateNodeEvent.java: -------------------------------------------------------------------------------- 1 | package com.metaversant.kafka.behavior; 2 | 3 | import java.io.Serializable; 4 | import java.util.Map; 5 | 6 | import org.alfresco.model.ContentModel; 7 | import org.alfresco.repo.node.NodeServicePolicies; 8 | import org.alfresco.repo.policy.Behaviour; 9 | import org.alfresco.repo.policy.JavaBehaviour; 10 | import org.alfresco.repo.policy.PolicyComponent; 11 | import org.alfresco.service.cmr.repository.ChildAssociationRef; 12 | import org.alfresco.service.cmr.repository.NodeRef; 13 | import org.alfresco.service.cmr.repository.NodeService; 14 | import org.alfresco.service.namespace.QName; 15 | import org.apache.log4j.Logger; 16 | 17 | import com.metaversant.kafka.model.NodeEvent; 18 | import com.metaversant.kafka.service.MessageService; 19 | import com.metaversant.kafka.transform.NodeRefToNodeEvent; 20 | import com.metaversant.kafka.transform.NodeRefToNodePermissions; 21 | 22 | /** 23 | * Created by jpotts, Metaversant on 6/9/17. 24 | */ 25 | public class GenerateNodeEvent implements NodeServicePolicies.BeforeDeleteNodePolicy, 26 | NodeServicePolicies.OnCreateNodePolicy, NodeServicePolicies.OnUpdatePropertiesPolicy { 27 | 28 | /** The Constant LOGGER. */ 29 | private static final Logger LOGGER = Logger.getLogger(GenerateNodeEvent.class); 30 | 31 | ///////////////////// Dependencies [Start] //////////////// 32 | /** The node service. */ 33 | private NodeService nodeService; 34 | 35 | /** The policy component. */ 36 | private PolicyComponent policyComponent; 37 | 38 | /** The message service. */ 39 | private MessageService messageService; 40 | 41 | /** The node transformer. */ 42 | private NodeRefToNodeEvent nodeTransformer; 43 | 44 | /** The node permissions transformer. */ 45 | private NodeRefToNodePermissions nodePermissionsTransformer; 46 | ///////////////////// Dependencies [End] ////////////////// 47 | 48 | ///////////////////// Behaviours [Start] ////////////////// 49 | /** The on create node. */ 50 | private Behaviour onCreateNode; 51 | 52 | /** The before delete node. */ 53 | private Behaviour beforeDeleteNode; 54 | 55 | /** The on update properties. */ 56 | private Behaviour onUpdateProperties; 57 | ///////////////////// Behaviours [End] ////////////////// 58 | 59 | /** 60 | * Inits the. 61 | */ 62 | public void init() { 63 | 64 | if (LOGGER.isDebugEnabled()) { 65 | LOGGER.debug("Initializing GenerateNodeEvent behaviors"); 66 | } 67 | 68 | // Create behaviours 69 | this.onCreateNode = new JavaBehaviour(this, "onCreateNode", Behaviour.NotificationFrequency.TRANSACTION_COMMIT); 70 | this.beforeDeleteNode = new JavaBehaviour(this, "beforeDeleteNode", Behaviour.NotificationFrequency.FIRST_EVENT); 71 | this.onUpdateProperties = new JavaBehaviour(this, "onUpdateProperties", Behaviour.NotificationFrequency.TRANSACTION_COMMIT); 72 | 73 | // Bind behaviours to node policies 74 | this.policyComponent.bindClassBehaviour( 75 | NodeServicePolicies.OnCreateNodePolicy.QNAME, 76 | ContentModel.TYPE_CMOBJECT, 77 | this.onCreateNode); 78 | 79 | this.policyComponent.bindClassBehaviour( 80 | NodeServicePolicies.BeforeDeleteNodePolicy.QNAME, 81 | ContentModel.TYPE_CMOBJECT, 82 | this.beforeDeleteNode); 83 | 84 | this.policyComponent.bindClassBehaviour( 85 | NodeServicePolicies.OnUpdatePropertiesPolicy.QNAME, 86 | ContentModel.TYPE_CMOBJECT, 87 | this.onUpdateProperties); 88 | 89 | } 90 | 91 | /** 92 | * On create node. 93 | * 94 | * @param childAssocRef the child assoc ref 95 | */ 96 | @Override 97 | public void onCreateNode(final ChildAssociationRef childAssocRef) { 98 | if (LOGGER.isDebugEnabled()) { 99 | LOGGER.debug("Inside onCreateNode"); 100 | } 101 | final NodeRef nodeRef = childAssocRef.getChildRef(); 102 | if (nodeService.exists(nodeRef)) { 103 | final NodeEvent nodeEvent = nodeTransformer.transform(nodeRef); 104 | nodeEvent.setEventType(NodeEvent.EventType.CREATE); 105 | nodeEvent.setPermissions(nodePermissionsTransformer.transform(nodeRef)); 106 | messageService.publish(nodeEvent); 107 | } 108 | } 109 | 110 | /** 111 | * Before delete node. 112 | * 113 | * @param nodeRef the node ref 114 | */ 115 | @Override 116 | public void beforeDeleteNode(final NodeRef nodeRef) { 117 | if (LOGGER.isDebugEnabled()) { 118 | LOGGER.debug("Inside onDeleteNode"); 119 | } 120 | if (nodeService.exists(nodeRef)) { 121 | final NodeEvent nodeEvent = nodeTransformer.transform(nodeRef); 122 | nodeEvent.setEventType(NodeEvent.EventType.DELETE); 123 | nodeEvent.setPermissions(nodePermissionsTransformer.transform(nodeRef)); 124 | messageService.publish(nodeEvent); 125 | } 126 | } 127 | 128 | /** 129 | * On update properties. 130 | * 131 | * @param nodeRef the node ref 132 | * @param beforeProps the before props 133 | * @param afterProps the after props 134 | */ 135 | @Override 136 | public void onUpdateProperties(final NodeRef nodeRef, final Map beforeProps, 137 | final Map afterProps) { 138 | if (LOGGER.isDebugEnabled()) { 139 | LOGGER.debug("Inside onUpdateProperties"); 140 | } 141 | if (nodeService.exists(nodeRef)) { 142 | final NodeEvent nodeEvent = nodeTransformer.transform(nodeRef); 143 | nodeEvent.setEventType(NodeEvent.EventType.UPDATE); 144 | nodeEvent.setPermissions(nodePermissionsTransformer.transform(nodeRef)); 145 | messageService.publish(nodeEvent); 146 | } 147 | } 148 | 149 | /** 150 | * Sets the node service. 151 | * 152 | * @param nodeService the new node service 153 | */ 154 | public void setNodeService(final NodeService nodeService) { 155 | this.nodeService = nodeService; 156 | } 157 | 158 | /** 159 | * Sets the policy component. 160 | * 161 | * @param policyComponent the new policy component 162 | */ 163 | public void setPolicyComponent(final PolicyComponent policyComponent) { 164 | this.policyComponent = policyComponent; 165 | } 166 | 167 | /** 168 | * Sets the message service. 169 | * 170 | * @param messageService the new message service 171 | */ 172 | public void setMessageService(final MessageService messageService) { 173 | this.messageService = messageService; 174 | } 175 | 176 | /** 177 | * Sets the node transformer. 178 | * 179 | * @param nodeTransformer the new node transformer 180 | */ 181 | public void setNodeTransformer(final NodeRefToNodeEvent nodeTransformer) { 182 | this.nodeTransformer = nodeTransformer; 183 | } 184 | 185 | /** 186 | * Sets the node permissions transformer. 187 | * 188 | * @param nodePermissionsTransformer the new node permissions transformer 189 | */ 190 | public void setNodePermissionsTransformer(final NodeRefToNodePermissions nodePermissionsTransformer) { 191 | this.nodePermissionsTransformer = nodePermissionsTransformer; 192 | } 193 | } 194 | -------------------------------------------------------------------------------- /alfresco-kafka-repo/src/main/java/com/metaversant/kafka/behavior/GenerateNodePermissionEvent.java: -------------------------------------------------------------------------------- 1 | package com.metaversant.kafka.behavior; 2 | 3 | import org.alfresco.model.ContentModel; 4 | import org.alfresco.repo.policy.Behaviour; 5 | import org.alfresco.repo.policy.JavaBehaviour; 6 | import org.alfresco.repo.policy.PolicyComponent; 7 | import org.alfresco.repo.security.permissions.PermissionServicePolicies; 8 | import org.alfresco.service.cmr.repository.NodeRef; 9 | import org.apache.log4j.Logger; 10 | 11 | import com.metaversant.kafka.model.NodeEvent; 12 | import com.metaversant.kafka.service.MessageService; 13 | import com.metaversant.kafka.transform.NodeRefToNodePermissions; 14 | 15 | 16 | /** 17 | * Created by jpotts, Metaversant on 8/28/19. 18 | */ 19 | public class GenerateNodePermissionEvent 20 | implements PermissionServicePolicies.OnGrantLocalPermission, PermissionServicePolicies.OnRevokeLocalPermission, 21 | PermissionServicePolicies.OnInheritPermissionsDisabled, PermissionServicePolicies.OnInheritPermissionsEnabled { 22 | 23 | /** The LOGGER. */ 24 | private static final Logger LOGGER = Logger.getLogger(GenerateNodePermissionEvent.class); 25 | 26 | ///////////////////// Dependencies [Start] //////////////// 27 | /** The policy component. */ 28 | private PolicyComponent policyComponent; 29 | 30 | /** The message service. */ 31 | private MessageService messageService; 32 | 33 | /** The node permissions transformer. */ 34 | private NodeRefToNodePermissions nodePermissionsTransformer; 35 | ///////////////////// Dependencies [End] ////////////////// 36 | 37 | ///////////////////// Behaviours [Start] ////////////////// 38 | /** The on grant local permission. */ 39 | private Behaviour onGrantLocalPermission; 40 | 41 | /** The on revoke local permission. */ 42 | private Behaviour onRevokeLocalPermission; 43 | 44 | /** The on inherit permissions enabled. */ 45 | private Behaviour onInheritPermissionsEnabled; 46 | 47 | /** The on inherit permissions disabled. */ 48 | private Behaviour onInheritPermissionsDisabled; 49 | ///////////////////// Behaviours [End] ////////////////// 50 | 51 | /** 52 | * Inits the. 53 | */ 54 | public void init() { 55 | 56 | if (LOGGER.isDebugEnabled()) { 57 | LOGGER.debug("Initializing GenerateNodePermissionEvent behaviors"); 58 | } 59 | 60 | // Create behaviours 61 | this.onGrantLocalPermission = new JavaBehaviour(this, "onGrantLocalPermission", Behaviour.NotificationFrequency.EVERY_EVENT); 62 | this.onRevokeLocalPermission = new JavaBehaviour(this, "onRevokeLocalPermission", Behaviour.NotificationFrequency.EVERY_EVENT); 63 | this.onInheritPermissionsEnabled = new JavaBehaviour(this, "onInheritPermissionsEnabled", Behaviour.NotificationFrequency.EVERY_EVENT); 64 | this.onInheritPermissionsDisabled = new JavaBehaviour(this, "onInheritPermissionsDisabled", Behaviour.NotificationFrequency.EVERY_EVENT); 65 | 66 | // Bind behaviours to node policies 67 | this.policyComponent.bindClassBehaviour( 68 | PermissionServicePolicies.OnGrantLocalPermission.QNAME, 69 | ContentModel.TYPE_CMOBJECT, 70 | this.onGrantLocalPermission); 71 | 72 | this.policyComponent.bindClassBehaviour( 73 | PermissionServicePolicies.OnRevokeLocalPermission.QNAME, 74 | ContentModel.TYPE_CMOBJECT, 75 | this.onRevokeLocalPermission); 76 | 77 | this.policyComponent.bindClassBehaviour( 78 | PermissionServicePolicies.OnInheritPermissionsEnabled.QNAME, 79 | ContentModel.TYPE_BASE, 80 | this.onInheritPermissionsEnabled); 81 | 82 | this.policyComponent.bindClassBehaviour( 83 | PermissionServicePolicies.OnInheritPermissionsDisabled.QNAME, 84 | ContentModel.TYPE_BASE, 85 | this.onInheritPermissionsDisabled); 86 | 87 | } 88 | 89 | /** 90 | * On grant local permission. 91 | * 92 | * @param nodeRef the node ref 93 | * @param authority the authority 94 | * @param permission the permission 95 | */ 96 | @Override 97 | public void onGrantLocalPermission(final NodeRef nodeRef, final String authority, final String permission) { 98 | if (LOGGER.isDebugEnabled()) { 99 | LOGGER.debug("inside onGrantLocalPermission"); 100 | } 101 | final NodeEvent nodeEvent = NodeEvent.builder() 102 | .eventType(NodeEvent.EventType.GRANT) 103 | .nodeRef(nodeRef.getId()) 104 | .authority(authority) 105 | .permission(permission) 106 | .build(); 107 | nodeEvent.setPermissions(nodePermissionsTransformer.transform(nodeRef)); 108 | messageService.publish(nodeEvent); 109 | } 110 | 111 | /** 112 | * On revoke local permission. 113 | * 114 | * @param nodeRef the node ref 115 | * @param authority the authority 116 | * @param permission the permission 117 | */ 118 | @Override 119 | public void onRevokeLocalPermission(final NodeRef nodeRef, final String authority, final String permission) { 120 | if (LOGGER.isDebugEnabled()) { 121 | LOGGER.debug("inside onRevokeLocalPermission"); 122 | } 123 | final NodeEvent nodeEvent = NodeEvent.builder() 124 | .eventType(NodeEvent.EventType.REVOKE) 125 | .nodeRef(nodeRef.getId()) 126 | .authority(authority) 127 | .permission(permission) 128 | .build(); 129 | nodeEvent.setPermissions(nodePermissionsTransformer.transform(nodeRef)); 130 | messageService.publish(nodeEvent); 131 | } 132 | 133 | /** 134 | * On inherit permissions disabled. 135 | * 136 | * @param nodeRef the node ref 137 | * @param async the async 138 | */ 139 | @Override 140 | public void onInheritPermissionsDisabled(final NodeRef nodeRef, final boolean async) { 141 | if (LOGGER.isDebugEnabled()) { 142 | LOGGER.debug("inside onInheritPermissionsDisabled"); 143 | } 144 | final NodeEvent nodeEvent = NodeEvent.builder() 145 | .eventType(NodeEvent.EventType.DISABLE_INHERIT) 146 | .nodeRef(nodeRef.getId()) 147 | .build(); 148 | nodeEvent.setPermissions(nodePermissionsTransformer.transform(nodeRef)); 149 | messageService.publish(nodeEvent); 150 | } 151 | 152 | /** 153 | * On inherit permissions enabled. 154 | * 155 | * @param nodeRef the node ref 156 | */ 157 | @Override 158 | public void onInheritPermissionsEnabled(final NodeRef nodeRef) { 159 | if (LOGGER.isDebugEnabled()) { 160 | LOGGER.debug("inside onInheritPermissionsEnabled"); 161 | } 162 | final NodeEvent nodeEvent = NodeEvent.builder() 163 | .eventType(NodeEvent.EventType.ENABLE_INHERIT) 164 | .nodeRef(nodeRef.getId()) 165 | .build(); 166 | nodeEvent.setPermissions(nodePermissionsTransformer.transform(nodeRef)); 167 | messageService.publish(nodeEvent); 168 | } 169 | 170 | /** 171 | * Sets the policy component. 172 | * 173 | * @param policyComponent the new policy component 174 | */ 175 | public void setPolicyComponent(final PolicyComponent policyComponent) { 176 | this.policyComponent = policyComponent; 177 | } 178 | 179 | /** 180 | * Sets the message service. 181 | * 182 | * @param messageService the new message service 183 | */ 184 | public void setMessageService(final MessageService messageService) { 185 | this.messageService = messageService; 186 | } 187 | 188 | /** 189 | * Sets the node permissions transformer. 190 | * 191 | * @param nodePermissionsTransformer the new node permissions transformer 192 | */ 193 | public void setNodePermissionsTransformer(final NodeRefToNodePermissions nodePermissionsTransformer) { 194 | this.nodePermissionsTransformer = nodePermissionsTransformer; 195 | } 196 | } 197 | -------------------------------------------------------------------------------- /alfresco-kafka-repo/src/main/java/com/metaversant/kafka/service/MessageService.java: -------------------------------------------------------------------------------- 1 | package com.metaversant.kafka.service; 2 | 3 | import java.util.Properties; 4 | 5 | import javax.annotation.PostConstruct; 6 | 7 | import org.alfresco.service.cmr.repository.NodeRef; 8 | import org.apache.kafka.clients.producer.KafkaProducer; 9 | import org.apache.kafka.clients.producer.ProducerRecord; 10 | import org.apache.log4j.Logger; 11 | 12 | import com.fasterxml.jackson.core.JsonProcessingException; 13 | import com.fasterxml.jackson.databind.ObjectMapper; 14 | import com.metaversant.kafka.model.NodeEvent; 15 | import com.metaversant.kafka.transform.NodeRefToNodeEvent; 16 | import com.metaversant.kafka.transform.NodeRefToNodePermissions; 17 | 18 | /** 19 | * Created by jpotts, Metaversant on 6/9/17. 20 | */ 21 | public class MessageService { 22 | 23 | /** The LOGGER. */ 24 | private static final Logger LOGGER = Logger.getLogger(MessageService.class); 25 | 26 | ///////////////////// Dependencies [Start] //////////////// 27 | /** The node transformer. */ 28 | private NodeRefToNodeEvent nodeTransformer; 29 | 30 | /** The node permissions transformer. */ 31 | private NodeRefToNodePermissions nodePermissionsTransformer; 32 | ///////////////////// Dependencies [End] //////////////// 33 | 34 | ///////////////////// Settings [Start] //////////////// 35 | /** The topic. */ 36 | private String topic = "alfresco-node-events"; 37 | 38 | /** The bootstrap servers. */ 39 | private String bootstrapServers = "localhost:9092"; 40 | 41 | /** The producer. */ 42 | private KafkaProducer producer; 43 | 44 | /** The mapper. */ 45 | private ObjectMapper mapper = new ObjectMapper(); 46 | ///////////////////// Settings [End] //////////////// 47 | 48 | /** 49 | * Inits the. 50 | */ 51 | @PostConstruct 52 | public void init() { 53 | if (LOGGER.isDebugEnabled()) { 54 | LOGGER.debug("init invoked, topic: " + this.topic + " | bootstrapServers: " + this.bootstrapServers); 55 | } 56 | producer = new KafkaProducer<>(createProducerConfig()); 57 | } 58 | 59 | /** 60 | * Ping. 61 | * 62 | * @param nodeRef the node ref 63 | */ 64 | public void ping(final NodeRef nodeRef) { 65 | if (LOGGER.isDebugEnabled()) { 66 | LOGGER.debug("ping invoked for nodeRef: " + nodeRef); 67 | } 68 | final NodeEvent nodeEvent = nodeTransformer.transform(nodeRef); 69 | nodeEvent.setEventType(NodeEvent.EventType.PING); 70 | nodeEvent.setPermissions(nodePermissionsTransformer.transform(nodeRef)); 71 | publish(nodeEvent); 72 | } 73 | 74 | /** 75 | * Publish. 76 | * 77 | * @param event the event 78 | */ 79 | public void publish(final NodeEvent event) { 80 | if (LOGGER.isDebugEnabled()) { 81 | LOGGER.debug("publish invoked for event: " + event); 82 | } 83 | try { 84 | final String message = mapper.writeValueAsString(event); 85 | if (LOGGER.isDebugEnabled()) { 86 | LOGGER.debug("Publishing message: " + message); 87 | } 88 | if (message != null && message.length() != 0) { 89 | producer.send(new ProducerRecord(topic, message)); 90 | } 91 | } catch (JsonProcessingException jpe) { 92 | LOGGER.error("Error occurred while publishing the event", jpe); 93 | } 94 | } 95 | 96 | /** 97 | * Creates the producer config. 98 | * 99 | * @return the properties 100 | */ 101 | private Properties createProducerConfig() { 102 | final Properties props = new Properties(); 103 | props.put("bootstrap.servers", bootstrapServers); 104 | props.put("acks", "all"); 105 | props.put("retries", 0); 106 | props.put("batch.size", 16384); 107 | props.put("linger.ms", 1); 108 | props.put("buffer.memory", 33554432); 109 | props.put("key.serializer", "org.apache.kafka.common.serialization.StringSerializer"); 110 | props.put("value.serializer", "org.apache.kafka.common.serialization.StringSerializer"); 111 | if (LOGGER.isDebugEnabled()) { 112 | LOGGER.debug("Props for initialization: " + props); 113 | } 114 | return props; 115 | } 116 | 117 | /** 118 | * Sets the topic. 119 | * 120 | * @param topic the new topic 121 | */ 122 | public void setTopic(final String topic) { 123 | this.topic = topic; 124 | } 125 | 126 | /** 127 | * Sets the bootstrap servers. 128 | * 129 | * @param bootstrapServers the new bootstrap servers 130 | */ 131 | public void setBootstrapServers(final String bootstrapServers) { 132 | this.bootstrapServers = bootstrapServers; 133 | } 134 | 135 | /** 136 | * Sets the node transformer. 137 | * 138 | * @param nodeTransformer the new node transformer 139 | */ 140 | public void setNodeTransformer(final NodeRefToNodeEvent nodeTransformer) { 141 | this.nodeTransformer = nodeTransformer; 142 | } 143 | 144 | /** 145 | * Sets the node permissions transformer. 146 | * 147 | * @param nodePermissionsTransformer the new node permissions transformer 148 | */ 149 | public void setNodePermissionsTransformer(final NodeRefToNodePermissions nodePermissionsTransformer) { 150 | this.nodePermissionsTransformer = nodePermissionsTransformer; 151 | } 152 | } 153 | -------------------------------------------------------------------------------- /alfresco-kafka-repo/src/main/java/com/metaversant/kafka/service/MessageServiceScopedObject.java: -------------------------------------------------------------------------------- 1 | package com.metaversant.kafka.service; 2 | 3 | import org.alfresco.repo.jscript.BaseScopableProcessorExtension; 4 | import org.alfresco.repo.jscript.ScriptNode; 5 | import org.apache.log4j.Logger; 6 | 7 | /** 8 | * Created by jpotts, Metaversant on 6/9/17. 9 | */ 10 | public class MessageServiceScopedObject extends BaseScopableProcessorExtension { 11 | 12 | /** The LOGGER. */ 13 | private static final Logger LOGGER = Logger.getLogger(MessageServiceScopedObject.class); 14 | 15 | ///////////////////// Dependencies [Start] //////////////// 16 | /** The message service. */ 17 | private MessageService messageService; 18 | ///////////////////// Dependencies [End] //////////////// 19 | 20 | /** 21 | * Ping. 22 | * 23 | * @param scriptNode the script node 24 | */ 25 | public void ping(final ScriptNode scriptNode) { 26 | if (LOGGER.isDebugEnabled()) { 27 | LOGGER.debug("ping invoked for scriptNode: " + scriptNode); 28 | } 29 | messageService.ping(scriptNode.getNodeRef()); 30 | } 31 | 32 | /** 33 | * Sets the message service. 34 | * 35 | * @param messageService the new message service 36 | */ 37 | public void setMessageService(final MessageService messageService) { 38 | this.messageService = messageService; 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /alfresco-kafka-repo/src/main/java/com/metaversant/kafka/transform/NodeRefToNodeEvent.java: -------------------------------------------------------------------------------- 1 | package com.metaversant.kafka.transform; 2 | 3 | import static org.alfresco.model.ContentModel.PROP_CONTENT; 4 | import static org.alfresco.model.ContentModel.PROP_CREATED; 5 | import static org.alfresco.model.ContentModel.PROP_CREATOR; 6 | import static org.alfresco.model.ContentModel.PROP_MODIFIED; 7 | import static org.alfresco.model.ContentModel.PROP_MODIFIER; 8 | 9 | import java.io.Serializable; 10 | import java.util.Date; 11 | import java.util.List; 12 | import java.util.Map; 13 | 14 | import org.alfresco.service.cmr.repository.ContentReader; 15 | import org.alfresco.service.cmr.repository.ContentService; 16 | import org.alfresco.service.cmr.repository.NodeRef; 17 | import org.alfresco.service.cmr.repository.NodeService; 18 | import org.alfresco.service.cmr.site.SiteInfo; 19 | import org.alfresco.service.cmr.site.SiteService; 20 | import org.alfresco.service.cmr.tagging.TaggingService; 21 | import org.alfresco.service.namespace.QName; 22 | import org.apache.log4j.Logger; 23 | 24 | import com.metaversant.kafka.model.NodeEvent; 25 | 26 | /** 27 | * Created by jpotts, Metaversant on 6/9/17. 28 | */ 29 | public class NodeRefToNodeEvent { 30 | 31 | /** The LOGGER. */ 32 | private static final Logger LOGGER = Logger.getLogger(NodeRefToNodeEvent.class); 33 | 34 | ///////////////////// Dependencies [Start] //////////////// 35 | /** The content service. */ 36 | private ContentService contentService; 37 | 38 | /** The node service. */ 39 | private NodeService nodeService; 40 | 41 | /** The site service. */ 42 | private SiteService siteService; 43 | 44 | /** The tagging service. */ 45 | private TaggingService taggingService; 46 | ///////////////////// Dependencies [End] //////////////// 47 | 48 | /** 49 | * Transform. 50 | * 51 | * @param nodeRef the node ref 52 | * @return the node event 53 | */ 54 | public NodeEvent transform(final NodeRef nodeRef) { 55 | if (LOGGER.isDebugEnabled()) { 56 | LOGGER.debug("NodeEvent transform invoked for nodeRef: " + nodeRef); 57 | } 58 | final Map props = nodeService.getProperties(nodeRef); 59 | final NodeEvent nodeEvent = NodeEvent.builder() 60 | .nodeRef(nodeRef.getId()) 61 | .creator((String) props.get(PROP_CREATOR)) 62 | .created((Date) props.get(PROP_CREATED)) 63 | .modifier((String) props.get(PROP_MODIFIER)) 64 | .modified((Date) props.get(PROP_MODIFIED)) 65 | .path(nodeService.getPath(nodeRef).toString()) 66 | .parent(nodeService.getPrimaryParent(nodeRef).getParentRef().getId()) 67 | .contentType(nodeService.getType(nodeRef).toPrefixString()) 68 | .build(); 69 | 70 | // If this node is in a site, add the site ID to the event 71 | final SiteInfo siteInfo = siteService.getSite(nodeRef); 72 | if (siteInfo != null) { 73 | nodeEvent.setSiteId(siteInfo.getShortName()); 74 | } 75 | 76 | // Retrieve the tags from the node and add them to the event 77 | final List tags = taggingService.getTags(nodeRef); 78 | nodeEvent.setTags(tags); 79 | 80 | // If this is a content object, set the mimetype and size props 81 | if (props.get(PROP_CONTENT) != null) { 82 | ContentReader reader = null; 83 | try { 84 | reader = contentService.getReader(nodeRef, PROP_CONTENT); 85 | } catch (Exception excp) { 86 | LOGGER.error("Error reading content: " + excp.getMessage(), excp); 87 | } 88 | 89 | if (reader != null) { 90 | nodeEvent.setMimetype(reader.getMimetype()); 91 | nodeEvent.setSize(reader.getContentData().getSize()); 92 | } 93 | } 94 | return nodeEvent; 95 | } 96 | 97 | /** 98 | * Sets the content service. 99 | * 100 | * @param contentService the new content service 101 | */ 102 | public void setContentService(final ContentService contentService) { 103 | this.contentService = contentService; 104 | } 105 | 106 | /** 107 | * Sets the node service. 108 | * 109 | * @param nodeService the new node service 110 | */ 111 | public void setNodeService(final NodeService nodeService) { 112 | this.nodeService = nodeService; 113 | } 114 | 115 | /** 116 | * Sets the site service. 117 | * 118 | * @param siteService the new site service 119 | */ 120 | public void setSiteService(final SiteService siteService) { 121 | this.siteService = siteService; 122 | } 123 | 124 | /** 125 | * Sets the tagging service. 126 | * 127 | * @param taggingService the new tagging service 128 | */ 129 | public void setTaggingService(final TaggingService taggingService) { 130 | this.taggingService = taggingService; 131 | } 132 | } 133 | -------------------------------------------------------------------------------- /alfresco-kafka-repo/src/main/java/com/metaversant/kafka/transform/NodeRefToNodePermissions.java: -------------------------------------------------------------------------------- 1 | package com.metaversant.kafka.transform; 2 | 3 | import java.util.HashSet; 4 | import java.util.Set; 5 | 6 | import org.alfresco.service.cmr.repository.NodeRef; 7 | import org.alfresco.service.cmr.security.AccessPermission; 8 | import org.alfresco.service.cmr.security.PermissionService; 9 | import org.apache.log4j.Logger; 10 | 11 | import com.metaversant.kafka.model.NodePermission; 12 | import com.metaversant.kafka.model.NodePermissions; 13 | 14 | /** 15 | * Created by jpotts, Metaversant on 8/28/19. 16 | */ 17 | public class NodeRefToNodePermissions { 18 | 19 | /** The LOGGER. */ 20 | private static final Logger LOGGER = Logger.getLogger(NodeRefToNodePermissions.class); 21 | 22 | ///////////////////// Dependencies [Start] //////////////// 23 | /** The permission service. */ 24 | private PermissionService permissionService; 25 | ///////////////////// Dependencies [End] //////////////// 26 | 27 | /** 28 | * Transform. 29 | * 30 | * @param nodeRef the node ref 31 | * @return the node permissions 32 | */ 33 | public NodePermissions transform(final NodeRef nodeRef) { 34 | if (LOGGER.isDebugEnabled()) { 35 | LOGGER.debug("NodePermissions transform invoked for nodeRef: " + nodeRef); 36 | } 37 | // determine if the node inherits its ACL from the parent 38 | final boolean inherits = permissionService.getInheritParentPermissions(nodeRef); 39 | final NodePermissions perms = new NodePermissions(); 40 | perms.setInheritanceEnabled(inherits); 41 | 42 | // convert the Alfresco object into our own 43 | final Set permissionSet = permissionService.getAllSetPermissions(nodeRef); 44 | final Set set = new HashSet<>(); 45 | for (final AccessPermission perm : permissionSet) { 46 | final NodePermission nodePerm = NodePermission.builder() 47 | .authority(perm.getAuthority()) 48 | .authorityType(perm.getAuthorityType().name()) 49 | .permission(perm.getPermission()) 50 | .isInherited(perm.isInherited()) 51 | .build(); 52 | set.add(nodePerm); 53 | } 54 | perms.setPermissions(set); 55 | return perms; 56 | } 57 | 58 | /** 59 | * Sets the permission service. 60 | * 61 | * @param permissionService the new permission service 62 | */ 63 | public void setPermissionService(final PermissionService permissionService) { 64 | this.permissionService = permissionService; 65 | } 66 | } 67 | -------------------------------------------------------------------------------- /alfresco-kafka-repo/src/main/resources/META-INF/resources/test.html: -------------------------------------------------------------------------------- 1 | Test 123 -------------------------------------------------------------------------------- /alfresco-kafka-repo/src/main/resources/alfresco/extension/templates/webscripts/com/metaversant/alfresco/kafka/ping.get.desc.xml: -------------------------------------------------------------------------------- 1 | 2 | Alfresco Kafka Ping 3 | Pings a node to cause it to get added to the stream. 4 | /metaversant/kafka/ping?nodeRef={nodeRef}&recurse={recurse} 5 | Metaversant 6 | extension 7 | admin 8 | -------------------------------------------------------------------------------- /alfresco-kafka-repo/src/main/resources/alfresco/extension/templates/webscripts/com/metaversant/alfresco/kafka/ping.get.js: -------------------------------------------------------------------------------- 1 | function main() { 2 | var recurse = false; 3 | if (args.recurse != null && args.recurse === 'true') { 4 | recurse = true; 5 | } 6 | if (args.nodeRef == null || args.nodeRef.length == 0) { 7 | logger.log("NodeRef arg not set"); 8 | status.code = 400; 9 | status.message = "NodeRef has not been provided"; 10 | status.redirect = true; 11 | } else { 12 | logger.log("Getting current node"); 13 | var curNode = search.findNode(args.nodeRef); 14 | if (curNode == null) { 15 | logger.log("Node not found"); 16 | status.code = 404; 17 | status.message = "No node found for nodeRef: " + args.nodeRef; 18 | status.redirect = true; 19 | } else { 20 | messageService.ping(curNode); 21 | model.nodeRef = args.nodeRef; 22 | } 23 | if (recurse && curNode.hasChildren) { 24 | logger.log("Recursing into list of children"); 25 | handleChildren(curNode.children); 26 | } 27 | } 28 | } 29 | 30 | function handleChildren(children) { 31 | for (var i = 0; i < children.length; i++) { 32 | logger.log("Pinging " + children[i].nodeRef.toString()); 33 | messageService.ping(children[i]); 34 | if (children[i].hasChildren) { 35 | handleChildren(children[i].children); 36 | } 37 | } 38 | } 39 | 40 | main(); 41 | -------------------------------------------------------------------------------- /alfresco-kafka-repo/src/main/resources/alfresco/extension/templates/webscripts/com/metaversant/alfresco/kafka/ping.get.json.ftl: -------------------------------------------------------------------------------- 1 | { 2 | "nodeRef": "${nodeRef}" 3 | } -------------------------------------------------------------------------------- /alfresco-kafka-repo/src/main/resources/alfresco/module/alfresco-kafka-repo/alfresco-global.properties: -------------------------------------------------------------------------------- 1 | ## This Alfresco Platform Configuration file should be used for custom properties that are introduced by this module. 2 | ## Define default values for all properties here. 3 | ## System Administrators can override these values in environment specific configurations in 4 | ## alfresco/tomcat/shared/classes/alfresco-global.properties. 5 | ## 6 | 7 | kafka.topic=alfresco-node-events 8 | kafka.server=localhost:9092 -------------------------------------------------------------------------------- /alfresco-kafka-repo/src/main/resources/alfresco/module/alfresco-kafka-repo/context/bootstrap-context.xml: -------------------------------------------------------------------------------- 1 | 2 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /alfresco-kafka-repo/src/main/resources/alfresco/module/alfresco-kafka-repo/context/service-context.xml: -------------------------------------------------------------------------------- 1 | 2 | 18 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | -------------------------------------------------------------------------------- /alfresco-kafka-repo/src/main/resources/alfresco/module/alfresco-kafka-repo/log4j.properties: -------------------------------------------------------------------------------- 1 | # Add here module-specific custom log4j.properties configuration -------------------------------------------------------------------------------- /alfresco-kafka-repo/src/main/resources/alfresco/module/alfresco-kafka-repo/module-context.xml: -------------------------------------------------------------------------------- 1 | 2 | 18 | 19 | 23 | 24 | 25 | 28 | 29 | 30 | 31 | 32 | -------------------------------------------------------------------------------- /alfresco-kafka-repo/src/main/resources/alfresco/module/alfresco-kafka-repo/module.properties: -------------------------------------------------------------------------------- 1 | # Licensed to the Apache Software Foundation (ASF) under one or more 2 | # contributor license agreements. See the NOTICE file distributed with 3 | # this work for additional information regarding copyright ownership. 4 | # The ASF licenses this file to You under the Apache License, Version 2.0 5 | # (the "License"); you may not use this file except in compliance with 6 | # the License. You may obtain a copy of the License at 7 | # 8 | # http://www.apache.org/licenses/LICENSE-2.0 9 | # 10 | # Unless required by applicable law or agreed to in writing, software 11 | # distributed under the License is distributed on an "AS IS" BASIS, 12 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | # See the License for the specific language governing permissions and 14 | # limitations under the License. 15 | 16 | 17 | 18 | # SDK Sample module 19 | 20 | # ==== Beginning of Alfresco required/optional properties ====== # 21 | # NB: These properties are filtered at build time by Maven, single 22 | # sourcing from POM properties 23 | module.id=${project.artifactId} 24 | #module.aliases=myModule-123, my-module 25 | module.title=${project.name} 26 | module.description=${project.description} 27 | module.version=${project.version} 28 | 29 | # The following optional properties can be used to prevent the module from being added 30 | # to inappropriate versions of the WAR file. 31 | # module.repo.version.min=2.0 32 | # module.repo.version.max=2.1 33 | 34 | # FIXME: This dependencies should come out of mvn dependencies on amp 35 | 36 | # The following describe dependencies on other modules 37 | # Depends on net.sf.myproject.module.SupportModuleA version ${version} or later 38 | # module.depends.net.sf.myproject.module.SupportModuleA=${version}-* 39 | # Depends on net.sf.myproject.module.SupportModuleA version ${version} to 2.0 40 | # module.depends.net.sf.myproject.module.SupportModuleB=${version}-2.0 41 | # Depends on net.sf.myproject.module.SupportModuleC - any version 42 | # module.depends.net.sf.myproject.module.SupportModuleB=* 43 | 44 | 45 | # ==== End of Alfresco required/optional properties ======= # 46 | 47 | 48 | # ==== Beginning of module required properties/optional ====== # -------------------------------------------------------------------------------- /alfresco-kafka-repo/src/main/resources/examples/enable_inherit.json: -------------------------------------------------------------------------------- 1 | { 2 | "nodeRef": "2b69af4a-9b11-486b-b192-0e676b6b1c8c", 3 | "eventType": "ENABLE_INHERIT", 4 | "permissions": { 5 | "permissions": [ 6 | { 7 | "authority": "GROUP_site_jtp-test-site-1_SiteManager", 8 | "authorityType": "GROUP", 9 | "permission": "SiteManager", 10 | "inherited": true 11 | }, 12 | { 13 | "authority": "GROUP_site_jtp-test-site-1_SiteConsumer", 14 | "authorityType": "GROUP", 15 | "permission": "SiteConsumer", 16 | "inherited": true 17 | }, 18 | { 19 | "authority": "GROUP_site_jtp-test-site-1_SiteContributor", 20 | "authorityType": "GROUP", 21 | "permission": "SiteContributor", 22 | "inherited": true 23 | }, 24 | { 25 | "authority": "GROUP_site_jtp-test-site-1_SiteManager", 26 | "authorityType": "GROUP", 27 | "permission": "SiteManager", 28 | "inherited": false 29 | }, 30 | { 31 | "authority": "GROUP_site_jtp-test-site-1_SiteCollaborator", 32 | "authorityType": "GROUP", 33 | "permission": "SiteCollaborator", 34 | "inherited": true 35 | } 36 | ], 37 | "inheritanceEnabled": true 38 | } 39 | } -------------------------------------------------------------------------------- /alfresco-kafka-repo/src/main/resources/examples/revoke.json: -------------------------------------------------------------------------------- 1 | { 2 | "nodeRef": "2b69af4a-9b11-486b-b192-0e676b6b1c8c", 3 | "eventType": "REVOKE", 4 | "authority": "GROUP_site_jtp-test-site-1_SiteManager", 5 | "permission": "SiteManager", 6 | "permissions": { 7 | "permissions": [ 8 | { 9 | "authority": "GROUP_site_jtp-test-site-1_SiteManager", 10 | "authorityType": "GROUP", 11 | "permission": "SiteManager", 12 | "inherited": true 13 | }, 14 | { 15 | "authority": "GROUP_site_jtp-test-site-1_SiteConsumer", 16 | "authorityType": "GROUP", 17 | "permission": "SiteConsumer", 18 | "inherited": true 19 | }, 20 | { 21 | "authority": "GROUP_site_jtp-test-site-1_SiteContributor", 22 | "authorityType": "GROUP", 23 | "permission": "SiteContributor", 24 | "inherited": true 25 | }, 26 | { 27 | "authority": "GROUP_site_jtp-test-site-1_SiteCollaborator", 28 | "authorityType": "GROUP", 29 | "permission": "SiteCollaborator", 30 | "inherited": true 31 | } 32 | ], 33 | "inheritanceEnabled": true 34 | } 35 | } -------------------------------------------------------------------------------- /alfresco-kafka-repo/src/main/resources/examples/update.json: -------------------------------------------------------------------------------- 1 | { 2 | "nodeRef": "8fe391f7-374d-4d10-aef7-9301f2c7e903", 3 | "eventType": "UPDATE", 4 | "path": "/{http://www.alfresco.org/model/application/1.0}company_home/{http://www.alfresco.org/model/site/1.0}sites/{http://www.alfresco.org/model/content/1.0}jtp-test-site-1/{http://www.alfresco.org/model/content/1.0}documentLibrary/{http://www.alfresco.org/model/content/1.0}testfolder2", 5 | "created": 1567032687513, 6 | "modified": 1567032687513, 7 | "creator": "admin", 8 | "modifier": "admin", 9 | "contentType": "folder", 10 | "siteId": "jtp-test-site-1", 11 | "parent": "244a089b-17ad-4a49-81f4-c8b17b7322a6", 12 | "permissions": { 13 | "permissions": [ 14 | { 15 | "authority": "GROUP_site_jtp-test-site-1_SiteConsumer", 16 | "authorityType": "GROUP", 17 | "permission": "SiteConsumer", 18 | "inherited": true 19 | }, 20 | { 21 | "authority": "GROUP_site_jtp-test-site-1_SiteContributor", 22 | "authorityType": "GROUP", 23 | "permission": "SiteContributor", 24 | "inherited": true 25 | }, 26 | { 27 | "authority": "GROUP_site_jtp-test-site-1_SiteCollaborator", 28 | "authorityType": "GROUP", 29 | "permission": "SiteCollaborator", 30 | "inherited": true 31 | }, 32 | { 33 | "authority": "GROUP_site_jtp-test-site-1_SiteManager", 34 | "authorityType": "GROUP", 35 | "permission": "SiteManager", 36 | "inherited": true 37 | } 38 | ], 39 | "inheritanceEnabled": true 40 | } 41 | } -------------------------------------------------------------------------------- /pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 4.0.0 5 | com.metaversant 6 | alfresco-kafka 7 | 0.0.3-SNAPSHOT 8 | alfresco-kafka Platform/Repository Module 9 | pom 10 | 11 | 12 | 13 | 4.1.0 14 | 15 | UTF-8 16 | 17 | 18 | org.alfresco 19 | acs-community-packaging 20 | 6.2.1-A8 21 | 6.2.1 22 | 23 | 24 | alfresco/alfresco-content-repository-community 25 | alfresco/alfresco-share 26 | 27 | 28 | 1.1.8 29 | 30 | 31 | 8180 32 | alfresco-kafka-repo-acs 33 | 8080 34 | 8888 35 | 5555 36 | 37 | 38 | 39 | 40 | 41 | 42 | 44 | 45 | 46 | junit 47 | junit 48 | 4.13.1 49 | test 50 | 51 | 52 | org.mockito 53 | mockito-all 54 | 1.9.5 55 | test 56 | 57 | 58 | org.apache.httpcomponents 59 | httpclient 60 | test 61 | 62 | 63 | 64 | 65 | ${alfresco.groupId} 66 | alfresco-remote-api 67 | provided 68 | 69 | 70 | 71 | 72 | org.alfresco.maven 73 | alfresco-rad 74 | ${alfresco.sdk.version} 75 | test 76 | 77 | 78 | 79 | 80 | org.projectlombok 81 | lombok 82 | 1.18.12 83 | 84 | 85 | 86 | 87 | org.apache.kafka 88 | kafka-clients 89 | 2.6.3 90 | 91 | 92 | 93 | 94 | 95 | 96 | 102 | 103 | ${alfresco.groupId} 104 | ${alfresco.bomDependencyArtifactId} 105 | ${alfresco.platform.version} 106 | pom 107 | import 108 | 109 | 110 | 111 | 112 | 113 | 114 | 121 | 148 | 149 | 151 | 152 | org.apache.maven.plugins 153 | maven-resources-plugin 154 | 3.1.0 155 | 156 | UTF-8 157 | 158 | ftl 159 | acp 160 | svg 161 | pdf 162 | doc 163 | docx 164 | xls 165 | xlsx 166 | ppt 167 | pptx 168 | bin 169 | lic 170 | swf 171 | zip 172 | msg 173 | jar 174 | ttf 175 | eot 176 | woff 177 | woff2 178 | css 179 | ico 180 | psd 181 | js 182 | 183 | 184 | 185 | 186 | copy-and-filter-docker-compose-resources 187 | validate 188 | 189 | copy-resources 190 | 191 | 192 | ${project.build.outputDirectory}/docker 193 | 194 | 195 | docker 196 | true 197 | 198 | 199 | 200 | 201 | 202 | copy-and-filter-docker-resources 203 | validate 204 | 205 | copy-resources 206 | 207 | 208 | ${project.build.directory} 209 | 210 | 211 | src/main/docker 212 | true 213 | 214 | **/*.jar 215 | **/*.so 216 | **/*.gz 217 | 218 | 219 | 220 | 221 | 222 | 223 | copy-and-filter-docker-resources-non-filtered 224 | validate 225 | 226 | copy-resources 227 | 228 | 229 | ${project.build.directory} 230 | 231 | 232 | src/main/docker 233 | false 234 | 235 | **/*.jar 236 | **/*.so 237 | **/*.gz 238 | 239 | 240 | 241 | 242 | 243 | 244 | copy-repository-extension 245 | package 246 | 247 | copy-resources 248 | 249 | 250 | ${project.build.directory}/extensions 251 | 252 | 253 | target 254 | 255 | ${project.build.finalName}.jar 256 | 257 | false 258 | 259 | 260 | 261 | 262 | 263 | copy-repository-tests 264 | pre-integration-test 265 | 266 | copy-resources 267 | 268 | 269 | ${project.build.directory}/extensions 270 | 271 | 272 | target 273 | 274 | ${project.build.finalName}-tests.jar 275 | 276 | false 277 | 278 | 279 | 280 | 281 | 282 | 283 | 284 | 285 | org.apache.maven.plugins 286 | maven-dependency-plugin 287 | 3.1.1 288 | 289 | 290 | 291 | collect-test-artifacts 292 | pre-integration-test 293 | 294 | copy-dependencies 295 | 296 | 297 | ${project.build.directory}/extensions 298 | compile 299 | 300 | 301 | 302 | 303 | collect-extensions 304 | package 305 | 306 | copy-dependencies 307 | 308 | 309 | ${project.build.directory}/extensions 310 | runtime 311 | 312 | 313 | 314 | 315 | 316 | 317 | 318 | 319 | org.apache.maven.plugins 320 | maven-jar-plugin 321 | 3.1.0 322 | 323 | 324 | 325 | test-jar 326 | 327 | 328 | 329 | 330 | 331 | 333 | 334 | org.apache.maven.plugins 335 | maven-failsafe-plugin 336 | 3.0.0-M1 337 | 338 | 339 | ${test.acs.endpoint.path} 340 | 341 | 342 | 343 | 344 | integration-test 345 | integration-test 346 | 347 | integration-test 348 | 349 | 350 | 351 | verify-test 352 | verify 353 | 354 | verify 355 | 356 | 357 | 358 | 359 | 360 | org.apache.maven.surefire 361 | surefire-junit47 362 | 3.0.0-M1 363 | 364 | 365 | 366 | 367 | 368 | 369 | net.alchim31.maven 370 | yuicompressor-maven-plugin 371 | 1.5.1 372 | 373 | 374 | 375 | compress-assembly 376 | 377 | compress 378 | 379 | 380 | ${project.basedir}/src/main/assembly/web 381 | ${project.basedir}/src/main/assembly/web 382 | 383 | **/webscripts/** 384 | **/site-webscripts/** 385 | **/META-INF/** 386 | **/*.lib.js 387 | **/*.css 388 | **/*-min.js 389 | **/*-min.css 390 | 391 | true 392 | false 393 | 394 | 395 | 396 | 397 | compress-resources 398 | 399 | compress 400 | 401 | 402 | 403 | **/webscripts/** 404 | **/site-webscripts/** 405 | **/*.lib.js 406 | **/*.css 407 | **/*-min.js 408 | **/*-min.css 409 | 410 | true 411 | false 412 | 413 | 414 | 415 | 416 | 417 | 418 | 419 | org.zeroturnaround 420 | jrebel-maven-plugin 421 | ${jrebel.version} 422 | 423 | 424 | generate-rebel-xml 425 | process-resources 426 | 427 | generate 428 | 429 | 430 | 431 | 432 | 434 | 435 | all 436 | 437 | 438 | ${project.build.outputDirectory} 439 | ${project.build.testOutputDirectory} 440 | 441 | 442 | 443 | 444 | 449 | true 450 | 451 | 452 | 453 | 454 | 455 | 456 | 457 | src/main/resources 458 | true 459 | 460 | 461 | 462 | 463 | 464 | src/test/resources 465 | true 466 | 467 | 468 | 469 | 470 | 471 | 472 | java8 473 | 474 | [1.8,11.0) 475 | 476 | 477 | 478 | 479 | org.apache.maven.plugins 480 | maven-compiler-plugin 481 | 3.8.0 482 | 483 | 1.8 484 | 1.8 485 | 486 | 487 | 488 | 489 | 490 | 491 | java11 492 | 493 | [11.0,) 494 | 495 | 496 | 497 | 498 | org.apache.maven.plugins 499 | maven-compiler-plugin 500 | 3.8.0 501 | 502 | 11 503 | 504 | 505 | 506 | 507 | 508 | 509 | 510 | 513 | 514 | 515 | alfresco-public 516 | https://artifacts.alfresco.com/nexus/content/groups/public 517 | 518 | 519 | alfresco-public-snapshots 520 | https://artifacts.alfresco.com/nexus/content/groups/public-snapshots 521 | 522 | true 523 | daily 524 | 525 | 526 | 527 | 528 | alfresco-private-repository 529 | https://artifacts.alfresco.com/nexus/content/groups/private 530 | 531 | 532 | 533 | 534 | 535 | alfresco-plugin-public 536 | https://artifacts.alfresco.com/nexus/content/groups/public 537 | 538 | 539 | alfresco-plugin-public-snapshots 540 | https://artifacts.alfresco.com/nexus/content/groups/public-snapshots 541 | 542 | true 543 | daily 544 | 545 | 546 | 547 | 548 | 549 | alfresco-kafka-model 550 | alfresco-kafka-repo 551 | 552 | -------------------------------------------------------------------------------- /run.bat: -------------------------------------------------------------------------------- 1 | @ECHO OFF 2 | 3 | SET COMPOSE_FILE_PATH=%CD%\alfresco-kafka-repo\target\classes\docker\docker-compose.yml 4 | 5 | IF [%M2_HOME%]==[] ( 6 | SET MVN_EXEC=mvn 7 | ) 8 | 9 | IF NOT [%M2_HOME%]==[] ( 10 | SET MVN_EXEC=%M2_HOME%\bin\mvn 11 | ) 12 | 13 | IF [%1]==[] ( 14 | echo "Usage: %0 {build_start|build_start_it_supported|start|stop|purge|tail|build_test|test}" 15 | GOTO END 16 | ) 17 | 18 | IF %1==build_start ( 19 | CALL :down 20 | CALL :build 21 | CALL :start 22 | CALL :tail 23 | GOTO END 24 | ) 25 | IF %1==build_start_it_supported ( 26 | CALL :down 27 | CALL :build 28 | CALL :prepare_test 29 | CALL :start 30 | CALL :tail 31 | GOTO END 32 | ) 33 | IF %1==start ( 34 | CALL :start 35 | CALL :tail 36 | GOTO END 37 | ) 38 | IF %1==stop ( 39 | CALL :down 40 | GOTO END 41 | ) 42 | IF %1==purge ( 43 | CALL:down 44 | CALL:purge 45 | GOTO END 46 | ) 47 | IF %1==tail ( 48 | CALL :tail 49 | GOTO END 50 | ) 51 | IF %1==build_test ( 52 | CALL :down 53 | CALL :build 54 | CALL :prepare_test 55 | CALL :start 56 | CALL :test 57 | CALL :tail_all 58 | CALL :down 59 | GOTO END 60 | ) 61 | IF %1==test ( 62 | CALL :test 63 | GOTO END 64 | ) 65 | echo "Usage: %0 {build_start|start|stop|purge|tail|build_test|test}" 66 | :END 67 | EXIT /B %ERRORLEVEL% 68 | 69 | :start 70 | docker volume create alfresco-kafka-repo-acs-volume 71 | docker volume create alfresco-kafka-repo-db-volume 72 | docker volume create alfresco-kafka-repo-ass-volume 73 | docker-compose -f "%COMPOSE_FILE_PATH%" up --build -d 74 | EXIT /B 0 75 | :down 76 | if exist "%COMPOSE_FILE_PATH%" ( 77 | docker-compose -f "%COMPOSE_FILE_PATH%" down 78 | ) 79 | EXIT /B 0 80 | :build 81 | call %MVN_EXEC% clean package 82 | EXIT /B 0 83 | :tail 84 | docker-compose -f "%COMPOSE_FILE_PATH%" logs -f 85 | EXIT /B 0 86 | :tail_all 87 | docker-compose -f "%COMPOSE_FILE_PATH%" logs --tail="all" 88 | EXIT /B 0 89 | :prepare_test 90 | call %MVN_EXEC% verify -DskipTests=true 91 | EXIT /B 0 92 | :test 93 | call %MVN_EXEC% verify 94 | EXIT /B 0 95 | :purge 96 | docker volume rm -f alfresco-kafka-repo-acs-volume 97 | docker volume rm -f alfresco-kafka-repo-db-volume 98 | docker volume rm -f alfresco-kafka-repo-ass-volume 99 | EXIT /B 0 -------------------------------------------------------------------------------- /run.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | export COMPOSE_FILE_PATH="${PWD}/alfresco-kafka-repo/target/classes/docker/docker-compose.yml" 4 | 5 | if [ -z "${M2_HOME}" ]; then 6 | export MVN_EXEC="mvn" 7 | else 8 | export MVN_EXEC="${M2_HOME}/bin/mvn" 9 | fi 10 | 11 | start() { 12 | docker volume create alfresco-kafka-repo-acs-volume 13 | docker volume create alfresco-kafka-repo-db-volume 14 | docker volume create alfresco-kafka-repo-ass-volume 15 | docker-compose -f "$COMPOSE_FILE_PATH" up --build -d 16 | } 17 | 18 | down() { 19 | if [ -f "$COMPOSE_FILE_PATH" ]; then 20 | docker-compose -f "$COMPOSE_FILE_PATH" down 21 | fi 22 | } 23 | 24 | purge() { 25 | docker volume rm -f alfresco-kafka-repo-acs-volume 26 | docker volume rm -f alfresco-kafka-repo-db-volume 27 | docker volume rm -f alfresco-kafka-repo-ass-volume 28 | } 29 | 30 | build() { 31 | $MVN_EXEC clean package 32 | } 33 | 34 | tail() { 35 | docker-compose -f "$COMPOSE_FILE_PATH" logs -f 36 | } 37 | 38 | tail_all() { 39 | docker-compose -f "$COMPOSE_FILE_PATH" logs --tail="all" 40 | } 41 | 42 | prepare_test() { 43 | $MVN_EXEC verify -DskipTests=true 44 | } 45 | 46 | test() { 47 | $MVN_EXEC verify 48 | } 49 | 50 | case "$1" in 51 | build_start) 52 | down 53 | build 54 | start 55 | tail 56 | ;; 57 | build_start_it_supported) 58 | down 59 | build 60 | prepare_test 61 | start 62 | tail 63 | ;; 64 | start) 65 | start 66 | tail 67 | ;; 68 | stop) 69 | down 70 | ;; 71 | purge) 72 | down 73 | purge 74 | ;; 75 | tail) 76 | tail 77 | ;; 78 | build_test) 79 | down 80 | build 81 | prepare_test 82 | start 83 | test 84 | tail_all 85 | down 86 | ;; 87 | test) 88 | test 89 | ;; 90 | *) 91 | echo "Usage: $0 {build_start|build_start_it_supported|start|stop|purge|tail|build_test|test}" 92 | esac --------------------------------------------------------------------------------