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}