/**
   * Adds the date range values to the search template.
   *
   * <pre>{@code
   * - _date-start
   * - _date-end
   *
   * }</pre>
   *
   * If there is no 'start' and 'end' request parameter, then the current day is used. A day starts
   * at 00:00 and ends the next day at 00:00
   *
   * @param request The request that has been done on the search node.
   * @param propertiesMap The map where the key-values should be added to.
   */
  protected void addStartEnd(SlingHttpServletRequest request, Map<String, String> propertiesMap) {
    try {
      // Default is today
      Calendar cStart = getDayCalendar();
      Calendar cEnd = getDayCalendar();
      cEnd.add(Calendar.DAY_OF_MONTH, 1);

      // If a parameter is specified, we try to parse it and use that one.
      RequestParameter startParam = request.getRequestParameter(START_DAY_PARAM);
      RequestParameter endParam = request.getRequestParameter(END_DAY_PARAM);
      if (startParam != null && endParam != null) {
        String start = startParam.getString("UTF-8");
        String end = endParam.getString("UTF-8");
        cStart.setTime(format.parse(start));
        cEnd.setTime(format.parse(end));
      }

      // Calculate the beginning and the end date.
      String beginning = DateUtils.iso8601jcr(cStart);
      String end = DateUtils.iso8601jcr(cEnd);

      // Add to map.
      propertiesMap.put("_date-start", ClientUtils.escapeQueryChars(beginning));
      propertiesMap.put("_date-end", ClientUtils.escapeQueryChars(end));
    } catch (UnsupportedEncodingException e) {
      LOGGER.error(
          "Caught an UnsupportedEncodingException when trying to provide properties for the calendar search templates.",
          e);
    } catch (ParseException e) {
      LOGGER.error(
          "Caught a ParseException when trying to provide properties for the calendar search templates.",
          e);
    }
  }
Example #2
0
  /**
   * Load properties from the query node, request and property provider.<br>
   * Overwrite order: query node &lt; request &lt; property provider<br>
   * This ordering allows the query node to set defaults, the request to override those defaults but
   * the property provider to have the final say in what value is set.
   *
   * @param request
   * @param propertyProviderName
   * @return
   * @throws RepositoryException
   */
  private Map<String, String> loadProperties(
      SlingHttpServletRequest request, String propertyProviderName, Node node)
      throws RepositoryException {
    Map<String, String> propertiesMap = new HashMap<String, String>();

    // 0. load authorizable (user) information
    String userId = request.getRemoteUser();
    String userPrivatePath = ClientUtils.escapeQueryChars(LitePersonalUtils.getPrivatePath(userId));
    propertiesMap.put("_userPrivatePath", userPrivatePath);
    propertiesMap.put("_userId", ClientUtils.escapeQueryChars(userId));

    // 1. load in properties from the query template node so defaults can be set
    PropertyIterator props = node.getProperties();
    while (props.hasNext()) {
      javax.jcr.Property prop = props.nextProperty();
      if (!propertiesMap.containsKey(prop.getName()) && !prop.isMultiple()) {
        propertiesMap.put(prop.getName(), prop.getString());
      }
    }

    // 2. load in properties from the request
    RequestParameterMap params = request.getRequestParameterMap();
    for (Entry<String, RequestParameter[]> entry : params.entrySet()) {
      String key = entry.getKey();
      RequestParameter[] vals = entry.getValue();
      String requestValue = vals[0].getString();

      // blank values aren't cool
      if (StringUtils.isBlank(requestValue)) {
        continue;
      }

      // KERN-1601 Wildcard searches have to be manually lowercased for case insensitive
      // matching as Solr bypasses the analyzer when dealing with a wildcard or fuzzy
      // search.
      if (StringUtils.contains(requestValue, '*') || StringUtils.contains(requestValue, '~')) {
        requestValue = requestValue.toLowerCase();
      }
      // KERN-1703 Escape just :
      requestValue = StringUtils.replace(requestValue, ":", "\\:");
      propertiesMap.put(entry.getKey(), requestValue);
    }

    // 3. load properties from a property provider
    if (propertyProviderName != null) {
      LOGGER.debug("Trying Provider Name {} ", propertyProviderName);
      SolrSearchPropertyProvider provider = propertyProvider.get(propertyProviderName);
      if (provider != null) {
        LOGGER.debug("Trying Provider {} ", provider);
        provider.loadUserProperties(request, propertiesMap);
      } else {
        LOGGER.warn("No properties provider found for {} ", propertyProviderName);
      }
    } else {
      LOGGER.debug("No Provider ");
    }

    return propertiesMap;
  }
Example #3
0
 private SolrQuery buildSolrQuery(HttpServletRequest req) {
   SolrQuery query = new SolrQuery();
   query.setParam(CommonParams.WT, "json"); // $NON-NLS-1$
   query.setParam(CommonParams.FL, FIELD_NAMES);
   String queryString = getEncodedParameter(req, CommonParams.Q);
   if (queryString == null) return null;
   if (queryString.length() > 0) {
     String processedQuery = ""; // $NON-NLS-1$
     // divide into search terms delimited by space or plus ('+') character
     List<String> terms =
         new ArrayList<String>(Arrays.asList(queryString.split("[\\s\\+]+"))); // $NON-NLS-1$
     while (!terms.isEmpty()) {
       String term = terms.remove(0);
       if (term.length() == 0) continue;
       if (isSearchField(term)) {
         if (term.startsWith("NameLower:")) { // $NON-NLS-1$
           // solr does not lowercase queries containing wildcards
           // https://issues.apache.org/jira/browse/SOLR-219
           processedQuery += "NameLower:" + term.substring(10).toLowerCase(); // $NON-NLS-1$
         } else if (term.startsWith("Location:")) { // $NON-NLS-1${
           // all other field searches are case sensitive
           processedQuery += "Location:" + term.substring(9 + req.getContextPath().length());
         } else {
           // all other field searches are case sensitive
           processedQuery += term;
         }
       } else {
         // decode the term string now
         try {
           term = URLDecoder.decode(term, "UTF-8");
         } catch (UnsupportedEncodingException e) {
           // try with encoded term
         }
         boolean isPhrase = term.charAt(0) == '"';
         // solr does not lowercase queries containing wildcards
         // see https://bugs.eclipse.org/bugs/show_bug.cgi?id=359766
         String processedTerm = ClientUtils.escapeQueryChars(term.toLowerCase());
         // add leading and trailing wildcards to match word segments
         if (!isPhrase) {
           if (processedTerm.charAt(0) != '*') processedTerm = '*' + processedTerm;
           if (processedTerm.charAt(processedTerm.length() - 1) != '*') processedTerm += '*';
         }
         processedQuery += processedTerm;
       }
       processedQuery += " AND "; // $NON-NLS-1$
     }
     queryString = processedQuery;
   }
   queryString +=
       ProtocolConstants.KEY_USER_NAME + ':' + ClientUtils.escapeQueryChars(req.getRemoteUser());
   query.setQuery(queryString);
   // other common fields
   setField(req, query, CommonParams.ROWS);
   setField(req, query, CommonParams.START);
   setField(req, query, CommonParams.SORT);
   return query;
 }
Example #4
0
 @Override
 public SolrFilterResult buildSolrQuery() {
   String format =
       dateProvider.format(date).replace("Z", ".000Z"); // Tweak to set the milliseconds
   return new SolrFilterResult(
       "item.lastmodified:[" + ClientUtils.escapeQueryChars(format) + " TO *]");
 }
  /**
   * Apply the 'search by role' filter to the lucene query string.
   *
   * @param parametersMap
   * @param filters
   */
  protected void buildSearchByRoleQuery(Map<String, String> parametersMap, List<String> filters) {
    SearchableRole role =
        SearchableRole.valueOf(getSearchParam(parametersMap, REQUEST_PARAMETERS.role.toString()));
    String userid = getSearchParam(parametersMap, REQUEST_PARAMETERS.userid.toString());
    AuthorizableManager authorizableManager = null;
    Session adminSession = null;
    try {
      adminSession = repository.loginAdministrative();
      authorizableManager = adminSession.getAuthorizableManager();
      Authorizable au = authorizableManager.findAuthorizable(userid);
      List<Authorizable> groups = AuthorizableUtil.getUserFacingGroups(au, authorizableManager);
      groups.add(au);

      List<String> groupStrs = new ArrayList<String>(groups.size());
      for (Authorizable memberAuthz : groups) {
        groupStrs.add(ClientUtils.escapeQueryChars(memberAuthz.getId()));
      }

      filters.add(String.format(ROLE_TEMPLATE, role.toString(), JOINER_OR.join(groupStrs)));
      adminSession.logout();
    } catch (ClientPoolException e) {
      throw new RuntimeException(e);
    } catch (StorageClientException e) {
      throw new RuntimeException(e);
    } catch (AccessDeniedException e) {
      throw new RuntimeException(e);
    } finally {
      SparseUtils.logoutQuietly(adminSession);
    }
  }
Example #6
0
  /**
   * Returns an array where the first value is the search string and the second is a display string.
   *
   * @param lsid
   * @return
   */
  public String[] getTaxonSearch(String lsid) {

    String[] result = new String[0];
    // use the name matching index
    try {
      if (nameIndex == null) {
        nameIndex = new ALANameSearcher(nameIndexLocation);
      }
      NameSearchResult nsr = nameIndex.searchForRecordByLsid(lsid);
      if (nsr != null) {
        String rank = nsr.getRank() != null ? nsr.getRank().toString() : "Unknown Rank";
        String scientificName =
            nsr.getRankClassification() != null
                ? nsr.getRankClassification().getScientificName()
                : null;
        StringBuffer dispSB = new StringBuffer(rank + ": " + scientificName);
        StringBuilder sb = new StringBuilder("lft:[");
        String lft = nsr.getLeft() != null ? nsr.getLeft() : "0";
        String rgt = nsr.getRight() != null ? nsr.getRight() : "0";
        sb.append(lft).append(" TO ").append(rgt).append("]");
        return new String[] {sb.toString(), dispSB.toString()};
      } else {
        return new String[] {
          "taxon_concept_lsid:" + ClientUtils.escapeQueryChars(lsid), "taxon_concept_lsid:" + lsid
        };
      }
    } catch (Exception e) {
      logger.error(e.getMessage(), e);
    }

    return result;
  }
Example #7
0
 @Override
 public Date read(String txt) {
   try {
     return ClientUtils.parseDate(txt);
   } catch (Exception ex) {
     ex.printStackTrace();
   }
   return null;
 }
 /**
  * {@inheritDoc}
  *
  * @see
  *     org.sakaiproject.nakamura.api.solr.IndexingHandler#getDeleteQueries(org.sakaiproject.nakamura.api.solr.RepositorySession,
  *     org.osgi.service.event.Event)
  */
 public Collection<String> getDeleteQueries(RepositorySession repositorySession, Event event) {
   LOGGER.debug("GetDelete for {} ", event);
   String path = (String) event.getProperty("path");
   boolean ignore = ignorePath(path);
   if (ignore) {
     return Collections.emptyList();
   } else {
     return ImmutableList.of(FIELD_ID + ":" + ClientUtils.escapeQueryChars(path));
   }
 }
 /**
  * {@inheritDoc}
  *
  * @see
  *     org.sakaiproject.nakamura.api.search.SearchPropertyProvider#loadUserProperties(org.apache.sling.api.SlingHttpServletRequest,
  *     java.util.Map)
  */
 public void loadUserProperties(
     SlingHttpServletRequest request, Map<String, String> propertiesMap) {
   String user = request.getRemoteUser();
   String connectionPath =
       ClientUtils.escapeQueryChars(ConnectionUtils.getConnectionPathBase(user));
   if (connectionPath.startsWith("/")) {
     connectionPath = connectionPath.substring(1);
   }
   propertiesMap.put(SEARCH_PROP_CONNECTIONSTORE, connectionPath);
 }
Example #10
0
 /**
  * {@inheritDoc}
  *
  * @see
  *     org.sakaiproject.nakamura.api.solr.IndexingHandler#getDeleteQueries(org.sakaiproject.nakamura.api.solr.RepositorySession,
  *     org.osgi.service.event.Event)
  */
 @Override
 public Collection<String> getDeleteQueries(RepositorySession repoSession, Event event) {
   List<String> retval = Collections.emptyList();
   LOGGER.debug("getDeleteQueries for {}", event);
   String path = (String) event.getProperty(IndexingHandler.FIELD_PATH);
   String resourceType = (String) event.getProperty("resourceType");
   if (CONTENT_TYPES.contains(resourceType)) {
     retval = ImmutableList.of("id:" + ClientUtils.escapeQueryChars(path));
   }
   return retval;
 }
  /**
   * {@inheritDoc}
   *
   * @see
   *     org.sakaiproject.nakamura.api.search.SearchPropertyProvider#loadUserProperties(org.apache.sling.api.SlingHttpServletRequest,
   *     java.util.Map)
   */
  public void loadUserProperties(
      SlingHttpServletRequest request, Map<String, String> propertiesMap) {
    String user = request.getRemoteUser();
    Session session =
        StorageClientUtils.adaptToSession(
            request.getResourceResolver().adaptTo(javax.jcr.Session.class));
    propertiesMap.put(
        MessageConstants.SEARCH_PROP_MESSAGESTORE,
        ClientUtils.escapeQueryChars(messagingService.getFullPathToStore(user, session)) + "*");

    RequestParameter address = request.getRequestParameter("address");
    if (address != null && !address.getString().equals("")) {
      // resolve the address by finding the authorizables.
      String addressString = address.getString();
      String storePath = messagingService.getFullPathToStore(addressString, session);
      propertiesMap.put(
          MessageConstants.SEARCH_PROP_MESSAGESTORE, ClientUtils.escapeQueryChars(storePath) + "*");
    }

    RequestParameter usersParam = request.getRequestParameter("_from");
    if (usersParam != null && !usersParam.getString().equals("")) {
      String[] users = StringUtils.split(usersParam.getString(), ',');

      StringBuilder solrQuery = new StringBuilder();

      // build solr query
      solrQuery.append("from:(");
      for (int i = 0; i < users.length; i++) {
        solrQuery.append('"').append(ClientUtils.escapeQueryChars(users[i])).append('"');

        if (i < users.length - 1) {
          solrQuery.append(" OR ");
        }
      }
      solrQuery.append(")");

      propertiesMap.put("_from", solrQuery.toString());
    }
  }
 /**
  * @param request
  * @param propertiesMap
  */
 protected void addCalendarEventPath(
     SlingHttpServletRequest request, Map<String, String> propertiesMap) {
   try {
     RequestParameter eventParam = request.getRequestParameter("event-path");
     if (eventParam != null) {
       String eventPath = eventParam.getString("UTF-8");
       propertiesMap.put("_event-path", ClientUtils.escapeQueryChars(eventPath));
     }
   } catch (UnsupportedEncodingException e) {
     LOGGER.error(
         "Caught an UnsupportedEncodingException when trying to provide properties for the calendar search templates.",
         e);
   }
 }
Example #13
0
 private String expandHomeDirectory(String queryString) {
   Matcher homePathMatcher = homePathPattern.matcher(queryString);
   if (homePathMatcher.find()) {
     String username = homePathMatcher.group(3);
     String homePrefix = homePathMatcher.group(1);
     String userHome = LitePersonalUtils.getHomePath(username);
     userHome = ClientUtils.escapeQueryChars(userHome);
     String homePath = homePrefix + userHome + "/";
     String prefix = "";
     if (homePathMatcher.start() > 0) {
       prefix = queryString.substring(0, homePathMatcher.start());
     }
     String suffix = queryString.substring(homePathMatcher.end());
     queryString = prefix + homePath + suffix;
   }
   return queryString;
 }
  /**
   * @param request
   * @param propertiesMap
   */
  protected void addCalendarPath(
      SlingHttpServletRequest request, Map<String, String> propertiesMap) {
    try {
      String user = request.getRemoteUser();
      String path =
          LitePersonalUtils.getHomePath(user) + "/" + CalendarConstants.SAKAI_CALENDAR_NODENAME;

      RequestParameter pathParam = request.getRequestParameter(PATH_PARAM);
      if (pathParam != null) {
        path = pathParam.getString("UTF-8");
      }

      propertiesMap.put("_calendar-path", ClientUtils.escapeQueryChars(path));

    } catch (UnsupportedEncodingException e) {
      LOGGER.error(
          "Caught an UnsupportedEncodingException when trying to provide properties for the calendar search templates.",
          e);
    }
  }
 @Override
 public void add(SearchDocument doc) throws IOException {
   SolrDocument document = ((SolrSearchDocument) doc).getDocument();
   addOrUpdateList.add(ClientUtils.toSolrInputDocument(document));
 }
Example #16
0
  public NamedList<Object> request(final SolrRequest request, final ResponseParser processor)
      throws SolrServerException, IOException {
    HttpRequestBase method = null;
    InputStream is = null;
    SolrParams params = request.getParams();
    Collection<ContentStream> streams = requestWriter.getContentStreams(request);
    String path = requestWriter.getPath(request);
    if (path == null || !path.startsWith("/")) {
      path = DEFAULT_PATH;
    }

    ResponseParser parser = request.getResponseParser();
    if (parser == null) {
      parser = this.parser;
    }

    // The parser 'wt=' and 'version=' params are used instead of the original
    // params
    ModifiableSolrParams wparams = new ModifiableSolrParams(params);
    if (parser != null) {
      wparams.set(CommonParams.WT, parser.getWriterType());
      wparams.set(CommonParams.VERSION, parser.getVersion());
    }
    if (invariantParams != null) {
      wparams.add(invariantParams);
    }

    int tries = maxRetries + 1;
    try {
      while (tries-- > 0) {
        // Note: since we aren't do intermittent time keeping
        // ourselves, the potential non-timeout latency could be as
        // much as tries-times (plus scheduling effects) the given
        // timeAllowed.
        try {
          if (SolrRequest.METHOD.GET == request.getMethod()) {
            if (streams != null) {
              throw new SolrException(
                  SolrException.ErrorCode.BAD_REQUEST, "GET can't send streams!");
            }
            method = new HttpGet(baseUrl + path + ClientUtils.toQueryString(wparams, false));
          } else if (SolrRequest.METHOD.POST == request.getMethod()) {

            String url = baseUrl + path;
            boolean hasNullStreamName = false;
            if (streams != null) {
              for (ContentStream cs : streams) {
                if (cs.getName() == null) {
                  hasNullStreamName = true;
                  break;
                }
              }
            }
            boolean isMultipart =
                (this.useMultiPartPost || (streams != null && streams.size() > 1))
                    && !hasNullStreamName;

            // only send this list of params as query string params
            ModifiableSolrParams queryParams = new ModifiableSolrParams();
            for (String param : this.queryParams) {
              String[] value = wparams.getParams(param);
              if (value != null) {
                for (String v : value) {
                  queryParams.add(param, v);
                }
                wparams.remove(param);
              }
            }

            LinkedList<NameValuePair> postParams = new LinkedList<NameValuePair>();
            if (streams == null || isMultipart) {
              HttpPost post = new HttpPost(url + ClientUtils.toQueryString(queryParams, false));
              post.setHeader("Content-Charset", "UTF-8");
              if (!isMultipart) {
                post.addHeader("Content-Type", "application/x-www-form-urlencoded; charset=UTF-8");
              }

              List<FormBodyPart> parts = new LinkedList<FormBodyPart>();
              Iterator<String> iter = wparams.getParameterNamesIterator();
              while (iter.hasNext()) {
                String p = iter.next();
                String[] vals = wparams.getParams(p);
                if (vals != null) {
                  for (String v : vals) {
                    if (isMultipart) {
                      parts.add(new FormBodyPart(p, new StringBody(v, Charset.forName("UTF-8"))));
                    } else {
                      postParams.add(new BasicNameValuePair(p, v));
                    }
                  }
                }
              }

              if (isMultipart && streams != null) {
                for (ContentStream content : streams) {
                  String contentType = content.getContentType();
                  if (contentType == null) {
                    contentType = BinaryResponseParser.BINARY_CONTENT_TYPE; // default
                  }
                  String name = content.getName();
                  if (name == null) {
                    name = "";
                  }
                  parts.add(
                      new FormBodyPart(
                          name,
                          new InputStreamBody(
                              content.getStream(), contentType, content.getName())));
                }
              }

              if (parts.size() > 0) {
                MultipartEntity entity = new MultipartEntity(HttpMultipartMode.STRICT);
                for (FormBodyPart p : parts) {
                  entity.addPart(p);
                }
                post.setEntity(entity);
              } else {
                // not using multipart
                post.setEntity(new UrlEncodedFormEntity(postParams, "UTF-8"));
              }

              method = post;
            }
            // It is has one stream, it is the post body, put the params in the URL
            else {
              String pstr = ClientUtils.toQueryString(wparams, false);
              HttpPost post = new HttpPost(url + pstr);

              // Single stream as body
              // Using a loop just to get the first one
              final ContentStream[] contentStream = new ContentStream[1];
              for (ContentStream content : streams) {
                contentStream[0] = content;
                break;
              }
              if (contentStream[0] instanceof RequestWriter.LazyContentStream) {
                post.setEntity(
                    new InputStreamEntity(contentStream[0].getStream(), -1) {
                      @Override
                      public Header getContentType() {
                        return new BasicHeader("Content-Type", contentStream[0].getContentType());
                      }

                      @Override
                      public boolean isRepeatable() {
                        return false;
                      }
                    });
              } else {
                post.setEntity(
                    new InputStreamEntity(contentStream[0].getStream(), -1) {
                      @Override
                      public Header getContentType() {
                        return new BasicHeader("Content-Type", contentStream[0].getContentType());
                      }

                      @Override
                      public boolean isRepeatable() {
                        return false;
                      }
                    });
              }
              method = post;
            }
          } else {
            throw new SolrServerException("Unsupported method: " + request.getMethod());
          }
        } catch (NoHttpResponseException r) {
          method = null;
          if (is != null) {
            is.close();
          }
          // If out of tries then just rethrow (as normal error).
          if (tries < 1) {
            throw r;
          }
        }
      }
    } catch (IOException ex) {
      throw new SolrServerException("error reading streams", ex);
    }

    // XXX client already has this set, is this needed?
    method.getParams().setParameter(ClientPNames.HANDLE_REDIRECTS, followRedirects);
    method.addHeader("User-Agent", AGENT);

    InputStream respBody = null;
    boolean shouldClose = true;
    boolean success = false;
    try {
      // Execute the method.
      final HttpResponse response = httpClient.execute(method);
      int httpStatus = response.getStatusLine().getStatusCode();

      // Read the contents
      respBody = response.getEntity().getContent();
      Header ctHeader = response.getLastHeader("content-type");
      String contentType;
      if (ctHeader != null) {
        contentType = ctHeader.getValue();
      } else {
        contentType = "";
      }

      // handle some http level checks before trying to parse the response
      switch (httpStatus) {
        case HttpStatus.SC_OK:
        case HttpStatus.SC_BAD_REQUEST:
        case HttpStatus.SC_CONFLICT: // 409
          break;
        case HttpStatus.SC_MOVED_PERMANENTLY:
        case HttpStatus.SC_MOVED_TEMPORARILY:
          if (!followRedirects) {
            throw new SolrServerException(
                "Server at " + getBaseURL() + " sent back a redirect (" + httpStatus + ").");
          }
          break;
        default:
          if (processor == null) {
            throw new RemoteSolrException(
                httpStatus,
                "Server at "
                    + getBaseURL()
                    + " returned non ok status:"
                    + httpStatus
                    + ", message:"
                    + response.getStatusLine().getReasonPhrase(),
                null);
          }
      }
      if (processor == null) {

        // no processor specified, return raw stream
        NamedList<Object> rsp = new NamedList<Object>();
        rsp.add("stream", respBody);
        // Only case where stream should not be closed
        shouldClose = false;
        success = true;
        return rsp;
      }

      String procCt = processor.getContentType();
      if (procCt != null) {
        if (!contentType.equals(procCt)) {
          // unexpected content type
          String msg = "Expected content type " + procCt + " but got " + contentType + ".";
          Header encodingHeader = response.getEntity().getContentEncoding();
          String encoding;
          if (encodingHeader != null) {
            encoding = encodingHeader.getValue();
          } else {
            encoding = "UTF-8"; // try UTF-8
          }
          try {
            msg = msg + " " + IOUtils.toString(respBody, encoding);
          } catch (IOException e) {
            throw new RemoteSolrException(
                httpStatus, "Could not parse response with encoding " + encoding, e);
          }
          RemoteSolrException e = new RemoteSolrException(httpStatus, msg, null);
          throw e;
        }
      }

      //      if(true) {
      //        ByteArrayOutputStream copy = new ByteArrayOutputStream();
      //        IOUtils.copy(respBody, copy);
      //        String val = new String(copy.toByteArray());
      //        System.out.println(">RESPONSE>"+val+"<"+val.length());
      //        respBody = new ByteArrayInputStream(copy.toByteArray());
      //      }

      NamedList<Object> rsp = null;
      String charset = EntityUtils.getContentCharSet(response.getEntity());
      try {
        rsp = processor.processResponse(respBody, charset);
      } catch (Exception e) {
        throw new RemoteSolrException(httpStatus, e.getMessage(), e);
      }
      if (httpStatus != HttpStatus.SC_OK) {
        String reason = null;
        try {
          NamedList err = (NamedList) rsp.get("error");
          if (err != null) {
            reason = (String) err.get("msg");
            // TODO? get the trace?
          }
        } catch (Exception ex) {
        }
        if (reason == null) {
          StringBuilder msg = new StringBuilder();
          msg.append(response.getStatusLine().getReasonPhrase());
          msg.append("\n\n");
          msg.append("request: " + method.getURI());
          reason = java.net.URLDecoder.decode(msg.toString(), UTF_8);
        }
        throw new RemoteSolrException(httpStatus, reason, null);
      }
      success = true;
      return rsp;
    } catch (ConnectException e) {
      throw new SolrServerException("Server refused connection at: " + getBaseURL(), e);
    } catch (SocketTimeoutException e) {
      throw new SolrServerException(
          "Timeout occured while waiting response from server at: " + getBaseURL(), e);
    } catch (IOException e) {
      throw new SolrServerException(
          "IOException occured when talking to server at: " + getBaseURL(), e);
    } finally {
      if (respBody != null && shouldClose) {
        try {
          respBody.close();
        } catch (Throwable t) {
        } // ignore
        if (!success) {
          method.abort();
        }
      }
    }
  }
  protected NamedList<Object> sendRequest(SolrRequest request)
      throws SolrServerException, IOException {
    connect();

    ClusterState clusterState = zkStateReader.getClusterState();

    boolean sendToLeaders = false;
    List<String> replicas = null;

    if (request instanceof IsUpdateRequest) {
      if (request instanceof UpdateRequest) {
        NamedList<Object> response = directUpdate((AbstractUpdateRequest) request, clusterState);
        if (response != null) {
          return response;
        }
      }
      sendToLeaders = true;
      replicas = new ArrayList<>();
    }

    SolrParams reqParams = request.getParams();
    if (reqParams == null) {
      reqParams = new ModifiableSolrParams();
    }
    List<String> theUrlList = new ArrayList<>();
    if (request.getPath().equals("/admin/collections")
        || request.getPath().equals("/admin/cores")) {
      Set<String> liveNodes = clusterState.getLiveNodes();
      for (String liveNode : liveNodes) {
        theUrlList.add(zkStateReader.getBaseUrlForNodeName(liveNode));
      }
    } else {
      String collection = reqParams.get(UpdateParams.COLLECTION, defaultCollection);

      if (collection == null) {
        throw new SolrServerException(
            "No collection param specified on request and no default collection has been set.");
      }

      Set<String> collectionsList = getCollectionList(clusterState, collection);
      if (collectionsList.size() == 0) {
        throw new SolrException(ErrorCode.BAD_REQUEST, "Could not find collection: " + collection);
      }

      String shardKeys = reqParams.get(ShardParams._ROUTE_);
      if (shardKeys == null) {
        shardKeys = reqParams.get(ShardParams.SHARD_KEYS); // deprecated
      }

      // TODO: not a big deal because of the caching, but we could avoid looking
      // at every shard
      // when getting leaders if we tweaked some things

      // Retrieve slices from the cloud state and, for each collection
      // specified,
      // add it to the Map of slices.
      Map<String, Slice> slices = new HashMap<>();
      for (String collectionName : collectionsList) {
        DocCollection col = getDocCollection(clusterState, collectionName);
        Collection<Slice> routeSlices = col.getRouter().getSearchSlices(shardKeys, reqParams, col);
        ClientUtils.addSlices(slices, collectionName, routeSlices, true);
      }
      Set<String> liveNodes = clusterState.getLiveNodes();

      List<String> leaderUrlList = null;
      List<String> urlList = null;
      List<String> replicasList = null;

      // build a map of unique nodes
      // TODO: allow filtering by group, role, etc
      Map<String, ZkNodeProps> nodes = new HashMap<>();
      List<String> urlList2 = new ArrayList<>();
      for (Slice slice : slices.values()) {
        for (ZkNodeProps nodeProps : slice.getReplicasMap().values()) {
          ZkCoreNodeProps coreNodeProps = new ZkCoreNodeProps(nodeProps);
          String node = coreNodeProps.getNodeName();
          if (!liveNodes.contains(coreNodeProps.getNodeName())
              || !coreNodeProps.getState().equals(ZkStateReader.ACTIVE)) continue;
          if (nodes.put(node, nodeProps) == null) {
            if (!sendToLeaders || (sendToLeaders && coreNodeProps.isLeader())) {
              String url;
              if (reqParams.get(UpdateParams.COLLECTION) == null) {
                url =
                    ZkCoreNodeProps.getCoreUrl(
                        nodeProps.getStr(ZkStateReader.BASE_URL_PROP), defaultCollection);
              } else {
                url = coreNodeProps.getCoreUrl();
              }
              urlList2.add(url);
            } else if (sendToLeaders) {
              String url;
              if (reqParams.get(UpdateParams.COLLECTION) == null) {
                url =
                    ZkCoreNodeProps.getCoreUrl(
                        nodeProps.getStr(ZkStateReader.BASE_URL_PROP), defaultCollection);
              } else {
                url = coreNodeProps.getCoreUrl();
              }
              replicas.add(url);
            }
          }
        }
      }

      if (sendToLeaders) {
        leaderUrlList = urlList2;
        replicasList = replicas;
      } else {
        urlList = urlList2;
      }

      if (sendToLeaders) {
        theUrlList = new ArrayList<>(leaderUrlList.size());
        theUrlList.addAll(leaderUrlList);
      } else {
        theUrlList = new ArrayList<>(urlList.size());
        theUrlList.addAll(urlList);
      }
      if (theUrlList.isEmpty()) {
        throw new SolrException(
            SolrException.ErrorCode.INVALID_STATE, "Not enough nodes to handle the request");
      }

      Collections.shuffle(theUrlList, rand);
      if (sendToLeaders) {
        ArrayList<String> theReplicas = new ArrayList<>(replicasList.size());
        theReplicas.addAll(replicasList);
        Collections.shuffle(theReplicas, rand);
        theUrlList.addAll(theReplicas);
      }
    }

    LBHttpSolrServer.Req req = new LBHttpSolrServer.Req(request, theUrlList);
    LBHttpSolrServer.Rsp rsp = lbServer.request(req);
    return rsp.getResponse();
  }
 /**
  * {@inheritDoc}
  *
  * @see
  *     org.sakaiproject.nakamura.api.solr.IndexingHandler#getDeleteQueries(org.sakaiproject.nakamura.api.solr.RepositorySession,
  *     org.osgi.service.event.Event)
  */
 public Collection<String> getDeleteQueries(RepositorySession respositorySession, Event event) {
   logger.debug("GetDelete for {} ", event);
   String path = (String) event.getProperty(FIELD_PATH);
   return ImmutableList.of("id:" + ClientUtils.escapeQueryChars(path));
 }
  public NamedList<Object> request(final SolrRequest request, ResponseParser processor)
      throws SolrServerException, IOException {
    HttpMethod method = null;
    InputStream is = null;
    SolrParams params = request.getParams();
    Collection<ContentStream> streams = requestWriter.getContentStreams(request);
    String path = requestWriter.getPath(request);
    if (path == null || !path.startsWith("/")) {
      path = "/select";
    }

    ResponseParser parser = request.getResponseParser();
    if (parser == null) {
      parser = _parser;
    }

    // The parser 'wt=' and 'version=' params are used instead of the original params
    ModifiableSolrParams wparams = new ModifiableSolrParams();
    wparams.set(CommonParams.WT, parser.getWriterType());
    wparams.set(CommonParams.VERSION, parser.getVersion());
    if (params == null) {
      params = wparams;
    } else {
      params = new DefaultSolrParams(wparams, params);
    }

    if (_invariantParams != null) {
      params = new DefaultSolrParams(_invariantParams, params);
    }

    int tries = _maxRetries + 1;
    try {
      while (tries-- > 0) {
        // Note: since we aren't do intermittent time keeping
        // ourselves, the potential non-timeout latency could be as
        // much as tries-times (plus scheduling effects) the given
        // timeAllowed.
        try {
          if (SolrRequest.METHOD.GET == request.getMethod()) {
            if (streams != null) {
              throw new SolrException(
                  SolrException.ErrorCode.BAD_REQUEST, "GET can't send streams!");
            }
            method = new GetMethod(_baseURL + path + ClientUtils.toQueryString(params, false));
          } else if (SolrRequest.METHOD.POST == request.getMethod()) {

            String url = _baseURL + path;
            boolean isMultipart = (streams != null && streams.size() > 1);

            if (streams == null || isMultipart) {
              PostMethod post = new PostMethod(url);
              post.getParams().setContentCharset("UTF-8");
              if (!this.useMultiPartPost && !isMultipart) {
                post.addRequestHeader(
                    "Content-Type", "application/x-www-form-urlencoded; charset=UTF-8");
              }

              List<Part> parts = new LinkedList<Part>();
              Iterator<String> iter = params.getParameterNamesIterator();
              while (iter.hasNext()) {
                String p = iter.next();
                String[] vals = params.getParams(p);
                if (vals != null) {
                  for (String v : vals) {
                    if (this.useMultiPartPost || isMultipart) {
                      parts.add(new StringPart(p, v, "UTF-8"));
                    } else {
                      post.addParameter(p, v);
                    }
                  }
                }
              }

              if (isMultipart) {
                int i = 0;
                for (ContentStream content : streams) {
                  final ContentStream c = content;

                  String charSet = null;
                  String transferEncoding = null;
                  parts.add(
                      new PartBase(c.getName(), c.getContentType(), charSet, transferEncoding) {
                        @Override
                        protected long lengthOfData() throws IOException {
                          return c.getSize();
                        }

                        @Override
                        protected void sendData(OutputStream out) throws IOException {
                          InputStream in = c.getStream();
                          try {
                            IOUtils.copy(in, out);
                          } finally {
                            in.close();
                          }
                        }
                      });
                }
              }
              if (parts.size() > 0) {
                post.setRequestEntity(
                    new MultipartRequestEntity(
                        parts.toArray(new Part[parts.size()]), post.getParams()));
              }

              method = post;
            }
            // It is has one stream, it is the post body, put the params in the URL
            else {
              String pstr = ClientUtils.toQueryString(params, false);
              PostMethod post = new PostMethod(url + pstr);

              // Single stream as body
              // Using a loop just to get the first one
              final ContentStream[] contentStream = new ContentStream[1];
              for (ContentStream content : streams) {
                contentStream[0] = content;
                break;
              }
              if (contentStream[0] instanceof RequestWriter.LazyContentStream) {
                post.setRequestEntity(
                    new RequestEntity() {
                      public long getContentLength() {
                        return -1;
                      }

                      public String getContentType() {
                        return contentStream[0].getContentType();
                      }

                      public boolean isRepeatable() {
                        return false;
                      }

                      public void writeRequest(OutputStream outputStream) throws IOException {
                        ((RequestWriter.LazyContentStream) contentStream[0]).writeTo(outputStream);
                      }
                    });

              } else {
                is = contentStream[0].getStream();
                post.setRequestEntity(
                    new InputStreamRequestEntity(is, contentStream[0].getContentType()));
              }
              method = post;
            }
          } else {
            throw new SolrServerException("Unsupported method: " + request.getMethod());
          }
        } catch (NoHttpResponseException r) {
          // This is generally safe to retry on
          method.releaseConnection();
          method = null;
          if (is != null) {
            is.close();
          }
          // If out of tries then just rethrow (as normal error).
          if ((tries < 1)) {
            throw r;
          }
          // log.warn( "Caught: " + r + ". Retrying..." );
        }
      }
    } catch (IOException ex) {
      throw new SolrServerException("error reading streams", ex);
    }

    method.setFollowRedirects(_followRedirects);
    method.addRequestHeader("User-Agent", AGENT);
    if (_allowCompression) {
      method.setRequestHeader(new Header("Accept-Encoding", "gzip,deflate"));
    }

    try {
      // Execute the method.
      // System.out.println( "EXECUTE:"+method.getURI() );

      int statusCode = _httpClient.executeMethod(method);
      if (statusCode != HttpStatus.SC_OK) {
        StringBuilder msg = new StringBuilder();
        msg.append(method.getStatusLine().getReasonPhrase());
        msg.append("\n\n");
        msg.append(method.getStatusText());
        msg.append("\n\n");
        msg.append("request: " + method.getURI());
        throw new SolrException(statusCode, java.net.URLDecoder.decode(msg.toString(), "UTF-8"));
      }

      // Read the contents
      String charset = "UTF-8";
      if (method instanceof HttpMethodBase) {
        charset = ((HttpMethodBase) method).getResponseCharSet();
      }
      InputStream respBody = method.getResponseBodyAsStream();
      // Jakarta Commons HTTPClient doesn't handle any
      // compression natively.  Handle gzip or deflate
      // here if applicable.
      if (_allowCompression) {
        Header contentEncodingHeader = method.getResponseHeader("Content-Encoding");
        if (contentEncodingHeader != null) {
          String contentEncoding = contentEncodingHeader.getValue();
          if (contentEncoding.contains("gzip")) {
            // log.debug( "wrapping response in GZIPInputStream" );
            respBody = new GZIPInputStream(respBody);
          } else if (contentEncoding.contains("deflate")) {
            // log.debug( "wrapping response in InflaterInputStream" );
            respBody = new InflaterInputStream(respBody);
          }
        } else {
          Header contentTypeHeader = method.getResponseHeader("Content-Type");
          if (contentTypeHeader != null) {
            String contentType = contentTypeHeader.getValue();
            if (contentType != null) {
              if (contentType.startsWith("application/x-gzip-compressed")) {
                // log.debug( "wrapping response in GZIPInputStream" );
                respBody = new GZIPInputStream(respBody);
              } else if (contentType.startsWith("application/x-deflate")) {
                // log.debug( "wrapping response in InflaterInputStream" );
                respBody = new InflaterInputStream(respBody);
              }
            }
          }
        }
      }
      return processor.processResponse(respBody, charset);
    } catch (HttpException e) {
      throw new SolrServerException(e);
    } catch (IOException e) {
      throw new SolrServerException(e);
    } finally {
      method.releaseConnection();
      if (is != null) {
        is.close();
      }
    }
  }