mirror of
https://github.com/DSpace/DSpace.git
synced 2025-10-07 01:54:22 +00:00
[Task 64334] implemented the scripts prototype
This commit is contained in:
201
dspace-api/src/main/java/org/dspace/content/Process.java
Normal file
201
dspace-api/src/main/java/org/dspace/content/Process.java
Normal file
@@ -0,0 +1,201 @@
|
||||
/**
|
||||
* The contents of this file are subject to the license and copyright
|
||||
* detailed in the LICENSE and NOTICE files at the root of the source
|
||||
* tree and available online at
|
||||
*
|
||||
* http://www.dspace.org/license/
|
||||
*/
|
||||
package org.dspace.content;
|
||||
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
import javax.persistence.Column;
|
||||
import javax.persistence.Entity;
|
||||
import javax.persistence.EnumType;
|
||||
import javax.persistence.Enumerated;
|
||||
import javax.persistence.FetchType;
|
||||
import javax.persistence.GeneratedValue;
|
||||
import javax.persistence.GenerationType;
|
||||
import javax.persistence.Id;
|
||||
import javax.persistence.JoinColumn;
|
||||
import javax.persistence.JoinTable;
|
||||
import javax.persistence.ManyToMany;
|
||||
import javax.persistence.ManyToOne;
|
||||
import javax.persistence.SequenceGenerator;
|
||||
import javax.persistence.Table;
|
||||
import javax.persistence.Temporal;
|
||||
import javax.persistence.TemporalType;
|
||||
|
||||
import org.apache.commons.lang3.builder.EqualsBuilder;
|
||||
import org.apache.commons.lang3.builder.HashCodeBuilder;
|
||||
import org.dspace.core.ReloadableEntity;
|
||||
import org.dspace.eperson.EPerson;
|
||||
|
||||
@Entity
|
||||
@Table(name = "process")
|
||||
public class Process implements ReloadableEntity<Integer> {
|
||||
|
||||
@Id
|
||||
@GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "process_id_seq")
|
||||
@SequenceGenerator(name = "process_id_seq", sequenceName = "process_id_seq", allocationSize = 1)
|
||||
@Column(name = "process_id", unique = true, nullable = false)
|
||||
private Integer processId;
|
||||
|
||||
@ManyToOne
|
||||
@JoinColumn(name = "user_id", nullable = false)
|
||||
private EPerson ePerson;
|
||||
|
||||
@Column(name = "start_time")
|
||||
@Temporal(TemporalType.TIMESTAMP)
|
||||
private Date startTime;
|
||||
|
||||
@Column(name = "finished_time")
|
||||
@Temporal(TemporalType.TIMESTAMP)
|
||||
private Date finishedTime;
|
||||
|
||||
@Column(name = "script", nullable = false)
|
||||
private String name;
|
||||
|
||||
@Column(name = "status")
|
||||
@Enumerated(EnumType.STRING)
|
||||
private ProcessStatus processStatus;
|
||||
|
||||
@Column(name = "parameters")
|
||||
private String parameters;
|
||||
|
||||
@ManyToMany(fetch = FetchType.LAZY)
|
||||
@JoinTable(
|
||||
name = "process2bitstream",
|
||||
joinColumns = {@JoinColumn(name = "process_id")},
|
||||
inverseJoinColumns = {@JoinColumn(name = "bitstream_id")}
|
||||
)
|
||||
private List<Bitstream> bitstreams;
|
||||
|
||||
@Column(name = "creation_time", nullable = false)
|
||||
@Temporal(TemporalType.TIMESTAMP)
|
||||
private Date creationTime;
|
||||
|
||||
protected Process() {
|
||||
}
|
||||
|
||||
public Integer getID() {
|
||||
return processId;
|
||||
}
|
||||
|
||||
public void setProcessId(Integer processId) {
|
||||
this.processId = processId;
|
||||
}
|
||||
|
||||
public EPerson getEPerson() {
|
||||
return ePerson;
|
||||
}
|
||||
|
||||
public void setePerson(EPerson ePerson) {
|
||||
this.ePerson = ePerson;
|
||||
}
|
||||
|
||||
public Date getStartTime() {
|
||||
return startTime;
|
||||
}
|
||||
|
||||
public void setStartTime(Date startTime) {
|
||||
this.startTime = startTime;
|
||||
}
|
||||
|
||||
public Date getFinishedTime() {
|
||||
return finishedTime;
|
||||
}
|
||||
|
||||
public void setFinishedTime(Date finishedTime) {
|
||||
this.finishedTime = finishedTime;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public void setName(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
public ProcessStatus getProcessStatus() {
|
||||
return processStatus;
|
||||
}
|
||||
|
||||
public void setProcessStatus(ProcessStatus processStatus) {
|
||||
this.processStatus = processStatus;
|
||||
}
|
||||
|
||||
/**
|
||||
* To get the parameters, use ProcessService.getParameters() to get a parsed list of DSpaceCommandLineParameters
|
||||
*/
|
||||
protected String getParameters() {
|
||||
return parameters;
|
||||
}
|
||||
|
||||
public void setParameters(String parameters) {
|
||||
this.parameters = parameters;
|
||||
}
|
||||
|
||||
public List<Bitstream> getBitstreams() {
|
||||
return bitstreams;
|
||||
}
|
||||
|
||||
public void setBitstreams(List<Bitstream> bitstreams) {
|
||||
this.bitstreams = bitstreams;
|
||||
}
|
||||
|
||||
public void removeBitstream(Bitstream bitstream) {
|
||||
getBitstreams().remove(bitstream);
|
||||
}
|
||||
|
||||
public void addBitstream(Bitstream bitstream) {
|
||||
getBitstreams().add(bitstream);
|
||||
}
|
||||
|
||||
public void setCreationTime(Date creationTime) {
|
||||
this.creationTime = creationTime;
|
||||
}
|
||||
|
||||
public Date getCreationTime() {
|
||||
return creationTime;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return <code>true</code> if <code>other</code> is the same Bitstream
|
||||
* as this object, <code>false</code> otherwise
|
||||
*
|
||||
* @param other object to compare to
|
||||
* @return <code>true</code> if object passed in represents the same
|
||||
* collection as this object
|
||||
*/
|
||||
@Override
|
||||
public boolean equals(Object other) {
|
||||
return (other instanceof Process &&
|
||||
new EqualsBuilder().append(this.getID(), ((Process) other).getID())
|
||||
.append(this.getName(), ((Process) other).getName())
|
||||
.append(this.getBitstreams(), ((Process) other).getBitstreams())
|
||||
.append(this.getProcessStatus(), ((Process) other).getProcessStatus())
|
||||
.append(this.getFinishedTime(), ((Process) other).getFinishedTime())
|
||||
.append(this.getStartTime(), ((Process) other).getStartTime())
|
||||
.append(this.getParameters(), ((Process) other).getParameters())
|
||||
.append(this.getCreationTime(), ((Process) other).getCreationTime())
|
||||
.append(this.getEPerson(), ((Process) other).getEPerson())
|
||||
.isEquals());
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return new HashCodeBuilder(17, 37)
|
||||
.append(this.getID())
|
||||
.append(this.getName())
|
||||
.append(this.getBitstreams())
|
||||
.append(this.getProcessStatus())
|
||||
.append(this.getFinishedTime())
|
||||
.append(this.getStartTime())
|
||||
.append(this.getParameters())
|
||||
.append(this.getCreationTime())
|
||||
.append(this.getEPerson())
|
||||
.toHashCode();
|
||||
}
|
||||
}
|
@@ -0,0 +1,146 @@
|
||||
/**
|
||||
* The contents of this file are subject to the license and copyright
|
||||
* detailed in the LICENSE and NOTICE files at the root of the source
|
||||
* tree and available online at
|
||||
*
|
||||
* http://www.dspace.org/license/
|
||||
*/
|
||||
package org.dspace.content;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.sql.SQLException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.Comparator;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.apache.logging.log4j.Logger;
|
||||
import org.dspace.authorize.AuthorizeException;
|
||||
import org.dspace.content.dao.ProcessDAO;
|
||||
import org.dspace.content.service.BitstreamService;
|
||||
import org.dspace.content.service.ProcessService;
|
||||
import org.dspace.core.Context;
|
||||
import org.dspace.eperson.EPerson;
|
||||
import org.dspace.scripts.DSpaceCommandLineParameter;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
|
||||
public class ProcessServiceImpl implements ProcessService {
|
||||
|
||||
private static final Logger log = org.apache.logging.log4j.LogManager.getLogger(ProcessService.class);
|
||||
|
||||
@Autowired
|
||||
private ProcessDAO processDAO;
|
||||
|
||||
@Autowired
|
||||
private BitstreamService bitstreamService;
|
||||
|
||||
@Override
|
||||
public Process create(Context context, EPerson ePerson, String scriptName,
|
||||
List<DSpaceCommandLineParameter> parameters) throws SQLException {
|
||||
|
||||
Process process = new Process();
|
||||
process.setePerson(ePerson);
|
||||
process.setName(scriptName);
|
||||
process.setParameters(DSpaceCommandLineParameter.concatenate(parameters));
|
||||
process.setCreationTime(new Date());
|
||||
Process createdProcess = processDAO.create(context, process);
|
||||
log.info("Process has been created for eperson with email: " + ePerson.getEmail() + " with ID: "
|
||||
+ createdProcess.getID() + " and scriptName: " + scriptName + " and parameters: " + parameters);
|
||||
return createdProcess;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Process find(Context context, int processId) throws SQLException {
|
||||
return processDAO.findByID(context, Process.class, processId);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<Process> findAll(Context context) throws SQLException {
|
||||
return processDAO.findAll(context, Process.class);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<Process> findAllSortByScript(Context context) throws SQLException {
|
||||
return processDAO.findAllSortByScript(context);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<Process> findAllSortByStartTime(Context context) throws SQLException {
|
||||
List<Process> processes = findAll(context);
|
||||
Comparator<Process> comparing = Comparator
|
||||
.comparing(Process::getStartTime, Comparator.nullsLast(Comparator.naturalOrder()));
|
||||
comparing = comparing.thenComparing(Process::getID);
|
||||
processes.sort(comparing);
|
||||
return processes;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void start(Context context, Process process) throws SQLException {
|
||||
process.setProcessStatus(ProcessStatus.RUNNING);
|
||||
process.setStartTime(new Date());
|
||||
update(context, process);
|
||||
log.info("Process with ID: " + process.getID() + " and name: " + process.getName() + " has started");
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void fail(Context context, Process process) throws SQLException {
|
||||
process.setProcessStatus(ProcessStatus.FAILED);
|
||||
process.setFinishedTime(new Date());
|
||||
update(context, process);
|
||||
log.info("Process with ID: " + process.getID() + " and name: " + process.getName() + " has failed");
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void complete(Context context, Process process) throws SQLException {
|
||||
process.setProcessStatus(ProcessStatus.COMPLETED);
|
||||
process.setFinishedTime(new Date());
|
||||
update(context, process);
|
||||
log.info("Process with ID: " + process.getID() + " and name: " + process.getName() + " has been completed");
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void appendFile(Context context, Process process, InputStream is, String type)
|
||||
throws IOException, SQLException, AuthorizeException {
|
||||
Bitstream bitstream = bitstreamService.create(context, is);
|
||||
bitstream.setName(context, "process-" + process.getID() + ".log");
|
||||
bitstreamService.addMetadata(context, bitstream, "process", "type", null, null, type);
|
||||
bitstreamService.update(context, bitstream);
|
||||
process.addBitstream(bitstream);
|
||||
update(context, process);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void delete(Context context, Process process) throws SQLException {
|
||||
processDAO.delete(context, process);
|
||||
log.info("Process with ID: " + process.getID() + " and name: " + process.getName() + " has been deleted");
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void update(Context context, Process process) throws SQLException {
|
||||
processDAO.save(context, process);
|
||||
}
|
||||
|
||||
public List<DSpaceCommandLineParameter> getParameters(Process process) {
|
||||
if (StringUtils.isBlank(process.getParameters())) {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
|
||||
String[] parameterArray = process.getParameters().split(Pattern.quote(DSpaceCommandLineParameter.SEPARATOR));
|
||||
List<DSpaceCommandLineParameter> parameterList = new ArrayList<>();
|
||||
|
||||
for (String parameter : parameterArray) {
|
||||
parameterList.add(new DSpaceCommandLineParameter(parameter));
|
||||
}
|
||||
|
||||
return parameterList;
|
||||
}
|
||||
|
||||
}
|
@@ -0,0 +1,16 @@
|
||||
/**
|
||||
* The contents of this file are subject to the license and copyright
|
||||
* detailed in the LICENSE and NOTICE files at the root of the source
|
||||
* tree and available online at
|
||||
*
|
||||
* http://www.dspace.org/license/
|
||||
*/
|
||||
package org.dspace.content;
|
||||
|
||||
public enum ProcessStatus {
|
||||
SCHEDULED,
|
||||
RUNNING,
|
||||
COMPLETED,
|
||||
FAILED
|
||||
|
||||
}
|
@@ -0,0 +1,21 @@
|
||||
/**
|
||||
* The contents of this file are subject to the license and copyright
|
||||
* detailed in the LICENSE and NOTICE files at the root of the source
|
||||
* tree and available online at
|
||||
*
|
||||
* http://www.dspace.org/license/
|
||||
*/
|
||||
package org.dspace.content.dao;
|
||||
|
||||
import java.sql.SQLException;
|
||||
import java.util.List;
|
||||
|
||||
import org.dspace.content.Process;
|
||||
import org.dspace.core.Context;
|
||||
import org.dspace.core.GenericDAO;
|
||||
|
||||
public interface ProcessDAO extends GenericDAO<Process> {
|
||||
|
||||
public List<Process> findAllSortByScript(Context context) throws SQLException;
|
||||
public List<Process> findAllSortByStartTime(Context context) throws SQLException;
|
||||
}
|
@@ -0,0 +1,48 @@
|
||||
/**
|
||||
* The contents of this file are subject to the license and copyright
|
||||
* detailed in the LICENSE and NOTICE files at the root of the source
|
||||
* tree and available online at
|
||||
*
|
||||
* http://www.dspace.org/license/
|
||||
*/
|
||||
package org.dspace.content.dao.impl;
|
||||
|
||||
import java.sql.SQLException;
|
||||
import java.util.List;
|
||||
import javax.persistence.criteria.CriteriaBuilder;
|
||||
import javax.persistence.criteria.CriteriaQuery;
|
||||
import javax.persistence.criteria.Root;
|
||||
|
||||
import org.dspace.content.Process;
|
||||
import org.dspace.content.Process_;
|
||||
import org.dspace.content.dao.ProcessDAO;
|
||||
import org.dspace.core.AbstractHibernateDAO;
|
||||
import org.dspace.core.Context;
|
||||
|
||||
public class ProcessDAOImpl extends AbstractHibernateDAO<Process> implements ProcessDAO {
|
||||
|
||||
@Override
|
||||
public List<Process> findAllSortByScript(Context context) throws SQLException {
|
||||
|
||||
CriteriaBuilder criteriaBuilder = getCriteriaBuilder(context);
|
||||
CriteriaQuery criteriaQuery = getCriteriaQuery(criteriaBuilder, Process.class);
|
||||
Root<Process> processRoot = criteriaQuery.from(Process.class);
|
||||
criteriaQuery.select(processRoot);
|
||||
criteriaQuery.orderBy(criteriaBuilder.asc(processRoot.get(Process_.name)));
|
||||
|
||||
return list(context, criteriaQuery, false, Process.class, -1, -1);
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<Process> findAllSortByStartTime(Context context) throws SQLException {
|
||||
CriteriaBuilder criteriaBuilder = getCriteriaBuilder(context);
|
||||
CriteriaQuery criteriaQuery = getCriteriaQuery(criteriaBuilder, Process.class);
|
||||
Root<Process> processRoot = criteriaQuery.from(Process.class);
|
||||
criteriaQuery.select(processRoot);
|
||||
criteriaQuery.orderBy(criteriaBuilder.desc(processRoot.get(Process_.startTime)),
|
||||
criteriaBuilder.desc(processRoot.get(Process_.processId)));
|
||||
|
||||
return list(context, criteriaQuery, false, Process.class, -1, -1);
|
||||
}
|
||||
}
|
@@ -0,0 +1,21 @@
|
||||
/**
|
||||
* The contents of this file are subject to the license and copyright
|
||||
* detailed in the LICENSE and NOTICE files at the root of the source
|
||||
* tree and available online at
|
||||
*
|
||||
* http://www.dspace.org/license/
|
||||
*/
|
||||
package org.dspace.content.factory;
|
||||
|
||||
import org.dspace.content.service.ProcessService;
|
||||
import org.dspace.services.factory.DSpaceServicesFactory;
|
||||
|
||||
public abstract class ProcessServiceFactory {
|
||||
|
||||
public abstract ProcessService getProcessService();
|
||||
|
||||
public static ProcessServiceFactory getInstance() {
|
||||
return DSpaceServicesFactory.getInstance().getServiceManager()
|
||||
.getServiceByName("processServiceFactory", ProcessServiceFactory.class);
|
||||
}
|
||||
}
|
@@ -0,0 +1,22 @@
|
||||
/**
|
||||
* The contents of this file are subject to the license and copyright
|
||||
* detailed in the LICENSE and NOTICE files at the root of the source
|
||||
* tree and available online at
|
||||
*
|
||||
* http://www.dspace.org/license/
|
||||
*/
|
||||
package org.dspace.content.factory.impl;
|
||||
|
||||
import org.dspace.content.factory.ProcessServiceFactory;
|
||||
import org.dspace.content.service.ProcessService;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
|
||||
public class ProcessServiceFactoryImpl extends ProcessServiceFactory {
|
||||
|
||||
@Autowired(required = true)
|
||||
private ProcessService processService;
|
||||
|
||||
public ProcessService getProcessService() {
|
||||
return processService;
|
||||
}
|
||||
}
|
@@ -0,0 +1,48 @@
|
||||
/**
|
||||
* The contents of this file are subject to the license and copyright
|
||||
* detailed in the LICENSE and NOTICE files at the root of the source
|
||||
* tree and available online at
|
||||
*
|
||||
* http://www.dspace.org/license/
|
||||
*/
|
||||
package org.dspace.content.service;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.sql.SQLException;
|
||||
import java.util.List;
|
||||
|
||||
import org.dspace.authorize.AuthorizeException;
|
||||
import org.dspace.content.Process;
|
||||
import org.dspace.core.Context;
|
||||
import org.dspace.eperson.EPerson;
|
||||
import org.dspace.scripts.DSpaceCommandLineParameter;
|
||||
|
||||
public interface ProcessService {
|
||||
|
||||
public Process create(Context context, EPerson ePerson, String scriptName,
|
||||
List<DSpaceCommandLineParameter> parameters) throws SQLException;
|
||||
|
||||
public Process find(Context context, int processId) throws SQLException;
|
||||
|
||||
public List<Process> findAll(Context context) throws SQLException;
|
||||
|
||||
public List<Process> findAllSortByScript(Context context) throws SQLException;
|
||||
|
||||
public List<Process> findAllSortByStartTime(Context context) throws SQLException;
|
||||
|
||||
public void start(Context context, Process process) throws SQLException;
|
||||
|
||||
public void fail(Context context, Process process) throws SQLException;
|
||||
|
||||
public void complete(Context context, Process process) throws SQLException;
|
||||
|
||||
public void appendFile(Context context, Process process, InputStream is, String type)
|
||||
throws IOException, SQLException, AuthorizeException;
|
||||
|
||||
public void delete(Context context, Process process) throws SQLException;
|
||||
|
||||
public void update(Context context, Process process) throws SQLException;
|
||||
|
||||
public List<DSpaceCommandLineParameter> getParameters(Process process);
|
||||
}
|
@@ -0,0 +1,78 @@
|
||||
/**
|
||||
* The contents of this file are subject to the license and copyright
|
||||
* detailed in the LICENSE and NOTICE files at the root of the source
|
||||
* tree and available online at
|
||||
*
|
||||
* http://www.dspace.org/license/
|
||||
*/
|
||||
package org.dspace.scripts;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
|
||||
public class DSpaceCommandLineParameter {
|
||||
private String name;
|
||||
private String value;
|
||||
|
||||
public static String SEPARATOR = "|||";
|
||||
|
||||
public DSpaceCommandLineParameter(String key, String value) {
|
||||
this.name = key;
|
||||
|
||||
if (StringUtils.isBlank(value)) {
|
||||
this.value = null;
|
||||
} else {
|
||||
this.value = value;
|
||||
}
|
||||
}
|
||||
|
||||
public DSpaceCommandLineParameter(String parameter) {
|
||||
this(StringUtils.substringBefore(parameter, " "), StringUtils.substringAfter(parameter, " "));
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public void setName(String key) {
|
||||
this.name = key;
|
||||
}
|
||||
|
||||
public String getValue() {
|
||||
return value;
|
||||
}
|
||||
|
||||
public void setValue(String value) {
|
||||
this.value = value;
|
||||
}
|
||||
|
||||
public String toString() {
|
||||
String stringToReturn = "";
|
||||
stringToReturn += getName();
|
||||
if (StringUtils.isNotBlank(getValue())) {
|
||||
stringToReturn += " ";
|
||||
stringToReturn += getValue();
|
||||
}
|
||||
return stringToReturn;
|
||||
}
|
||||
|
||||
public static String concatenate(List<DSpaceCommandLineParameter> parameterList) {
|
||||
if (parameterList.isEmpty()) {
|
||||
return null;
|
||||
}
|
||||
return parameterList.stream().map(parameter -> parameter.toString()).collect(Collectors.joining(SEPARATOR));
|
||||
}
|
||||
|
||||
public boolean equals(Object other) {
|
||||
if (other == null) {
|
||||
return false;
|
||||
}
|
||||
if (other.getClass() != DSpaceCommandLineParameter.class) {
|
||||
return false;
|
||||
}
|
||||
return StringUtils.equals(this.getName(), ((DSpaceCommandLineParameter) other).getName()) && StringUtils
|
||||
.equals(this.getValue(), ((DSpaceCommandLineParameter) other).getValue());
|
||||
}
|
||||
}
|
@@ -0,0 +1,80 @@
|
||||
/**
|
||||
* The contents of this file are subject to the license and copyright
|
||||
* detailed in the LICENSE and NOTICE files at the root of the source
|
||||
* tree and available online at
|
||||
*
|
||||
* http://www.dspace.org/license/
|
||||
*/
|
||||
package org.dspace.scripts;
|
||||
|
||||
import org.apache.commons.cli.CommandLine;
|
||||
import org.apache.commons.cli.DefaultParser;
|
||||
import org.apache.commons.cli.Options;
|
||||
import org.apache.commons.cli.ParseException;
|
||||
import org.dspace.scripts.handler.DSpaceRunnableHandler;
|
||||
import org.springframework.beans.factory.annotation.Required;
|
||||
|
||||
public abstract class DSpaceRunnable implements Runnable {
|
||||
|
||||
private String name;
|
||||
private String description;
|
||||
protected CommandLine commandLine;
|
||||
protected Options options;
|
||||
protected DSpaceRunnableHandler handler;
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
@Required
|
||||
public void setName(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
public String getDescription() {
|
||||
return description;
|
||||
}
|
||||
|
||||
@Required
|
||||
public void setDescription(String description) {
|
||||
this.description = description;
|
||||
}
|
||||
|
||||
public Options getOptions() {
|
||||
return options;
|
||||
}
|
||||
|
||||
private void parse(String[] args) throws ParseException {
|
||||
commandLine = new DefaultParser().parse(getOptions(), args);
|
||||
setup();
|
||||
}
|
||||
|
||||
public void printHelp() {
|
||||
handler.printHelp(options, name);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
try {
|
||||
handler.start();
|
||||
internalRun();
|
||||
handler.handleCompletion();
|
||||
} catch (Exception e) {
|
||||
handler.handleException(e);
|
||||
}
|
||||
}
|
||||
|
||||
private void setHandler(DSpaceRunnableHandler dSpaceRunnableHandler) {
|
||||
this.handler = dSpaceRunnableHandler;
|
||||
}
|
||||
|
||||
public void initialize(String[] args, DSpaceRunnableHandler dSpaceRunnableHandler) throws ParseException {
|
||||
this.setHandler(dSpaceRunnableHandler);
|
||||
this.parse(args);
|
||||
}
|
||||
|
||||
public abstract void internalRun() throws Exception;
|
||||
|
||||
public abstract void setup() throws ParseException;
|
||||
}
|
@@ -0,0 +1,63 @@
|
||||
/**
|
||||
* The contents of this file are subject to the license and copyright
|
||||
* detailed in the LICENSE and NOTICE files at the root of the source
|
||||
* tree and available online at
|
||||
*
|
||||
* http://www.dspace.org/license/
|
||||
*/
|
||||
|
||||
package org.dspace.scripts;
|
||||
|
||||
import org.apache.commons.cli.CommandLine;
|
||||
|
||||
public enum IndexClientOptions {
|
||||
REMOVE,
|
||||
CLEAN,
|
||||
FORCECLEAN,
|
||||
BUILD,
|
||||
BUILDANDSPELLCHECK,
|
||||
OPTIMIZE,
|
||||
SPELLCHECK,
|
||||
INDEX,
|
||||
UPDATE,
|
||||
FORCEUPDATE,
|
||||
UPDATEANDSPELLCHECK,
|
||||
FORCEUPDATEANDSPELLCHECK,
|
||||
HELP;
|
||||
|
||||
public static IndexClientOptions getIndexClientOption(CommandLine commandLine) {
|
||||
if (commandLine.hasOption("h")) {
|
||||
return IndexClientOptions.HELP;
|
||||
} else if (commandLine.hasOption("r")) {
|
||||
return IndexClientOptions.REMOVE;
|
||||
} else if (commandLine.hasOption("c")) {
|
||||
if (commandLine.hasOption("f")) {
|
||||
return IndexClientOptions.FORCECLEAN;
|
||||
} else {
|
||||
return IndexClientOptions.CLEAN;
|
||||
}
|
||||
} else if (commandLine.hasOption("b")) {
|
||||
if (commandLine.hasOption("s")) {
|
||||
return IndexClientOptions.BUILDANDSPELLCHECK;
|
||||
} else {
|
||||
return IndexClientOptions.BUILD;
|
||||
}
|
||||
} else if (commandLine.hasOption("o")) {
|
||||
return IndexClientOptions.OPTIMIZE;
|
||||
} else if (commandLine.hasOption("s")) {
|
||||
return IndexClientOptions.SPELLCHECK;
|
||||
} else if (commandLine.hasOption("i")) {
|
||||
return IndexClientOptions.INDEX;
|
||||
} else {
|
||||
if (commandLine.hasOption("f") && commandLine.hasOption("s")) {
|
||||
return IndexClientOptions.FORCEUPDATEANDSPELLCHECK;
|
||||
} else if (commandLine.hasOption("f")) {
|
||||
return IndexClientOptions.FORCEUPDATE;
|
||||
} else if (commandLine.hasOption("s")) {
|
||||
return IndexClientOptions.UPDATEANDSPELLCHECK;
|
||||
} else {
|
||||
return IndexClientOptions.UPDATE;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,35 @@
|
||||
/**
|
||||
* The contents of this file are subject to the license and copyright
|
||||
* detailed in the LICENSE and NOTICE files at the root of the source
|
||||
* tree and available online at
|
||||
*
|
||||
* http://www.dspace.org/license/
|
||||
*/
|
||||
package org.dspace.scripts.handler;
|
||||
|
||||
import java.sql.SQLException;
|
||||
|
||||
import org.apache.commons.cli.Options;
|
||||
|
||||
public interface DSpaceRunnableHandler {
|
||||
|
||||
public void start() throws SQLException;
|
||||
|
||||
public void handleCompletion() throws SQLException;
|
||||
|
||||
public void handleException(Exception e);
|
||||
|
||||
public void handleException(String message);
|
||||
|
||||
public void handleException(String message, Exception e);
|
||||
|
||||
public void logDebug(String message);
|
||||
|
||||
public void logInfo(String message);
|
||||
|
||||
public void logWarning(String message);
|
||||
|
||||
public void logError(String message);
|
||||
|
||||
public void printHelp(Options options, String name);
|
||||
}
|
@@ -0,0 +1,83 @@
|
||||
/**
|
||||
* The contents of this file are subject to the license and copyright
|
||||
* detailed in the LICENSE and NOTICE files at the root of the source
|
||||
* tree and available online at
|
||||
*
|
||||
* http://www.dspace.org/license/
|
||||
*/
|
||||
package org.dspace.scripts.handler.impl;
|
||||
|
||||
import org.apache.commons.cli.HelpFormatter;
|
||||
import org.apache.commons.cli.Options;
|
||||
import org.apache.logging.log4j.Logger;
|
||||
import org.dspace.scripts.handler.DSpaceRunnableHandler;
|
||||
|
||||
public class CommandLineDSpaceRunnableHandler implements DSpaceRunnableHandler {
|
||||
private static final Logger log = org.apache.logging.log4j.LogManager
|
||||
.getLogger(CommandLineDSpaceRunnableHandler.class);
|
||||
|
||||
@Override
|
||||
public void start() {
|
||||
System.out.println("The script has started");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void handleCompletion() {
|
||||
System.out.println("The script has completed");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void handleException(Exception e) {
|
||||
handleException(null, e);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void handleException(String message) {
|
||||
handleException(message, null);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void handleException(String message, Exception e) {
|
||||
if (message != null) {
|
||||
System.err.println(message);
|
||||
log.error(message);
|
||||
}
|
||||
if (e != null) {
|
||||
e.printStackTrace();
|
||||
log.error(e.getMessage(), e);
|
||||
}
|
||||
|
||||
System.exit(1);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void logDebug(String message) {
|
||||
log.debug(message);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void logInfo(String message) {
|
||||
System.out.println(message);
|
||||
log.info(message);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void logWarning(String message) {
|
||||
System.out.println(message);
|
||||
log.warn(message);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void logError(String message) {
|
||||
System.err.println(message);
|
||||
log.error(message);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void printHelp(Options options, String name) {
|
||||
if (options != null) {
|
||||
HelpFormatter formatter = new HelpFormatter();
|
||||
formatter.printHelp(name, options);
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,258 @@
|
||||
/**
|
||||
* The contents of this file are subject to the license and copyright
|
||||
* detailed in the LICENSE and NOTICE files at the root of the source
|
||||
* tree and available online at
|
||||
*
|
||||
* http://www.dspace.org/license/
|
||||
*/
|
||||
package org.dspace.scripts.impl;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.sql.SQLException;
|
||||
import java.util.Iterator;
|
||||
import java.util.UUID;
|
||||
|
||||
import org.apache.commons.cli.CommandLine;
|
||||
import org.apache.commons.cli.Options;
|
||||
import org.apache.commons.cli.ParseException;
|
||||
import org.dspace.content.Collection;
|
||||
import org.dspace.content.Community;
|
||||
import org.dspace.content.Item;
|
||||
import org.dspace.content.factory.ContentServiceFactory;
|
||||
import org.dspace.content.service.ItemService;
|
||||
import org.dspace.core.Constants;
|
||||
import org.dspace.core.Context;
|
||||
import org.dspace.discovery.IndexableObject;
|
||||
import org.dspace.discovery.IndexingService;
|
||||
import org.dspace.discovery.SearchServiceException;
|
||||
import org.dspace.handle.factory.HandleServiceFactory;
|
||||
import org.dspace.scripts.DSpaceRunnable;
|
||||
import org.dspace.scripts.IndexClientOptions;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
|
||||
public class IndexClient extends DSpaceRunnable {
|
||||
|
||||
private Context context;
|
||||
|
||||
@Autowired
|
||||
private IndexingService indexer;
|
||||
|
||||
private IndexClientOptions indexClientOptions;
|
||||
|
||||
@Override
|
||||
public void internalRun() throws Exception {
|
||||
if (indexClientOptions == IndexClientOptions.HELP) {
|
||||
printHelp();
|
||||
return;
|
||||
}
|
||||
|
||||
/** Acquire from dspace-services in future */
|
||||
/**
|
||||
* new DSpace.getServiceManager().getServiceByName("org.dspace.discovery.SolrIndexer");
|
||||
*/
|
||||
|
||||
if (indexClientOptions == IndexClientOptions.REMOVE) {
|
||||
handler.logInfo("Removing " + commandLine.getOptionValue("r") + " from Index");
|
||||
indexer.unIndexContent(context, commandLine.getOptionValue("r"));
|
||||
} else if (indexClientOptions == IndexClientOptions.CLEAN) {
|
||||
handler.logInfo("Cleaning Index");
|
||||
indexer.cleanIndex(false);
|
||||
} else if (indexClientOptions == IndexClientOptions.FORCECLEAN) {
|
||||
handler.logInfo("Cleaning Index");
|
||||
indexer.cleanIndex(true);
|
||||
} else if (indexClientOptions == IndexClientOptions.BUILD ||
|
||||
indexClientOptions == IndexClientOptions.BUILDANDSPELLCHECK) {
|
||||
handler.logInfo("(Re)building index from scratch.");
|
||||
indexer.createIndex(context);
|
||||
if (indexClientOptions == IndexClientOptions.BUILDANDSPELLCHECK) {
|
||||
checkRebuildSpellCheck(commandLine, indexer);
|
||||
}
|
||||
} else if (indexClientOptions == IndexClientOptions.OPTIMIZE) {
|
||||
handler.logInfo("Optimizing search core.");
|
||||
indexer.optimize();
|
||||
} else if (indexClientOptions == IndexClientOptions.SPELLCHECK) {
|
||||
checkRebuildSpellCheck(commandLine, indexer);
|
||||
} else if (indexClientOptions == IndexClientOptions.INDEX) {
|
||||
final String param = commandLine.getOptionValue('i');
|
||||
UUID uuid = null;
|
||||
try {
|
||||
uuid = UUID.fromString(param);
|
||||
} catch (Exception e) {
|
||||
// nothing to do, it should be an handle
|
||||
}
|
||||
IndexableObject dso = null;
|
||||
if (uuid != null) {
|
||||
dso = ContentServiceFactory.getInstance().getItemService().find(context, uuid);
|
||||
if (dso == null) {
|
||||
// it could be a community
|
||||
dso = ContentServiceFactory.getInstance().getCommunityService().find(context, uuid);
|
||||
if (dso == null) {
|
||||
// it could be a collection
|
||||
dso = ContentServiceFactory.getInstance().getCollectionService().find(context, uuid);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
dso = (IndexableObject) HandleServiceFactory.getInstance()
|
||||
.getHandleService().resolveToObject(context, param);
|
||||
}
|
||||
if (dso == null) {
|
||||
throw new IllegalArgumentException("Cannot resolve " + param + " to a DSpace object");
|
||||
}
|
||||
handler.logInfo("Indexing " + param + " force " + commandLine.hasOption("f"));
|
||||
final long startTimeMillis = System.currentTimeMillis();
|
||||
final long count = indexAll(indexer, ContentServiceFactory.getInstance().getItemService(), context,
|
||||
dso);
|
||||
final long seconds = (System.currentTimeMillis() - startTimeMillis) / 1000;
|
||||
handler.logInfo("Indexed " + count + " object" + (count > 1 ? "s" : "") + " in " + seconds + " seconds");
|
||||
} else if (indexClientOptions == IndexClientOptions.UPDATE ||
|
||||
indexClientOptions == IndexClientOptions.UPDATEANDSPELLCHECK) {
|
||||
handler.logInfo("Updating and Cleaning Index");
|
||||
indexer.cleanIndex(false);
|
||||
indexer.updateIndex(context, false);
|
||||
if (indexClientOptions == IndexClientOptions.UPDATEANDSPELLCHECK) {
|
||||
checkRebuildSpellCheck(commandLine, indexer);
|
||||
}
|
||||
} else if (indexClientOptions == IndexClientOptions.FORCEUPDATE ||
|
||||
indexClientOptions == IndexClientOptions.FORCEUPDATEANDSPELLCHECK) {
|
||||
handler.logInfo("Updating and Cleaning Index");
|
||||
indexer.cleanIndex(true);
|
||||
indexer.updateIndex(context, true);
|
||||
if (indexClientOptions == IndexClientOptions.FORCEUPDATEANDSPELLCHECK) {
|
||||
checkRebuildSpellCheck(commandLine, indexer);
|
||||
}
|
||||
}
|
||||
|
||||
handler.logInfo("Done with indexing");
|
||||
}
|
||||
|
||||
public void setup() throws ParseException {
|
||||
try {
|
||||
context = new Context(Context.Mode.READ_ONLY);
|
||||
context.turnOffAuthorisationSystem();
|
||||
} catch (Exception e) {
|
||||
throw new ParseException("Unable to create a new DSpace Context: " + e.getMessage());
|
||||
}
|
||||
|
||||
indexClientOptions = IndexClientOptions.getIndexClientOption(commandLine);
|
||||
}
|
||||
|
||||
private IndexClient() {
|
||||
Options options = constructOptions();
|
||||
this.options = options;
|
||||
}
|
||||
|
||||
private Options constructOptions() {
|
||||
Options options = new Options();
|
||||
|
||||
options
|
||||
.addOption("r", "remove", true, "remove an Item, Collection or Community from index based on its handle");
|
||||
options.getOption("r").setType(String.class);
|
||||
options.addOption("i", "index", true,
|
||||
"add or update an Item, Collection or Community based on its handle or uuid");
|
||||
options.getOption("i").setType(boolean.class);
|
||||
options.addOption("c", "clean", false,
|
||||
"clean existing index removing any documents that no longer exist in the db");
|
||||
options.getOption("c").setType(boolean.class);
|
||||
options.addOption("b", "build", false, "(re)build index, wiping out current one if it exists");
|
||||
options.getOption("b").setType(boolean.class);
|
||||
options.addOption("s", "spellchecker", false, "Rebuild the spellchecker, can be combined with -b and -f.");
|
||||
options.getOption("s").setType(boolean.class);
|
||||
options.addOption("f", "force", false,
|
||||
"if updating existing index, force each handle to be reindexed even if uptodate");
|
||||
options.getOption("f").setType(boolean.class);
|
||||
options.addOption("h", "help", false, "print this help message");
|
||||
options.getOption("h").setType(boolean.class);
|
||||
return options;
|
||||
}
|
||||
|
||||
/**
|
||||
* Indexes the given object and all children, if applicable.
|
||||
*
|
||||
* @param indexingService
|
||||
* @param itemService
|
||||
* @param context The relevant DSpace Context.
|
||||
* @param dso DSpace object to index recursively
|
||||
* @throws IOException A general class of exceptions produced by failed or interrupted I/O operations.
|
||||
* @throws SearchServiceException in case of a solr exception
|
||||
* @throws SQLException An exception that provides information on a database access error or other errors.
|
||||
*/
|
||||
private static long indexAll(final IndexingService indexingService,
|
||||
final ItemService itemService,
|
||||
final Context context,
|
||||
final IndexableObject dso)
|
||||
throws IOException, SearchServiceException, SQLException {
|
||||
long count = 0;
|
||||
|
||||
indexingService.indexContent(context, dso, true, true);
|
||||
count++;
|
||||
if (dso.getType() == Constants.COMMUNITY) {
|
||||
final Community community = (Community) dso;
|
||||
final String communityHandle = community.getHandle();
|
||||
for (final Community subcommunity : community.getSubcommunities()) {
|
||||
count += indexAll(indexingService, itemService, context, subcommunity);
|
||||
//To prevent memory issues, discard an object from the cache after processing
|
||||
context.uncacheEntity(subcommunity);
|
||||
}
|
||||
final Community reloadedCommunity = (Community) HandleServiceFactory.getInstance().getHandleService()
|
||||
.resolveToObject(context,
|
||||
communityHandle);
|
||||
for (final Collection collection : reloadedCommunity.getCollections()) {
|
||||
count++;
|
||||
indexingService.indexContent(context, collection, true, true);
|
||||
count += indexItems(indexingService, itemService, context, collection);
|
||||
//To prevent memory issues, discard an object from the cache after processing
|
||||
context.uncacheEntity(collection);
|
||||
}
|
||||
} else if (dso.getType() == Constants.COLLECTION) {
|
||||
count += indexItems(indexingService, itemService, context, (Collection) dso);
|
||||
}
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
/**
|
||||
* Indexes all items in the given collection.
|
||||
*
|
||||
* @param indexingService
|
||||
* @param itemService
|
||||
* @param context The relevant DSpace Context.
|
||||
* @param collection collection to index
|
||||
* @throws IOException A general class of exceptions produced by failed or interrupted I/O operations.
|
||||
* @throws SearchServiceException in case of a solr exception
|
||||
* @throws SQLException An exception that provides information on a database access error or other errors.
|
||||
*/
|
||||
private static long indexItems(final IndexingService indexingService,
|
||||
final ItemService itemService,
|
||||
final Context context,
|
||||
final Collection collection)
|
||||
throws IOException, SearchServiceException, SQLException {
|
||||
long count = 0;
|
||||
|
||||
final Iterator<Item> itemIterator = itemService.findByCollection(context, collection);
|
||||
while (itemIterator.hasNext()) {
|
||||
Item item = itemIterator.next();
|
||||
indexingService.indexContent(context, item, true, false);
|
||||
count++;
|
||||
//To prevent memory issues, discard an object from the cache after processing
|
||||
context.uncacheEntity(item);
|
||||
}
|
||||
indexingService.commit();
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check the command line options and rebuild the spell check if active.
|
||||
*
|
||||
* @param line the command line options
|
||||
* @param indexer the solr indexer
|
||||
* @throws SearchServiceException in case of a solr exception
|
||||
* @throws IOException passed through
|
||||
*/
|
||||
protected void checkRebuildSpellCheck(CommandLine line, IndexingService indexer)
|
||||
throws SearchServiceException, IOException {
|
||||
handler.logInfo("Rebuilding spell checker.");
|
||||
indexer.buildSpellCheck();
|
||||
}
|
||||
|
||||
}
|
@@ -0,0 +1,40 @@
|
||||
--
|
||||
-- The contents of this file are subject to the license and copyright
|
||||
-- detailed in the LICENSE and NOTICE files at the root of the source
|
||||
-- tree and available online at
|
||||
--
|
||||
-- http://www.dspace.org/license/
|
||||
--
|
||||
|
||||
-- ===============================================================
|
||||
-- WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING
|
||||
--
|
||||
-- DO NOT MANUALLY RUN THIS DATABASE MIGRATION. IT WILL BE EXECUTED
|
||||
-- AUTOMATICALLY (IF NEEDED) BY "FLYWAY" WHEN YOU STARTUP DSPACE.
|
||||
-- http://flywaydb.org/
|
||||
-- ===============================================================
|
||||
CREATE SEQUENCE process_id_seq;
|
||||
|
||||
CREATE TABLE process
|
||||
(
|
||||
process_id INTEGER NOT NULL PRIMARY KEY,
|
||||
user_id UUID NOT NULL,
|
||||
start_time TIMESTAMP,
|
||||
finished_time TIMESTAMP,
|
||||
creation_time TIMESTAMP NOT NULL,
|
||||
script VARCHAR(256) NOT NULL,
|
||||
status VARCHAR(32),
|
||||
parameters VARCHAR (512)
|
||||
);
|
||||
|
||||
CREATE TABLE process2bitstream
|
||||
(
|
||||
process_id INTEGER REFERENCES process(process_id),
|
||||
bitstream_id UUID REFERENCES bitstream(uuid),
|
||||
CONSTRAINT PK_process2bitstream PRIMARY KEY (process_id, bitstream_id)
|
||||
);
|
||||
|
||||
CREATE INDEX process_user_id_idx ON process(user_id);
|
||||
CREATE INDEX process_status_idx ON process(status);
|
||||
CREATE INDEX process_name_idx on process(script);
|
||||
CREATE INDEX process_start_time_idx on process(start_time);
|
@@ -0,0 +1,90 @@
|
||||
/**
|
||||
* The contents of this file are subject to the license and copyright
|
||||
* detailed in the LICENSE and NOTICE files at the root of the source
|
||||
* tree and available online at
|
||||
*
|
||||
* http://www.dspace.org/license/
|
||||
*/
|
||||
package org.dspace.app.rest;
|
||||
|
||||
import java.sql.SQLException;
|
||||
import java.util.Arrays;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
|
||||
import org.apache.logging.log4j.LogManager;
|
||||
import org.apache.logging.log4j.Logger;
|
||||
import org.dspace.app.rest.link.HalLinkService;
|
||||
import org.dspace.app.rest.model.ProcessRest;
|
||||
import org.dspace.app.rest.model.hateoas.EmbeddedPage;
|
||||
import org.dspace.app.rest.model.hateoas.ProcessResource;
|
||||
import org.dspace.app.rest.repository.ProcessRestRepository;
|
||||
import org.springframework.beans.factory.InitializingBean;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.data.domain.Page;
|
||||
import org.springframework.data.domain.PageImpl;
|
||||
import org.springframework.data.domain.Pageable;
|
||||
import org.springframework.hateoas.Link;
|
||||
import org.springframework.web.bind.annotation.PathVariable;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RequestMethod;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
|
||||
@RestController
|
||||
@RequestMapping("/api/" + ProcessRest.CATEGORY + "/" + ProcessRest.PLURAL_NAME)
|
||||
public class ProcessRestController implements InitializingBean {
|
||||
|
||||
private static final Logger log = LogManager.getLogger();
|
||||
|
||||
@Autowired
|
||||
HalLinkService linkService;
|
||||
|
||||
@Autowired
|
||||
private DiscoverableEndpointsService discoverableEndpointsService;
|
||||
|
||||
@Autowired
|
||||
private ProcessRestRepository processRestRepository;
|
||||
|
||||
@Override
|
||||
public void afterPropertiesSet() throws Exception {
|
||||
discoverableEndpointsService
|
||||
.register(this, Arrays.asList(
|
||||
new Link("/api/" + ProcessRest.CATEGORY + "/" + ProcessRest.PLURAL_NAME, ProcessRest.PLURAL_NAME)));
|
||||
}
|
||||
|
||||
@RequestMapping(method = RequestMethod.GET)
|
||||
public EmbeddedPage getProcesses(Pageable pageable) throws Exception {
|
||||
if (log.isTraceEnabled()) {
|
||||
log.trace("Retrieving processes");
|
||||
}
|
||||
|
||||
List<ProcessRest> processRestList = processRestRepository.getAllProcesses();
|
||||
List<ProcessResource> processResources = new LinkedList<>();
|
||||
for (ProcessRest processRest : processRestList) {
|
||||
ProcessResource processResource = new ProcessResource(processRest);
|
||||
linkService.addLinks(processResource);
|
||||
processResources.add(processResource);
|
||||
|
||||
}
|
||||
|
||||
Page page = new PageImpl<>(processResources, pageable, processRestList.size());
|
||||
|
||||
// SearchResultsResourceHalLinkFactory linkFactory = new SearchResultsResourceHalLinkFactory();
|
||||
EmbeddedPage embeddedPage = new EmbeddedPage("test",
|
||||
page, processResources, "scripts");
|
||||
|
||||
return embeddedPage;
|
||||
}
|
||||
|
||||
@RequestMapping(method = RequestMethod.GET, value = "/{processId}")
|
||||
public ProcessResource getProcessById(@PathVariable(name = "processId") Integer processId) throws SQLException {
|
||||
if (log.isTraceEnabled()) {
|
||||
log.trace("Retrieving Process with ID: " + processId);
|
||||
}
|
||||
|
||||
ProcessRest processRest = processRestRepository.getProcessById(processId);
|
||||
ProcessResource processResource = new ProcessResource(processRest);
|
||||
linkService.addLinks(processResource);
|
||||
return processResource;
|
||||
}
|
||||
}
|
@@ -0,0 +1,47 @@
|
||||
/**
|
||||
* The contents of this file are subject to the license and copyright
|
||||
* detailed in the LICENSE and NOTICE files at the root of the source
|
||||
* tree and available online at
|
||||
*
|
||||
* http://www.dspace.org/license/
|
||||
*/
|
||||
package org.dspace.app.rest;
|
||||
|
||||
import org.apache.logging.log4j.LogManager;
|
||||
import org.apache.logging.log4j.Logger;
|
||||
import org.dspace.app.rest.model.ProcessRest;
|
||||
import org.dspace.app.rest.model.ScriptRest;
|
||||
import org.dspace.app.rest.model.hateoas.ProcessResource;
|
||||
import org.dspace.app.rest.repository.ScriptRestRepository;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.security.access.prepost.PreAuthorize;
|
||||
import org.springframework.web.bind.annotation.PathVariable;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RequestMethod;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
|
||||
|
||||
@RestController
|
||||
@RequestMapping("/api/" + ScriptRest.CATEGORY + "/" + ScriptRest.PLURAL_NAME)
|
||||
public class ScriptRestController {
|
||||
|
||||
private static final Logger log = LogManager.getLogger();
|
||||
|
||||
@Autowired
|
||||
private DiscoverableEndpointsService discoverableEndpointsService;
|
||||
|
||||
@Autowired
|
||||
private ScriptRestRepository scriptRestRepository;
|
||||
|
||||
@RequestMapping(method = RequestMethod.POST, value = "/{name}/processes")
|
||||
@PreAuthorize("hasAuthority('ADMIN')")
|
||||
public ProcessResource startProcess(@PathVariable(name = "name") String scriptName) throws Exception {
|
||||
if (log.isTraceEnabled()) {
|
||||
log.trace("Starting Process for Script with name: " + scriptName);
|
||||
}
|
||||
ProcessRest processRest = scriptRestRepository.startProcess(scriptName);
|
||||
ProcessResource processResource = new ProcessResource(processRest);
|
||||
return processResource;
|
||||
}
|
||||
|
||||
}
|
@@ -0,0 +1,28 @@
|
||||
/**
|
||||
* The contents of this file are subject to the license and copyright
|
||||
* detailed in the LICENSE and NOTICE files at the root of the source
|
||||
* tree and available online at
|
||||
*
|
||||
* http://www.dspace.org/license/
|
||||
*/
|
||||
package org.dspace.app.rest.converter;
|
||||
|
||||
import org.dspace.app.rest.model.ParameterValueRest;
|
||||
import org.dspace.scripts.DSpaceCommandLineParameter;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
@Component
|
||||
public class DSpaceRunnableParameterConverter
|
||||
implements DSpaceConverter<DSpaceCommandLineParameter, ParameterValueRest> {
|
||||
|
||||
public ParameterValueRest fromModel(DSpaceCommandLineParameter dSpaceCommandLineParameter) {
|
||||
ParameterValueRest parameterValueRest = new ParameterValueRest();
|
||||
parameterValueRest.setName(dSpaceCommandLineParameter.getName());
|
||||
parameterValueRest.setValue(dSpaceCommandLineParameter.getValue());
|
||||
return parameterValueRest;
|
||||
}
|
||||
|
||||
public DSpaceCommandLineParameter toModel(ParameterValueRest parameterValueRest) {
|
||||
return new DSpaceCommandLineParameter(parameterValueRest.getName(), parameterValueRest.getValue());
|
||||
}
|
||||
}
|
@@ -0,0 +1,34 @@
|
||||
/**
|
||||
* The contents of this file are subject to the license and copyright
|
||||
* detailed in the LICENSE and NOTICE files at the root of the source
|
||||
* tree and available online at
|
||||
*
|
||||
* http://www.dspace.org/license/
|
||||
*/
|
||||
package org.dspace.app.rest.converter;
|
||||
|
||||
import org.dspace.app.rest.converter.processes.ParameterConverter;
|
||||
import org.dspace.app.rest.model.ScriptRest;
|
||||
import org.dspace.scripts.DSpaceRunnable;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
@Component
|
||||
public class ScriptConverter implements DSpaceConverter<DSpaceRunnable, ScriptRest> {
|
||||
|
||||
@Autowired
|
||||
private ParameterConverter parameterConverter;
|
||||
|
||||
public ScriptRest fromModel(DSpaceRunnable script) {
|
||||
ScriptRest scriptRest = new ScriptRest();
|
||||
scriptRest.setDescription(script.getDescription());
|
||||
scriptRest.setId(script.getName());
|
||||
scriptRest.setName(script.getName());
|
||||
scriptRest.setParameterRestList(parameterConverter.convertOptionsToParameterRestList(script.getOptions()));
|
||||
return scriptRest;
|
||||
}
|
||||
|
||||
public DSpaceRunnable toModel(ScriptRest obj) {
|
||||
return null;
|
||||
}
|
||||
}
|
@@ -0,0 +1,35 @@
|
||||
/**
|
||||
* The contents of this file are subject to the license and copyright
|
||||
* detailed in the LICENSE and NOTICE files at the root of the source
|
||||
* tree and available online at
|
||||
*
|
||||
* http://www.dspace.org/license/
|
||||
*/
|
||||
package org.dspace.app.rest.converter.processes;
|
||||
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
|
||||
import org.apache.commons.cli.Option;
|
||||
import org.apache.commons.cli.Options;
|
||||
import org.apache.commons.collections4.CollectionUtils;
|
||||
import org.dspace.app.rest.model.ParameterRest;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
@Component
|
||||
public class ParameterConverter {
|
||||
|
||||
public List<ParameterRest> convertOptionsToParameterRestList(Options options) {
|
||||
List<ParameterRest> listToReturn = new LinkedList<>();
|
||||
|
||||
for (Option option : CollectionUtils.emptyIfNull(options.getOptions())) {
|
||||
ParameterRest parameterRest = new ParameterRest();
|
||||
parameterRest.setDescription(option.getDescription());
|
||||
parameterRest.setName(option.getOpt());
|
||||
parameterRest.setType(((Class) option.getType()).getSimpleName());
|
||||
listToReturn.add(parameterRest);
|
||||
}
|
||||
|
||||
return listToReturn;
|
||||
}
|
||||
}
|
@@ -0,0 +1,45 @@
|
||||
/**
|
||||
* The contents of this file are subject to the license and copyright
|
||||
* detailed in the LICENSE and NOTICE files at the root of the source
|
||||
* tree and available online at
|
||||
*
|
||||
* http://www.dspace.org/license/
|
||||
*/
|
||||
package org.dspace.app.rest.converter.processes;
|
||||
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import org.dspace.app.rest.converter.DSpaceConverter;
|
||||
import org.dspace.app.rest.converter.DSpaceRunnableParameterConverter;
|
||||
import org.dspace.app.rest.model.ProcessRest;
|
||||
import org.dspace.content.Process;
|
||||
import org.dspace.content.service.ProcessService;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
@Component
|
||||
public class ProcessConverter implements DSpaceConverter<Process, ProcessRest> {
|
||||
|
||||
@Autowired
|
||||
private ProcessService processService;
|
||||
|
||||
@Autowired
|
||||
private DSpaceRunnableParameterConverter dSpaceRunnableParameterConverter;
|
||||
|
||||
public ProcessRest fromModel(Process process) {
|
||||
ProcessRest processRest = new ProcessRest();
|
||||
processRest.setScriptName(process.getName());
|
||||
processRest.setProcessId(process.getID());
|
||||
processRest.setUserId(process.getEPerson().getID());
|
||||
processRest.setProcessStatus(process.getProcessStatus());
|
||||
processRest.setStartTime(process.getStartTime());
|
||||
processRest.setParameterRestList(
|
||||
processService.getParameters(process).stream().map(x -> dSpaceRunnableParameterConverter.fromModel(x))
|
||||
.collect(Collectors.toList()));
|
||||
return processRest;
|
||||
}
|
||||
|
||||
public Process toModel(ProcessRest obj) {
|
||||
return null;
|
||||
}
|
||||
}
|
@@ -0,0 +1,47 @@
|
||||
/**
|
||||
* The contents of this file are subject to the license and copyright
|
||||
* detailed in the LICENSE and NOTICE files at the root of the source
|
||||
* tree and available online at
|
||||
*
|
||||
* http://www.dspace.org/license/
|
||||
*/
|
||||
package org.dspace.app.rest.link.process;
|
||||
|
||||
import java.util.LinkedList;
|
||||
|
||||
import org.dspace.app.rest.ProcessRestController;
|
||||
import org.dspace.app.rest.link.HalLinkFactory;
|
||||
import org.dspace.app.rest.model.hateoas.ProcessResource;
|
||||
import org.dspace.services.ConfigurationService;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.data.domain.Pageable;
|
||||
import org.springframework.hateoas.Link;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
@Component
|
||||
public class ProcessHalLinkFactory extends HalLinkFactory<ProcessResource, ProcessRestController> {
|
||||
|
||||
@Autowired
|
||||
private ConfigurationService configurationService;
|
||||
|
||||
protected void addLinks(ProcessResource halResource, Pageable pageable, LinkedList<Link> list) throws Exception {
|
||||
String dspaceRestUrl = configurationService.getProperty("dspace.restUrl");
|
||||
list.add(buildLink(Link.REL_SELF, getMethodOn().getProcessById(halResource.getContent().getProcessId())));
|
||||
list.add(
|
||||
buildLink("script", dspaceRestUrl + "/api/system/scripts/" + halResource.getContent().getScriptName()));
|
||||
// TODO Replace the bottom two with getMethodOn() when the Controller methods are created
|
||||
list.add(buildLink("output", dspaceRestUrl + "/api/system/processes/" + halResource.getContent()
|
||||
.getProcessId() + "/output"
|
||||
));
|
||||
list.add(buildLink("files", dspaceRestUrl + "/api/system/processes/" + halResource.getContent()
|
||||
.getProcessId() + "/files"));
|
||||
}
|
||||
|
||||
protected Class<ProcessRestController> getControllerClass() {
|
||||
return ProcessRestController.class;
|
||||
}
|
||||
|
||||
protected Class<ProcessResource> getResourceClass() {
|
||||
return ProcessResource.class;
|
||||
}
|
||||
}
|
@@ -0,0 +1,39 @@
|
||||
/**
|
||||
* The contents of this file are subject to the license and copyright
|
||||
* detailed in the LICENSE and NOTICE files at the root of the source
|
||||
* tree and available online at
|
||||
*
|
||||
* http://www.dspace.org/license/
|
||||
*/
|
||||
package org.dspace.app.rest.model;
|
||||
|
||||
public class ParameterRest {
|
||||
|
||||
private String name;
|
||||
private String description;
|
||||
private String type;
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public void setName(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
public String getDescription() {
|
||||
return description;
|
||||
}
|
||||
|
||||
public void setDescription(String description) {
|
||||
this.description = description;
|
||||
}
|
||||
|
||||
public String getType() {
|
||||
return type;
|
||||
}
|
||||
|
||||
public void setType(String type) {
|
||||
this.type = type;
|
||||
}
|
||||
}
|
@@ -0,0 +1,42 @@
|
||||
/**
|
||||
* The contents of this file are subject to the license and copyright
|
||||
* detailed in the LICENSE and NOTICE files at the root of the source
|
||||
* tree and available online at
|
||||
*
|
||||
* http://www.dspace.org/license/
|
||||
*/
|
||||
package org.dspace.app.rest.model;
|
||||
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
|
||||
public class ParameterValueRest {
|
||||
|
||||
private String name;
|
||||
private String value;
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public void setName(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
public String getValue() {
|
||||
return value;
|
||||
}
|
||||
|
||||
public void setValue(String value) {
|
||||
this.value = value;
|
||||
}
|
||||
|
||||
public String toString() {
|
||||
String stringToReturn = "";
|
||||
stringToReturn += getName();
|
||||
if (StringUtils.isNotBlank(getValue())) {
|
||||
stringToReturn += " ";
|
||||
stringToReturn += getValue();
|
||||
}
|
||||
return stringToReturn;
|
||||
}
|
||||
}
|
@@ -0,0 +1,96 @@
|
||||
/**
|
||||
* The contents of this file are subject to the license and copyright
|
||||
* detailed in the LICENSE and NOTICE files at the root of the source
|
||||
* tree and available online at
|
||||
*
|
||||
* http://www.dspace.org/license/
|
||||
*/
|
||||
package org.dspace.app.rest.model;
|
||||
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
import java.util.UUID;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonIgnore;
|
||||
import org.dspace.app.rest.ProcessRestController;
|
||||
import org.dspace.content.ProcessStatus;
|
||||
|
||||
public class ProcessRest extends BaseObjectRest<UUID> {
|
||||
public static final String NAME = "process";
|
||||
public static final String PLURAL_NAME = "processes";
|
||||
public static final String CATEGORY = RestAddressableModel.SYSTEM;
|
||||
|
||||
|
||||
public String getCategory() {
|
||||
return CATEGORY;
|
||||
}
|
||||
|
||||
public Class getController() {
|
||||
return ProcessRestController.class;
|
||||
}
|
||||
|
||||
public String getType() {
|
||||
return NAME;
|
||||
}
|
||||
|
||||
private String scriptName;
|
||||
private UUID userId;
|
||||
private Integer processId;
|
||||
private Date startTime;
|
||||
private ProcessStatus processStatus;
|
||||
private List<ParameterValueRest> parameterRestList;
|
||||
|
||||
public UUID getUserId() {
|
||||
return userId;
|
||||
}
|
||||
|
||||
public void setUserId(UUID userId) {
|
||||
this.userId = userId;
|
||||
}
|
||||
|
||||
public Integer getProcessId() {
|
||||
return processId;
|
||||
}
|
||||
|
||||
public void setProcessId(Integer processId) {
|
||||
this.processId = processId;
|
||||
}
|
||||
|
||||
public ProcessStatus getProcessStatus() {
|
||||
return processStatus;
|
||||
}
|
||||
|
||||
public void setProcessStatus(ProcessStatus processStatus) {
|
||||
this.processStatus = processStatus;
|
||||
}
|
||||
|
||||
public List<ParameterValueRest> getParameterRestList() {
|
||||
return parameterRestList;
|
||||
}
|
||||
|
||||
public void setParameterRestList(List<ParameterValueRest> parameterRestList) {
|
||||
this.parameterRestList = parameterRestList;
|
||||
}
|
||||
|
||||
public Date getStartTime() {
|
||||
return startTime;
|
||||
}
|
||||
|
||||
public void setStartTime(Date startTime) {
|
||||
this.startTime = startTime;
|
||||
}
|
||||
|
||||
public String getScriptName() {
|
||||
return scriptName;
|
||||
}
|
||||
|
||||
public void setScriptName(String scriptName) {
|
||||
this.scriptName = scriptName;
|
||||
}
|
||||
|
||||
@JsonIgnore
|
||||
@Override
|
||||
public UUID getId() {
|
||||
return id;
|
||||
}
|
||||
}
|
@@ -27,6 +27,7 @@ public interface RestModel extends Serializable {
|
||||
public static final String CONFIGURATION = "config";
|
||||
public static final String INTEGRATION = "integration";
|
||||
public static final String SUBMISSION = "submission";
|
||||
public static final String SYSTEM = "system";
|
||||
public static final String WORKFLOW = "workflow";
|
||||
public static final String AUTHORIZATION = "authz";
|
||||
|
||||
|
@@ -0,0 +1,73 @@
|
||||
/**
|
||||
* The contents of this file are subject to the license and copyright
|
||||
* detailed in the LICENSE and NOTICE files at the root of the source
|
||||
* tree and available online at
|
||||
*
|
||||
* http://www.dspace.org/license/
|
||||
*/
|
||||
package org.dspace.app.rest.model;
|
||||
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonIgnore;
|
||||
import com.fasterxml.jackson.annotation.JsonProperty;
|
||||
import org.dspace.app.rest.RestResourceController;
|
||||
|
||||
public class ScriptRest extends BaseObjectRest<String> {
|
||||
|
||||
public static final String NAME = "script";
|
||||
public static final String PLURAL_NAME = "scripts";
|
||||
public static final String CATEGORY = RestAddressableModel.SYSTEM;
|
||||
|
||||
private String name;
|
||||
private String description;
|
||||
@JsonProperty(value = "parameters")
|
||||
private List<ParameterRest> parameterRestList = new LinkedList<>();
|
||||
|
||||
public String getCategory() {
|
||||
return CATEGORY;
|
||||
}
|
||||
|
||||
public Class getController() {
|
||||
return RestResourceController.class;
|
||||
}
|
||||
|
||||
public String getType() {
|
||||
return NAME;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public void setName(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
public String getDescription() {
|
||||
return description;
|
||||
}
|
||||
|
||||
public void setDescription(String description) {
|
||||
this.description = description;
|
||||
}
|
||||
|
||||
public List<ParameterRest> getParameterRestList() {
|
||||
return parameterRestList;
|
||||
}
|
||||
|
||||
public void setParameterRestList(List<ParameterRest> parameterRestList) {
|
||||
this.parameterRestList = parameterRestList;
|
||||
}
|
||||
|
||||
public void addToParameterRestList(ParameterRest parameter) {
|
||||
parameterRestList.add(parameter);
|
||||
}
|
||||
|
||||
@JsonIgnore
|
||||
public String getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
}
|
@@ -0,0 +1,18 @@
|
||||
/**
|
||||
* The contents of this file are subject to the license and copyright
|
||||
* detailed in the LICENSE and NOTICE files at the root of the source
|
||||
* tree and available online at
|
||||
*
|
||||
* http://www.dspace.org/license/
|
||||
*/
|
||||
package org.dspace.app.rest.model.hateoas;
|
||||
|
||||
import org.dspace.app.rest.model.ProcessRest;
|
||||
import org.dspace.app.rest.model.hateoas.annotations.RelNameDSpaceResource;
|
||||
|
||||
@RelNameDSpaceResource(ProcessRest.NAME)
|
||||
public class ProcessResource extends HALResource<ProcessRest> {
|
||||
public ProcessResource(ProcessRest content) {
|
||||
super(content);
|
||||
}
|
||||
}
|
@@ -0,0 +1,19 @@
|
||||
/**
|
||||
* The contents of this file are subject to the license and copyright
|
||||
* detailed in the LICENSE and NOTICE files at the root of the source
|
||||
* tree and available online at
|
||||
*
|
||||
* http://www.dspace.org/license/
|
||||
*/
|
||||
package org.dspace.app.rest.model.hateoas;
|
||||
|
||||
import org.dspace.app.rest.model.ScriptRest;
|
||||
import org.dspace.app.rest.model.hateoas.annotations.RelNameDSpaceResource;
|
||||
import org.dspace.app.rest.utils.Utils;
|
||||
|
||||
@RelNameDSpaceResource(ScriptRest.NAME)
|
||||
public class ScriptResource extends DSpaceResource<ScriptRest> {
|
||||
public ScriptResource(ScriptRest data, Utils utils, String... rels) {
|
||||
super(data, utils, rels);
|
||||
}
|
||||
}
|
@@ -0,0 +1,48 @@
|
||||
/**
|
||||
* The contents of this file are subject to the license and copyright
|
||||
* detailed in the LICENSE and NOTICE files at the root of the source
|
||||
* tree and available online at
|
||||
*
|
||||
* http://www.dspace.org/license/
|
||||
*/
|
||||
package org.dspace.app.rest.repository;
|
||||
|
||||
import java.sql.SQLException;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
|
||||
import org.dspace.app.rest.converter.processes.ProcessConverter;
|
||||
import org.dspace.app.rest.model.ProcessRest;
|
||||
import org.dspace.content.Process;
|
||||
import org.dspace.content.service.ProcessService;
|
||||
import org.dspace.core.Context;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
@Component(ProcessRest.CATEGORY + "." + ProcessRest.NAME)
|
||||
public class ProcessRestRepository extends AbstractDSpaceRestRepository {
|
||||
|
||||
@Autowired
|
||||
private ProcessService processService;
|
||||
|
||||
@Autowired
|
||||
private ProcessConverter processConverter;
|
||||
|
||||
public List<ProcessRest> getAllProcesses() throws SQLException {
|
||||
Context context = obtainContext();
|
||||
List<Process> list = processService.findAll(context);
|
||||
|
||||
List<ProcessRest> listToReturn = new LinkedList<>();
|
||||
for (Process process : list) {
|
||||
listToReturn.add(processConverter.fromModel(process));
|
||||
}
|
||||
|
||||
return listToReturn;
|
||||
}
|
||||
|
||||
public ProcessRest getProcessById(Integer processId) throws SQLException {
|
||||
Context context = obtainContext();
|
||||
Process process = processService.find(context, processId);
|
||||
return processConverter.fromModel(process);
|
||||
}
|
||||
}
|
@@ -0,0 +1,140 @@
|
||||
/**
|
||||
* The contents of this file are subject to the license and copyright
|
||||
* detailed in the LICENSE and NOTICE files at the root of the source
|
||||
* tree and available online at
|
||||
*
|
||||
* http://www.dspace.org/license/
|
||||
*/
|
||||
package org.dspace.app.rest.repository;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.sql.SQLException;
|
||||
import java.util.Arrays;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import org.apache.commons.cli.ParseException;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.apache.logging.log4j.LogManager;
|
||||
import org.apache.logging.log4j.Logger;
|
||||
import org.dspace.app.rest.converter.DSpaceRunnableParameterConverter;
|
||||
import org.dspace.app.rest.converter.ScriptConverter;
|
||||
import org.dspace.app.rest.converter.processes.ProcessConverter;
|
||||
import org.dspace.app.rest.exception.DSpaceBadRequestException;
|
||||
import org.dspace.app.rest.model.ParameterValueRest;
|
||||
import org.dspace.app.rest.model.ProcessRest;
|
||||
import org.dspace.app.rest.model.ScriptRest;
|
||||
import org.dspace.app.rest.model.hateoas.DSpaceResource;
|
||||
import org.dspace.app.rest.model.hateoas.ScriptResource;
|
||||
import org.dspace.app.rest.scripts.handler.impl.RestDSpaceRunnableHandler;
|
||||
import org.dspace.content.service.ProcessService;
|
||||
import org.dspace.core.Context;
|
||||
import org.dspace.scripts.DSpaceCommandLineParameter;
|
||||
import org.dspace.scripts.DSpaceRunnable;
|
||||
import org.dspace.utils.DSpace;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.data.domain.Page;
|
||||
import org.springframework.data.domain.PageImpl;
|
||||
import org.springframework.data.domain.Pageable;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
@Component(ScriptRest.CATEGORY + "." + ScriptRest.NAME)
|
||||
public class ScriptRestRepository extends DSpaceRestRepository<ScriptRest, String> {
|
||||
|
||||
private static final Logger log = LogManager.getLogger();
|
||||
|
||||
@Autowired
|
||||
private List<DSpaceRunnable> dspaceRunnables;
|
||||
|
||||
@Autowired
|
||||
private ScriptConverter scriptConverter;
|
||||
|
||||
@Autowired
|
||||
private ProcessService processService;
|
||||
|
||||
@Autowired
|
||||
private ProcessConverter processConverter;
|
||||
|
||||
@Autowired
|
||||
private DSpaceRunnableParameterConverter dSpaceRunnableParameterConverter;
|
||||
|
||||
@Override
|
||||
public ScriptRest findOne(Context context, String name) {
|
||||
for (DSpaceRunnable dSpaceRunnable : dspaceRunnables) {
|
||||
if (StringUtils.equalsIgnoreCase(dSpaceRunnable.getName(), name)) {
|
||||
return scriptConverter.fromModel(dSpaceRunnable);
|
||||
}
|
||||
}
|
||||
throw new DSpaceBadRequestException("The script with name: " + name + " could not be found");
|
||||
}
|
||||
|
||||
@Override
|
||||
public Page<ScriptRest> findAll(Context context, Pageable pageable) {
|
||||
List list = dspaceRunnables.stream().skip(pageable.getOffset()).limit(pageable.getPageSize())
|
||||
.collect(Collectors.toList());
|
||||
Page<ScriptRest> scriptRestPage = new PageImpl<>(list, pageable, dspaceRunnables.size()).map(scriptConverter);
|
||||
return scriptRestPage;
|
||||
}
|
||||
|
||||
public Class<ScriptRest> getDomainClass() {
|
||||
return ScriptRest.class;
|
||||
}
|
||||
|
||||
public DSpaceResource<ScriptRest> wrapResource(ScriptRest model, String... rels) {
|
||||
return new ScriptResource(model, utils, rels);
|
||||
}
|
||||
|
||||
public ProcessRest startProcess(String scriptName) throws SQLException, IOException {
|
||||
Context context = obtainContext();
|
||||
List<ParameterValueRest> parameterValueRestList = new LinkedList<>();
|
||||
ObjectMapper objectMapper = new ObjectMapper();
|
||||
String propertiesJson = requestService.getCurrentRequest().getServletRequest().getParameter("properties");
|
||||
if (StringUtils.isNotBlank(propertiesJson)) {
|
||||
try {
|
||||
parameterValueRestList = Arrays
|
||||
.asList(objectMapper.readValue(propertiesJson, ParameterValueRest[].class));
|
||||
} catch (IOException e) {
|
||||
log.error(
|
||||
"Couldn't convert the given properties to proper ParameterValueRest objects: " + propertiesJson, e);
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
|
||||
List<DSpaceCommandLineParameter> dSpaceCommandLineParameters = new LinkedList<>();
|
||||
dSpaceCommandLineParameters.addAll(
|
||||
parameterValueRestList.stream().map(x -> dSpaceRunnableParameterConverter.toModel(x))
|
||||
.collect(Collectors.toList()));
|
||||
try {
|
||||
RestDSpaceRunnableHandler restDSpaceRunnableHandler = new RestDSpaceRunnableHandler(
|
||||
context.getCurrentUser(), scriptName, dSpaceCommandLineParameters);
|
||||
runDSpaceScriptWithArgs(dSpaceCommandLineParameters.stream().map(x -> x.toString()).toArray(String[]::new),
|
||||
restDSpaceRunnableHandler, scriptName);
|
||||
context.complete();
|
||||
return processConverter.fromModel(restDSpaceRunnableHandler.getProcess());
|
||||
} catch (SQLException e) {
|
||||
log.error("Failed to create a process with user: " + context.getCurrentUser() +
|
||||
" scriptname: " + scriptName + " and parameters " + DSpaceCommandLineParameter
|
||||
.concatenate(dSpaceCommandLineParameters), e);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private void runDSpaceScriptWithArgs(String[] args, RestDSpaceRunnableHandler dSpaceRunnableHandler,
|
||||
String scriptName) {
|
||||
List<DSpaceRunnable> scripts = new DSpace().getServiceManager().getServicesByType(DSpaceRunnable.class);
|
||||
for (DSpaceRunnable script : scripts) {
|
||||
if (StringUtils.equalsIgnoreCase(script.getName(), scriptName)) {
|
||||
try {
|
||||
script.initialize(args, dSpaceRunnableHandler);
|
||||
dSpaceRunnableHandler.schedule(script);
|
||||
} catch (ParseException e) {
|
||||
script.printHelp();
|
||||
dSpaceRunnableHandler.handleException("Failed to parse the arguments given to the script with name: " + scriptName
|
||||
+ " and args: " + Arrays.toString(args), e);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,202 @@
|
||||
/**
|
||||
* The contents of this file are subject to the license and copyright
|
||||
* detailed in the LICENSE and NOTICE files at the root of the source
|
||||
* tree and available online at
|
||||
*
|
||||
* http://www.dspace.org/license/
|
||||
*/
|
||||
package org.dspace.app.rest.scripts.handler.impl;
|
||||
|
||||
import java.io.PrintWriter;
|
||||
import java.io.StringWriter;
|
||||
import java.sql.SQLException;
|
||||
import java.util.List;
|
||||
|
||||
import org.apache.commons.cli.HelpFormatter;
|
||||
import org.apache.commons.cli.Options;
|
||||
import org.apache.commons.lang3.exception.ExceptionUtils;
|
||||
import org.apache.logging.log4j.Logger;
|
||||
import org.dspace.content.Process;
|
||||
import org.dspace.content.ProcessStatus;
|
||||
import org.dspace.content.factory.ProcessServiceFactory;
|
||||
import org.dspace.content.service.ProcessService;
|
||||
import org.dspace.core.Context;
|
||||
import org.dspace.eperson.EPerson;
|
||||
import org.dspace.scripts.DSpaceCommandLineParameter;
|
||||
import org.dspace.scripts.DSpaceRunnable;
|
||||
import org.dspace.scripts.handler.DSpaceRunnableHandler;
|
||||
import org.dspace.utils.DSpace;
|
||||
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
|
||||
|
||||
public class RestDSpaceRunnableHandler implements DSpaceRunnableHandler {
|
||||
private static final Logger log = org.apache.logging.log4j.LogManager
|
||||
.getLogger(RestDSpaceRunnableHandler.class);
|
||||
|
||||
private ProcessService processService = ProcessServiceFactory.getInstance().getProcessService();
|
||||
|
||||
private Integer processId;
|
||||
private String scriptName;
|
||||
|
||||
public RestDSpaceRunnableHandler(EPerson ePerson, String scriptName, List<DSpaceCommandLineParameter> parameters) {
|
||||
Context context = new Context();
|
||||
try {
|
||||
Process process = processService.create(context, ePerson, scriptName, parameters);
|
||||
processId = process.getID();
|
||||
this.scriptName = process.getName();
|
||||
|
||||
context.complete();
|
||||
} catch (SQLException e) {
|
||||
log.error("RestDSpaceRunnableHandler with ePerson: " + ePerson
|
||||
.getEmail() + " for Script with name: " + scriptName +
|
||||
" and parameters: " + parameters + " could nto be created", e);
|
||||
} finally {
|
||||
if (context.isValid()) {
|
||||
context.abort();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void start() {
|
||||
Context context = new Context();
|
||||
try {
|
||||
Process process = processService.find(context, processId);
|
||||
processService.start(context, process);
|
||||
context.complete();
|
||||
logInfo("The script has started");
|
||||
} catch (SQLException e) {
|
||||
log.error("RestDSpaceRunnableHandler with process: " + processId + " could not be started", e);
|
||||
} finally {
|
||||
if (context.isValid()) {
|
||||
context.abort();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void handleCompletion() {
|
||||
Context context = new Context();
|
||||
try {
|
||||
Process process = processService.find(context, processId);
|
||||
processService.complete(context, process);
|
||||
context.complete();
|
||||
logInfo("The script has completed");
|
||||
} catch (SQLException e) {
|
||||
log.error("RestDSpaceRunnableHandler with process: " + processId + " could not be completed", e);
|
||||
} finally {
|
||||
if (context.isValid()) {
|
||||
context.abort();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void handleException(Exception e) {
|
||||
handleException(null, e);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void handleException(String message) {
|
||||
handleException(message, null);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void handleException(String message, Exception e) {
|
||||
if (message != null) {
|
||||
logError(message);
|
||||
}
|
||||
if (e != null) {
|
||||
logError(ExceptionUtils.getStackTrace(e));
|
||||
}
|
||||
|
||||
Context context = new Context();
|
||||
try {
|
||||
Process process = processService.find(context, processId);
|
||||
processService.fail(context, process);
|
||||
context.complete();
|
||||
} catch (SQLException sqlException) {
|
||||
log.error("SQL exception while handling another exception", e);
|
||||
} finally {
|
||||
if (context.isValid()) {
|
||||
context.abort();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void logDebug(String message) {
|
||||
String logMessage = getLogMessage(message);
|
||||
log.debug(logMessage);
|
||||
}
|
||||
|
||||
private String getLogMessage(String message) {
|
||||
return String
|
||||
.format("Process id: %d, script name: %s, message: %s", processId, scriptName, message);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void logInfo(String message) {
|
||||
String logMessage = getLogMessage(message);
|
||||
log.info(logMessage);
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void logWarning(String message) {
|
||||
String logMessage = getLogMessage(message);
|
||||
log.warn(logMessage);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void logError(String message) {
|
||||
String logMessage = getLogMessage(message);
|
||||
log.error(logMessage);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void printHelp(Options options, String name) {
|
||||
if (options != null) {
|
||||
HelpFormatter formatter = new HelpFormatter();
|
||||
StringWriter out = new StringWriter();
|
||||
PrintWriter pw = new PrintWriter(out);
|
||||
|
||||
formatter.printUsage(pw, 1000, name, options);
|
||||
pw.flush();
|
||||
|
||||
String helpString = out.toString();
|
||||
|
||||
logInfo(helpString);
|
||||
}
|
||||
}
|
||||
|
||||
public Process getProcess() {
|
||||
Context context = new Context();
|
||||
try {
|
||||
return processService.find(context, processId);
|
||||
} catch (SQLException e) {
|
||||
log.error("RestDSpaceRunnableHandler with process: " + processId + " could not be found", e);
|
||||
} finally {
|
||||
if (context.isValid()) {
|
||||
context.abort();
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public void schedule(DSpaceRunnable script) {
|
||||
Context context = new Context();
|
||||
try {
|
||||
Process process = processService.find(context, processId);
|
||||
process.setProcessStatus(ProcessStatus.SCHEDULED);
|
||||
processService.update(context, process);
|
||||
context.complete();
|
||||
} catch (SQLException e) {
|
||||
log.error("RestDSpaceRunnableHandler with process: " + processId + " ran into an SQLException", e);
|
||||
} finally {
|
||||
if (context.isValid()) {
|
||||
context.abort();
|
||||
}
|
||||
}
|
||||
script.run();
|
||||
}
|
||||
}
|
@@ -48,6 +48,8 @@
|
||||
<mapping class="org.dspace.content.RelationshipType"/>
|
||||
<mapping class="org.dspace.content.EntityType"/>
|
||||
|
||||
<mapping class="org.dspace.content.Process"/>
|
||||
|
||||
<mapping class="org.dspace.content.MetadataField"/>
|
||||
<mapping class="org.dspace.content.MetadataSchema"/>
|
||||
<mapping class="org.dspace.content.MetadataValue"/>
|
||||
|
@@ -32,6 +32,8 @@
|
||||
<bean class="org.dspace.content.dao.impl.EntityTypeDAOImpl"/>
|
||||
<bean class="org.dspace.content.dao.impl.RelationshipTypeDAOImpl"/>
|
||||
|
||||
<bean class="org.dspace.content.dao.impl.ProcessDAOImpl"/>
|
||||
|
||||
<bean class="org.dspace.eperson.dao.impl.EPersonDAOImpl"/>
|
||||
<bean class="org.dspace.eperson.dao.impl.Group2GroupCacheDAOImpl"/>
|
||||
<bean class="org.dspace.eperson.dao.impl.GroupDAOImpl"/>
|
||||
|
@@ -22,6 +22,7 @@
|
||||
<bean id="authorizeServiceFactory" class="org.dspace.authorize.factory.AuthorizeServiceFactoryImpl"/>
|
||||
<bean id="checkerServiceFactory" class="org.dspace.checker.factory.CheckerServiceFactoryImpl"/>
|
||||
<bean id="contentServiceFactory" class="org.dspace.content.factory.ContentServiceFactoryImpl"/>
|
||||
<bean id="processServiceFactory" class="org.dspace.content.factory.impl.ProcessServiceFactoryImpl"/>
|
||||
<bean id="coreServiceFactory" class="org.dspace.core.factory.CoreServiceFactoryImpl"/>
|
||||
<bean id="curateServiceFactory" class="org.dspace.curate.factory.CurateServiceFactoryImpl"/>
|
||||
|
||||
|
@@ -55,6 +55,8 @@
|
||||
<bean class="org.dspace.content.EntityServiceImpl"/>
|
||||
<bean class="org.dspace.content.RelationshipTypeServiceImpl"/>
|
||||
|
||||
<bean class="org.dspace.content.ProcessServiceImpl"/>
|
||||
|
||||
<bean class="org.dspace.content.authority.ChoiceAuthorityServiceImpl"/>
|
||||
<bean class="org.dspace.content.authority.MetadataAuthorityServiceImpl" lazy-init="true"/>
|
||||
|
||||
@@ -112,5 +114,7 @@
|
||||
<bean class="org.dspace.xmlworkflow.XmlWorkflowServiceImpl"/>
|
||||
<bean class="org.dspace.xmlworkflow.WorkflowRequirementsServiceImpl"/>
|
||||
<bean class="org.dspace.xmlworkflow.XmlWorkflowFactoryImpl"/>
|
||||
|
||||
|
||||
</beans>
|
||||
|
||||
|
13
dspace/config/spring/api/scripts-and-processes.xml
Normal file
13
dspace/config/spring/api/scripts-and-processes.xml
Normal file
@@ -0,0 +1,13 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<beans xmlns="http://www.springframework.org/schema/beans"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://www.springframework.org/schema/beans
|
||||
http://www.springframework.org/schema/beans/spring-beans-2.5.xsd">
|
||||
|
||||
<bean id="indexClient" class="org.dspace.scripts.impl.IndexClient" scope="prototype">
|
||||
<property name="name" value="index-discovery"/>
|
||||
<property name="description" value="Update Discovery Solr Search Index"/>
|
||||
</bean>
|
||||
|
||||
|
||||
</beans>
|
Reference in New Issue
Block a user