diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 0000000..279d2ac --- /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/dspace/dspace-deposit-${BUILD_VERSION}.jar" \ +--header "Authorization: Basic ${CREPO_BINARIES_CREDENTIAL}" \ +--header "Content-Type: application/json" \ +--data-binary "@/build/target/repositorydepositdspace-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..b815d03 --- /dev/null +++ b/README.md @@ -0,0 +1,27 @@ +# Using DSpace repository with Argos + +The repository-deposit-dspace module implements the [https://code-repo.d4science.org/MaDgiK-CITE/repository-deposit-base](https://) interface for the DSpace repository. + +## Setup + +After creating the jar from the project, environment variables should be set since they are used in the application.properties +1) STORAGE_TMP_DSPACE - a temporary storage needed +2) CONFIGURATION_DSPACE - 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 dspace does not provide oauth2 protocol but, instead, uses system accounts
+**repositoryId** - unique identifier for the repository
+**email** - system email provided for the depositions
+**password** - system password provided for the depositions
+**workflowEmail** - email(can be the same as the system email if that user is privileged) provided for the workflows of dspace
+**workflowPassword** - password provided for the workflows of dspace
+**repositoryUrl** - repository's api url e.g. "https://api7.dspace.org/server/api/"
+**repositoryRecordUrl** - repository's record url, this url is used to index dmps that are created e.g. "https://demo7.dspace.org/handle/"
+**collection** - collection uuid 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..5a45859 --- /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. json +4. jsoup +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 index 143d640..f1f1bb9 100644 --- a/pom.xml +++ b/pom.xml @@ -52,7 +52,7 @@ gr.cite.opendmp repositorydepositbase - 1.0.0 + 1.0.1 @@ -60,6 +60,12 @@ json 20160810 + + + org.jsoup + jsoup + 1.14.3 + @@ -109,11 +115,23 @@ org.json dspacerepository.shaded.org.json + + org.jsoup + dspacerepository.shaded.org.jsoup + + + org.apache.maven.plugins + maven-compiler-plugin + + 9 + 9 + + 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/dspacerepository/config/ConfigLoader.java b/src/main/java/eu/eudat/depositinterface/dspacerepository/config/ConfigLoader.java index 04c27f6..4eca44b 100644 --- a/src/main/java/eu/eudat/depositinterface/dspacerepository/config/ConfigLoader.java +++ b/src/main/java/eu/eudat/depositinterface/dspacerepository/config/ConfigLoader.java @@ -1,5 +1,6 @@ package eu.eudat.depositinterface.dspacerepository.config; public interface ConfigLoader { + byte[] getLogo(); DSpaceConfig getDSpaceConfig(); } diff --git a/src/main/java/eu/eudat/depositinterface/dspacerepository/config/ConfigLoaderImpl.java b/src/main/java/eu/eudat/depositinterface/dspacerepository/config/ConfigLoaderImpl.java index a0807ea..01b17e1 100644 --- a/src/main/java/eu/eudat/depositinterface/dspacerepository/config/ConfigLoaderImpl.java +++ b/src/main/java/eu/eudat/depositinterface/dspacerepository/config/ConfigLoaderImpl.java @@ -7,10 +7,7 @@ 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; +import java.io.*; @Service("dspaceConfigLoader") public class ConfigLoaderImpl implements ConfigLoader{ @@ -34,6 +31,25 @@ public class ConfigLoaderImpl implements ConfigLoader{ return dspaceConfig; } + @Override + public byte[] getLogo() { + String logo = environment.getProperty("configuration.logo"); + InputStream logoStream; + if(logo != null && !logo.isEmpty()) { + logoStream = getStreamFromPath(logo); + } + else{ + logoStream = getClass().getClassLoader().getResourceAsStream("dspace.svg"); + } + try { + return (logoStream != null) ? logoStream.readAllBytes() : null; + } + catch (IOException e){ + logger.error(e.getMessage(), e); + return null; + } + } + private InputStream getStreamFromPath(String filePath) { try { return new FileInputStream(filePath); diff --git a/src/main/java/eu/eudat/depositinterface/dspacerepository/config/DSpaceConfig.java b/src/main/java/eu/eudat/depositinterface/dspacerepository/config/DSpaceConfig.java index 22d3711..834c45f 100644 --- a/src/main/java/eu/eudat/depositinterface/dspacerepository/config/DSpaceConfig.java +++ b/src/main/java/eu/eudat/depositinterface/dspacerepository/config/DSpaceConfig.java @@ -39,12 +39,18 @@ public class DSpaceConfig { private String email; @JsonProperty("password") private String password; + @JsonProperty("workflowEmail") + private String workflowEmail; + @JsonProperty("workflowPassword") + private String workflowPassword; @JsonProperty("repositoryUrl") private String repositoryUrl; @JsonProperty("repositoryRecordUrl") private String repositoryRecordUrl; @JsonProperty("collection") private String collection; + @JsonProperty("hasLogo") + private boolean hasLogo; public int getDepositType() { return depositType; @@ -74,6 +80,20 @@ public class DSpaceConfig { this.password = password; } + public String getWorkflowEmail() { + return workflowEmail; + } + public void setWorkflowEmail(String workflowEmail) { + this.workflowEmail = workflowEmail; + } + + public String getWorkflowPassword() { + return workflowPassword; + } + public void setWorkflowPassword(String workflowPassword) { + this.workflowPassword = workflowPassword; + } + public String getRepositoryUrl() { return repositoryUrl; } @@ -95,12 +115,20 @@ public class DSpaceConfig { this.collection = collection; } + 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/dspacerepository/interfaces/DSpaceDeposit.java b/src/main/java/eu/eudat/depositinterface/dspacerepository/interfaces/DSpaceDeposit.java index 0628456..0678f4f 100644 --- a/src/main/java/eu/eudat/depositinterface/dspacerepository/interfaces/DSpaceDeposit.java +++ b/src/main/java/eu/eudat/depositinterface/dspacerepository/interfaces/DSpaceDeposit.java @@ -1,26 +1,33 @@ package eu.eudat.depositinterface.dspacerepository.interfaces; -import com.fasterxml.jackson.core.type.TypeReference; +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.databind.JsonNode; import com.fasterxml.jackson.databind.ObjectMapper; import eu.eudat.depositinterface.dspacerepository.config.ConfigLoader; import eu.eudat.depositinterface.dspacerepository.config.DSpaceConfig; import eu.eudat.depositinterface.models.DMPDepositModel; import eu.eudat.depositinterface.repository.RepositoryDeposit; import eu.eudat.depositinterface.repository.RepositoryDepositConfiguration; +import org.json.JSONObject; +import org.jsoup.Jsoup; +import org.jsoup.nodes.Document; +import org.jsoup.nodes.Element; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.core.env.Environment; -import org.springframework.http.HttpEntity; -import org.springframework.http.HttpHeaders; -import org.springframework.http.HttpMethod; -import org.springframework.http.MediaType; +import org.springframework.http.*; import org.springframework.http.client.HttpComponentsClientHttpRequestFactory; import org.springframework.stereotype.Component; import org.springframework.util.LinkedMultiValueMap; 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.text.DateFormat; import java.text.SimpleDateFormat; import java.util.*; @@ -35,11 +42,15 @@ public class DSpaceDeposit implements RepositoryDeposit { private String csrfToken; private String bearerToken; + private String submitterId; + + private String repositoryApiUrl; @Autowired public DSpaceDeposit(ConfigLoader configLoader, Environment environment){ this.configLoader = configLoader; this.environment = environment; + this.repositoryApiUrl = configLoader.getDSpaceConfig().getRepositoryUrl(); } @Override @@ -49,6 +60,7 @@ public class DSpaceDeposit implements RepositoryDeposit { this.setCsrfToken(); this.setBearerToken(dSpaceConfig.getEmail(), dSpaceConfig.getPassword()); + this.setSubmitterId(); if(dmpDepositModel.getPreviousDOI() == null || dmpDepositModel.getPreviousDOI().isEmpty()){ RestTemplate restTemplate = new RestTemplate(); @@ -56,48 +68,253 @@ public class DSpaceDeposit implements RepositoryDeposit { HttpHeaders headers = this.createHeaders(); headers.setContentType(MediaType.APPLICATION_JSON); - String url = dSpaceConfig.getRepositoryUrl() + "submission/workspaceitems?owningCollection=" + dSpaceConfig.getCollection(); + String url = this.repositoryApiUrl + "submission/workspaceitems?owningCollection=" + dSpaceConfig.getCollection(); Object response = restTemplate.exchange(url, HttpMethod.POST, new HttpEntity<>("", headers), Object.class).getBody(); Map respMap = objectMapper.convertValue(response, Map.class); String id = String.valueOf(respMap.get("id")); + respMap = (Map) respMap.get("_embedded"); + respMap = (Map) respMap.get("item"); + String itemId = String.valueOf(respMap.get("id")); - PatchEntity entity = new PatchEntity(); + url = this.repositoryApiUrl + "submission/workspaceitems/" + id; + sendPatchRequest(url, "add", "/sections/traditionalpageone/dc.title", dmpDepositModel.getLabel()); + DateFormat df = new SimpleDateFormat("yyyy-MM-dd"); + sendPatchRequest(url, "add", "/sections/traditionalpageone/dc.date.issued", df.format(new Date())); + + PatchBooleanEntity entity = new PatchBooleanEntity(); entity.setOp("add"); - entity.setPath("/sections/traditionalpageone/dc.title"); - List> value = new ArrayList<>(); - Map title = new HashMap<>(); - title.put("value", dmpDepositModel.getLabel()); - value.add(title); - entity.setValue(value); + entity.setPath("/sections/license/granted"); + entity.setValue(true); - url = dSpaceConfig.getRepositoryUrl() + "submission/workspaceitems/" + id; - List entityList = new ArrayList<>(); + List entityList = new ArrayList<>(); entityList.add(entity); logger.debug(objectMapper.writeValueAsString(entityList)); restTemplate.exchange(url, HttpMethod.PATCH, new HttpEntity<>(entityList, headers), Object.class); + sendPatchRequest(url, "add", "/sections/traditionalpageone/dc.contributor.author", "Argos User"); + sendPatchRequest(url, "add", "/sections/traditionalpageone/dc.publisher", "Argos User"); - entity = new PatchEntity(); - entity.setOp("add"); - entity.setPath("/sections/traditionalpageone/dc.date.issued"); - value = new ArrayList<>(); - Map date = new HashMap<>(); - DateFormat df = new SimpleDateFormat("dd-MM-yyyy"); - date.put("value", df.format(new Date())); - value.add(date); - entity.setValue(value); + this.uploadFiles(dmpDepositModel, url); - entityList = new ArrayList<>(); - entityList.add(entity); - logger.debug(objectMapper.writeValueAsString(entityList)); - restTemplate.exchange(url, HttpMethod.PATCH, new HttpEntity<>(entityList, headers), Object.class); + String workFlowId = this.createWorkflow(url); + + this.setBearerToken(dSpaceConfig.getWorkflowEmail(), dSpaceConfig.getWorkflowPassword()); + String claimedTaskId = this.createClaimedTask(workFlowId); + + this.submitTask(claimedTaskId); + + return this.getHandle(itemId); + + } + else{ + String itemId = this.getItemIdFromHandle(dSpaceConfig.getRepositoryRecordUrl(), dmpDepositModel.getPreviousDOI()); + + this.setBearerToken(dSpaceConfig.getWorkflowEmail(), dSpaceConfig.getWorkflowPassword()); + String workSpaceItemId = this.createNewVersion(itemId); + + this.deleteFiles(workSpaceItemId); + + String workSpaceItemUrl = this.repositoryApiUrl + "submission/workspaceitems/" + workSpaceItemId; + + this.uploadFiles(dmpDepositModel, workSpaceItemUrl); + + String workFlowId = this.createWorkflow(workSpaceItemUrl); + + String claimedTaskId = this.createClaimedTask(workFlowId); + + this.submitTask(claimedTaskId); + + return this.getHandle(itemId); } - return null; - } + private void deleteFiles(String workSpaceItemId){ + RestTemplate restTemplate = new RestTemplate(); + HttpHeaders headers = this.createHeaders(); + String workSpaceItemUrl = this.repositoryApiUrl + "submission/workspaceitems/" + workSpaceItemId; + Object response = restTemplate.exchange(workSpaceItemUrl, HttpMethod.GET, new HttpEntity<>(headers), Object.class).getBody(); + Map respMap = objectMapper.convertValue(response, Map.class); + respMap = (Map) respMap.get("sections"); + respMap = (Map) respMap.get("upload"); + List files = (List) respMap.get("files"); + for(Object file: files){ + respMap = objectMapper.convertValue(file, Map.class); + String fileId = String.valueOf(respMap.get("uuid")); + String bitStreamUrl = this.repositoryApiUrl + "core/bitstreams/" + fileId; + restTemplate.exchange(bitStreamUrl, HttpMethod.DELETE, new HttpEntity<>(headers), Object.class); + } + } + + private String createNewVersion(String itemId){ + RestTemplate restTemplate = new RestTemplate(); + + HttpHeaders headers = this.createHeaders(); + headers.add("Content-Type", "text/uri-list"); + + String itemUrl = this.repositoryApiUrl + "core/items/" + itemId; + Object response = restTemplate.postForEntity(this.repositoryApiUrl + "versioning/versions", new HttpEntity<>(itemUrl, headers), Object.class).getBody(); + Map respMap = objectMapper.convertValue(response, Map.class); + respMap = (Map) respMap.get("_links"); + respMap = (Map) respMap.get("versionhistory"); + String versionHistoryUrl = (String) respMap.get("href"); + + response = restTemplate.exchange(versionHistoryUrl, HttpMethod.GET, new HttpEntity<>(headers), Object.class).getBody(); + respMap = objectMapper.convertValue(response, Map.class); + respMap = (Map) respMap.get("_links"); + respMap = (Map) respMap.get("draftVersion"); + String draftVersionUrl = (String) respMap.get("href"); + + response = restTemplate.exchange(draftVersionUrl, HttpMethod.GET, new HttpEntity<>(headers), Object.class).getBody(); + respMap = objectMapper.convertValue(response, Map.class); + + return String.valueOf(respMap.get("id")); + } + + private String getHandle(String itemId){ + RestTemplate restTemplate = new RestTemplate(); + + HttpHeaders headers = this.createHeaders(); + String url = this.repositoryApiUrl + "core/items/" + itemId; + Object response = restTemplate.exchange(url, HttpMethod.GET, new HttpEntity<>(headers), Object.class).getBody(); + Map respMap = objectMapper.convertValue(response, Map.class); + + return (String) respMap.get("handle"); + } + + private void submitTask(String claimedTaskId){ + RestTemplate restTemplate = new RestTemplate(); + + HttpHeaders headers = this.createHeaders(); + headers.setContentType(MediaType.APPLICATION_FORM_URLENCODED); + + MultiValueMap map = new LinkedMultiValueMap<>(); + map.add("submit_approve", true); + + HttpEntity> entity = new HttpEntity<>(map, headers); + String url = this.repositoryApiUrl + "workflow/claimedtasks/" + claimedTaskId; + restTemplate.exchange(url, HttpMethod.POST, entity, Object.class); + } + + private String createClaimedTask(String workFlowId){ + RestTemplate restTemplate = new RestTemplate(); + + HttpHeaders headers = this.createHeaders(); + headers.add("Content-Type", "text/uri-list"); + + String poolTaskId = this.getPoolTaskId(workFlowId); + + String pooltaskUrl = this.repositoryApiUrl + "workflow/pooltasks/" + poolTaskId; + Object response = restTemplate.postForEntity(this.repositoryApiUrl + "workflow/claimedtasks", new HttpEntity<>(pooltaskUrl, headers), Object.class).getBody(); + Map respMap = objectMapper.convertValue(response, Map.class); + + return String.valueOf(respMap.get("id")); + } + + private String getPoolTaskId(String workFlowId){ + RestTemplate restTemplate = new RestTemplate(); + + HttpHeaders headers = this.createHeaders(); + String url = this.repositoryApiUrl + "workflow/pooltasks/search/findByUser?uuid=" + this.submitterId; + Object response = restTemplate.exchange(url, HttpMethod.GET, new HttpEntity<>(headers), Object.class).getBody(); + Map respMap = objectMapper.convertValue(response, Map.class); + Object embedded = respMap.get("_embedded"); + respMap = objectMapper.convertValue(embedded, Map.class); + List pooltasks = (List) respMap.get("pooltasks"); + for(Object pooltask: pooltasks){ + JsonNode task = objectMapper.valueToTree(pooltask); + JsonNode workFlowItem = task.get("_embedded").get("workflowitem"); + int wfId = workFlowItem.get("id").asInt(); + if(wfId == Integer.parseInt(workFlowId)){ + return String.valueOf(task.get("id").asInt()); + } + } + return null; + } + + private String createWorkflow(String workSpaceItemUrl){ + RestTemplate restTemplate = new RestTemplate(); + + HttpHeaders headers = this.createHeaders(); + headers.add("Content-Type", "text/uri-list"); + + Object response = restTemplate.postForEntity(this.repositoryApiUrl + "workflow/workflowitems", new HttpEntity<>(workSpaceItemUrl, headers), Object.class).getBody(); + Map respMap = objectMapper.convertValue(response, Map.class); + + return String.valueOf(respMap.get("id")); + } + + private void uploadFiles(DMPDepositModel dmpDepositModel, String url) throws IOException { + this.uploadFile(dmpDepositModel.getPdfFileName(), dmpDepositModel.getPdfFile(), url); + + 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, url); + Files.deleteIfExists(rdaJson.toPath()); + + if(dmpDepositModel.getSupportingFilesZip() != null) { + this.uploadFile(dmpDepositModel.getSupportingFilesZip().getName(), dmpDepositModel.getSupportingFilesZip(), url); + } + } + + private void uploadFile(String filename, File file, String url) throws IOException { + HttpHeaders headers =this.createHeaders(); + headers.setContentType(MediaType.MULTIPART_FORM_DATA); + MultiValueMap fileMap = new LinkedMultiValueMap<>(); + ContentDisposition contentDisposition = ContentDisposition + .builder("form-data") + .name("file") + .filename(filename) + .build(); + fileMap.add(HttpHeaders.CONTENT_DISPOSITION, contentDisposition.toString()); + HttpEntity fileEntity = new HttpEntity<>(Files.readAllBytes(file.toPath()), fileMap); + MultiValueMap body = new LinkedMultiValueMap<>(); + body.add("file", fileEntity); + HttpEntity> requestEntity + = new HttpEntity<>(body, headers); + + RestTemplate restTemplate = new RestTemplate(); + restTemplate.postForEntity(url, requestEntity, Object.class); + } + + private void sendPatchRequest(String url, String op, String path, String value) throws JsonProcessingException { + RestTemplate restTemplate = new RestTemplate(); + restTemplate.setRequestFactory(new HttpComponentsClientHttpRequestFactory()); + + HttpHeaders headers = this.createHeaders(); + headers.setContentType(MediaType.APPLICATION_JSON); + + PatchEntity entity = new PatchEntity(); + entity.setOp(op); + entity.setPath(path); + List> v = new ArrayList<>(); + Map map = new HashMap<>(); + map.put("value", value); + v.add(map); + entity.setValue(v); + + List entityList = new ArrayList<>(); + entityList.add(entity); + logger.debug(objectMapper.writeValueAsString(entityList)); + restTemplate.exchange(url, HttpMethod.PATCH, new HttpEntity<>(entityList, headers), Object.class); + } + + private String getItemIdFromHandle(String recordUrl, String handle) throws IOException { + Document doc = Jsoup.connect(recordUrl + handle).get(); + Element element = doc.select("a[href^=/statistics/items]").get(0); + String hrefToItemId = element.attr("href"); + return hrefToItemId.split("/")[3]; + } private HttpHeaders createHeaders() { HttpHeaders headers = new HttpHeaders(); @@ -110,7 +327,7 @@ public class DSpaceDeposit implements RepositoryDeposit { private void setCsrfToken(){ RestTemplate restTemplate = new RestTemplate(); - HttpHeaders headers = restTemplate.exchange(this.configLoader.getDSpaceConfig().getRepositoryUrl(), HttpMethod.GET, null, Object.class).getHeaders(); + HttpHeaders headers = restTemplate.exchange(this.repositoryApiUrl, HttpMethod.GET, null, Object.class).getHeaders(); this.csrfToken = headers.get("DSPACE-XSRF-TOKEN").get(0); } @@ -127,7 +344,18 @@ public class DSpaceDeposit implements RepositoryDeposit { map.add("password", password); HttpEntity> entity = new HttpEntity<>(map, headers); - this.bearerToken = restTemplate.exchange(this.configLoader.getDSpaceConfig().getRepositoryUrl() + "authn/login", HttpMethod.POST, entity, Object.class).getHeaders().get("Authorization").get(0); + this.bearerToken = restTemplate.exchange(this.repositoryApiUrl + "authn/login", HttpMethod.POST, entity, Object.class).getHeaders().get("Authorization").get(0); + } + + private void setSubmitterId(){ + if(this.bearerToken != null){ + String token = this.bearerToken.split(" ")[1]; + String[] chunks = token.split("\\."); + Base64.Decoder decoder = Base64.getUrlDecoder(); + String payload = new String(decoder.decode(chunks[1])); + JSONObject object = new JSONObject(payload); + this.submitterId = object.getString("eid"); + } } @Override @@ -140,4 +368,14 @@ public class DSpaceDeposit implements RepositoryDeposit { public String authenticate(String code) { return null; } + + @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; + } } diff --git a/src/main/java/eu/eudat/depositinterface/dspacerepository/interfaces/PatchBooleanEntity.java b/src/main/java/eu/eudat/depositinterface/dspacerepository/interfaces/PatchBooleanEntity.java new file mode 100644 index 0000000..f44b203 --- /dev/null +++ b/src/main/java/eu/eudat/depositinterface/dspacerepository/interfaces/PatchBooleanEntity.java @@ -0,0 +1,29 @@ +package eu.eudat.depositinterface.dspacerepository.interfaces; + +public class PatchBooleanEntity { + + private String op; + private String path; + private boolean value; + + public String getOp() { + return op; + } + public void setOp(String op) { + this.op = op; + } + + public String getPath() { + return path; + } + public void setPath(String path) { + this.path = path; + } + + public boolean getValue() { + return value; + } + public void setValue(boolean value) { + this.value = value; + } +} diff --git a/src/main/resources/application.properties b/src/main/resources/application.properties index acfb7b1..4507f9f 100644 --- a/src/main/resources/application.properties +++ b/src/main/resources/application.properties @@ -1,2 +1,3 @@ storage.temp=${STORAGE_TMP_DSPACE} -configuration.dspace=${CONFIGURATION_DSPACE} \ No newline at end of file +configuration.dspace=${CONFIGURATION_DSPACE} +configuration.dspace.logo=${CONFIGURATION_LOGO_DSPACE} \ No newline at end of file diff --git a/src/main/resources/dspace.png b/src/main/resources/dspace.png new file mode 100644 index 0000000..77f38a6 Binary files /dev/null and b/src/main/resources/dspace.png differ