001package com.randomnoun.common.servlet;
002
003/* (c) 2013 randomnoun. All Rights Reserved. This work is licensed under a
004 * BSD Simplified License. (http://www.randomnoun.com/bsd-simplified.html)
005 */
006
007import java.io.ByteArrayOutputStream;
008import java.io.IOException;
009import java.io.InputStream;
010import java.io.PrintWriter;
011import java.text.ParseException;
012import java.util.List;
013import java.util.Map;
014
015import jakarta.servlet.ServletConfig;
016import jakarta.servlet.ServletException;
017import jakarta.servlet.http.HttpServletRequest;
018import jakarta.servlet.http.HttpServletResponse;
019
020import org.apache.log4j.Logger;
021
022import com.randomnoun.common.MRUCache;
023import com.randomnoun.common.StreamUtil;
024import com.randomnoun.common.Text;
025
026/**
027 * Deliver a page containing multiple javascript files
028 *
029 * Parameters:
030 * js - csv list of javascript files. 
031 *      in this list of files the ".js" extension is optional
032 *      files will be retrieved from "/js" relative directory 
033 * 
034 */
035public class MultiJavascriptServlet extends jakarta.servlet.http.HttpServlet implements jakarta.servlet.Servlet {
036    
037     /** Generated serialVersionUID */
038        private static final long serialVersionUID = -5425445186806002874L;
039
040        /** Cache of combined js */
041    @SuppressWarnings("unchecked")
042        public static Map<String, String> cache = new MRUCache(100, 0, null);
043     
044    /** Logger for this class */
045    public static final Logger logger = Logger.getLogger(MultiJavascriptServlet.class);
046     
047     
048        public MultiJavascriptServlet() {
049                super();
050        }
051        
052        public void init(ServletConfig config) throws ServletException {
053                super.init(config);
054                logger.debug("Calling init");
055        }
056        
057        /** Post method; just defers to get
058         * 
059         * @see jakarta.servlet.http.HttpServlet#doPost(HttpServletRequest request, HttpServletResponse response)
060         */
061        protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
062                doGet(request, response);
063        }
064    
065        /** Lets get this turkey stand on the road
066         * 
067         * @see jakarta.servlet.http.HttpServlet#doGet(HttpServletRequest request, HttpServletResponse response)
068         */
069    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException 
070    {
071                // dump the classpath
072                /*
073                System.out.println("*************************");
074                System.out.println(getClassLoaderTrace(MultiJavascriptServlet.class));
075                System.out.println("*************************");
076                */
077                String result = null;
078                // could cache these results, or respond to If-Modified-Since headers
079                // TODO: Content-Length headers
080                // TODO: maybe store result as byte arrays rather than strings
081                // TODO: try/catch & log everything
082                
083        String js = request.getParameter("js");
084        if (js==null || js.equals("")) { return; }
085        
086        PrintWriter pw = response.getWriter();
087        
088        result = cache.get(js);
089        if (result!=null) { 
090                pw.println(result);
091                return;
092        }
093        
094        ByteArrayOutputStream os = new ByteArrayOutputStream();
095        List<String> files;
096                try {
097                        files = Text.parseCsv(js);
098                } catch (ParseException e) {
099                        logger.error("Invalid js parameter '" + js + "'", e);
100                        throw new IllegalArgumentException("Invalid js parameter");
101                }
102        for (String file : files) {
103                if (!file.endsWith(".js")) {
104                        file+=".js";
105                }
106                // @TODO get relative base from somewhere. referrer ?
107                // request param ? servler init param ?
108                /*InputStream is = MultiJavascriptServlet.class.getClassLoader().
109                  getResourceAsStream("./stocktake/js/" + file);*/
110                InputStream is = getServletContext().getResourceAsStream("/js/" + file);
111                if (is==null) {
112                        logger.error("Unknown file '" + file + "'");
113                        throw new IllegalArgumentException("Unknown file '" + file + "'");
114                }
115                StreamUtil.copyStream(is, os);
116                is.close();
117        }
118        os.flush();
119        result = os.toString();
120        cache.put(js, result);
121        pw.println(result);
122        }       
123}