@Override
  public synchronized void updateEntry(final String key, final HttpCacheUpdateCallback callback)
      throws IOException, HttpCacheUpdateException {
    int numRetries = 0;
    do {
      final Element oldElement = cache.get(key);

      HttpCacheEntry existingEntry = null;
      if (oldElement != null) {
        final byte[] data = (byte[]) oldElement.getValue();
        existingEntry = serializer.readFrom(new ByteArrayInputStream(data));
      }

      final HttpCacheEntry updatedEntry = callback.update(existingEntry);

      if (existingEntry == null) {
        putEntry(key, updatedEntry);
        return;
      } else {
        // Attempt to do a CAS replace, if we fail then retry
        // While this operation should work fine within this instance, multiple instances
        //  could trample each others' data
        final ByteArrayOutputStream bos = new ByteArrayOutputStream();
        serializer.writeTo(updatedEntry, bos);
        final Element newElement = new Element(key, bos.toByteArray());
        if (cache.replace(oldElement, newElement)) {
          return;
        } else {
          numRetries++;
        }
      }
    } while (numRetries <= maxUpdateRetries);
    throw new HttpCacheUpdateException("Failed to update");
  }
 @Override
 public synchronized void putEntry(final String key, final HttpCacheEntry entry)
     throws IOException {
   final ByteArrayOutputStream bos = new ByteArrayOutputStream();
   serializer.writeTo(entry, bos);
   cache.put(new Element(key, bos.toByteArray()));
 }
  @Override
  public synchronized HttpCacheEntry getEntry(final String key) throws IOException {
    final Element e = cache.get(key);
    if (e == null) {
      return null;
    }

    final byte[] data = (byte[]) e.getValue();
    return serializer.readFrom(new ByteArrayInputStream(data));
  }