public void processDSpaceObject(
      Context context,
      HttpServletRequest request,
      HttpServletResponse response,
      DSpaceObject dso,
      String extraPathInfo)
      throws ServletException, IOException, SQLException, AuthorizeException {
    // OK, we have a valid URI. What is it?
    if (dso.getType() == Constants.BITSTREAM) {
      // FIXME: Check for if-modified-since header
      Bitstream bitstream = (Bitstream) dso;

      log.info(
          LogManager.getHeader(context, "view_bitstream", "bitstream_id=" + bitstream.getID()));

      // Pipe the bits
      //            InputStream is = bitstream.retrieve();
      InputStream is = BitstreamStorageManager.retrieve(context, bitstream);

      // Set the response MIME type
      response.setContentType(bitstream.getFormat().getMIMEType());

      response.setHeader("Content-Length", String.valueOf(bitstream.getSize()));
      response.setHeader("Content-disposition", "attachment; filename=" + bitstream.getName());

      Utils.bufferedCopy(is, response.getOutputStream());
      is.close();
      response.getOutputStream().flush();
    } else if (dso.getType() == Constants.ITEM) {
      Item item = (Item) dso;

      response.setDateHeader("Last-Modified", item.getLastModified().getTime());

      // Check for if-modified-since header
      long modSince = request.getDateHeader("If-Modified-Since");

      if (modSince != -1 && item.getLastModified().getTime() < modSince) {
        // Item has not been modified since requested date,
        // hence bitstream has not; return 304
        response.setStatus(HttpServletResponse.SC_NOT_MODIFIED);
      } else {
        // Display the item page
        displayItem(context, request, response, item);
      }
    } else if (dso.getType() == Constants.COLLECTION) {
      Collection c = (Collection) dso;

      // Store collection location in request
      request.setAttribute("dspace.collection", c);

      /*
       * Find the "parent" community the collection, mainly for
       * "breadcrumbs" FIXME: At the moment, just grab the first community
       * the collection is in. This should probably be more context
       * sensitive when we have multiple inclusion.
       */
      Community[] parents = (Community[]) c.getCommunities().toArray();
      request.setAttribute("dspace.community", parents[0]);

      /*
       * Find all the "parent" communities for the collection for
       * "breadcrumbs"
       */
      request.setAttribute("dspace.communities", getParents(parents[0], true));

      // home page, or forward to another page?
      if ((extraPathInfo == null) || (extraPathInfo.equals("/"))) {
        collectionHome(context, request, response, parents[0], c);
      } else {
        // Forward to another servlet
        request.getRequestDispatcher(extraPathInfo).forward(request, response);
      }
    } else if (dso.getType() == Constants.COMMUNITY) {
      Community c = (Community) dso;

      // Store collection location in request
      request.setAttribute("dspace.community", c);

      /*
       * Find all the "parent" communities for the community
       */
      request.setAttribute("dspace.communities", getParents(c, false));

      // home page, or forward to another page?
      if ((extraPathInfo == null) || (extraPathInfo.equals("/"))) {
        communityHome(context, request, response, c);
      } else {
        // Forward to another servlet
        request.getRequestDispatcher(extraPathInfo).forward(request, response);
      }
    } else {
      // Shouldn't happen. Log and treat as invalid ID
      log.info(
          LogManager.getHeader(
              context,
              "URI not an item, collection or community",
              "identifier=" + dso.getIdentifier().toString()));
      JSPManager.showInvalidIDError(request, response, request.getPathInfo(), -1);

      return;
    }
  }
Beispiel #2
0
  protected void doDSGet(Context context, HttpServletRequest request, HttpServletResponse response)
      throws ServletException, IOException, SQLException, AuthorizeException {
    includeAll = ConfigurationManager.getBooleanProperty("harvest.includerestricted.rss", true);
    String path = request.getPathInfo();
    String feedType = null;
    String handle = null;

    // build label map from localized Messages resource bundle
    Locale locale = request.getLocale();
    ResourceBundle msgs = ResourceBundle.getBundle("Messages", locale);
    Map<String, String> labelMap = new HashMap<String, String>();
    labelMap.put(SyndicationFeed.MSG_UNTITLED, msgs.getString(clazz + ".notitle"));
    labelMap.put(SyndicationFeed.MSG_LOGO_TITLE, msgs.getString(clazz + ".logo.title"));
    labelMap.put(
        SyndicationFeed.MSG_FEED_DESCRIPTION, msgs.getString(clazz + ".general-feed.description"));
    labelMap.put(SyndicationFeed.MSG_UITYPE, SyndicationFeed.UITYPE_JSPUI);
    for (String selector : SyndicationFeed.getDescriptionSelectors()) {
      labelMap.put("metadata." + selector, msgs.getString(SyndicationFeed.MSG_METADATA + selector));
    }

    if (path != null) {
      // substring(1) is to remove initial '/'
      path = path.substring(1);
      int split = path.indexOf('/');
      if (split != -1) {
        feedType = path.substring(0, split);
        handle = path.substring(split + 1);
      }
    }

    DSpaceObject dso = null;

    // as long as this is not a site wide feed,
    // attempt to retrieve the Collection or Community object
    if (handle != null && !handle.equals(SITE_FEED_KEY)) {
      // Determine if handle is a valid reference
      dso = HandleManager.resolveToObject(context, handle);
      if (dso == null) {
        log.info(LogManager.getHeader(context, "invalid_handle", "path=" + path));
        JSPManager.showInvalidIDError(request, response, handle, -1);
        return;
      }
    }

    if (!enabled
        || (dso != null
            && (dso.getType() != Constants.COLLECTION && dso.getType() != Constants.COMMUNITY))) {
      log.info(LogManager.getHeader(context, "invalid_id", "path=" + path));
      JSPManager.showInvalidIDError(request, response, path, -1);
      return;
    }

    // Determine if requested format is supported
    if (feedType == null || !formats.contains(feedType)) {
      log.info(LogManager.getHeader(context, "invalid_syndformat", "path=" + path));
      JSPManager.showInvalidIDError(request, response, path, -1);
      return;
    }

    if (dso != null && dso.getType() == Constants.COLLECTION) {
      labelMap.put(
          SyndicationFeed.MSG_FEED_TITLE,
          MessageFormat.format(
              msgs.getString(clazz + ".feed.title"),
              msgs.getString(clazz + ".feed-type.collection"),
              dso.getMetadata("short_description")));
    } else if (dso != null && dso.getType() == Constants.COMMUNITY) {
      labelMap.put(
          SyndicationFeed.MSG_FEED_TITLE,
          MessageFormat.format(
              msgs.getString(clazz + ".feed.title"),
              msgs.getString(clazz + ".feed-type.community"),
              dso.getMetadata("short_description")));
    }

    // Lookup or generate the feed
    // Cache key is handle + locale
    String cacheKey = (handle == null ? "site" : handle) + "." + locale.toString();
    SyndicationFeed feed = null;
    if (feedCache != null) {
      CacheFeed cFeed = feedCache.get(cacheKey);
      if (cFeed != null) // cache hit, but...
      {
        // Is the feed current?
        boolean cacheFeedCurrent = false;
        if (cFeed.timeStamp + (cacheAge * HOUR_MSECS) < System.currentTimeMillis()) {
          cacheFeedCurrent = true;
        }
        // Not current, but have any items changed since feed was created/last checked?
        else if (!itemsChanged(context, dso, cFeed.timeStamp)) {
          // no items have changed, re-stamp feed and use it
          cFeed.timeStamp = System.currentTimeMillis();
          cacheFeedCurrent = true;
        }
        if (cacheFeedCurrent) {
          feed = cFeed.access();
        }
      }
    }

    // either not caching, not found in cache, or feed in cache not current
    if (feed == null) {
      feed = new SyndicationFeed(SyndicationFeed.UITYPE_JSPUI);
      feed.populate(request, dso, getItems(context, dso), labelMap);
      if (feedCache != null) {
        cache(cacheKey, new CacheFeed(feed));
      }
    }

    // set the feed to the requested type & return it
    try {
      feed.setType(feedType);
      response.setContentType("text/xml; charset=UTF-8");
      feed.output(response.getWriter());
    } catch (FeedException fex) {
      throw new IOException(fex.getMessage(), fex);
    }
  }
  protected void doDSGet(Context context, HttpServletRequest request, HttpServletResponse response)
      throws ServletException, IOException, SQLException, AuthorizeException {
    ExternalIdentifierDAO identifierDAO = ExternalIdentifierDAOFactory.getInstance(context);

    Item item = null;
    Bitstream bitstream = null;

    String idString = request.getPathInfo();
    String filenameNoPath = null;
    String fullpath = null;
    String uri = null;

    // Parse URL
    if (idString != null) {
      // Remove leading slash
      if (idString.startsWith("/")) {
        idString = idString.substring(1);
      }

      // Get uri and full file path
      int slashIndex = idString.indexOf('/');
      if (slashIndex != -1) {
        slashIndex = idString.indexOf('/', slashIndex + 1);
        if (slashIndex != -1) {
          uri = idString.substring(0, slashIndex);
          fullpath =
              URLDecoder.decode(idString.substring(slashIndex + 1), Constants.DEFAULT_ENCODING);

          // Get filename with no path
          slashIndex = fullpath.indexOf('/');
          if (slashIndex != -1) {
            String[] pathComponents = fullpath.split("/");
            if (pathComponents.length <= maxDepthGuess + 1) {
              filenameNoPath = pathComponents[pathComponents.length - 1];
            }
          }
        }
      }
    }

    if (uri != null && fullpath != null) {
      // Find the item
      try {
        /*
         * If the original item doesn't have a persistent identifier
         * yet (because it's in the workflow) what we actually have is
         * a URL of the form: db-id/1234 where 1234 is the database ID
         * of the item.
         *
         * FIXME: This first part could be totally omitted now that we
         * have the dsi:x/y format of identification.
         */
        if (uri.startsWith("db-id")) {
          String dbIDString = uri.substring(uri.indexOf('/') + 1);
          int dbID = Integer.parseInt(dbIDString);
          item = ItemDAOFactory.getInstance(context).retrieve(dbID);
        } else {
          ExternalIdentifier identifier = identifierDAO.retrieve(uri);
          ObjectIdentifier oi = identifier.getObjectIdentifier();
          item = (Item) oi.getObject(context);
        }
      } catch (NumberFormatException nfe) {
        // Invalid ID - this will be dealt with below
      }
    }

    if (item != null) {
      // Try to find bitstream with exactly matching name + path
      bitstream = getItemBitstreamByName(item, fullpath);

      if (bitstream == null && filenameNoPath != null) {
        // No match with the full path, but we can try again with
        // only the filename
        bitstream = getItemBitstreamByName(item, filenameNoPath);
      }
    }

    // Did we get a bitstream?
    if (bitstream != null) {
      log.info(
          LogManager.getHeader(
              context, "view_html", "uri=" + uri + ",bitstream_id=" + bitstream.getID()));

      // Set the response MIME type
      response.setContentType(bitstream.getFormat().getMIMEType());

      // Response length
      response.setHeader("Content-Length", String.valueOf(bitstream.getSize()));

      // Pipe the bits
      InputStream is = bitstream.retrieve();

      Utils.bufferedCopy(is, response.getOutputStream());
      is.close();
      response.getOutputStream().flush();
    } else {
      // No bitstream - we got an invalid ID
      log.info(LogManager.getHeader(context, "view_html", "invalid_bitstream_id=" + idString));

      JSPManager.showInvalidIDError(request, response, idString, Constants.BITSTREAM);
    }
  }
  protected void doDSGet(Context context, HttpServletRequest request, HttpServletResponse response)
      throws ServletException, IOException, SQLException, AuthorizeException {
    // We will resolve the HTTP request parameters into a scope
    BrowseScope scope = new BrowseScope(context);

    // Will need to know whether to highlight the "focus" point
    boolean highlight = false;

    // Build up log information
    String logInfo = "";

    // For browse by date, we'll need to work out the URL query string to
    // use when the user swaps the ordering, so that they stay at the same
    // point in the index
    String flipOrderingQuery = "";

    // Grab HTTP request parameters
    String focus = request.getParameter("focus");
    String startsWith = request.getParameter("starts_with");
    String top = request.getParameter("top");
    String bottom = request.getParameter("bottom");

    // The following three are specific to browsing items by date
    String month = request.getParameter("month");
    String year = request.getParameter("year");
    String order = request.getParameter("order");

    // For browse by date: oldest item first?
    boolean oldestFirst = false;

    if ((order != null) && order.equalsIgnoreCase("oldestfirst")) {
      oldestFirst = true;
    }

    if (browseDates
        && (year != null)
        && !year.equals("")
        && ((startsWith == null) || startsWith.equals(""))) {
      // We're browsing items by date, the user hasn't typed anything
      // into the "year" text box, and they've selected a year from
      // the drop-down list. From this we work out where to start
      // the browse.
      startsWith = year;

      if ((month != null) & !month.equals("-1")) {
        // They've selected a month as well
        if (month.length() == 1) {
          // Ensure double-digit month number
          month = "0" + month;
        }

        startsWith = year + "-" + month;
      }
    }

    // Set the scope according to the parameters passed in
    if (focus != null) {
      // ----------------------------------------------
      // Browse should start at a specified focus point
      // ----------------------------------------------
      if (browseAuthors || browseSubjects) {
        // For browsing authors, focus is just a text value
        scope.setFocus(focus);
      } else {
        // For browsing items by title or date, focus is a Handle
        Item item = (Item) HandleManager.resolveToObject(context, focus);

        if (item == null) {
          // Handle is invalid one. Show an error.
          JSPManager.showInvalidIDError(request, response, focus, Constants.ITEM);

          return;
        }

        scope.setFocus(item);
      }

      // Will need to highlight the focus
      highlight = true;

      logInfo = "focus=" + focus + ",";

      if (browseDates) {
        // if the date order is flipped, we'll keep the same focus
        flipOrderingQuery =
            "focus=" + URLEncoder.encode(focus, Constants.DEFAULT_ENCODING) + "&amp;";
      }
    } else if (startsWith != null) {
      // ----------------------------------------------
      // Start the browse using user-specified text
      // ----------------------------------------------
      if (browseDates) {
        // if the date order is flipped, we'll keep the same focus
        flipOrderingQuery =
            "starts_with=" + URLEncoder.encode(startsWith, Constants.DEFAULT_ENCODING) + "&amp;";

        /*
         * When the user is browsing with the most recent items first,
         * the browse code algorithm doesn't quite do what some people
         * might expect. For example, if in the index there are entries:
         *
         * Mar-2000 15-Feb-2000 6-Feb-2000 15-Jan-2000
         *
         * and the user has selected "Feb 2000" as the start point for
         * the browse, the browse algorithm will start at the first
         * point in that index *after* "Feb 2000". "Feb 2000" would
         * appear in the index above between 6-Feb-2000 and 15-Jan-2000.
         * So, the browse code in this case will start the browse at
         * "15-Jan-2000". This isn't really what users are likely to
         * want: They're more likely to want the browse to start at the
         * first Feb 2000 date, i.e. 15-Feb-2000. A similar scenario
         * occurs when the user enters just a year. Our quick hack to
         * produce this behaviour is to add "-32" to the startsWith
         * variable, when sorting with most recent items first. This
         * means the browse code starts at the topmost item in the index
         * that matches the user's input, rather than the point in the
         * index where the user's input would appear.
         */
        if (!oldestFirst) {
          startsWith = startsWith + "-32";
        }
      }

      scope.setFocus(startsWith);
      highlight = true;
      logInfo = "starts_with=" + startsWith + ",";
    } else if ((top != null) || (bottom != null)) {
      // ----------------------------------------------
      // Paginating: put specified entry at top or bottom
      // ----------------------------------------------
      // Use a single value and a boolean to simplify the code below
      String val = bottom;
      boolean isTop = false;

      if (top != null) {
        val = top;
        isTop = true;
      }

      if (browseAuthors || browseSubjects) {
        // Value will be a text value for author browse
        scope.setFocus(val);
      } else {
        // Value is Handle if we're browsing items by title or date
        Item item = (Item) HandleManager.resolveToObject(context, val);

        if (item == null) {
          // Handle is invalid one. Show an error.
          JSPManager.showInvalidIDError(request, response, focus, Constants.ITEM);

          return;
        }

        scope.setFocus(item);
      }

      // This entry appears at the top or bottom, and so needs to have
      // 0 or 20 entries shown before it
      scope.setNumberBefore(isTop ? 0 : 20);

      logInfo = (isTop ? "top" : "bottom") + "=" + val + ",";

      if (browseDates) {
        // If the date order is flipped, we'll flip the table upside
        // down - i.e. the top will become the bottom and the bottom
        // the top.
        if (top != null) {
          flipOrderingQuery =
              "bottom=" + URLEncoder.encode(top, Constants.DEFAULT_ENCODING) + "&amp;";
        } else {
          flipOrderingQuery =
              "top=" + URLEncoder.encode(bottom, Constants.DEFAULT_ENCODING) + "&amp;";
        }
      }
    }

    // ----------------------------------------------
    // If none of the above apply, no positioning parameters
    // set - use start of index
    // ----------------------------------------------
    // Are we in a community or collection?
    Community community = UIUtil.getCommunityLocation(request);
    Collection collection = UIUtil.getCollectionLocation(request);

    if (collection != null) {
      logInfo = logInfo + ",collection_id=" + collection.getID() + ",";
      scope.setScope(collection);
    } else if (community != null) {
      logInfo = logInfo + ",community_id=" + community.getID() + ",";
      scope.setScope(community);
    }

    BrowseInfo browseInfo;

    try {
      // Query the browse index
      if (browseAuthors) {
        browseInfo = Browse.getAuthors(scope);
      } else if (browseDates) {
        browseInfo = Browse.getItemsByDate(scope, oldestFirst);
      } else if (browseSubjects) {
        browseInfo = Browse.getSubjects(scope);
      } else {
        browseInfo = Browse.getItemsByTitle(scope);
      }
    } catch (SQLException sqle) {
      // An invalid scope was given
      JSPManager.showIntegrityError(request, response);
      return;
    }

    // Write log entry
    String what = "title";

    if (browseAuthors) {
      what = "author";
    } else if (browseSubjects) {
      what = "subject";
    } else if (browseDates) {
      what = "date";
    }

    log.info(
        LogManager.getHeader(
            context, "browse_" + what, logInfo + "results=" + browseInfo.getResultCount()));

    if (browseInfo.getResultCount() == 0) {
      // No results!
      request.setAttribute("community", community);
      request.setAttribute("collection", collection);

      JSPManager.showJSP(request, response, "/browse/no-results.jsp");
    } else {
      // Work out what the query strings will be for the previous
      // and next pages
      if (!browseInfo.isFirst()) {
        // Not the first page, so we'll need a "previous page" button
        // The top entry of the current page becomes the bottom
        // entry of the "previous page"
        String s;

        if (browseAuthors || browseSubjects) // aneesh
        {
          s = (browseInfo.getStringResults())[0];
        } else {
          Item firstItem = (browseInfo.getItemResults())[0];
          s = firstItem.getHandle();
        }

        if (browseDates && oldestFirst) {
          // For browsing by date, oldest first, we need
          // to add the ordering parameter
          request.setAttribute(
              "previous.query",
              "order=oldestfirst&amp;bottom=" + URLEncoder.encode(s, Constants.DEFAULT_ENCODING));
        } else {
          request.setAttribute(
              "previous.query", "bottom=" + URLEncoder.encode(s, Constants.DEFAULT_ENCODING));
        }
      }

      if (!browseInfo.isLast()) {
        // Not the last page, so we'll need a "next page" button
        // The bottom entry of the current page will be the top
        // entry in the next page
        String s;

        if (browseAuthors) {
          String[] authors = browseInfo.getStringResults();
          s = authors[authors.length - 1];
        } else if (browseSubjects) {
          String[] subjects = browseInfo.getStringResults();
          s = subjects[subjects.length - 1];
        } else {
          Item[] items = browseInfo.getItemResults();
          Item lastItem = items[items.length - 1];
          s = lastItem.getHandle();
        }

        if (browseDates && oldestFirst) {
          // For browsing by date, oldest first, we need
          // to add the ordering parameter
          request.setAttribute(
              "next.query",
              "order=oldestfirst&amp;top=" + URLEncoder.encode(s, Constants.DEFAULT_ENCODING));
        } else {
          request.setAttribute(
              "next.query", "top=" + URLEncoder.encode(s, Constants.DEFAULT_ENCODING));
        }
      }

      // Set appropriate attributes and forward to results page
      request.setAttribute("community", community);
      request.setAttribute("collection", collection);
      request.setAttribute("browse.info", browseInfo);
      request.setAttribute("highlight", new Boolean(highlight));

      if (browseAuthors) {
        JSPManager.showJSP(request, response, "/browse/authors.jsp");
      } else if (browseSubjects) {
        JSPManager.showJSP(request, response, "/browse/subjects.jsp");
      } else if (browseDates) {
        request.setAttribute("oldest.first", new Boolean(oldestFirst));
        request.setAttribute("flip.ordering.query", flipOrderingQuery);
        JSPManager.showJSP(request, response, "/browse/items-by-date.jsp");
      } else {
        JSPManager.showJSP(request, response, "/browse/items-by-title.jsp");
      }
    }
  }
  protected void doDSGet(Context context, HttpServletRequest request, HttpServletResponse response)
      throws ServletException, IOException, SQLException, AuthorizeException {
    ExternalIdentifierDAO identifierDAO = ExternalIdentifierDAOFactory.getInstance(context);

    // Obtain information from request
    String uri = request.getParameter("uri");
    ExternalIdentifier identifier = identifierDAO.retrieve(uri);
    ObjectIdentifier oi = identifier.getObjectIdentifier();

    // Lookup Item title & collection
    Item item = null;
    String link = "";
    String title = null;
    String collName = null;
    if (identifier != null) {
      item = (Item) oi.getObject(context);
      link = item.getIdentifier().getURL().toString();
      request.setAttribute("link", link);

      if (item != null) {
        DCValue[] titleDC = item.getDC("title", null, Item.ANY);
        if (titleDC != null || titleDC.length > 0) {
          title = titleDC[0].value;
        }
        Collection[] colls = item.getCollections();
        collName = colls[0].getMetadata("name");
      }
    } else {
      String path = request.getPathInfo();
      log.info(LogManager.getHeader(context, "invalid_id", "path=" + path));
      JSPManager.showInvalidIDError(request, response, path, -1);
      return;
    }
    if (title == null) {
      title = "";
    }
    if (collName == null) {
      collName = "";
    }
    request.setAttribute("suggest.title", title);

    // User email from context
    EPerson currentUser = context.getCurrentUser();
    String authEmail = null;
    String userName = null;

    if (currentUser != null) {
      authEmail = currentUser.getEmail();
      userName = currentUser.getFullName();
    }

    if (request.getParameter("submit") != null) {
      String recipAddr = request.getParameter("recip_email");
      // the only required field is recipient email address
      if (recipAddr == null || recipAddr.equals("")) {
        log.info(LogManager.getHeader(context, "show_suggest_form", "problem=true"));
        request.setAttribute("suggest.problem", new Boolean(true));
        JSPManager.showJSP(request, response, "/suggest/suggest.jsp");
        return;
      }
      String recipName = request.getParameter("recip_name");
      if (recipName == null || "".equals(recipName)) {
        try {
          recipName =
              I18nUtil.getMessage("org.dspace.app.webui.servlet.SuggestServlet.recipient", context);
        } catch (MissingResourceException e) {
          log.warn(
              LogManager.getHeader(
                  context,
                  "show_suggest_form",
                  "Missing Resource: org.dspace.app.webui.servlet.SuggestServlet.sender"));
          recipName = "colleague";
        }
      }
      String senderName = request.getParameter("sender_name");
      if (senderName == null || "".equals(senderName)) {
        // use userName if available
        if (userName != null) {
          senderName = userName;
        } else {
          try {
            senderName =
                I18nUtil.getMessage("org.dspace.app.webui.servlet.SuggestServlet.sender", context);
          } catch (MissingResourceException e) {
            log.warn(
                LogManager.getHeader(
                    context,
                    "show_suggest_form",
                    "Missing Resource: org.dspace.app.webui.servlet.SuggestServlet.sender"));
            senderName = "A DSpace User";
          }
        }
      }
      String senderAddr = request.getParameter("sender_email");
      if (senderAddr == null || "".equals(senderAddr)) {
        // use authEmail if available
        if (authEmail != null) {
          senderAddr = authEmail;
        }
      }
      String itemUri = identifier.getURI().toString();
      String message = request.getParameter("message");
      String siteName = ConfigurationManager.getProperty("dspace.name");

      // All data is there, send the email
      try {
        Email email =
            ConfigurationManager.getEmail(
                I18nUtil.getEmailFilename(context.getCurrentLocale(), "suggest"));
        email.addRecipient(recipAddr); // recipient address
        email.addArgument(recipName); // 1st arg - recipient name
        email.addArgument(senderName); // 2nd arg - sender name
        email.addArgument(siteName); // 3rd arg - repository name
        email.addArgument(title); // 4th arg - item title
        email.addArgument(itemUri); // 5th arg - item identifier URI
        email.addArgument(link); // 6th arg - item local URL
        email.addArgument(collName); // 7th arg - collection name
        email.addArgument(message); // 8th arg - user comments

        // Set sender's address as 'reply-to' address if supplied
        if (senderAddr != null && !"".equals(senderAddr)) {
          email.setReplyTo(senderAddr);
        }

        // Only actually send the email if feature is enabled
        if (ConfigurationManager.getBooleanProperty("webui.suggest.enable", false)) {
          email.send();
        } else {
          throw new MessagingException(
              "Suggest item email not sent - webui.suggest.enable = false");
        }

        log.info(LogManager.getHeader(context, "sent_suggest", "from=" + senderAddr));

        JSPManager.showJSP(request, response, "/suggest/suggest_ok.jsp");
      } catch (MessagingException me) {
        log.warn(LogManager.getHeader(context, "error_mailing_suggest", ""), me);
        JSPManager.showInternalError(request, response);
      }
    } else {
      // Display suggest form
      log.info(LogManager.getHeader(context, "show_suggest_form", "problem=false"));
      request.setAttribute("authenticated.email", authEmail);
      request.setAttribute("eperson.name", userName);
      JSPManager.showJSP(request, response, "/suggest/suggest.jsp"); // asd
    }
  }
  @Override
  protected void doDSGet(Context context, HttpServletRequest request, HttpServletResponse response)
      throws ServletException, IOException, SQLException, AuthorizeException {
    Item item = null;
    Bitstream bitstream = null;

    // Get the ID from the URL
    String idString = request.getPathInfo();
    String handle = "";
    String sequenceText = "";
    String filename = null;
    int sequenceID;

    // Parse 'handle' and 'sequence' (bitstream seq. number) out
    // of remaining URL path, which is typically of the format:
    // {handle}/{sequence}/{bitstream-name}
    // But since the bitstream name MAY have any number of "/"s in
    // it, and the handle is guaranteed to have one slash, we
    // scan from the start to pick out handle and sequence:

    // Remove leading slash if any:
    if (idString.startsWith("/")) {
      idString = idString.substring(1);
    }

    // skip first slash within handle
    int slashIndex = idString.indexOf('/');
    if (slashIndex != -1) {
      slashIndex = idString.indexOf('/', slashIndex + 1);
      if (slashIndex != -1) {
        handle = idString.substring(0, slashIndex);
        int slash2 = idString.indexOf('/', slashIndex + 1);
        if (slash2 != -1) {
          sequenceText = idString.substring(slashIndex + 1, slash2);
          filename = idString.substring(slash2 + 1);
        }
      }
    }

    try {
      sequenceID = Integer.parseInt(sequenceText);
    } catch (NumberFormatException nfe) {
      sequenceID = -1;
    }

    // Now try and retrieve the item
    DSpaceObject dso = HandleManager.resolveToObject(context, handle);

    // Make sure we have valid item and sequence number
    if (dso != null && dso.getType() == Constants.ITEM && sequenceID >= 0) {
      item = (Item) dso;

      if (item.isWithdrawn()) {
        log.info(
            LogManager.getHeader(
                context, "view_bitstream", "handle=" + handle + ",withdrawn=true"));
        JSPManager.showJSP(request, response, "/tombstone.jsp");
        return;
      }

      boolean found = false;

      Bundle[] bundles = item.getBundles();

      for (int i = 0; (i < bundles.length) && !found; i++) {
        Bitstream[] bitstreams = bundles[i].getBitstreams();

        for (int k = 0; (k < bitstreams.length) && !found; k++) {
          if (sequenceID == bitstreams[k].getSequenceID()) {
            bitstream = bitstreams[k];
            found = true;
          }
        }
      }
    }

    if (bitstream == null || filename == null || !filename.equals(bitstream.getName())) {
      // No bitstream found or filename was wrong -- ID invalid
      log.info(LogManager.getHeader(context, "invalid_id", "path=" + idString));
      JSPManager.showInvalidIDError(request, response, idString, Constants.BITSTREAM);

      return;
    }

    log.info(LogManager.getHeader(context, "view_bitstream", "bitstream_id=" + bitstream.getID()));

    // Modification date
    // Only use last-modified if this is an anonymous access
    // - caching content that may be generated under authorisation
    //   is a security problem
    if (context.getCurrentUser() == null) {
      // TODO: Currently the date of the item, since we don't have dates
      // for files
      response.setDateHeader("Last-Modified", item.getLastModified().getTime());

      // Check for if-modified-since header
      long modSince = request.getDateHeader("If-Modified-Since");

      if (modSince != -1 && item.getLastModified().getTime() < modSince) {
        // Item has not been modified since requested date,
        // hence bitstream has not; return 304
        response.setStatus(HttpServletResponse.SC_NOT_MODIFIED);
        return;
      }
    }

    // Pipe the bits
    InputStream is = bitstream.retrieve();

    // Set the response MIME type
    response.setContentType(bitstream.getFormat().getMIMEType());

    // Response length
    response.setHeader("Content-Length", String.valueOf(bitstream.getSize()));

    if (threshold != -1 && bitstream.getSize() >= threshold) {
      setBitstreamDisposition(bitstream.getName(), request, response);
    }

    Utils.bufferedCopy(is, response.getOutputStream());
    is.close();
    response.getOutputStream().flush();
  }