public ComponentEventRequestParameters decodeComponentEventRequest(String requestPath) {
    Matcher matcher = COMPONENT_EVENT_REQUEST_PATH_PATTERN.matcher(requestPath);

    if (!matcher.matches()) return null;

    String nestedComponentId = matcher.group(NESTED_ID);

    String eventType = matcher.group(EVENT_NAME);

    if (nestedComponentId == null && eventType == null) return null;

    String activePageName = matcher.group(LOGICAL_PAGE_NAME);

    if (!componentClassResolver.isPageName(activePageName)) return null;

    activePageName = componentClassResolver.canonicalizePageName(activePageName);

    EventContext eventContext = new EmptyEventContext();
    // we first encode the value because the link is not built by tapestry and can contain
    // white spaces and other characters that need to be encoded.
    String context = matcher.group(CONTEXT);
    if (context != null) {
      String[] contextSplit = context.split("/");
      StringBuilder encodedContext = new StringBuilder();
      for (String contextToEncode : contextSplit) {
        encodedContext.append(contextPathEncoder.encodeValue(contextToEncode));
        encodedContext.append("/");
      }
      eventContext = contextPathEncoder.decodePath(encodedContext.toString());
    }

    EventContext activationContext = new EmptyEventContext();
    // .decodePath(request.getParameter(InternalConstants.PAGE_CONTEXT_NAME));

    // The event type is often omitted, and defaults to "action".

    if (eventType == null) eventType = EventConstants.ACTION;

    if (nestedComponentId == null) nestedComponentId = "";

    String containingPageName = activePageName;

    return new ComponentEventRequestParameters(
        activePageName,
        containingPageName,
        nestedComponentId,
        eventType,
        activationContext,
        eventContext);
  }
  public boolean dispatch(Request request, Response response) throws IOException {
    /*
     * We need to get the Tapestry page requested by the user. So we parse
     * the path extracted from the request
     */
    String path = request.getPath();
    if (path.equals("")) return false;

    int nextslashx = path.length();
    String pageName;

    while (true) {
      pageName = path.substring(1, nextslashx);
      if (!pageName.endsWith("/") && resolver.isPageName(pageName)) break;
      nextslashx = path.lastIndexOf('/', nextslashx - 1);
      if (nextslashx <= 1) return false;
    }
    return checkAccess(pageName, request, response);
  }
 protected final void train_canonicalizePageName(
     ComponentClassResolver resolver, String pageName, String canonicalized) {
   expect(resolver.canonicalizePageName(pageName)).andReturn(canonicalized);
 }
 protected final void train_isPageName(
     ComponentClassResolver resolver, String pageName, boolean result) {
   expect(resolver.isPageName(pageName)).andReturn(result);
 }
 protected final void stub_isPageName(ComponentClassResolver resolver, boolean result) {
   expect(resolver.isPageName(isA(String.class))).andStubReturn(result);
 }
 protected final void train_resolvePageClassNameToPageName(
     ComponentClassResolver resolver, String pageClassName, String pageName) {
   expect(resolver.resolvePageClassNameToPageName(pageClassName)).andReturn(pageName);
 }