@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");
  }
Exemple #8
0
  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);
  }