private Object parseMessage() {
    // Consume SOAP message, if any
    // TODO: Add a SOAP handler in Parser.java
    if (soapAction != null) {
      try {
        MimeHeaders mime_headers = new MimeHeaders();

        for (Object k : headers.getIds()) {
          if (k instanceof String) {
            String name = (String) k;
            String value = Context.toString(ScriptableObject.getProperty(headers, name));

            mime_headers.addHeader(name, value);
          }
        }

        return MessageFactory.newInstance(SOAPConstants.DYNAMIC_SOAP_PROTOCOL)
            .createMessage(mime_headers, request.getInputStream());
      } catch (IOException ex) {
        throw new ESXXException("Unable to read SOAP message stream: " + ex.getMessage());
      } catch (SOAPException ex) {
        throw new ESXXException(400 /* Bad Request */, "Invalid SOAP message: " + ex.getMessage());
      } finally {
        try {
          request.getInputStream().close();
        } catch (Exception ignored) {
        }
      }
    } else if (contentType != null && contentLength > 0) {
      try {
        ESXX esxx = ESXX.getInstance();
        return esxx.parseStream(
            contentType,
            request.getInputStream(),
            URI.create("urn:x-esxx:incoming-request-entity"),
            null,
            new java.io.PrintWriter(request.getErrorWriter()),
            Context.getCurrentContext(),
            this);
      } catch (Exception ex) {
        throw new ESXXException(
            400 /* Bad Request */, "Unable to parse request entity: " + ex.getMessage(), ex);
      } finally {
        try {
          request.getInputStream().close();
        } catch (Exception ignored) {
        }
      }
    } else {
      // Return a dummy object
      return Context.getCurrentContext().newObject(this);
    }
  }
  private void handleAcceptHeader(String hdr, String value, Context cx, Scriptable accept) {
    String subname;

    if (hdr.equals("Accept")) {
      subname = "media";
    } else if (hdr.startsWith("Accept-")) {
      subname = hdr.substring(7).toLowerCase();
    } else {
      // Do nothing
      return;
    }

    Map<Double, List<Scriptable>> objects = new TreeMap<Double, List<Scriptable>>();

    String[] values = value.split(",");

    for (String v : values) {
      double q = 1.0;
      double w = 0.0;
      String[] parts = v.split(";");

      Scriptable object = cx.newObject(accept);
      object.put("valueOf", object, acceptValueOf);
      object.put("value", object, parts[0].trim());

      // Add all attributes
      for (int i = 1; i < parts.length; ++i) {
        String[] attr = parts[i].split("=", 2);

        if (attr.length == 2) {
          // Parse Q factor
          if (attr[0].trim().equals("q")) {
            q = Double.parseDouble(attr[1].trim());
          } else {
            object.put(attr[0].trim(), object, attr[1].trim());
          }
        }
      }

      object.put("q", object, "" + q);

      // Calculate implicit weight
      if (parts[0].trim().equals("*/*")) {
        w = 0.0000;
      } else if (parts[0].trim().endsWith("/*")) {
        w = 0.0001;
      } else {
        w = 0.0002;
      }

      // Attributes give extra points
      w += parts.length * 0.00001;

      // Add to tree multi-map, inverse order
      double key = -(q + w);

      List<Scriptable> l = objects.get(key);

      if (l == null) {
        l = new ArrayList<Scriptable>();
        objects.put(key, l);
      }

      l.add(object);
    }

    Scriptable object = cx.newArray(accept, objects.size());
    accept.put(subname, accept, object);

    int i = 0;
    for (List<Scriptable> l : objects.values()) {
      for (Scriptable s : l) {
        object.put(i++, object, s);
      }
    }
  }
 @SuppressWarnings("unused")
 private static Object acceptValueOf(
     Context cx, Scriptable thisObj, Object[] args, Function funObj) {
   return thisObj.get("value", thisObj);
 }