diff --git a/dspace-spring-rest/src/main/java/org/dspace/app/rest/RestResourceController.java b/dspace-spring-rest/src/main/java/org/dspace/app/rest/RestResourceController.java index 07db166db4..bb9964e20b 100644 --- a/dspace-spring-rest/src/main/java/org/dspace/app/rest/RestResourceController.java +++ b/dspace-spring-rest/src/main/java/org/dspace/app/rest/RestResourceController.java @@ -25,6 +25,7 @@ import javax.servlet.http.HttpServletResponse; import com.fasterxml.jackson.databind.JsonNode; import com.fasterxml.jackson.databind.ObjectMapper; + import org.apache.commons.collections4.CollectionUtils; import org.apache.commons.lang3.StringUtils; import org.apache.log4j.Logger; @@ -551,6 +552,8 @@ public class RestResourceController implements InitializingBean { public ResponseEntity upload(HttpServletRequest request, @PathVariable String apiCategory, @PathVariable String model, + @RequestParam(required = false) + String extraField, @RequestParam("file") MultipartFile uploadfile) throws SQLException, FileNotFoundException, IOException, AuthorizeException { @@ -558,7 +561,7 @@ public class RestResourceController implements InitializingBean { checkModelPluralForm(apiCategory, model); DSpaceRestRepository repository = utils.getResourceRepository(apiCategory, model); - Iterable content = repository.upload(request, uploadfile); + Iterable content = repository.upload(request, extraField, uploadfile); List resources = new ArrayList<>(); for (T modelObject : content) { @@ -630,7 +633,6 @@ public class RestResourceController implements InitializingBean { String model, ID id, JsonNode jsonNode) throws HttpRequestMethodNotSupportedException { - checkModelPluralForm(apiCategory, model); DSpaceRestRepository repository = utils.getResourceRepository(apiCategory, model); RestAddressableModel modelObject = null; diff --git a/dspace-spring-rest/src/main/java/org/dspace/app/rest/repository/DSpaceRestRepository.java b/dspace-spring-rest/src/main/java/org/dspace/app/rest/repository/DSpaceRestRepository.java index 2d79f61961..181af6b2e1 100644 --- a/dspace-spring-rest/src/main/java/org/dspace/app/rest/repository/DSpaceRestRepository.java +++ b/dspace-spring-rest/src/main/java/org/dspace/app/rest/repository/DSpaceRestRepository.java @@ -373,6 +373,8 @@ public abstract class DSpaceRestRepository upload(HttpServletRequest request, MultipartFile uploadfile) + public Iterable upload(HttpServletRequest request, String extraField, MultipartFile uploadfile) throws SQLException, FileNotFoundException, IOException, AuthorizeException { Context context = obtainContext(); - Iterable entity = upload(context, request, uploadfile); + Iterable entity = upload(context, request, extraField, uploadfile); context.commit(); return entity; } /** * Method to implement to support bulk creation of objects from a file + * * @param request * the http request + * @param extraField + * the original name of the uploaded file * @param uploadfile * the file to process * @return the created objects @@ -402,7 +407,8 @@ public abstract class DSpaceRestRepository upload(Context context, HttpServletRequest request, MultipartFile uploadfile) + protected Iterable upload(Context context, HttpServletRequest request, String extraField, + MultipartFile uploadfile) throws SQLException, FileNotFoundException, IOException, AuthorizeException { throw new RepositoryMethodNotImplementedException("No implementation found; Method not allowed!", ""); } diff --git a/dspace-spring-rest/src/main/java/org/dspace/app/rest/repository/WorkspaceItemRestRepository.java b/dspace-spring-rest/src/main/java/org/dspace/app/rest/repository/WorkspaceItemRestRepository.java index 3bff819652..98ce42b614 100644 --- a/dspace-spring-rest/src/main/java/org/dspace/app/rest/repository/WorkspaceItemRestRepository.java +++ b/dspace-spring-rest/src/main/java/org/dspace/app/rest/repository/WorkspaceItemRestRepository.java @@ -65,6 +65,7 @@ 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.data.rest.webmvc.json.patch.PatchException; import org.springframework.stereotype.Component; import org.springframework.web.multipart.MultipartFile; @@ -325,6 +326,7 @@ public class WorkspaceItemRestRepository extends DSpaceRestRepository upload(Context context, HttpServletRequest request, MultipartFile uploadfile) + public Iterable upload(Context context, HttpServletRequest request, String extraField, + MultipartFile uploadfile) throws SQLException, FileNotFoundException, IOException, AuthorizeException { File file = Utils.getFile(uploadfile, "upload-loader", "filedataloader"); List results = new ArrayList<>(); @@ -360,7 +363,7 @@ public class WorkspaceItemRestRepository extends DSpaceRestRepository tmpResult = new ArrayList(); TransformationEngine transformationEngine1 = submissionLookupService.getPhase1TransformationEngine(); + TransformationSpec spec = new TransformationSpec(); + // FIXME this is mostly due to the need to test. The BTE framework has an assert statement that check if the + // number of found record is less than the requested and treat 0 as is, instead, the implementation assume + // 0=unlimited this lead to test failure. + // It is unclear if BTE really respect values other than 0/MAX allowing us to put a protection against heavy + // load + spec.setNumberOfRecords(Integer.MAX_VALUE); if (transformationEngine1 != null) { MultipleSubmissionLookupDataLoader dataLoader = (MultipleSubmissionLookupDataLoader) transformationEngine1.getDataLoader(); @@ -383,7 +393,7 @@ public class WorkspaceItemRestRepository extends DSpaceRestRepository()); log.debug("BTE transformation is about to start!"); - transformationEngine1.transform(new TransformationSpec()); + transformationEngine1.transform(spec); log.debug("BTE transformation finished!"); tmpResult.addAll(outputGenerator.getDtoList()); if (!tmpResult.isEmpty()) { @@ -417,7 +427,7 @@ public class WorkspaceItemRestRepository extends DSpaceRestRepository findAuthorizedOptimized = collectionService.findAuthorizedOptimized(context, + Constants.ADD); + if (findAuthorizedOptimized != null && findAuthorizedOptimized.size() > 0) { + collection = findAuthorizedOptimized.get(0); } else { - collection = collectionService.findAll(context, 1, 0).get(0); + throw new RESTAuthorizationException("No collection suitable for submission for the current user"); } - wsi = workspaceItemService.create(context, collection, true); - } catch (Exception e) { - log.error(e.getMessage(), e); } - } else { - //TODO manage setup of default collection in the case WSI it is not null - //TODO manage setup of collection discovered into request + + if (collection == null) { + throw new RESTAuthorizationException("collectionUUID=" + collectionUUID + " not found"); + } + wsi = workspaceItemService.create(context, collection, true); + } catch (SQLException e) { + // wrap in a runtime exception as we cannot change the method signature + throw new UncategorizedScriptException(e.getMessage(), e); + } catch (AuthorizeException ae) { + throw new RESTAuthorizationException(ae); } return wsi; } diff --git a/dspace-spring-rest/src/main/java/org/dspace/app/rest/submit/step/UploadStep.java b/dspace-spring-rest/src/main/java/org/dspace/app/rest/submit/step/UploadStep.java index 8ca0e10bac..a602433c4d 100644 --- a/dspace-spring-rest/src/main/java/org/dspace/app/rest/submit/step/UploadStep.java +++ b/dspace-spring-rest/src/main/java/org/dspace/app/rest/submit/step/UploadStep.java @@ -7,22 +7,32 @@ */ package org.dspace.app.rest.submit.step; +import java.io.BufferedInputStream; +import java.io.InputStream; import java.util.List; +import org.apache.log4j.Logger; +import org.dspace.app.rest.model.ErrorRest; import org.dspace.app.rest.model.patch.Operation; import org.dspace.app.rest.model.step.DataUpload; import org.dspace.app.rest.model.step.UploadBitstreamRest; +import org.dspace.app.rest.repository.WorkspaceItemRestRepository; import org.dspace.app.rest.submit.AbstractRestProcessingStep; import org.dspace.app.rest.submit.SubmissionService; +import org.dspace.app.rest.submit.UploadableStep; import org.dspace.app.rest.submit.factory.PatchOperationFactory; import org.dspace.app.rest.submit.factory.impl.PatchOperation; import org.dspace.app.util.SubmissionStepConfig; import org.dspace.content.Bitstream; +import org.dspace.content.BitstreamFormat; import org.dspace.content.Bundle; +import org.dspace.content.InProgressSubmission; +import org.dspace.content.Item; import org.dspace.content.WorkspaceItem; import org.dspace.core.Constants; import org.dspace.core.Context; import org.dspace.services.model.Request; +import org.springframework.web.multipart.MultipartFile; /** * Upload step for DSpace Spring Rest. Expose information about the bitstream @@ -30,8 +40,10 @@ import org.dspace.services.model.Request; * * @author Luigi Andrea Pascarelli (luigiandrea.pascarelli at 4science.it) */ -public class UploadStep extends org.dspace.submit.step.UploadStep implements AbstractRestProcessingStep { +public class UploadStep extends org.dspace.submit.step.UploadStep + implements AbstractRestProcessingStep, UploadableStep { + private static final Logger log = Logger.getLogger(UploadStep.class); @Override public DataUpload getData(SubmissionService submissionService, WorkspaceItem obj, SubmissionStepConfig config) @@ -79,4 +91,54 @@ public class UploadStep extends org.dspace.submit.step.UploadStep implements Abs } + @Override + public ErrorRest upload(Context context, SubmissionService submissionService, SubmissionStepConfig stepConfig, + InProgressSubmission wsi, MultipartFile file, String extraField) { + + Bitstream source = null; + BitstreamFormat bf = null; + + Item item = wsi.getItem(); + List bundles = null; + try { + // do we already have a bundle? + bundles = itemService.getBundles(item, Constants.CONTENT_BUNDLE_NAME); + + InputStream inputStream = new BufferedInputStream(file.getInputStream()); + if (bundles.size() < 1) { + // set bundle's name to ORIGINAL + source = itemService.createSingleBitstream(context, inputStream, item, Constants.CONTENT_BUNDLE_NAME); + } else { + // we have a bundle already, just add bitstream + source = bitstreamService.create(context, bundles.get(0), inputStream); + } + + source.setName(context, extraField); + source.setSource(context, file.getOriginalFilename()); + + // Identify the format + bf = bitstreamFormatService.guessFormat(context, source); + source.setFormat(context, bf); + + // Update to DB + bitstreamService.update(context, source); + itemService.update(context, item); + + } catch (Exception e) { + log.error(e.getMessage(), e); + ErrorRest result = new ErrorRest(); + result.setMessage(e.getMessage()); + if (bundles != null && bundles.size() > 0) { + result.getPaths().add( + "/" + WorkspaceItemRestRepository.OPERATION_PATH_SECTIONS + "/" + stepConfig.getId() + "/files/" + + bundles.get(0).getBitstreams().size()); + } else { + result.getPaths() + .add("/" + WorkspaceItemRestRepository.OPERATION_PATH_SECTIONS + "/" + stepConfig.getId()); + } + return result; + } + + return null; + } }