/** Accept the representation of a mail received from a sender, and create it. */
  @Override
  public void acceptRepresentation(Representation entity) throws ResourceException {
    final Form form = new Form(entity);
    final Mail mail = new Mail();
    mail.setStatus(Mail.STATUS_RECEIVED);

    // Look for an existing contact or create it.
    final String senderAddress = form.getFirstValue("senderAddress");
    final String senderName = form.getFirstValue("senderName");

    Contact contact = getObjectsFacade().lookForContact(senderAddress, this.mailbox);
    if (contact == null) {
      contact = new Contact();
      contact.setMailAddress(senderAddress);
      contact.setName(senderName);
    }
    mail.setSender(contact);

    mail.setMessage(form.getFirstValue("message"));
    mail.setSubject(form.getFirstValue("subject"));
    // form2.add("sendingDate", mail.getSendingDate().toString());
    final Series<Parameter> recipients = form.subList("recipient");
    for (final Parameter recipient : recipients) {
      contact = getObjectsFacade().lookForContact(recipient.getValue(), this.mailbox);
      if (contact == null) {
        contact = new Contact();
        final String[] recipientValues = recipient.getValue().split("\\$");
        contact.setMailAddress(recipientValues[0]);
        contact.setName(recipientValues[1]);
      }
      mail.getRecipients().add(contact);
    }
    getObjectsFacade().createMail(this.mailbox, mail);
  }
  @Override
  public PreferenceWriter append(Preference<?> pref) {
    append(pref.getMetadata().getName());

    if (pref.getQuality() < 1F) {
      append(";q=");
      appendQuality(pref.getQuality());
    }

    if (pref.getParameters() != null) {
      Parameter param;

      for (Iterator<Parameter> iter = pref.getParameters().iterator(); iter.hasNext(); ) {
        param = iter.next();

        if (param.getName() != null) {
          append(';').append(param.getName());

          if ((param.getValue() != null) && (param.getValue().length() > 0)) {
            append('=').append(param.getValue());
          }
        }
      }
    }

    return this;
  }
  @Override
  public void parseResponse(
      ChallengeResponse challenge, Request request, Series<Header> httpHeaders) {
    if (challenge.getRawValue() != null) {
      HeaderReader<Object> hr = new HeaderReader<Object>(challenge.getRawValue());

      try {
        Parameter param = hr.readParameter();

        while (param != null) {
          try {
            if ("username".equals(param.getName())) {
              challenge.setIdentifier(param.getValue());
            } else if ("realm".equals(param.getName())) {
              challenge.setRealm(param.getValue());
            } else if ("nonce".equals(param.getName())) {
              challenge.setServerNonce(param.getValue());
            } else if ("uri".equals(param.getName())) {
              challenge.setDigestRef(new Reference(param.getValue()));
            } else if ("response".equals(param.getName())) {
              challenge.setSecret(param.getValue());
            } else if ("algorithm".equals(param.getName())) {
              challenge.setDigestAlgorithm(param.getValue());
            } else if ("cnonce".equals(param.getName())) {
              challenge.setClientNonce(param.getValue());
            } else if ("opaque".equals(param.getName())) {
              challenge.setOpaque(param.getValue());
            } else if ("qop".equals(param.getName())) {
              challenge.setQuality(param.getValue());
            } else if ("nc".equals(param.getName())) {
              challenge.setServerNounceCount(Integer.valueOf(param.getValue(), 16));
            } else {
              challenge.getParameters().add(param);
            }
          } catch (Throwable e) {
            Context.getCurrentLogger()
                .log(Level.WARNING, "Unable to parse the challenge request header parameter", e);
          }
          if (hr.skipValueSeparator()) {
            param = hr.readParameter();
          } else {
            param = null;
          }
        }
      } catch (Exception e) {
        Context.getCurrentLogger()
            .log(Level.WARNING, "Unable to parse the challenge request header parameter", e);
      }
    }
  }
  @Override
  public void formatResponse(
      ChallengeWriter cw,
      ChallengeResponse challenge,
      Request request,
      Series<Header> httpHeaders) {

    if (challenge.getIdentifier() != null) {
      cw.appendQuotedChallengeParameter("username", challenge.getIdentifier());
    }

    if (challenge.getRealm() != null) {
      cw.appendQuotedChallengeParameter("realm", challenge.getRealm());
    }

    if (challenge.getServerNonce() != null) {
      cw.appendQuotedChallengeParameter("nonce", challenge.getServerNonce());
    }

    if (challenge.getDigestRef() != null) {
      challenge.setDigestRef(new Reference(request.getResourceRef().getPath()));
      cw.appendQuotedChallengeParameter("uri", challenge.getDigestRef().toString());
    }

    char[] responseDigest = formatResponseDigest(challenge, request);

    if (responseDigest != null) {
      cw.appendQuotedChallengeParameter("response", new String(responseDigest));
    }

    if ((challenge.getDigestAlgorithm() != null)
        && !Digest.ALGORITHM_MD5.equals(challenge.getDigestAlgorithm())) {
      cw.appendChallengeParameter("algorithm", challenge.getDigestAlgorithm());
    }

    if (challenge.getClientNonce() != null) {
      cw.appendQuotedChallengeParameter("cnonce", challenge.getClientNonce());
    }

    if (challenge.getOpaque() != null) {
      cw.appendQuotedChallengeParameter("opaque", challenge.getOpaque());
    }

    if (challenge.getQuality() != null) {
      cw.appendChallengeParameter("qop", challenge.getQuality());
    }

    if ((challenge.getQuality() != null) && (challenge.getServerNounceCount() > 0)) {
      cw.appendChallengeParameter("nc", challenge.getServerNounceCountAsHex());
    }

    for (Parameter param : challenge.getParameters()) {
      if (HeaderUtils.isToken(param.getValue())) {
        cw.appendChallengeParameter(param);
      } else {
        cw.appendQuotedChallengeParameter(param);
      }
    }
  }
Exemple #5
0
 /**
  * Writes a header line.
  *
  * @param header The header to write.
  * @param os The output stream.
  * @throws IOException
  */
 public static void writeHeader(Parameter header, OutputStream os) throws IOException {
   os.write(header.getName().getBytes());
   os.write(':');
   os.write(' ');
   os.write(header.getValue().getBytes());
   os.write(13); // CR
   os.write(10); // LF
 }
 private static void completeOperationQueryParameter(
     Operation operation, MethodAnnotationInfo mai) {
   if (mai.getQuery() != null) {
     Form form = new Form(mai.getQuery());
     for (org.restlet.data.Parameter parameter : form) {
       QueryParameter queryParameter = new QueryParameter();
       queryParameter.setName(parameter.getName());
       queryParameter.setRequired(true);
       queryParameter.setDescription(
           StringUtils.isNullOrEmpty(parameter.getValue())
               ? ""
               : "Value: " + parameter.getValue());
       queryParameter.setDefaultValue(parameter.getValue());
       queryParameter.setAllowMultiple(false);
       operation.getQueryParameters().add(queryParameter);
     }
   }
 }
  @Override
  public void doInit() {
    super.doInit();

    final Form form = getRequest().getResourceRef().getQueryAsForm();
    for (Parameter parameter : form) {
      params.put(parameter.getName(), parameter.getValue());
    }
  }
  /**
   * Returns the canonicalized resource name.
   *
   * @param resourceRef The resource reference.
   * @return The canonicalized resource name.
   */
  private static String getCanonicalizedResourceName(Reference resourceRef) {
    Form form = resourceRef.getQueryAsForm();
    Parameter param = form.getFirst("comp", true);

    if (param != null) {
      StringBuilder sb = new StringBuilder(resourceRef.getPath());
      return sb.append("?").append("comp=").append(param.getValue()).toString();
    }

    return resourceRef.getPath();
  }
  @Override
  public void formatRequest(
      ChallengeWriter cw, ChallengeRequest challenge, Response response, Series<Header> httpHeaders)
      throws IOException {
    // Format the parameters WWW-Authenticate: OAuth realm='Example
    // Service', error='expired-token'
    cw.append("realm='");
    cw.append(challenge.getRealm());
    cw.append("'");

    for (Parameter p : challenge.getParameters()) {
      cw.append(", ");
      cw.append(p.getName());
      cw.append("='");
      cw.append(p.getValue());
      cw.append("'");
    }
  }
    @Override
    public void handle(Request request, Response response) {
      Form form = request.getResourceRef().getQueryAsForm();
      List<Range> ranges = request.getRanges();
      boolean match = false;

      for (Parameter parameter : form) {
        long index = 0;
        long length = 0;
        String value = parameter.getValue();
        if (value.startsWith("-")) {
          index = Range.INDEX_LAST;
          length = Long.parseLong(value.substring(1));
        } else if (value.endsWith("-")) {
          index = Long.parseLong(value.substring(0, value.length() - 1));
          length = Range.SIZE_MAX;
        } else {
          String[] tab = value.split("-");
          if (tab.length == 2) {
            index = Long.parseLong(tab[0]);
            length = Long.parseLong(tab[1]) - index;
          }
        }

        boolean found = false;
        for (Range range : ranges) {
          found = (index == range.getIndex()) && (length == range.getSize());
          if (found) {
            break;
          }
        }
        if (!found) {
          break;
        }
        match = true;
      }
      if (match) {
        response.setStatus(Status.SUCCESS_OK);
        response.setEntity(str1000, MediaType.TEXT_PLAIN);
      } else {
        response.setStatus(Status.CLIENT_ERROR_BAD_REQUEST);
      }
    }
  /**
   * Extract the quality value. If the value is not found, 1 is returned.
   *
   * @param parameters The preference parameters.
   * @return The quality value.
   */
  protected float extractQuality(Series<Parameter> parameters) {
    float result = 1F;
    boolean found = false;

    if (parameters != null) {
      Parameter param = null;
      for (final Iterator<Parameter> iter = parameters.iterator(); !found && iter.hasNext(); ) {
        param = iter.next();
        if (param.getName().equals("q")) {
          result = PreferenceUtils.parseQuality(param.getValue());
          found = true;

          // Remove the quality parameter as we will directly store it
          // in the Preference object
          iter.remove();
        }
      }
    }

    return result;
  }
  @Override
  public void parseRequest(
      ChallengeRequest challenge, Response response, Series<Header> httpHeaders) {
    if (challenge.getRawValue() != null) {
      HeaderReader<Object> hr = new HeaderReader<Object>(challenge.getRawValue());

      try {
        Parameter param = hr.readParameter();

        while (param != null) {
          try {
            if ("realm".equals(param.getName())) {
              challenge.setRealm(param.getValue());
            } else if ("domain".equals(param.getName())) {
              challenge.getDomainRefs().add(new Reference(param.getValue()));
            } else if ("nonce".equals(param.getName())) {
              challenge.setServerNonce(param.getValue());
            } else if ("opaque".equals(param.getName())) {
              challenge.setOpaque(param.getValue());
            } else if ("stale".equals(param.getName())) {
              challenge.setStale(Boolean.valueOf(param.getValue()));
            } else if ("algorithm".equals(param.getName())) {
              challenge.setDigestAlgorithm(param.getValue());
            } else if ("qop".equals(param.getName())) {
              // challenge.setDigestAlgorithm(param.getValue());
            } else {
              challenge.getParameters().add(param);
            }

            if (hr.skipValueSeparator()) {
              param = hr.readParameter();
            } else {
              param = null;
            }
          } catch (Exception e) {
            Context.getCurrentLogger()
                .log(Level.WARNING, "Unable to parse the challenge request header parameter", e);
          }
        }
      } catch (Exception e) {
        Context.getCurrentLogger()
            .log(Level.WARNING, "Unable to parse the challenge request header parameter", e);
      }
    }
  }
  /**
   * Sends the request to the client. Commits the request line, headers and optional entity and send
   * them over the network.
   *
   * @param request The high-level request.
   * @return The result status.
   */
  @Override
  public Status sendRequest(Request request) {
    Status result = null;

    try {
      final Representation entity = request.getEntity();

      // Set the request headers
      for (final Parameter header : getRequestHeaders()) {
        getHttpMethod().addRequestHeader(header.getName(), header.getValue());
      }

      // For those method that accept enclosing entites, provide it
      if ((entity != null) && (getHttpMethod() instanceof EntityEnclosingMethod)) {
        final EntityEnclosingMethod eem = (EntityEnclosingMethod) getHttpMethod();
        eem.setRequestEntity(
            new RequestEntity() {
              public long getContentLength() {
                return entity.getSize();
              }

              public String getContentType() {
                return (entity.getMediaType() != null) ? entity.getMediaType().toString() : null;
              }

              public boolean isRepeatable() {
                return !entity.isTransient();
              }

              public void writeRequest(OutputStream os) throws IOException {
                entity.write(os);
              }
            });
      }

      // Ensure that the connection is active
      this.clientHelper.getHttpClient().executeMethod(getHttpMethod());

      // Now we can access the status code, this MUST happen after closing
      // any open request stream.
      result = new Status(getStatusCode(), null, getReasonPhrase(), null);

      // If there is no response body, immediately release the connection
      if (getHttpMethod().getResponseBodyAsStream() == null) {
        getHttpMethod().releaseConnection();
      }
    } catch (IOException ioe) {
      this.clientHelper
          .getLogger()
          .log(
              Level.WARNING,
              "An error occurred during the communication with the remote HTTP server.",
              ioe);
      result = new Status(Status.CONNECTOR_ERROR_COMMUNICATION, ioe);

      // Release the connection
      getHttpMethod().releaseConnection();
    }

    return result;
  }
  @Override
  public void formatRequest(
      ChallengeWriter cw, ChallengeRequest challenge, Response response, Series<Header> httpHeaders)
      throws IOException {

    if (challenge.getRealm() != null) {
      cw.appendQuotedChallengeParameter("realm", challenge.getRealm());
    }

    if (!challenge.getDomainRefs().isEmpty()) {
      cw.append(", domain=\"");

      for (int i = 0; i < challenge.getDomainRefs().size(); i++) {
        if (i > 0) {
          cw.append(' ');
        }

        cw.append(challenge.getDomainRefs().get(i).toString());
      }

      cw.append('"');
    }

    if (challenge.getServerNonce() != null) {
      cw.appendQuotedChallengeParameter("nonce", challenge.getServerNonce());
    }

    if (challenge.getOpaque() != null) {
      cw.appendQuotedChallengeParameter("opaque", challenge.getOpaque());
    }

    if (challenge.isStale()) {
      cw.appendChallengeParameter("stale", "true");
    }

    if (challenge.getDigestAlgorithm() != null) {
      cw.appendChallengeParameter("algorithm", challenge.getDigestAlgorithm());
    }

    if (!challenge.getQualityOptions().isEmpty()) {
      cw.append(", qop=\"");

      for (int i = 0; i < challenge.getQualityOptions().size(); i++) {
        if (i > 0) {
          cw.append(',');
        }

        cw.appendToken(challenge.getQualityOptions().get(i).toString());
      }

      cw.append('"');
    }

    for (Parameter param : challenge.getParameters()) {
      if (HeaderUtils.isToken(param.getValue())) {
        cw.appendChallengeParameter(param);
      } else {
        cw.appendQuotedChallengeParameter(param);
      }
    }
  }
  @Get
  public void resetMethod(String body) {

    String urilistener = null;
    String timeoutString = null;
    Long timeout = -1l;
    short warmStartValue = 0x00;

    Parameter urilistenerParam =
        getRequest().getResourceRef().getQueryAsForm().getFirst(Resources.URI_PARAM_URILISTENER);
    if (urilistenerParam != null) {
      urilistener = urilistenerParam.getValue().trim();
    }
    Parameter timeoutParam =
        getRequest().getResourceRef().getQueryAsForm().getFirst(Resources.URI_PARAM_TIMEOUT);
    if (timeoutParam != null) {
      timeoutString = timeoutParam.getValue().trim();
      try {
        timeout = Long.decode("0x" + timeoutString);
      } catch (NumberFormatException nfe) {
        Info info = new Info();
        Status _st = new Status();
        _st.setCode((short) GatewayConstants.GENERAL_ERROR);
        _st.setMessage(nfe.getMessage());
        info.setStatus(_st);
        Info.Detail detail = new Info.Detail();
        info.setDetail(detail);
        getResponse().setEntity(Util.marshal(info), MediaType.APPLICATION_XML);
        return;
      }
      if (!Util.isUnsigned32(timeout)) {
        Info info = new Info();
        Status _st = new Status();
        _st.setCode((short) GatewayConstants.GENERAL_ERROR);
        _st.setMessage("Wrong timeout");
        info.setStatus(_st);
        Info.Detail detail = new Info.Detail();
        info.setDetail(detail);
        getResponse().setEntity(Util.marshal(info), MediaType.APPLICATION_XML);
        return;
      }
    } else {
      // The timeout parameter is optional. If not provided we use a
      // default.
      timeout = (long) INTERNAL_TIMEOUT;
    }

    // TODO Set the right warm start value.
    String warmparamString = null;

    Parameter warmparam =
        getRequest()
            .getResourceRef()
            .getQueryAsForm()
            .getFirst(Resources.URI_PARAM_START_MODE_RESET);
    if (warmparam != null) {
      warmparamString = warmparam.getValue().trim();
      try {
        warmStartValue = Short.decode(warmparamString);
      } catch (NumberFormatException nfe) {
        Info info = new Info();
        Status _st = new Status();
        _st.setCode((short) GatewayConstants.GENERAL_ERROR);
        _st.setMessage(nfe.getMessage());
        info.setStatus(_st);
        Info.Detail detail = new Info.Detail();
        info.setDetail(detail);
        getResponse().setEntity(Util.marshal(info), MediaType.APPLICATION_XML);
        return;
      }

    } else {
      // The warm start value is mandatory!!
      Info info = new Info();
      Status _st = new Status();
      _st.setCode((short) GatewayConstants.GENERAL_ERROR);
      _st.setMessage("The warm start value is mandatory");
      info.setStatus(_st);
      Info.Detail detail = new Info.Detail();
      info.setDetail(detail);
      getResponse().setEntity(Util.marshal(info), MediaType.APPLICATION_XML);
      return;
    }

    if (urilistenerParam == null) {
      // Sync reset
      try {
        proxyGalInterface =
            getRestManager()
                .getClientObjectKey(-1, getClientInfo().getAddress())
                .getGatewayInterface();

        Status result = proxyGalInterface.resetDongleSync(timeout, warmStartValue);
        Info info = new Info();
        info.setStatus(result);
        getResponse().setEntity(Util.marshal(info), MediaType.TEXT_XML);

      } catch (Exception e) {
        Info info = new Info();
        Status _st = new Status();
        _st.setCode((short) GatewayConstants.GENERAL_ERROR);
        _st.setMessage(e.getMessage());
        info.setStatus(_st);
        Info.Detail detail = new Info.Detail();
        info.setDetail(detail);
        getResponse().setEntity(Util.marshal(info), MediaType.APPLICATION_XML);
        return;
      }
    } else {
      // Async reset
      try {
        ClientResources rcmal =
            getRestManager()
                .getClientObjectKey(
                    Util.getPortFromUriListener(urilistener), getClientInfo().getAddress());
        proxyGalInterface = rcmal.getGatewayInterface();
        if (!urilistener.equals("")) {
          rcmal.getClientEventListener().setResetDestination(urilistener);
        }
        proxyGalInterface.resetDongle(timeout, warmStartValue);
        Info.Detail detail = new Info.Detail();
        Info infoToReturn = new Info();
        Status status = new Status();
        status.setCode((short) GatewayConstants.SUCCESS);
        infoToReturn.setStatus(status);
        infoToReturn.setRequestIdentifier(Util.getRequestIdentifier());
        infoToReturn.setDetail(detail);
        getResponse().setEntity(Util.marshal(infoToReturn), MediaType.TEXT_XML);
        return;
      } catch (Exception e) {
        Info info = new Info();
        Status _st = new Status();
        _st.setCode((short) GatewayConstants.GENERAL_ERROR);
        _st.setMessage("The warm start value is mandatory");
        info.setStatus(_st);
        Info.Detail detail = new Info.Detail();
        info.setDetail(detail);
        getResponse().setEntity(Util.marshal(info), MediaType.APPLICATION_XML);
        return;
      }
    }
  }
  @Override
  public ContactInfo readValue() throws IOException {
    ContactInfo result = null;

    skipSpaces();
    if (peek() != -1) {
      result = new ContactInfo();
      if (peek() == '"') {
        result.setDisplayName(readQuotedString());
        skipSpaces();
        result.setReference(new Reference(readReference()));
      } else if (peek() == '<') {
        result.setReference(new Reference(readReference()));
      } else if (HeaderUtils.isTokenChar(peek())) {
        // Read value until end or value or parameter separator
        StringBuilder sb = null;
        int next = read();

        while ((next != -1) && !isComma(next) && !isSemiColon(next)) {
          if (sb == null) {
            sb = new StringBuilder();
          }

          sb.append((char) next);
          next = read();
        }

        // Remove trailing spaces
        if (sb != null) {
          for (int i = sb.length() - 1; (i >= 0) && isLinearWhiteSpace(sb.charAt(i)); i--) {
            sb.deleteCharAt(i);
          }
        }

        // Unread the separator
        if (isComma(next) || isSemiColon(next)) {
          unread();
        }

        // The last token is the reference
        int index = sb.lastIndexOf(" ");
        if (index != -1) {
          if (sb.charAt(index + 1) == '<') {
            if (sb.charAt(sb.length() - 1) == '>') {
              result.setReference(new Reference(sb.substring(index + 2, sb.length() - 1)));
            } else {
              throw new IOException("Unexpected end of reference. Please check your value");
            }
          }
          result.setDisplayName(sb.substring(0, index).trim());
        } else {
          result.setReference(new Reference(sb.toString()));
        }
      }
    }

    // Read address parameters.
    if (skipParameterSeparator()) {
      Parameter param = readParameter();

      while (param != null) {
        if ("q".equals(param.getName())) {
          result.setQuality(PreferenceReader.readQuality(param.getValue()));
        } else if ("expires".equals(param.getName())) {
          result.setExpires(param.getValue());
        } else {
          addParameter(result, param);
        }

        if (skipParameterSeparator()) {
          param = readParameter();
        } else {
          param = null;
        }
      }
    }

    return result;
  }
  /**
   * Search against all repositories using provided parameters. Note there are a few different types
   * of searches you can perform. If you provide the 'q' query parameter, a keyword search will be
   * performed. If you provide the 'g, a, v, p or c' query parameters, a maven coordinate search
   * will be performed. If you provide the 'cn' query parameter, a classname search will be
   * performed. If you provide the 'sha1' query parameter, a checksum search will be performed.
   *
   * @param q provide this param for a keyword search (g, a, v, p, c, cn, sha1 params will be
   *     ignored).
   * @param sha1 provide this param for a checksum search (g, a, v, p, c, cn params will be
   *     ignored).
   * @param cn provide this param for a classname search (g, a, v, p, c params will be ignored).
   * @param g group id to perform a maven search against (can be combined with a, v, p & c params as
   *     well).
   * @param a artifact id to perform a maven search against (can be combined with g, v, p & c params
   *     as well).
   * @param v version to perform a maven search against (can be combined with g, a, p & c params as
   *     well).
   * @param p packaging type to perform a maven search against (can be combined with g, a, v & c
   *     params as well).
   * @param c classifier to perform a maven search against (can be combined with g, a, v & p params
   *     as well).
   * @param from result index to start retrieving results from.
   * @param count number of results to have returned to you.
   * @param repositoryId The repositoryId to which repository search should be narrowed. Omit if
   *     search should be global.
   */
  @Override
  @GET
  @ResourceMethodSignature(
      queryParams = {
        @QueryParam("q"),
        @QueryParam("g"),
        @QueryParam("a"),
        @QueryParam("v"),
        @QueryParam("p"),
        @QueryParam("c"),
        @QueryParam("cn"),
        @QueryParam("sha1"),
        @QueryParam("from"),
        @QueryParam("count"),
        @QueryParam("repositoryId")
      },
      output = SearchResponse.class)
  public Object get(Context context, Request request, Response response, Variant variant)
      throws ResourceException {
    Form form = request.getResourceRef().getQueryAsForm();

    final Map<String, String> terms = new HashMap<String, String>();

    for (Parameter parameter : form) {
      terms.put(parameter.getName(), parameter.getValue());
    }

    Integer from = null;
    Boolean exact = null;
    String repositoryId = null;
    Boolean expandVersion = Boolean.FALSE;
    Boolean collapseResults = Boolean.FALSE;

    if (form.getFirstValue("from") != null) {
      try {
        from = Integer.valueOf(form.getFirstValue("from"));
      } catch (NumberFormatException e) {
        from = null;
      }
    }

    int count = LUCENE_HIT_LIMIT;
    if (form.getFirstValue("count") != null) {
      try {
        // capping the possible count
        count = Math.min(LUCENE_HIT_LIMIT, Integer.valueOf(form.getFirstValue("count")));
      } catch (NumberFormatException e) {
        count = LUCENE_HIT_LIMIT;
      }
    }

    if (form.getFirstValue("repositoryId") != null) {
      repositoryId = form.getFirstValue("repositoryId");
    }

    if (form.getFirstValue("exact") != null) {
      exact = Boolean.valueOf(form.getFirstValue("exact"));
    }

    if (form.getFirstValue("versionexpand") != null) {
      expandVersion = Boolean.valueOf(form.getFirstValue("versionexpand"));
    }
    if (form.getFirstValue("collapseresults") != null) {
      collapseResults = Boolean.valueOf(form.getFirstValue("collapseresults"));
    }

    // A little explanation about collapseResults, that might seems little bit awkward, since
    // currently we have only
    // one column "collapsable" (the version), but before and maybe in the future that's not the
    // case. So, here is
    // it:
    // the "collapseResults" is just a flag "do we allow collapse at all". It is just a shorthand to
    // turn on or off
    // collapse generally
    // Let's assume we have columns colA, colB and colC collapsable. So, instead saying
    // expandColA=true,expandColB=true,expandColC=true,
    // it is just easy to say collapseresults=false
    // BUT, if collapseresults=true is sent by client, even then an "override" will happen if there
    // is actually NO
    // ROW to collapse!
    // So: collapseresults=false EQUALS-TO expandColA=true & expandColB=true & expandColC=true
    if (collapseResults) {
      // here we would like to have ANDed all the collapsable column flags and negated the result
      // currently we
      collapseResults = !(true && expandVersion); // && expandColA && expandColB;
    }

    IteratorSearchResponse searchResult = null;

    SearchNGResponse result = new SearchNGResponse();

    int runCount = 0;

    while (runCount < RETRIES) {
      try {
        List<ArtifactInfoFilter> filters = new ArrayList<ArtifactInfoFilter>();

        // we need to save this reference to later
        SystemWideLatestVersionCollector systemWideCollector =
            new SystemWideLatestVersionCollector();
        filters.add(systemWideCollector);

        RepositoryWideLatestVersionCollector repositoryWideCollector = null;

        if (collapseResults) {
          repositoryWideCollector = new RepositoryWideLatestVersionCollector();
          filters.add(repositoryWideCollector);
        }

        try {
          searchResult =
              searchByTerms(
                  terms,
                  repositoryId,
                  from,
                  count,
                  exact,
                  expandVersion,
                  collapseResults,
                  filters,
                  searchers);

          if (searchResult == null) {
            collapseResults = false;

            continue;
          } else {
            repackIteratorSearchResponse(
                request,
                terms,
                result,
                collapseResults,
                from,
                count,
                searchResult,
                systemWideCollector,
                repositoryWideCollector);

            if (!result.isTooManyResults()) {
              // if we had collapseResults ON, and the totalHits are larger than actual (filtered)
              // results, and the actual result count is below COLLAPSE_OVERRIDE_TRESHOLD,
              // and full result set is smaller than HIT_LIMIT
              // then repeat without collapse
              if (collapseResults
                  && result.getData().size() < searchResult.getTotalHitsCount()
                  && result.getData().size() < COLLAPSE_OVERRIDE_TRESHOLD
                  && searchResult.getTotalHitsCount() < GA_HIT_LIMIT) {
                collapseResults = false;

                continue;
              }
            }
          }
        } catch (IOException e) {
          throw new ResourceException(Status.SERVER_ERROR_INTERNAL, e.getMessage(), e);
        }

        // we came here, so we break the while-loop, we got what we need
        break;
      } catch (NoSuchRepositoryException e) {
        throw new ResourceException(
            Status.CLIENT_ERROR_BAD_REQUEST, "Repository to be searched does not exists!", e);
      } catch (AlreadyClosedException e) {
        runCount++;

        getLogger()
            .info(
                "NexusIndexer issue (NEXUS-3702), we got AlreadyClosedException that happens when Reindexing or other \"indexer intensive\" task is running on instance while searching! Redoing search again.");

        if (getLogger().isDebugEnabled()) {
          // just keep it silent (DEBUG)
          getLogger().debug("Got AlreadyClosedException exception!", e);
        }

        result.setData(null);
      }
    }

    if (result.getData() == null) {
      try {
        repackIteratorSearchResponse(
            request,
            terms,
            result,
            collapseResults,
            from,
            count,
            IteratorSearchResponse.empty(null),
            null,
            null);
      } catch (NoSuchRepositoryException e) {
        // will not happen
      } catch (IOException e) {
        // will not happen
      }

      getLogger()
          .info(
              "Nexus issue (NEXUS-3702): Was unable to perform search "
                  + RETRIES
                  + " times, giving up, and lying about TooManyResults. Please retry to reproduce this with DEBUG logs and report this issue!");
    }

    return result;
  }