text:
namespace {

// Hardcode constant to avoid any dependencies on content/.
const char kViewSourceScheme[] = "view-source";

void AdjustCursorPositionIfNecessary(size_t num_leading_chars_removed,
                                     size_t* cursor_position) {
  if (*cursor_position == base::string16::npos)
    return;
  if (num_leading_chars_removed < *cursor_position)
    *cursor_position -= num_leading_chars_removed;
  else
    *cursor_position = 0;
}

}  // namespace

AutocompleteInput::AutocompleteInput()
    : cursor_position_(base::string16::npos),
      current_page_classification_(metrics::OmniboxEventProto::INVALID_SPEC),
      type_(metrics::OmniboxInputType::INVALID),
      prevent_inline_autocomplete_(false),
      prefer_keyword_(false),
      allow_exact_keyword_match_(true),
      want_asynchronous_matches_(true) {
}

AutocompleteInput::AutocompleteInput(
    const base::string16& text,
    size_t cursor_position,
    const std::string& desired_tld,
    const GURL& current_url,
    metrics::OmniboxEventProto::PageClassification current_page_classification,
    bool prevent_inline_autocomplete,
    bool prefer_keyword,
    bool allow_exact_keyword_match,
    bool want_asynchronous_matches,
    const AutocompleteSchemeClassifier& scheme_classifier)
    : cursor_position_(cursor_position),
      current_url_(current_url),
      current_page_classification_(current_page_classification),
      prevent_inline_autocomplete_(prevent_inline_autocomplete),
      prefer_keyword_(prefer_keyword),
      allow_exact_keyword_match_(allow_exact_keyword_match),
      want_asynchronous_matches_(want_asynchronous_matches) {
  DCHECK(cursor_position <= text.length() ||
         cursor_position == base::string16::npos)
      << "Text: '" << text << "', cp: " << cursor_position;
  // None of the providers care about leading white space so we always trim it.
  // Providers that care about trailing white space handle trimming themselves.
  if ((base::TrimWhitespace(text, base::TRIM_LEADING, &text_) &
       base::TRIM_LEADING) != 0)
    AdjustCursorPositionIfNecessary(text.length() - text_.length(),
                                    &cursor_position_);

  GURL canonicalized_url;
  type_ = Parse(text_, desired_tld, scheme_classifier, &parts_, &scheme_,
                &canonicalized_url);

  if (type_ == metrics::OmniboxInputType::INVALID)
    return;

  if (((type_ == metrics::OmniboxInputType::UNKNOWN) ||
       (type_ == metrics::OmniboxInputType::URL)) &&
      canonicalized_url.is_valid() &&
      (!canonicalized_url.IsStandard() || canonicalized_url.SchemeIsFile() ||
       canonicalized_url.SchemeIsFileSystem() ||
       !canonicalized_url.host().empty()))
    canonicalized_url_ = canonicalized_url;

  size_t chars_removed = RemoveForcedQueryStringIfNecessary(type_, &text_);
  AdjustCursorPositionIfNecessary(chars_removed, &cursor_position_);
  if (chars_removed) {
    // Remove spaces between opening question mark and first actual character.
    base::string16 trimmed_text;
    if ((base::TrimWhitespace(text_, base::TRIM_LEADING, &trimmed_text) &
         base::TRIM_LEADING) != 0) {
      AdjustCursorPositionIfNecessary(text_.length() - trimmed_text.length(),
                                      &cursor_position_);
      text_ = trimmed_text;
    }
  }
}

AutocompleteInput::~AutocompleteInput() {
}

// static
size_t AutocompleteInput::RemoveForcedQueryStringIfNecessary(
    metrics::OmniboxInputType::Type type,
    base::string16* text) {
  if ((type != metrics::OmniboxInputType::FORCED_QUERY) || text->empty() ||
      (*text)[0] != L'?')
    return 0;
  // Drop the leading '?'.
  text->erase(0, 1);
  return 1;
}

// static
std::string AutocompleteInput::TypeToString(
    metrics::OmniboxInputType::Type type) {
  switch (type) {
    case metrics::OmniboxInputType::INVALID:      return "invalid";
    case metrics::OmniboxInputType::UNKNOWN:      return "unknown";
    case metrics::OmniboxInputType::DEPRECATED_REQUESTED_URL:
      return "deprecated-requested-url";
    case metrics::OmniboxInputType::URL:          return "url";
    case metrics::OmniboxInputType::QUERY:        return "query";
    case metrics::OmniboxInputType::FORCED_QUERY: return "forced-query";
  }
  return std::string();
}

// static
metrics::OmniboxInputType::Type AutocompleteInput::Parse(
    const base::string16& text,
    const std::string& desired_tld,
    const AutocompleteSchemeClassifier& scheme_classifier,
    url::Parsed* parts,
    base::string16* scheme,
    GURL* canonicalized_url) {
  size_t first_non_white = text.find_first_not_of(base::kWhitespaceUTF16, 0);
  if (first_non_white == base::string16::npos)
    return metrics::OmniboxInputType::INVALID;  // All whitespace.

  if (text[first_non_white] == L'?') {
    // If the first non-whitespace character is a '?', we magically treat this
    // as a query.
    return metrics::OmniboxInputType::FORCED_QUERY;
  }

  // Ask our parsing back-end to help us understand what the user typed.  We
  // use the URLFixerUpper here because we want to be smart about what we
  // consider a scheme.  For example, we shouldn't consider www.google.com:80
  // to have a scheme.
  url::Parsed local_parts;
  if (!parts)
    parts = &local_parts;
  const base::string16 parsed_scheme(url_fixer::SegmentURL(text, parts));
  if (scheme)
    *scheme = parsed_scheme;
  const std::string parsed_scheme_utf8(base::UTF16ToUTF8(parsed_scheme));

  // If we can't canonicalize the user's input, the rest of the autocomplete
  // system isn't going to be able to produce a navigable URL match for it.
  // So we just return QUERY immediately in these cases.
  GURL placeholder_canonicalized_url;
  if (!canonicalized_url)
    canonicalized_url = &placeholder_canonicalized_url;
  *canonicalized_url =
      url_fixer::FixupURL(base::UTF16ToUTF8(text), desired_tld);
  if (!canonicalized_url->is_valid())
    return metrics::OmniboxInputType::QUERY;

  if (LowerCaseEqualsASCII(parsed_scheme_utf8, url::kFileScheme)) {
    // A user might or might not type a scheme when entering a file URL.  In
    // either case, |parsed_scheme_utf8| will tell us that this is a file URL,
    // but |parts->scheme| might be empty, e.g. if the user typed "C:\foo".
    return metrics::OmniboxInputType::URL;
  }

  // If the user typed a scheme, and it's HTTP or HTTPS, we know how to parse it
  // well enough that we can fall through to the heuristics below.  If it's
  // something else, we can just determine our action based on what we do with
  // any input of this scheme.  In theory we could do better with some schemes
  // (e.g. "ftp" or "view-source") but I'll wait to spend the effort on that
  // until I run into some cases that really need it.
  if (parts->scheme.is_nonempty() &&
      !LowerCaseEqualsASCII(parsed_scheme_utf8, url::kHttpScheme) &&
      !LowerCaseEqualsASCII(parsed_scheme_utf8, url::kHttpsScheme)) {
    metrics::OmniboxInputType::Type type =
        scheme_classifier.GetInputTypeForScheme(parsed_scheme_utf8);
    if (type != metrics::OmniboxInputType::INVALID)
      return type;

    // We don't know about this scheme.  It might be that the user typed a
    // URL of the form "username:password@foo.com".
    const base::string16 http_scheme_prefix =
        base::ASCIIToUTF16(std::string(url::kHttpScheme) +
                           url::kStandardSchemeSeparator);
    url::Parsed http_parts;
    base::string16 http_scheme;
    GURL http_canonicalized_url;
    metrics::OmniboxInputType::Type http_type =
        Parse(http_scheme_prefix + text, desired_tld, scheme_classifier,
              &http_parts, &http_scheme, &http_canonicalized_url);
    DCHECK_EQ(std::string(url::kHttpScheme),
              base::UTF16ToUTF8(http_scheme));

    if ((http_type == metrics::OmniboxInputType::URL) &&
        http_parts.username.is_nonempty() &&
        http_parts.password.is_nonempty()) {
      // Manually re-jigger the parsed parts to match |text| (without the
      // http scheme added).
      http_parts.scheme.reset();
      url::Component* components[] = {
        &http_parts.username,
        &http_parts.password,
        &http_parts.host,
        &http_parts.port,
        &http_parts.path,
        &http_parts.query,
        &http_parts.ref,
      };
      for (size_t i = 0; i < arraysize(components); ++i) {
        url_fixer::OffsetComponent(
            -static_cast<int>(http_scheme_prefix.length()), components[i]);
      }

      *parts = http_parts;
      if (scheme)
        scheme->clear();
      *canonicalized_url = http_canonicalized_url;

      return metrics::OmniboxInputType::URL;
    }

    // We don't know about this scheme and it doesn't look like the user
    // typed a username and password.  It's likely to be a search operator
    // like "site:" or "link:".  We classify it as UNKNOWN so the user has
    // the option of treating it as a URL if we're wrong.
    // Note that SegmentURL() is smart so we aren't tricked by "c:\foo" or
    // "www.example.com:81" in this case.
    return metrics::OmniboxInputType::UNKNOWN;
  }

  // Either the user didn't type a scheme, in which case we need to distinguish
  // between an HTTP URL and a query, or the scheme is HTTP or HTTPS, in which
  // case we should reject invalid formulations.

  // If we have an empty host it can't be a valid HTTP[S] URL.  (This should
  // only trigger for input that begins with a colon, which GURL will parse as a
  // valid, non-standard URL; for standard URLs, an empty host would have
  // resulted in an invalid |canonicalized_url| above.)
  if (!canonicalized_url->has_host())
    return metrics::OmniboxInputType::QUERY;

  // Determine the host family.  We get this information by (re-)canonicalizing
  // the already-canonicalized host rather than using the user's original input,
  // in case fixup affected the result here (e.g. an input that looks like an
  // IPv4 address but with a non-empty desired TLD would return IPV4 before
  // fixup and NEUTRAL afterwards, and we want to treat it as NEUTRAL).
  url::CanonHostInfo host_info;
  net::CanonicalizeHost(canonicalized_url->host(), &host_info);

  // Check if the canonicalized host has a known TLD, which we'll want to know
  // below.
  const size_t registry_length =
      net::registry_controlled_domains::GetRegistryLength(
          canonicalized_url->host(),
          net::registry_controlled_domains::EXCLUDE_UNKNOWN_REGISTRIES,
          net::registry_controlled_domains::EXCLUDE_PRIVATE_REGISTRIES);
  DCHECK_NE(std::string::npos, registry_length);
  const bool has_known_tld = registry_length != 0;

  // See if the hostname is valid.  While IE and GURL allow hostnames to contain
  // many other characters (perhaps for weird intranet machines), it's extremely
  // unlikely that a user would be trying to type those in for anything other
  // than a search query.
  const base::string16 original_host(
      text.substr(parts->host.begin, parts->host.len));
  if ((host_info.family == url::CanonHostInfo::NEUTRAL) &&
      !net::IsCanonicalizedHostCompliant(canonicalized_url->host())) {
    // Invalid hostname.  There are several possible cases:
    // * The user is typing a multi-word query.  If we see a space anywhere in
    //   the input host we assume this is a search and return QUERY.  (We check
    //   the input string instead of canonicalized_url->host() in case fixup
    //   escaped the space.)
    // * The user is typing some garbage string.  Return QUERY.
    // * Our checker is too strict and the user is typing a real-world URL
    //   that's "invalid" but resolves.  To catch these, we return UNKNOWN when
    //   the user explicitly typed a scheme or when the hostname has a known
    //   TLD, so we'll still search by default but we'll show the accidental
    //   search infobar if necessary.
    //
    // This means we would block the following kinds of navigation attempts:
    // * Navigations to a hostname with spaces
    // * Navigations to a hostname with invalid characters and an unknown TLD
    // These might be possible in intranets, but we're not going to support them
    // without concrete evidence that doing so is necessary.
    return (parts->scheme.is_nonempty() ||
        (has_known_tld && (original_host.find(' ') == base::string16::npos))) ?
        metrics::OmniboxInputType::UNKNOWN : metrics::OmniboxInputType::QUERY;
  }

  // For hostnames that look like IP addresses, distinguish between IPv6
  // addresses, which are basically guaranteed to be navigations, and IPv4
  // addresses, which are much fuzzier.
  if (host_info.family == url::CanonHostInfo::IPV6)
    return metrics::OmniboxInputType::URL;
  if (host_info.family == url::CanonHostInfo::IPV4) {
    // The host may be a real IP address, or something that looks a bit like it
    // (e.g. "1.2" or "3232235521").  We check whether it was convertible to an
    // IP with a non-zero first octet; IPs with first octet zero are "source
    // IPs" and are almost never navigable as destination addresses.
    //
    // The one exception to this is 0.0.0.0; on many systems, attempting to
    // navigate to this IP actually navigates to localhost.  To support this
    // case, when the converted IP is 0.0.0.0, we go ahead and run the "did the
    // user actually type four components" test in the conditional below, so
    // that we'll allow explicit attempts to navigate to "0.0.0.0".  If the
    // input was anything else (e.g. "0"), we'll fall through to returning QUERY
    // afterwards.
    if ((host_info.address[0] != 0) ||
        ((host_info.address[1] == 0) && (host_info.address[2] == 0) &&
         (host_info.address[3] == 0))) {
      // This is theoretically a navigable IP.  We have four cases.  The first
      // three are:
      // * If the user typed four distinct components, this is an IP for sure.
      // * If the user typed two or three components, this is almost certainly a
      //   query, especially for two components (as in "13.5/7.25"), but we'll
      //   allow navigation for an explicit scheme or trailing slash below.
      // * If the user typed one component, this is likely a query, but could be
      //   a non-dotted-quad version of an IP address.
      // Unfortunately, since we called CanonicalizeHost() on the
      // already-canonicalized host, all of these cases will have been changed
      // to have four components (e.g. 13.2 -> 13.0.0.2), so we have to call
      // CanonicalizeHost() again, this time on the original input, so that we
      // can get the correct number of IP components.
      //
      // The fourth case is that the user typed something ambiguous like ".1.2"
      // that fixup converted to an IP address ("1.0.0.2").  In this case the
      // call to CanonicalizeHost() will return NEUTRAL here.  Since it's not
      // clear what the user intended, we fall back to our other heuristics.
      net::CanonicalizeHost(base::UTF16ToUTF8(original_host), &host_info);
      if ((host_info.family == url::CanonHostInfo::IPV4) &&
          (host_info.num_ipv4_components == 4))
        return metrics::OmniboxInputType::URL;
    }

    // By this point, if we have an "IP" with first octet zero, we know it
    // wasn't "0.0.0.0", so mark it as non-navigable.
    if (host_info.address[0] == 0)
      return metrics::OmniboxInputType::QUERY;
  }

  // Now that we've ruled out all schemes other than http or https and done a
  // little more sanity checking, the presence of a scheme means this is likely
  // a URL.
  if (parts->scheme.is_nonempty())
    return metrics::OmniboxInputType::URL;

  // Trailing slashes force the input to be treated as a URL.
  if (parts->path.is_nonempty()) {
    base::char16 c = text[parts->path.end() - 1];
    if ((c == '\\') || (c == '/'))
      return metrics::OmniboxInputType::URL;
  }

  // Handle the cases we detected in the IPv4 code above as "almost certainly a
  // query" now that we know the user hasn't tried to force navigation via a
  // scheme/trailing slash.
  if ((host_info.family == url::CanonHostInfo::IPV4) &&
      (host_info.num_ipv4_components > 1))
    return metrics::OmniboxInputType::QUERY;

  // If there is more than one recognized non-host component, this is likely to
  // be a URL, even if the TLD is unknown (in which case this is likely an
  // intranet URL).
  if (NumNonHostComponents(*parts) > 1)
    return metrics::OmniboxInputType::URL;

  // If we reach here with a username, our input looks something like
  // "user@host".  Unless there is a desired TLD, we think this is more likely
  // an email address than an HTTP auth attempt, so we search by default.  (When
  // there _is_ a desired TLD, the user hit ctrl-enter, and we assume that
  // implies an attempted navigation.)
  if (canonicalized_url->has_username() && desired_tld.empty())
    return metrics::OmniboxInputType::UNKNOWN;

  // If the host has a known TLD or a port, it's probably a URL.  Note that we
  // special-case "localhost" as a known hostname.
  if (has_known_tld || (canonicalized_url->host() == "localhost") ||
      canonicalized_url->has_port())
    return metrics::OmniboxInputType::URL;

  // If the input looks like a word followed by a pound sign and possibly more
  // characters ("c#" or "c# foo"), this is almost certainly an attempt to
  // search.  We try to be conservative here by not firing on cases like "c/#"
  // or "c?#" that might actually indicate some cryptic attempt to access an
  // intranet host, and by placing this check late enough that other tests
  // (e.g., for a non-empty TLD or a non-empty scheme) will have already
  // returned URL.
  if (!parts->path.is_valid() && !canonicalized_url->has_query() &&
      canonicalized_url->has_ref())
    return metrics::OmniboxInputType::QUERY;

  // No scheme, username, port, and no known TLD on the host.
  // This could be:
  // * A single word "foo"; possibly an intranet site, but more likely a search.
  //   This is ideally an UNKNOWN, and we can let the Alternate Nav URL code
  //   catch our mistakes.
  // * A URL with a valid TLD we don't know about yet.  If e.g. a registrar adds
  //   "xxx" as a TLD, then until we add it to our data file, Chrome won't know
  //   "foo.xxx" is a real URL.  So ideally this is a URL, but we can't really
  //   distinguish this case from:
  // * A "URL-like" string that's not really a URL (like
  //   "browser.tabs.closeButtons" or "java.awt.event.*").  This is ideally a
  //   QUERY.  Since this is indistinguishable from the case above, and this
  //   case is much more likely, claim these are UNKNOWN, which should default
  //   to the right thing and let users correct us on a case-by-case basis.
  return metrics::OmniboxInputType::UNKNOWN;
}

// static
void AutocompleteInput::ParseForEmphasizeComponents(
    const base::string16& text,
    const AutocompleteSchemeClassifier& scheme_classifier,
    url::Component* scheme,
    url::Component* host) {
  url::Parsed parts;
  base::string16 scheme_str;
  Parse(text, std::string(), scheme_classifier, &parts, &scheme_str, NULL);

  *scheme = parts.scheme;
  *host = parts.host;

  int after_scheme_and_colon = parts.scheme.end() + 1;
  // For the view-source scheme, we should emphasize the scheme and host of the
  // URL qualified by the view-source prefix.
  if (LowerCaseEqualsASCII(scheme_str, kViewSourceScheme) &&
      (static_cast<int>(text.length()) > after_scheme_and_colon)) {
    // Obtain the URL prefixed by view-source and parse it.
    base::string16 real_url(text.substr(after_scheme_and_colon));
    url::Parsed real_parts;
    AutocompleteInput::Parse(real_url, std::string(), scheme_classifier,
                             &real_parts, NULL, NULL);
    if (real_parts.scheme.is_nonempty() || real_parts.host.is_nonempty()) {
      if (real_parts.scheme.is_nonempty()) {
        *scheme = url::Component(
            after_scheme_and_colon + real_parts.scheme.begin,
            real_parts.scheme.len);
      } else {
        scheme->reset();
      }
      if (real_parts.host.is_nonempty()) {
        *host = url::Component(after_scheme_and_colon + real_parts.host.begin,
                               real_parts.host.len);
      } else {
        host->reset();
      }
    }
  } else if (LowerCaseEqualsASCII(scheme_str, url::kFileSystemScheme) &&
             parts.inner_parsed() && parts.inner_parsed()->scheme.is_valid()) {
    *host = parts.inner_parsed()->host;
  }
}

// static
base::string16 AutocompleteInput::FormattedStringWithEquivalentMeaning(
    const GURL& url,
    const base::string16& formatted_url,
    const AutocompleteSchemeClassifier& scheme_classifier) {
  if (!net::CanStripTrailingSlash(url))
    return formatted_url;
  const base::string16 url_with_path(formatted_url + base::char16('/'));
  return (AutocompleteInput::Parse(formatted_url, std::string(),
                                   scheme_classifier, NULL, NULL, NULL) ==
          AutocompleteInput::Parse(url_with_path, std::string(),
                                   scheme_classifier, NULL, NULL, NULL)) ?
      formatted_url : url_with_path;
}

// static
int AutocompleteInput::NumNonHostComponents(const url::Parsed& parts) {
  int num_nonhost_components = 0;
  if (parts.scheme.is_nonempty())
    ++num_nonhost_components;
  if (parts.username.is_nonempty())
    ++num_nonhost_components;
  if (parts.password.is_nonempty())
    ++num_nonhost_components;
  if (parts.port.is_nonempty())
    ++num_nonhost_components;
  if (parts.path.is_nonempty())
    ++num_nonhost_components;
  if (parts.query.is_nonempty())
    ++num_nonhost_components;
  if (parts.ref.is_nonempty())
    ++num_nonhost_components;
  return num_nonhost_components;
}

// static
bool AutocompleteInput::HasHTTPScheme(const base::string16& input) {
  std::string utf8_input(base::UTF16ToUTF8(input));
  url::Component scheme;
  if (url::FindAndCompareScheme(utf8_input, kViewSourceScheme, &scheme)) {
    utf8_input.erase(0, scheme.end() + 1);
  }
  return url::FindAndCompareScheme(utf8_input, url::kHttpScheme, NULL);
}

void AutocompleteInput::UpdateText(const base::string16& text,
                                   size_t cursor_position,
                                   const url::Parsed& parts) {
  DCHECK(cursor_position <= text.length() ||
         cursor_position == base::string16::npos)
      << "Text: '" << text << "', cp: " << cursor_position;
  text_ = text;
  cursor_position_ = cursor_position;
  parts_ = parts;
}

void AutocompleteInput::Clear() {
  text_.clear();
  cursor_position_ = base::string16::npos;
  current_url_ = GURL();
  current_page_classification_ = metrics::OmniboxEventProto::INVALID_SPEC;
  type_ = metrics::OmniboxInputType::INVALID;
  parts_ = url::Parsed();
  scheme_.clear();
  canonicalized_url_ = GURL();
  prevent_inline_autocomplete_ = false;
  prefer_keyword_ = false;
  allow_exact_keyword_match_ = false;
  want_asynchronous_matches_ = true;
}


text:
package org.jsecurity.session;

import java.io.Serializable;

/**
 * Exception thrown when attempting to interact with the system under the pretense of a
 * particular session (e.g. under a specific session id), and that session does not exist in
 * the system.
 *
 * @author Les Hazlewood
 * @since 0.1
 */
public class UnknownSessionException extends InvalidSessionException {

    /**
     * Creates a new UnknownSessionException.
     */
    public UnknownSessionException() {
        super();
    }

    /**
     * Constructs a new UnknownSessionException.
     *
     * @param message the reason for the exception
     */
    public UnknownSessionException(String message) {
        super(message);
    }

    /**
     * Constructs a new UnknownSessionException.
     *
     * @param cause the underlying Throwable that caused this exception to be thrown.
     */
    public UnknownSessionException(Throwable cause) {
        super(cause);
    }

    /**
     * Constructs a new UnknownSessionException.
     *
     * @param message the reason for the exception
     * @param cause   the underlying Throwable that caused this exception to be thrown.
     */
    public UnknownSessionException(String message, Throwable cause) {
        super(message, cause);
    }

    /**
     * Constructs a new UnknownSessionException.
     *
     * @param sessionId the session id given that is unknown to the system.
     */
    public UnknownSessionException(Serializable sessionId) {
        super(sessionId);
    }

    /**
     * Constructs a new UnknownSessionException.
     *
     * @param message   the reason for the exception
     * @param sessionId the session id given that is unknown to the system.
     */
    public UnknownSessionException(String message, Serializable sessionId) {
        super(message, sessionId);
    }

    /**
     * Constructs a new UnknownSessionException.
     *
     * @param message   the reason for the exception
     * @param cause     the underlying Throwable that caused this exception to be thrown.
     * @param sessionId the session id given that is unknown to the system.
     */
    public UnknownSessionException(String message, Throwable cause, Serializable sessionId) {
        super(message, cause, sessionId);
    }
}

redpajama_set_name: RedPajamaGithub


text:
<!DOCTYPE html>

  <meta charset='utf-8'>
  <meta http-equiv="X-UA-Compatible" content="chrome=1">
  <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1">
  <link href='https://fonts.googleapis.com/css?family=Architects+Daughter' rel='stylesheet' type='text/css'>
  <link rel="stylesheet" type="text/css" href="stylesheets/stylesheet.css" media="screen">
  <link rel="stylesheet" type="text/css" href="stylesheets/github-light.css" media="screen">
  <link rel="stylesheet" type="text/css" href="stylesheets/print.css" media="print">

  <title>JavaScript Mocha Error Timeout Require Done Callback</title>

Hasan Setiawan

Write, write, write give your wings on code!

      Follow me on GitHub

JavaScript Ignore Spesific Line in Flow and Eslint

            You got itches, with very single line error

          That is very simple one, just add this in to your code

                // $FlowFixMe
                import { Picker } from 'native-base';

                const Item = Picker.Item;
                type Props = {};
                type State = {
                  selectedItem: any;
                  selected1: string;
                  results: {
                    items: Array<any>;
                  };
                }
                export default class BikeType extends Component {
                  state: State; // eslint-disable-line
                ....

          Have a look `// $FlowFixMe` and `// eslint-disable-line` those magic comment will make Flow and Eslint ignore the line

This page was generated by GitHub Pages using the Architect theme by Jason Long.

Back


text:
import { NgModule } from '@angular/core';
import { CommonModule } from '@angular/common';
import { FormsModule } from '@angular/forms';
import { CKEditorModule } from 'ng2-ckeditor';
import { NgaModule } from '../../theme/nga.module';
import { NgbDropdownModule, NgbModalModule } from '@ng-bootstrap/ng-bootstrap';

import { DataTableModule } from "angular2-datatable";
import { DataFilterPipe } from './data-filter.pipe';
import { TruncatePipe } from './truncate';

import { routing } from './registrant.routing';
import { Registrant } from './registrant.component';
import { Participant } from './participant/participant.component';
import { AppsToday } from './appstoday/appstoday.component';
import { HackToday } from './hacktoday/hacktoday.component';
import { Seminar } from './seminar/seminar.component';
import { Single } from './viewsingle/single.component';
import { Team } from './viewteam/team.component';

@NgModule({
  imports: [
    CommonModule,
    FormsModule,
    NgaModule,
    CKEditorModule,
    routing,
    NgbDropdownModule,
    NgbModalModule,
    DataTableModule
  ],
  declarations: [
    Registrant,
    Participant,
    AppsToday,
    HackToday,
    Seminar,
    Single,
    Team,
    DataFilterPipe,
    TruncatePipe
  ]
})
export class RegistrantModule {}


text:
<?php
/**
 * This file is part of the Kenjis.PHPUnitVWTest
 *
 * @license http://opensource.org/licenses/MIT MIT
 */
namespace Kenjis\PHPUnitVWTest;

class PHPUnitVWTest
{
}


text:
//
// Redis.cs - How to use Redis in Unity
//
// TeamDev C# Redis Client
// https://redis.codeplex.com/
//
using UnityEngine;
using System.Collections;
using System;
using TeamDev.Redis;

public class Redis {

    //
    // singletone
    //
    static Redis singleton;

    public static Redis GetInstance()
    {
        if (singleton == null)
        {
            singleton = new Redis();
        }

        return singleton;
    }

    ////////////////////////////////////////////////////////////////

    protected RedisDataAccessProvider redis;

    protected Redis()
    {
        try
        {
            redis = new RedisDataAccessProvider();
            redis.Configuration.Host = "127.0.0.1";
            redis.Configuration.Port = 6379;
            redis.Connect();
        }
        catch(Exception e)
        {
            Debug.Log("Redis connection failed..." + e.Message);
            redis = null;
        }
    }

    public bool isConnected()
    {
        if (redis == null) return false;
        return true;
    }

    public float getFloat(string key)
    {
        string str = getString(key);
        if (str == null) return 0.0f;
        return float.Parse(str);
    }

    public void setFloat(string key, float val)
    {
        setString(key, val.ToString());
    }

    public string getString(string key)
    {
        if (redis == null) return null;

        int command_id = redis.SendCommand(RedisCommand.GET, key);
        string str = redis.ReadString(command_id);

        if (str == null) return null;

        return str;
    }

    public void setString(string key, string val)
    {
        if (redis == null) return;

        redis.SendCommand(RedisCommand.SET, key, val);
        redis.WaitComplete();
    }
}


text:
<!DOCTYPE html><html><head>

    <title>iron-scroll-target-behavior using the document scrolling</title>

    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width,initial-scale=1">

    <script src="../../webcomponentsjs/webcomponents-lite.js"></script>

    <link rel="import" href="../iron-scroll-target-behavior.html">
    <link rel="import" href="x-scrollable.html">

    <style>body{margin:0;padding:0;}</style>
  </head>
  <body unresolved="">

    <x-scrollable scroll-target="document"></x-scrollable>

</body></html>


text:
					Home

					Ledger

Ledger Lists

				<form class="form-search">

						<input type="text" placeholder="Search ..." class="nav-search-input" id="nav-search-input" autocomplete="off" />

				</form>

					Ledger List

			<?php foreach($ledgers as $ledg){  ?>

<?php echo ucwords(strtolower($ledg['name'])); ?>

						<form class="form" id="ledList"></form>

								 <?php

						                echo "

						                Name
						                  Group/Ledger
						                  Nature
						                  Behaviour
						                  Purpose
						                  Status
						                  Actions

";
						                $flag = 0;
						            ?>
						            <tr data-tt-id="<?php echo $ledg["ledger_account_id"]; ?>" <?php if ($flag == 0) { $flag = 1;} else {echo "data-tt-parent-id=" . $ledg["parent"];} ?>>
						                    <?php echo ucwords(strtolower($ledg['name'])); ?>
						                    <?php echo $ledg['entity_type']; ?>
						                    <?php if($ledg['nature']=='cr') { echo "Credit";} else if($ledg['nature']=='dr'){ echo "Debit";} else {echo "";} ?>
						                    <?php echo $ledg['behaviour']; ?>

						                    <?php if($ledg['status']==1){ echo "Active";} else {echo "Inactive";}?>

						                <?php
						                recursiveArr($ledg['children']);
						                echo "

";
					                ?>

				<?php } ?>

 <?php

function recursiveArr($ledgers){

    global $flag;
    $txt=array();

    if (isset($ledgers) && is_array($ledgers)) {

        global $config;

        foreach($ledgers as $val){
?>
                    <tr data-tt-id="<?php echo $val["ledger_account_id"]; ?>" <?php if ($flag == 1) { $flag = 0;} else {echo "data-tt-parent-id=" . $val["parent"];} ?>>
                    <?php echo ucwords($val["name"]); ?>
                    <?php echo $val['entity_type']; ?>
                    <?php if($val['nature']=='cr') { echo "Credit";} else if($val['nature']=='dr'){ echo "Debit";} else {echo "";} ?>
                    <?php echo $val['behaviour']; ?>
                    <?php echo $val['context']; ?>
                    <?php if($val['status']==1){ echo "Active";$class = "times";} else {echo "Inactive"; $class = "check";}?>
                    <?php if($val['entity_type']=='ledger' ){?><a href="editEntity/<?php echo $val["ledger_account_id"]; ?>"> <a href="<?php echo $config->system->full_base_url; ?>listTransaction/<?php echo $val["ledger_account_id"]; ?>" target="_blank"> <a class="red disabled_action" href="#" id="<?php echo  $val["ledger_account_id"]; ?>"><i class="fa fa-<?php echo $class; ?>"><?php } ?>

<?php

            if($val['children'] && is_array($val['children'])){
                recursiveArr($val['children']);
            }
        }
    }

}

?>

<link rel="stylesheet" href="<?php echo base_url(); ?>css/ledgerlist.css" />


text:
package com.vlath.keyboard.keyboard.internal;

import android.content.Context;
import android.content.res.Resources;
import android.text.TextUtils;

import java.util.Locale;

import com.vlath.keyboard.annotations.UsedForTesting;
import com.vlath.keyboard.latin.common.Constants;
import com.vlath.keyboard.latin.utils.RunInLocale;
import com.vlath.keyboard.latin.utils.SubtypeLocaleUtils;

// TODO: Make this an immutable class.
public final class KeyboardTextsSet {
    public static final String PREFIX_TEXT = "!text/";
    private static final String PREFIX_RESOURCE = "!string/";

    private static final char BACKSLASH = Constants.CODE_BACKSLASH;
    private static final int MAX_REFERENCE_INDIRECTION = 10;

    private Resources mResources;
    private Locale mResourceLocale;
    private String mResourcePackageName;
    private String[] mTextsTable;

    public void setLocale(final Locale locale, final Context context) {
        final Resources res = context.getResources();
        // Null means the current system locale.
        final String resourcePackageName = res.getResourcePackageName(
                context.getApplicationInfo().labelRes);
        setLocale(locale, res, resourcePackageName);
    }

    @UsedForTesting
    public void setLocale(final Locale locale, final Resources res,
            final String resourcePackageName) {
        mResources = res;
        // Null means the current system locale.
        mResourceLocale = SubtypeLocaleUtils.NO_LANGUAGE.equals(locale.toString()) ? null : locale;
        mResourcePackageName = resourcePackageName;
        mTextsTable = KeyboardTextsTable.getTextsTable(locale);
    }

    public String getText(final String name) {
        return KeyboardTextsTable.getText(name, mTextsTable);
    }

    private static int searchTextNameEnd(final String text, final int start) {
        final int size = text.length();
        for (int pos = start; pos < size; pos++) {
            final char c = text.charAt(pos);
            // Label name should be consisted of [a-zA-Z_0-9].
            if ((c >= 'a' && c <= 'z') || c == '_' || (c >= '0' && c <= '9')) {
                continue;
            }
            return pos;
        }
        return size;
    }

    // TODO: Resolve text reference when creating {@link KeyboardTextsTable} class.
    public String resolveTextReference(final String rawText) {
        if (TextUtils.isEmpty(rawText)) {
            return null;
        }
        int level = 0;
        String text = rawText;
        StringBuilder sb;
        do {
            level++;
            if (level >= MAX_REFERENCE_INDIRECTION) {
                throw new RuntimeException("Too many " + PREFIX_TEXT + " or " + PREFIX_RESOURCE +
                        " reference indirection: " + text);
            }

            final int prefixLength = PREFIX_TEXT.length();
            final int size = text.length();
            if (size < prefixLength) {
                break;
            }

            sb = null;
            for (int pos = 0; pos < size; pos++) {
                final char c = text.charAt(pos);
                if (text.startsWith(PREFIX_TEXT, pos)) {
                    if (sb == null) {
                        sb = new StringBuilder(text.substring(0, pos));
                    }
                    pos = expandReference(text, pos, PREFIX_TEXT, sb);
                } else if (text.startsWith(PREFIX_RESOURCE, pos)) {
                    if (sb == null) {
                        sb = new StringBuilder(text.substring(0, pos));
                    }
                    pos = expandReference(text, pos, PREFIX_RESOURCE, sb);
                } else if (c == BACKSLASH) {
                    if (sb != null) {
                        // Append both escape character and escaped character.
                        sb.append(text.substring(pos, Math.min(pos + 2, size)));
                    }
                    pos++;
                } else if (sb != null) {
                    sb.append(c);
                }
            }

            if (sb != null) {
                text = sb.toString();
            }
        } while (sb != null);
        return TextUtils.isEmpty(text) ? null : text;
    }

    private int expandReference(final String text, final int pos, final String prefix,
            final StringBuilder sb) {
        final int prefixLength = prefix.length();
        final int end = searchTextNameEnd(text, pos + prefixLength);
        final String name = text.substring(pos + prefixLength, end);
        if (prefix.equals(PREFIX_TEXT)) {
            sb.append(getText(name));
        } else { // PREFIX_RESOURCE
            final String resourcePackageName = mResourcePackageName;
            final RunInLocale<String> getTextJob = new RunInLocale<String>() {
                @Override
                protected String job(final Resources res) {
                    final int resId = res.getIdentifier(name, "string", resourcePackageName);
                    return res.getString(resId);
                }
            };
            sb.append(getTextJob.runInLocale(mResources, mResourceLocale));
        }
        return end - 1;
    }
}


text:
package org.zstack.network.service.lb;

import org.springframework.http.HttpMethod;
import org.zstack.header.identity.Action;
import org.zstack.header.message.APICreateMessage;
import org.zstack.header.message.APIEvent;
import org.zstack.header.message.APIMessage;
import org.zstack.header.message.APIParam;
import org.zstack.header.rest.RestRequest;

/**
 * Created by shixin on 04/12/2018.
 */
@Action(category = LoadBalancerConstants.ACTION_CATEGORY)
@RestRequest(
        path = "/certificates/{uuid}/actions",
        method = HttpMethod.PUT,
        responseClass = APIUpdateCertificateEvent.class,
        isAction = true
)
public class APIUpdateCertificateMsg extends APICreateMessage {
    @APIParam(resourceType = CertificateVO.class, checkAccount = true, operationTarget = true)
    private String uuid;
    @APIParam(maxLength = 255, required = false)
    private String name;
    @APIParam(maxLength = 2048, required = false)
    private String description;

    public String getUuid() {
        return uuid;
    }

    public void setUuid(String uuid) {
        this.uuid = uuid;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getDescription() {
        return description;
    }

    public void setDescription(String description) {
        this.description = description;
    }

    public static APIUpdateCertificateMsg __example__() {
        APIUpdateCertificateMsg msg = new APIUpdateCertificateMsg();
        msg.uuid = uuid();
        msg.setDescription("info");
        msg.setName("Test-Cer");

        return msg;
    }
}


text:
package org.support.project.common.bean;

import java.util.Locale;

import org.support.project.common.config.CommonBaseParameter;
import org.support.project.common.config.Resources;
import org.support.project.common.log.LogLevel;

public class ValidateError {

	public static final int WARN = LogLevel.WARN.getValue();
	public static final int ERROR = LogLevel.ERROR.getValue();

	private Integer level;

	//private String msg;

	private String key;
	private String[] params;

	public ValidateError(Integer level, String key, String... params) {
		super();
		this.level = level;
		this.key = key;
		this.params = params;
		//Resources resources = Resources.getInstance(CommonBaseParameter.APP_RESOURCE);
		//msg = resources.getResource(key, params);
	}

	public ValidateError(String key, String... params) {
		this(WARN, key, params);
	}

	public String getMsg(Locale locale) {
		Resources resources = Resources.getInstance(CommonBaseParameter.APP_RESOURCE, locale);
		String msg = resources.getResource(key, params);
		return msg;
	}

	public Integer getLevel() {
		return level;
	}

}


text:
import hashlib
import inspect
import json
import logging
import re
from xml.sax.saxutils import escape as xml_escape

import webob
from wsgiservice import xmlserializer
from wsgiservice.decorators import mount
from wsgiservice.exceptions import (MultiValidationException, ResponseException,
                                    ValidationException)
from wsgiservice.status import *

logger = logging.getLogger(__name__)

class Resource(object):
    """Base class for all WsgiService resources. A resource is a unique REST
    endpoint which accepts different methods for different actions.

    For each HTTP call the corresponding method (equal to the HTTP method)
    will be called.
    """
    #: The root tag for generated XML output. Used by :func:`to_text_xml`.
    #: (Default: 'response')
    XML_ROOT_TAG = 'response'

    #: List of the known HTTP methods. Used by :func:`get_method` to handle
    #: methods that are not implemented. (Default: All methods defined by the
    #: HTTP 1.1 standard :rfc:`2616`)
    KNOWN_METHODS = ['OPTIONS', 'GET', 'HEAD', 'POST', 'PUT', 'DELETE',
                     'TRACE', 'CONNECT']

    #: List of tuples mapping file extensions to MIME types. The first item of
    #: the tuple is the extension and the second is the associated MIME type.
    #: Used by :func:`get_content_type` to determine the requested MIME type.
    #: (Default: '.xml' and '.json').
    EXTENSION_MAP = [
        ('.xml', 'text/xml'),
        ('.json', 'application/json'),
    ]

    #: A tuple of exceptions that should be treated as 404. An ideal candidate
    #: is KeyError if you do dictionary accesses. Used by :func:`call` which
    #: calls :func:`handle_exception_404` whenever an exception from this
    #: tuple occurs. (Default: Empty tuple)
    NOT_FOUND = ()

    #: A tuple of absolute paths that should return a 404. By default this is
    #: used to ignored requests for favicon.ico and robots.txt so that
    #: browsers don't cause too many exceptions.
    IGNORED_PATHS = ('/favicon.ico', '/robots.txt')

    #: Whether the input parameters from GET and POST should be decoded
    #: according to the encoding specified by the request. This should only be
    #: changed to False if the input is supposed to be byte values. (Default:
    #: True)
    DECODE_PARAMS = True

    #: Object representing the current request. Set by the constructor.
    request = None

    #: Object representing the current response. Set by the constructor.
    response = None

    #: Dictionary with the path parameters. Set by the constructor.
    path_params = None

    #: String with the current path. Same as request.path except the extension
    #: is removed. So instead of `/movies.json` it is just `/movies`. Set by
    #: the constructor.
    request_path = None

    #: Reference to the application. Set by the constructor.
    application = None

    #: Charset to output in the Content-Type headers. Set to None to avoid
    #: sending this.
    charset = 'UTF-8'

    # Cache for the `data` property
    _data = None

    def __init__(self, request, response, path_params, application=None):
        """Constructor. Order of the parameters is not guaranteed, always
        used named parameters.

        :param request: Object representing the current request.
        :type request: :class:`webob.Request`
        :param response: Object representing the response to be sent.
        :type response: :class:`webob.Response`
        :param path_params: Dictionary of all parameters passed in via the
                            path. This is the return value of
                            :func:`Router.__call__`.
        :type path_params: dict
        :param application: Reference to the application which is calling this
                            resource. Can be used to reference other resources
                            or properties of the application itself.
        :type path_params: :class:`wsgiservice.Application`
        """
        self.request = request
        self.response = response
        self.path_params = path_params
        self.application = application
        self.request_path = ''
        if request:
            self.request_path = request.path
            if path_params and path_params.get('_extension'):
                ext = path_params['_extension']
                if self.request_path.endswith(ext):
                    self.request_path = self.request_path[0:-len(ext)]

    def OPTIONS(self):
        """Default implementation of the OPTIONS verb. Outputs a list of
        allowed methods on this resource in the ``Allow`` response header.
        """
        self.response.headers['Allow'] = self.get_allowed_methods()

    def __call__(self):
        """Main entry point for calling this resource. Handles the method
        dispatching, response conversion, etc. for this resource.

        Catches all exceptions:

            - :class:`webob.exceptions.ResponseException`: Replaces the
              instance's response attribute with the one from the exception.
            - For all exceptions in the :attr:`NOT_FOUND` tuple
              :func:`handle_exception_404` is called.
            - :class:`wsgiservice.exceptions.ValidationException`:
              :func:`handle_exception_400` is called.
            - For all other exceptions deriving from the :class:`Exception`
              base class, the :func:`handle_exception` method is called.
        """
        self.type = self.get_content_type()
        try:
            self.method = self.get_method()
            self.handle_ignored_resources()
            self.assert_conditions()
            self.response.body_raw = self.call_method(self.method)
        except ResponseException, e:
            # a response was raised, catch it
            self.response = e.response
            r = e.response
            if r.status_int == 404 and not r.body and not hasattr(r, 'body_raw'):
                self.handle_exception_404(e)
        except self.NOT_FOUND, e:
            self.handle_exception_404(e)
        except ValidationException, e:
            self.handle_exception_400(e)
        except Exception, e:
            self.handle_exception(e)
        self.convert_response()
        self.set_response_headers()
        return self.response

    @property
    def data(self):
        """Returns the request data as a dictionary.

        Merges the path parameters, GET parameters and POST parameters
        (form-encoded or JSON dictionary). If a key is present in multiple of
        these, the first one defined is used.
        """
        if self._data:
            return self._data

        retval = {}
        data = self.get_request_data()
        for subdata in data:
            for key, value in subdata.iteritems():
                if not key in retval:
                    retval[key] = value

        self._data = retval
        return retval

    def get_resource(self, resource, **kwargs):
        """Returns a new instance of the resource class passed in as resource.
        This is a helper to make future-compatibility easier when new
        arguments get added to the constructor.

        :param resource: Resource class to instantiate. Gets called with the
                         named arguments as required for the constructor.
        :type resource: :class:`Resource`
        :param kwargs: Additional named arguments to pass to the constructor
                       function.
        :type kwargs: dict
        """
        return resource(request=self.request, response=self.response,
            path_params=self.path_params, application=self.application,
            **kwargs)

    def get_method(self, method=None):
        """Returns the method to call on this instance as a string. Raises a
        HTTP exception if no method can be found. Aborts with a 405 status
        code for known methods (based on the :attr:`KNOWN_METHODS` list) and a
        501 status code for all other methods.

        :param method: Name of the method to return. Must be all-uppercase.
        :type method: str

        :raises: :class:`webob.exceptions.ResponseException` of status 405 or
                 501 if the method is not implemented on this resource.
        """
        if method is None:
            method = self.request.method
        if hasattr(self, method) and callable(getattr(self, method)):
            return method
        elif method == 'HEAD':
            return self.get_method('GET')
        # Error: did not find any method, raise a 405 or 501 exception
        elif method in self.KNOWN_METHODS:
            # Known HTTP methods => 405 Method Not Allowed
            raise_405(self)
        else:
            # Unknown HTTP methods => 501 Not Implemented
            raise_501(self)

    def get_content_type(self):
        """Returns the Content Type to serve from either the extension or the
        Accept headers. Uses the :attr:`EXTENSION_MAP` list for all the
        configured MIME types.
        """
        extension = self.path_params.get('_extension')
        for ext, mime in self.EXTENSION_MAP:
            if ext == extension:
                return mime
        # Else: use the Accept headers
        if self.response.vary is None:
            self.response.vary = ['Accept']
        else:
            self.response.vary.append('Accept')
        types = [mime for ext, mime in self.EXTENSION_MAP]
        ct = self.request.accept.best_match(types)
        # No best match found. The specification allows us to either return a
        # 406 or just use another format in this case.
        # We pick the default format, though that may become a configurable
        # behavior in the future.
        if not ct:
            ct = types[0]
        return ct

    def handle_ignored_resources(self):
        """Ignore robots.txt and favicon.ico GET requests based on a list of
        absolute paths in :attr:`IGNORED_PATHS`. Aborts the request with a 404
        status code.

        This is mostly a usability issue to avoid extra log entries for
        resources we are not interested in.

        :raises: :class:`webob.exceptions.ResponseException` of status 404 if
                 the resource is ignored.
        """
        if (self.method in ('GET', 'HEAD') and
                self.request.path_qs in self.IGNORED_PATHS):
            raise_404(self)

    def assert_conditions(self):
        """Handles various HTTP conditions and raises HTTP exceptions to
        abort the request.

            - Content-MD5 request header must match the MD5 hash of the full
              input (:func:`assert_condition_md5`).
            - If-Match and If-None-Match etags are checked against the ETag of
              this resource (:func:`assert_condition_etag`).
            - If-Modified-Since and If-Unmodified-Since are checked against
              the modification date of this resource
              (:func:`assert_condition_last_modified`).

        .. todo:: Return a 501 exception when any Content-* headers have been
                  set in the request. (See :rfc:`2616`, section 9.6)
        """
        self.assert_condition_md5()
        etag = self.clean_etag(self.call_method('get_etag'))
        self.response.last_modified = self.call_method('get_last_modified')
        self.assert_condition_etag()
        self.assert_condition_last_modified()

    def assert_condition_md5(self):
        """If the ``Content-MD5`` request header is present in the request
        it's verified against the MD5 hash of the request body. If they don't
        match, a 400 HTTP response is returned.

        :raises: :class:`webob.exceptions.ResponseException` of status 400 if
                 the MD5 hash does not match the body.
        """
        if 'Content-MD5' in self.request.headers:
            body_md5 = hashlib.md5(self.request.body).hexdigest()
            if body_md5 != self.request.headers['Content-MD5']:
                raise_400(self, msg='Invalid Content-MD5 request header.')

    def assert_condition_etag(self):
        """If the resource has an ETag (see :func:`get_etag`) the request
        headers ``If-Match`` and ``If-None-Match`` are verified. May abort the
        request with 304 or 412 response codes.

        :raises:
            - :class:`webob.exceptions.ResponseException` of status 304 if the
              ETag matches the ``If-None-Match`` request header (GET/HEAD
              requests only).
            - :class:`webob.exceptions.ResponseException` of status 412 if the
              ETag matches the ``If-None-Match`` request header (for requests
              other than GET/HEAD) or the ETag does not match the ``If-Match``
              header.
        """
        if self.response.etag:
            etag = self.response.etag.replace('"', '')
            if not etag in self.request.if_match:
                raise_412(self,
                    'If-Match request header does not the resource ETag.')
            if etag in self.request.if_none_match:
                if self.request.method in ('GET', 'HEAD'):
                    raise_304(self)
                else:
                    raise_412(self,
                        'If-None-Match request header matches resource ETag.')

    def assert_condition_last_modified(self):
        """If the resource has a last modified date (see
        :func:`get_last_modified`) the request headers ``If-Modified-Since``
        and ``If-Unmodified-Since`` are verified. May abort the request with
        304 or 412 response codes.

        :raises:
            - :class:`webob.exceptions.ResponseException` of status 304 if the
              ``If-Modified-Since`` is later than the last modified date.
            - :class:`webob.exceptions.ResponseException` of status 412 if the
              last modified date is later than the ``If-Unmodified-Since``
              header.
        """
        rq = self.request
        rs = self.response
        if rs.last_modified:
            rsl = rs.last_modified
            if rq.if_modified_since and rsl <= rq.if_modified_since:
                raise_304(self)
            if rq.if_unmodified_since and rsl > rq.if_unmodified_since:
                raise_412(self, 'Resource is newer than the '
                    'If-Unmodified-Since request header.')

    def get_etag(self):
        """Returns a string to be used as the ETag for this resource. Used to
        set the ``ETag`` response headers and for conditional requests using
        the ``If-Match`` and ``If-None-Match`` request headers.
        """
        return None

    def clean_etag(self, etag):
        """Cleans the ETag as returned by :func:`get_etag`. Will wrap it in
        quotes and append the extension for the current MIME type.
        """
        if etag:
            etag = etag.replace('"', '')
            extension = None
            for ext, mime in self.EXTENSION_MAP:
                if mime == self.type:
                    extension = ext[1:]
                    break
            if extension:
                etag += '_' + extension
            self.response.etag = etag

    def get_last_modified(self):
        """Return a :class:`datetime.datetime` object of the when the resource
        was last modified. Used to set the ``Last-Modified`` response header
        and for conditional requests using the ``If-Modified-Since`` and
        ``If-Unmodified-Since`` request headers.

        :rtype: :class:`datetime.datetime`
        """
        return None

    def get_allowed_methods(self):
        """Returns a coma-separated list of method names that are allowed on
        this instance. Useful to set the ``Allowed`` response header.
        """
        return ", ".join([method for method in dir(self)
            if method.upper() == method
            and callable(getattr(self, method))])

    def call_method(self, method_name):
        """Call an instance method filling in all the method parameters based
        on their names. The parameters are filled in from the following
        locations (in that order of precedence):

            1. Path parameters from routing
            2. GET parameters
            3. POST parameters

        All values are validated using the method :func:`validate_param`. The
        return value of the method is returned unaltered.

        :param method_name: Name of the method on the current instance to
                            call.
        :type method_name: str
        """
        params = []
        method = getattr(self, method_name)

        method_params, varargs, varkw, defaults = inspect.getargspec(method)
        if method_params and len(method_params) > 1:
            method_params.pop(0)  # pop the self off
            data = self._merge_defaults(self.data, method_params, defaults)
            params = self._get_validated_params(method, method_params, data)

        return self._call_method(method, params, method_params)

    def _call_method(self, method, params, method_params):
        """
        Override this method to add additional validation.

        :param method: Method to be called.
        :param params: Validated parameter values for calling the method.
        :param method_params: The list of parameters in the method's signature.
        :return: The result of calling the method.
        """
        return method(*params)

    def _get_validated_params(self, method, method_params, data):
        """
        Returns a list of params to call the method with.

        The parameters are returned in the order as they are expected by the
        method. All parameters are validated and converted to the requested
        datatype, based on the configuration from the `@validate` decorator.

        :param method_params: The introspected parameters the method needs.
        :type method_params: List of parameter names.
        :param data: All key/value pairs passed in with the request.
        :type data: dict
        """
        errors = {}
        params = []

        for param in method_params:
            value = data.get(param)
            try:
                self.validate_param(method, param, value)
                value = self.convert_param(method, param, value)
            except ValidationException, e:
                # Collect all errors, so we can raise them as one consolidated
                # validation exception.
                errors[param] = e
            else:
                params.append(value)

        if not errors:
            return params

        # Raise consolidated exceptions. The message of the first error is used
        # as message of the new consolidated exception.
        raise MultiValidationException(errors, unicode(errors.values()[0]).encode('utf-8'))

    def validate_param(self, method, param, value):
        """Validates the parameter according to the configurations in the
        _validations dictionary of either the method or the instance. This
        dictionaries are written by the decorator
        :func:`wsgiservice.decorators.validate`.

        .. todo:: Allow validation by type (e.g. header, post, query, etc.)

        :param method: A function to get the validation information from (done
                       using :func:`_get_validation`).
        :type method: Python function
        :param param: Name of the parameter to validate the value for.
        :type param: str
        :param value: Value passed in for the given parameter.
        :type value: Any valid Python value

        :raises: :class:`wsgiservice.exceptions.ValidationException` if the
            value is invalid for the given method and parameter.
        """
        rules = self._get_validation(method, param)
        if not rules:
            return
        if rules.get('mandatory') and (
                value is None or
                (isinstance(value, basestring) and len(value) == 0)):
            raise ValidationException("Missing value for {0}.".format(param))
        elif rules.get('re') and (rules.get('mandatory') or value is not None):
            if not re.search('^' + rules['re'] + '$', value):
                raise ValidationException("Invalid value for {0}.".format(param))

    def convert_param(self, method, param, value):
        """Converts the parameter using the function 'convert' function of the
        validation rules. Same parameters as the `validate_param` method, so
        it might have just been added there. But lumping together the two
        functionalities would make overwriting harder.

        :param method: A function to get the validation information from (done
                       using :func:`_get_validation`).
        :type method: Python function
        :param param: Name of the parameter to validate the value for.
        :type param: str
        :param value: Value passed in for the given parameter.
        :type value: Any valid Python value

        :raises: :class:`wsgiservice.exceptions.ValidationException` if the
                value is invalid for the given method and parameter.
        """
        rules = self._get_validation(method, param)
        has_convert = rules and rules.get('convert')
        if not has_convert or (value is None and not rules['mandatory']):
            return value
        try:
            return rules['convert'](value)
        except ValueError:
            raise ValidationException("Invalid value for {0}.".format(param))

    def _get_validation(self, method, param):
        """Return the correct validations dictionary for this parameter.
        First checks the method itself and then its class. If no validation is
        defined for this parameter, None is returned.

        :param method: A function to get the validation information from.
        :type method: Python function
        :param param: Name of the parameter to get validation information for.
        :type param: str
        """
        if hasattr(method, '_validations') and param in method._validations:
            return method._validations[param]
        elif (hasattr(method.im_class, '_validations') and
                param in method.im_class._validations):
            return method.im_class._validations[param]
        else:
            return None

    def convert_response(self):
        """Finish filling the instance's response object so it's ready to be
        served to the client. This includes converting the body_raw property
        to the content type requested by the user if necessary.
        """
        if hasattr(self.response, 'body_raw'):
            if self.response.body_raw is not None:
                to_type = re.sub('[^a-zA-Z_]', '_', self.type)
                to_type_method = 'to_' + to_type
                if hasattr(self, to_type_method):
                    self.response.body = getattr(self, to_type_method)(
                        self.response.body_raw)
            del self.response.body_raw

    def to_application_json(self, raw):
        """Returns the JSON version of the given raw Python object.

        :param raw: The return value of the resource method.
        :type raw: Any valid Python value
        :rtype: string
        """
        return json.dumps(raw)

    def to_text_xml(self, raw):
        """Returns the XML string version of the given raw Python object. Uses
        :func:`_get_xml_value` which applies some heuristics for converting
        data to XML.

        The default root tag is 'response', but that can be overwritten by
        changing the :attr:`XML_ROOT_TAG` instance variable.

        Uses :func:`wsgiservice.xmlserializer.dumps()` for the actual work.

        :param raw: The return value of the resource method.
        :type raw: Any valid Python value
        :rtype: string
        """
        return xmlserializer.dumps(raw, self.XML_ROOT_TAG)

    def handle_exception(self, e, status=500):
        """Handle the given exception. Log, sets the response code and
        output the exception message as an error message.

        :param e: Exception which is being handled.
        :type e: :class:`Exception`
        :param status: Status code to set.
        :type status: int
        """
        logger.exception(
            "An exception occurred while handling the request: %s", e)
        self.response.body_raw = {'error': unicode(e).encode('utf-8')}
        self.response.status = status

    def handle_exception_400(self, e):
        """Handle the given validation exception. Log, sets the response code
        to 400 and output all errors as a dictionary.

        :param e: Exception which is being handled.
        :type e: :class:`ValidationException`, usually its subclass
                 :class:`MultiValidationException`.
        """
        if isinstance(e, MultiValidationException):
            errors = dict([
                (param, unicode(exc).encode('utf-8')) for param, exc in e.errors.iteritems()
            ])
            logger.info("A 400 Bad Request exception occurred while "
                        "handling the request",
                        exc_info=True,
                        extra={'errors': errors, 'e': e})
            first_error = unicode(e.errors.values()[0]).encode('utf-8')
            self.response.body_raw = {'errors': errors, 'error': first_error}
            self.response.status = 400
        else:
            # Use normal `handle_exception` as fallback. This point is probably
            # reached by legacy code only.
            self.handle_exception(e, status=400)

    def handle_exception_404(self, e):
        """Handle the given exception. Log, sets the response code to 404 and
        output the exception message as an error message.

        :param e: Exception which is being handled.
        :type e: :class:`Exception`
        """
        logger.debug("A 404 Not Found exception occurred while handling "
                     "the request.")
        self.response.body_raw = {'error': 'Not Found'}
        self.response.status = 404

    def set_response_headers(self):
        """Sets all the calculated response headers."""
        self.set_response_content_type()
        self.set_response_content_md5()

    def set_response_content_type(self):
        """Set the Content-Type in the response. Uses the :attr:`type`
        instance attribute which was set by :func:`get_content_type`. Also
        declares a UTF-8 charset.
        """
        if self.response.body:
            ct = self.type
            if self.charset:
                ct += '; charset=' + self.charset
            self.response.headers['Content-Type'] = ct
        elif 'Content-Type' in self.response.headers:
            del self.response.headers['Content-Type']

    def set_response_content_md5(self):
        """Set the Content-MD5 response header. Calculated from the the
        response body by creating the MD5 hash from it.
        """
        self.response.content_md5 = hashlib.md5(self.response.body).hexdigest()

    def get_request_data(self):
        """
        Read the input values.

        Returns a list of dictionaries. These will be used to automatically
        pass them into the method.

        Additionally a combined dictionary is written to `self.data`.

        In the case of JSON input, that element in this list will be the parsed
        JSON value. That may not be a dictionary.
        """
        request_data = [self.path_params, self.request.GET]

        content_type = self.request.headers.get('Content-Type', '')\
            .split(';')[0].strip()
        if content_type  ==  'application/json' and self.request.body:
            try:
                post = json.loads(self.request.body)
            except ValueError:
                raise_400(self, msg='Invalid JSON content data')
            if isinstance(post, dict):
                request_data.append(post)
        else:
            request_data.append(self.request.POST)

        return request_data

    def _merge_defaults(self, data, method_params, defaults):
        """Helper method for adding default values to the data dictionary.

        The `defaults` are the default values inspected from the method that
        will be called. For any values that are not present in the incoming
        data, the default value is added.
        """
        if defaults:
            optional_args = method_params[-len(defaults):]
            for key, value in zip(optional_args, defaults):
                if not key in data:
                    data[key] = value
        return data

@mount('/_internal/help')
class Help(Resource):
    """Provides documentation for all resources of the current application.

    .. todo:: Allow documentation of output.
    .. todo:: Use first sentence of docstring for summary, add bigger version
              at the bottom.
    """
    EXTENSION_MAP = [('.html', 'text/html')] + Resource.EXTENSION_MAP
    XML_ROOT_TAG = 'help'

    def GET(self):
        """Returns documentation for the application."""
        retval = []
        for res in self.application._resources:
            retval.append({
                'name': res.__name__,
                'desc': self._get_doc(res),
                'properties': {
                    'XML_ROOT_TAG': res.XML_ROOT_TAG,
                    'KNOWN_METHODS': res.KNOWN_METHODS,
                    'EXTENSION_MAP': dict((key[1:], value) for key, value
                        in res.EXTENSION_MAP),
                    'NOT_FOUND': [ex.__name__ for ex in res.NOT_FOUND],
                },
                'methods': self._get_methods(res),
                'path': self.request.script_name + res._path,
            })
        # Sort by name
        retval = [(r['name'], r) for r in retval]
        retval.sort()
        retval = [r[1] for r in retval]

        return retval

    def _get_methods(self, res):
        """Return a dictionary of method descriptions for the given resource.

        :param res: Resource class to get all HTTP methods from.
        :type res: :class:`webob.resource.Resource`
        """
        retval = {}
        inst = res(request=webob.Request.blank('/'),
            response=webob.Response(), path_params={})
        methods = [m.strip() for m in inst.get_allowed_methods().split(',')]
        for method_name in methods:
            method = getattr(res, method_name)
            retval[method_name] = {
                'desc': self._get_doc(method),
                'parameters': self._get_parameters(res, method)}
        return retval

    def _get_doc(self, obj):
        """Returns a slightly modified (stripped) docstring for the given
        Python object. Returns an empty string if the object doesn't have any
        documentation.

        :param obj: Python object to get the docstring from.
        :type obj: A method or class.
        """
        doc = obj.__doc__
        if doc:
            return doc.strip()
        else:
            return ''

    def _get_parameters(self, res, method):
        """Return a parameters dictionary for the given resource/method.

        :param res: Resource class to get all HTTP methods from.
        :type res: :class:`webob.resource.Resource`
        :param method: The method to get parameters from.
        :type method: Python function
        """
        method_params, varargs, varkw, defaults = inspect.getargspec(method)
        if method_params:
            method_params.pop(0) # pop the self off
        self._add_path_parameters(method_params, res)
        retval = {}
        for param in method_params:
            is_path_param = '{' + param + '}' in res._path
            validation = self._get_validation(method, param)
            retval[param] = {
                'path_param': is_path_param,
                'mandatory': is_path_param or validation,
                'validate_re': None,
                'desc': '',
            }
            if validation:
                retval[param]['validate_re'] = validation['re']
                retval[param]['desc'] = validation['doc'] or ''
        return retval

    def _add_path_parameters(self, method_params, res):
        """Extract all path parameters as they are always required even though
        some methods may not have them in their definition.

        :param method_params: Current list of parameters from the method.
        :type method_params: Ordered list of method parameter names.
        :param res: Resource class to get the path from.
        :type res: :class:`webob.resource.Resource`
        """
        for param in re.findall('{([^}]+)}', res._path):
            if param not in method_params:
                method_params.append(param)

    def _get_xml_value(self, value):
        """Overwritten _get_xml_value which uses the tag 'resource' for list
        children. Calls :func:`Resource._get_xml_value` for all non-list
        values.

        :param value: The value to convert to HTML.
        :type raw: Any valid Python value
        """
        if isinstance(value, list):
            retval = []
            for key, value in enumerate(value):
                retval.append('<resource>')
                retval.append(self._get_xml_value(value))
                retval.append('</resource>')
            return "".join(retval)
        else:
            return Resource._get_xml_value(self, value)

    def to_text_html(self, raw):
        """Returns the HTML string version of the given raw Python object.
        Hard-coded to return a nicely-presented service information document.

        :param raw: The return value of the resource method.
        :type raw: Any valid Python object
        :rtype: string

        .. todo:: Treat paragraphs and/or newlines better in output.
        """
        retval = ["""<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
                        "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
            <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
            <head>
                <meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
                <title>Help Example</title>
                <style>
                    /* YUI reset.css */
                    html{color:#000;background:#FFF;}body,div,dl,dt,dd,ul,ol,li,h1,h2,h3,h4,h5,h6,pre,code,form,fieldset,legend,input,button,textarea,p,blockquote,th,td{margin:0;padding:0;}table{border-collapse:collapse;border-spacing:0;}fieldset,img{border:0;}address,caption,cite,code,dfn,em,strong,th,var,optgroup{font-style:inherit;font-weight:inherit;}del,ins{text-decoration:none;}li{list-style:none;}caption,th{text-align:left;}h1,h2,h3,h4,h5,h6{font-size:100%;font-weight:normal;}q:before,q:after{content:'';}abbr,acronym{border:0;font-variant:normal;}sup{vertical-align:baseline;}sub{vertical-align:baseline;}legend{color:#000;}input,button,textarea,select,optgroup,option{font-family:inherit;font-size:inherit;font-style:inherit;font-weight:inherit;}input,button,textarea,select{*font-size:100%;}
                    /* YUI fonts.css */
                    body{font:13px/1.231 arial,helvetica,clean,sans-serif;*font-size:small;*font:x-small;}select,input,button,textarea,button{font:99% arial,helvetica,clean,sans-serif;}table{font-size:inherit;font:100%;}pre,code,kbd,samp,tt{font-family:monospace;*font-size:108%;line-height:100%;}
                    /* YUI base.css */
                    body{margin:10px;}h1{font-size:138.5%;}h2{font-size:123.1%;}h3{font-size:108%;}h1,h2,h3{margin:1em 0;}h1,h2,h3,h4,h5,h6,strong,dt{font-weight:bold;}optgroup{font-weight:normal;}abbr,acronym{border-bottom:1px dotted #000;cursor:help;}em{font-style:italic;}del{text-decoration:line-through;}blockquote,ul,ol,dl{margin:1em;}ol,ul,dl{margin-left:2em;}ol li{list-style:decimal outside;}ul li{list-style:disc outside;}dl dd{margin-left:1em;}th,td{border:1px solid #000;padding:.5em;}th{font-weight:bold;text-align:center;}caption{margin-bottom:.5em;text-align:center;}sup{vertical-align:super;}sub{vertical-align:sub;}p,fieldset,table,pre{margin-bottom:1em;}button,input[type="checkbox"],input[type="radio"],input[type="reset"],input[type="submit"]{padding:1px;}

                    h2 {margin-top: 0;}
                    .resource_details {padding-top: 2em;border-top: 1px dotted #ccc;margin-top: 2em;}
                    .method_details {margin-left: 2em;}

                    /* JS form */
                    form {
                        padding: 1em;
                        border: 1px solid #ccc;
                    }
                    input.error {
                        background: #FCECEC;
                        color: red;
                        border: 1px solid red;
                    }
                    label {
                        font-weight: bold;
                        float: left;
                        width: 10em;
                    }
                    p.form_element, input.submit {
                        clear: left;
                    }
                    div.result {
                        margin-top: 1em;
                    }
                    h4 {
                        margin-bottom: 0.5em;
                    }
                    a.add_input {
                        margin: 0.5em;
                    }
                    .hidden { display: none !important; }
                    a.toggle_details {
                        margin-bottom: 1em;
                        display: block;
                    }
                </style>
                <script>
                /**
                 * Adds a resource's method - a form to the current location with the ability
                 * to submit a request to the service filling in all the parameters.
                 */
                function add_resource_method(target, resource, method_name, method) {
                    new ResourceMethodForm(target, resource, method_name, method);
                }

                function ResourceMethodForm(target, resource, method_name, method) {
                    this.targetName = target;
                    this.target = document.getElementById(target);
                    this.resource = resource;
                    this.method_name = method_name;
                    this.method = method;
                    this.init();
                }

                var pr = ResourceMethodForm.prototype;

                pr.init = function() {
                    var fragment = document.createDocumentFragment();
                    var form = this.create_form(fragment);
                    var input_container = document.createElement('div');
                    this.input_container = input_container;
                    form.appendChild(input_container);
                    this.create_form_params(input_container);
                    this.create_form_buttons(form);
                    this.create_result_field(form);
                    this.target.appendChild(fragment);
                };
                pr.create_form = function(parent) {
                    var form = document.createElement('form');
                    form.action = '';
                    form.target = '_blank';
                    var that = this;
                    form.onsubmit = function() {
                        return that.on_submit();
                    };
                    var h4 = document.createElement('h4');
                    h4.innerHTML = 'Debug form';
                    form.appendChild(h4);

                    parent.appendChild(form);
                    return form;
                };
                pr.create_form_params = function(parent) {
                    for (param in this.method.parameters) {
                        this.create_form_field(parent, 'param', 'text', param);
                    }

                    // Accept header
                    var mimes = [];
                    var emap = this.resource.properties.EXTENSION_MAP;
                    for (extension in emap) {
                        mimes.push(emap[extension]);
                    }
                    this.create_form_field(parent, 'header', 'select', 'Accept', mimes);
                };
                pr.create_form_field = function(parent, type, field_type, name, options) {
                    var id = type + '_' + this.resource['name'] + '_' + this.method_name + '_' + name;
                    var d = document.createElement('div');
                    d.className = type;
                    d.id = id;

                    var input_id = id + '_input';
                    var lbl = document.createElement('label');
                    lbl.innerHTML = name;
                    if (type == 'header') {
                        lbl.innerHTML += ' (Header)';
                    }
                    lbl.setAttribute('for', input_id);
                    d.appendChild(lbl);

                    var field = null;
                    if (field_type == 'select') {
                        field = document.createElement('select');
                        for (var i = 0; i < options.length; i++) {
                            var option = document.createElement('option');
                            option.value = options[i];
                            option.innerHTML = this.format(options[i]);
                            field.appendChild(option);
                        }
                    } else {
                        field = document.createElement('input');
                        field.type = 'text';
                    }
                    field.id = input_id;
                    field.name = name;
                    d.appendChild(field);

                    parent.appendChild(d);
                };
                pr.create_form_buttons = function(parent) {
                    var subm = document.createElement('input');
                    subm.type = 'submit';
                    subm.value = 'Execute request (' + this.method_name + ')';
                    subm.className = 'submit';
                    parent.appendChild(subm);

                    var that = this;
                    var create_field = document.createElement('a');
                    create_field.href = '#';
                    create_field.className = 'add_input';
                    create_field.innerHTML = 'Add parameter';
                    create_field.onclick = function() {
                        var name = prompt("Enter a field name:");
                        if (name !== null) {
                            that.create_form_field(that.input_container, 'param', 'text', name);
                        }
                        return false;
                    };
                    parent.appendChild(create_field);

                    var create_header = document.createElement('a');
                    create_header.href = '#';
                    create_header.className = 'add_input';
                    create_header.innerHTML = 'Add header';
                    create_header.onclick = function() {
                        var name = prompt("Enter a header name:");
                        if (name !== null) {
                            that.create_form_field(that.input_container, 'header', 'text', name);
                        }
                        return false;
                    };
                    parent.appendChild(create_header);
                };
                pr.create_result_field = function(parent) {
                    this.result_node = document.createElement('div');
                    this.result_node.className = 'result';
                    parent.appendChild(this.result_node);
                };
                pr.on_submit = function() {
                    var xhr = null;
                    var that = this;
                    this.result_node.innerHTML = 'Executing...';

                    if (window.XMLHttpRequest) {
                        xhr = new XMLHttpRequest();
                    } else if (window.ActiveXObject) {
                        xhr = new ActiveXObject("Microsoft.XMLHTTP");
                    }
                    xhr.onreadystatechange = function() {
                        if (xhr.readyState == 4) {
                            // Received
                            var data = [
                                '<h5>Status</h5>', xhr.status, ' ',
                                that.get_status(xhr.status, xhr.statusText),
                                '<h5>Response Headers</h5>',
                                that.format(xhr.getAllResponseHeaders()),
                                '<h5>Response Body</h5>',
                                that.format(xhr.responseText),
                                '(' + xhr.responseText.length + ' bytes)'
                            ];
                            that.result_node.innerHTML = '';
                            for (var i = 0; i < data.length; i++) {
                                that.result_node.innerHTML += data[i];
                            }
                        }
                    };

                    // Get parameters and fill them into path, query string and POST data
                    var input = this.get_parameters();
                    if (input['__error__']) {
                        this.result_node.innerHTML = 'ERROR: Missing data.';
                        return false;
                    }

                    var path = this.resource.path;
                    var data = '';
                    // Request parameters
                    for (param_name in this.method.parameters) {
                        var param = this.method.parameters[param_name];
                        if (param['path_param']) {
                            path = path.replace('{' + param_name + '}', input['params'][param_name]);
                        } else {
                            data += escape(param_name) + '=' + escape(input['params'][param_name]) + '&';
                        }
                    }

                    if (data === '') {
                        data = null;
                    } else if (this.method_name == 'GET' || this.method_name == 'HEAD') {
                        // Convert data to query string
                        path += '?' + data;
                        data = null;
                    }

                    xhr.open(this.method_name, path, true);
                    if (data !== null) {
                        xhr.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');
                    }
                    // Request headers
                    for (header in input['headers']) {
                        xhr.setRequestHeader(header, input['headers'][header]);
                    }
                    xhr.send(data);

                    return false;
                };
                pr.format = function(str) {
                    var str = str.replace(/&/g, "&").replace(/</g, "<").
                        replace(/>/g, ">");
                    // Linkify HTTP URLs
                    str = str.replace(/(http:\/\/[^ ]+)/g, '<a href="$1" target="_blank">$1</a>');
                    str = '<pre>' + str + '</pre>';
                    return str;
                };
                pr.get_status = function(status, statusText) {
                    /* Need to get the status text manually as statusText is broken on
                       Safari. */
                    if (statusText == 'OK') {
                        // Safari always uses OK, replace it manually
                        var STATI = { 200: 'OK', 201: 'Created', 202: 'Accepted',
                            203: 'Non-Authoritative Information', 204: 'No Content',
                            205: 'Reset Content', 206: 'Partial Content',
                            300: 'Multiple Choices', 301: 'Moved Permanently', 302: 'Found',
                            303: 'See Other', 304: 'Not Modified', 305: 'Use Proxy',
                            307: 'Temporary Redirect', 400: 'Bad Request',
                            401: 'Unauthorized', 402: 'Payment Required', 403: 'Forbidden',
                            404: 'Not Found', 405: 'Method Not Allowed', 406: 'Not Acceptable',
                            407: 'Proxy Authentication Required', 408: 'Request Timeout',
                            409: 'Conflict', 410: 'Gone', 411: 'Length Required',
                            412: 'Precondition Failed', 413: 'Request Entity Too Large',
                            414: 'Request-URI Too Long', 415: 'Unsupported Media Type',
                            416: 'Requested Range Not Satisfiable', 417: 'Expectation Failed',
                            500: 'Internal Server Error', 501: 'Not Implemented',
                            502: 'Bad Gateway', 503: 'Service Unavailable',
                            504: 'Gateway Timeout', 505: 'HTTP Version Not Supported'
                        };
                        if (typeof(STATI[status]) !== 'undefined') {
                            return STATI[status];
                        }
                    }
                    return statusText;
                };
                pr.get_parameters = function() {
                    var params = {'__error__': false, 'headers': {}, 'params': {}};
                    var fields = [];

                    // Get all fields
                    var inputs = this.target.getElementsByTagName('input');
                    for (var i = 0; i < inputs.length; i++) {
                        fields.push(inputs[i]);
                    }
                    var selects = this.target.getElementsByTagName('select');
                    for (var i = 0; i < selects.length; i++) {
                        fields.push(selects[i]);
                    }

                    var inp = null;
                    for (var i = 0; i < fields.length; i++) {
                        inp = fields[i];
                        var type = inp.parentNode.className;
                        if (type == 'header') {
                            params['headers'][inp.name] = inp.value;
                        } else if (type == 'param') {
                            inp.className = '';
                            params['params'][inp.name] = inp.value;

                            // Validate input
                            if (this.method.parameters[inp.name]['mandatory'] && inp.value === '') {
                                inp.className = 'error';
                                params['__error__'] = true;
                            }
                        }
                    }
                    return params;
                };

                /* Hides all .resource_details elements and inserts a toggle link at their
                   place. */
                function toggle_visibility() {
                    var divs = document.getElementsByTagName('div');
                    var len = divs.length;
                    for (var i = 0; i < len; i++) {
                        var div = divs[i];
                        if (div.className == 'method_details') {
                            toggle_visibility_div(div);
                        }
                    }
                }

                function toggle_visibility_div(div) {
                    div.className += ' hidden';
                    var link = document.createElement('a');
                    link.innerHTML = 'Show details';
                    link.href = '#';
                    link.className = 'toggle_details';
                    link.onclick = function() {
                        console.debug(div);
                        if (link.innerHTML == 'Show details') {
                            div.className = div.className.replace(' hidden', '');
                            link.innerHTML = 'Hide details';
                        } else {
                            div.className += ' hidden';
                            link.innerHTML = 'Show details';
                        }
                        return false;
                    };
                    div.parentNode.insertBefore(link, div);
                }
                </script>
            </head>
            <body>
                <h1>WsgiService help</h1>
        """]
        self.to_text_html_overview(retval, raw)
        self.to_text_html_resources(retval, raw)
        retval.append('<script>toggle_visibility();</script>')
        retval.append('</body></html>')
        return re.compile('^ *', re.MULTILINE).sub('', "".join(retval))

    def to_text_html_overview(self, retval, raw):
        """Add the overview table to the HTML output.

        :param retval: The list of strings which is used to collect the HTML
                       response.
        :type retval: list
        :param raw: The original return value of this resources :func:`GET`
                    method.
        :type raw: Dictionary
        """
        retval.append('<table id="overview">')
        retval.append('<tr><th>Resource</th><th>Path</th><th>Description</th></tr>')
        for resource in raw:
            retval.append('<tr><td><a href="#{0}">{0}</a></td><td>{1}</td><td>{2}</td></tr>'.format(
                xml_escape(resource['name']), xml_escape(resource['path']),
                xml_escape(resource['desc'])))
        retval.append('</table>')

    def to_text_html_resources(self, retval, raw):
        """Add the resources details to the HTML output.

        :param retval: The list of strings which is used to collect the HTML
                       response.
        :type retval: list
        :param raw: The original return value of this resources :func:`GET`
                    method.
        :type raw: Dictionary
        """
        for resource in raw:
            retval.append('<div class="resource_details">')
            retval.append('<h2 id="{0}">{0}</h2>'.format(
                xml_escape(resource['name'])))
            if resource['desc']:
                retval.append('<p class="desc">{0}</p>'.format(xml_escape(resource['desc'])))
            retval.append('<table class="config">')
            retval.append('<tr><th>Path</th><td>{0}</td>'.format(xml_escape(
                resource['path'])))
            representations = [value + ' (.' + key + ')' for key, value
                in resource['properties']['EXTENSION_MAP'].iteritems()]
            retval.append('<tr><th>Representations</th><td>{0}</td>'.format(
                xml_escape(', '.join(representations))))
            retval.append('</table>')
            self.to_text_html_methods(retval, resource)
            retval.append('</div>')

    def to_text_html_methods(self, retval, resource):
        """Add the methods of this resource to the HTML output.

        :param retval: The list of strings which is used to collect the HTML
                       response.
        :type retval: list
        :param resource: The documentation of one resource.
        :type resource: Dictionary
        """
        for method_name, method in resource['methods'].iteritems():
            retval.append('<h3 id="{0}_{1}">{1}</h3>'.format(
                xml_escape(resource['name']), xml_escape(method_name)))
            retval.append('<div class="method_details" id="{0}_{1}_container">'.format(
                xml_escape(resource['name']), xml_escape(method_name)))
            if method['desc']:
                retval.append('<p class="desc">{0}</p>'.format(xml_escape(method['desc'])))
            if method['parameters']:
                retval.append('<table class="parameters">')
                retval.append('<tr><th>Name</th><th>Mandatory</th><th>Description</th><th>Validation</th>')
                for param_name, param in method['parameters'].iteritems():
                    # filter out any parameters that can't be written as html.
                    # can contain stuff in other encodings than ascii,
                    # so convert it to ascii
                    mandatory = '-'
                    description = param['desc'].encode('ascii', 'replace')
                    validation = ''
                    if param['mandatory']:
                        mandatory = 'Yes'
                        # the 'convert' key is a <type 'function'> that can't
                        # be written as a string, so convert it to one.
                        if type(param['mandatory']) is dict and \
                                'convert' in param['mandatory']:
                            param['mandatory']['convert'] = \
                                    str(param['mandatory']['convert'])
                    if param['path_param']:
                        mandatory += ' (Path parameter)'
                    if param['validate_re']:
                        validation = 'Regular expression: <tt>' + \
                            xml_escape(param['validate_re'].encode('ascii', 'replace')) + \
                                        '</tt>'
                    retval.append('<tr><td>{0}</td><td>{1}</td><td>{2}</td>'
                        '<td>{3}</td>'.format(xml_escape(param_name),
                        xml_escape(mandatory), xml_escape(description), validation))
                retval.append('</table>')
            retval.append('</div>')
            retval.append('<script>add_resource_method({0},{1},{2},{3});</script>'.format(
                xml_escape(json.dumps(resource['name']+'_'+method_name+'_container')),
                xml_escape(json.dumps(resource)),
                xml_escape(json.dumps(method_name)),
                xml_escape(json.dumps(method))))

class NotFoundResource(Resource):
    EXTENSION_MAP = [('.html', 'text/html')] + Resource.EXTENSION_MAP

    def GET(self):
        self.response.status = 404
        return {'error': 'The requested resource does not exist.'}

    def get_method(self, method=None):
        return 'GET'

    def handle_ignored_resources(self):
        return

    def to_text_html(self, raw):
        return "".join([
            '<html>',
            '<head><title>404 Not Found</title></head>',
            '<body>',
            '<center><h1>404 Not Found</h1></center>',
            '<center>The requested resource does not exist.</center>',
            '</body></html>'
        ])