com.paladin.mvc.URLMappingFilter.java Source code

Java tutorial

Introduction

Here is the source code for com.paladin.mvc.URLMappingFilter.java

Source

/**
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *          http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package com.paladin.mvc;

import org.apache.commons.lang3.StringUtils;

import javax.servlet.*;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.File;
import java.io.IOException;
import java.net.URLEncoder;
import java.util.*;

/**
 * ???URL
 *
 * @author Winter Lau (http://my.oschina.net/javayou)<br>
 * @modify Erhu
 */
public class URLMappingFilter implements Filter {

    private ServletContext context;

    public final static String REQUEST_URI = "request_uri"; // {/index}
    private String PATH_PREFIX;
    private final static String VM_EXT = ".vm";
    private final static String VM_INDEX = "/index" + VM_EXT;

    private String rootDomain = "oschina.net";
    private String default_base;
    private HashMap<String, String> other_base = new HashMap<String, String>();
    private List<String> ignoreURIs = new ArrayList<String>();
    private List<String> ignoreExts = new ArrayList<String>();

    @Override
    public void init(FilterConfig cfg) throws ServletException {
        this.context = cfg.getServletContext();

        // ?  
        this.PATH_PREFIX = cfg.getInitParameter("template-path-prefix");
        if (this.PATH_PREFIX == null)
            this.PATH_PREFIX = "/WEB-INF/templates";
        else if (this.PATH_PREFIX.endsWith("/"))
            this.PATH_PREFIX = this.PATH_PREFIX.substring(0, this.PATH_PREFIX.length() - 1);

        // ? URL ??? /img/***
        String ignores = cfg.getInitParameter("ignore");
        if (ignores != null)
            for (String ig : StringUtils.split(ignores, ','))
                ignoreURIs.add(ig.trim());

        // ? URL ?? ? ? *.jpg
        ignores = cfg.getInitParameter("ignoreExts");
        if (ignores != null)
            for (String ig : StringUtils.split(ignores, ','))
                ignoreExts.add('.' + ig.trim());

        // ?? 
        String tmp = cfg.getInitParameter("domain");
        if (StringUtils.isNotBlank(tmp))
            rootDomain = tmp;

        //  ??   ? ? 
        @SuppressWarnings("unchecked")
        Enumeration<String> names = cfg.getInitParameterNames();
        while (names.hasMoreElements()) {
            String name = names.nextElement();
            String v = cfg.getInitParameter(name);
            if (v.endsWith("/"))
                v = v.substring(0, v.length() - 1);
            if ("ignore".equalsIgnoreCase(name) || "ignoreExts".equalsIgnoreCase(name))
                continue;
            if ("default".equalsIgnoreCase(name))
                default_base = PATH_PREFIX + v;
            else
                other_base.put(name, PATH_PREFIX + v);
        }
    }

    @Override
    public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain)
            throws IOException, ServletException {
        //  ? ?
        HttpServletRequest request = (HttpServletRequest) req;
        HttpServletResponse response = (HttpServletResponse) res;
        RequestContext rc = RequestContext.begin(this.context, request, response);

        String req_uri = rc.uri();

        try {
            //  URL ?
            for (String ignoreURI : ignoreURIs) {
                if (req_uri.startsWith(ignoreURI)) {
                    chain.doFilter(rc.request(), rc.response());
                    return;
                }
            }
            //  URL ?
            for (String ignoreExt : ignoreExts) {
                if (req_uri.endsWith(ignoreExt)) {
                    chain.doFilter(rc.request(), rc.response());
                    return;
                }
            }

            rc.request().setAttribute(REQUEST_URI, req_uri);
            String[] paths = StringUtils.split(req_uri, '/');
            String vm = _GetTemplate(rc.request(), paths, paths.length);

            rc.forward(vm);

        } catch (SecurityException e) {
            String login_page = e.getMessage() + "?goto_page=" + URLEncoder.encode(req_uri, "utf-8");
            rc.redirect(login_page);
        } finally {
            if (rc != null)
                rc.end();
        }
    }

    @Override
    public void destroy() {
    }

    private String _GetTemplate(HttpServletRequest req, String[] paths, int idx_base) {
        StringBuilder vm = new StringBuilder(_GetTemplateBase(req));

        if (idx_base == 0)
            return vm.toString() + VM_INDEX + _MakeQueryString(paths, idx_base);

        for (int i = 0; i < idx_base; i++) {
            vm.append('/');
            vm.append(paths[i]);
        }
        String vms = vm.toString();
        String the_path = vms;

        if (_IsVmExist(the_path + VM_EXT))
            return the_path + VM_EXT + _MakeQueryString(paths, idx_base);

        the_path += VM_INDEX;

        if (_IsVmExist(the_path))
            return the_path + _MakeQueryString(paths, idx_base);

        vms += VM_EXT;
        if (_IsVmExist(vms))
            return vms + _MakeQueryString(paths, idx_base);

        return _GetTemplate(req, paths, idx_base - 1);
    }

    private String _MakeQueryString(String[] paths, int idx_base) {
        StringBuilder params = new StringBuilder();
        int idx = 1;
        for (int i = idx_base; i < paths.length; i++) {
            if (params.length() == 0)
                params.append('?');
            if (i > idx_base)
                params.append('&');
            params.append("p");
            params.append(idx++);
            params.append('=');
            params.append(paths[i]);
        }
        return params.toString();
    }

    private String _GetTemplateBase(HttpServletRequest req) {
        String base = null;
        String prefix = req.getServerName().toLowerCase();
        int idx = (rootDomain != null) ? prefix.indexOf(rootDomain) : 0;
        if (idx > 0) {
            prefix = prefix.substring(0, idx - 1);
            base = other_base.get(prefix);
        }
        return (base == null) ? default_base : base;
    }

    private final static List<String> vm_cache = new Vector<String>();

    /**
     * ???
     *
     * @param path
     * @return
     */
    private boolean _IsVmExist(String path) {
        if (vm_cache.contains(path))
            return true;
        File testFile = new File(context.getRealPath(path));
        boolean isVM = testFile.exists() && testFile.isFile();
        if (isVM)
            vm_cache.add(path);
        return isVM;
    }
}