All Downloads are FREE. Search and download functionalities are using the official Maven repository.

javaxt.http.servlet.JspServlet Maven / Gradle / Ivy

package javaxt.http.servlet;

import java.io.IOException;

import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.tools.FileObject;
import javax.tools.ForwardingJavaFileManager;
import javax.tools.JavaCompiler;
import javax.tools.JavaFileManager;
import javax.tools.JavaFileObject;
import javax.tools.JavaFileObject.Kind;
import javax.tools.SimpleJavaFileObject;
import javax.tools.StandardJavaFileManager;
import javax.tools.ToolProvider;

//******************************************************************************
//**  JSP Servlet
//******************************************************************************
/**
 * Http Servlet used to serve JSP files. JSP files are converted into servlet
 * code and compiled at runtime.
 * 

* * Note that this class is only a partial implementation of the JavaServer Pages * 2.1 specification. Tag libraries and other "advanced" features are not * supported at this time. * ******************************************************************************/ public class JspServlet extends HttpServlet { private java.io.File jspFile; private long date; private Object instance; private java.lang.reflect.Method method; private static final Class[] parameterTypes = { HttpServletRequest.class, HttpServletResponse.class }; private String pageEncoding = "ISO-8859-1"; // ************************************************************************** // ** Constructor // ************************************************************************** /** * Instantiates this class using a single JSP file. * * @param jspFile * A JSP file. */ public JspServlet(java.io.File jspFile) throws Exception { this.jspFile = jspFile; this.date = jspFile.lastModified(); compile(jspFile); } // ************************************************************************** // ** Constructor // ************************************************************************** /** * Constructor for application developers who wish to extend this class. */ protected JspServlet() { } // ************************************************************************** // ** processRequest // ************************************************************************** @Override public void service(ServletRequest request, ServletResponse response) throws javax.servlet.ServletException, IOException { // response.setContentType("text/html"); // response.setCharacterEncoding(pageEncoding); try { if (jspFile != null && jspFile.lastModified() != date) { compile(jspFile); date = jspFile.lastModified(); } method.invoke(instance, new Object[] { request, response }); } catch (Exception e) { throw new ServletException(e.getLocalizedMessage()); } } // ************************************************************************** // ** compile // ************************************************************************** /** * Used to parse a JSP file and generate servlet code. The servlet is then * compiled into byte-code and invoked by the processRequest() method. */ protected void compile(java.io.File jspFile) throws java.io.IOException, java.lang.ClassNotFoundException, java.lang.InstantiationException, java.lang.IllegalAccessException, java.lang.NoSuchMethodException { String source = this.getText(jspFile); String className = jspFile.getName(); compile(source, className); } // ************************************************************************** // ** compile // ************************************************************************** /** * Used to parse content from a JSP file and generate servlet code. The * servlet is then compiled into byte-code and invoked by the * processRequest() method. */ protected void compile(String source, String className) throws java.io.IOException, java.lang.ClassNotFoundException, java.lang.InstantiationException, java.lang.IllegalAccessException, java.lang.NoSuchMethodException { if (className.contains(".")) className = className.substring(0, className.indexOf(".")); java.util.HashSet imports = new java.util.HashSet(); imports.add("javaxt.http.servlet.*"); StringBuffer functions = new StringBuffer(); StringBuffer main = new StringBuffer(); String[] arr = source.split("<%"); for (String str : arr) { String code = ""; String html = ""; if (str.contains("%>")) { code = str.substring(0, str.indexOf("%>")); html = str.substring(str.indexOf("%>") + 2); } else { html = str; } if (code.startsWith("!")) { functions.append(code.substring(1)); code = ""; } else if (code.startsWith("=")) { code = code.substring(1).trim(); code = " str.append(" + code + ");\r\n"; } else if (code.startsWith("@")) { code = code.substring(1).trim(); if (code.startsWith("page")) { code = code.substring(4).trim(); org.w3c.dom.NamedNodeMap attributes = getAttributes(code); for (int i = 0; i < attributes.getLength(); i++) { org.w3c.dom.Node attr = attributes.item(i); String name = attr.getNodeName(); String value = attr.getTextContent().trim(); if (value.length() > 0) { if (name.equals("import")) imports.add(value); else if (name.equalsIgnoreCase("pageEncoding")) pageEncoding = value; else { log().d(name + ": " + value); } } } code = ""; } } else if (code.startsWith("--")) { code = ""; } else { code = " " + code + "\r\n"; } // Wrap html in an append statement html = html.replace("\"", "\\\""); StringBuffer s = new StringBuffer(); for (String line : html.split("\n")) { line = line.replace("\r", ""); if (line.trim().length() > 0) { s.append(" str.append(\""); s.append(line); s.append("\");\r\n"); s.append(" str.append(\"\\r\\n\");\r\n"); } } html = s.toString(); main.append(code); main.append(html); } StringBuilder src = new StringBuilder(); java.util.Iterator it = imports.iterator(); while (it.hasNext()) { src.append("import " + it.next() + ";\r\n"); } src.append("public class " + className + " extends HttpServlet {\r\n"); src.append(functions); src.append(" public void processRequest(HttpServletRequest request, HttpServletResponse response)\r\n"); src.append(" throws ServletException, java.io.IOException {\r\n"); /* * response.setContentType("text/html;charset=ISO-8859-1"); JspFactory * _jspxFactory = JspFactory.getDefaultFactory(); PageContext * pageContext = _jspxFactory.getPageContext(this, request, response, * null, true, 8192, true); * * ServletContext application = pageContext.getServletContext(); * ServletConfig config = pageContext.getServletConfig(); HttpSession * session = pageContext.getSession(); * * JspWriter out = pageContext.getOut(); JspWriter _jspx_out = out; * PageContext _jspx_page_context = pageContext; */ src.append(" StringBuffer str = new StringBuffer();\r\n"); src.append(main); src.append(" response.write(str.toString());\r\n"); src.append(" }\r\n"); src.append("}"); // System.out.println(src); // Get an instance of a JavaCompiler. This requires access to the JDK. JavaCompiler compiler = ToolProvider.getSystemJavaCompiler(); if (compiler == null) throw new java.io.IOException("Compiler not found. Are you using a JDK?"); // Then we create a custom file manager JavaFileManager fileManager = new ClassFileManager(compiler.getStandardFileManager(null, null, null)); // Dynamic compiling requires specifying a list of "files" to compile. // In // our case this is a list containing one "file" which is in our case // our // own implementation (see details below) java.util.List jfiles = new java.util.ArrayList(); jfiles.add(new CharSequenceJavaFileObject(className, src)); // Specify a task for the compiler. Compiler should use our file manager // and our list of "files". Then we run the compilation with call() compiler.getTask(null, fileManager, null, null, null, jfiles).call(); // Load the class and create a new instance Class classToLoad = fileManager.getClassLoader(null).loadClass(className); instance = classToLoad.newInstance(); // Find the "processRequest" method method = classToLoad.getMethod("processRequest", parameterTypes); } // ************************************************************************** // ** getText // ************************************************************************** /** Returns the content of a file as a String. */ private String getText(java.io.File jspFile) { if (jspFile.exists()) { try { java.io.ByteArrayOutputStream bas = new java.io.ByteArrayOutputStream(); java.io.FileInputStream is = new java.io.FileInputStream(jspFile); java.nio.channels.FileChannel inputStream = is.getChannel(); java.nio.ByteBuffer buf = java.nio.ByteBuffer.allocateDirect(1024); while (inputStream.read(buf) > -1) { byte[] arr = new byte[buf.position()]; buf.rewind(); buf.get(arr); bas.write(arr); buf.clear(); buf.rewind(); } inputStream.close(); is.close(); inputStream = null; is = null; return bas.toString("UTF-8"); } catch (Exception e) { } } return null; } // ************************************************************************** // ** getAttributes // ************************************************************************** /** Returns attributes of JSP tag/element. */ private org.w3c.dom.NamedNodeMap getAttributes(String str) { try { str = ""; java.io.InputStream is = new java.io.ByteArrayInputStream(str.getBytes("UTF-8")); javax.xml.parsers.DocumentBuilderFactory builderFactory = javax.xml.parsers.DocumentBuilderFactory .newInstance(); javax.xml.parsers.DocumentBuilder builder = builderFactory.newDocumentBuilder(); org.w3c.dom.Document xml = builder.parse(is); org.w3c.dom.NodeList OuterNodes = xml.getChildNodes(); for (int i = 0; i < OuterNodes.getLength(); i++) { if (OuterNodes.item(i).getNodeType() == 1) { return OuterNodes.item(i).getAttributes(); } } } catch (Exception e) { // e.printStackTrace(); } return null; } // ************************************************************************** // ** CharSequenceJavaFileObject Class // ************************************************************************** private static class CharSequenceJavaFileObject extends SimpleJavaFileObject { /** * CharSequence representing the source code to be compiled */ private CharSequence content; /** * This constructor will store the source code in the internal "content" * variable and register it as a source code, using a URI containing the * class full name * * @param className * name of the public class in the source code * @param content * source code to compile */ public CharSequenceJavaFileObject(String className, CharSequence content) { super(java.net.URI.create("string:///" + className.replace('.', '/') + Kind.SOURCE.extension), Kind.SOURCE); this.content = content; } /** * Answers the CharSequence to be compiled. It will give the source code * stored in variable "content" */ @Override public CharSequence getCharContent(boolean ignoreEncodingErrors) { return content; } } private static class JavaClassObject extends SimpleJavaFileObject { /** * Byte code created by the compiler will be stored in this * ByteArrayOutputStream so that we can later get the byte array out of * it and put it in the memory as an instance of our class. */ protected final java.io.ByteArrayOutputStream bos = new java.io.ByteArrayOutputStream(); /** * Registers the compiled class object under URI containing the class * full name * * @param name * Full name of the compiled class * @param kind * Kind of the data. It will be CLASS in our case */ public JavaClassObject(String name, Kind kind) { super(java.net.URI.create("string:///" + name.replace('.', '/') + kind.extension), kind); } /** * Will be used by our file manager to get the byte code that can be put * into memory to instantiate our class * * @return compiled byte code */ public byte[] getBytes() { return bos.toByteArray(); } /** * Will provide the compiler with an output stream that leads to our * byte array. This way the compiler will write everything into the byte * array that we will instantiate later */ @Override public java.io.OutputStream openOutputStream() throws java.io.IOException { return bos; } } private static class ClassFileManager extends ForwardingJavaFileManager { /** * Instance of JavaClassObject that will store the compiled bytecode of * our class */ private JavaClassObject jclassObject; /** * Will initialize the manager with the specified standard java file * manager * * @param standardManger */ public ClassFileManager(StandardJavaFileManager standardManager) { super(standardManager); } /** * Will be used by us to get the class loader for our compiled class. It * creates an anonymous class extending the SecureClassLoader which uses * the byte code created by the compiler and stored in the * JavaClassObject, and returns the Class for it */ @Override public ClassLoader getClassLoader(Location location) { return new java.security.SecureClassLoader() { // @Override @Override protected Class findClass(String name) throws ClassNotFoundException { byte[] b = jclassObject.getBytes(); return super.defineClass(name, jclassObject.getBytes(), 0, b.length); } }; } /** * Gives the compiler an instance of the JavaClassObject so that the * compiler can write the byte code into it. */ @Override public JavaFileObject getJavaFileForOutput(Location location, String className, Kind kind, FileObject sibling) throws java.io.IOException { jclassObject = new JavaClassObject(className, kind); return jclassObject; } } }





© 2015 - 2025 Weber Informatics LLC | Privacy Policy