Ejemplo n.º 1
0
  @Override
  public String intercept(ActionInvocation invocation) throws Exception {

    ActionConfig config = invocation.getProxy().getConfig();
    ActionContext ac = invocation.getInvocationContext();
    Object action = invocation.getAction();

    // get the action's parameters
    final Map<String, String> parameters = config.getParams();

    if (parameters.containsKey(aliasesKey)) {

      String aliasExpression = parameters.get(aliasesKey);
      ValueStack stack = ac.getValueStack();
      Object obj = stack.findValue(aliasExpression);

      if (obj != null && obj instanceof Map) {
        // get secure stack
        ValueStack newStack = valueStackFactory.createValueStack(stack);
        boolean clearableStack = newStack instanceof ClearableValueStack;
        if (clearableStack) {
          // if the stack's context can be cleared, do that to prevent OGNL
          // from having access to objects in the stack, see XW-641
          ((ClearableValueStack) newStack).clearContextValues();
          Map<String, Object> context = newStack.getContext();
          ReflectionContextState.setCreatingNullObjects(context, true);
          ReflectionContextState.setDenyMethodExecution(context, true);
          ReflectionContextState.setReportingConversionErrors(context, true);

          // keep locale from original context
          context.put(ActionContext.LOCALE, stack.getContext().get(ActionContext.LOCALE));
        }

        // override
        Map aliases = (Map) obj;
        for (Object o : aliases.entrySet()) {
          Map.Entry entry = (Map.Entry) o;
          String name = entry.getKey().toString();
          String alias = (String) entry.getValue();
          Object value = stack.findValue(name);
          if (null == value) {
            // workaround
            Map<String, Object> contextParameters = ActionContext.getContext().getParameters();

            if (null != contextParameters) {
              value = contextParameters.get(name);
            }
          }
          if (null != value) {
            try {
              newStack.setValue(alias, value);
            } catch (RuntimeException e) {
              if (devMode) {
                String developerNotification =
                    LocalizedTextUtil.findText(
                        ParametersInterceptor.class,
                        "devmode.notification",
                        ActionContext.getContext().getLocale(),
                        "Developer Notification:\n{0}",
                        new Object[] {
                          "Unexpected Exception caught setting '"
                              + entry.getKey()
                              + "' on '"
                              + action.getClass()
                              + ": "
                              + e.getMessage()
                        });
                LOG.error(developerNotification);
                if (action instanceof ValidationAware) {
                  ((ValidationAware) action).addActionMessage(developerNotification);
                }
              }
            }
          }
        }

        if (clearableStack && (stack.getContext() != null) && (newStack.getContext() != null))
          stack
              .getContext()
              .put(
                  ActionContext.CONVERSION_ERRORS,
                  newStack.getContext().get(ActionContext.CONVERSION_ERRORS));
      } else {
        LOG.debug("invalid alias expression:" + aliasesKey);
      }
    }

    return invocation.invoke();
  }
Ejemplo n.º 2
0
  /**
   * Load Action class for mapping and invoke the appropriate Action method, or go directly to the
   * Result.
   *
   * <p>This method first creates the action context from the given parameters, and then loads an
   * <tt>ActionProxy</tt> from the given action name and namespace. After that, the Action method is
   * executed and output channels through the response object. Actions not found are sent back to
   * the user via the {@link Dispatcher#sendError} method, using the 404 return code. All other
   * errors are reported by throwing a ServletException.
   *
   * @param request the HttpServletRequest object
   * @param response the HttpServletResponse object
   * @param mapping the action mapping object
   * @throws ServletException when an unknown error occurs (not a 404, but typically something that
   *     would end up as a 5xx by the servlet container)
   * @param context Our ServletContext object
   */
  public void serviceAction(
      HttpServletRequest request,
      HttpServletResponse response,
      ServletContext context,
      ActionMapping mapping)
      throws ServletException {

    Map<String, Object> extraContext = createContextMap(request, response, mapping, context);

    // If there was a previous value stack, then create a new copy and pass it in to be used by the
    // new Action
    ValueStack stack =
        (ValueStack) request.getAttribute(ServletActionContext.STRUTS_VALUESTACK_KEY);
    boolean nullStack = stack == null;
    if (nullStack) {
      ActionContext ctx = ActionContext.getContext();
      if (ctx != null) {
        stack = ctx.getValueStack();
      }
    }
    if (stack != null) {
      extraContext.put(ActionContext.VALUE_STACK, valueStackFactory.createValueStack(stack));
    }

    String timerKey = "Handling request from Dispatcher";
    try {
      UtilTimerStack.push(timerKey);
      String namespace = mapping.getNamespace();
      String name = mapping.getName();
      String method = mapping.getMethod();

      Configuration config = configurationManager.getConfiguration();
      ActionProxy proxy =
          config
              .getContainer()
              .getInstance(ActionProxyFactory.class)
              .createActionProxy(namespace, name, method, extraContext, true, false);

      request.setAttribute(
          ServletActionContext.STRUTS_VALUESTACK_KEY, proxy.getInvocation().getStack());

      // if the ActionMapping says to go straight to a result, do it!
      if (mapping.getResult() != null) {
        Result result = mapping.getResult();
        result.execute(proxy.getInvocation());
      } else {
        proxy.execute();
      }

      // If there was a previous value stack then set it back onto the request
      if (!nullStack) {
        request.setAttribute(ServletActionContext.STRUTS_VALUESTACK_KEY, stack);
      }
    } catch (ConfigurationException e) {
      // WW-2874 Only log error if in devMode
      if (devMode) {
        String reqStr = request.getRequestURI();
        if (request.getQueryString() != null) {
          reqStr = reqStr + "?" + request.getQueryString();
        }
        LOG.error("Could not find action or result\n" + reqStr, e);
      } else {
        if (LOG.isWarnEnabled()) {
          LOG.warn("Could not find action or result", e);
        }
      }
      sendError(request, response, context, HttpServletResponse.SC_NOT_FOUND, e);
    } catch (Exception e) {
      if (handleException || devMode) {
        sendError(request, response, context, HttpServletResponse.SC_INTERNAL_SERVER_ERROR, e);
      } else {
        throw new ServletException(e);
      }
    } finally {
      UtilTimerStack.pop(timerKey);
    }
  }
  protected void setParameters(
      Object action, ValueStack stack, final Map<String, Object> parameters) {
    ParameterNameAware parameterNameAware =
        (action instanceof ParameterNameAware) ? (ParameterNameAware) action : null;

    Map<String, Object> params;
    Map<String, Object> acceptableParameters;
    if (ordered) {
      params = new TreeMap<String, Object>(getOrderedComparator());
      acceptableParameters = new TreeMap<String, Object>(getOrderedComparator());
      params.putAll(parameters);
    } else {
      params = new TreeMap<String, Object>(parameters);
      acceptableParameters = new TreeMap<String, Object>();
    }

    for (Map.Entry<String, Object> entry : params.entrySet()) {
      String name = entry.getKey();

      boolean acceptableName =
          acceptableName(name)
              && (parameterNameAware == null || parameterNameAware.acceptableParameterName(name));

      if (acceptableName) {
        acceptableParameters.put(name, entry.getValue());
      }
    }

    ValueStack newStack = valueStackFactory.createValueStack(stack);
    boolean clearableStack = newStack instanceof ClearableValueStack;
    if (clearableStack) {
      // if the stack's context can be cleared, do that to prevent OGNL
      // from having access to objects in the stack, see XW-641
      ((ClearableValueStack) newStack).clearContextValues();
      Map<String, Object> context = newStack.getContext();
      ReflectionContextState.setCreatingNullObjects(context, true);
      ReflectionContextState.setDenyMethodExecution(context, true);
      ReflectionContextState.setReportingConversionErrors(context, true);

      // keep locale from original context
      context.put(ActionContext.LOCALE, stack.getContext().get(ActionContext.LOCALE));
    }

    boolean memberAccessStack = newStack instanceof MemberAccessValueStack;
    if (memberAccessStack) {
      // block or allow access to properties
      // see WW-2761 for more details
      MemberAccessValueStack accessValueStack = (MemberAccessValueStack) newStack;
      accessValueStack.setAcceptProperties(acceptParams);
      accessValueStack.setExcludeProperties(excludeParams);
    }

    for (Map.Entry<String, Object> entry : acceptableParameters.entrySet()) {
      String name = entry.getKey();
      Object value = entry.getValue();
      try {
        newStack.setValue(name, value);
      } catch (RuntimeException e) {
        if (devMode) {
          String developerNotification =
              LocalizedTextUtil.findText(
                  ParametersInterceptor.class,
                  "devmode.notification",
                  ActionContext.getContext().getLocale(),
                  "Developer Notification:\n{0}",
                  new Object[] {
                    "Unexpected Exception caught setting '"
                        + name
                        + "' on '"
                        + action.getClass()
                        + ": "
                        + e.getMessage()
                  });
          LOG.error(developerNotification);
          if (action instanceof ValidationAware) {
            ((ValidationAware) action).addActionMessage(developerNotification);
          }
        }
      }
    }

    if (clearableStack && (stack.getContext() != null) && (newStack.getContext() != null))
      stack
          .getContext()
          .put(
              ActionContext.CONVERSION_ERRORS,
              newStack.getContext().get(ActionContext.CONVERSION_ERRORS));

    addParametersToContext(ActionContext.getContext(), acceptableParameters);
  }