commit 122da0b856c92cc1625de85a680ad8193580c4ac Author: Aldo Mihasi Date: Tue Jan 31 13:58:43 2023 +0200 initial commit diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..92322c4 --- /dev/null +++ b/.gitignore @@ -0,0 +1,2 @@ +.idea/ +target/ diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 0000000..1f30298 --- /dev/null +++ b/Dockerfile @@ -0,0 +1,18 @@ +####################################### Build stage ####################################### +FROM maven:3.6.3-openjdk-11-slim AS build-stage + +COPY . /build/ +WORKDIR /build/ +RUN mvn clean package -DskipTests + +ARG CREPO_BINARIES_REPO_URL +ARG CREPO_BINARIES_CREDENTIAL +ARG BUILD_VERSION +ENV CREPO_BINARIES_REPO_URL=$CREPO_BINARIES_REPO_URL +ENV CREPO_BINARIES_CREDENTIAL=$CREPO_BINARIES_CREDENTIAL +ENV BUILD_VERSION=$BUILD_VERSION + +RUN curl --location --request PUT "${CREPO_BINARIES_REPO_URL}opendmp/repository-jars/ckan/ckan-deposit-${BUILD_VERSION}.jar" \ +--header "Authorization: Basic ${CREPO_BINARIES_CREDENTIAL}" \ +--header "Content-Type: application/json" \ +--data-binary "@/build/target/repositorydepositckan-1.0.0-SNAPSHOT.jar" \ No newline at end of file diff --git a/LICENSE.txt b/LICENSE.txt new file mode 100644 index 0000000..47b2a43 --- /dev/null +++ b/LICENSE.txt @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2019-2020 OpenAIRE AMKE + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/README.md b/README.md new file mode 100644 index 0000000..f7bb73c --- /dev/null +++ b/README.md @@ -0,0 +1,25 @@ +# Using Ckan repository with Argos + +The repository-deposit-ckan module implements the [https://code-repo.d4science.org/MaDgiK-CITE/repository-deposit-base](https://) interface for the Ckan repository +which has the DOI extension. + +## Setup + +After creating the jar from the project, environment variables should be set since they are used in the application.properties +1) STORAGE_TMP_CKAN - a temporary storage needed +2) CONFIGURATION_CKAN - path to json file which includes the configuration for the repository + +### JSON configuration file + +The following fields should be set:
+**depositType** - an integer representing how the dmp user can deposit in the repository,
+a. **0** stands for system deposition meaning the dmp is deposited using argos credentials to the repository,
+b. **1** stands for user deposition in which the argos user specifies his/her own credentials to the repository,
+c. **2** stands for both ways deposition if the repository allows the deposits of dmps to be made from both argos and users accounts
+note: depositType should be set to **0** since ckan does not provide oauth2 protocol but, instead, uses api tokens
+**repositoryId** - unique identifier for the repository
+**apiToken** - api token provided for the depositions
+**repositoryUrl** - repository's api url e.g. "http://localhost:5000/api/3/action/"
+**repositoryRecordUrl** - repository's record url, this url is used to index dmps that are created e.g. "http://localhost:5000/dataset?doi="
+**organization** - organization uuid (or name) in which all dmps that are deposited will be resided
+**hasLogo** - if the repository has a logo
\ No newline at end of file diff --git a/THIRD-PARTY-NOTICES.txt b/THIRD-PARTY-NOTICES.txt new file mode 100644 index 0000000..0480858 --- /dev/null +++ b/THIRD-PARTY-NOTICES.txt @@ -0,0 +1,429 @@ +THIRD-PARTY SOFTWARE NOTICES AND INFORMATION +Do Not Translate or Localize + +This component uses third party material from the projects listed below. +The original copyright notice and the license under which CITE +received such third party material are set forth below. CITE +reserves all other rights not expressly granted, whether by +implication, estoppel or otherwise. + +In the event that we accidentally failed to list a required notice, please +bring it to our attention. Post an issue or email us: reception@cite.gr + +1. spring-boot-starter-parent +2. spring-boot-starter-web +3. spring-boot-starter-webflux +4. json +5. repositorydepositbase + +spring-boot-starter-parent NOTICES, INFORMATION, AND LICENSE BEGIN HERE +========================================= + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +========================================= +END OF spring-boot-starter-parent NOTICES, INFORMATION, AND LICENSE + +spring-boot-starter-web NOTICES, INFORMATION, AND LICENSE BEGIN HERE +========================================= + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +========================================= +END OF spring-boot-starter-web NOTICES, INFORMATION, AND LICENSE \ No newline at end of file diff --git a/pom.xml b/pom.xml new file mode 100644 index 0000000..6b7b2a3 --- /dev/null +++ b/pom.xml @@ -0,0 +1,123 @@ + + + 4.0.0 + + org.springframework.boot + spring-boot-starter-parent + 2.5.2 + + + + gr.cite.opendmp + repositorydepositckan + ${revision} + jar + + OpenDMP Repository Deposit Ckan + OpenDMP Repository Deposit Ckan + https://code-repo.d4science.org/MaDgiK-CITE/repository-deposit-ckan + + + MIT License + https://code-repo.d4science.org/MaDgiK-CITE/repository-deposit-ckan/src/branch/master/LICENSE.txt + repo + + + + + CITE S.A. + maven-central@cite.gr + CITE S.A. + https://www.cite.gr + + + + scm:git:git://code-repo.d4science.org + scm:git:ssh://code-repo.d4science.org + https://code-repo.d4science.org/MaDgiK-CITE/repository-deposit-ckan + + + + 1.0.0-SNAPSHOT + + + + + org.springframework.boot + spring-boot-starter-web + + + + org.springframework.boot + spring-boot-starter-webflux + + + + gr.cite.opendmp + repositorydepositbase + 1.0.1 + + + + org.json + json + 20160810 + + + + + + + maven-assembly-plugin + + + package + + single + + + + + + + eu.eudat.EuDatApplication + + + + jar-with-dependencies + + + + + org.apache.maven.plugins + maven-shade-plugin + 3.4.1 + + + package + + shade + + + + + *:* + + module-info.class + + + + + + org.json + ckanrepository.shaded.org.json + + + + + + + + + diff --git a/settings.xml b/settings.xml new file mode 100644 index 0000000..e6874ab --- /dev/null +++ b/settings.xml @@ -0,0 +1,18 @@ + + + + ossrh + ${server_username} + ${server_password} + + + + + ossrh + + ${gpg_passphrase} + ${gpg_keyname} + + + + \ No newline at end of file diff --git a/src/main/java/eu/eudat/depositinterface/ckanrepository/config/CkanConfig.java b/src/main/java/eu/eudat/depositinterface/ckanrepository/config/CkanConfig.java new file mode 100644 index 0000000..9bda7f1 --- /dev/null +++ b/src/main/java/eu/eudat/depositinterface/ckanrepository/config/CkanConfig.java @@ -0,0 +1,107 @@ +package eu.eudat.depositinterface.ckanrepository.config; + +import com.fasterxml.jackson.annotation.JsonProperty; +import eu.eudat.depositinterface.repository.RepositoryDepositConfiguration; + +public class CkanConfig { + private enum DepositType { + SystemDeposit(0), UserDeposit(1), BothWaysDeposit(2); + + private final int value; + + DepositType(int value) { + this.value = value; + } + + public int getValue() { + return value; + } + + public static DepositType fromInteger(int value) { + switch (value) { + case 0: + return SystemDeposit; + case 1: + return UserDeposit; + case 2: + return BothWaysDeposit; + default: + throw new RuntimeException("Unsupported Deposit Type"); + } + } + } + + @JsonProperty("depositType") + private int depositType; + @JsonProperty("repositoryId") + private String repositoryId; + @JsonProperty("apiToken") + private String apiToken; + @JsonProperty("repositoryUrl") + private String repositoryUrl; + @JsonProperty("repositoryRecordUrl") + private String repositoryRecordUrl; + @JsonProperty("organization") + private String organization; + @JsonProperty("hasLogo") + private boolean hasLogo; + + public int getDepositType() { + return depositType; + } + public void setDepositType(int depositType) { + this.depositType = depositType; + } + + public String getRepositoryId() { + return repositoryId; + } + public void setRepositoryId(String repositoryId) { + this.repositoryId = repositoryId; + } + + public String getApiToken() { + return apiToken; + } + public void setApiToken(String apiToken) { + this.apiToken = apiToken; + } + + public String getRepositoryUrl() { + return repositoryUrl; + } + public void setRepositoryUrl(String repositoryUrl) { + this.repositoryUrl = repositoryUrl; + } + + public String getRepositoryRecordUrl() { + return repositoryRecordUrl; + } + public void setRepositoryRecordUrl(String repositoryRecordUrl) { + this.repositoryRecordUrl = repositoryRecordUrl; + } + + public String getOrganization() { + return organization; + } + public void setOrganization(String organization) { + this.organization = organization; + } + + public boolean isHasLogo() { + return hasLogo; + } + public void setHasLogo(boolean hasLogo) { + this.hasLogo = hasLogo; + } + + public RepositoryDepositConfiguration toRepoConfig() { + RepositoryDepositConfiguration config = new RepositoryDepositConfiguration(); + config.setDepositType(this.depositType); + config.setRepositoryId(this.repositoryId); + config.setRepositoryUrl(this.repositoryUrl); + config.setRepositoryRecordUrl(this.repositoryRecordUrl); + config.setHasLogo(this.hasLogo); + return config; + } +} diff --git a/src/main/java/eu/eudat/depositinterface/ckanrepository/config/ConfigLoader.java b/src/main/java/eu/eudat/depositinterface/ckanrepository/config/ConfigLoader.java new file mode 100644 index 0000000..26d084a --- /dev/null +++ b/src/main/java/eu/eudat/depositinterface/ckanrepository/config/ConfigLoader.java @@ -0,0 +1,6 @@ +package eu.eudat.depositinterface.ckanrepository.config; + +public interface ConfigLoader { + byte[] getLogo(); + CkanConfig getCkanConfig(); +} diff --git a/src/main/java/eu/eudat/depositinterface/ckanrepository/config/ConfigLoaderImpl.java b/src/main/java/eu/eudat/depositinterface/ckanrepository/config/ConfigLoaderImpl.java new file mode 100644 index 0000000..675afe6 --- /dev/null +++ b/src/main/java/eu/eudat/depositinterface/ckanrepository/config/ConfigLoaderImpl.java @@ -0,0 +1,61 @@ +package eu.eudat.depositinterface.ckanrepository.config; + +import com.fasterxml.jackson.databind.ObjectMapper; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.core.env.Environment; +import org.springframework.stereotype.Service; + +import java.io.FileInputStream; +import java.io.FileNotFoundException; +import java.io.IOException; +import java.io.InputStream; + +@Service("ckanConfigLoader") +public class ConfigLoaderImpl implements ConfigLoader{ + private static final Logger logger = LoggerFactory.getLogger(ConfigLoaderImpl.class); + private static final ObjectMapper mapper = new ObjectMapper(); + + private CkanConfig ckanConfig; + + @Autowired + private Environment environment; + + @Override + public CkanConfig getCkanConfig() { + if(ckanConfig == null){ + try{ + ckanConfig = mapper.readValue(getStreamFromPath(environment.getProperty("configuration.ckan")), CkanConfig.class); + } catch (IOException e) { + logger.error(e.getLocalizedMessage(), e); + } + } + return ckanConfig; + } + + @Override + public byte[] getLogo() { + String logo = environment.getProperty("configuration.logo"); + if(logo != null && !logo.isEmpty()){ + InputStream logoStream = getStreamFromPath(logo); + try { + return logoStream.readAllBytes(); + } + catch (IOException e){ + logger.error(e.getMessage(), e); + return null; + } + } + return null; + } + + private InputStream getStreamFromPath(String filePath) { + try { + return new FileInputStream(filePath); + } catch (FileNotFoundException e) { + logger.info("loading from classpath"); + return getClass().getClassLoader().getResourceAsStream(filePath); + } + } +} diff --git a/src/main/java/eu/eudat/depositinterface/ckanrepository/interfaces/CkanDataset.java b/src/main/java/eu/eudat/depositinterface/ckanrepository/interfaces/CkanDataset.java new file mode 100644 index 0000000..999f1f6 --- /dev/null +++ b/src/main/java/eu/eudat/depositinterface/ckanrepository/interfaces/CkanDataset.java @@ -0,0 +1,65 @@ +package eu.eudat.depositinterface.ckanrepository.interfaces; + +import com.fasterxml.jackson.annotation.JsonProperty; + +public class CkanDataset { + + private String name; + @JsonProperty("private") + private boolean isPrivate; + private String author; + private String author_email; + private String notes; + private String version; + private String owner_org; + + public String getName() { + return name; + } + public void setName(String name) { + this.name = name; + } + + public boolean isPrivate() { + return isPrivate; + } + public void setPrivate(boolean aPrivate) { + isPrivate = aPrivate; + } + + public String getAuthor() { + return author; + } + public void setAuthor(String author) { + this.author = author; + } + + public String getAuthor_email() { + return author_email; + } + public void setAuthor_email(String author_email) { + this.author_email = author_email; + } + + public String getNotes() { + return notes; + } + public void setNotes(String notes) { + this.notes = notes; + } + + public String getVersion() { + return version; + } + public void setVersion(String version) { + this.version = version; + } + + public String getOwner_org() { + return owner_org; + } + public void setOwner_org(String owner_org) { + this.owner_org = owner_org; + } + +} diff --git a/src/main/java/eu/eudat/depositinterface/ckanrepository/interfaces/CkanDeposit.java b/src/main/java/eu/eudat/depositinterface/ckanrepository/interfaces/CkanDeposit.java new file mode 100644 index 0000000..8b62584 --- /dev/null +++ b/src/main/java/eu/eudat/depositinterface/ckanrepository/interfaces/CkanDeposit.java @@ -0,0 +1,194 @@ +package eu.eudat.depositinterface.ckanrepository.interfaces; + +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.databind.JsonNode; +import com.fasterxml.jackson.databind.ObjectMapper; +import eu.eudat.depositinterface.ckanrepository.config.CkanConfig; +import eu.eudat.depositinterface.ckanrepository.config.ConfigLoader; +import eu.eudat.depositinterface.models.DMPDepositModel; +import eu.eudat.depositinterface.repository.RepositoryDeposit; +import eu.eudat.depositinterface.repository.RepositoryDepositConfiguration; +import org.json.JSONObject; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.core.env.Environment; +import org.springframework.core.io.FileSystemResource; +import org.springframework.core.io.Resource; +import org.springframework.http.*; +import org.springframework.http.client.MultipartBodyBuilder; +import org.springframework.stereotype.Component; +import org.springframework.util.MultiValueMap; +import org.springframework.web.client.RestTemplate; + +import java.io.File; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.OutputStream; +import java.nio.file.Files; +import java.util.*; + +@Component +public class CkanDeposit implements RepositoryDeposit { + private static final Logger logger = LoggerFactory.getLogger(CkanDeposit.class); + private static final ObjectMapper objectMapper = new ObjectMapper(); + + private ConfigLoader configLoader; + private Environment environment; + + @Autowired + public CkanDeposit(ConfigLoader configLoader, Environment environment){ + this.configLoader = configLoader; + this.environment = environment; + } + + @Override + public String deposit(DMPDepositModel dmpDepositModel, String repositoryAccessToken) throws Exception { + + CkanConfig ckanConfig = this.configLoader.getCkanConfig(); + + String doi; + + CkanDataset dataset = new CkanDataset(); + dataset.setName(dmpDepositModel.getLabel().replaceAll("[^a-zA-Z0-9]+", "_").toLowerCase()); + //dataset.setPrivate(!dmpDepositModel.isPublic()); + dataset.setPrivate(true); + dataset.setNotes(dmpDepositModel.getDescription()); + dataset.setVersion(String.valueOf(dmpDepositModel.getVersion())); + dataset.setOwner_org(ckanConfig.getOrganization()); + dataset.setAuthor("Argos User"); + dataset.setAuthor_email("argosUser@example.com"); + + if(dmpDepositModel.getPreviousDOI() == null || dmpDepositModel.getPreviousDOI().isEmpty()){ + RestTemplate restTemplate = new RestTemplate(); + HttpHeaders headers = new HttpHeaders(); + headers.set("Authorization", ckanConfig.getApiToken()); + headers.setContentType(MediaType.APPLICATION_JSON); + String url = ckanConfig.getRepositoryUrl() + "package_create"; + Object response = restTemplate.exchange(url, HttpMethod.POST, new HttpEntity<>(dataset, headers), Object.class).getBody(); + Map respMap = objectMapper.convertValue(response, Map.class); + respMap = (Map) respMap.get("result"); + String id = String.valueOf(respMap.get("id")); + + doi = String.valueOf(respMap.get("doi")); + + this.uploadFiles(dmpDepositModel, id); + } + else{ + JsonNode datasetJson = this.getDatasetIdentifier(dmpDepositModel.getPreviousDOI()).get(0); + String datasetId = datasetJson.get("id").asText(); + String version = datasetJson.get("version").asText(); + + JsonNode files = datasetJson.get("resources"); + if(files.isArray()) { + for (JsonNode file : files) { + String fileId = file.get("id").asText(); + this.deleteFile(fileId); + } + } + + this.uploadFiles(dmpDepositModel, datasetId); + + Map resp = this.updateVersion(datasetId, version); + doi = (String) resp.get("doi"); + } + + return doi; + + } + + private Map updateVersion(String datasetId, String version){ + HttpHeaders headers = new HttpHeaders(); + headers.set("Authorization", this.configLoader.getCkanConfig().getApiToken()); + headers.setContentType(MediaType.APPLICATION_JSON); + String serverUrl = this.configLoader.getCkanConfig().getRepositoryUrl() + "package_patch"; + Map body = new HashMap<>(); + body.put("id", datasetId); + body.put("version", String.valueOf(Integer.parseInt(version) + 1)); + RestTemplate restTemplate = new RestTemplate(); + return (Map)restTemplate.exchange(serverUrl, HttpMethod.POST, new HttpEntity<>(body, headers), Map.class).getBody().get("result"); + } + + private void deleteFile(String fileId){ + HttpHeaders headers = new HttpHeaders(); + headers.set("Authorization", this.configLoader.getCkanConfig().getApiToken()); + headers.setContentType(MediaType.APPLICATION_JSON); + String serverUrl = this.configLoader.getCkanConfig().getRepositoryUrl() + "resource_delete"; + Map map = new HashMap<>(); + map.put("id", fileId); + RestTemplate restTemplate = new RestTemplate(); + restTemplate.exchange(serverUrl, HttpMethod.POST, new HttpEntity<>(map, headers), Object.class); + } + + private void uploadFiles(DMPDepositModel dmpDepositModel, String id) throws IOException { + this.uploadFile(dmpDepositModel.getPdfFileName(), dmpDepositModel.getPdfFile(), id); + + String contentDisposition = dmpDepositModel.getRdaJson().getHeaders().get("Content-Disposition").get(0); + String jsonFileName = contentDisposition.substring(contentDisposition.lastIndexOf('=') + 1); + File rdaJson = new File(this.environment.getProperty("storage.temp") + jsonFileName); + OutputStream output = new FileOutputStream(rdaJson); + try { + output.write(Objects.requireNonNull(dmpDepositModel.getRdaJson().getBody())); + output.flush(); + output.close(); + } catch (IOException e) { + logger.error(e.getMessage(), e); + } + this.uploadFile(jsonFileName, rdaJson, id); + Files.deleteIfExists(rdaJson.toPath()); + + if(dmpDepositModel.getSupportingFilesZip() != null) { + this.uploadFile(dmpDepositModel.getSupportingFilesZip().getName(), dmpDepositModel.getSupportingFilesZip(), id); + } + } + + private JsonNode getDatasetIdentifier(String previousDOI) throws JsonProcessingException { + HttpHeaders headers = new HttpHeaders(); + headers.set("Authorization", this.configLoader.getCkanConfig().getApiToken()); + String serverUrl = this.configLoader.getCkanConfig().getRepositoryUrl() + "package_search?q=doi:" + previousDOI + "&include_private=True"; + RestTemplate restTemplate = new RestTemplate(); + Object response = restTemplate.exchange(serverUrl, HttpMethod.GET, new HttpEntity<>(headers), Map.class).getBody().get("result"); + JsonNode jsonNode = objectMapper.readTree(new JSONObject((Map)response).toString()); + return jsonNode.findValues("results").get(0); + } + + private void uploadFile(String filename, File file, String datasetId) { + HttpHeaders headers = new HttpHeaders(); + headers.setContentType(MediaType.MULTIPART_FORM_DATA); + headers.set("Authorization", this.configLoader.getCkanConfig().getApiToken()); + MultipartBodyBuilder multipartBodyBuilder = new MultipartBodyBuilder(); + Resource resource = new FileSystemResource(file); + multipartBodyBuilder.part("upload", resource) + .header("filename", filename); + multipartBodyBuilder.part("name", filename); + multipartBodyBuilder.part("package_id", datasetId); + MultiValueMap> multipartBody = multipartBodyBuilder.build(); + HttpEntity>> requestEntity = new HttpEntity<>(multipartBody, headers); + + String serverUrl = this.configLoader.getCkanConfig().getRepositoryUrl() + "resource_create"; + + RestTemplate restTemplate = new RestTemplate(); + ResponseEntity resp = restTemplate.postForEntity(serverUrl, requestEntity, Object.class); + } + + @Override + public RepositoryDepositConfiguration getConfiguration() { + eu.eudat.depositinterface.ckanrepository.config.CkanConfig ckanConfig = this.configLoader.getCkanConfig(); + return ckanConfig.toRepoConfig(); + } + + @Override + public String getLogo() { + RepositoryDepositConfiguration conf = this.getConfiguration(); + if(conf.isHasLogo()){ + byte[] logo = this.configLoader.getLogo(); + return (logo != null && logo.length != 0) ? Base64.getEncoder().encodeToString(logo) : null; + } + return null; + } + + @Override + public String authenticate(String code) { + return null; + } +} diff --git a/src/main/resources/application.properties b/src/main/resources/application.properties new file mode 100644 index 0000000..3a5e685 --- /dev/null +++ b/src/main/resources/application.properties @@ -0,0 +1,3 @@ +storage.temp=${STORAGE_TMP_CKAN} +configuration.ckan=${CONFIGURATION_CKAN} +configuration.ckan.logo=${CONFIGURATION_LOGO_CKAN} \ No newline at end of file diff --git a/src/main/resources/ckan.png b/src/main/resources/ckan.png new file mode 100644 index 0000000..e01821e Binary files /dev/null and b/src/main/resources/ckan.png differ