package org.smartly.application.desktopgap.impl.app.server.handlers; import org.apache.velocity.VelocityContext; import org.apache.velocity.app.VelocityEngine; import org.eclipse.jetty.util.resource.Resource; import org.smartly.Smartly; import org.smartly.application.desktopgap.impl.app.IDesktopConstants; import org.smartly.application.desktopgap.impl.app.applications.window.AppManifest; import org.smartly.application.desktopgap.impl.app.server.ServletUtils; import org.smartly.application.desktopgap.impl.app.server.WebServer; import org.smartly.application.desktopgap.impl.app.server.vtools.Cookies; import org.smartly.application.desktopgap.impl.app.server.vtools.Req; import org.smartly.application.desktopgap.impl.app.utils.DOM; import org.smartly.commons.logging.Level; import org.smartly.commons.logging.Logger; import org.smartly.commons.logging.util.LoggingUtils; import org.smartly.commons.util.*; import org.smartly.packages.velocity.impl.VLCManager; import org.smartly.packages.velocity.impl.vtools.toolbox.VLCToolbox; import javax.servlet.ServletException; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.io.IOException; import java.util.*; /** * Servlet for site file parsing. * <p/> * This servlet replace SmartlyVHTMLServlet */ public class EndPointServlet extends HttpServlet { public static String PATH = "/*"; private static final String CHARSET = Smartly.getCharset(); private static final String MIME_HTML = "text/html"; private static final String SP_VELOCITY_CONTEXT = "velocity-context"; private static final String SP_URL_PARAMS = "url-params"; private static final Set<String> _extensions = new HashSet<String>(Arrays.asList(new String[]{ ".html", ".vhtml" // velocity })); private Resource _baseResource; private WebServer _server; public EndPointServlet() { } public EndPointServlet(final Object params) { } // -------------------------------------------------------------------- // p u b l i c // -------------------------------------------------------------------- public void setServer(final WebServer server) { _server = server; _server.getServletExtensions().addAll(_extensions); } public void setBaseResource(final Resource base) { _baseResource = base; } public void setResourceBase(final String resourceBase) { try { this.setBaseResource(Resource.newResource(resourceBase)); } catch (Exception e) { this.getLogger().warning(e.toString()); throw new IllegalArgumentException(resourceBase); } } protected void doGet(final HttpServletRequest request, final HttpServletResponse response) throws ServletException, IOException { this.handle(request, response); } protected void doPost(final HttpServletRequest request, final HttpServletResponse response) throws ServletException, IOException { this.handle(request, response); } protected void handle(final HttpServletRequest request, final HttpServletResponse response) throws ServletException, IOException { this.handleInternal(request, response); } // ------------------------------------------------------------------------ // p r i v a t e // ------------------------------------------------------------------------ private Logger getLogger() { return LoggingUtils.getLogger(this); } private void handleInternal(final HttpServletRequest request, final HttpServletResponse response) throws ServletException, IOException { final String resourcePath = ServletUtils.getResourcePath(request); if (isHandled(resourcePath)) { //-- .vhtml --// final Resource resource = ServletUtils.getResource(_baseResource, null, resourcePath); if (!resource.exists()) { ServletUtils.notFound404(response); return; } // parse resource final byte[] output = this.merge(resource, request, response); if (output.length > 0) { // write body ServletUtils.writeResponse(response, DateUtils.now().getTime(), MIME_HTML, output); return; } } ServletUtils.notFound404(response); } private byte[] merge(final Resource resource, final HttpServletRequest request, final HttpServletResponse response) { final Map<String, String> urlParams = getParams(request); try { String result = new String(ByteUtils.getBytes(resource.getInputStream()), CHARSET); // resolve velocity template if any if (isVelocity(resource.getName())) { final Map<String, Object> sessionContext = new HashMap<String, Object>(); final VelocityEngine engine = getEngine(); // execution context final VelocityContext context = new VelocityContext(sessionContext, this.createInnerContext( resource.getName(), urlParams, request, response)); //-- eval velocity template --// if (null != engine) { result = VLCManager.getInstance().evaluateText(engine, resource.getName(), result, context); } else { result = VLCManager.getInstance().evaluateText(resource.getName(), result, context); } if (StringUtils.hasText(result)) { return result.getBytes(); } } if(!urlParams.isEmpty()){ // get appid from parameters // retrieve manifest and pass to wrapInFrame final String appId = urlParams.get(IDesktopConstants.PARAM_APPID); final AppManifest manifest = _server.getManifest(appId); // merge page with frame if (urlParams.containsKey(IDesktopConstants.PARAM_DESKTOPGAP)) { //result = wrapInFrame(manifest, result); result = addDesktopGapScripts(result); } } return StringUtils.hasText(result) ? result.getBytes(CHARSET) : new byte[0]; } catch (Throwable t) { this.getLogger().log(Level.SEVERE, FormatUtils.format( "ERROR MERGING TEMPLATE FOR RESOURCE '{0}': {1}", resource.getName(), ExceptionUtils.getRealMessage(t)), t); } return new byte[0]; } private VelocityContext createInnerContext(final String url, final Map<String, String> restParams, final HttpServletRequest request, final HttpServletResponse response) { final VelocityContext result = new VelocityContext(VLCToolbox.getInstance().getToolsContext()); //-- "$req" tool --// result.put(Req.NAME, new Req(url, restParams, request, response)); //-- "$cookies" tool --// result.put(Cookies.NAME, new Cookies(request, response)); return result; } private Map<String, String> getParams(final HttpServletRequest request){ final String queryString = request.getQueryString(); if(StringUtils.hasText(queryString)){ return CollectionUtils.stringToMapOfStrings(queryString, "&"); } return new HashMap<String, String>(); } private String addDesktopGapScripts(final String pageHtml) { try { return DOM.addDesktopGapScripts(pageHtml, null); } catch (Throwable ignored) { } return ""; } private String wrapInFrame(final String resourcePath, final String pageHtml) { try { final AppManifest manifest = AppManifest.getManifest(resourcePath); if (null != manifest) { return DOM.insertInFrame(manifest, pageHtml, null); } } catch (Throwable ignored) { } return ""; } private String wrapInFrame(final AppManifest manifest, final String pageHtml) { try { if (null != manifest) { return DOM.insertInFrame(manifest, pageHtml, null); } } catch (Throwable ignored) { } return ""; } // -------------------------------------------------------------------- // S T A T I C // -------------------------------------------------------------------- private static VelocityEngine __engine; private static VelocityEngine getEngine() throws Exception { if (null == __engine) { __engine = VLCManager.getInstance().getEngine().getNativeEngine(); } return __engine; } private static boolean isHandled(final String path) { final String ext = PathUtils.getFilenameExtension(path, true); return _extensions.contains(ext); } private static boolean isVelocity(final String path) { final String ext = PathUtils.getFilenameExtension(path, true); return ".vhtml".equalsIgnoreCase(ext); } }