@Override public WorkspaceItem abort(Context c, XmlWorkflowItem wi, EPerson e) throws AuthorizeException, SQLException, IOException { if (!authorizeService.isAdmin(c)) { throw new AuthorizeException("You must be an admin to abort a workflow"); } c.turnOffAuthorisationSystem(); // Restore permissions for the submitter // convert into personal workspace WorkspaceItem wsi = returnToWorkspace(c, wi); log.info( LogManager.getHeader( c, "abort_workflow", "workflow_item_id=" + wi.getID() + "item_id=" + wsi.getItem().getID() + "collection_id=" + wi.getCollection().getID() + "eperson_id=" + e.getID())); c.restoreAuthSystemState(); return wsi; }
/** * Return the workflow item to the workspace of the submitter. The workflow item is removed, and a * workspace item created. * * @param c Context * @param wfi WorkflowItem to be 'dismantled' * @return the workspace item * @throws java.io.IOException ... * @throws java.sql.SQLException ... * @throws org.dspace.authorize.AuthorizeException ... */ protected WorkspaceItem returnToWorkspace(Context c, XmlWorkflowItem wfi) throws SQLException, IOException, AuthorizeException { // authorize a DSpaceActions.REJECT // stop workflow deleteAllTasks(c, wfi); c.turnOffAuthorisationSystem(); // Also clear all info for this step workflowRequirementsService.clearInProgressUsers(c, wfi); // Remove (if any) the workflowItemroles for this item workflowItemRoleService.deleteForWorkflowItem(c, wfi); Item myitem = wfi.getItem(); // Restore permissions for the submitter grantUserAllItemPolicies(c, myitem, myitem.getSubmitter()); // FIXME: How should this interact with the workflow system? // FIXME: Remove license // FIXME: Provenance statement? // Create the new workspace item row WorkspaceItem workspaceItem = workspaceItemService.create(c, wfi); workspaceItem.setMultipleFiles(wfi.hasMultipleFiles()); workspaceItem.setMultipleTitles(wfi.hasMultipleTitles()); workspaceItem.setPublishedBefore(wfi.isPublishedBefore()); workspaceItemService.update(c, workspaceItem); // myitem.update(); log.info( LogManager.getHeader( c, "return_to_workspace", "workflow_item_id=" + wfi.getID() + "workspace_item_id=" + workspaceItem.getID())); // Now remove the workflow object manually from the database xmlWorkflowItemService.deleteWrapper(c, wfi); return workspaceItem; }
@Override public Group createAdministrators(Context context, Community community) throws SQLException, AuthorizeException { // Check authorisation - Must be an Admin to create more Admins AuthorizeUtil.authorizeManageAdminGroup(context, community); Group admins = community.getAdministrators(); if (admins == null) { // turn off authorization so that Community Admins can create Sub-Community Admins context.turnOffAuthorisationSystem(); admins = groupService.create(context); context.restoreAuthSystemState(); admins.setName(context, "COMMUNITY_" + community.getID() + "_ADMIN"); groupService.update(context, admins); } authorizeService.addPolicy(context, community, Constants.ADMIN, admins); // register this as the admin group community.setAdmins(admins); return admins; }
@Override public XmlWorkflowItem start(Context context, WorkspaceItem wsi) throws SQLException, AuthorizeException, IOException, WorkflowException { try { Item myitem = wsi.getItem(); Collection collection = wsi.getCollection(); Workflow wf = xmlWorkflowFactory.getWorkflow(collection); XmlWorkflowItem wfi = xmlWorkflowItemService.create(context, myitem, collection); wfi.setMultipleFiles(wsi.hasMultipleFiles()); wfi.setMultipleTitles(wsi.hasMultipleTitles()); wfi.setPublishedBefore(wsi.isPublishedBefore()); xmlWorkflowItemService.update(context, wfi); removeUserItemPolicies(context, myitem, myitem.getSubmitter()); grantSubmitterReadPolicies(context, myitem); context.turnOffAuthorisationSystem(); Step firstStep = wf.getFirstStep(); if (firstStep.isValidStep(context, wfi)) { activateFirstStep(context, wf, firstStep, wfi); } else { // Get our next step, if none is found, archive our item firstStep = wf.getNextStep(context, wfi, firstStep, ActionResult.OUTCOME_COMPLETE); if (firstStep == null) { archive(context, wfi); } else { activateFirstStep(context, wf, firstStep, wfi); } } // remove the WorkspaceItem workspaceItemService.deleteWrapper(context, wsi); context.restoreAuthSystemState(); return wfi; } catch (WorkflowConfigurationException e) { throw new WorkflowException(e); } }
/** * Return instance of collection with passed id. You can add more properties through expand * parameter. * * @param expand String in which is what you want to add to returned instance of collection. * Options are: "all", "parentCommunityList", "parentCommunity", "items", "license" and * "logo". If you want to use multiple options, it must be separated by commas. * @param limit Limit value for items in list in collection. Default value is 100. * @param offset Offset of start index in list of items of collection. Default value is 0. * @param filters Comma separated list of Item Filters to use to evaluate against the items in a * collection * @param query_field List of metadata fields to evaluate in a metadata query. Each list value is * used in conjunction with a query_op and query_field. * @param query_op List of metadata operators to use in a metadata query. Each list value is used * in conjunction with a query_field and query_field. * @param query_val List of metadata values to evaluate in a metadata query. Each list value is * used in conjunction with a query_value and query_op. * @param collSel List of collections to query. * @param headers If you want to access to collection under logged user into context. In headers * must be set header "rest-dspace-token" with passed token from login method. * @return Return instance of collection. It can also return status code NOT_FOUND(404) if id of * collection is incorrect or status code UNATHORIZED(401) if user has no permission to read * collection. * @throws WebApplicationException It is thrown when was problem with database reading * (SQLException) or problem with creating context(ContextException). It is thrown by * NOT_FOUND and UNATHORIZED status codes, too. */ @GET @Produces({MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML}) public org.dspace.rest.common.ItemFilter getItemQuery( @QueryParam("expand") String expand, @QueryParam("limit") @DefaultValue("100") Integer limit, @QueryParam("offset") @DefaultValue("0") Integer offset, @QueryParam("userIP") String user_ip, @QueryParam("userAgent") String user_agent, @QueryParam("xforwarderfor") String xforwarderfor, @QueryParam("filters") @DefaultValue("is_item,all_filters") String filters, @QueryParam("query_field[]") @DefaultValue("dc.title") List<String> query_field, @QueryParam("query_op[]") @DefaultValue("exists") List<String> query_op, @QueryParam("query_val[]") @DefaultValue("") List<String> query_val, @QueryParam("collSel[]") @DefaultValue("") List<String> collSel, @Context HttpHeaders headers, @Context HttpServletRequest request) { org.dspace.core.Context context = null; ItemFilterSet itemFilterSet = new ItemFilterSet(filters, true); ItemFilter result = itemFilterSet.getAllFiltersFilter(); try { context = createContext(getUser(headers)); if (!configurationService.getBooleanProperty("rest.reporting-authenticate", true)) { context.turnOffAuthorisationSystem(); } int index = Math.min(query_field.size(), Math.min(query_op.size(), query_val.size())); List<ItemFilterQuery> itemFilterQueries = new ArrayList<ItemFilterQuery>(); for (int i = 0; i < index; i++) { itemFilterQueries.add( new ItemFilterQuery(query_field.get(i), query_op.get(i), query_val.get(i))); } String regexClause = configurationService.getProperty("rest.regex-clause"); if (regexClause == null) { regexClause = ""; } List<UUID> uuids = getUuidsFromStrings(collSel); List<List<MetadataField>> listFieldList = getMetadataFieldsList(context, query_field); Iterator<org.dspace.content.Item> childItems = itemService.findByMetadataQuery( context, listFieldList, query_op, query_val, uuids, regexClause, offset, limit); int count = itemFilterSet.processSaveItems(context, childItems, true, expand); writeStats( siteService.findSite(context), UsageEvent.Action.VIEW, user_ip, user_agent, xforwarderfor, headers, request, context); result.annotateQuery(query_field, query_op, query_val); result.setUnfilteredItemCount(count); context.complete(); } catch (IOException e) { processException(e.getMessage(), context); } catch (SQLException e) { processException(e.getMessage(), context); } catch (AuthorizeException e) { processException(e.getMessage(), context); } catch (ContextException e) { processException("Unauthorized filtered item query. " + e.getMessage(), context); } finally { processFinally(context); } return result; }
@Override public WorkspaceItem sendWorkflowItemBackSubmission( Context context, XmlWorkflowItem wi, EPerson e, String provenance, String rejection_message) throws SQLException, AuthorizeException, IOException { String workflowID = null; String currentStepId = null; String currentActionConfigId = null; ClaimedTask claimedTask = claimedTaskService.findByWorkflowIdAndEPerson(context, wi, e); if (claimedTask != null) { // Log it workflowID = claimedTask.getWorkflowID(); currentStepId = claimedTask.getStepID(); currentActionConfigId = claimedTask.getActionID(); } context.turnOffAuthorisationSystem(); // rejection provenance Item myitem = wi.getItem(); // Get current date String now = DCDate.getCurrent().toString(); // Get user's name + email address String usersName = getEPersonName(e); // Here's what happened String provDescription = provenance + " Rejected by " + usersName + ", reason: " + rejection_message + " on " + now + " (GMT) "; // Add to item as a DC field itemService.addMetadata( context, myitem, MetadataSchema.DC_SCHEMA, "description", "provenance", "en", provDescription); // Clear any workflow schema related metadata itemService.clearMetadata( context, myitem, WorkflowRequirementsService.WORKFLOW_SCHEMA, Item.ANY, Item.ANY, Item.ANY); itemService.update(context, myitem); // convert into personal workspace WorkspaceItem wsi = returnToWorkspace(context, wi); // notify that it's been rejected notifyOfReject(context, wi, e, rejection_message); log.info( LogManager.getHeader( context, "reject_workflow", "workflow_item_id=" + wi.getID() + "item_id=" + wi.getItem().getID() + "collection_id=" + wi.getCollection().getID() + "eperson_id=" + e.getID())); logWorkflowEvent(context, workflowID, currentStepId, currentActionConfigId, wi, e, null, null); context.restoreAuthSystemState(); return wsi; }
@Override public WorkflowActionConfig processOutcome( Context c, EPerson user, Workflow workflow, Step currentStep, WorkflowActionConfig currentActionConfig, ActionResult currentOutcome, XmlWorkflowItem wfi, boolean enteredNewStep) throws IOException, AuthorizeException, SQLException, WorkflowException { if (currentOutcome.getType() == ActionResult.TYPE.TYPE_PAGE || currentOutcome.getType() == ActionResult.TYPE.TYPE_ERROR) { // Our outcome is a page or an error, so return our current action c.restoreAuthSystemState(); return currentActionConfig; } else if (currentOutcome.getType() == ActionResult.TYPE.TYPE_CANCEL || currentOutcome.getType() == ActionResult.TYPE.TYPE_SUBMISSION_PAGE) { // We either pressed the cancel button or got an order to return to the submission page, so // don't return an action // By not returning an action we ensure ourselfs that we go back to the submission page c.restoreAuthSystemState(); return null; } else if (currentOutcome.getType() == ActionResult.TYPE.TYPE_OUTCOME) { Step nextStep = null; WorkflowActionConfig nextActionConfig = null; try { // We have completed our action search & retrieve the next action if (currentOutcome.getResult() == ActionResult.OUTCOME_COMPLETE) { nextActionConfig = currentStep.getNextAction(currentActionConfig); } if (nextActionConfig != null) { // We remain in the current step since an action is found nextStep = currentStep; nextActionConfig.getProcessingAction().activate(c, wfi); if (nextActionConfig.requiresUI() && !enteredNewStep) { createOwnedTask(c, wfi, currentStep, nextActionConfig, user); return nextActionConfig; } else if (nextActionConfig.requiresUI() && enteredNewStep) { // We have entered a new step and have encountered a UI, return null since the current // user doesn't have anything to do with this c.restoreAuthSystemState(); return null; } else { ActionResult newOutcome = nextActionConfig.getProcessingAction().execute(c, wfi, currentStep, null); return processOutcome( c, user, workflow, currentStep, nextActionConfig, newOutcome, wfi, enteredNewStep); } } else if (enteredNewStep) { // If the user finished his/her step, we keep processing until there is a UI step action // or no step at all nextStep = workflow.getNextStep(c, wfi, currentStep, currentOutcome.getResult()); c.turnOffAuthorisationSystem(); nextActionConfig = processNextStep(c, user, workflow, currentOutcome, wfi, nextStep); // If we require a user interface return null so that the user is redirected to the // "submissions page" if (nextActionConfig == null || nextActionConfig.requiresUI()) { return null; } else { return nextActionConfig; } } else { ClaimedTask task = claimedTaskService.findByWorkflowIdAndEPerson(c, wfi, user); // Check if we have a task for this action (might not be the case with automatic steps) // First add it to our list of finished users, since no more actions remain workflowRequirementsService.addFinishedUser(c, wfi, user); c.turnOffAuthorisationSystem(); // Check if our requirements have been met if ((currentStep.isFinished(c, wfi) && currentOutcome.getResult() == ActionResult.OUTCOME_COMPLETE) || currentOutcome.getResult() != ActionResult.OUTCOME_COMPLETE) { // Delete all the table rows containing the users who performed this task workflowRequirementsService.clearInProgressUsers(c, wfi); // Remove all the tasks deleteAllTasks(c, wfi); nextStep = workflow.getNextStep(c, wfi, currentStep, currentOutcome.getResult()); nextActionConfig = processNextStep(c, user, workflow, currentOutcome, wfi, nextStep); // If we require a user interface return null so that the user is redirected to the // "submissions page" if (nextActionConfig == null || nextActionConfig.requiresUI()) { return null; } else { return nextActionConfig; } } else { // We are done with our actions so go to the submissions page but remove action // ClaimedAction first deleteClaimedTask(c, wfi, task); c.restoreAuthSystemState(); nextStep = currentStep; nextActionConfig = currentActionConfig; return null; } } } catch (Exception e) { log.error("error while processing workflow outcome", e); e.printStackTrace(); } finally { if ((nextStep != null && currentStep != null && nextActionConfig != null) || (wfi.getItem().isArchived() && currentStep != null)) { logWorkflowEvent( c, currentStep.getWorkflow().getID(), currentStep.getId(), currentActionConfig.getId(), wfi, user, nextStep, nextActionConfig); } } } log.error(LogManager.getHeader(c, "Invalid step outcome", "Workflow item id: " + wfi.getID())); throw new WorkflowException("Invalid step outcome"); }
public static void main(String[] argv) throws Exception { DSIndexer.setBatchProcessingMode(true); Date startTime = new Date(); int status = 0; try { // create an options object and populate it CommandLineParser parser = new PosixParser(); Options options = new Options(); options.addOption("a", "add", false, "add items to DSpace"); options.addOption("r", "replace", false, "replace items in mapfile"); options.addOption("d", "delete", false, "delete items listed in mapfile"); options.addOption("s", "source", true, "source of items (directory)"); options.addOption("z", "zip", true, "name of zip file"); options.addOption("c", "collection", true, "destination collection(s) Handle or database ID"); options.addOption("m", "mapfile", true, "mapfile items in mapfile"); options.addOption("e", "eperson", true, "email of eperson doing importing"); options.addOption("w", "workflow", false, "send submission through collection's workflow"); options.addOption( "n", "notify", false, "if sending submissions through the workflow, send notification emails"); options.addOption("t", "test", false, "test run - do not actually import items"); options.addOption("p", "template", false, "apply template"); options.addOption("R", "resume", false, "resume a failed import (add only)"); options.addOption("q", "quiet", false, "don't display metadata"); options.addOption("h", "help", false, "help"); CommandLine line = parser.parse(options, argv); String command = null; // add replace remove, etc String sourcedir = null; String mapfile = null; String eperson = null; // db ID or email String[] collections = null; // db ID or handles if (line.hasOption('h')) { HelpFormatter myhelp = new HelpFormatter(); myhelp.printHelp("ItemImport\n", options); System.out.println( "\nadding items: ItemImport -a -e eperson -c collection -s sourcedir -m mapfile"); System.out.println( "\nadding items from zip file: ItemImport -a -e eperson -c collection -s sourcedir -z filename.zip -m mapfile"); System.out.println( "replacing items: ItemImport -r -e eperson -c collection -s sourcedir -m mapfile"); System.out.println("deleting items: ItemImport -d -e eperson -m mapfile"); System.out.println( "If multiple collections are specified, the first collection will be the one that owns the item."); System.exit(0); } if (line.hasOption('a')) { command = "add"; } if (line.hasOption('r')) { command = "replace"; } if (line.hasOption('d')) { command = "delete"; } if (line.hasOption('w')) { useWorkflow = true; if (line.hasOption('n')) { useWorkflowSendEmail = true; } } if (line.hasOption('t')) { isTest = true; System.out.println("**Test Run** - not actually importing items."); } if (line.hasOption('p')) { template = true; } if (line.hasOption('s')) // source { sourcedir = line.getOptionValue('s'); } if (line.hasOption('m')) // mapfile { mapfile = line.getOptionValue('m'); } if (line.hasOption('e')) // eperson { eperson = line.getOptionValue('e'); } if (line.hasOption('c')) // collections { collections = line.getOptionValues('c'); } if (line.hasOption('R')) { isResume = true; System.out.println("**Resume import** - attempting to import items not already imported"); } if (line.hasOption('q')) { isQuiet = true; } boolean zip = false; String zipfilename = ""; String ziptempdir = ConfigurationManager.getProperty("org.dspace.app.itemexport.work.dir"); if (line.hasOption('z')) { zip = true; zipfilename = sourcedir + System.getProperty("file.separator") + line.getOptionValue('z'); } // now validate // must have a command set if (command == null) { System.out.println( "Error - must run with either add, replace, or remove (run with -h flag for details)"); System.exit(1); } else if ("add".equals(command) || "replace".equals(command)) { if (sourcedir == null) { System.out.println("Error - a source directory containing items must be set"); System.out.println(" (run with -h flag for details)"); System.exit(1); } if (mapfile == null) { System.out.println("Error - a map file to hold importing results must be specified"); System.out.println(" (run with -h flag for details)"); System.exit(1); } if (eperson == null) { System.out.println("Error - an eperson to do the importing must be specified"); System.out.println(" (run with -h flag for details)"); System.exit(1); } if (collections == null) { System.out.println("Error - at least one destination collection must be specified"); System.out.println(" (run with -h flag for details)"); System.exit(1); } } else if ("delete".equals(command)) { if (eperson == null) { System.out.println("Error - an eperson to do the importing must be specified"); System.exit(1); } if (mapfile == null) { System.out.println("Error - a map file must be specified"); System.exit(1); } } // can only resume for adds if (isResume && !"add".equals(command)) { System.out.println("Error - resume option only works with --add command"); System.exit(1); } // do checks around mapfile - if mapfile exists and 'add' is selected, // resume must be chosen File myFile = new File(mapfile); if (!isResume && "add".equals(command) && myFile.exists()) { System.out.println("Error - the mapfile " + mapfile + " already exists."); System.out.println( "Either delete it or use --resume if attempting to resume an aborted import."); System.exit(1); } // does the zip file exist and can we write to the temp directory if (zip) { File zipfile = new File(sourcedir); if (!zipfile.canRead()) { System.out.println("Zip file '" + sourcedir + "' does not exist, or is not readable."); System.exit(1); } if (ziptempdir == null) { System.out.println( "Unable to unzip import file as the key 'org.dspace.app.itemexport.work.dir' is not set in dspace.cfg"); System.exit(1); } zipfile = new File(ziptempdir); if (!zipfile.isDirectory()) { System.out.println( "'" + ConfigurationManager.getProperty("org.dspace.app.itemexport.work.dir") + "' as defined by the key 'org.dspace.app.itemexport.work.dir' in dspace.cfg " + "is not a valid directory"); System.exit(1); } File tempdir = new File(ziptempdir); if (!tempdir.exists() && !tempdir.mkdirs()) { log.error("Unable to create temporary directory"); } sourcedir = ziptempdir + System.getProperty("file.separator") + line.getOptionValue("z"); ziptempdir = ziptempdir + System.getProperty("file.separator") + line.getOptionValue("z") + System.getProperty("file.separator"); } ItemImport myloader = new ItemImport(); // create a context Context c = new Context(); // find the EPerson, assign to context EPerson myEPerson = null; if (eperson.indexOf('@') != -1) { // @ sign, must be an email myEPerson = EPerson.findByEmail(c, eperson); } else { myEPerson = EPerson.find(c, Integer.parseInt(eperson)); } if (myEPerson == null) { System.out.println("Error, eperson cannot be found: " + eperson); System.exit(1); } c.setCurrentUser(myEPerson); // find collections Collection[] mycollections = null; // don't need to validate collections set if command is "delete" if (!"delete".equals(command)) { System.out.println("Destination collections:"); mycollections = new Collection[collections.length]; // validate each collection arg to see if it's a real collection for (int i = 0; i < collections.length; i++) { // is the ID a handle? if (collections[i].indexOf('/') != -1) { // string has a / so it must be a handle - try and resolve // it mycollections[i] = (Collection) HandleManager.resolveToObject(c, collections[i]); // resolved, now make sure it's a collection if ((mycollections[i] == null) || (mycollections[i].getType() != Constants.COLLECTION)) { mycollections[i] = null; } } // not a handle, try and treat it as an integer collection // database ID else if (collections[i] != null) { mycollections[i] = Collection.find(c, Integer.parseInt(collections[i])); } // was the collection valid? if (mycollections[i] == null) { throw new IllegalArgumentException( "Cannot resolve " + collections[i] + " to collection"); } // print progress info String owningPrefix = ""; if (i == 0) { owningPrefix = "Owning "; } System.out.println(owningPrefix + " Collection: " + mycollections[i].getMetadata("name")); } } // end of validating collections try { // If this is a zip archive, unzip it first if (zip) { ZipFile zf = new ZipFile(zipfilename); ZipEntry entry; Enumeration<? extends ZipEntry> entries = zf.entries(); while (entries.hasMoreElements()) { entry = entries.nextElement(); if (entry.isDirectory()) { if (!new File(ziptempdir + entry.getName()).mkdir()) { log.error("Unable to create contents directory"); } } else { System.out.println("Extracting file: " + entry.getName()); int index = entry.getName().lastIndexOf('/'); if (index == -1) { // Was it created on Windows instead? index = entry.getName().lastIndexOf('\\'); } if (index > 0) { File dir = new File(ziptempdir + entry.getName().substring(0, index)); if (!dir.mkdirs()) { log.error("Unable to create directory"); } } byte[] buffer = new byte[1024]; int len; InputStream in = zf.getInputStream(entry); BufferedOutputStream out = new BufferedOutputStream(new FileOutputStream(ziptempdir + entry.getName())); while ((len = in.read(buffer)) >= 0) { out.write(buffer, 0, len); } in.close(); out.close(); } } } c.turnOffAuthorisationSystem(); if ("add".equals(command)) { myloader.addItems(c, mycollections, sourcedir, mapfile, template); } else if ("replace".equals(command)) { myloader.replaceItems(c, mycollections, sourcedir, mapfile, template); } else if ("delete".equals(command)) { myloader.deleteItems(c, mapfile); } // complete all transactions c.complete(); } catch (Exception e) { // abort all operations if (mapOut != null) { mapOut.close(); } mapOut = null; c.abort(); e.printStackTrace(); System.out.println(e); status = 1; } // Delete the unzipped file try { if (zip) { System.gc(); System.out.println("Deleting temporary zip directory: " + ziptempdir); ItemImport.deleteDirectory(new File(ziptempdir)); } } catch (Exception ex) { System.out.println("Unable to delete temporary zip archive location: " + ziptempdir); } if (mapOut != null) { mapOut.close(); } if (isTest) { System.out.println("***End of Test Run***"); } } finally { DSIndexer.setBatchProcessingMode(false); Date endTime = new Date(); System.out.println("Started: " + startTime.getTime()); System.out.println("Ended: " + endTime.getTime()); System.out.println( "Elapsed time: " + ((endTime.getTime() - startTime.getTime()) / 1000) + " secs (" + (endTime.getTime() - startTime.getTime()) + " msecs)"); } System.exit(status); }