You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@ranger.apache.org by bo...@apache.org on 2015/03/18 00:33:37 UTC

[15/17] incubator-ranger git commit: Support for Solr as Audit Destination.

http://git-wip-us.apache.org/repos/asf/incubator-ranger/blob/40aa090d/ranger_solrj/src/main/java/org/apache/solr/client/solrj/SolrQuery.java
----------------------------------------------------------------------
diff --git a/ranger_solrj/src/main/java/org/apache/solr/client/solrj/SolrQuery.java b/ranger_solrj/src/main/java/org/apache/solr/client/solrj/SolrQuery.java
new file mode 100644
index 0000000..bda6f34
--- /dev/null
+++ b/ranger_solrj/src/main/java/org/apache/solr/client/solrj/SolrQuery.java
@@ -0,0 +1,1109 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.solr.client.solrj;
+
+import org.apache.solr.common.params.CommonParams;
+import org.apache.solr.common.params.FacetParams;
+import org.apache.solr.common.params.HighlightParams;
+import org.apache.solr.common.params.ModifiableSolrParams;
+import org.apache.solr.common.params.StatsParams;
+import org.apache.solr.common.params.TermsParams;
+import org.apache.solr.common.util.DateUtil;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Date;
+import java.util.List;
+import java.util.Locale;
+import java.util.regex.Pattern;
+
+
+/**
+ * This is an augmented SolrParams with get/set/add fields for common fields used
+ * in the Standard and Dismax request handlers
+ * 
+ *
+ * @since solr 1.3
+ */
+public class SolrQuery extends ModifiableSolrParams 
+{  
+  public static final String DOCID = "_docid_"; // duplicate of org.apache.solr.search.QueryParsing.DOCID which is not accessible from here
+  
+  public enum ORDER { desc, asc;
+    public ORDER reverse() {
+      return (this == asc) ? desc : asc;
+    }
+  }
+
+  /** Maintains a map of current sorts */
+  private List<SortClause> sortClauses;
+  
+  public SolrQuery() {
+    super();
+  }
+
+  /** Create a new SolrQuery
+   * 
+   * @param q query string
+   */
+  public SolrQuery(String q) {
+    this();
+    this.set(CommonParams.Q, q);
+  }
+
+  /** enable/disable terms.  
+   * 
+   * @param b flag to indicate terms should be enabled. <br> if b==false, removes all other terms parameters
+   * @return Current reference (<i>this</i>)
+   */
+  public SolrQuery setTerms(boolean b) {
+    if (b) {
+      this.set(TermsParams.TERMS, true);
+    } else {
+      this.remove(TermsParams.TERMS);
+      this.remove(TermsParams.TERMS_FIELD);
+      this.remove(TermsParams.TERMS_LOWER);
+      this.remove(TermsParams.TERMS_UPPER);
+      this.remove(TermsParams.TERMS_UPPER_INCLUSIVE);
+      this.remove(TermsParams.TERMS_LOWER_INCLUSIVE);
+      this.remove(TermsParams.TERMS_LIMIT);
+      this.remove(TermsParams.TERMS_PREFIX_STR);
+      this.remove(TermsParams.TERMS_MINCOUNT);
+      this.remove(TermsParams.TERMS_MAXCOUNT);
+      this.remove(TermsParams.TERMS_RAW);
+      this.remove(TermsParams.TERMS_SORT);
+      this.remove(TermsParams.TERMS_REGEXP_STR);
+      this.remove(TermsParams.TERMS_REGEXP_FLAG);
+    }
+    return this;
+  }
+  
+  public boolean getTerms() {
+    return this.getBool(TermsParams.TERMS, false);
+  }
+  
+  public SolrQuery addTermsField(String field) {
+    this.add(TermsParams.TERMS_FIELD, field);
+    return this;
+  }
+  
+  public String[] getTermsFields() {
+    return this.getParams(TermsParams.TERMS_FIELD);
+  }
+  
+  public SolrQuery setTermsLower(String lower) {
+    this.set(TermsParams.TERMS_LOWER, lower);
+    return this;
+  }
+  
+  public String getTermsLower() {
+    return this.get(TermsParams.TERMS_LOWER, "");
+  }
+  
+  public SolrQuery setTermsUpper(String upper) {
+    this.set(TermsParams.TERMS_UPPER, upper);
+    return this;
+  }
+  
+  public String getTermsUpper() {
+    return this.get(TermsParams.TERMS_UPPER, "");
+  }
+  
+  public SolrQuery setTermsUpperInclusive(boolean b) {
+    this.set(TermsParams.TERMS_UPPER_INCLUSIVE, b);
+    return this;
+  }
+  
+  public boolean getTermsUpperInclusive() {
+    return this.getBool(TermsParams.TERMS_UPPER_INCLUSIVE, false);
+  }
+  
+  public SolrQuery setTermsLowerInclusive(boolean b) {
+    this.set(TermsParams.TERMS_LOWER_INCLUSIVE, b);
+    return this;
+  }
+  
+  public boolean getTermsLowerInclusive() {
+    return this.getBool(TermsParams.TERMS_LOWER_INCLUSIVE, true);
+  }
+ 
+  public SolrQuery setTermsLimit(int limit) {
+    this.set(TermsParams.TERMS_LIMIT, limit);
+    return this;
+  }
+  
+  public int getTermsLimit() {
+    return this.getInt(TermsParams.TERMS_LIMIT, 10);
+  }
+ 
+  public SolrQuery setTermsMinCount(int cnt) {
+    this.set(TermsParams.TERMS_MINCOUNT, cnt);
+    return this;
+  }
+  
+  public int getTermsMinCount() {
+    return this.getInt(TermsParams.TERMS_MINCOUNT, 1);
+  }
+
+  public SolrQuery setTermsMaxCount(int cnt) {
+    this.set(TermsParams.TERMS_MAXCOUNT, cnt);
+    return this;
+  }
+  
+  public int getTermsMaxCount() {
+    return this.getInt(TermsParams.TERMS_MAXCOUNT, -1);
+  }
+  
+  public SolrQuery setTermsPrefix(String prefix) {
+    this.set(TermsParams.TERMS_PREFIX_STR, prefix);
+    return this;
+  }
+  
+  public String getTermsPrefix() {
+    return this.get(TermsParams.TERMS_PREFIX_STR, "");
+  }
+  
+  public SolrQuery setTermsRaw(boolean b) {
+    this.set(TermsParams.TERMS_RAW, b);
+    return this;
+  }
+  
+  public boolean getTermsRaw() {
+    return this.getBool(TermsParams.TERMS_RAW, false);
+  }
+ 
+  public SolrQuery setTermsSortString(String type) {
+    this.set(TermsParams.TERMS_SORT, type);
+    return this;
+  }
+  
+  public String getTermsSortString() {
+    return this.get(TermsParams.TERMS_SORT, TermsParams.TERMS_SORT_COUNT);
+  }
+
+  public SolrQuery setTermsRegex(String regex)  {
+    this.set(TermsParams.TERMS_REGEXP_STR, regex);
+    return this;
+  }
+
+  public String getTermsRegex() {
+    return this.get(TermsParams.TERMS_REGEXP_STR);
+  }
+
+  public SolrQuery setTermsRegexFlag(String flag) {
+    this.add(TermsParams.TERMS_REGEXP_FLAG, flag);
+    return this;
+  }
+
+  public String[] getTermsRegexFlags()  {
+    return this.getParams(TermsParams.TERMS_REGEXP_FLAG);
+  }
+     
+  /** Add field(s) for facet computation.
+   * 
+   * @param fields Array of field names from the IndexSchema
+   * @return this
+   */
+  public SolrQuery addFacetField(String ... fields) {
+    add(FacetParams.FACET_FIELD, fields);
+    this.set(FacetParams.FACET, true);
+    return this;
+  }
+
+  /** Add field(s) for pivot computation.
+   * 
+   * pivot fields are comma separated
+   * 
+   * @param fields Array of field names from the IndexSchema
+   * @return this
+   */
+  public SolrQuery addFacetPivotField(String ... fields) {
+    add(FacetParams.FACET_PIVOT, fields);
+    this.set(FacetParams.FACET, true);
+    return this;
+  }
+
+  /**
+   * Add a numeric range facet.
+   *
+   * @param field The field
+   * @param start The start of range
+   * @param end The end of the range
+   * @param gap The gap between each count
+   * @return this
+   */
+  public SolrQuery addNumericRangeFacet(String field, Number start, Number end, Number gap) {
+    add(FacetParams.FACET_RANGE, field);
+    add(String.format(Locale.ROOT, "f.%s.%s", field, FacetParams.FACET_RANGE_START), start.toString());
+    add(String.format(Locale.ROOT, "f.%s.%s", field, FacetParams.FACET_RANGE_END), end.toString());
+    add(String.format(Locale.ROOT, "f.%s.%s", field, FacetParams.FACET_RANGE_GAP), gap.toString());
+    this.set(FacetParams.FACET, true);
+    return this;
+  }
+
+  /**
+   * Add a numeric range facet.
+   *
+   * @param field The field
+   * @param start The start of range
+   * @param end The end of the range
+   * @param gap The gap between each count
+   * @return this
+   */
+  public SolrQuery addDateRangeFacet(String field, Date start, Date end, String gap) {
+    add(FacetParams.FACET_RANGE, field);
+    add(String.format(Locale.ROOT, "f.%s.%s", field, FacetParams.FACET_RANGE_START), DateUtil.getThreadLocalDateFormat().format(start));
+    add(String.format(Locale.ROOT, "f.%s.%s", field, FacetParams.FACET_RANGE_END), DateUtil.getThreadLocalDateFormat().format(end));
+    add(String.format(Locale.ROOT, "f.%s.%s", field, FacetParams.FACET_RANGE_GAP), gap);
+    this.set(FacetParams.FACET, true);
+    return this;
+  }
+  
+  /**
+   * Add Interval Faceting on a field. All intervals for the same field should be included
+   * in the same call to this method.
+   * For syntax documentation see <a href="https://wiki.apache.org/solr/SimpleFacetParameters#Interval_Faceting">Solr wiki</a>.
+   * <br>
+   * Key substitution, filter exclusions or other local params on the field are not supported when using this method, 
+   * if this is needed, use the lower level {@link #add} method.<br> 
+   * Key substitution IS supported on intervals when using this method.
+   * 
+   * 
+   * @param field the field to add facet intervals. Must be an existing field and can't be null
+   * @param intervals Intervals to be used for faceting. It can be an empty array, but it can't 
+   * be <code>null</code>
+   * @return this
+   */
+  public SolrQuery addIntervalFacets(String field, String[] intervals) {
+    if (intervals == null) {
+      throw new IllegalArgumentException("Can't add null intervals");
+    }
+    if (field == null) {
+      throw new IllegalArgumentException("Field can't be null");
+    }
+    set(FacetParams.FACET, true);
+    add(FacetParams.FACET_INTERVAL, field);
+    for (String interval:intervals) {
+      add(String.format(Locale.ROOT, "f.%s.facet.interval.set", field), interval);
+    }
+    return this;
+  }
+  
+  /**
+   * Remove all Interval Facets on a field
+   * 
+   * @param field the field to remove from facet intervals
+   * @return Array of current intervals for <code>field</code>
+   */
+  public String[] removeIntervalFacets(String field) {
+    while(remove(FacetParams.FACET_INTERVAL, field)){};
+    return remove(String.format(Locale.ROOT, "f.%s.facet.interval.set", field));
+  }
+  
+  /** get the facet fields
+   * 
+   * @return string array of facet fields or null if not set/empty
+   */
+  public String[] getFacetFields() {
+    return this.getParams(FacetParams.FACET_FIELD);
+  }
+
+  /** remove a facet field
+   * 
+   * @param name Name of the facet field to be removed.
+   * 
+   * @return true, if the item was removed. <br>
+   *           false, if the facet field was null or did not exist.
+   */
+  public boolean removeFacetField(String name) {
+    boolean b = this.remove(FacetParams.FACET_FIELD, name);
+    if (this.get(FacetParams.FACET_FIELD) == null && this.get(FacetParams.FACET_QUERY) == null) {
+      this.setFacet(false);
+    }
+    return b;
+  }
+  
+  /** enable/disable faceting.  
+   * 
+   * @param b flag to indicate faceting should be enabled. <br> if b==false, removes all other faceting parameters
+   * @return Current reference (<i>this</i>)
+   */
+  public SolrQuery setFacet(boolean b) {
+    if (b) {
+      this.set(FacetParams.FACET, true);
+    } else {
+      this.remove(FacetParams.FACET);
+      this.remove(FacetParams.FACET_MINCOUNT);
+      this.remove(FacetParams.FACET_FIELD);
+      this.remove(FacetParams.FACET_LIMIT);
+      this.remove(FacetParams.FACET_MISSING);
+      this.remove(FacetParams.FACET_OFFSET);
+      this.remove(FacetParams.FACET_PREFIX);
+      this.remove(FacetParams.FACET_QUERY);
+      this.remove(FacetParams.FACET_SORT);
+      this.remove(FacetParams.FACET_ZEROS);
+      this.remove(FacetParams.FACET_PREFIX); // does not include the individual fields...
+      this.remove(FacetParams.FACET_INTERVAL); // does not remove interval parameters
+    }
+    return this;
+  }
+  
+  public SolrQuery setFacetPrefix( String prefix )
+  {
+    this.set( FacetParams.FACET_PREFIX, prefix );
+    return this;
+  }
+
+  public SolrQuery setFacetPrefix( String field, String prefix )
+  {
+    this.set( "f."+field+"."+FacetParams.FACET_PREFIX, prefix );
+    return this;
+  }
+
+  /** add a faceting query
+   * 
+   * @param f facet query
+   */
+  public SolrQuery addFacetQuery(String f) {
+    this.add(FacetParams.FACET_QUERY, f);
+    this.set(FacetParams.FACET, true);
+    return this;
+  }
+
+  /** get facet queries
+   * 
+   * @return all facet queries or null if not set/empty
+   */
+  public String[] getFacetQuery() {
+    return this.getParams(FacetParams.FACET_QUERY);
+  }
+
+  /** remove a facet query
+   * 
+   * @param q the facet query to remove
+   * @return true if the facet query was removed false otherwise
+   */
+  public boolean removeFacetQuery(String q) {
+    boolean b = this.remove(FacetParams.FACET_QUERY, q);
+    if (this.get(FacetParams.FACET_FIELD) == null && this.get(FacetParams.FACET_QUERY) == null) {
+      this.setFacet(false);
+    }
+    return b;
+  }
+
+  /** set the facet limit
+   * 
+   * @param lim number facet items to return
+   */
+  public SolrQuery setFacetLimit(int lim) {
+    this.set(FacetParams.FACET_LIMIT, lim);
+    return this;
+  }
+
+  /** get current facet limit
+   * 
+   * @return facet limit or default of 25
+   */
+  public int getFacetLimit() {
+    return this.getInt(FacetParams.FACET_LIMIT, 25);
+  }
+
+  /** set facet minimum count
+   * 
+   * @param cnt facets having less that cnt hits will be excluded from teh facet list
+   */
+  public SolrQuery setFacetMinCount(int cnt) {
+    this.set(FacetParams.FACET_MINCOUNT, cnt);
+    return this;
+  }
+
+  /** get facet minimum count
+   * 
+   * @return facet minimum count or default of 1
+   */
+  public int getFacetMinCount() {
+    return this.getInt(FacetParams.FACET_MINCOUNT, 1);
+  }
+
+  /**
+   * Sets facet missing boolean flag 
+   * 
+   * @param v flag to indicate the field of  {@link FacetParams#FACET_MISSING} .
+   * @return this
+   */
+  public SolrQuery setFacetMissing(Boolean v) {
+    this.set(FacetParams.FACET_MISSING, v);
+    return this;
+  }
+
+  /** get facet sort
+   * 
+   * @return facet sort or default of {@link FacetParams#FACET_SORT_COUNT}
+   */
+  public String getFacetSortString() {
+    return this.get(FacetParams.FACET_SORT, FacetParams.FACET_SORT_COUNT);
+  }
+
+
+  /** set facet sort
+   * 
+   * @param sort sort facets
+   * @return this
+   */
+  public SolrQuery setFacetSort(String sort) {
+    this.set(FacetParams.FACET_SORT, sort);
+    return this;
+  }
+
+  /** add highlight field
+   * 
+   * @param f field to enable for highlighting
+   */
+  public SolrQuery addHighlightField(String f) {
+    this.add(HighlightParams.FIELDS, f);
+    this.set(HighlightParams.HIGHLIGHT, true);
+    return this;
+  }
+
+  /** remove a field for highlighting
+   * 
+   * @param f field name to not highlight
+   * @return <i>true</i>, if removed, <br> <i>false</i>, otherwise
+   */
+  public boolean removeHighlightField(String f) {
+    boolean b = this.remove(HighlightParams.FIELDS, f);
+    if (this.get(HighlightParams.FIELDS) == null) {
+      this.setHighlight(false);
+    }
+    return b;
+  }
+
+  /** get list of highlighted fields
+   * 
+   * @return Array of highlight fields or null if not set/empty
+   */
+  public String[] getHighlightFields() {
+    return this.getParams(HighlightParams.FIELDS);
+  }
+
+  public SolrQuery setHighlightSnippets(int num) {
+    this.set(HighlightParams.SNIPPETS, num);
+    return this;
+  }
+
+  public int getHighlightSnippets() {
+    return this.getInt(HighlightParams.SNIPPETS, 1);
+  }
+
+  public SolrQuery setHighlightFragsize(int num) {
+    this.set(HighlightParams.FRAGSIZE, num);
+    return this;
+  }
+
+  public int getHighlightFragsize() {
+    return this.getInt(HighlightParams.FRAGSIZE, 100);
+  }
+
+  public SolrQuery setHighlightRequireFieldMatch(boolean flag) {
+    this.set(HighlightParams.FIELD_MATCH, flag);
+    return this;
+  }
+
+  public boolean getHighlightRequireFieldMatch() {
+    return this.getBool(HighlightParams.FIELD_MATCH, false);
+  }
+
+  public SolrQuery setHighlightSimplePre(String f) {
+    this.set(HighlightParams.SIMPLE_PRE, f);
+    return this;
+  }
+
+  public String getHighlightSimplePre() {
+    return this.get(HighlightParams.SIMPLE_PRE, "");
+  }
+
+  public SolrQuery setHighlightSimplePost(String f) {
+    this.set(HighlightParams.SIMPLE_POST, f);
+    return this;
+  }
+
+  public String getHighlightSimplePost() {
+    return this.get(HighlightParams.SIMPLE_POST, "");
+  }
+
+  /**
+   * Gets the raw sort field, as it will be sent to Solr.
+   * <p>
+   * The returned sort field will always contain a serialized version
+   * of the sort string built using {@link #setSort(SortClause)},
+   * {@link #addSort(SortClause)}, {@link #addOrUpdateSort(SortClause)},
+   * {@link #removeSort(SortClause)}, {@link #clearSorts()} and 
+   * {@link #setSorts(List)}.
+   */
+  public String getSortField() {
+    return this.get(CommonParams.SORT);
+  }
+  
+  /**
+   * Clears current sort information.
+   *
+   * @return the modified SolrQuery object, for easy chaining
+   * @since 4.2
+   */
+  public SolrQuery clearSorts() {
+    sortClauses = null;
+    serializeSorts();
+    return this;
+  }
+
+  /**
+   * Replaces the current sort information.
+   *
+   * @return the modified SolrQuery object, for easy chaining
+   * @since 4.2
+   */
+  public SolrQuery setSorts(List<SortClause> value) {
+    sortClauses = new ArrayList<>(value);
+    serializeSorts();
+    return this;
+  }
+
+  /**
+   * Gets an a list of current sort clauses.
+   *
+   * @return an immutable list of current sort clauses
+   * @since 4.2
+   */
+  public List<SortClause> getSorts() {
+    if (sortClauses == null) return Collections.emptyList();
+    else return Collections.unmodifiableList(sortClauses);
+  }
+
+  /**
+   * Replaces the current sort information with a single sort clause
+   *
+   * @return the modified SolrQuery object, for easy chaining
+   * @since 4.2
+   */
+  public SolrQuery setSort(String field, ORDER order) {
+    return setSort(new SortClause(field, order));
+  }
+
+  /**
+   * Replaces the current sort information with a single sort clause
+   *
+   * @return the modified SolrQuery object, for easy chaining
+   * @since 4.2
+   */
+  public SolrQuery setSort(SortClause sortClause) {
+    clearSorts();
+    return addSort(sortClause);
+  }
+
+  /**
+   * Adds a single sort clause to the end of the current sort information.
+   *
+   * @return the modified SolrQuery object, for easy chaining
+   * @since 4.2
+   */
+  public SolrQuery addSort(String field, ORDER order) {
+    return addSort(new SortClause(field, order));
+  }
+
+  /**
+   * Adds a single sort clause to the end of the query.
+   *
+   * @return the modified SolrQuery object, for easy chaining
+   * @since 4.2
+   */
+  public SolrQuery addSort(SortClause sortClause) {
+    if (sortClauses == null) sortClauses = new ArrayList<>();
+    sortClauses.add(sortClause);
+    serializeSorts();
+    return this;
+  }
+
+  /**
+   * Updates or adds a single sort clause to the query.
+   * If the field is already used for sorting, the order
+   * of the existing field is modified; otherwise, it is
+   * added to the end.
+   * <p>
+   * @return the modified SolrQuery object, for easy chaining
+   * @since 4.2
+   */
+  public SolrQuery addOrUpdateSort(String field, ORDER order) {
+    return addOrUpdateSort(new SortClause(field, order));
+  }
+
+  /**
+   * Updates or adds a single sort field specification to the current sort
+   * information. If the sort field already exist in the sort information map,
+   * its position is unchanged and the sort order is set; if it does not exist,
+   * it is appended at the end with the specified order..
+   *
+   * @return the modified SolrQuery object, for easy chaining
+   * @since 4.2
+   */
+  public SolrQuery addOrUpdateSort(SortClause sortClause) {
+    if (sortClauses != null) {
+      for (int index=0 ; index<sortClauses.size() ; index++) {
+        SortClause existing = sortClauses.get(index);
+        if (existing.getItem().equals(sortClause.getItem())) {
+          sortClauses.set(index, sortClause);
+          serializeSorts();
+          return this;
+        }
+      }
+    }
+    return addSort(sortClause);
+  }
+
+  /**
+   * Removes a single sort field from the current sort information.
+   *
+   * @return the modified SolrQuery object, for easy chaining
+   * @since 4.2
+   */
+  public SolrQuery removeSort(SortClause sortClause) {
+    return removeSort(sortClause.getItem());
+  }
+
+  /**
+   * Removes a single sort field from the current sort information.
+   *
+   * @return the modified SolrQuery object, for easy chaining
+   * @since 4.2
+   */
+  public SolrQuery removeSort(String itemName) {
+    if (sortClauses != null) {
+      for (SortClause existing : sortClauses) {
+        if (existing.getItem().equals(itemName)) {
+          sortClauses.remove(existing);
+          if (sortClauses.isEmpty()) sortClauses = null;
+          serializeSorts();
+          break;
+        }
+      }
+    }
+    return this;
+  }
+
+  private void serializeSorts() {
+    if (sortClauses == null || sortClauses.isEmpty()) {
+      remove(CommonParams.SORT);
+    } else {
+      StringBuilder sb = new StringBuilder();
+      for (SortClause sortClause : sortClauses) {
+        if (sb.length() > 0) sb.append(",");
+        sb.append(sortClause.getItem());
+        sb.append(" ");
+        sb.append(sortClause.getOrder());
+      }
+      set(CommonParams.SORT, sb.toString());
+    }
+  }
+
+  public void setGetFieldStatistics( boolean v )
+  {
+    this.set( StatsParams.STATS, v );
+  }
+  
+  public void setGetFieldStatistics( String field )
+  {
+    this.set( StatsParams.STATS, true );
+    this.add( StatsParams.STATS_FIELD, field );
+  }
+  
+
+  public void addGetFieldStatistics( String ... field )
+    {
+      this.set( StatsParams.STATS, true );
+      this.add( StatsParams.STATS_FIELD, field );
+    }
+  
+  public void addStatsFieldFacets( String field, String ... facets )
+  {
+    if( field == null ) {
+      this.add( StatsParams.STATS_FACET, facets );
+    }
+    else {
+      for( String f : facets ) {
+        this.add( "f."+field+"."+StatsParams.STATS_FACET, f );
+      }
+    }
+  }
+
+  public void addStatsFieldCalcDistinct(String field, boolean calcDistinct) {
+    if (field == null) {
+      this.add(StatsParams.STATS_CALC_DISTINCT, Boolean.toString(calcDistinct));
+    } else {
+      this.add("f." + field + "." + StatsParams.STATS_CALC_DISTINCT, Boolean.toString(calcDistinct));
+    }
+  }
+
+  public SolrQuery setFilterQueries(String ... fq) {
+    this.set(CommonParams.FQ, fq);
+    return this;
+  }
+
+  public SolrQuery addFilterQuery(String ... fq) {
+    this.add(CommonParams.FQ, fq);
+    return this;
+  }
+
+  public boolean removeFilterQuery(String fq) {
+    return this.remove(CommonParams.FQ, fq);
+  }
+
+  public String[] getFilterQueries() {
+    return this.getParams(CommonParams.FQ);
+  }
+  
+  public boolean getHighlight() {
+    return this.getBool(HighlightParams.HIGHLIGHT, false);
+  }
+  
+  public SolrQuery setHighlight(boolean b) {
+    if (b) {
+      this.set(HighlightParams.HIGHLIGHT, true);
+    } else {
+      this.remove(HighlightParams.HIGHLIGHT);
+      this.remove(HighlightParams.FIELD_MATCH);
+      this.remove(HighlightParams.FIELDS);
+      this.remove(HighlightParams.FORMATTER);
+      this.remove(HighlightParams.FRAGSIZE);
+      this.remove(HighlightParams.SIMPLE_POST);
+      this.remove(HighlightParams.SIMPLE_PRE);
+      this.remove(HighlightParams.SNIPPETS);
+    }
+    return this;
+  }
+
+  public SolrQuery setFields(String ... fields) {
+    if( fields == null || fields.length == 0 ) {
+      this.remove( CommonParams.FL );
+      return this;
+    }
+    StringBuilder sb = new StringBuilder();
+    sb.append( fields[0] );
+    for( int i=1; i<fields.length; i++ ) {
+      sb.append( ',' );
+      sb.append( fields[i] );
+    }
+    this.set(CommonParams.FL, sb.toString() );
+    return this;
+  }
+    
+  public SolrQuery addField(String field) {
+    return addValueToParam(CommonParams.FL, field);
+  }
+
+  public String getFields() {
+    String fields = this.get(CommonParams.FL);
+    if (fields!=null && fields.equals("score")) {
+      fields = "*, score";
+    }
+    return fields;
+  }
+
+  private static Pattern scorePattern = Pattern.compile("(^|[, ])score");
+
+  public SolrQuery setIncludeScore(boolean includeScore) {
+    String fields = get(CommonParams.FL,"*");
+    if (includeScore) {
+      if (!scorePattern.matcher(fields).find()) {   
+        this.set(CommonParams.FL, fields+",score");
+      }
+    } else {
+      this.set(CommonParams.FL, scorePattern.matcher(fields).replaceAll(""));
+    }
+    return this;
+  }
+
+  public SolrQuery setQuery(String query) {
+    this.set(CommonParams.Q, query);
+    return this;
+  }
+
+  public String getQuery() {
+    return this.get(CommonParams.Q);
+  }
+
+  public SolrQuery setRows(Integer rows) {
+    if( rows == null ) {
+      this.remove( CommonParams.ROWS );
+    }
+    else {
+      this.set(CommonParams.ROWS, rows);
+    }
+    return this;
+  }
+
+  public Integer getRows()
+  {
+    return this.getInt(CommonParams.ROWS);
+  }
+
+  public void setShowDebugInfo(boolean showDebugInfo) {
+    this.set(CommonParams.DEBUG_QUERY, String.valueOf(showDebugInfo));
+  }
+
+  public void setDistrib(boolean val) {
+    this.set(CommonParams.DISTRIB, String.valueOf(val));
+  }
+
+
+  public SolrQuery setStart(Integer start) {
+    if( start == null ) {
+      this.remove( CommonParams.START );
+    }
+    else {
+      this.set(CommonParams.START, start);
+    }
+    return this;
+  }
+  
+  public Integer getStart()
+  {
+    return this.getInt(CommonParams.START);
+  }
+
+  /**
+   * The Request Handler to use (see the solrconfig.xml), which is stored in the "qt" parameter.
+   * Normally it starts with a '/' and if so it will be used by
+   * {@link org.apache.solr.client.solrj.request.QueryRequest#getPath()} in the URL instead of the "qt" parameter.
+   * If this is left blank, then the default of "/select" is assumed.
+   *
+   * @param qt The Request Handler name corresponding to one in solrconfig.xml on the server.
+   * @return this
+   */
+  public SolrQuery setRequestHandler(String qt) {
+    this.set(CommonParams.QT, qt);
+    return this;
+  }
+
+  public String getRequestHandler() {
+    return this.get(CommonParams.QT);
+  }
+
+  /**
+   * @return this
+   * @see ModifiableSolrParams#set(String,String[])
+   */
+  public SolrQuery setParam(String name, String ... values) {
+    this.set(name, values);
+    return this;
+  }
+
+  /**
+   * @return this
+   * @see org.apache.solr.common.params.ModifiableSolrParams#set(String, boolean)
+   */
+  public SolrQuery setParam(String name, boolean value) {
+    this.set(name, value);
+    return this;
+  }
+
+  /** get a deep copy of this object **/
+  public SolrQuery getCopy() {
+    SolrQuery q = new SolrQuery();
+    for (String name : this.getParameterNames()) {
+      q.setParam(name, this.getParams(name));
+    }
+    return q;
+  }
+  
+  /**
+  * Set the maximum time allowed for this query. If the query takes more time
+  * than the specified milliseconds, a timeout occurs and partial (or no)
+  * results may be returned.
+  * 
+  * If given Integer is null, then this parameter is removed from the request
+  * 
+  *@param milliseconds the time in milliseconds allowed for this query
+  */
+  public SolrQuery setTimeAllowed(Integer milliseconds) {
+    if (milliseconds == null) {
+      this.remove(CommonParams.TIME_ALLOWED);
+    } else {
+      this.set(CommonParams.TIME_ALLOWED, milliseconds);
+    }
+    return this;
+  }
+  
+  /**
+  * Get the maximum time allowed for this query.
+  */
+  public Integer getTimeAllowed() {
+    return this.getInt(CommonParams.TIME_ALLOWED);
+  }
+
+  ///////////////////////
+  //  Utility functions
+  ///////////////////////
+  
+  private String toSortString(String field, ORDER order) {
+    return field.trim() + ' ' + String.valueOf(order).trim();
+  }
+  
+  private String join(String a, String b, String sep) {
+    StringBuilder sb = new StringBuilder();
+    if (a!=null && a.length()>0) {
+      sb.append(a);
+      sb.append(sep);
+    } 
+    if (b!=null && b.length()>0) {
+      sb.append(b);
+    }
+    return sb.toString().trim();
+  }
+  
+  private SolrQuery addValueToParam(String name, String value) {
+    String tmp = this.get(name);
+    tmp = join(tmp, value, ",");
+    this.set(name, tmp);
+    return this;
+  }
+   
+  private String join(String[] vals, String sep, String removeVal) {
+    StringBuilder sb = new StringBuilder();
+    for (int i=0; i<vals.length; i++) {
+      if (!vals[i].equals(removeVal)) {
+        if (sb.length() > 0) {
+          sb.append(sep);
+        }
+        sb.append(vals[i]);
+      }
+    }
+    return sb.toString().trim();
+  }
+
+  /**
+   * A single sort clause, encapsulating what to sort and the sort order.
+   * <p>
+   * The item specified can be "anything sortable" by solr; some examples
+   * include a simple field name, the constant string {@code score}, and functions
+   * such as {@code sum(x_f, y_f)}.
+   * <p>
+   * A SortClause can be created through different mechanisms:
+   * <PRE><code>
+   * new SortClause("product", SolrQuery.ORDER.asc);
+   * new SortClause("product", "asc");
+   * SortClause.asc("product");
+   * SortClause.desc("product");
+   * </code></PRE>
+   */
+  public static class SortClause implements java.io.Serializable {
+
+    private static final long serialVersionUID = 1L;
+
+    private final String item;
+    private final ORDER order;
+
+    /**
+     * Creates a SortClause based on item and order
+     * @param item item to sort on
+     * @param order direction to sort
+     */
+    public SortClause(String item, ORDER order) {
+      this.item = item;
+      this.order = order;
+    }
+
+    /**
+     * Creates a SortClause based on item and order
+     * @param item item to sort on
+     * @param order string value for direction to sort
+     */
+    public SortClause(String item, String order) {
+      this(item, ORDER.valueOf(order));
+    }
+
+    /**
+     * Creates an ascending SortClause for an item
+     * @param item item to sort on
+     */
+    public static SortClause create (String item, ORDER order) {
+      return new SortClause(item, order);
+    }
+
+    /**
+     * Creates a SortClause based on item and order
+     * @param item item to sort on
+     * @param order string value for direction to sort
+     */
+    public static SortClause create(String item, String order) {
+      return new SortClause(item, ORDER.valueOf(order));
+    }
+
+    /**
+     * Creates an ascending SortClause for an item
+     * @param item item to sort on
+     */
+    public static SortClause asc (String item) {
+      return new SortClause(item, ORDER.asc);
+    }
+
+    /**
+     * Creates a decending SortClause for an item
+     * @param item item to sort on
+     */
+    public static SortClause desc (String item) {
+      return new SortClause(item, ORDER.desc);
+    }
+
+    /**
+     * Gets the item to sort, typically a function or a fieldname
+     * @return item to sort
+     */
+    public String getItem() {
+      return item;
+    }
+
+    /**
+     * Gets the order to sort
+     * @return order to sort
+     */
+    public ORDER getOrder() {
+      return order;
+    }
+
+    public boolean equals(Object other){
+      if (this == other) return true;
+      if (!(other instanceof SortClause)) return false;
+      final SortClause that = (SortClause) other;
+      return this.getItem().equals(that.getItem()) && this.getOrder().equals(that.getOrder());
+    }
+
+    public int hashCode(){
+      return this.getItem().hashCode();
+    }
+
+    /**
+     * Gets a human readable description of the sort clause.
+     * <p>
+     * The returned string is not suitable for passing to Solr,
+     * but may be useful in debug output and the like.
+     * @return a description of the current sort clause
+     */
+    public String toString() {
+      return "[" + getClass().getSimpleName() + ": item=" + getItem() + "; order=" + getOrder() + "]";
+    }
+  }
+}

http://git-wip-us.apache.org/repos/asf/incubator-ranger/blob/40aa090d/ranger_solrj/src/main/java/org/apache/solr/client/solrj/SolrRequest.java
----------------------------------------------------------------------
diff --git a/ranger_solrj/src/main/java/org/apache/solr/client/solrj/SolrRequest.java b/ranger_solrj/src/main/java/org/apache/solr/client/solrj/SolrRequest.java
new file mode 100644
index 0000000..6d4efb6
--- /dev/null
+++ b/ranger_solrj/src/main/java/org/apache/solr/client/solrj/SolrRequest.java
@@ -0,0 +1,137 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.solr.client.solrj;
+
+import org.apache.solr.common.params.SolrParams;
+import org.apache.solr.common.util.ContentStream;
+
+import java.io.IOException;
+import java.io.Serializable;
+import java.util.Collection;
+import java.util.Set;
+import java.util.concurrent.TimeUnit;
+
+/**
+ * 
+ *
+ * @since solr 1.3
+ */
+public abstract class SolrRequest<T extends SolrResponse> implements Serializable {
+
+  public enum METHOD {
+    GET,
+    POST,
+    PUT
+  };
+
+  private METHOD method = METHOD.GET;
+  private String path = null;
+
+  private ResponseParser responseParser;
+  private StreamingResponseCallback callback;
+  private Set<String> queryParams;
+  
+  //---------------------------------------------------------
+  //---------------------------------------------------------
+
+  public SolrRequest( METHOD m, String path )
+  {
+    this.method = m;
+    this.path = path;
+  }
+
+  //---------------------------------------------------------
+  //---------------------------------------------------------
+
+  public METHOD getMethod() {
+    return method;
+  }
+  public void setMethod(METHOD method) {
+    this.method = method;
+  }
+
+  public String getPath() {
+    return path;
+  }
+  public void setPath(String path) {
+    this.path = path;
+  }
+
+  /**
+   *
+   * @return The {@link org.apache.solr.client.solrj.ResponseParser}
+   */
+  public ResponseParser getResponseParser() {
+    return responseParser;
+  }
+
+  /**
+   * Optionally specify how the Response should be parsed.  Not all server implementations require a ResponseParser
+   * to be specified.
+   * @param responseParser The {@link org.apache.solr.client.solrj.ResponseParser}
+   */
+  public void setResponseParser(ResponseParser responseParser) {
+    this.responseParser = responseParser;
+  }
+
+  public StreamingResponseCallback getStreamingResponseCallback() {
+    return callback;
+  }
+
+  public void setStreamingResponseCallback(StreamingResponseCallback callback) {
+    this.callback = callback;
+  }
+
+  /**
+   * Parameter keys that are sent via the query string
+   */
+  public Set<String> getQueryParams() {
+    return this.queryParams;
+  }
+
+  public void setQueryParams(Set<String> queryParams) {
+    this.queryParams = queryParams;
+  }
+
+  public abstract SolrParams getParams();
+
+  public abstract Collection<ContentStream> getContentStreams() throws IOException;
+
+  /**
+   * Create a new SolrResponse to hold the response from the server
+   * @param client the {@link SolrClient} the request will be sent to
+   */
+  protected abstract T createResponse(SolrClient client);
+
+  /**
+   * Send this request to a {@link SolrClient} and return the response
+   * @param client the SolrClient to communicate with
+   * @return the response
+   * @throws SolrServerException if there is an error on the Solr server
+   * @throws IOException if there is a communication error
+   */
+  public final T process(SolrClient client) throws SolrServerException, IOException {
+    long startTime = TimeUnit.MILLISECONDS.convert(System.nanoTime(), TimeUnit.NANOSECONDS);
+    T res = createResponse(client);
+    res.setResponse(client.request(this));
+    long endTime = TimeUnit.MILLISECONDS.convert(System.nanoTime(), TimeUnit.NANOSECONDS);
+    res.setElapsedTime(endTime - startTime);
+    return res;
+  }
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-ranger/blob/40aa090d/ranger_solrj/src/main/java/org/apache/solr/client/solrj/SolrResponse.java
----------------------------------------------------------------------
diff --git a/ranger_solrj/src/main/java/org/apache/solr/client/solrj/SolrResponse.java b/ranger_solrj/src/main/java/org/apache/solr/client/solrj/SolrResponse.java
new file mode 100644
index 0000000..244a757
--- /dev/null
+++ b/ranger_solrj/src/main/java/org/apache/solr/client/solrj/SolrResponse.java
@@ -0,0 +1,65 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.solr.client.solrj;
+
+import org.apache.solr.common.SolrException;
+import org.apache.solr.common.SolrException.ErrorCode;
+import org.apache.solr.common.util.NamedList;
+
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.ObjectInputStream;
+import java.io.ObjectOutputStream;
+import java.io.Serializable;
+
+
+/**
+ * 
+ * 
+ * @since solr 1.3
+ */
+public abstract class SolrResponse implements Serializable {
+  public abstract long getElapsedTime();
+  
+  public abstract void setResponse(NamedList<Object> rsp);
+
+  public abstract void setElapsedTime(long elapsedTime);
+  
+  public abstract NamedList<Object> getResponse();
+  
+  public static byte[] serializable(SolrResponse response) {
+    try {
+      ByteArrayOutputStream byteStream = new ByteArrayOutputStream();
+      ObjectOutputStream outputStream = new ObjectOutputStream(byteStream);
+      outputStream.writeObject(response);
+      return byteStream.toByteArray();
+    } catch (Exception e) {
+      throw new SolrException(ErrorCode.SERVER_ERROR, e);
+    }
+  }
+  
+  public static SolrResponse deserialize(byte[] bytes) {
+    try {
+      ByteArrayInputStream byteStream = new ByteArrayInputStream(bytes);
+      ObjectInputStream inputStream = new ObjectInputStream(byteStream);
+      return (SolrResponse) inputStream.readObject();
+    } catch (Exception e) {
+      throw new SolrException(ErrorCode.SERVER_ERROR, e);
+    }
+  }
+}

http://git-wip-us.apache.org/repos/asf/incubator-ranger/blob/40aa090d/ranger_solrj/src/main/java/org/apache/solr/client/solrj/SolrServer.java
----------------------------------------------------------------------
diff --git a/ranger_solrj/src/main/java/org/apache/solr/client/solrj/SolrServer.java b/ranger_solrj/src/main/java/org/apache/solr/client/solrj/SolrServer.java
new file mode 100644
index 0000000..0238214
--- /dev/null
+++ b/ranger_solrj/src/main/java/org/apache/solr/client/solrj/SolrServer.java
@@ -0,0 +1,25 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.solr.client.solrj;
+
+/**
+ * @deprecated Use {@link org.apache.solr.client.solrj.SolrClient}
+ */
+@Deprecated
+public abstract class SolrServer extends SolrClient {
+}

http://git-wip-us.apache.org/repos/asf/incubator-ranger/blob/40aa090d/ranger_solrj/src/main/java/org/apache/solr/client/solrj/SolrServerException.java
----------------------------------------------------------------------
diff --git a/ranger_solrj/src/main/java/org/apache/solr/client/solrj/SolrServerException.java b/ranger_solrj/src/main/java/org/apache/solr/client/solrj/SolrServerException.java
new file mode 100644
index 0000000..ed16a43
--- /dev/null
+++ b/ranger_solrj/src/main/java/org/apache/solr/client/solrj/SolrServerException.java
@@ -0,0 +1,54 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.solr.client.solrj;
+
+/** Exception to catch all types of communication / parsing issues associated with talking to SOLR
+ * 
+ *
+ * @since solr 1.3
+ */
+public class SolrServerException extends Exception {
+
+  private static final long serialVersionUID = -3371703521752000294L;
+  
+  public SolrServerException(String message, Throwable cause) {
+    super(message, cause);
+  }
+
+  public SolrServerException(String message) {
+    super(message);
+  }
+
+  public SolrServerException(Throwable cause) {
+    super(cause);
+  }
+  
+  public Throwable getRootCause() {
+    Throwable t = this;
+    while (true) {
+      Throwable cause = t.getCause();
+      if (cause!=null) {
+        t = cause;
+      } else {
+        break;
+      }
+    }
+    return t;
+  }
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-ranger/blob/40aa090d/ranger_solrj/src/main/java/org/apache/solr/client/solrj/StreamingResponseCallback.java
----------------------------------------------------------------------
diff --git a/ranger_solrj/src/main/java/org/apache/solr/client/solrj/StreamingResponseCallback.java b/ranger_solrj/src/main/java/org/apache/solr/client/solrj/StreamingResponseCallback.java
new file mode 100644
index 0000000..2ba79c8
--- /dev/null
+++ b/ranger_solrj/src/main/java/org/apache/solr/client/solrj/StreamingResponseCallback.java
@@ -0,0 +1,37 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.solr.client.solrj;
+
+import org.apache.solr.common.SolrDocument;
+
+/**
+ * A callback interface for streaming response
+ * 
+ * @since solr 4.0
+ */
+public abstract class StreamingResponseCallback {
+  /*
+   * Called for each SolrDocument in the response
+   */
+  public abstract void streamSolrDocument( SolrDocument doc );
+
+  /*
+   * Called at the beginning of each DocList (and SolrDocumentList)
+   */
+  public abstract void streamDocListInfo( long numFound, long start, Float maxScore );
+}

http://git-wip-us.apache.org/repos/asf/incubator-ranger/blob/40aa090d/ranger_solrj/src/main/java/org/apache/solr/client/solrj/beans/BindingException.java
----------------------------------------------------------------------
diff --git a/ranger_solrj/src/main/java/org/apache/solr/client/solrj/beans/BindingException.java b/ranger_solrj/src/main/java/org/apache/solr/client/solrj/beans/BindingException.java
new file mode 100644
index 0000000..cd10138
--- /dev/null
+++ b/ranger_solrj/src/main/java/org/apache/solr/client/solrj/beans/BindingException.java
@@ -0,0 +1,29 @@
+package org.apache.solr.client.solrj.beans;
+
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+public class BindingException extends RuntimeException {
+
+  public BindingException(String message) {
+    super(message);
+  }
+
+  public BindingException(String message, Throwable cause) {
+    super(message, cause);
+  }
+}

http://git-wip-us.apache.org/repos/asf/incubator-ranger/blob/40aa090d/ranger_solrj/src/main/java/org/apache/solr/client/solrj/beans/DocumentObjectBinder.java
----------------------------------------------------------------------
diff --git a/ranger_solrj/src/main/java/org/apache/solr/client/solrj/beans/DocumentObjectBinder.java b/ranger_solrj/src/main/java/org/apache/solr/client/solrj/beans/DocumentObjectBinder.java
new file mode 100644
index 0000000..bff6c6a
--- /dev/null
+++ b/ranger_solrj/src/main/java/org/apache/solr/client/solrj/beans/DocumentObjectBinder.java
@@ -0,0 +1,470 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.solr.client.solrj.beans;
+
+import org.apache.solr.common.SolrDocumentList;
+import org.apache.solr.common.SolrDocument;
+import org.apache.solr.common.SolrInputDocument;
+
+import java.lang.reflect.*;
+import java.util.*;
+import java.util.regex.Pattern;
+import java.util.concurrent.ConcurrentHashMap;
+import java.nio.ByteBuffer;
+
+/**
+ * A class to map objects to and from solr documents.
+ *
+ *
+ * @since solr 1.3
+ */
+public class DocumentObjectBinder {
+
+  private final Map<Class, List<DocField>> infocache = new ConcurrentHashMap<>();
+
+  public DocumentObjectBinder() {
+  }
+
+  public <T> List<T> getBeans(Class<T> clazz, SolrDocumentList solrDocList) {
+    List<DocField> fields = getDocFields(clazz);
+    List<T> result = new ArrayList<>(solrDocList.size());
+
+    for (SolrDocument sdoc : solrDocList) {
+      result.add(getBean(clazz, fields, sdoc));
+    }
+    return result;
+  }
+
+  public <T> T getBean(Class<T> clazz, SolrDocument solrDoc) {
+    return getBean(clazz, null, solrDoc);
+  }
+
+  private <T> T getBean(Class<T> clazz, List<DocField> fields, SolrDocument solrDoc) {
+    if (fields == null) {
+      fields = getDocFields(clazz);
+    }
+
+    try {
+      T obj = clazz.newInstance();
+      for (DocField docField : fields) {
+        docField.inject(obj, solrDoc);
+      }
+      return obj;
+    } catch (Exception e) {
+      throw new BindingException("Could not instantiate object of " + clazz, e);
+    }
+  }
+
+  public SolrInputDocument toSolrInputDocument(Object obj) {
+    List<DocField> fields = getDocFields(obj.getClass());
+    if (fields.isEmpty()) {
+      throw new BindingException("class: " + obj.getClass() + " does not define any fields.");
+    }
+
+    SolrInputDocument doc = new SolrInputDocument();
+    for (DocField field : fields) {
+      if (field.dynamicFieldNamePatternMatcher != null &&
+          field.get(obj) != null &&
+          field.isContainedInMap) {
+        Map<String, Object> mapValue = (Map<String, Object>) field.get(obj);
+
+        for (Map.Entry<String, Object> e : mapValue.entrySet()) {
+          doc.setField(e.getKey(), e.getValue(), 1.0f);
+        }
+      } else {
+        if (field.child != null) {
+          addChild(obj, field, doc);
+        } else {
+          doc.setField(field.name, field.get(obj), 1.0f);
+        }
+      }
+    }
+    return doc;
+  }
+
+  private void addChild(Object obj, DocField field, SolrInputDocument doc) {
+    Object val = field.get(obj);
+    if (val == null) return;
+    if (val instanceof Collection) {
+      Collection collection = (Collection) val;
+      for (Object o : collection) {
+        SolrInputDocument child = toSolrInputDocument(o);
+        doc.addChildDocument(child);
+      }
+    } else if (val.getClass().isArray()) {
+      Object[] objs = (Object[]) val;
+      for (Object o : objs) doc.addChildDocument(toSolrInputDocument(o));
+    } else {
+      doc.addChildDocument(toSolrInputDocument(val));
+    }
+  }
+
+  private List<DocField> getDocFields(Class clazz) {
+    List<DocField> fields = infocache.get(clazz);
+    if (fields == null) {
+      synchronized(infocache) {
+        infocache.put(clazz, fields = collectInfo(clazz));
+      }
+    }
+    return fields;
+  }
+
+  private List<DocField> collectInfo(Class clazz) {
+    List<DocField> fields = new ArrayList<>();
+    Class superClazz = clazz;
+    List<AccessibleObject> members = new ArrayList<>();
+
+    while (superClazz != null && superClazz != Object.class) {
+      members.addAll(Arrays.asList(superClazz.getDeclaredFields()));
+      members.addAll(Arrays.asList(superClazz.getDeclaredMethods()));
+      superClazz = superClazz.getSuperclass();
+    }
+    boolean childFieldFound = false;
+    for (AccessibleObject member : members) {
+      if (member.isAnnotationPresent(Field.class)) {
+        member.setAccessible(true);
+        DocField df = new DocField(member);
+        if (df.child != null) {
+          if (childFieldFound)
+            throw new BindingException(clazz.getName() + " cannot have more than one Field with child=true");
+          childFieldFound = true;
+        }
+        fields.add(df);
+      }
+    }
+    return fields;
+  }
+
+  private class DocField {
+    private Field annotation;
+    private String name;
+    private java.lang.reflect.Field field;
+    private Method setter;
+    private Method getter;
+    private Class type;
+    private boolean isArray;
+    private boolean isList;
+    private List<DocField> child;
+
+    /*
+     * dynamic fields may use a Map based data structure to bind a given field.
+     * if a mapping is done using, "Map<String, List<String>> foo", <code>isContainedInMap</code>
+     * is set to <code>TRUE</code> as well as <code>isList</code> is set to <code>TRUE</code>
+     */
+    private boolean isContainedInMap;
+    private Pattern dynamicFieldNamePatternMatcher;
+
+    public DocField(AccessibleObject member) {
+      if (member instanceof java.lang.reflect.Field) {
+        field = (java.lang.reflect.Field) member;
+      } else {
+        setter = (Method) member;
+      }
+      annotation = member.getAnnotation(Field.class);
+      storeName(annotation);
+      storeType();
+
+      // Look for a matching getter
+      if (setter != null) {
+        String gname = setter.getName();
+        if (gname.startsWith("set")) {
+          gname = "get" + gname.substring(3);
+          try {
+            getter = setter.getDeclaringClass().getMethod(gname, (Class[]) null);
+          } catch (Exception ex) {
+            // no getter -- don't worry about it...
+            if (type == Boolean.class) {
+              gname = "is" + setter.getName().substring(3);
+              try {
+                getter = setter.getDeclaringClass().getMethod(gname, (Class[]) null);
+              } catch(Exception ex2) {
+                // no getter -- don't worry about it...
+              }
+            }
+          }
+        }
+      }
+    }
+
+    private void storeName(Field annotation) {
+      if (annotation.value().equals(DEFAULT)) {
+        if (field != null) {
+          name = field.getName();
+        } else {
+          String setterName = setter.getName();
+          if (setterName.startsWith("set") && setterName.length() > 3) {
+            name = setterName.substring(3, 4).toLowerCase(Locale.ROOT) + setterName.substring(4);
+          } else {
+            name = setter.getName();
+          }
+        }
+      } else if (annotation.value().indexOf('*') >= 0) { //dynamic fields are annotated as @Field("categories_*")
+        //if the field was annotated as a dynamic field, convert the name into a pattern
+        //the wildcard (*) is supposed to be either a prefix or a suffix, hence the use of replaceFirst
+        name = annotation.value().replaceFirst("\\*", "\\.*");
+        dynamicFieldNamePatternMatcher = Pattern.compile("^"+name+"$");
+      } else {
+        name = annotation.value();
+      }
+    }
+
+    private void storeType() {
+      if (field != null) {
+        type = field.getType();
+      } else {
+        Class[] params = setter.getParameterTypes();
+        if (params.length != 1) {
+          throw new BindingException("Invalid setter method. Must have one and only one parameter");
+        }
+        type = params[0];
+      }
+
+      if (type == Collection.class || type == List.class || type == ArrayList.class) {
+        isList = true;
+        if (annotation.child()) {
+          populateChild(field.getGenericType());
+        } else {
+          type = Object.class;
+        }
+      } else if (type == byte[].class) {
+        //no op
+      } else if (type.isArray()) {
+        isArray = true;
+        if (annotation.child()) {
+          populateChild(type.getComponentType());
+        } else {
+          type = type.getComponentType();
+        }
+      } else if (type == Map.class || type == HashMap.class) { //corresponding to the support for dynamicFields
+        if (annotation.child()) throw new BindingException("Map should is not a valid type for a child document");
+        isContainedInMap = true;
+        //assigned a default type
+        type = Object.class;
+        if (field != null) {
+          if (field.getGenericType() instanceof ParameterizedType) {
+            //check what are the generic values
+            ParameterizedType parameterizedType = (ParameterizedType) field.getGenericType();
+            Type[] types = parameterizedType.getActualTypeArguments();
+            if (types != null && types.length == 2 && types[0] == String.class) {
+              //the key should always be String
+              //Raw and primitive types
+              if (types[1] instanceof Class) {
+                //the value could be multivalued then it is a List, Collection, ArrayList
+                if (types[1] == Collection.class || types[1] == List.class || types[1] == ArrayList.class) {
+                  type = Object.class;
+                  isList = true;
+                } else {
+                  //else assume it is a primitive and put in the source type itself
+                  type = (Class) types[1];
+                }
+              } else if (types[1] instanceof ParameterizedType) { //Of all the Parameterized types, only List is supported
+                Type rawType = ((ParameterizedType) types[1]).getRawType();
+                if (rawType == Collection.class || rawType == List.class || rawType == ArrayList.class) {
+                  type = Object.class;
+                  isList = true;
+                }
+              } else if (types[1] instanceof GenericArrayType) { //Array types
+                type = (Class) ((GenericArrayType) types[1]).getGenericComponentType();
+                isArray = true;
+              } else { //Throw an Exception if types are not known
+                throw new BindingException("Allowed type for values of mapping a dynamicField are : " +
+                    "Object, Object[] and List");
+              }
+            }
+          }
+        }
+      } else {
+        if (annotation.child()) {
+          populateChild(type);
+        }
+      }
+    }
+
+    private void populateChild(Type typ) {
+      if (typ == null) {
+        throw new RuntimeException("no type information available for" + (field == null ? setter : field));
+      }
+      if (typ.getClass() == Class.class) {//of type class
+        type = (Class) typ;
+      } else if (typ instanceof ParameterizedType) {
+        type = (Class) ((ParameterizedType) typ).getActualTypeArguments()[0];
+      } else {
+        throw new BindingException("Invalid type information available for" + (field == null ? setter : field));
+
+      }
+      child = getDocFields(type);
+    }
+
+    /**
+     * Called by the {@link #inject} method to read the value(s) for a field
+     * This method supports reading of all "matching" fieldName's in the <code>SolrDocument</code>
+     *
+     * Returns <code>SolrDocument.getFieldValue</code> for regular fields,
+     * and <code>Map<String, List<Object>></code> for a dynamic field. The key is all matching fieldName's.
+     */
+    @SuppressWarnings("unchecked")
+    private Object getFieldValue(SolrDocument solrDocument) {
+      if (child != null) {
+        List<SolrDocument> children = solrDocument.getChildDocuments();
+        if (children == null || children.isEmpty()) return null;
+        if (isList) {
+          ArrayList list = new ArrayList(children.size());
+          for (SolrDocument c : children) {
+            list.add(getBean(type, child, c));
+          }
+          return list;
+        } else if (isArray) {
+          Object[] arr = (Object[]) Array.newInstance(type, children.size());
+          for (int i = 0; i < children.size(); i++) {
+            arr[i] = getBean(type, child, children.get(i));
+          }
+          return arr;
+
+        } else {
+          return getBean(type, child, children.get(0));
+        }
+      }
+      Object fieldValue = solrDocument.getFieldValue(name);
+      if (fieldValue != null) {
+        //this is not a dynamic field. so return the value
+        return fieldValue;
+      }
+
+      if (dynamicFieldNamePatternMatcher == null) {
+        return null;
+      }
+
+      //reading dynamic field values
+      Map<String, Object> allValuesMap = null;
+      List allValuesList = null;
+      if (isContainedInMap) {
+        allValuesMap = new HashMap<>();
+      } else {
+        allValuesList = new ArrayList();
+      }
+
+      for (String field : solrDocument.getFieldNames()) {
+        if (dynamicFieldNamePatternMatcher.matcher(field).find()) {
+          Object val = solrDocument.getFieldValue(field);
+          if (val == null) {
+            continue;
+          }
+
+          if (isContainedInMap) {
+            if (isList) {
+              if (!(val instanceof List)) {
+                List al = new ArrayList();
+                al.add(val);
+                val = al;
+              }
+            } else if (isArray) {
+              if (!(val instanceof List)) {
+                Object[] arr = (Object[]) Array.newInstance(type, 1);
+                arr[0] = val;
+                val = arr;
+              } else {
+                val = Array.newInstance(type, ((List) val).size());
+              }
+            }
+            allValuesMap.put(field, val);
+          } else {
+            if (val instanceof Collection) {
+              allValuesList.addAll((Collection) val);
+            } else {
+              allValuesList.add(val);
+            }
+          }
+        }
+      }
+      if (isContainedInMap) {
+        return allValuesMap.isEmpty() ? null : allValuesMap;
+      } else {
+        return allValuesList.isEmpty() ? null : allValuesList;
+      }
+    }
+
+    <T> void inject(T obj, SolrDocument sdoc) {
+      Object val = getFieldValue(sdoc);
+      if(val == null) {
+        return;
+      }
+
+      if (isArray && !isContainedInMap) {
+        List list;
+        if (val.getClass().isArray()) {
+          set(obj, val);
+          return;
+        } else if (val instanceof List) {
+          list = (List) val;
+        } else {
+          list = new ArrayList();
+          list.add(val);
+        }
+        set(obj, list.toArray((Object[]) Array.newInstance(type, list.size())));
+      } else if (isList && !isContainedInMap) {
+        if (!(val instanceof List)) {
+          List list = new ArrayList();
+          list.add(val);
+          val =  list;
+        }
+        set(obj, val);
+      } else if (isContainedInMap) {
+        if (val instanceof Map) {
+          set(obj,  val);
+        }
+      } else {
+        set(obj, val);
+      }
+
+    }
+
+    private void set(Object obj, Object v) {
+      if (v != null && type == ByteBuffer.class && v.getClass() == byte[].class) {
+        v = ByteBuffer.wrap((byte[]) v);
+      }
+      try {
+        if (field != null) {
+          field.set(obj, v);
+        } else if (setter != null) {
+          setter.invoke(obj, v);
+        }
+      }
+      catch (Exception e) {
+        throw new BindingException("Exception while setting value : " + v + " on " + (field != null ? field : setter), e);
+      }
+    }
+
+    public Object get(final Object obj) {
+      if (field != null) {
+        try {
+          return field.get(obj);
+        } catch (Exception e) {
+          throw new BindingException("Exception while getting value: " + field, e);
+        }
+      } else if (getter == null) {
+        throw new BindingException("Missing getter for field: " + name + " -- You can only call the 'get' for fields that have a field of 'get' method");
+      }
+
+      try {
+        return getter.invoke(obj, (Object[]) null);
+      } catch (Exception e) {
+        throw new BindingException("Exception while getting value: " + getter, e);
+      }
+    }
+  }
+  public static final String DEFAULT = "#default";
+}

http://git-wip-us.apache.org/repos/asf/incubator-ranger/blob/40aa090d/ranger_solrj/src/main/java/org/apache/solr/client/solrj/beans/Field.java
----------------------------------------------------------------------
diff --git a/ranger_solrj/src/main/java/org/apache/solr/client/solrj/beans/Field.java b/ranger_solrj/src/main/java/org/apache/solr/client/solrj/beans/Field.java
new file mode 100644
index 0000000..39f6752
--- /dev/null
+++ b/ranger_solrj/src/main/java/org/apache/solr/client/solrj/beans/Field.java
@@ -0,0 +1,38 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.solr.client.solrj.beans;
+
+import static java.lang.annotation.ElementType.*;
+import static java.lang.annotation.RetentionPolicy.RUNTIME;
+import static org.apache.solr.client.solrj.beans.DocumentObjectBinder.DEFAULT;
+
+import java.lang.annotation.Target;
+import java.lang.annotation.Retention;
+
+
+/**
+ * This class can be used to annotate a field or a setter an any class
+ * and SlrJ would help you convert to SolrInputDocument and from SolrDocument
+ *
+ * @since solr 1.3
+ */
+@Target({FIELD, METHOD})
+@Retention(RUNTIME)
+public @interface Field {
+  boolean child() default false;
+  String value() default DEFAULT;
+}

http://git-wip-us.apache.org/repos/asf/incubator-ranger/blob/40aa090d/ranger_solrj/src/main/java/org/apache/solr/client/solrj/beans/package-info.java
----------------------------------------------------------------------
diff --git a/ranger_solrj/src/main/java/org/apache/solr/client/solrj/beans/package-info.java b/ranger_solrj/src/main/java/org/apache/solr/client/solrj/beans/package-info.java
new file mode 100644
index 0000000..890005f
--- /dev/null
+++ b/ranger_solrj/src/main/java/org/apache/solr/client/solrj/beans/package-info.java
@@ -0,0 +1,23 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+ 
+/** 
+ * Annotation based mapping of client objects to Solr documents.
+ */
+package org.apache.solr.client.solrj.beans;
+
+

http://git-wip-us.apache.org/repos/asf/incubator-ranger/blob/40aa090d/ranger_solrj/src/main/java/org/apache/solr/client/solrj/impl/BinaryRequestWriter.java
----------------------------------------------------------------------
diff --git a/ranger_solrj/src/main/java/org/apache/solr/client/solrj/impl/BinaryRequestWriter.java b/ranger_solrj/src/main/java/org/apache/solr/client/solrj/impl/BinaryRequestWriter.java
new file mode 100644
index 0000000..67274c2
--- /dev/null
+++ b/ranger_solrj/src/main/java/org/apache/solr/client/solrj/impl/BinaryRequestWriter.java
@@ -0,0 +1,120 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.solr.client.solrj.impl;
+
+import org.apache.solr.client.solrj.SolrRequest;
+import org.apache.solr.client.solrj.request.JavaBinUpdateRequestCodec;
+import org.apache.solr.client.solrj.request.RequestWriter;
+import org.apache.solr.client.solrj.request.UpdateRequest;
+import org.apache.solr.common.util.ContentStream;
+
+import java.io.*;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.List;
+
+/**
+ * A RequestWriter which writes requests in the javabin format
+ *
+ *
+ * @see org.apache.solr.client.solrj.request.RequestWriter
+ * @since solr 1.4
+ */
+public class BinaryRequestWriter extends RequestWriter {
+
+  @Override
+  public Collection<ContentStream> getContentStreams(SolrRequest req) throws IOException {
+    if (req instanceof UpdateRequest) {
+      UpdateRequest updateRequest = (UpdateRequest) req;
+      if (isNull(updateRequest.getDocuments()) &&
+              isNull(updateRequest.getDeleteByIdMap()) &&
+              isNull(updateRequest.getDeleteQuery())
+              && (updateRequest.getDocIterator() == null) ) {
+        return null;
+      }
+      List<ContentStream> l = new ArrayList<>();
+      l.add(new LazyContentStream(updateRequest));
+      return l;
+    } else {
+      return super.getContentStreams(req);
+    }
+
+  }
+
+
+  @Override
+  public String getUpdateContentType() {
+    return "application/javabin";
+  }
+
+  @Override
+  public ContentStream getContentStream(final UpdateRequest request) throws IOException {
+    final BAOS baos = new BAOS();
+    new JavaBinUpdateRequestCodec().marshal(request, baos);
+    
+    return new ContentStream() {
+      @Override
+      public String getName() {
+        return null;
+      }
+
+      @Override
+      public String getSourceInfo() {
+        return "javabin";
+      }
+
+      @Override
+      public String getContentType() {
+        return "application/javabin";
+      }
+
+      @Override
+      public Long getSize() // size if we know it, otherwise null
+      {
+        return new Long(baos.size());
+      }
+
+      @Override
+      public InputStream getStream() {
+        return new ByteArrayInputStream(baos.getbuf(), 0, baos.size());
+      }
+
+      @Override
+      public Reader getReader() {
+        throw new RuntimeException("No reader available . this is a binarystream");
+      }
+    };
+  }
+
+
+  @Override
+  public void write(SolrRequest request, OutputStream os) throws IOException {
+    if (request instanceof UpdateRequest) {
+      UpdateRequest updateRequest = (UpdateRequest) request;
+      new JavaBinUpdateRequestCodec().marshal(updateRequest, os);
+    }
+  }
+  
+  /*
+   * A hack to get access to the protected internal buffer and avoid an additional copy
+   */
+  class BAOS extends ByteArrayOutputStream {
+    byte[] getbuf() {
+      return super.buf;
+    }
+  }
+}

http://git-wip-us.apache.org/repos/asf/incubator-ranger/blob/40aa090d/ranger_solrj/src/main/java/org/apache/solr/client/solrj/impl/BinaryResponseParser.java
----------------------------------------------------------------------
diff --git a/ranger_solrj/src/main/java/org/apache/solr/client/solrj/impl/BinaryResponseParser.java b/ranger_solrj/src/main/java/org/apache/solr/client/solrj/impl/BinaryResponseParser.java
new file mode 100644
index 0000000..4f3caf1
--- /dev/null
+++ b/ranger_solrj/src/main/java/org/apache/solr/client/solrj/impl/BinaryResponseParser.java
@@ -0,0 +1,64 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.solr.client.solrj.impl;
+
+import org.apache.solr.client.solrj.ResponseParser;
+import org.apache.solr.common.SolrException;
+import org.apache.solr.common.util.NamedList;
+import org.apache.solr.common.util.JavaBinCodec;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.Reader;
+
+/**
+ *
+ * @since solr 1.3
+ */
+public class BinaryResponseParser extends ResponseParser {
+  public static final String BINARY_CONTENT_TYPE = "application/octet-stream";
+  
+  @Override
+  public String getWriterType() {
+    return "javabin";
+  }
+
+  @Override
+  public NamedList<Object> processResponse(InputStream body, String encoding) {
+    try {
+      return (NamedList<Object>) new JavaBinCodec().unmarshal(body);
+    } catch (IOException e) {
+      throw new SolrException(SolrException.ErrorCode.SERVER_ERROR, "parsing error", e);
+
+    }
+  }
+
+  @Override
+  public String getContentType() {
+    return BINARY_CONTENT_TYPE;
+  }
+
+  @Override
+  public String getVersion() {
+    return "2";
+  }
+
+  @Override
+  public NamedList<Object> processResponse(Reader reader) {
+    throw new RuntimeException("Cannot handle character stream");
+  }
+}