Loading vospace-ui-backend/src/main/java/it/inaf/ia2/vospace/ui/client/VOSpaceClient.java +32 −3 Original line number Diff line number Diff line Loading @@ -6,6 +6,7 @@ import it.inaf.ia2.vospace.ui.VOSpaceException; import it.inaf.ia2.vospace.ui.VOSpaceUiApplication; import java.io.IOException; import java.io.InputStream; import java.io.StringWriter; import java.io.UncheckedIOException; import java.net.ConnectException; import java.net.URI; Loading @@ -20,7 +21,9 @@ import java.util.function.Function; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpSession; import javax.xml.bind.JAXB; import net.ivoa.xml.uws.v1.JobSummary; import net.ivoa.xml.vospace.v2.Node; import net.ivoa.xml.vospace.v2.Transfer; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; Loading @@ -42,7 +45,7 @@ public class VOSpaceClient { private final ForkJoinPool jaxbExecutor; @Autowired private HttpServletRequest servletRequest; protected HttpServletRequest servletRequest; public VOSpaceClient(@Value("${vospace-backend-url}") String backendUrl) { if (backendUrl.endsWith("/")) { Loading @@ -65,7 +68,18 @@ public class VOSpaceClient { .header("Accept", useJson ? "application/json" : "text/xml") .build(); return call(request, BodyHandlers.ofInputStream(), 200, res -> parseJson(res, Node.class)); return call(request, BodyHandlers.ofInputStream(), 200, res -> unmarshal(res, Node.class)); } public JobSummary startTransferJob(Transfer transfer) { HttpRequest request = getRequest("/transfers?PHASE=RUN") .header("Accept", useJson ? "application/json" : "text/xml") .header("Content-Type", useJson ? "application/json" : "text/xml") .POST(HttpRequest.BodyPublishers.ofString(marshal(transfer))) .build(); return call(request, BodyHandlers.ofInputStream(), 200, res -> unmarshal(res, JobSummary.class)); } private <T, U> U call(HttpRequest request, HttpResponse.BodyHandler<T> responseBodyHandler, int expectedStatusCode, Function<T, U> responseHandler) { Loading Loading @@ -116,7 +130,7 @@ public class VOSpaceClient { return null; } private <T> T parseJson(InputStream in, Class<T> type) { private <T> T unmarshal(InputStream in, Class<T> type) { try { if (useJson) { return MAPPER.readValue(in, type); Loading @@ -129,6 +143,21 @@ public class VOSpaceClient { } } private String marshal(Object data) { try { if (useJson) { return MAPPER.writeValueAsString(data); } else { try ( StringWriter sw = new StringWriter()) { JAXB.marshal(data, sw); return sw.toString(); } } } catch (IOException ex) { throw new UncheckedIOException(ex); } } private static <T> void logServerError(HttpRequest request, HttpResponse<T> response) { if (response.body() instanceof String) { logServerErrorString(request, (HttpResponse<String>) response); Loading vospace-ui-backend/src/main/java/it/inaf/ia2/vospace/ui/controller/JobController.java 0 → 100644 +57 −0 Original line number Diff line number Diff line package it.inaf.ia2.vospace.ui.controller; import it.inaf.ia2.vospace.ui.client.VOSpaceClient; import it.inaf.ia2.vospace.ui.data.Job; import java.util.ArrayList; import java.util.List; import net.ivoa.xml.uws.v1.ExecutionPhase; import net.ivoa.xml.uws.v1.JobSummary; import net.ivoa.xml.vospace.v2.Protocol; import net.ivoa.xml.vospace.v2.Transfer; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value; import org.springframework.http.MediaType; import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RestController; @RestController public class JobController { @Value("${vospace-authority}") private String authority; @Autowired private VOSpaceClient client; @PostMapping(value = "/recall", consumes = MediaType.APPLICATION_JSON_VALUE, produces = MediaType.APPLICATION_JSON_VALUE) public ResponseEntity<Job> startRecallFromTapeJob(@RequestBody List<String> paths) { if (paths.size() != 1) { throw new UnsupportedOperationException(); } Transfer transfer = new Transfer(); transfer.setDirection("pullToVoSpace"); transfer.setTarget("vos://" + authority + paths.get(0)); Protocol protocol = new Protocol(); protocol.setUri("ia2:tape-recall"); transfer.getProtocol().add(protocol); JobSummary job = client.startTransferJob(transfer); if (job.getPhase() == ExecutionPhase.QUEUED) { return ResponseEntity.ok(new Job(job)); } // TODO: proper handling throw new RuntimeException("Error while executing job " + job.getJobId() + ". Job phase is " + job.getPhase() + ". QUEUED expected"); } @GetMapping(value = "/jobs", produces = MediaType.APPLICATION_JSON_VALUE) public List<Job> getJobs() { // TODO return new ArrayList<>(); } } vospace-ui-backend/src/main/java/it/inaf/ia2/vospace/ui/data/Job.java 0 → 100644 +43 −0 Original line number Diff line number Diff line package it.inaf.ia2.vospace.ui.data; import net.ivoa.xml.uws.v1.ExecutionPhase; import net.ivoa.xml.uws.v1.JobSummary; public class Job { private String id; private ExecutionPhase phase; private boolean read; public Job() { } public Job(JobSummary job) { this.id = job.getJobId(); this.phase = job.getPhase(); } public String getId() { return id; } public void setId(String id) { this.id = id; } public ExecutionPhase getPhase() { return phase; } public void setPhase(ExecutionPhase phase) { this.phase = phase; } public boolean isRead() { return read; } public void setRead(boolean read) { this.read = read; } } vospace-ui-backend/src/main/java/it/inaf/ia2/vospace/ui/service/NodesService.java +1 −1 Original line number Diff line number Diff line Loading @@ -85,6 +85,6 @@ public class NodesService { return true; } // TODO: check user group return false; return true; // temporary always true } } vospace-ui-backend/src/main/resources/application.properties +3 −1 Original line number Diff line number Diff line Loading @@ -2,8 +2,10 @@ server.port=8085 vospace-backend-url=http://localhost:8083/vospace vospace-authority=example.com!vospace use-json=true use-json=false # For development only: spring.profiles.active=dev cors.allowed.origin=http://localhost:8080 logging.level.it.inaf=TRACE Loading
vospace-ui-backend/src/main/java/it/inaf/ia2/vospace/ui/client/VOSpaceClient.java +32 −3 Original line number Diff line number Diff line Loading @@ -6,6 +6,7 @@ import it.inaf.ia2.vospace.ui.VOSpaceException; import it.inaf.ia2.vospace.ui.VOSpaceUiApplication; import java.io.IOException; import java.io.InputStream; import java.io.StringWriter; import java.io.UncheckedIOException; import java.net.ConnectException; import java.net.URI; Loading @@ -20,7 +21,9 @@ import java.util.function.Function; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpSession; import javax.xml.bind.JAXB; import net.ivoa.xml.uws.v1.JobSummary; import net.ivoa.xml.vospace.v2.Node; import net.ivoa.xml.vospace.v2.Transfer; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; Loading @@ -42,7 +45,7 @@ public class VOSpaceClient { private final ForkJoinPool jaxbExecutor; @Autowired private HttpServletRequest servletRequest; protected HttpServletRequest servletRequest; public VOSpaceClient(@Value("${vospace-backend-url}") String backendUrl) { if (backendUrl.endsWith("/")) { Loading @@ -65,7 +68,18 @@ public class VOSpaceClient { .header("Accept", useJson ? "application/json" : "text/xml") .build(); return call(request, BodyHandlers.ofInputStream(), 200, res -> parseJson(res, Node.class)); return call(request, BodyHandlers.ofInputStream(), 200, res -> unmarshal(res, Node.class)); } public JobSummary startTransferJob(Transfer transfer) { HttpRequest request = getRequest("/transfers?PHASE=RUN") .header("Accept", useJson ? "application/json" : "text/xml") .header("Content-Type", useJson ? "application/json" : "text/xml") .POST(HttpRequest.BodyPublishers.ofString(marshal(transfer))) .build(); return call(request, BodyHandlers.ofInputStream(), 200, res -> unmarshal(res, JobSummary.class)); } private <T, U> U call(HttpRequest request, HttpResponse.BodyHandler<T> responseBodyHandler, int expectedStatusCode, Function<T, U> responseHandler) { Loading Loading @@ -116,7 +130,7 @@ public class VOSpaceClient { return null; } private <T> T parseJson(InputStream in, Class<T> type) { private <T> T unmarshal(InputStream in, Class<T> type) { try { if (useJson) { return MAPPER.readValue(in, type); Loading @@ -129,6 +143,21 @@ public class VOSpaceClient { } } private String marshal(Object data) { try { if (useJson) { return MAPPER.writeValueAsString(data); } else { try ( StringWriter sw = new StringWriter()) { JAXB.marshal(data, sw); return sw.toString(); } } } catch (IOException ex) { throw new UncheckedIOException(ex); } } private static <T> void logServerError(HttpRequest request, HttpResponse<T> response) { if (response.body() instanceof String) { logServerErrorString(request, (HttpResponse<String>) response); Loading
vospace-ui-backend/src/main/java/it/inaf/ia2/vospace/ui/controller/JobController.java 0 → 100644 +57 −0 Original line number Diff line number Diff line package it.inaf.ia2.vospace.ui.controller; import it.inaf.ia2.vospace.ui.client.VOSpaceClient; import it.inaf.ia2.vospace.ui.data.Job; import java.util.ArrayList; import java.util.List; import net.ivoa.xml.uws.v1.ExecutionPhase; import net.ivoa.xml.uws.v1.JobSummary; import net.ivoa.xml.vospace.v2.Protocol; import net.ivoa.xml.vospace.v2.Transfer; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value; import org.springframework.http.MediaType; import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RestController; @RestController public class JobController { @Value("${vospace-authority}") private String authority; @Autowired private VOSpaceClient client; @PostMapping(value = "/recall", consumes = MediaType.APPLICATION_JSON_VALUE, produces = MediaType.APPLICATION_JSON_VALUE) public ResponseEntity<Job> startRecallFromTapeJob(@RequestBody List<String> paths) { if (paths.size() != 1) { throw new UnsupportedOperationException(); } Transfer transfer = new Transfer(); transfer.setDirection("pullToVoSpace"); transfer.setTarget("vos://" + authority + paths.get(0)); Protocol protocol = new Protocol(); protocol.setUri("ia2:tape-recall"); transfer.getProtocol().add(protocol); JobSummary job = client.startTransferJob(transfer); if (job.getPhase() == ExecutionPhase.QUEUED) { return ResponseEntity.ok(new Job(job)); } // TODO: proper handling throw new RuntimeException("Error while executing job " + job.getJobId() + ". Job phase is " + job.getPhase() + ". QUEUED expected"); } @GetMapping(value = "/jobs", produces = MediaType.APPLICATION_JSON_VALUE) public List<Job> getJobs() { // TODO return new ArrayList<>(); } }
vospace-ui-backend/src/main/java/it/inaf/ia2/vospace/ui/data/Job.java 0 → 100644 +43 −0 Original line number Diff line number Diff line package it.inaf.ia2.vospace.ui.data; import net.ivoa.xml.uws.v1.ExecutionPhase; import net.ivoa.xml.uws.v1.JobSummary; public class Job { private String id; private ExecutionPhase phase; private boolean read; public Job() { } public Job(JobSummary job) { this.id = job.getJobId(); this.phase = job.getPhase(); } public String getId() { return id; } public void setId(String id) { this.id = id; } public ExecutionPhase getPhase() { return phase; } public void setPhase(ExecutionPhase phase) { this.phase = phase; } public boolean isRead() { return read; } public void setRead(boolean read) { this.read = read; } }
vospace-ui-backend/src/main/java/it/inaf/ia2/vospace/ui/service/NodesService.java +1 −1 Original line number Diff line number Diff line Loading @@ -85,6 +85,6 @@ public class NodesService { return true; } // TODO: check user group return false; return true; // temporary always true } }
vospace-ui-backend/src/main/resources/application.properties +3 −1 Original line number Diff line number Diff line Loading @@ -2,8 +2,10 @@ server.port=8085 vospace-backend-url=http://localhost:8083/vospace vospace-authority=example.com!vospace use-json=true use-json=false # For development only: spring.profiles.active=dev cors.allowed.origin=http://localhost:8080 logging.level.it.inaf=TRACE