commit b1f3219bf6ef3b7499330dc1a7f2e698a91a0948 Author: Aldo Mihasi Date: Fri Dec 30 16:12:18 2022 +0200 initial commit diff --git a/pom.xml b/pom.xml new file mode 100644 index 0000000..143d640 --- /dev/null +++ b/pom.xml @@ -0,0 +1,119 @@ + + + 4.0.0 + + org.springframework.boot + spring-boot-starter-parent + 2.5.2 + + + + gr.cite.opendmp + repositorydepositdspace + ${revision} + jar + + OpenDMP Repository Deposit DSpace + OpenDMP Repository Deposit DSpace + https://code-repo.d4science.org/MaDgiK-CITE/repository-deposit-dspace + + + MIT License + https://code-repo.d4science.org/MaDgiK-CITE/repository-deposit-dspace/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-dspace + + + + 1.0.0-SNAPSHOT + + + + + + org.springframework.boot + spring-boot-starter-web + + + + gr.cite.opendmp + repositorydepositbase + 1.0.0 + + + + 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 + dspacerepository.shaded.org.json + + + + + + + + + diff --git a/src/main/java/eu/eudat/depositinterface/dspacerepository/config/ConfigLoader.java b/src/main/java/eu/eudat/depositinterface/dspacerepository/config/ConfigLoader.java new file mode 100644 index 0000000..04c27f6 --- /dev/null +++ b/src/main/java/eu/eudat/depositinterface/dspacerepository/config/ConfigLoader.java @@ -0,0 +1,5 @@ +package eu.eudat.depositinterface.dspacerepository.config; + +public interface ConfigLoader { + 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 new file mode 100644 index 0000000..a0807ea --- /dev/null +++ b/src/main/java/eu/eudat/depositinterface/dspacerepository/config/ConfigLoaderImpl.java @@ -0,0 +1,45 @@ +package eu.eudat.depositinterface.dspacerepository.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("dspaceConfigLoader") +public class ConfigLoaderImpl implements ConfigLoader{ + private static final Logger logger = LoggerFactory.getLogger(ConfigLoaderImpl.class); + private static final ObjectMapper mapper = new ObjectMapper(); + + private DSpaceConfig dspaceConfig; + + @Autowired + private Environment environment; + + @Override + public DSpaceConfig getDSpaceConfig() { + if(dspaceConfig == null){ + try{ + dspaceConfig = mapper.readValue(getStreamFromPath(environment.getProperty("configuration.dspace")), DSpaceConfig.class); + } catch (IOException e) { + logger.error(e.getLocalizedMessage(), e); + } + } + return dspaceConfig; + } + + 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/dspacerepository/config/DSpaceConfig.java b/src/main/java/eu/eudat/depositinterface/dspacerepository/config/DSpaceConfig.java new file mode 100644 index 0000000..22d3711 --- /dev/null +++ b/src/main/java/eu/eudat/depositinterface/dspacerepository/config/DSpaceConfig.java @@ -0,0 +1,106 @@ +package eu.eudat.depositinterface.dspacerepository.config; + +import com.fasterxml.jackson.annotation.JsonProperty; +import eu.eudat.depositinterface.repository.RepositoryDepositConfiguration; + +public class DSpaceConfig { + 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("email") + private String email; + @JsonProperty("password") + private String password; + @JsonProperty("repositoryUrl") + private String repositoryUrl; + @JsonProperty("repositoryRecordUrl") + private String repositoryRecordUrl; + @JsonProperty("collection") + private String collection; + + 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 getEmail() { + return email; + } + public void setEmail(String email) { + this.email = email; + } + + public String getPassword() { + return password; + } + public void setPassword(String password) { + this.password = password; + } + + 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 getCollection() { + return collection; + } + public void setCollection(String collection) { + this.collection = collection; + } + + public RepositoryDepositConfiguration toRepoConfig() { + RepositoryDepositConfiguration config = new RepositoryDepositConfiguration(); + config.setDepositType(this.depositType); + config.setRepositoryId(this.repositoryId); + config.setRepositoryUrl(this.repositoryUrl); + config.setRepositoryRecordUrl(this.repositoryRecordUrl); + 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 new file mode 100644 index 0000000..0628456 --- /dev/null +++ b/src/main/java/eu/eudat/depositinterface/dspacerepository/interfaces/DSpaceDeposit.java @@ -0,0 +1,143 @@ +package eu.eudat.depositinterface.dspacerepository.interfaces; + +import com.fasterxml.jackson.core.type.TypeReference; +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.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.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.text.DateFormat; +import java.text.SimpleDateFormat; +import java.util.*; + +@Component +public class DSpaceDeposit implements RepositoryDeposit { + private static final Logger logger = LoggerFactory.getLogger(DSpaceDeposit.class); + private static final ObjectMapper objectMapper = new ObjectMapper(); + + private ConfigLoader configLoader; + private Environment environment; + + private String csrfToken; + private String bearerToken; + + @Autowired + public DSpaceDeposit(ConfigLoader configLoader, Environment environment){ + this.configLoader = configLoader; + this.environment = environment; + } + + @Override + public String deposit(DMPDepositModel dmpDepositModel, String repositoryAccessToken) throws Exception { + + DSpaceConfig dSpaceConfig = this.configLoader.getDSpaceConfig(); + + this.setCsrfToken(); + this.setBearerToken(dSpaceConfig.getEmail(), dSpaceConfig.getPassword()); + + if(dmpDepositModel.getPreviousDOI() == null || dmpDepositModel.getPreviousDOI().isEmpty()){ + RestTemplate restTemplate = new RestTemplate(); + restTemplate.setRequestFactory(new HttpComponentsClientHttpRequestFactory()); + + HttpHeaders headers = this.createHeaders(); + headers.setContentType(MediaType.APPLICATION_JSON); + String url = dSpaceConfig.getRepositoryUrl() + "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")); + + PatchEntity entity = new PatchEntity(); + 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); + + url = dSpaceConfig.getRepositoryUrl() + "submission/workspaceitems/" + id; + List entityList = new ArrayList<>(); + entityList.add(entity); + logger.debug(objectMapper.writeValueAsString(entityList)); + restTemplate.exchange(url, HttpMethod.PATCH, new HttpEntity<>(entityList, headers), Object.class); + + + 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); + + entityList = new ArrayList<>(); + entityList.add(entity); + logger.debug(objectMapper.writeValueAsString(entityList)); + restTemplate.exchange(url, HttpMethod.PATCH, new HttpEntity<>(entityList, headers), Object.class); + + } + + return null; + + } + + + private HttpHeaders createHeaders() { + HttpHeaders headers = new HttpHeaders(); + headers.add("X-XSRF-TOKEN", this.csrfToken); + headers.add("Cookie", "DSPACE-XSRF-COOKIE=" + this.csrfToken); + headers.add("Authorization", this.bearerToken); + headers.setAccept(Collections.singletonList(MediaType.APPLICATION_JSON)); + return headers; + } + + private void setCsrfToken(){ + RestTemplate restTemplate = new RestTemplate(); + HttpHeaders headers = restTemplate.exchange(this.configLoader.getDSpaceConfig().getRepositoryUrl(), HttpMethod.GET, null, Object.class).getHeaders(); + this.csrfToken = headers.get("DSPACE-XSRF-TOKEN").get(0); + } + + private void setBearerToken(String email, String password){ + RestTemplate restTemplate = new RestTemplate(); + + HttpHeaders headers = new HttpHeaders(); + headers.setContentType(MediaType.APPLICATION_FORM_URLENCODED); + headers.add("X-XSRF-TOKEN", this.csrfToken); + headers.add("Cookie", "DSPACE-XSRF-COOKIE=" + this.csrfToken); + + MultiValueMap map = new LinkedMultiValueMap<>(); + map.add("user", email); + 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); + } + + @Override + public RepositoryDepositConfiguration getConfiguration() { + eu.eudat.depositinterface.dspacerepository.config.DSpaceConfig dspaceConfig = this.configLoader.getDSpaceConfig(); + return dspaceConfig.toRepoConfig(); + } + + @Override + public String authenticate(String code) { + return null; + } +} diff --git a/src/main/java/eu/eudat/depositinterface/dspacerepository/interfaces/PatchEntity.java b/src/main/java/eu/eudat/depositinterface/dspacerepository/interfaces/PatchEntity.java new file mode 100644 index 0000000..0362db6 --- /dev/null +++ b/src/main/java/eu/eudat/depositinterface/dspacerepository/interfaces/PatchEntity.java @@ -0,0 +1,32 @@ +package eu.eudat.depositinterface.dspacerepository.interfaces; + +import java.util.List; +import java.util.Map; + +public class PatchEntity { + + private String op; + private String path; + private List> 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 List> getValue() { + return value; + } + public void setValue(List> value) { + this.value = value; + } +} diff --git a/src/main/resources/application.properties b/src/main/resources/application.properties new file mode 100644 index 0000000..acfb7b1 --- /dev/null +++ b/src/main/resources/application.properties @@ -0,0 +1,2 @@ +storage.temp=${STORAGE_TMP_DSPACE} +configuration.dspace=${CONFIGURATION_DSPACE} \ No newline at end of file