/* * Copyright 2013 Guidewire Software, Inc. */ package gw.util.servlet; import gw.lang.reflect.IMethodInfo; import gw.lang.reflect.TypeSystem; import gw.lang.reflect.gs.ITemplateType; import gw.lang.reflect.java.JavaTypes; import gw.lang.Gosu; import javax.servlet.ServletException; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.io.File; import java.io.FilenameFilter; import java.io.IOException; import java.io.PrintWriter; import java.io.Writer; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Properties; @SuppressWarnings("serial") public class GosuServlet extends HttpServlet { private static final String ENCODING = "UTF-8"; private HashMap<ITemplateType, IMethodInfo> _renderMethodsMap = new HashMap<ITemplateType, IMethodInfo>(); private boolean _bInit; @Override protected void service( HttpServletRequest req, HttpServletResponse resp ) throws ServletException, IOException { initGosu( req ); resp.setContentType( "text/html; charset=" + ENCODING ); String uri = req.getRequestURI(); String strType = getTypeNameFromUri( uri, req.getContextPath() ); ITemplateType templateType = (ITemplateType)TypeSystem.getByFullNameIfValid( strType ); if( templateType == null ) { resp.sendError( HttpServletResponse.SC_INTERNAL_SERVER_ERROR, strType + " not found" ); return; } if( !templateType.isValid() ) { resp.sendError( HttpServletResponse.SC_INTERNAL_SERVER_ERROR, getInvalidTemplateMessage( templateType ) ); return; } ServletParams params = new ServletParams( req, resp, req.getSession(), req.getSession().getServletContext() ); renderTemplate( templateType, resp.getWriter(), params ); resp.setStatus( HttpServletResponse.SC_OK ); } private void renderTemplate( ITemplateType templateType, PrintWriter writer, ServletParams params ) { IMethodInfo renderMethod = _renderMethodsMap.get(templateType); if( renderMethod == null ) { renderMethod = templateType.getTypeInfo().getMethod( "render", JavaTypes.getJreType(Writer.class), JavaTypes.getJreType( ServletParams.class ) ); _renderMethodsMap.put(templateType, renderMethod); } renderMethod.getCallHandler().handleCall( null, writer, params ); } private String getInvalidTemplateMessage( ITemplateType templateType ) { StringBuilder sb = new StringBuilder( "Template: " + templateType.getName() + " has errors:\n" ); //noinspection ThrowableResultOfMethodCallIgnored sb.append( templateType.getTemplateGenerator().getProgram().getGosuProgram().getParseResultsException().getFeedback() ); return sb.toString(); } private String getTypeNameFromUri( String uri, String context ) { String strType = uri.replaceFirst( context, "" ).replace( '/', '.' ); if( strType.startsWith( "." ) ) { strType = strType.substring( 1 ); } strType = strType.substring( 0, strType.lastIndexOf( '.' ) ); return strType; } private void initGosu( HttpServletRequest req ) { if( !_bInit ) { synchronized( GosuServlet.class ) { if( !_bInit ) { Properties props = System.getProperties(); for ( String prop : props.stringPropertyNames() ) { if ( prop.startsWith("gw.") && prop.endsWith(".env") ) { _bInit = true; return; } } String strServletDir = req.getSession().getServletContext().getRealPath( "/" ); File servletDir = new File( strServletDir ); List<File> classpath = new ArrayList<File>(); classpath.add( servletDir ); addWebInfPaths( new File( servletDir, "WEB-INF" ), classpath ); Gosu.init( classpath ); _bInit = true; } } } } public void addWebInfPaths( File webInf, List<File> classpath ) { if( !webInf.isDirectory() ) { return; } File classes = new File( webInf, "classes" ); classpath.add( classes ); File lib = new File( webInf, "lib" ); if( lib.isDirectory() ) { addJarsToClassPath( classpath, lib ); } } private static void addJarsToClassPath( final List<File> classpath, File lib ) { //noinspection ResultOfMethodCallIgnored lib.listFiles( new FilenameFilter() { public boolean accept( File dir, String name ) { String lname = name.toLowerCase(); if( lname.endsWith( ".jar" ) || lname.endsWith( ".zip" ) ) { classpath.add( new File( dir, name ) ); } return false; } } ); } }