package com.sun.grizzly.http.servlet.deployer; import java.io.File; import java.io.FileInputStream; import java.io.IOException; import java.net.MalformedURLException; import java.net.URL; import java.net.URLClassLoader; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; import javax.servlet.Filter; import javax.servlet.Servlet; import javax.xml.bind.JAXBContext; import javax.xml.bind.JAXBElement; import javax.xml.bind.Unmarshaller; import com.sun.grizzly.http.embed.GrizzlyWebServer; import com.sun.grizzly.http.servlet.ServletAdapter; import com.sun.grizzly.http.servlet.xsd.FilterMappingType; import com.sun.grizzly.http.servlet.xsd.FilterType; import com.sun.grizzly.http.servlet.xsd.ListenerType; import com.sun.grizzly.http.servlet.xsd.ParamValueType; import com.sun.grizzly.http.servlet.xsd.ServletMappingType; import com.sun.grizzly.http.servlet.xsd.ServletType; import com.sun.grizzly.http.servlet.xsd.UrlPatternType; import com.sun.grizzly.http.servlet.xsd.WebAppType; import com.sun.grizzly.util.ClassLoaderUtil; import com.sun.grizzly.util.ExpandJar; public class GrizzlyWebServerDeployer { public static final String DEFAULT_CONTEXT = "/"; private String warPath; private String webxmlPath; private int port = 8080; public void init(String args[]) throws MalformedURLException, IOException { if (args.length == 0) { printHelpAndExit(); } // parse options parseOptions(args); webxmlPath = appendWarContentToClassPath(warPath); } public void printHelpAndExit() { System.err.println("Usage: " + GrizzlyWebServerDeployer.class.getCanonicalName() + " [options] Servlet_Classname"); System.err.println(); System.err.println(" -p, --port=port Runs Servlet on the specified port."); System.err.println(" Default: 8080"); System.err.println(" -a, --application=application path The Servlet folder or jar or war location."); System.err.println(" Default: ."); System.err.println(" -h, --help Show this help message."); System.exit(1); } protected void setWarFilename(String filename){ warPath = filename; } protected String getWarFilename(){ return warPath; } protected void setPort(int port){ this.port = port; } protected int getPort(){ return port; } public boolean parseOptions(String[] args) { // parse options for (int i = 0; i < args.length - 1; i++) { String arg = args[i]; if ("-h".equals(arg) || "--help".equals(arg)) { printHelpAndExit(); } else if ("-a".equals(arg)) { i++; setWarFilename(args[i]); } else if (arg.startsWith("--application=")) { setWarFilename(arg.substring("--application=".length(), arg.length())); } else if ("-p".equals(arg)) { i++; setPort(Integer.parseInt(args[i])); } else if (arg.startsWith("--port=")) { String num = arg.substring("--port=".length(), arg.length()); setPort(Integer.parseInt(num)); } } if (getWarFilename() == null) { System.err.println("Illegal War|Jar file or folder location."); printHelpAndExit(); } return true; } public void launch(){ GrizzlyWebServer ws = new GrizzlyWebServer(port); try { // extract the items from the web.xml Map> itemMap = extractWebxmlInfo(); if (itemMap==null || !itemMap.containsKey("ServletType")) { throw new Exception("invalid"); } for (int i=0;i> map, int index){ // Set the Servlet ServletType servletType = (ServletType) map.get("ServletType").get(index); Servlet servlet = (Servlet) ClassLoaderUtil.load(servletType.getServletClass().getValue()); sa.setServletInstance(servlet); List initParams = servletType.getInitParam(); if (initParams != null) { for (Object element : initParams) { ParamValueType paramValueType = (ParamValueType) element; sa.addInitParameter(paramValueType.getParamName().getValue(), paramValueType.getParamValue().getValue()); } } } @SuppressWarnings("unchecked") protected void setListeners(ServletAdapter sa, Map> map){ // Add the Listener List listeners = map.get("ListenerType"); if (listeners != null) { for (Object element : listeners) { ListenerType listenerType = (ListenerType) element; sa.addServletListener(listenerType.getListenerClass().getValue()); } } } @SuppressWarnings("unchecked") protected void setFilters(ServletAdapter sa, Map> map, String context){ // Add the Filters List filters = map.get("FilterType"); List filtersMapping = map.get("FilterMappingType"); if (filters != null) { for (Object element : filters) { FilterType filterType = (FilterType) element; // we had the filter if the url-pattern is for this context // we need to get the right filter-mapping form the name for (Object obj : filtersMapping) { FilterMappingType filterMapping = (FilterMappingType) obj; // we must compare to the context.. ex : // / and /x.jsp is valid but /xyz/x.jsp is not if(isContextMatching(filterMapping.getUrlPattern().getValue(), context)){ Filter filter = (Filter) ClassLoaderUtil.load(filterType.getFilterClass().getValue()); // initParams List initParams = filterType.getInitParam(); Map initParamsMap = new HashMap(); if (initParams != null) { for (Object param : initParams) { ParamValueType paramValueType = (ParamValueType) param; initParamsMap.put(paramValueType.getParamName().getValue(), paramValueType.getParamValue().getValue()); } } sa.addFilter(filter, filterType.getFilterName().getValue(), initParamsMap); } } } } } protected boolean isContextMatching(String filterContext, String context){ if(filterContext==null || context==null){ return false; } // find the last / int indexLastContext = context.lastIndexOf('/'); int indexLastFilterContext = context.lastIndexOf('/'); // if the substring match is the same context path String contextPath = ""; String filterContextPath = ""; if(indexLastContext>-1){ contextPath = context.substring(0,indexLastContext); } // that will also remove the extension : /xyz/*.jsp if(indexLastContext>-1){ filterContextPath = filterContext.substring(0,indexLastFilterContext); } return contextPath.equals(filterContextPath); } protected Map> getItemMap(List itemList) throws Exception { // need to find something nicer Map> itemMap = null; if (itemList != null) { itemMap = new HashMap>(); // convert it to a Map, will be easier to retrieve values for (Object object : itemList) { List list = null; String key = object.getClass().getSimpleName(); if (itemMap.containsKey(key)) { list = itemMap.get(key); } else { list = new ArrayList(); itemMap.put(key, list); } list.add(object); } } else { // error handling when list is null ... throw new Exception("invalid"); } return itemMap; } /** * Make available the content of a War file to the current Thread Context Classloader. * @return the exploded war file location. */ public String appendWarContentToClassPath(String appliPath) throws MalformedURLException, IOException { String path; File file = null; URL appRoot = null; URL classesURL = null; if (appliPath != null && (appliPath.endsWith(".war") || appliPath.endsWith(".jar"))) { file = new File(appliPath); appRoot = new URL("jar:file:" + file.getCanonicalPath() + "!/"); classesURL = new URL("jar:file:" + file.getCanonicalPath() + "!/WEB-INF/classes/"); path = ExpandJar.expand(appRoot); } else { path = appliPath; classesURL = new URL("file://" + path + "WEB-INF/classes/"); appRoot = new URL("file://" + path); } String absolutePath = new File(path).getAbsolutePath(); URL[] urls = null; File libFiles = new File(absolutePath + File.separator + "WEB-INF"+ File.separator + "lib"); int arraySize = (appRoot == null ? 1:2); //Must be a better way because that sucks! String separator = (System.getProperty("os.name").toLowerCase().startsWith("win")? "/" : "//"); if (libFiles.exists() && libFiles.isDirectory()){ urls = new URL[libFiles.listFiles().length + arraySize]; for (int i=0; i < libFiles.listFiles().length; i++){ urls[i] = new URL("jar:file:" + separator + libFiles.listFiles()[i].toString().replace('\\','/') + "!/"); } } else { urls = new URL[arraySize]; } urls[urls.length -1] = classesURL; urls[urls.length -2] = appRoot; ClassLoader urlClassloader = new URLClassLoader(urls,Thread.currentThread().getContextClassLoader()); Thread.currentThread().setContextClassLoader(urlClassloader); return path; } @SuppressWarnings("unchecked") protected Map> extractWebxmlInfo() throws Exception { // check if we can populate the adapter from the web.xml File webxmlFile = new File(webxmlPath + File.separator + "WEB-INF" + File.separator + "web.xml"); // the package name was generated by the ant task. JAXBContext jc = JAXBContext.newInstance("com.sun.grizzly.http.servlet.xsd"); // create an Unmarshaller Unmarshaller u = jc.createUnmarshaller(); JAXBElement root = (JAXBElement) u.unmarshal(new FileInputStream(webxmlFile)); WebAppType webApp = (WebAppType) root.getValue(); List itemList = webApp.getDescriptionAndDisplayNameAndIcon(); return getItemMap(itemList); } /** * @param args */ public static void main(String[] args) { GrizzlyWebServerDeployer ws = new GrizzlyWebServerDeployer(); try { // ready to launch ws.init(args); ws.launch(); } catch (Exception e){ e.printStackTrace(); } } }