diff --git a/Apache_Solr_Document.php b/Apache_Solr_Document.php
new file mode 100644
index 0000000..514857b
--- /dev/null
+++ b/Apache_Solr_Document.php
@@ -0,0 +1,387 @@
+<?php
+/**
+ * Copyright (c) 2007-2009, Conduit Internet Technologies, Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ *  - Redistributions of source code must retain the above copyright notice,
+ *    this list of conditions and the following disclaimer.
+ *  - Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *  - Neither the name of Conduit Internet Technologies, Inc. nor the names of
+ *    its contributors may be used to endorse or promote products derived from
+ *    this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ *
+ * @copyright Copyright 2007-2009 Conduit Internet Technologies, Inc. (http://conduit-it.com)
+ * @license New BSD (http://solr-php-client.googlecode.com/svn/trunk/COPYING)
+ * @version $Id: Document.php 15 2009-08-04 17:53:08Z donovan.jimenez $
+ *
+ * @package Apache
+ * @subpackage Solr
+ * @author Donovan Jimenez <djimenez@conduit-it.com>
+ */
+
+/**
+ * Holds Key / Value pairs that represent a Solr Document along with any associated boost
+ * values. Field values can be accessed by direct dereferencing such as:
+ * <code>
+ * ...
+ * $document->title = 'Something';
+ * echo $document->title;
+ * ...
+ * </code>
+ *
+ * Additionally, the field values can be iterated with foreach
+ *
+ * <code>
+ * foreach ($document as $fieldName => $fieldValue)
+ * {
+ * ...
+ * }
+ * </code>
+ */
+class Apache_Solr_Document implements IteratorAggregate {
+
+  /**
+   * Document boost value
+   *
+   * @var float
+   */
+  protected $_documentBoost = FALSE;
+
+  /**
+   * Document field values, indexed by name
+   *
+   * @var array
+   */
+  protected $_fields = array();
+
+  /**
+   * Document field boost values, indexed by name
+   *
+   * @var array array of floats
+   */
+  protected $_fieldBoosts = array();
+
+  /**
+   * Clear all boosts and fields from this document
+   */
+  public function clear() {
+    $this->_documentBoost = FALSE;
+
+    $this->_fields = array();
+    $this->_fieldBoosts = array();
+  }
+
+  /**
+   * Get current document boost
+   *
+   * @return mixed will be false for default, or else a float
+   */
+  public function getBoost() {
+    return $this->_documentBoost;
+  }
+
+  /**
+   * Set document boost factor
+   *
+   * @param mixed $boost Use false for default boost, else cast to float that should be > 0 or will be treated as false
+   */
+  public function setBoost($boost) {
+    $boost = (float) $boost;
+
+    if ($boost > 0.0) {
+      $this->_documentBoost = $boost;
+    }
+    else {
+      $this->_documentBoost = FALSE;
+    }
+  }
+
+  /**
+   * Add a value to a multi-valued field
+   *
+   * NOTE: the solr XML format allows you to specify boosts
+   * PER value even though the underlying Lucene implementation
+   * only allows a boost per field. To remedy this, the final
+   * field boost value will be the product of all specified boosts
+   * on field values - this is similar to SolrJ's functionality.
+   *
+   * <code>
+   * $doc = new Apache_Solr_Document();
+   *
+   * $doc->addField('foo', 'bar', 2.0);
+   * $doc->addField('foo', 'baz', 3.0);
+   *
+   * // resultant field boost will be 6!
+   * echo $doc->getFieldBoost('foo');
+   * </code>
+   *
+   * @param string $key
+   * @param mixed $value
+   * @param mixed $boost Use false for default boost, else cast to float that should be > 0 or will be treated as false
+   */
+  public function addField($key, $value, $boost = FALSE) {
+    if (!isset($this->_fields[$key])) {
+      // create holding array if this is the first value
+      $this->_fields[$key] = array();
+    }
+    else if (!is_array($this->_fields[$key])) {
+      // move existing value into array if it is not already an array
+      $this->_fields[$key] = array($this->_fields[$key]);
+    }
+
+    if ($this->getFieldBoost($key) === FALSE) {
+      // boost not already set, set it now
+      $this->setFieldBoost($key, $boost);
+    }
+    else if ((float) $boost > 0.0) {
+      // multiply passed boost with current field boost - similar to SolrJ implementation
+      $this->_fieldBoosts[$key] *= (float) $boost;
+    }
+
+    // add value to array
+    $this->_fields[$key][] = $value;
+  }
+
+  /**
+   * Handle the array manipulation for a multi-valued field
+   *
+   * @param string $key
+   * @param string $value
+   * @param mixed $boost Use false for default boost, else cast to float that should be > 0 or will be treated as false
+   *
+   * @deprecated Use addField(...) instead
+   */
+  public function setMultiValue($key, $value, $boost = FALSE) {
+    $this->addField($key, $value, $boost);
+  }
+
+  /**
+   * Get field information
+   *
+   * @param string $key
+   * @return mixed associative array of info if field exists, false otherwise
+   */
+  public function getField($key) {
+    if (isset($this->_fields[$key])) {
+      return array(
+        'name' => $key,
+        'value' => $this->_fields[$key],
+        'boost' => $this->getFieldBoost($key)
+      );
+    }
+
+    return FALSE;
+  }
+
+  /**
+   * Set a field value. Multi-valued fields should be set as arrays
+   * or instead use the addField(...) function which will automatically
+   * make sure the field is an array.
+   *
+   * @param string $key
+   * @param mixed $value
+   * @param mixed $boost Use false for default boost, else cast to float that should be > 0 or will be treated as false
+   */
+  public function setField($key, $value, $boost = FALSE) {
+    $this->_fields[$key] = $value;
+    $this->setFieldBoost($key, $boost);
+  }
+
+  /**
+   * Get the currently set field boost for a document field
+   *
+   * @param string $key
+   * @return float currently set field boost, false if one is not set
+   */
+  public function getFieldBoost($key) {
+    return isset($this->_fieldBoosts[$key]) ? $this->_fieldBoosts[$key] : FALSE;
+  }
+
+  /**
+   * Set the field boost for a document field
+   *
+   * @param string $key field name for the boost
+   * @param mixed $boost Use false for default boost, else cast to float that should be > 0 or will be treated as false
+   */
+  public function setFieldBoost($key, $boost) {
+    $boost = (float) $boost;
+
+    if ($boost > 0.0) {
+      $this->_fieldBoosts[$key] = $boost;
+    }
+    else {
+      $this->_fieldBoosts[$key] = FALSE;
+    }
+  }
+
+  /**
+   * Return current field boosts, indexed by field name
+   *
+   * @return array
+   */
+  public function getFieldBoosts() {
+    return $this->_fieldBoosts;
+  }
+
+  /**
+   * Get the names of all fields in this document
+   *
+   * @return array
+   */
+  public function getFieldNames() {
+    return array_keys($this->_fields);
+  }
+
+  /**
+   * Get the values of all fields in this document
+   *
+   * @return array
+   */
+  public function getFieldValues() {
+    return array_values($this->_fields);
+  }
+
+  /**
+   * IteratorAggregate implementation function. Allows usage:
+   *
+   * <code>
+   * foreach ($document as $key => $value)
+   * {
+   *   ...
+   * }
+   * </code>
+   */
+  public function getIterator() {
+    $arrayObject = new ArrayObject($this->_fields);
+
+    return $arrayObject->getIterator();
+  }
+
+  /**
+   * Magic get for field values
+   *
+   * @param string $key
+   * @return mixed
+   */
+  public function __get($key) {
+    return $this->_fields[$key];
+  }
+
+  /**
+   * Magic set for field values. Multi-valued fields should be set as arrays
+   * or instead use the addField(...) function which will automatically
+   * make sure the field is an array.
+   *
+   * @param string $key
+   * @param mixed $value
+   */
+  public function __set($key, $value) {
+    $this->setField($key, $value);
+  }
+
+  /**
+   * Magic isset for fields values.  Do not call directly. Allows usage:
+   *
+   * <code>
+   * isset($document->some_field);
+   * </code>
+   *
+   * @param string $key
+   * @return boolean
+   */
+  public function __isset($key) {
+    return isset($this->_fields[$key]);
+  }
+
+  /**
+   * Magic unset for field values. Do not call directly. Allows usage:
+   *
+   * <code>
+   * unset($document->some_field);
+   * </code>
+   *
+   * @param string $key
+   */
+  public function __unset($key) {
+    unset($this->_fields[$key]);
+    unset($this->_fieldBoosts[$key]);
+  }
+
+  /**
+   * Create an XML fragment from a Apache_Solr_Document instance appropriate for use inside a Solr add call
+   *
+   * @return string
+   */
+  public static function documentToXml(Apache_Solr_Document $document) {
+    $xml = '<doc';
+
+    if ($document->getBoost() !== FALSE) {
+      $xml .= ' boost="' . $document->getBoost() . '"';
+    }
+
+    $xml .= '>';
+
+    foreach ($document as $key => $value) {
+      $key = htmlspecialchars($key, ENT_QUOTES, 'UTF-8');
+      $fieldBoost = $document->getFieldBoost($key);
+
+      if (is_array($value)) {
+        foreach ($value as $multivalue) {
+          $xml .= '<field name="' . $key . '"';
+
+          if ($fieldBoost !== FALSE) {
+            $xml .= ' boost="' . $fieldBoost . '"';
+
+            // Only set the boost for the first field in the set
+            $fieldBoost = FALSE;
+          }
+
+          $xml .= '>' . htmlspecialchars($multivalue, ENT_NOQUOTES, 'UTF-8') . '</field>';
+        }
+      }
+      else {
+        $xml .= '<field name="' . $key . '"';
+
+        if ($fieldBoost !== FALSE) {
+          $xml .= ' boost="' . $fieldBoost . '"';
+        }
+
+        $xml .= '>' . htmlspecialchars($value, ENT_NOQUOTES, 'UTF-8') . '</field>';
+      }
+    }
+
+    $xml .= '</doc>';
+
+    // Remove any control characters to avoid Solr XML parser exception
+    return self::stripCtrlChars($xml);
+  }
+
+  /**
+   * Replace control (non-printable) characters from string that are invalid to Solr's XML parser with a space.
+   *
+   * @param string $string
+   * @return string
+   */
+  public static function stripCtrlChars($string) {
+    // See:  http://w3.org/International/questions/qa-forms-utf-8.html
+    // Printable utf-8 does not include any of these chars below x7F
+    return preg_replace('@[\x00-\x08\x0B\x0C\x0E-\x1F]@', ' ', $string);
+  }
+}
\ No newline at end of file
diff --git a/Drupal_Apache_Solr_Service.php b/Drupal_Apache_Solr_Service.php
index 7397ae1..4139667 100644
--- a/Drupal_Apache_Solr_Service.php
+++ b/Drupal_Apache_Solr_Service.php
@@ -1,33 +1,107 @@
 <?php
 
-class DrupalApacheSolrService extends Apache_Solr_Service {
+/**
+ * Copyright (c) 2007-2009, Conduit Internet Technologies, Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ *  - Redistributions of source code must retain the above copyright notice,
+ *    this list of conditions and the following disclaimer.
+ *  - Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *  - Neither the name of Conduit Internet Technologies, Inc. nor the names of
+ *    its contributors may be used to endorse or promote products derived from
+ *    this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ *
+ * @copyright Copyright 2007-2009 Conduit Internet Technologies, Inc. (http://conduit-it.com)
+ * @license New BSD (http://solr-php-client.googlecode.com/svn/trunk/COPYING)
+ * @version $Id: Service.php 22 2009-11-09 22:46:54Z donovan.jimenez $
+ *
+ * @package Apache
+ * @subpackage Solr
+ * @author Donovan Jimenez <djimenez@conduit-it.com>
+ */
+
+/**
+ * Additional code Copyright (c) 2008-2011 by Robert Douglass, James McKinney,
+ * Jacob Singh, Alejandro Garza, Peter Wolanin, and additional contributors.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, version 2, or any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program as the file LICENSE.txt; if not, please see
+ * http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt.
+ */
+
+require_once(dirname(__FILE__) . '/Apache_Solr_Document.php');
+
+/**
+ * Starting point for the Solr API. Represents a Solr server resource and has
+ * methods for pinging, adding, deleting, committing, optimizing and searching.
+ */
+
+class DrupalApacheSolrService {
+  /**
+   * How NamedLists should be formatted in the output.  This specifically effects facet counts. Valid values
+   * are 'map' (default) or 'flat'.
+   *
+   */
+  const NAMED_LIST_FORMAT = 'map';
 
-  protected $server_id;
-  protected $luke;
-  protected $luke_cid;
-  protected $stats;
+  /**
+   * Servlet mappings
+   */
+  const PING_SERVLET = 'admin/ping';
+  const UPDATE_SERVLET = 'update';
+  const SEARCH_SERVLET = 'select';
   const LUKE_SERVLET = 'admin/luke';
   const STATS_SERVLET = 'admin/stats.jsp';
 
   /**
-   * Whether {@link Apache_Solr_Response} objects should create {@link Apache_Solr_Document}s in
-   * the returned parsed data
-   *
-   * @var boolean
+   * Server identification strings
    *
-   * @override to FALSE by default.
+   * @var string
    */
-  protected $_createDocuments = FALSE;
+  protected $_host, $_port, $_path;
 
   /**
-   * Whether {@link Apache_Solr_Response} objects should have multivalue fields with only a single value
-   * collapsed to appear as a single value would.
+   * Constructed servlet full path URLs
    *
-   * @var boolean
+   * @var string
+   */
+  protected $_pingUrl, $_updateUrl, $_searchUrl;
+
+  /**
+   * Default HTTP timeout when one is not specified (initialized to default_socket_timeout ini setting)
    *
-   * @override to FALSE by default
+   * var float
    */
-  protected $_collapseSingleValueArrays = FALSE;
+  protected $_defaultTimeout;
+  protected $server_id;
+  protected $luke;
+  protected $stats;
 
   /**
    * Call the /admin/ping servlet, to test the connection to the server.
@@ -44,10 +118,9 @@ class DrupalApacheSolrService extends Apache_Solr_Service {
       $timeout = -1;
     }
     // Attempt a HEAD request to the solr ping url.
-    list($data, $headers) = $this->_makeHttpRequest($this->_pingUrl, 'HEAD', array(), NULL, $timeout);
-    $response = new Apache_Solr_Response($data, $headers);
+    $response = $this->_makeHttpRequest($this->_pingUrl, 'HEAD', array(), NULL, $timeout);
 
-    if ($response->getHttpStatus() == 200) {
+    if ($response->code == 200) {
       // Add 0.1 ms to the ping time so we never return 0.0.
       return microtime(TRUE) - $start + 0.0001;
     }
@@ -61,9 +134,17 @@ class DrupalApacheSolrService extends Apache_Solr_Service {
    */
   protected function setLuke($num_terms = 0) {
     if (empty($this->luke[$num_terms])) {
-      $url = $this->_constructUrl(self::LUKE_SERVLET, array('numTerms' => "$num_terms", 'wt' => self::SOLR_WRITER));
+      $url = $this->_constructUrl(self::LUKE_SERVLET, array('numTerms' => "$num_terms", 'wt' => 'json'));
+      $cid = $this->server_id . ":luke:" . drupal_hash_base64($url);
+      $cache = cache_get($cid, 'cache_apachesolr');
+      if (isset($cache->data)) {
+        $this->luke = $cache->data;
+      }
+    }
+    // Second pass to populate the cache if necessary.
+    if (empty($this->luke[$num_terms])) {
       $this->luke[$num_terms] = $this->_sendRawGet($url);
-      cache_set($this->luke_cid, $this->luke, 'cache_apachesolr');
+      cache_set($cid, $this->luke, 'cache_apachesolr');
     }
   }
 
@@ -99,8 +180,8 @@ class DrupalApacheSolrService extends Apache_Solr_Service {
       }
       else {
         $response = $this->_sendRawGet($url);
-        $this->stats = simplexml_load_string($response->getRawResponse());
-        cache_set($this->stats_cid, $response->getRawResponse(), 'cache_apachesolr');
+        $this->stats = simplexml_load_string($response->data);
+        cache_set($this->stats_cid, $response->data, 'cache_apachesolr');
       }
     }
   }
@@ -176,26 +257,6 @@ class DrupalApacheSolrService extends Apache_Solr_Service {
   }
 
   /**
-   * Clear the cache whenever we commit changes.
-   *
-   * @see Apache_Solr_Service::commit()
-   */
-  public function commit($optimize = TRUE, $waitFlush = TRUE, $waitSearcher = TRUE, $timeout = 3600) {
-    parent::commit($optimize, $waitFlush, $waitSearcher, $timeout);
-    $this->_clearCache();
-  }
-
-  /**
-   * Construct the Full URLs for the three servlets we reference
-   *
-   * @see Apache_Solr_Service::_initUrls()
-   */
-  protected function _initUrls() {
-    parent::_initUrls();
-    $this->_lukeUrl = $this->_constructUrl(self::LUKE_SERVLET, array('numTerms' => '0', 'wt' => self::SOLR_WRITER));
-  }
-
-  /**
    * Make a request to a servlet (a path) that's not a standard path.
    *
    * @param string $servlet
@@ -227,18 +288,17 @@ class DrupalApacheSolrService extends Apache_Solr_Service {
     }
     // Add default params.
     $params += array(
-      'wt' => self::SOLR_WRITER,
+      'wt' => 'json',
     );
 
     $url = $this->_constructUrl($servlet, $params);
-    list($data, $headers) = $this->_makeHttpRequest($url, $method, $request_headers, $rawPost, $timeout);
-    $response = new Apache_Solr_Response($data, $headers, $this->_createDocuments, $this->_collapseSingleValueArrays);
-    $code = (int) $response->getHttpStatus();
+    $response = $this->_makeHttpRequest($url, $method, $request_headers, $rawPost, $timeout);
+    $code = (int) $response->code;
     if ($code != 200) {
-      $message = $response->getHttpStatusMessage();
+      $message = $response->status_message;
       if ($code >= 400 && $code != 403 && $code != 404) {
         // Add details, like Solr's exception message.
-        $message .= $response->getRawResponse();
+        $message .= $response->data;
       }
       throw new Exception('"' . $code . '" Status: ' . $message);
     }
@@ -246,9 +306,7 @@ class DrupalApacheSolrService extends Apache_Solr_Service {
   }
 
   /**
-   * Put Luke meta-data from the cache into $this->luke when we instantiate.
-   *
-   * @see Apache_Solr_Service::__construct()
+   * Constructor
    */
   public function __construct($server_id, $host = 'localhost', $port = 8983, $path = '/solr/') {
     $this->server_id = $server_id;
@@ -265,11 +323,6 @@ class DrupalApacheSolrService extends Apache_Solr_Service {
     if ($this->_defaultTimeout <= 0) {
       $this->_defaultTimeout = 60;
     }
-    $this->luke_cid = $this->server_id . ":luke:" . drupal_hash_base64($this->_lukeUrl);
-    $cache = cache_get($this->luke_cid, 'cache_apachesolr');
-    if (isset($cache->data)) {
-      $this->luke = $cache->data;
-    }
   }
 
   function get_server_id() {
@@ -282,14 +335,13 @@ class DrupalApacheSolrService extends Apache_Solr_Service {
    * @see Apache_Solr_Service::_sendRawGet()
    */
   protected function _sendRawGet($url, $timeout = FALSE) {
-    list($data, $headers) = $this->_makeHttpRequest($url, 'GET', array(), '', $timeout);
-    $response = new Apache_Solr_Response($data, $headers, $this->_createDocuments, $this->_collapseSingleValueArrays);
-    $code = (int) $response->getHttpStatus();
+    $response = $this->_makeHttpRequest($url, 'GET', array(), '', $timeout);
+    $code = (int) $response->code;
     if ($code != 200) {
-      $message = $response->getHttpStatusMessage();
+      $message = $response->status_message;
       if ($code >= 400 && $code != 403 && $code != 404) {
         // Add details, like Solr's exception message.
-        $message .= $response->getRawResponse();
+        $message .= $response->data;
       }
       throw new Exception('"' . $code . '" Status: ' . $message);
     }
@@ -303,14 +355,13 @@ class DrupalApacheSolrService extends Apache_Solr_Service {
    */
   protected function _sendRawPost($url, $rawPost, $timeout = FALSE, $contentType = 'text/xml; charset=UTF-8') {
     $request_headers = array('Content-Type' => $contentType);
-    list($data, $headers) = $this->_makeHttpRequest($url, 'POST', $request_headers, $rawPost, $timeout);
-    $response = new Apache_Solr_Response($data, $headers, $this->_createDocuments, $this->_collapseSingleValueArrays);
-    $code = (int) $response->getHttpStatus();
+    $response = $this->_makeHttpRequest($url, 'POST', $request_headers, $rawPost, $timeout);
+    $code = (int) $response->code;
     if ($code != 200) {
-      $message = $response->getHttpStatusMessage();
+      $message = $response->status_message;
       if ($code >= 400 && $code != 403 && $code != 404) {
         // Add details, like Solr's exception message.
-        $message .= $response->getRawResponse();
+        $message .= $response->data;
       }
       throw new Exception('"' . $code . '" Status: ' . $message);
     }
@@ -342,14 +393,364 @@ class DrupalApacheSolrService extends Apache_Solr_Service {
 
     if (!isset($result->data)) {
       $result->data = '';
+      $result->response = NULL;
     }
-    // The headers have to be reformatted for the response class.
-    $headers[] = "{$result->protocol} {$result->code} {$result->status_message}";
-    if (isset($result->headers)) {
-      foreach ($result->headers as $name => $value) {
-        $headers[] = "$name: $value";
+    else {
+      $response = json_decode($result->data);
+      foreach ($response as $key => $value) {
+        $result->$key = $value;
       }
     }
-    return array($result->data, $headers);
+    return $result;
+  }
+
+
+  /**
+   * Escape a value for special query characters such as ':', '(', ')', '*', '?', etc.
+   *
+   * NOTE: inside a phrase fewer characters need escaped, use {@link Apache_Solr_Service::escapePhrase()} instead
+   *
+   * @param string $value
+   * @return string
+   */
+  static public function escape($value)
+  {
+    //list taken from http://lucene.apache.org/java/docs/queryparsersyntax.html#Escaping%20Special%20Characters
+    $pattern = '/(\+|-|&&|\|\||!|\(|\)|\{|}|\[|]|\^|"|~|\*|\?|:|\\\)/';
+    $replace = '\\\$1';
+
+    return preg_replace($pattern, $replace, $value);
+  }
+
+  /**
+   * Escape a value meant to be contained in a phrase for special query characters
+   *
+   * @param string $value
+   * @return string
+   */
+  static public function escapePhrase($value)
+  {
+    $pattern = '/("|\\\)/';
+    $replace = '\\\$1';
+
+    return preg_replace($pattern, $replace, $value);
+  }
+
+  /**
+   * Convenience function for creating phrase syntax from a value
+   *
+   * @param string $value
+   * @return string
+   */
+  static public function phrase($value)
+  {
+    return '"' . self::escapePhrase($value) . '"';
+  }
+
+  /**
+   * Return a valid http URL given this server's host, port and path and a provided servlet name
+   *
+   * @param string $servlet
+   * @return string
+   */
+  protected function _constructUrl($servlet, $params = array()) {
+    if (count($params)) {
+      //escape all parameters appropriately for inclusion in the query string
+      $escapedParams = array();
+
+      foreach ($params as $key => $value) {
+        $escapedParams[] = rawurlencode($key) . '=' . rawurlencode($value);
+      }
+
+      $queryString = '?' . implode('&', $escapedParams);
+    }
+    else {
+      $queryString = '';
+    }
+
+    return 'http://' . $this->_host . ':' . $this->_port . $this->_path . $servlet . $queryString;
+  }
+
+  /**
+   * Construct the Full URLs for the three servlets we reference
+   */
+  protected function _initUrls() {
+    //Initialize our full servlet URLs now that we have server information
+    $this->_pingUrl = $this->_constructUrl(self::PING_SERVLET);
+    $this->_updateUrl = $this->_constructUrl(self::UPDATE_SERVLET, array('wt' => 'json'));
+    $this->_searchUrl = $this->_constructUrl(self::SEARCH_SERVLET);
+  }
+
+
+  /**
+   * Returns the set host
+   *
+   * @return string
+   */
+  public function getHost() {
+    return $this->_host;
+  }
+
+  /**
+   * Set the host used. If empty will fallback to constants
+   *
+   * @param string $host
+   */
+  public function setHost($host) {
+    //Use the provided host or use the default
+    if (empty($host)) {
+      throw new Exception('Host parameter is empty');
+    }
+    else {
+      $this->_host = $host;
+    }
+
+    $this->_initUrls();
+  }
+
+  /**
+   * Get the set port
+   *
+   * @return integer
+   */
+  public function getPort() {
+    return $this->_port;
+  }
+
+  /**
+   * Set the port used. If empty will fallback to constants
+   *
+   * @param integer $port
+   */
+  public function setPort($port) {
+    //Use the provided port or use the default
+    $port = (int) $port;
+
+    if ($port <= 0) {
+      throw new Exception('Port is not a valid port number');
+    }
+    else {
+      $this->_port = $port;
+    }
+
+    $this->_initUrls();
+  }
+
+  /**
+   * Get the set path.
+   *
+   * @return string
+   */
+  public function getPath() {
+    return $this->_path;
+  }
+
+  /**
+   * Set the path used. If empty will fallback to constants
+   *
+   * @param string $path
+   */
+  public function setPath($path) {
+    $path = trim($path, '/');
+
+    $this->_path = '/' . $path . '/';
+
+    $this->_initUrls();
+  }
+
+  /**
+   * Raw update Method. Takes a raw post body and sends it to the update service.  Post body
+   * should be a complete and well formed xml document.
+   *
+   * @param string $rawPost
+   * @param float $timeout Maximum expected duration (in seconds)
+   *
+   * @return response object
+   *
+   * @throws Exception If an error occurs during the service call
+   */
+  public function update($rawPost, $timeout = FALSE) {
+    return $this->_sendRawPost($this->_updateUrl, $rawPost, $timeout);
+  }
+
+  /**
+   * Add an array of Solr Documents to the index all at once
+   *
+   * @param array $documents Should be an array of Apache_Solr_Document instances
+   * @param boolean $allowDups
+   * @param boolean $overwritePending
+   * @param boolean $overwriteCommitted
+   *
+   * @return response objecte
+   *
+   * @throws Exception If an error occurs during the service call
+   */
+  public function addDocuments($documents, $overwrite = NULL, $commitWithin = NULL) {
+    $attr = '';
+
+    if (isset($overwrite)) {
+      $attr .= ' overwrite="' . empty($overwrite) ? 'false"' : 'true"';
+    }
+    if (isset($commitWithin)) {
+      $attr .= ' commitWithin="' . intval($commitWithin) . '"';
+    }
+
+    $rawPost = "<add{$attr}>";
+    foreach ($documents as $document) {
+      $rawPost .= Apache_Solr_Document::documentToXml($document);
+    }
+    $rawPost .= '</add>';
+
+    return $this->update($rawPost);
+  }
+
+  /**
+   * Send a commit command.  Will be synchronous unless both wait parameters are set to false.
+   *
+   * @param boolean $optimize Defaults to true
+   * @param boolean $waitFlush Defaults to true
+   * @param boolean $waitSearcher Defaults to true
+   * @param float $timeout Maximum expected duration (in seconds) of the commit operation on the server (otherwise, will throw a communication exception). Defaults to 1 hour
+   *
+   * @return response object
+   *
+   * @throws Exception If an error occurs during the service call
+   */
+  public function commit($optimize = true, $waitFlush = true, $waitSearcher = true, $timeout = 3600) {
+    $optimizeValue = $optimize ? 'true' : 'false';
+    $flushValue = $waitFlush ? 'true' : 'false';
+    $searcherValue = $waitSearcher ? 'true' : 'false';
+
+    $rawPost = '<commit optimize="' . $optimizeValue . '" waitFlush="' . $flushValue . '" waitSearcher="' . $searcherValue . '" />';
+
+    $response = $this->update($rawPost, $timeout);
+    $this->_clearCache();
+    return $response;
+  }
+
+  /**
+   * Create a delete document based on document ID
+   *
+   * @param string $id Expected to be utf-8 encoded
+   * @param float $timeout Maximum expected duration of the delete operation on the server (otherwise, will throw a communication exception)
+   *
+   * @return response object
+   *
+   * @throws Exception If an error occurs during the service call
+   */
+  public function deleteById($id, $timeout = 3600) {
+    return $this->deleteByMultipleIds(array($id), $timeout);
+  }
+
+  /**
+   * Create and post a delete document based on multiple document IDs.
+   *
+   * @param array $ids Expected to be utf-8 encoded strings
+   * @param float $timeout Maximum expected duration of the delete operation on the server (otherwise, will throw a communication exception)
+   *
+   * @return response object
+   *
+   * @throws Exception If an error occurs during the service call
+   */
+  public function deleteByMultipleIds($ids, $timeout = 3600) {
+
+    $rawPost = '<delete>';
+
+    foreach ($ids as $id) {
+      // Escape special xml characters
+      $id = htmlspecialchars($id, ENT_NOQUOTES, 'UTF-8');
+
+      $rawPost .= '<id>' . $id . '</id>';
+    }
+
+    $rawPost .= '</delete>';
+
+    return $this->update($rawPost, $timeout);
+  }
+
+  /**
+   * Create a delete document based on a query and submit it
+   *
+   * @param string $rawQuery Expected to be utf-8 encoded
+   * @param float $timeout Maximum expected duration of the delete operation on the server (otherwise, will throw a communication exception)
+   * @return Apache_Solr_Response
+   *
+   * @throws Exception If an error occurs during the service call
+   */
+  public function deleteByQuery($rawQuery, $timeout = 3600) {
+    // Escape special xml characters
+    $rawQuery = htmlspecialchars($rawQuery, ENT_NOQUOTES, 'UTF-8');
+
+    $rawPost = '<delete><query>' . $rawQuery . '</query></delete>';
+
+    return $this->update($rawPost, $timeout);
+  }
+
+  /**
+   * Send an optimize command.  Will be synchronous unless both wait parameters are set
+   * to false.
+   *
+   * @param boolean $waitFlush
+   * @param boolean $waitSearcher
+   * @param float $timeout Maximum expected duration of the commit operation on the server (otherwise, will throw a communication exception)
+   *
+   * @return response object
+   *
+   * @throws Exception If an error occurs during the service call
+   */
+  public function optimize($waitFlush = true, $waitSearcher = true, $timeout = 3600) {
+    $flushValue = $waitFlush ? 'true' : 'false';
+    $searcherValue = $waitSearcher ? 'true' : 'false';
+
+    $rawPost = '<optimize waitFlush="' . $flushValue . '" waitSearcher="' . $searcherValue . '" />';
+
+    return $this->update($rawPost, $timeout);
+  }
+
+  /**
+   * Simple Search interface
+   *
+   * @param string $query The raw query string
+   * @param array $params key / value pairs for other query parameters (see Solr documentation), use arrays for parameter keys used more than once (e.g. facet.field)
+   *
+   * @return response object
+   *
+   * @throws Exception If an error occurs during the service call
+   */
+  public function search($query = '', $params = array(), $method = 'GET') {
+    if (!is_array($params)) {
+      $params = array();
+    }
+    // Always use JSON. See http://code.google.com/p/solr-php-client/issues/detail?id=6#c1 for reasoning
+    $params['wt'] = 'json';
+    // Additional default params.
+    $params += array(
+      'json.nl' => self::NAMED_LIST_FORMAT,
+    );
+    if ($query) {
+      $params += array(
+        'q' => $query,
+      );
+    }
+
+    // use http_build_query to encode our arguments because its faster
+    // than urlencoding all the parts ourselves in a loop
+    $queryString = http_build_query($params, NULL, '&');
+
+    // because http_build_query treats arrays differently than we want to, correct the query
+    // string by changing foo[#]=bar (# being an actual number) parameter strings to just
+    // multiple foo=bar strings. This regex should always work since '=' will be urlencoded
+    // anywhere else the regex isn't expecting it
+    $queryString = preg_replace('/%5B(?:[0-9]|[1-9][0-9]+)%5D=/', '=', $queryString);
+
+    if ($method == 'GET') {
+      return $this->_sendRawGet($this->_searchUrl . '?' . $queryString);
+    }
+    else if ($method == 'POST') {
+      return $this->_sendRawPost($this->_searchUrl, $queryString, FALSE, 'application/x-www-form-urlencoded');
+    }
+    else {
+      throw new Exception("Unsupported method '$method' for search(), use GET or POST");
+    }
   }
 }
diff --git a/Solr_Base_Query.php b/Solr_Base_Query.php
index 3bd7eeb..31efc02 100644
--- a/Solr_Base_Query.php
+++ b/Solr_Base_Query.php
@@ -520,7 +520,7 @@ class SolrBaseQuery implements DrupalSolrQueryInterface {
     if (!isset($keys)) {
       $keys = $this->rebuild_query();
     }
-    return $this->solr->search($keys, $this->params['start'], $this->params['rows'], $this->params);
+    return $this->solr->search($keys, $this->params);
   }
 
   function solr($method) {
diff --git a/apachesolr.admin.inc b/apachesolr.admin.inc
index 97d2b3e..3d5a531 100644
--- a/apachesolr.admin.inc
+++ b/apachesolr.admin.inc
@@ -724,7 +724,7 @@ function apachesolr_config_files_overview() {
   try {
     $solr = apachesolr_get_solr();
     $response = $solr->makeServletRequest('admin/file');
-    $xml = simplexml_load_string($response->getRawResponse());
+    $xml = simplexml_load_string($response->data);
   }
   catch (Exception $e) {
     watchdog('Apache Solr', nl2br(check_plain($e->getMessage())), NULL, WATCHDOG_ERROR);
@@ -755,7 +755,7 @@ function apachesolr_config_file($name) {
   try {
     $solr = apachesolr_get_solr();
     $response = $solr->makeServletRequest('admin/file', array('file' => $name));
-    $raw_file = $response->getRawResponse();
+    $raw_file = $response->data;
     $output = '<pre>' . check_plain($raw_file) . '</pre>';
     drupal_set_title(check_plain($name));
   }
diff --git a/apachesolr.info b/apachesolr.info
index 4b69f9b..413456a 100644
--- a/apachesolr.info
+++ b/apachesolr.info
@@ -9,6 +9,5 @@ files[] = apachesolr.admin.inc
 files[] = apachesolr.index.inc
 files[] = Drupal_Apache_Solr_Service.php
 files[] = Solr_Base_Query.php
-files[] = SolrPhpClient/Apache/Solr/Service.php
 files[] = tests/solr_index_and_search.test
 files[] = tests/solr_base_query.test
diff --git a/apachesolr.install b/apachesolr.install
index d98e250..92a1ce8 100644
--- a/apachesolr.install
+++ b/apachesolr.install
@@ -10,26 +10,27 @@
  */
 function apachesolr_requirements($phase) {
   $requirements = array();
-  $file_exists = file_exists(dirname(__FILE__) . '/SolrPhpClient/Apache/Solr/Service.php');
+  if ($phase != 'runtime') {
+    return $requirements;
+  }
   // Ensure translations don't break at install time
   $t = get_t();
   $has_server_settings = FALSE;
-  if ($phase == 'runtime' && $file_exists) {
-    $server_id = variable_get('apachesolr_default_server', 'solr');
-      $server = apachesolr_server_load($server_id);
-      if (!$server || empty($server['host']) || empty($server['port']) || empty($server['path'])) {
-      $requirements['apachesolr'] = array(
-        'title' => $t('Apache Solr'),
-        'value' => $t('Missing server configuration'),
-        'description' => $t('Missing or invalid Solr server record for the default server ID %id.', array('%id' => $server_id)),
-        'severity' => REQUIREMENT_ERROR,
-      );
-    }
-    else {
-      $has_server_settings = TRUE;
-    }
+  $server_id = variable_get('apachesolr_default_server', 'solr');
+    $server = apachesolr_server_load($server_id);
+    if (!$server || empty($server['host']) || empty($server['port']) || empty($server['path'])) {
+    $requirements['apachesolr'] = array(
+      'title' => $t('Apache Solr'),
+      'value' => $t('Missing server configuration'),
+      'description' => $t('Missing or invalid Solr server record for the default server ID %id.', array('%id' => $server_id)),
+      'severity' => REQUIREMENT_ERROR,
+    );
   }
-  if ($phase == 'runtime' && $has_server_settings) {
+  else {
+    $has_server_settings = TRUE;
+  }
+
+  if ($has_server_settings) {
     $ping = FALSE;
     try {
       $solr = apachesolr_get_solr($server_id);
@@ -57,37 +58,7 @@ function apachesolr_requirements($phase) {
       'severity' => $severity,
     );
   }
-  // All phases
-  $title = $t('Apache Solr PHP Client Library');
-  if ($file_exists) {
-    $expected_revision = 'Revision: 22';
-    require_once 'SolrPhpClient/Apache/Solr/Service.php';
-    $revision = defined('Apache_Solr_Service::SVN_REVISION') ? trim(Apache_Solr_Service::SVN_REVISION, ' $') : '';
-    if ($revision == $expected_revision) {
-      $severity = REQUIREMENT_OK;
-      $value = $t('Correct version "@expected".', array('@expected' => $expected_revision));
-      $description = NULL;
-    }
-    else {
-      $value = $t('Incorrect version "@version". See the instructions in README.txt.', array('@version' => $revision));
-      $description = $t('The version of the library in the SolrPhpClient directory is "@version" compared to the expected "@expected"', array('@version' => $revision, '@expected' => $expected_revision));
-      $severity = REQUIREMENT_ERROR;
-    }
-    $requirements['SolrPhpClient'] = array(
-      'title' => $title,
-      'value' => $value,
-      'description' => $description,
-      'severity' => $severity,
-    );
-  }
-  else {
-    $requirements['SolrPhpClient'] = array(
-        'title' => $title,
-        'value' => $t('<em>Missing</em>.  See the instructions in README.txt'),
-        'description' => $t('The Solr PHP library must be present in a sub-directory named SolrPhpClient.'),
-        'severity' => REQUIREMENT_ERROR,
-    );
-  }
+
   return $requirements;
 }
 
diff --git a/apachesolr_search.module b/apachesolr_search.module
index 09b2947..a49de82 100644
--- a/apachesolr_search.module
+++ b/apachesolr_search.module
@@ -572,7 +572,7 @@ function apachesolr_search_process_response($response, DrupalSolrQueryInterface
   $results = array();
   // We default to getting snippets from the body.
   $hl_fl = isset($query->params['hl.fl']) ? explode(',', $query->params['hl.fl']) : array('content');
-  $total = $response->response->numFound;
+  $total = $response->response->numFound;drupal_set_message('<pre>'.print_r($response,1));
   pager_default_initialize($total, $query->params['rows']);
   if ($total > 0) {
     foreach ($response->response->docs as $doc) {
