ckan2zenodo-library/src/main/java/org/gcube/data/publishing/ckan2zenodo/clients/Zenodo.java

229 lines
7.7 KiB
Java

package org.gcube.data.publishing.ckan2zenodo.clients;
import java.io.File;
import java.io.IOException;
import java.net.URL;
import java.nio.file.Files;
import java.nio.file.StandardCopyOption;
import java.util.concurrent.Callable;
import java.util.concurrent.Future;
import javax.ws.rs.client.Client;
import javax.ws.rs.client.ClientBuilder;
import javax.ws.rs.client.Entity;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;
import org.gcube.data.publishing.ckan2zenodo.Fixer;
import org.gcube.data.publishing.ckan2zenodo.model.ZenodoCredentials;
import org.gcube.data.publishing.ckan2zenodo.model.faults.ZenodoException;
import org.gcube.data.publishing.ckan2zenodo.model.zenodo.DepositionMetadata;
import org.gcube.data.publishing.ckan2zenodo.model.zenodo.FileDeposition;
import org.gcube.data.publishing.ckan2zenodo.model.zenodo.ZenodoDeposition;
import org.glassfish.jersey.client.ClientProperties;
import org.glassfish.jersey.media.multipart.FormDataMultiPart;
import org.glassfish.jersey.media.multipart.MultiPartFeature;
import org.glassfish.jersey.media.multipart.file.FileDataBodyPart;
import com.fasterxml.jackson.annotation.JsonInclude.Include;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.DeserializationFeature;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.SerializationFeature;
import lombok.NonNull;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
@RequiredArgsConstructor
@Slf4j
public class Zenodo {
private static final String CONTENT_TYPE="application/json";
private static final String DEPOSITION_BASE_URL="deposit/depositions";
private static final String PUBLISH_URL_PRE="deposit/depositions";
private static final String PUBLISH_URL_POST="actions/publish";
private static final String UNLOCK_URL_PRE="deposit/depositions";
private static final String UNLOCK_URL_POST="actions/edit";
private static final String ACCESS_TOKEN="access_token";
private static ObjectMapper mapper = new ObjectMapper();
static {
mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES,false);
mapper.configure(SerializationFeature.WRITE_EMPTY_JSON_ARRAYS, false);
mapper.setSerializationInclusion(Include.NON_NULL);
// mapper.configure(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS, false);
}
public static final Zenodo get() {
// READ FROM IS
throw new RuntimeException("IMPLEMENT THIS");
}
@NonNull
private ZenodoCredentials credentials;
Client client;
private synchronized Client getWebClient() {
if(client==null) {
client = ClientBuilder.newClient()
.property(ClientProperties.SUPPRESS_HTTP_COMPLIANCE_VALIDATION, true);
client.register(MultiPartFeature.class);
}
return client;
}
public ZenodoDeposition readDeposition(Integer id) throws ZenodoException {
Response resp= getWebClient().target(credentials.getBaseUrl()).
path(DEPOSITION_BASE_URL).path(id+"").
queryParam(ACCESS_TOKEN, credentials.getKey()).request(CONTENT_TYPE)
.get();
return check(resp,ZenodoDeposition.class);
}
private static <T> T check(Response resp, Class<T> clazz) throws ZenodoException{
if(resp.getStatus()<200||resp.getStatus()>=300) {
throw new ZenodoException("RESP STATUS IS "+resp.getStatus()+". Message : "+resp.readEntity(String.class));
}else {
if(clazz==null) return null;
String respString=resp.readEntity(String.class);
try {
return mapper.readValue(Fixer.fixIncoming(respString), clazz);
} catch (IOException e) {
throw new ZenodoException("Unable to parse response from Zenodo. Content was : \n "+respString,e);
}
}
}
public ZenodoDeposition updateMetadata(ZenodoDeposition dep) throws ZenodoException {
return updateMetadata(dep.getId(), dep.getMetadata());
}
public FileDeposition uploadFile(ZenodoDeposition dep, String toUploadName,String urlString) throws ZenodoException {
Callable<Response> call=new Callable<Response>() {
@Override
public Response call() throws Exception {
File temp=null;
try {
log.debug("Downloading "+urlString);
//Download locally into temp
URL url=new URL(urlString);
temp=File.createTempFile("zenodo_", ".tmp");
long size=Files.copy(url.openStream(), temp.toPath(),StandardCopyOption.REPLACE_EXISTING);
//upload
FormDataMultiPart multi=new FormDataMultiPart();
FileDataBodyPart fileDataBodyPart = new FileDataBodyPart("file",
temp,MediaType.APPLICATION_OCTET_STREAM_TYPE);
multi.field("name", toUploadName);
multi.bodyPart(fileDataBodyPart);
log.debug("Starting transfer of "+toUploadName+" ("+urlString+") into "+dep.getId());
Response toReturn=getWebClient().target(credentials.getBaseUrl()).
path(DEPOSITION_BASE_URL).path(dep.getId()+"").path("files").
queryParam(ACCESS_TOKEN, credentials.getKey()).request(CONTENT_TYPE)
.post(Entity.entity(multi,multi.getMediaType()));
log.debug("DONE.");
return toReturn;
}catch(Throwable e) {
throw new ZenodoException("Unable to transfer file "+toUploadName+" url : "+urlString,e);
}finally {
//finally delete temp
if(temp!=null) Files.deleteIfExists(temp.toPath());
}
}
};
log.debug("Submitting request to upload "+urlString+" to Manager");
Future<Response> resp=FileUploaderManager.submitForResponse(call);
try {
return check(resp.get(),FileDeposition.class);
}catch(ZenodoException z) {
throw z;
}catch(Throwable t) {
throw new ZenodoException(t.getMessage(),t);
}
//return
}
private ZenodoDeposition updateMetadata(Integer depositionId,DepositionMetadata meta) throws ZenodoException {
try{
String serialized="{\"metadata\":"+Fixer.fixIncoming(mapper.writeValueAsString(meta))+"}";
try {
Response resp = getWebClient().target(credentials.getBaseUrl()).
path(DEPOSITION_BASE_URL).path(depositionId+"").
queryParam(ACCESS_TOKEN, credentials.getKey()).request(CONTENT_TYPE)
.put(Entity.json(serialized));
return check(resp,ZenodoDeposition.class);
}catch(Throwable t) {
log.debug("Error while tryin to update "+serialized);
throw t;
}
}catch(JsonProcessingException e) {
log.debug("Error while parsing "+meta,e);
throw new ZenodoException("Internal error.",e);
}
}
public ZenodoDeposition unlockPublished(Integer depositionId) throws ZenodoException {
Response resp = getWebClient().target(credentials.getBaseUrl()).
path(UNLOCK_URL_PRE).
path(depositionId+"").
path(UNLOCK_URL_POST).
queryParam(ACCESS_TOKEN, credentials.getKey()).request(CONTENT_TYPE)
.post(Entity.json("{}"));
return check(resp,ZenodoDeposition.class);
}
public void deleteDeposition(Integer depositionId) throws ZenodoException {
Response resp = getWebClient().target(credentials.getBaseUrl()).
path(DEPOSITION_BASE_URL).path(depositionId+"").
queryParam(ACCESS_TOKEN, credentials.getKey()).request(CONTENT_TYPE)
.delete();
check(resp,null);
}
public ZenodoDeposition createNew() throws ZenodoException {
Response resp = getWebClient().target(credentials.getBaseUrl()).
path(DEPOSITION_BASE_URL).
queryParam(ACCESS_TOKEN, credentials.getKey()).request(CONTENT_TYPE)
.post(Entity.json("{}"));
return check(resp,ZenodoDeposition.class);
}
public ZenodoDeposition publish(ZenodoDeposition dep) throws ZenodoException{
return publish(dep.getId());
}
private ZenodoDeposition publish(Integer depositionId) throws ZenodoException{
Response resp = getWebClient().target(credentials.getBaseUrl()).
path(PUBLISH_URL_PRE).
path(depositionId+"").
path(PUBLISH_URL_POST).
queryParam(ACCESS_TOKEN, credentials.getKey()).request(CONTENT_TYPE)
.post(Entity.json("{}"));
return check(resp,ZenodoDeposition.class);
}
}