Beispiel #1
0
  @Override
  public int perform(DSpaceObject dso) throws IOException {
    status = Curator.CURATE_SKIP;
    logDebugMessage("The target dso is " + dso.getName());
    if (dso instanceof Item) {
      status = Curator.CURATE_SUCCESS;
      Item item = (Item) dso;
      try {
        openSession();
      } catch (IOException ioE) {
        // no point going further - set result and error out
        closeSession();
        setResult(CONNECT_FAIL_MESSAGE);
        return Curator.CURATE_ERROR;
      }

      try {
        Bundle bundle = item.getBundles("ORIGINAL")[0];
        results = new ArrayList<String>();
        for (Bitstream bitstream : bundle.getBitstreams()) {
          InputStream inputstream = bitstream.retrieve();
          logDebugMessage("Scanning " + bitstream.getName() + " . . . ");
          int bstatus = scan(bitstream, inputstream, getItemHandle(item));
          inputstream.close();
          if (bstatus == Curator.CURATE_ERROR) {
            // no point going further - set result and error out
            setResult(SCAN_FAIL_MESSAGE);
            status = bstatus;
            break;
          }
          if (failfast && bstatus == Curator.CURATE_FAIL) {
            status = bstatus;
            break;
          } else if (bstatus == Curator.CURATE_FAIL && status == Curator.CURATE_SUCCESS) {
            status = bstatus;
          }
        }
      } catch (AuthorizeException authE) {
        throw new IOException(authE.getMessage(), authE);
      } catch (SQLException sqlE) {
        throw new IOException(sqlE.getMessage(), sqlE);
      } finally {
        closeSession();
      }

      if (status != Curator.CURATE_ERROR) {
        formatResults(item);
      }
    }
    return status;
  }
  @GET
  @Path("/{bitstream_id}/retrieve")
  public javax.ws.rs.core.Response getFile(
      @PathParam("bitstream_id") final Integer bitstream_id,
      @QueryParam("userIP") String user_ip,
      @QueryParam("userAgent") String user_agent,
      @QueryParam("xforwarderfor") String xforwarderfor,
      @Context HttpHeaders headers,
      @Context HttpServletRequest request) {
    org.dspace.core.Context context = null;
    try {
      context = new org.dspace.core.Context();

      org.dspace.content.Bitstream bitstream =
          org.dspace.content.Bitstream.find(context, bitstream_id);
      if (AuthorizeManager.authorizeActionBoolean(
          context, bitstream, org.dspace.core.Constants.READ)) {
        if (writeStatistics) {
          writeStats(context, bitstream_id, user_ip, user_agent, xforwarderfor, headers, request);
        }

        return Response.ok(bitstream.retrieve()).type(bitstream.getFormat().getMIMEType()).build();
      } else {
        throw new WebApplicationException(Response.Status.UNAUTHORIZED);
      }

    } catch (IOException e) {
      log.error(e.getMessage());
      throw new WebApplicationException(Response.Status.INTERNAL_SERVER_ERROR);
    } catch (SQLException e) {
      log.error(e.getMessage());
      throw new WebApplicationException(Response.Status.INTERNAL_SERVER_ERROR);
    } catch (AuthorizeException e) {
      log.error(e.getMessage());
      throw new WebApplicationException(Response.Status.UNAUTHORIZED);
    } finally {
      if (context != null) {
        try {
          context.complete();
        } catch (SQLException e) {
          log.error(e.getMessage() + " occurred while trying to close");
        }
      }
    }
  }
  /** Write out a METS manifest. Mostly lifted from Rob Tansley's METS exporter. */
  private void writeManifest(Context context, Item item, PackageParameters params, OutputStream out)
      throws PackageValidationException, CrosswalkException, AuthorizeException, SQLException,
          IOException {
    try {
      // Create the METS file
      Mets mets = new Mets();

      // Top-level stuff
      mets.setID(gensym("mets"));
      mets.setOBJID("hdl:" + item.getHandle());
      mets.setLABEL("DSpace Item");
      mets.setPROFILE(getProfile());

      // MetsHdr
      MetsHdr metsHdr = new MetsHdr();
      metsHdr.setCREATEDATE(new Date()); // FIXME: CREATEDATE is now:
      // maybe should be item create
      // date?

      // Agent
      Agent agent = new Agent();
      agent.setROLE(Role.CUSTODIAN);
      agent.setTYPE(Type.ORGANIZATION);
      Name name = new Name();
      name.getContent().add(new PCData(ConfigurationManager.getProperty("dspace.name")));
      agent.getContent().add(name);
      metsHdr.getContent().add(agent);
      mets.getContent().add(metsHdr);

      // add DMD sections
      // Each type element MAY be either just a MODS-and-crosswalk name, OR
      // a combination "MODS-name:crosswalk-name" (e.g. "DC:qDC").
      String dmdTypes[] = getDmdTypes(params);

      // record of ID of each dmdsec to make DMDID in structmap.
      String dmdGroup = gensym("dmd_group");
      String dmdId[] = new String[dmdTypes.length];
      for (int i = 0; i < dmdTypes.length; ++i) {
        dmdId[i] = gensym("dmd");
        XmlData xmlData = new XmlData();
        String xwalkName, metsName;
        String parts[] = dmdTypes[i].split(":", 2);
        if (parts.length > 1) {
          metsName = parts[0];
          xwalkName = parts[1];
        } else xwalkName = metsName = dmdTypes[i];

        DisseminationCrosswalk xwalk =
            (DisseminationCrosswalk)
                PluginManager.getNamedPlugin(DisseminationCrosswalk.class, xwalkName);
        if (xwalk == null)
          throw new PackageValidationException("Cannot find " + dmdTypes[i] + " crosswalk plugin!");
        else crosswalkToMets(xwalk, item, xmlData);

        DmdSec dmdSec = new DmdSec();
        dmdSec.setID(dmdId[i]);
        dmdSec.setGROUPID(dmdGroup);
        MdWrap mdWrap = new MdWrap();
        setMdType(mdWrap, metsName);
        mdWrap.getContent().add(xmlData);
        dmdSec.getContent().add(mdWrap);
        mets.getContent().add(dmdSec);
      }

      // Only add license AMD section if there are any licenses.
      // Catch authorization failures accessing license bitstreams
      // only if we are skipping unauthorized bitstreams.
      String licenseID = null;
      try {
        AmdSec amdSec = new AmdSec();
        addRightsMd(context, item, amdSec);
        if (amdSec.getContent().size() > 0) {
          licenseID = gensym("license");
          amdSec.setID(licenseID);
          mets.getContent().add(amdSec);
        }
      } catch (AuthorizeException e) {
        String unauth = (params == null) ? null : params.getProperty("unauthorized");
        if (!(unauth != null && unauth.equalsIgnoreCase("skip"))) throw e;
        else log.warn("Skipping license metadata because of access failure: " + e.toString());
      }

      // FIXME: History data???? Nooooo!!!!

      // fileSec - all non-metadata bundles go into fileGrp,
      // and each bitstream therein into a file.
      // Create the bitstream-level techMd and div's for structmap
      // at the same time so we can connec the IDREFs to IDs.
      FileSec fileSec = new FileSec();

      String techMdType = getTechMdType(params);
      String parts[] = techMdType.split(":", 2);
      String xwalkName, metsName;
      if (parts.length > 1) {
        metsName = parts[0];
        xwalkName = parts[1];
      } else xwalkName = metsName = techMdType;

      DisseminationCrosswalk xwalk =
          (DisseminationCrosswalk)
              PluginManager.getNamedPlugin(DisseminationCrosswalk.class, xwalkName);
      if (xwalk == null)
        throw new PackageValidationException("Cannot find " + xwalkName + " crosswalk plugin!");

      // log the primary bitstream for structmap
      String primaryBitstreamFileID = null;

      // accumulate content DIV items to put in structMap later.
      List contentDivs = new ArrayList();

      // how to handle unauthorized bundle/bitstream:
      String unauth = (params == null) ? null : params.getProperty("unauthorized");

      Bundle[] bundles = item.getBundles();
      for (int i = 0; i < bundles.length; i++) {
        if (PackageUtils.isMetaInfoBundle(bundles[i])) continue;

        // unauthorized bundle?
        // NOTE: This must match the logic in disseminate()
        if (!AuthorizeManager.authorizeActionBoolean(context, bundles[i], Constants.READ)) {
          if (unauth != null && (unauth.equalsIgnoreCase("skip"))) continue;
          else
            throw new AuthorizeException(
                "Not authorized to read Bundle named \"" + bundles[i].getName() + "\"");
        }

        Bitstream[] bitstreams = bundles[i].getBitstreams();

        // Create a fileGrp
        FileGrp fileGrp = new FileGrp();

        // Bundle name for USE attribute
        String bName = bundles[i].getName();
        if ((bName != null) && !bName.equals("")) fileGrp.setUSE(bundleToFileGrp(bName));

        // watch for primary bitstream
        int primaryBitstreamID = -1;
        boolean isContentBundle = false;
        if ((bName != null) && bName.equals("ORIGINAL")) {
          isContentBundle = true;
          primaryBitstreamID = bundles[i].getPrimaryBitstreamID();
        }

        for (int bits = 0; bits < bitstreams.length; bits++) {
          // Check for authorization.  Handle unauthorized
          // bitstreams to match the logic in disseminate(),
          // i.e. "unauth=zero" means include a 0-length bitstream,
          // "unauth=skip" means to ignore it (and exclude from
          // manifest).
          boolean auth =
              AuthorizeManager.authorizeActionBoolean(context, bitstreams[bits], Constants.READ);
          if (!auth) {
            if (unauth != null && unauth.equalsIgnoreCase("skip")) continue;
            else if (!(unauth != null && unauth.equalsIgnoreCase("zero")))
              throw new AuthorizeException(
                  "Not authorized to read Bitstream, SID="
                      + String.valueOf(bitstreams[bits].getSequenceID()));
          }

          String sid = String.valueOf(bitstreams[bits].getSequenceID());

          edu.harvard.hul.ois.mets.File file = new edu.harvard.hul.ois.mets.File();

          String xmlIDstart = "bitstream_";
          String fileID = xmlIDstart + sid;

          file.setID(fileID);

          // log primary bitstream for later (structMap)
          if (bitstreams[bits].getID() == primaryBitstreamID) primaryBitstreamFileID = fileID;

          // if this is content, add to structmap too:
          if (isContentBundle) {
            Div div = new Div();
            div.setID(gensym("div"));
            div.setTYPE("DSpace Content Bitstream");
            Fptr fptr = new Fptr();
            fptr.setFILEID(fileID);
            div.getContent().add(fptr);
            contentDivs.add(div);
          }

          file.setSEQ(bitstreams[bits].getSequenceID());

          String groupID = "GROUP_" + xmlIDstart + sid;

          /*
           * If we're in THUMBNAIL or TEXT bundles, the bitstream is
           * extracted text or a thumbnail, so we use the name to work
           * out which bitstream to be in the same group as
           */
          if ((bundles[i].getName() != null)
              && (bundles[i].getName().equals("THUMBNAIL")
                  || bundles[i].getName().startsWith("TEXT"))) {
            // Try and find the original bitstream, and chuck the
            // derived bitstream in the same group
            Bitstream original = findOriginalBitstream(item, bitstreams[bits]);

            if (original != null) {
              groupID = "GROUP_" + xmlIDstart + original.getSequenceID();
            }
          }

          file.setGROUPID(groupID);
          file.setMIMETYPE(bitstreams[bits].getFormat().getMIMEType());

          // FIXME: CREATED: no date

          file.setSIZE(auth ? bitstreams[bits].getSize() : 0);

          // translate checksum and type to METS, if available.
          String csType = bitstreams[bits].getChecksumAlgorithm();
          String cs = bitstreams[bits].getChecksum();
          if (auth && cs != null && csType != null) {
            try {
              file.setCHECKSUMTYPE(Checksumtype.parse(csType));
              file.setCHECKSUM(cs);
            } catch (MetsException e) {
              log.warn("Cannot set bitstream checksum type=" + csType + " in METS.");
            }
          }

          // FLocat: filename is MD5 checksum
          FLocat flocat = new FLocat();
          flocat.setLOCTYPE(Loctype.URL);
          flocat.setXlinkHref(makeBitstreamName(bitstreams[bits]));

          // Make bitstream techMD metadata, add to file.
          String techID = "techMd_for_bitstream_" + bitstreams[bits].getSequenceID();
          AmdSec fAmdSec = new AmdSec();
          fAmdSec.setID(techID);
          TechMD techMd = new TechMD();
          techMd.setID(gensym("tech"));
          MdWrap mdWrap = new MdWrap();
          setMdType(mdWrap, metsName);
          XmlData xmlData = new XmlData();
          mdWrap.getContent().add(xmlData);
          techMd.getContent().add(mdWrap);
          fAmdSec.getContent().add(techMd);
          mets.getContent().add(fAmdSec);
          crosswalkToMets(xwalk, bitstreams[bits], xmlData);
          file.setADMID(techID);

          // Add FLocat to File, and File to FileGrp
          file.getContent().add(flocat);
          fileGrp.getContent().add(file);
        }

        // Add fileGrp to fileSec
        fileSec.getContent().add(fileGrp);
      }

      // Add fileSec to document
      mets.getContent().add(fileSec);

      // Create simple structMap: initial div represents the Item,
      // and user-visible content bitstreams are in its child divs.
      StringBuffer dmdIds = new StringBuffer();
      for (int i = 0; i < dmdId.length; ++i) dmdIds.append(" " + dmdId[i]);
      StructMap structMap = new StructMap();
      structMap.setID(gensym("struct"));
      structMap.setTYPE("LOGICAL");
      structMap.setLABEL("DSpace");
      Div div0 = new Div();
      div0.setID(gensym("div"));
      div0.setTYPE("DSpace Item");
      div0.setDMDID(dmdIds.substring(1));
      if (licenseID != null) div0.setADMID(licenseID);

      // if there is a primary bitstream, add FPTR to it.
      if (primaryBitstreamFileID != null) {
        Fptr fptr = new Fptr();
        fptr.setFILEID(primaryBitstreamFileID);
        div0.getContent().add(fptr);
      }

      // add DIV for each content bitstream
      div0.getContent().addAll(contentDivs);

      structMap.getContent().add(div0);

      // Does subclass have something to add to structMap?
      addStructMap(context, item, params, mets);

      mets.getContent().add(structMap);

      mets.validate(new MetsValidator());

      mets.write(new MetsWriter(out));
    } catch (MetsException e) {
      // We don't pass up a MetsException, so callers don't need to
      // know the details of the METS toolkit
      // e.printStackTrace();
      throw new PackageValidationException(e);
    }
  }
  public static void main(String[] argv) throws Exception {
    // create an options object and populate it
    CommandLineParser parser = new PosixParser();

    Options options = new Options();

    options.addOption("s", "set", false, "set a parent/child relationship");
    options.addOption("r", "remove", false, "remove a parent/child relationship");
    options.addOption("p", "parent", true, "parent community (handle or database ID)");
    options.addOption("c", "child", true, "child community (handle or databaseID)");
    options.addOption("h", "help", false, "help");

    CommandLine line = parser.parse(options, argv);

    String command = null; // set or remove
    String parentID = null;
    String childID = null;

    if (line.hasOption('h')) {
      HelpFormatter myhelp = new HelpFormatter();
      myhelp.printHelp("CommunityFiliator\n", options);
      System.out.println("\nestablish a relationship: CommunityFiliator -s -p parentID -c childID");
      System.out.println("remove a relationship: CommunityFiliator -r -p parentID -c childID");

      System.exit(0);
    }

    if (line.hasOption('s')) {
      command = "set";
    }

    if (line.hasOption('r')) {
      command = "remove";
    }

    if (line.hasOption('p')) // parent
    {
      parentID = line.getOptionValue('p');
    }

    if (line.hasOption('c')) // child
    {
      childID = line.getOptionValue('c');
    }

    // now validate
    // must have a command set
    if (command == null) {
      System.out.println(
          "Error - must run with either set or remove (run with -h flag for details)");
      System.exit(1);
    }

    if (command.equals("set") || command.equals("remove")) {
      if (parentID == null) {
        System.out.println("Error - a parentID must be specified (run with -h flag for details)");
        System.exit(1);
      }

      if (childID == null) {
        System.out.println("Error - a childID must be specified (run with -h flag for details)");
        System.exit(1);
      }
    }

    CommunityFiliator filiator = new CommunityFiliator();
    Context c = new Context();

    // ve are superuser!
    c.setIgnoreAuthorization(true);

    try {
      // validate and resolve the parent and child IDs into commmunities
      Community parent = filiator.resolveCommunity(c, parentID);
      Community child = filiator.resolveCommunity(c, childID);

      if (parent == null) {
        System.out.println("Error, parent community cannot be found: " + parentID);
        System.exit(1);
      }

      if (child == null) {
        System.out.println("Error, child community cannot be found: " + childID);
        System.exit(1);
      }

      if (command.equals("set")) {
        filiator.filiate(c, parent, child);
      } else {
        filiator.defiliate(c, parent, child);
      }
    } catch (SQLException sqlE) {
      System.out.println("Error - SQL exception: " + sqlE.toString());
    } catch (AuthorizeException authE) {
      System.out.println("Error - Authorize exception: " + authE.toString());
    } catch (IOException ioE) {
      System.out.println("Error - IO exception: " + ioE.toString());
    }
  }
  /**
   * 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;
  }
Beispiel #6
0
  protected void dspaceDFS(DSpaceObject dso, Callback callback, boolean check, boolean reset)
      throws SQLException {
    if (dso.getType() != Constants.SITE
        && dso.getType() != Constants.COMMUNITY
        && dso.getType() != Constants.COLLECTION
        && dso.getType() != Constants.ITEM) {
      throw new IllegalArgumentException(
          contentServiceFactory.getDSpaceObjectService(dso).getTypeText(dso)
              + " is currently not supported as independent entity.");
    }

    if (reset) {
      this.processed.clear();
    }

    if (isProcessed(dso)) {
      log.debug(
          "Skipping processing of "
              + contentServiceFactory.getDSpaceObjectService(dso).getTypeText(dso)
              + " "
              + dso.getID()
              + " (handle "
              + dso.getHandle()
              + "), already processed.");
      return;
    }
    markProcessed(dso);
    // this is useful to debug depth first search, but it is really noisy.
    // log.debug("Procesing " + contentServiceFactory.getDSpaceObjectService(dso).getTypeText(dso) +
    // " " + dso.getID() + ":" + dso.getHandle() + ".");

    // if this method is used for conversion we should check if we have the
    // permissions to read a DSO before converting all of it decendents
    // (e.g. check read permission on a community before converting all of
    // its subcommunties and collections).
    // just skip items with missing permissions and report them.
    if (check) {
      try {
        RDFUtil.isPublic(context, dso);
      } catch (ItemNotArchivedException ex) {
        if (!(dso instanceof Item)) throw new IllegalStateException(ex.getMessage(), ex);
        report(
            "Skipping processing of Item "
                + dso.getID()
                + " (handle "
                + dso.getHandle()
                + "): Item is not "
                + "archived.");
        return;
      } catch (ItemWithdrawnException ex) {
        if (!(dso instanceof Item)) throw new IllegalStateException(ex.getMessage(), ex);
        report(
            "Skipping processing of Item "
                + dso.getID()
                + " (handle "
                + dso.getHandle()
                + "): Item is "
                + "withdrawn.");
        return;
      } catch (ItemNotDiscoverableException ex) {
        if (!(dso instanceof Item)) throw new IllegalStateException(ex.getMessage(), ex);
        report(
            "Skipping processing of Item "
                + dso.getID()
                + " (handle "
                + dso.getHandle()
                + "): Item is not "
                + "discoverable.");
        return;
      } catch (AuthorizeException ex) {
        report(
            "Skipping processing of "
                + contentServiceFactory.getDSpaceObjectService(dso).getTypeText(dso)
                + " "
                + dso.getID()
                + " (handle "
                + dso.getHandle()
                + ")"
                + ", not authorized: "
                + ex.getMessage());
        return;
      }
    }

    if (dso instanceof Site) {
      List<Community> communities = communityService.findAllTop(context);
      for (Community community : communities) {
        this.dspaceDFS(community, callback, check, false);
      }
    }

    if (dso instanceof Community) {
      List<Community> subcommunities = ((Community) dso).getSubcommunities();
      for (Community sub : subcommunities) {
        this.dspaceDFS(sub, callback, check, false);
      }
      List<Collection> collections = ((Community) dso).getCollections();
      for (Collection collection : collections) {
        this.dspaceDFS(collection, callback, check, false);
      }
    }

    if (dso instanceof Collection) {
      Iterator<Item> items = itemService.findAllByCollection(context, (Collection) dso);
      while (items.hasNext()) {
        Item item = items.next();
        this.dspaceDFS(item, callback, check, false);
      }
    }

    //        Currently Bundles and Bitsreams aren't supported as independent entities.
    //        They should be converted as part of an item. So we do not need to make
    //        the recursive call for them. An item itself will be converted as part
    //        of the callback call below.
    //        The following code is left here for the day, we decide to also convert
    //        bundles and/or bitstreams.
    //
    //        if (dso instanceof Item)
    //        {
    //            Bundle[] bundles = ((Item) dso).getBundles();
    //            for (Bundle bundle : bundles)
    //            {
    //                this.dspaceDFS(bundle, callback, check, false);
    //            }
    //        }
    //
    //        if (dso instanceof Bundle)
    //        {
    //            Bitstream[] bistreams = ((Bundle) dso).getBitstreams();
    //            for (Bitstream bitstream : bistreams)
    //            {
    //                this.dspaceDFS(bitstream, callback, check, false);
    //            }
    //        }

    callback.callback(dso);
    report(
        "Processed "
            + contentServiceFactory.getDSpaceObjectService(dso).getTypeText(dso)
            + " "
            + dso.getID()
            + " (handle "
            + dso.getHandle()
            + ").");
  }