oblac / jodd

Jodd! Lightweight. Java. Zero dependencies. Use what you like.
https://jodd.org
BSD 2-Clause "Simplified" License
4.06k stars 723 forks source link

About `AbstractTemplateViewResult` and `ServletDispatcherResult` #88

Closed zqq90 closed 10 years ago

zqq90 commented 10 years ago

i just see the last commit 10422ed86c52f6beaa277dc331db1260365a89bf it should be wonderful if has a AbstractTemplateViewResult .

code without test:

public abstract class AbstractTemplateViewResult extends BaseActionResult<String> {

    private static final Logger log = LoggerFactory.getLogger(ServletDispatcherResult.class);

    public AbstractTemplateViewResult(String name) {
        super(name);
        targetCache = new HashMap<String, String>(256);
    }
    protected HashMap<String, String> targetCache;

    @In(scope = ScopeType.CONTEXT)
    protected ResultMapper resultMapper;

    @Override
    public void render(ActionRequest actionRequest, String resultValue) throws Exception {
        final String actionAndResultPath = actionRequest.getActionPath() + (resultValue != null ? ':' + resultValue : StringPool.EMPTY);
        String target = targetCache.get(actionAndResultPath);

        if (target == null) {
            if (log.isDebugEnabled()) {
                log.debug("target not found: " + actionAndResultPath);
            }
            target = resolveTarget(actionRequest, resultValue);
            // store target in cache
            if (target == null) {
                actionRequest.getHttpServletResponse().sendError(SC_NOT_FOUND, "Result not found: " + actionAndResultPath);
                return;
            }
            if (log.isDebugEnabled()) {
                log.debug("target found: " + target);
            }
            targetCache.put(actionAndResultPath, target);
        }
        renderView(actionRequest, target);
    }

    protected String resolveTarget(ActionRequest actionRequest, String resultValue) {

        ResultPath resultPath = resultMapper.resolveResultPath(actionRequest.getActionPath(), resultValue);

        String actionPath = resultPath.getPath();
        String path = actionPath;
        String value = resultPath.getValue();
        String target;
        for (;;) {
            // variant #1: with value
            if (value != null) {
                if (path == null) {
                    // only value remains
                    int lastSlashNdx = actionPath.lastIndexOf('/');
                    if (lastSlashNdx != -1) {
                        target = actionPath.substring(0, lastSlashNdx + 1) + value;
                    } else {
                        target = '/' + value;
                    }
                } else {
                    target = path + '.' + value;
                }

                if ((target = processTargetIfExist(actionRequest, target)) != null) {
                    break;
                }
            }

            if (path != null) {
                // variant #2: without value
                if ((target = processTargetIfExist(actionRequest, path)) != null) {
                    break;
                }
            } else {
                //actionRequest.getHttpServletResponse().sendError(SC_NOT_FOUND, "Result not found: " + resultPath);
                return null;
            }

            int dotNdx = MadvocUtil.lastIndexOfDotAfterSlash(path);
            if (dotNdx == -1) {
                path = null;
            } else {
                path = path.substring(0, dotNdx);
            }
        }
        return target;
    }

    protected abstract String processTargetIfExist(ActionRequest actionRequest, String target);

    protected abstract void renderView(ActionRequest actionRequest, String target) throws Exception;
}
public class ServletDispatcherResult extends AbstractTemplateViewResult {

    public static final String NAME = "dispatch";

    protected String[] extensions = new String[]{".jspf", ".jsp"};

    public ServletDispatcherResult() {
        super(NAME);
    }

    @Override
    protected String processTargetIfExist(final ActionRequest actionRequest, final String path) {
        if (path == null) {
            return null;
        }
        String target;
        final ServletContext servletContext = actionRequest.getHttpServletRequest().getSession().getServletContext();
        for (String ext : extensions) {
            target = path + ext; //append extension
            target = processTarget(servletContext, target);
            if (targetExist(servletContext, target)) {
                return target;
            }
        }
        return null;
    }

    protected String processTarget(ServletContext servletContext, String target) {
        return target;
    }

    protected boolean targetExist(ServletContext servletContext, String target) {
        try {
            return servletContext.getResource(target) != null;
        } catch (MalformedURLException ignore) {
            return false;
        }
    }

    @Override
    protected void renderView(ActionRequest actionRequest, String target) throws Exception {

        HttpServletRequest request = actionRequest.getHttpServletRequest();
        HttpServletResponse response = actionRequest.getHttpServletResponse();

        RequestDispatcher dispatcher = request.getRequestDispatcher(target);
        if (dispatcher == null) {
            response.sendError(SC_NOT_FOUND, "Result not found: " + target);    // should never happened
            return;
        }

        // If we're included, then include the view, otherwise do forward.
        // This allow the page to, for example, set content type.
        if (DispatcherUtil.isPageIncluded(request, response)) {
            dispatcher.include(request, response);
        } else {
            dispatcher.forward(request, response);
        }
    }
}
igr commented 10 years ago

Got it, you want to reuse the base for other templates, like webit :)

Thank you for the submission! Just want to rename the processTargetIfExist method :) Also processTarget should be called only once, for already founded target.

I will commit it today! I tried to refactor this few days ago in the similar way, but your idea is better! Thank you again :smile:

igr commented 10 years ago

Please see the commit