public InputStream disseminate(Context context, Item item)
      throws DSpaceSwordException, SwordError, SwordServerException {
    try {
      Abdera abdera = new Abdera();
      Feed feed = abdera.newFeed();

      this.addMetadata(feed, item);

      Bundle[] originals = item.getBundles("ORIGINAL");
      for (Bundle original : originals) {
        Bitstream[] bss = original.getBitstreams();
        for (Bitstream bitstream : bss) {
          Entry entry = feed.addEntry();
          this.populateEntry(context, entry, bitstream);
        }
      }

      ByteArrayOutputStream baos = new ByteArrayOutputStream();
      feed.writeTo(baos);
      ByteArrayInputStream bais = new ByteArrayInputStream(baos.toByteArray());
      return bais;
    } catch (SQLException e) {
      throw new DSpaceSwordException(e);
    } catch (IOException e) {
      throw new DSpaceSwordException(e);
    }
  }
示例#2
0
  /**
   * Return this resource's children. Item's children are its bitstreams.
   *
   * @return the DAV resource[]
   * @throws SQLException the SQL exception
   */
  @Override
  protected DAVResource[] children() throws SQLException {
    // Check for overall read permission on Item
    if (!AuthorizeManager.authorizeActionBoolean(this.context, this.item, Constants.READ)) {
      return new DAVResource[0];
    }

    Vector result = new Vector();
    Bundle[] bundles = this.item.getBundles();
    for (Bundle element : bundles) {
      // check read permission on this Bundle
      if (!AuthorizeManager.authorizeActionBoolean(this.context, element, Constants.READ)) {
        continue;
      }

      Bitstream[] bitstreams = element.getBitstreams();
      for (Bitstream element0 : bitstreams) {
        String ext[] = element0.getFormat().getExtensions();
        result.add(
            new DAVBitstream(
                this.context,
                this.request,
                this.response,
                makeChildPath(
                    DAVBitstream.getPathElt(
                        element0.getSequenceID(), ext.length < 1 ? null : ext[0])),
                this.item,
                element0));
      }
    }
    return (DAVResource[]) result.toArray(new DAVResource[result.size()]);
  }
  /* (non-Javadoc)
   * @see uk.ac.jorum.packager.detector.BasePackageDetector#isValidPackage()
   */
  @Override
  public boolean isValidPackage() {
    boolean result = false;
    boolean isUrl = false;

    try {
      // Download the feed
      // url is the bitstream contents

      // Check that the bitstream belongs in the FEED_BUNDLE - if it isn't then we may be looking at
      // raw content ie not a link to a feed!
      Bundle[] bundles = this.getBitstream().getBundles();
      for (Bundle b : bundles) {
        if (b.getName().equals(Constants.FEED_BUNDLE)) {
          isUrl = true;
          break;
        }
      }

      if (isUrl) {
        Document xmlDoc = getRssDocument(this.getBitstream());
        Element root = xmlDoc.getRootElement();

        Attribute version = root.getAttribute("version");
        if (root.getName().equals("rss") && version != null && version.getValue().equals("2.0")) {
          result = true;
        }
      }

    } catch (Exception e) {
      ExceptionLogger.logException(log, e);
    }

    return result;
  }
示例#4
0
  /**
   * each entry represents a bitstream....
   *
   * @param c
   * @param i
   * @param path
   * @param fileName
   * @param bundleName
   * @throws SQLException
   * @throws IOException
   * @throws AuthorizeException
   */
  private void processContentFileEntry(
      Context c, Item i, String path, String fileName, String bundleName, boolean primary)
      throws SQLException, IOException, AuthorizeException {
    String fullpath = path + File.separatorChar + fileName;

    // get an input stream
    BufferedInputStream bis = new BufferedInputStream(new FileInputStream(fullpath));

    Bitstream bs = null;
    String newBundleName = bundleName;

    if (bundleName == null) {
      // is it license.txt?
      if ("license.txt".equals(fileName)) {
        newBundleName = "LICENSE";
      } else {
        // call it ORIGINAL
        newBundleName = "ORIGINAL";
      }
    }

    if (!isTest) {
      // find the bundle
      Bundle[] bundles = i.getBundles(newBundleName);
      Bundle targetBundle = null;

      if (bundles.length < 1) {
        // not found, create a new one
        targetBundle = i.createBundle(newBundleName);
      } else {
        // put bitstreams into first bundle
        targetBundle = bundles[0];
      }

      // now add the bitstream
      bs = targetBundle.createBitstream(bis);

      bs.setName(fileName);

      // Identify the format
      // FIXME - guessing format guesses license.txt incorrectly as a text
      // file format!
      BitstreamFormat bf = FormatIdentifier.guessFormat(c, bs);
      bs.setFormat(bf);

      // Is this a the primary bitstream?
      if (primary) {
        targetBundle.setPrimaryBitstreamID(bs.getID());
        targetBundle.update();
      }

      bs.update();
    }

    bis.close();
  }
示例#5
0
 // check whether any bundle belongs to any item that passed submission
 // and workflow process
 protected boolean isAnyItemInstalled(Context ctx, List<Bundle> bundles) throws SQLException {
   for (Bundle bundle : bundles) {
     for (Item item : bundle.getItems()) {
       if (workspaceItemService.findByItem(ctx, item) == null
           && workflowItemService.findByItem(ctx, item) == null) {
         return true;
       }
     }
   }
   return false;
 }
示例#6
0
 /**
  * Get the license for this Item as String. License is the first bitstream named "license.txt" in
  * a LICENSE bundle, apparently?
  *
  * <p>FIXME: is this correct? there's no counterexample..
  *
  * @return license string, or null if none found.
  * @throws SQLException the SQL exception
  * @throws AuthorizeException the authorize exception
  * @throws IOException Signals that an I/O exception has occurred.
  */
 private String getLicenseAsString() throws SQLException, AuthorizeException, IOException {
   Bundle lb[] = this.item.getBundles(Constants.LICENSE_BUNDLE_NAME);
   for (Bundle element : lb) {
     Bitstream lbs = element.getBitstreamByName("license.txt");
     if (lbs != null) {
       ByteArrayOutputStream baos = new ByteArrayOutputStream((int) lbs.getSize());
       Utils.copy(lbs.retrieve(), baos);
       return baos.toString();
     }
   }
   return null;
 }
示例#7
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;
  }
 protected void addGroupPolicyToItem(Context context, Item item, int type, Group group)
     throws AuthorizeException, SQLException {
   if (group != null) {
     authorizeService.addPolicy(context, item, type, group);
     List<Bundle> bundles = item.getBundles();
     for (Bundle bundle : bundles) {
       authorizeService.addPolicy(context, bundle, type, group);
       List<Bitstream> bits = bundle.getBitstreams();
       for (Bitstream bit : bits) {
         authorizeService.addPolicy(context, bit, type, group);
       }
     }
   }
 }
 /**
  * Tests bitstream for membership in specified bundles (ORIGINAL, TEXT, THUMBNAIL)
  *
  * @param bitstream
  * @throws BitstreamFilterException
  * @returns true if bitstream is in specified bundles
  */
 public boolean accept(Bitstream bitstream) throws BitstreamFilterException {
   try {
     Bundle[] bundles = bitstream.getBundles();
     for (Bundle b : bundles) {
       for (String bn : bundlesToEmpty) {
         if (b.getName().equals(bn)) {
           return true;
         }
       }
     }
   } catch (SQLException e) {
     throw new BitstreamFilterException(e);
   }
   return false;
 }
  /**
   * Delete bitstream from item
   *
   * @param context
   * @param ItemArchive
   * @param isTest
   * @param suppressUndo
   * @throws IllegalArgumentException
   * @throws ParseException
   * @throws IOException
   * @throws AuthorizeException
   * @throws SQLException
   */
  public void execute(Context context, ItemArchive itarch, boolean isTest, boolean suppressUndo)
      throws IllegalArgumentException, IOException, SQLException, AuthorizeException,
          ParseException {
    File f = new File(itarch.getDirectory(), ItemUpdate.DELETE_CONTENTS_FILE);
    if (!f.exists()) {
      ItemUpdate.pr(
          "Warning: Delete_contents file for item " + itarch.getDirectoryName() + " not found.");
    } else {
      List<Integer> list = MetadataUtilities.readDeleteContentsFile(f);
      if (list.isEmpty()) {
        ItemUpdate.pr("Warning: empty delete_contents file for item " + itarch.getDirectoryName());
      } else {
        for (int id : list) {
          try {
            Bitstream bs = Bitstream.find(context, id);
            if (bs == null) {
              ItemUpdate.pr("Bitstream not found by id: " + id);
            } else {
              Bundle[] bundles = bs.getBundles();
              for (Bundle b : bundles) {
                if (isTest) {
                  ItemUpdate.pr("Delete bitstream with id = " + id);
                } else {
                  b.removeBitstream(bs);
                  ItemUpdate.pr("Deleted bitstream with id = " + id);
                }
              }

              if (alterProvenance) {
                DtoMetadata dtom = DtoMetadata.create("dc.description.provenance", "en", "");

                String append =
                    "Bitstream " + bs.getName() + " deleted on " + DCDate.getCurrent() + "; ";
                Item item = bundles[0].getItems()[0];
                ItemUpdate.pr("Append provenance with: " + append);

                if (!isTest) {
                  MetadataUtilities.appendMetadata(item, dtom, false, append);
                }
              }
            }
          } catch (SQLException e) {
            ItemUpdate.pr("Error finding bitstream from id: " + id + " : " + e.toString());
          }
        }
      }
    }
  }
示例#11
0
 protected void removeGroupItemPolicies(Context context, Item item, Group e)
     throws SQLException, AuthorizeException {
   if (e != null) {
     // Also remove any lingering authorizations from this user
     authorizeService.removeGroupPolicies(context, item, e);
     // Remove the bundle rights
     List<Bundle> bundles = item.getBundles();
     for (Bundle bundle : bundles) {
       authorizeService.removeGroupPolicies(context, bundle, e);
       List<Bitstream> bitstreams = bundle.getBitstreams();
       for (Bitstream bitstream : bitstreams) {
         authorizeService.removeGroupPolicies(context, bitstream, e);
       }
     }
   }
 }
示例#12
0
  /**
   * Register the bitstream file into DSpace
   *
   * @param c
   * @param i
   * @param assetstore
   * @param bitstreamPath the full filepath expressed in the contents file
   * @param bundleName
   * @throws SQLException
   * @throws IOException
   * @throws AuthorizeException
   */
  private void registerBitstream(
      Context c, Item i, int assetstore, String bitstreamPath, String bundleName)
      throws SQLException, IOException, AuthorizeException {
    // TODO validate assetstore number
    // TODO make sure the bitstream is there

    Bitstream bs = null;
    String newBundleName = bundleName;

    if (bundleName == null) {
      // is it license.txt?
      if (bitstreamPath.endsWith("license.txt")) {
        newBundleName = "LICENSE";
      } else {
        // call it ORIGINAL
        newBundleName = "ORIGINAL";
      }
    }

    if (!isTest) {
      // find the bundle
      Bundle[] bundles = i.getBundles(newBundleName);
      Bundle targetBundle = null;

      if (bundles.length < 1) {
        // not found, create a new one
        targetBundle = i.createBundle(newBundleName);
      } else {
        // put bitstreams into first bundle
        targetBundle = bundles[0];
      }

      // now add the bitstream
      bs = targetBundle.registerBitstream(assetstore, bitstreamPath);

      // set the name to just the filename
      int iLastSlash = bitstreamPath.lastIndexOf('/');
      bs.setName(bitstreamPath.substring(iLastSlash + 1));

      // Identify the format
      // FIXME - guessing format guesses license.txt incorrectly as a text file format!
      BitstreamFormat bf = FormatIdentifier.guessFormat(c, bs);
      bs.setFormat(bf);

      bs.update();
    }
  }
 /**
  * Find the local Bitstream referenced in an <code>mdRef</code> element.
  *
  * @param mdref the METS mdRef element to locate the bitstream for.
  * @return bitstream or null if none found.
  */
 public Bitstream getBitstreamForMdRef(Element mdref)
     throws MetadataValidationException, IOException, SQLException, AuthorizeException {
   String path = METSManifest.getFileName(mdref);
   if (mdBundle == null)
     throw new MetadataValidationException(
         "Failed referencing mdRef element, because there were no metadata files.");
   return mdBundle.getBitstreamByName(path);
 }
  /**
   * Process Item, correcting CC-License if encountered.
   *
   * @param item
   * @throws SQLException
   * @throws AuthorizeException
   * @throws IOException
   */
  protected static void handleItem(Item item) throws SQLException, AuthorizeException, IOException {
    Bundle[] bundles = item.getBundles("CC-LICENSE");

    if (bundles == null || bundles.length == 0) return;

    Bundle bundle = bundles[0];

    Bitstream bitstream = bundle.getBitstreamByName("license_rdf");

    String license_rdf = new String(copy(bitstream));

    /* quickly fix xml by ripping out offensive parts */
    license_rdf = license_rdf.replaceFirst("<license", "");
    license_rdf = license_rdf.replaceFirst("</license>", "");

    StringWriter result = new StringWriter();

    try {
      templates
          .newTransformer()
          .transform(
              new StreamSource(new ByteArrayInputStream(license_rdf.getBytes())),
              new StreamResult(result));
    } catch (TransformerException e) {
      throw new RuntimeException(e.getMessage(), e);
    }

    StringBuffer buffer = result.getBuffer();

    Bitstream newBitstream =
        bundle.createBitstream(new ByteArrayInputStream(buffer.toString().getBytes()));

    newBitstream.setName(bitstream.getName());
    newBitstream.setDescription(bitstream.getDescription());
    newBitstream.setFormat(bitstream.getFormat());
    newBitstream.setSource(bitstream.getSource());
    newBitstream.setUserFormatDescription(bitstream.getUserFormatDescription());
    newBitstream.update();

    bundle.removeBitstream(bitstream);

    bundle.update();
  }
示例#15
0
 protected void removeUserItemPolicies(Context context, Item item, EPerson e)
     throws SQLException, AuthorizeException {
   if (e != null) {
     // Also remove any lingering authorizations from this user
     authorizeService.removeEPersonPolicies(context, item, e);
     // Remove the bundle rights
     List<Bundle> bundles = item.getBundles();
     for (Bundle bundle : bundles) {
       authorizeService.removeEPersonPolicies(context, bundle, e);
       List<Bitstream> bitstreams = bundle.getBitstreams();
       for (Bitstream bitstream : bitstreams) {
         authorizeService.removeEPersonPolicies(context, bitstream, e);
       }
     }
     // Ensure that the submitter always retains his resource policies
     if (e.getID().equals(item.getSubmitter().getID())) {
       grantSubmitterReadPolicies(context, item);
     }
   }
 }
  @Override
  public void unlink(Item item, Bundle bundle) throws AuthorizeException {
    if (!linked(item, bundle)) {
      return;
    }

    try {
      // Remove bundle mappings from DB
      DatabaseManager.updateQuery(
          context,
          "DELETE FROM item2bundle WHERE item_id= ? " + "AND bundle_id= ? ",
          item.getID(),
          bundle.getID());
    } catch (SQLException sqle) {
      throw new RuntimeException(sqle);
    }
  }
  @Override
  public List<Item> getParentItems(Bundle bundle) {
    try {
      // Get items
      TableRowIterator tri =
          DatabaseManager.queryTable(
              context,
              "item",
              "SELECT i.item_id FROM item i, item2bundle i2b "
                  + "WHERE i2b.item_id = i.item_id "
                  + "AND i2b.bundle_id = ? ",
              bundle.getID());

      return returnAsList(tri);
    } catch (SQLException sqle) {
      throw new RuntimeException(sqle);
    }
  }
  @Override
  public void link(Item item, Bundle bundle) throws AuthorizeException {
    if (linked(item, bundle)) {
      return;
    }

    try {
      TableRow row = DatabaseManager.create(context, "item2bundle");
      row.setColumn("item_id", item.getID());
      row.setColumn("bundle_id", bundle.getID());
      DatabaseManager.update(context, row);

      // If we're adding the Bundle to the Item, we bequeath our
      // policies unto it.
      AuthorizeManager.inheritPolicies(context, item, bundle);
    } catch (SQLException sqle) {
      throw new RuntimeException(sqle);
    }
  }
  @Override
  public boolean linked(Item item, Bundle bundle) {
    try {
      TableRowIterator tri =
          DatabaseManager.query(
              context,
              "SELECT id FROM item2bundle "
                  + " WHERE item_id="
                  + item.getID()
                  + " AND bundle_id="
                  + bundle.getID());

      boolean result = tri.hasNext();
      tri.close();

      return result;
    } catch (SQLException sqle) {
      throw new RuntimeException(sqle);
    }
  }
示例#20
0
  /** Add rights information. This attaches an href to the URL of the item's licence file */
  protected void addRights() throws DSpaceSWORDException {
    try {
      // work our way up to the item
      List<Bundle> bundle2bitstreams = this.bitstream.getBundles();
      if (bundle2bitstreams.isEmpty()) {
        log.error("Found orphaned bitstream: " + bitstream.getID());
        throw new DSpaceSWORDException("Orphaned bitstream discovered");
      }
      Bundle bundle = bundle2bitstreams.get(0);
      List<Item> items = bundle.getItems();
      if (items.isEmpty()) {
        log.error("Found orphaned bundle: " + bundle.getID());
        throw new DSpaceSWORDException("Orphaned bundle discovered");
      }
      Item item = items.get(0);

      // now get the licence out of the item
      SWORDUrlManager urlManager = swordService.getUrlManager();
      StringBuilder rightsString = new StringBuilder();
      List<Bundle> lbundles = item.getBundles();
      for (Bundle lbundle : lbundles) {
        if (!Constants.LICENSE_BUNDLE_NAME.equals(lbundle.getName())) {
          // skip non-license bundles
          continue;
        }
        List<Bitstream> bss = lbundle.getBitstreams();
        for (Bitstream bs : bss) {
          String url = urlManager.getBitstreamUrl(bs);
          rightsString.append(url).append(" ");
        }
      }

      Rights rights = new Rights();
      rights.setContent(rightsString.toString());
      rights.setType(ContentType.TEXT);
      entry.setRights(rights);
      log.debug("Added rights entry to entity");
    } catch (SQLException e) {
      log.error("caught exception: ", e);
      throw new DSpaceSWORDException(e);
    }
  }
示例#21
0
  /**
   * Perform a deposit, using the supplied SWORD Deposit object.
   *
   * @param deposit
   * @throws SWORDErrorException
   * @throws DSpaceSWORDException
   */
  public DepositResult doDeposit(Deposit deposit) throws SWORDErrorException, DSpaceSWORDException {
    // get the things out of the service that we need
    Context context = swordService.getContext();
    SWORDConfiguration swordConfig = swordService.getSwordConfig();
    SWORDUrlManager urlManager = swordService.getUrlManager();

    // FIXME: the spec is unclear what to do in this situation.  I'm going
    // the throw a 415 (ERROR_CONTENT) until further notice
    //
    // determine if this is an acceptable file format
    if (!swordConfig.isAcceptableContentType(context, deposit.getContentType(), collection)) {
      log.error(
          "Unacceptable content type detected: "
              + deposit.getContentType()
              + " for collection "
              + collection.getID());
      throw new SWORDErrorException(
          ErrorCodes.ERROR_CONTENT,
          "Unacceptable content type in deposit request: " + deposit.getContentType());
    }

    // determine if this is an acceptable packaging type for the deposit
    // if not, we throw a 415 HTTP error (Unsupported Media Type, ERROR_CONTENT)
    if (!swordConfig.isSupportedMediaType(deposit.getPackaging(), this.collection)) {
      log.error(
          "Unacceptable packaging type detected: "
              + deposit.getPackaging()
              + "for collection"
              + collection.getID());
      throw new SWORDErrorException(
          ErrorCodes.ERROR_CONTENT,
          "Unacceptable packaging type in deposit request: " + deposit.getPackaging());
    }

    // Obtain the relevant ingester from the factory
    SWORDIngester si = SWORDIngesterFactory.getInstance(context, deposit, collection);
    swordService.message("Loaded ingester: " + si.getClass().getName());

    // do the deposit
    DepositResult result = si.ingest(swordService, deposit, collection);
    swordService.message("Archive ingest completed successfully");

    // if there's an item availalble, and we want to keep the original
    // then do that
    try {
      if (swordConfig.isKeepOriginal()) {
        swordService.message(
            "DSpace will store an original copy of the deposit, "
                + "as well as ingesting the item into the archive");

        // in order to be allowed to add the file back to the item, we need to ignore authorisations
        // for a moment
        boolean ignoreAuth = context.ignoreAuthorization();
        context.setIgnoreAuthorization(true);

        String bundleName = ConfigurationManager.getProperty("sword-server", "bundle.name");
        if (bundleName == null || "".equals(bundleName)) {
          bundleName = "SWORD";
        }
        Item item = result.getItem();
        Bundle[] bundles = item.getBundles(bundleName);
        Bundle swordBundle = null;
        if (bundles.length > 0) {
          swordBundle = bundles[0];
        }
        if (swordBundle == null) {
          swordBundle = item.createBundle(bundleName);
        }

        String fn = swordService.getFilename(context, deposit, true);

        Bitstream bitstream;
        FileInputStream fis = null;
        try {
          fis = new FileInputStream(deposit.getFile());
          bitstream = swordBundle.createBitstream(fis);
        } finally {
          if (fis != null) {
            fis.close();
          }
        }

        bitstream.setName(fn);
        bitstream.setDescription("SWORD deposit package");

        BitstreamFormat bf = BitstreamFormat.findByMIMEType(context, deposit.getContentType());
        if (bf != null) {
          bitstream.setFormat(bf);
        }

        bitstream.update();

        swordBundle.update();
        item.update();

        swordService.message(
            "Original package stored as " + fn + ", in item bundle " + swordBundle);

        // now reset the context ignore authorisation
        context.setIgnoreAuthorization(ignoreAuth);

        // set the media link for the created item
        result.setMediaLink(urlManager.getMediaLink(bitstream));
      } else {
        // set the vanilla media link, which doesn't resolve to anything
        result.setMediaLink(urlManager.getBaseMediaLinkUrl());
      }
    } catch (SQLException e) {
      log.error("caught exception: ", e);
      throw new DSpaceSWORDException(e);
    } catch (AuthorizeException e) {
      log.error("caught exception: ", e);
      throw new DSpaceSWORDException(e);
    } catch (FileNotFoundException e) {
      log.error("caught exception: ", e);
      throw new DSpaceSWORDException(e);
    } catch (IOException e) {
      log.error("caught exception: ", e);
      throw new DSpaceSWORDException(e);
    }

    return result;
  }
示例#22
0
  /**
   * perform the ingest using the given deposit object onto the specified target dspace object,
   * using the sword service implementation
   *
   * @param service
   * @param deposit
   * @param target
   * @return
   * @throws DSpaceSWORDException
   * @throws SWORDErrorException
   */
  public DepositResult ingest(SWORDService service, Deposit deposit, DSpaceObject target)
      throws DSpaceSWORDException, SWORDErrorException {
    try {
      if (!(target instanceof Item)) {
        throw new DSpaceSWORDException(
            "SimpleFileIngester can only be loaded for deposit onto DSpace Items");
      }
      Item item = (Item) target;

      // now set the sword service
      SWORDService swordService = service;

      // get the things out of the service that we need
      Context context = swordService.getContext();
      SWORDUrlManager urlManager = swordService.getUrlManager();

      Bundle[] bundles = item.getBundles("ORIGINAL");
      Bundle original;
      if (bundles.length > 0) {
        original = bundles[0];
      } else {
        original = item.createBundle("ORIGINAL");
      }

      Bitstream bs;
      FileInputStream fis = null;

      try {
        fis = new FileInputStream(deposit.getFile());
        bs = original.createBitstream(fis);
      } finally {
        if (fis != null) {
          fis.close();
        }
      }

      String fn = swordService.getFilename(context, deposit, false);
      bs.setName(fn);

      swordService.message("File created in item with filename " + fn);

      BitstreamFormat bf = BitstreamFormat.findByMIMEType(context, deposit.getContentType());
      if (bf != null) {
        bs.setFormat(bf);
      }

      // to do the updates, we need to ignore authorisation in the context
      boolean ignoreAuth = context.ignoreAuthorization();
      context.setIgnoreAuthorization(true);

      bs.update();
      original.update();
      item.update();

      // reset the ignore authorisation
      context.setIgnoreAuthorization(ignoreAuth);

      DepositResult result = new DepositResult();
      result.setHandle(urlManager.getBitstreamUrl(bs));
      result.setTreatment(this.getTreatment());
      result.setBitstream(bs);

      return result;
    } catch (SQLException e) {
      throw new DSpaceSWORDException(e);
    } catch (AuthorizeException e) {
      throw new DSpaceSWORDException(e);
    } catch (IOException e) {
      throw new DSpaceSWORDException(e);
    }
  }
示例#23
0
  public static void main(String[] argv) throws Exception {
    Options options = new Options();
    options.addOption("c", "collection", true, "destination collection(s) Handle (repeatable)");
    options.addOption("e", "eperson", true, "email address of eperson doing importing");
    options.addOption(
        "w",
        "install",
        false,
        "disable workflow; install immediately without going through collection's workflow");
    options.addOption("t", "type", true, "package type or MIMEtype");
    options.addOption(
        "o", "option", true, "Packager option to pass to plugin, \"name=value\" (repeatable)");
    options.addOption(
        "d", "disseminate", false, "Disseminate package (output); default is to submit.");
    options.addOption("i", "item", true, "Handle of item to disseminate.");
    options.addOption("h", "help", false, "help");

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

    String sourceFile = null;
    String eperson = null;
    String[] collections = null;
    boolean useWorkflow = true;
    String packageType = null;
    boolean submit = true;
    String itemHandle = null;
    PackageParameters pkgParams = new PackageParameters();

    if (line.hasOption('h')) {
      HelpFormatter myhelp = new HelpFormatter();
      myhelp.printHelp("Packager  [options]  package-file|-\n", options);
      System.out.println("\nAvailable Submission Package (SIP) types:");
      String pn[] = PluginManager.getAllPluginNames(PackageIngester.class);
      for (int i = 0; i < pn.length; ++i) System.out.println("  " + pn[i]);
      System.out.println("\nAvailable Dissemination Package (DIP) types:");
      pn = PluginManager.getAllPluginNames(PackageDisseminator.class);
      for (int i = 0; i < pn.length; ++i) System.out.println("  " + pn[i]);
      System.exit(0);
    }
    if (line.hasOption('w')) useWorkflow = false;
    if (line.hasOption('e')) eperson = line.getOptionValue('e');
    if (line.hasOption('c')) collections = line.getOptionValues('c');
    if (line.hasOption('t')) packageType = line.getOptionValue('t');
    if (line.hasOption('i')) itemHandle = line.getOptionValue('i');
    String files[] = line.getArgs();
    if (files.length > 0) sourceFile = files[0];
    if (line.hasOption('d')) submit = false;
    if (line.hasOption('o')) {
      String popt[] = line.getOptionValues('o');
      for (int i = 0; i < popt.length; ++i) {
        String pair[] = popt[i].split("\\=", 2);
        if (pair.length == 2) pkgParams.addProperty(pair[0].trim(), pair[1].trim());
        else if (pair.length == 1) pkgParams.addProperty(pair[0].trim(), "");
        else System.err.println("Warning: Illegal package option format: \"" + popt[i] + "\"");
      }
    }

    // Sanity checks on arg list: required args
    if (sourceFile == null
        || eperson == null
        || packageType == null
        || (submit && collections == null)) {
      System.err.println("Error - missing a REQUIRED argument or option.\n");
      HelpFormatter myhelp = new HelpFormatter();
      myhelp.printHelp("PackageManager  [options]  package-file|-\n", options);
      System.exit(0);
    }

    // find the EPerson, assign to context
    Context context = new Context();
    EPerson myEPerson = null;
    myEPerson = EPerson.findByEmail(context, eperson);
    if (myEPerson == null) usageError("Error, eperson cannot be found: " + eperson);
    context.setCurrentUser(myEPerson);

    if (submit) {
      // make sure we have an input file

      // GWaller 11/1/10 Disable piping of input in - we need to archive the package so it is
      // simpler to assume a file stream
      //                 rather than save the System.in bytes and re-read.

      if (sourceFile.equals("-")) {
        usageError(
            "Error, input piping not allowed. Specify a file name of a physical file to read");
      }

      InputStream source = new FileInputStream(sourceFile);

      PackageIngester sip =
          (PackageIngester) PluginManager.getNamedPlugin(PackageIngester.class, packageType);
      if (sip == null) usageError("Error, Unknown package type: " + packageType);

      // find collections
      Collection[] mycollections = null;

      System.out.println("Destination collections:");

      // validate each collection arg to see if it's a real collection
      mycollections = new Collection[collections.length];
      for (int i = 0; i < collections.length; i++) {
        // sanity check: did handle resolve, and to a collection?
        DSpaceObject dso = HandleManager.resolveToObject(context, collections[i]);
        if (dso == null)
          throw new IllegalArgumentException(
              "Bad collection list -- "
                  + "Cannot resolve collection handle \""
                  + collections[i]
                  + "\"");
        else if (dso.getType() != Constants.COLLECTION)
          throw new IllegalArgumentException(
              "Bad collection list -- "
                  + "Object at handle \""
                  + collections[i]
                  + "\" is not a collection!");
        mycollections[i] = (Collection) dso;
        System.out.println(
            (i == 0 ? "  Owning " : "  ") + " Collection: " + mycollections[i].getMetadata("name"));
      }

      try {
        // GWaller 26/08/09 Support array of collections
        WorkspaceItem wi = sip.ingest(context, mycollections, source, pkgParams, null);

        // GWaller 11/1/10 IssueID #157 Archive the package
        InputStream sourceCopy = new FileInputStream(sourceFile);
        Bundle archivedBundle =
            BundleUtils.getBundleByName(wi.getItem(), Constants.ARCHIVED_CONTENT_PACKAGE_BUNDLE);
        Bitstream bs = archivedBundle.createBitstream(sourceCopy);
        bs.setName(new File(sourceFile).getName());
        bs.update();
        archivedBundle.update();

        if (useWorkflow) {
          String handle = null;

          // Check if workflow completes immediately, and
          // return Handle if so.
          WorkflowItem wfi = WorkflowManager.startWithoutNotify(context, wi);

          if (wfi.getState() == WorkflowManager.WFSTATE_ARCHIVE) {
            Item ni = wfi.getItem();
            handle = HandleManager.findHandle(context, ni);
          }
          if (handle == null)
            System.out.println("Created Workflow item, ID=" + String.valueOf(wfi.getID()));
          else System.out.println("Created and installed item, handle=" + handle);
        } else {
          InstallItem.installItem(context, wi);
          System.out.println(
              "Created and installed item, handle="
                  + HandleManager.findHandle(context, wi.getItem()));
        }
        context.complete();
        System.exit(0);
      } catch (Exception e) {
        // abort all operations
        context.abort();
        e.printStackTrace();
        System.out.println(e);
        System.exit(1);
      }
    } else {
      OutputStream dest =
          (sourceFile.equals("-"))
              ? (OutputStream) System.out
              : (OutputStream) (new FileOutputStream(sourceFile));

      PackageDisseminator dip =
          (PackageDisseminator)
              PluginManager.getNamedPlugin(PackageDisseminator.class, packageType);
      if (dip == null) usageError("Error, Unknown package type: " + packageType);

      DSpaceObject dso = HandleManager.resolveToObject(context, itemHandle);
      if (dso == null)
        throw new IllegalArgumentException(
            "Bad Item handle -- " + "Cannot resolve handle \"" + itemHandle);
      dip.disseminate(context, dso, pkgParams, dest);
    }
  }
  public void addBody(Body body) throws SQLException, WingException {
    // Get our parameters and state
    int itemID = parameters.getParameterAsInteger("itemID", -1);
    Item item = Item.find(context, itemID);
    String baseURL = contextPath + "/admin/item?administrative-continue=" + knot.getId();

    // DIVISION: main div
    Division main =
        body.addInteractiveDivision(
            "edit-item-status",
            contextPath + "/admin/item",
            Division.METHOD_POST,
            "primary administrative item");
    main.setHead(T_option_head);

    // LIST: options
    List options = main.addList("options", List.TYPE_SIMPLE, "horizontal");
    options.addItem().addXref(baseURL + "&submit_status", T_option_status);
    options
        .addItem()
        .addHighlight("bold")
        .addXref(baseURL + "&submit_bitstreams", T_option_bitstreams);
    options.addItem().addXref(baseURL + "&submit_metadata", T_option_metadata);
    options.addItem().addXref(baseURL + "&view_item", T_option_view);

    // TABLE: Bitstream summary
    Table files = main.addTable("editItemBitstreams", 1, 1);

    files.setHead(T_head1);

    Row header = files.addRow(Row.ROLE_HEADER);
    header.addCellContent(T_column1);
    header.addCellContent(T_column2);
    header.addCellContent(T_column3);
    header.addCellContent(T_column4);
    header.addCellContent(T_column5);

    Bundle[] bundles = item.getBundles();

    for (Bundle bundle : bundles) {

      Cell bundleCell = files.addRow().addCell(1, 5);
      bundleCell.addContent(T_bundle_label.parameterize(bundle.getName()));

      Bitstream[] bitstreams = bundle.getBitstreams();

      for (Bitstream bitstream : bitstreams) {
        boolean primary = (bundle.getPrimaryBitstreamID() == bitstream.getID());
        String name = bitstream.getName();

        if (name != null && name.length() > 50) {
          // If the fiel name is too long the shorten it so that it will display nicely.
          String shortName = name.substring(0, 15);
          shortName += " ... ";
          shortName += name.substring(name.length() - 25, name.length());
          name = shortName;
        }

        String description = bitstream.getDescription();
        String format = null;
        BitstreamFormat bitstreamFormat = bitstream.getFormat();
        if (bitstreamFormat != null) format = bitstreamFormat.getShortDescription();
        String editURL =
            contextPath
                + "/admin/item?administrative-continue="
                + knot.getId()
                + "&bitstreamID="
                + bitstream.getID()
                + "&submit_edit";
        String viewURL =
            contextPath + "/bitstream/id/" + bitstream.getID() + "/" + bitstream.getName();

        Row row = files.addRow();
        CheckBox remove = row.addCell().addCheckBox("remove");
        remove.setLabel("remove");
        remove.addOption(bundle.getID() + "/" + bitstream.getID());
        if (!AuthorizeManager.authorizeActionBoolean(context, item, Constants.REMOVE)) {
          remove.setDisabled();
        }

        if (AuthorizeManager.authorizeActionBoolean(context, bitstream, Constants.WRITE)) {
          // The user can edit the bitstream give them a link.
          Cell cell = row.addCell();
          cell.addXref(editURL, name);
          if (primary) cell.addXref(editURL, T_primary_label);

          row.addCell().addXref(editURL, description);
          row.addCell().addXref(editURL, format);
        } else {
          // The user can't edit the bitstream just show them it.
          Cell cell = row.addCell();
          cell.addContent(name);
          if (primary) cell.addContent(T_primary_label);

          row.addCell().addContent(description);
          row.addCell().addContent(format);
        }

        Highlight highlight = row.addCell().addHighlight("fade");
        highlight.addContent("[");
        highlight.addXref(viewURL, T_view_link);
        highlight.addContent("]");
      }
    }

    if (AuthorizeManager.authorizeActionBoolean(context, item, Constants.ADD)) {
      Cell cell = files.addRow().addCell(1, 5);
      cell.addXref(
          contextPath + "/admin/item?administrative-continue=" + knot.getId() + "&submit_add",
          T_submit_add);
    } else {
      Cell cell = files.addRow().addCell(1, 5);
      cell.addHighlight("fade").addContent(T_no_upload);
    }

    // PARA: actions
    Para actions = main.addPara("editItemActionsP", "editItemActionsP");
    if (AuthorizeManager.authorizeActionBoolean(context, item, Constants.REMOVE))
      actions.addButton("submit_delete").setValue(T_submit_delete);
    else {
      Button button = actions.addButton("submit_delete");
      button.setValue(T_submit_delete);
      button.setDisabled();

      main.addPara().addHighlight("fade").addContent(T_no_remove);
    }
    actions.addButton("submit_return").setValue(T_submit_return);

    main.addHidden("administrative-continue").setValue(knot.getId());
  }
  /**
   * Create a new DSpace item out of a METS content package. All contents are dictated by the METS
   * manifest. Package is a ZIP archive, all files relative to top level and the manifest (as per
   * spec) in mets.xml.
   *
   * @param context - DSpace context.
   * @param collection - collection under which to create new item.
   * @param pkg - input stream containing package to ingest.
   * @param license - may be null, which takes default license.
   * @return workspace item created by ingest.
   * @throws PackageValidationException if package is unacceptable or there is a fatal error turning
   *     it into an Item.
   */
  public WorkspaceItem ingest(
      Context context,
      Collection collection,
      InputStream pkg,
      PackageParameters params,
      String license)
      throws PackageValidationException, CrosswalkException, AuthorizeException, SQLException,
          IOException {
    BitstreamDAO bsDAO = BitstreamDAOFactory.getInstance(context);
    BitstreamFormatDAO bfDAO = BitstreamFormatDAOFactory.getInstance(context);
    BundleDAO bundleDAO = BundleDAOFactory.getInstance(context);
    WorkspaceItemDAO wsiDAO = WorkspaceItemDAOFactory.getInstance(context);

    ZipInputStream zip = new ZipInputStream(pkg);
    HashMap fileIdToBitstream = new HashMap();
    WorkspaceItem wi = null;
    boolean success = false;
    HashSet packageFiles = new HashSet();

    boolean validate = params.getBooleanProperty("validate", true);

    try {
      /* 1. Read all the files in the Zip into bitstreams first,
       *  because we only get to take one pass through a Zip input
       *  stream.  Give them temporary bitstream names corresponding
       *  to the same names they had in the Zip, since those MUST
       *  match the URL references in <Flocat> and <mdRef> elements.
       */
      METSManifest manifest = null;
      wi = wsiDAO.create(collection, false);
      Item item = wi.getItem();
      Bundle contentBundle = item.createBundle(Constants.CONTENT_BUNDLE_NAME);
      Bundle mdBundle = null;
      ZipEntry ze;
      while ((ze = zip.getNextEntry()) != null) {
        if (ze.isDirectory()) continue;
        Bitstream bs = null;
        String fname = ze.getName();
        if (fname.equals(MANIFEST_FILE)) {
          if (preserveManifest) {
            mdBundle = item.createBundle(Constants.METADATA_BUNDLE_NAME);
            bs = mdBundle.createBitstream(new PackageUtils.UnclosableInputStream(zip));
            bs.setName(fname);
            bs.setSource(fname);

            // Get magic bitstream format to identify manifest.
            BitstreamFormat manifestFormat = null;
            manifestFormat =
                PackageUtils.findOrCreateBitstreamFormat(
                    context,
                    MANIFEST_BITSTREAM_FORMAT,
                    "application/xml",
                    MANIFEST_BITSTREAM_FORMAT + " package manifest");
            bs.setFormat(manifestFormat);

            manifest = METSManifest.create(bs.retrieve(), validate);
          } else {
            manifest = METSManifest.create(new PackageUtils.UnclosableInputStream(zip), validate);
            continue;
          }
        } else {
          bs = contentBundle.createBitstream(new PackageUtils.UnclosableInputStream(zip));
          bs.setSource(fname);
          bs.setName(fname);
        }
        packageFiles.add(fname);
        bs.setSource(fname);
        bsDAO.update(bs);
      }
      zip.close();

      if (manifest == null)
        throw new PackageValidationException(
            "No METS Manifest found (filename=" + MANIFEST_FILE + ").  Package is unacceptable.");

      // initial sanity checks on manifest (in subclass)
      checkManifest(manifest);

      /* 2. Grovel a file list out of METS Manifest and compare
       *  it to the files in package, as an integrity test.
       */
      List manifestContentFiles = manifest.getContentFiles();

      // Compare manifest files with the ones found in package:
      //  a. Start with content files (mentioned in <fileGrp>s)
      HashSet missingFiles = new HashSet();
      for (Iterator mi = manifestContentFiles.iterator(); mi.hasNext(); ) {
        // First locate corresponding Bitstream and make
        // map of Bitstream to <file> ID.
        Element mfile = (Element) mi.next();
        String mfileId = mfile.getAttributeValue("ID");
        if (mfileId == null)
          throw new PackageValidationException(
              "Invalid METS Manifest: file element without ID attribute.");
        String path = METSManifest.getFileName(mfile);
        Bitstream bs = contentBundle.getBitstreamByName(path);
        if (bs == null) {
          log.warn(
              "Cannot find bitstream for filename=\""
                  + path
                  + "\", skipping it..may cause problems later.");
          missingFiles.add(path);
        } else {
          fileIdToBitstream.put(mfileId, bs);

          // Now that we're done using Name to match to <file>,
          // set default bitstream Name to last path element;
          // Zip entries all have '/' pathname separators
          // NOTE: set default here, hopefully crosswalk of
          // a bitstream techMD section will override it.
          String fname = bs.getName();
          int lastSlash = fname.lastIndexOf('/');
          if (lastSlash >= 0 && lastSlash + 1 < fname.length())
            bs.setName(fname.substring(lastSlash + 1));

          // Set Default bitstream format:
          //  1. attempt to guess from MIME type
          //  2. if that fails, guess from "name" extension.
          String mimeType = mfile.getAttributeValue("MIMETYPE");
          BitstreamFormat bf = (mimeType == null) ? null : bfDAO.retrieveByMimeType(mimeType);
          if (bf == null) bf = FormatIdentifier.guessFormat(context, bs);
          bs.setFormat(bf);

          // if this bitstream belongs in another Bundle, move it:
          String bundleName = manifest.getBundleName(mfile);
          if (!bundleName.equals(Constants.CONTENT_BUNDLE_NAME)) {
            Bundle bn;
            Bundle bns[] = item.getBundles(bundleName);
            if (bns != null && bns.length > 0) bn = bns[0];
            else bn = item.createBundle(bundleName);
            bn.addBitstream(bs);
            contentBundle.removeBitstream(bs);
          }

          // finally, build compare lists by deleting matches.
          if (packageFiles.contains(path)) packageFiles.remove(path);
          else missingFiles.add(path);
        }
      }

      //  b. Process files mentioned in <mdRef>s - check and move
      //     to METADATA bundle.
      for (Iterator mi = manifest.getMdFiles().iterator(); mi.hasNext(); ) {
        Element mdref = (Element) mi.next();
        String path = METSManifest.getFileName(mdref);

        // finally, build compare lists by deleting matches.
        if (packageFiles.contains(path)) packageFiles.remove(path);
        else missingFiles.add(path);

        // if there is a bitstream with that name in Content, move
        // it to the Metadata bundle:
        Bitstream mdbs = contentBundle.getBitstreamByName(path);
        if (mdbs != null) {
          if (mdBundle == null) mdBundle = item.createBundle(Constants.METADATA_BUNDLE_NAME);
          mdBundle.addBitstream(mdbs);
          contentBundle.removeBitstream(mdbs);
        }
      }

      // KLUDGE: make sure Manifest file doesn't get flagged as missing
      // or extra, since it won't be mentioned in the manifest.
      if (packageFiles.contains(MANIFEST_FILE)) packageFiles.remove(MANIFEST_FILE);

      // Give subclass a chance to refine the lists of in-package
      // and missing files, delete extraneous files, etc.
      checkPackageFiles(packageFiles, missingFiles, manifest);

      // Any discrepency in file lists is a fatal error:
      if (!(packageFiles.isEmpty() && missingFiles.isEmpty())) {
        StringBuffer msg =
            new StringBuffer("Package is unacceptable: contents do not match manifest.");
        if (!missingFiles.isEmpty()) {
          msg.append("\nPackage is missing these files listed in Manifest:");
          for (Iterator mi = missingFiles.iterator(); mi.hasNext(); )
            msg.append("\n\t" + (String) mi.next());
        }
        if (!packageFiles.isEmpty()) {
          msg.append("\nPackage contains extra files NOT in manifest:");
          for (Iterator mi = packageFiles.iterator(); mi.hasNext(); )
            msg.append("\n\t" + (String) mi.next());
        }
        throw new PackageValidationException(msg.toString());
      }

      /* 3. crosswalk the metadata
       */
      // get mdref'd streams from "callback" object.
      MdrefManager callback = new MdrefManager(mdBundle);

      chooseItemDmd(context, item, manifest, callback, manifest.getItemDmds());

      // crosswalk content bitstreams too.
      for (Iterator ei = fileIdToBitstream.entrySet().iterator(); ei.hasNext(); ) {
        Map.Entry ee = (Map.Entry) ei.next();
        manifest.crosswalkBitstream(
            context, (Bitstream) ee.getValue(), (String) ee.getKey(), callback);
      }

      // Take a second pass over files to correct names of derived files
      // (e.g. thumbnails, extracted text) to what DSpace expects:
      for (Iterator mi = manifestContentFiles.iterator(); mi.hasNext(); ) {
        Element mfile = (Element) mi.next();
        String bundleName = manifest.getBundleName(mfile);
        if (!bundleName.equals(Constants.CONTENT_BUNDLE_NAME)) {
          Element origFile = manifest.getOriginalFile(mfile);
          if (origFile != null) {
            String ofileId = origFile.getAttributeValue("ID");
            Bitstream obs = (Bitstream) fileIdToBitstream.get(ofileId);
            String newName = makeDerivedFilename(bundleName, obs.getName());
            if (newName != null) {
              String mfileId = mfile.getAttributeValue("ID");
              Bitstream bs = (Bitstream) fileIdToBitstream.get(mfileId);
              bs.setName(newName);
              bsDAO.update(bs);
            }
          }
        }
      }

      // Sanity-check the resulting metadata on the Item:
      PackageUtils.checkMetadata(item);

      /* 4. Set primary bitstream; same Bundle
       */
      Element pbsFile = manifest.getPrimaryBitstream();
      if (pbsFile != null) {
        Bitstream pbs = (Bitstream) fileIdToBitstream.get(pbsFile.getAttributeValue("ID"));
        if (pbs == null)
          log.error(
              "Got Primary Bitstream file ID="
                  + pbsFile.getAttributeValue("ID")
                  + ", but found no corresponding bitstream.");
        else {
          List<Bundle> bn = bundleDAO.getBundles(pbs);
          if (bn.size() > 0) bn.get(0).setPrimaryBitstreamID(pbs.getID());
          else log.error("Sanity check, got primary bitstream without any parent bundle.");
        }
      }

      // have subclass manage license since it may be extra package file.
      addLicense(context, collection, item, manifest, callback, license);

      // subclass hook for final checks and rearrangements
      finishItem(context, item);

      // commit any changes to bundles
      Bundle allBn[] = item.getBundles();
      for (int i = 0; i < allBn.length; ++i) {
        bundleDAO.update(allBn[i]);
      }

      wsiDAO.update(wi);
      success = true;
      log.info(
          LogManager.getHeader(
              context,
              "ingest",
              "Created new Item, db ID="
                  + String.valueOf(item.getID())
                  + ", WorkspaceItem ID="
                  + String.valueOf(wi.getID())));
      return wi;
    } catch (SQLException se) {
      // disable attempt to delete the workspace object, since
      // database may have suffered a fatal error and the
      // transaction rollback will get rid of it anyway.
      wi = null;

      // Pass this exception on to the next handler.
      throw se;
    } finally {
      // kill item (which also deletes bundles, bitstreams) if ingest fails
      if (!success && wi != null) wsiDAO.deleteAll(wi.getID());
    }
  }
示例#26
0
  /**
   * Create new Item out of the ingested package, in the indicated collection. It creates a
   * workspace item, which the application can then install if it chooses to bypass Workflow.
   *
   * <p>This is a VERY crude import of a single Adobe PDF (Portable Document Format) file, using the
   * document's embedded metadata for package metadata. If the PDF file hasn't got the minimal
   * metadata available, it is rejected.
   *
   * <p>
   *
   * @param context DSpace context.
   * @param collection collection under which to create new item.
   * @param pkg input stream containing package to ingest.
   * @param params package parameters (none recognized)
   * @param license may be null, which takes default license.
   * @return workspace item created by ingest.
   * @throws PackageException if package is unacceptable or there is a fatal error turning it into
   *     an Item.
   */
  public WorkspaceItem ingest(
      Context context,
      Collection collection,
      InputStream pkg,
      PackageParameters params,
      String license)
      throws PackageValidationException, CrosswalkException, AuthorizeException, SQLException,
          IOException {
    InputStream bis = null;
    COSDocument cos = null;
    boolean success = false;
    Bundle original = null;
    Bitstream bs = null;
    WorkspaceItem wi = null;

    /**
     * XXX comment out for now // XXX for debugging of parameter handling if (params != null) {
     * Enumeration pe = params.propertyNames(); while (pe.hasMoreElements()) { String name =
     * (String)pe.nextElement(); String v[] = params.getProperties(name); StringBuffer msg = new
     * StringBuffer("PackageParam: "); msg.append(name).append(" = "); for (int i = 0; i < v.length;
     * ++i) { if (i > 0) msg.append(", "); msg.append(v[i]); } log.debug(msg); } }
     */
    try {
      // Save the PDF in a bitstream first, since the parser
      // has to read it as well, and we cannot "rewind" it after that.
      wi = WorkspaceItem.create(context, collection, false);
      Item myitem = wi.getItem();
      original = myitem.createBundle("ORIGINAL");
      bs = original.createBitstream(pkg);
      pkg.close();
      bs.setName("package.pdf");
      setFormatToMIMEType(context, bs, "application/pdf");
      bs.update();
      log.debug("Created bitstream ID=" + String.valueOf(bs.getID()) + ", parsing...");

      crosswalkPDF(context, myitem, bs.retrieve());

      wi.update();
      context.commit();
      success = true;
      log.info(
          LogManager.getHeader(
              context,
              "ingest",
              "Created new Item, db ID="
                  + String.valueOf(myitem.getID())
                  + ", WorkspaceItem ID="
                  + String.valueOf(wi.getID())));
      return wi;
    } finally {
      try {
        // Close bitstream input stream and PDF file.
        if (bis != null) bis.close();
        if (cos != null) cos.close();
      } catch (IOException ie) {
      }

      // get rid of bitstream and item if ingest fails
      if (!success) {
        if (original != null && bs != null) original.removeBitstream(bs);
        if (wi != null) wi.deleteAll();
      }
      context.commit();
    }
  }