class SAXDecoder implements Decoder {

  @Override
  public Object decode(Response response, Type type) throws IOException, DecodeException {
    if (response.body() == null)
      return null;
    ContentHandlerWithResult.Factory<?> handlerFactory = handlerFactories.get(type);
    checkState(handlerFactory != null, "type %s not in configured handlers %s", type,
        handlerFactories.keySet());
    ContentHandlerWithResult<?> handler = handlerFactory.create();
    try {
      XMLReader xmlReader = XMLReaderFactory.createXMLReader();
      xmlReader.setFeature("http://xml.org/sax/features/namespaces", false);
      xmlReader.setFeature("http://xml.org/sax/features/validation", false);
      /* Explicitly control sax configuration to prevent XXE attacks */
      xmlReader.setFeature("http://xml.org/sax/features/external-general-entities", false);
      xmlReader.setFeature("http://xml.org/sax/features/external-parameter-entities", false);
      xmlReader.setFeature("http://apache.org/xml/features/disallow-doctype-decl", false);
      xmlReader.setFeature("http://apache.org/xml/features/nonvalidating/load-external-dtd", false);
      xmlReader.setContentHandler(handler);
      InputStream inputStream = response.body().asInputStream();
      try {
        xmlReader.parse(new InputSource(inputStream));
      } finally {
        ensureClosed(inputStream);
      }
      return handler.result();
    } catch (SAXException e) {
      throw new DecodeException(response.status(), e.getMessage(), response.request(), e);
    }
  }

  private  SAXDecoder(Map<Type, ContentHandlerWithResult.Factory<?>> handlerFactories);

}