com.asual.lesscss.ResourceServlet.java Source code

Java tutorial

Introduction

Here is the source code for com.asual.lesscss.ResourceServlet.java

Source

/*
 * Copyright 2009-2010 the original author or authors.
 *
 * 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.asual.lesscss;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.util.HashMap;
import java.util.Map;

import javax.naming.Context;
import javax.naming.NamingException;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

/**
 * @author Rostislav Hristov
 */
public class ResourceServlet extends HttpServlet {

    private static final long serialVersionUID = 413708886190444579L;
    private final Log logger = LogFactory.getLog(getClass());
    protected Context initialContext = null;
    protected boolean cache = true;
    protected boolean compress = true;
    protected int maxAge = 31556926;
    protected long milliseconds = 1000L;
    protected String charset = "UTF-8";
    protected String separator = ";";
    protected Map<String, Resource> resources;
    protected Map<String, String> mimeTypes = new HashMap<String, String>();
    {
        mimeTypes.put("css", "text/css");
        mimeTypes.put("less", "text/css");
        mimeTypes.put("html", "text/html");
        mimeTypes.put("htm", "text/html");
        mimeTypes.put("js", "text/javascript");
        mimeTypes.put("txt", "text/plain");
        mimeTypes.put("xml", "text/xml");
        mimeTypes.put("gif", "image/gif");
        mimeTypes.put("ico", "image/x-icon");
        mimeTypes.put("jpeg", "image/jpeg");
        mimeTypes.put("jpg", "image/jpeg");
        mimeTypes.put("png", "image/png");
        mimeTypes.put("svg", "image/svg+xml");

        mimeTypes.put("oga", "audio/ogg");
        mimeTypes.put("ogg", "audio/ogg");
        mimeTypes.put("ogv", "video/ogg");
        mimeTypes.put("mp4", "video/mp4");
        mimeTypes.put("webm", "video/webm");

        mimeTypes.put("ttf", "font/truetype");
        mimeTypes.put("otf", "font/opentype");
        mimeTypes.put("eot", "application/vnd.ms-fontobject");
        mimeTypes.put("woff", "application/x-font-woff");
    }

    public void init() {

        if (getServletConfig() != null) {
            if (getInitParameter("charset") != null) {
                charset = getInitParameter("charset");
            }
            if (getInitParameter("separator") != null) {
                separator = getInitParameter("separator");
            }
            if (getInitParameter("cache") != null) {
                cache = Boolean.valueOf(getInitParameter("cache"));
            }
            if (getInitParameter("compress") != null) {
                compress = Boolean.valueOf(getInitParameter("compress"));
            }
        }

        try {
            initialContext = new javax.naming.InitialContext();
        } catch (NamingException e) {
        } catch (NoClassDefFoundError e) {
        }

        if (initialContext != null) {
            if (getJndiParameter("Charset") != null) {
                charset = (String) getJndiParameter("Charset");
            }
            if (getJndiParameter("Separator") != null) {
                separator = (String) getJndiParameter("Separator");
            }
            if (getJndiParameter("Cache") != null) {
                cache = (Boolean) getJndiParameter("Cache");
            }
            if (getJndiParameter("Compress") != null) {
                compress = (Boolean) getJndiParameter("Compress");
            }
        }

        resources = new HashMap<String, Resource>();
    }

    protected Object getJndiParameter(String name) {
        try {
            return initialContext.lookup("java:comp/env/resource/" + name);
        } catch (NamingException ne) {
        }
        return null;
    }

    protected Resource getResource(String uri) throws ResourceNotFoundException {

        String mimeType = getResourceMimeType(uri);
        if (!resources.containsKey(uri)) {
            if ("text/css".equals(mimeType)) {
                resources.put(uri, new StyleResource(getServletContext(), uri, charset, cache, compress));
            } else if ("text/javascript".equals(mimeType)) {
                resources.put(uri, new ScriptResource(getServletContext(), uri, charset, cache, compress));
            } else {
                resources.put(uri, new Resource(getServletContext(), uri, charset, cache));
            }
        }
        return resources.get(uri);
    }

    protected byte[] getResourceContent(String uri) throws Exception {

        Resource resource = getResource(uri);
        return resource.getContent();
    }

    protected long getResourceLastModified(String uri) throws ResourceNotFoundException, IOException {

        Resource resource = getResource(uri);
        return resource.getLastModified();
    }

    protected String getResourceMimeType(String uri) {

        String extension = uri.substring(uri.lastIndexOf(".") + 1);
        String mimeType = mimeTypes.containsKey(extension) ? mimeTypes.get(extension)
                : getServletContext().getMimeType(uri);
        return mimeType != null ? mimeType : "application/octet-stream";
    }

    protected byte[] mergeContent(byte[] c1, byte[] c2) throws UnsupportedEncodingException {

        byte[] line = "\n".getBytes(charset);
        int l1 = c1.length;
        int l2 = l1 != 0 ? line.length : 0;
        int l3 = c2.length;
        byte[] result = new byte[l1 + l2 + l3];

        for (int i = 0; i < l1; i++) {
            result[i] = c1[i];
        }
        for (int i = 0; i < l2; i++) {
            result[i + l1] = line[i];
        }
        for (int i = 0; i < l3; i++) {
            result[i + l1 + l2] = c2[i];
        }
        return result;
    }

    public void service(HttpServletRequest request, HttpServletResponse response) throws ServletException {

        try {

            String pkg = request.getParameter("pack");
            String[] uri = (pkg != null) ? pkg.split(separator)
                    : new String[] { request.getRequestURI().replaceAll("/+", "/") };
            String mimeType = getResourceMimeType(uri[0]);

            long lastModified = 0;
            byte[] content = new byte[0];

            for (String resource : uri) {
                resource = resource.replaceAll("^" + request.getContextPath(), "");
                try {
                    content = mergeContent(content, getResourceContent(resource));
                } catch (FileNotFoundException e) {
                    response.setStatus(HttpServletResponse.SC_NOT_FOUND);
                    return;
                } catch (ResourceNotFoundException e) {
                    response.setStatus(HttpServletResponse.SC_NOT_FOUND);
                    return;
                }
                lastModified = Math.max(lastModified, getResourceLastModified(resource));
            }

            long ifModifiedSince = request.getDateHeader("If-Modified-Since");
            if (ifModifiedSince != 0 && ifModifiedSince / milliseconds == lastModified / milliseconds) {
                logger.debug("Return with SC_NOT_MODIFIED, since " + ifModifiedSince + " == " + lastModified);
                response.setStatus(HttpServletResponse.SC_NOT_MODIFIED);
                return;
            }

            response.setContentType(mimeType + (mimeType.startsWith("text/") ? ";charset=" + charset : ""));
            if (cache) {
                response.setDateHeader("Expires", System.currentTimeMillis() + maxAge * milliseconds);
                response.setDateHeader("Last-Modified", lastModified);
                response.setHeader("Cache-control", "max-age=" + maxAge);
            } else {
                response.setDateHeader("Expires", System.currentTimeMillis());
                response.setDateHeader("Last-Modified", System.currentTimeMillis());
                response.setHeader("Cache-control", "max-age=0");
            }
            response.setContentLength(content.length);
            response.getOutputStream().write(content);
            response.getOutputStream().flush();
            response.getOutputStream().close();

        } catch (Exception e) {
            throw new ServletException(e.getMessage(), e);
        }
    }
}