Search in sources :

Example 1 with GroovityErrorHandlerChain

use of com.disney.groovity.servlet.error.GroovityErrorHandlerChain in project groovity by disney.

the class GroovityServlet method service.

/**
 * Primary request entry method for this servlet
 *
 * see {@link HttpServlet#service(HttpServletRequest, HttpServletResponse)}
 */
@Override
public void service(HttpServletRequest req, HttpServletResponse res) throws ServletException, IOException {
    GroovityError error = null;
    try {
        Processor processor = groovityScriptViewFactory.createProcessor(req);
        if (processor != null) {
            if (req.getMethod().equals("HEAD")) {
                // prevent any body from being written, but we'll capture
                // the length
                final AtomicLong length = new AtomicLong(0);
                final AtomicBoolean scriptSetLength = new AtomicBoolean(false);
                final AtomicReference<PrintWriter> respWriter = new AtomicReference<PrintWriter>(null);
                final ServletOutputStream nullStream = new ServletOutputStream() {

                    @Override
                    public void write(int b) throws IOException {
                        length.incrementAndGet();
                    }

                    @Override
                    public void write(byte[] buf, int offset, int len) throws IOException {
                        length.addAndGet(len);
                    }

                    public void setWriteListener(WriteListener arg0) {
                    }

                    public boolean isReady() {
                        return true;
                    }
                };
                processor.process(req, new HttpServletResponseWrapper(res) {

                    PrintWriter writer;

                    @Override
                    public ServletOutputStream getOutputStream() throws IOException {
                        return nullStream;
                    }

                    @Override
                    public PrintWriter getWriter() throws UnsupportedEncodingException {
                        if (writer == null) {
                            writer = new PrintWriter(new OutputStreamWriter(nullStream, getCharacterEncoding()));
                            respWriter.set(writer);
                        }
                        return writer;
                    }

                    @Override
                    public void setContentLength(int len) {
                        res.setContentLength(len);
                        scriptSetLength.set(true);
                    }
                });
                if (!scriptSetLength.get()) {
                    if (respWriter.get() != null) {
                        respWriter.get().flush();
                    }
                    res.setContentLength((int) length.get());
                }
            } else {
                processor.process(req, res);
            }
        } else {
            error = new GroovityError();
            Object acceptMethods = req.getAttribute(REQUEST_ATTRIBUTE_ALLOW_METHODS);
            if (acceptMethods != null && acceptMethods instanceof Collection) {
                @SuppressWarnings("unchecked") Collection<String> am = (Collection<String>) acceptMethods;
                String sep = "";
                StringBuilder sb = new StringBuilder();
                for (Object m : am) {
                    String method = m.toString();
                    sb.append(sep).append(method);
                    sep = ", ";
                }
                res.setHeader("Allow", sb.toString());
                error.setStatus(405);
                error.setMessage("Allowed methods for " + req.getRequestURI() + " are " + sb.toString());
            } else {
                error.setStatus(404);
            }
        }
    } catch (Throwable e) {
        error = new GroovityError();
        error.setCause(e);
        error.setStatus(500);
    }
    if (error != null) {
        error.setReason(EnglishReasonPhraseCatalog.INSTANCE.getReason(error.getStatus(), res.getLocale()));
        String uri = req.getRequestURI();
        if (req.getQueryString() != null) {
            uri = uri.concat("?").concat(req.getQueryString());
        }
        error.setUri(uri);
        req.setAttribute(GroovityScriptView.GROOVITY_ERROR, error);
        boolean handled = false;
        GroovityErrorHandlerChain handlers = groovityScriptViewFactory.getErrorHandlers();
        if (handlers != null) {
            handled = handlers.handleError(req, res, error);
        }
        if (!handled) {
            Throwable cause = error.getCause();
            if (cause != null) {
                if (cause instanceof RuntimeException) {
                    throw (RuntimeException) cause;
                }
                throw new ServletException(cause);
            } else {
                res.sendError(error.getStatus(), error.getMessage());
            }
        }
    }
}
Also used : Processor(com.disney.groovity.servlet.GroovityScriptView.Processor) ServletOutputStream(javax.servlet.ServletOutputStream) HttpServletResponseWrapper(javax.servlet.http.HttpServletResponseWrapper) GroovityError(com.disney.groovity.servlet.error.GroovityError) ServletException(javax.servlet.ServletException) WriteListener(javax.servlet.WriteListener) PrintWriter(java.io.PrintWriter) GroovityErrorHandlerChain(com.disney.groovity.servlet.error.GroovityErrorHandlerChain) UnsupportedEncodingException(java.io.UnsupportedEncodingException) AtomicReference(java.util.concurrent.atomic.AtomicReference) IOException(java.io.IOException) AtomicBoolean(java.util.concurrent.atomic.AtomicBoolean) AtomicLong(java.util.concurrent.atomic.AtomicLong) Collection(java.util.Collection) OutputStreamWriter(java.io.OutputStreamWriter)

Example 2 with GroovityErrorHandlerChain

use of com.disney.groovity.servlet.error.GroovityErrorHandlerChain in project groovity by disney.

the class GroovityServlet method init.

/**
 * see {@link GenericServlet#init}
 */
@Override
public void init() throws ServletException {
    try {
        LOG.info("Initializing GroovityServlet");
        ServletConfig config = getServletConfig();
        if (groovityScriptViewFactory == null) {
            GroovityBuilder builder = new GroovityBuilder();
            configProperties = new Properties();
            String propsFile = getParam(PROPS_FILE);
            if (isNotBlank(propsFile)) {
                URL url = config.getServletContext().getClassLoader().getResource(propsFile);
                if (url == null && propsFile.startsWith("/")) {
                    url = config.getServletContext().getResource(propsFile);
                }
                if (url != null) {
                    LOG.info("Found groovity properties resource " + url);
                    builder.setPropsUrl(url);
                    try (InputStream configStream = url.openStream()) {
                        configProperties.load(configStream);
                    }
                } else {
                    File file = new File(propsFile);
                    if (file.exists()) {
                        LOG.info("Found groovity properties file " + file.getAbsolutePath());
                        builder.setPropsFile(file);
                        if (!file.isDirectory()) {
                            try (InputStream configStream = new FileInputStream(file)) {
                                configProperties.load(configStream);
                            }
                        }
                    } else {
                        LOG.warning("Groovity properties file " + propsFile + " not found");
                    }
                }
            } else {
                URL url = config.getServletContext().getClassLoader().getResource("groovity.properties");
                if (url != null) {
                    LOG.info("Found groovity.properties on classpath");
                    builder.setPropsUrl(url);
                    try (InputStream configStream = url.openStream()) {
                        configProperties.load(configStream);
                    }
                }
            }
            if (configProperties.containsKey(IGNORE_STATUS_CODES) && !System.getProperties().containsKey(IGNORE_STATUS_CODES)) {
                System.setProperty(IGNORE_STATUS_CODES, configProperties.getProperty(IGNORE_STATUS_CODES));
            }
            if (configProperties.containsKey(ERROR_PAGE) && !System.getProperties().containsKey(ERROR_PAGE)) {
                System.setProperty(ERROR_PAGE, configProperties.getProperty(ERROR_PAGE));
            }
            String async = getParam(ASYNC_THREADS_PARAM);
            if (isNotBlank(async)) {
                builder.setAsyncThreads(Integer.parseInt(async));
            }
            String caseSens = getParam(CASE_SENSITIVE_PARAM);
            if (isNotBlank(caseSens)) {
                builder.setCaseSensitive(Boolean.parseBoolean(caseSens));
            }
            String maxPerRoute = getParam(MAX_CONN_PER_ROUTE_PARAM);
            if (isNotBlank(maxPerRoute)) {
                builder.setMaxHttpConnPerRoute(Integer.parseInt(maxPerRoute));
            }
            String maxTotal = getParam(MAX_CONN_TOTAL_PARAM);
            if (isNotBlank(maxTotal)) {
                builder.setMaxHttpConnTotal(Integer.parseInt(maxTotal));
            }
            File jarDirectory;
            String jarDir = getParam(JAR_DIRECTORY_PARAM);
            if (isNotBlank(jarDir)) {
                jarDirectory = new File(jarDir);
            } else {
                // default jar directory;
                jarDirectory = new File(getServletContext().getRealPath("/"), JAR_DIRECTORY_PARAM_DEFAULT_VALUE);
            }
            builder.setJarDirectory(jarDirectory);
            String jarPhase = getParam(JAR_PHASES_PARAM);
            if (isNotBlank(jarPhase)) {
                builder.setJarPhase(jarPhase);
            }
            String scriptBase = getParam(SCRIPT_BASE_CLASS_PARAM);
            if (isNotBlank(scriptBase)) {
                builder.setScriptBaseClass(scriptBase);
            }
            String defaultBinding = getParam(DEFAULT_BINDING);
            if (isNotBlank(defaultBinding)) {
                @SuppressWarnings("unchecked") Map<String, Object> db = (Map<String, Object>) new JsonSlurper().parse(new StringReader(defaultBinding));
                builder.setDefaultBinding(db);
            }
            String sourcePhase = getParam(SOURCE_PHASES_PARAM);
            if (isNotBlank(sourcePhase)) {
                builder.setSourcePhase(sourcePhase);
            }
            String sourcePoll = getParam(SOURCE_POLL_SECONDS);
            if (isNotBlank(sourcePoll)) {
                builder.setSourcePollSeconds(Integer.parseInt(sourcePoll));
            }
            String configurator = getParam(CONFIGURATOR);
            if (isNotBlank(configurator)) {
                builder.setConfigurator((Configurator) loadInstance(configurator));
            }
            String shutdown = getParam(SHUTDOWN_HANDLER);
            if (isNotBlank(shutdown)) {
                shutdownHandler = (Runnable) loadInstance(shutdown);
            }
            String hostnameVerifier = getParam(HOSTNAME_VERIFIER);
            if (isNotBlank(hostnameVerifier)) {
                builder.getHttpClientBuilder().setSSLHostnameVerifier((HostnameVerifier) loadInstance(hostnameVerifier));
            }
            String trustStrategy = getParam(TRUST_STRATEGY);
            if (isNotBlank(trustStrategy)) {
                SSLContextBuilder sslb = new SSLContextBuilder();
                sslb.loadTrustMaterial((TrustStrategy) loadInstance(trustStrategy));
                builder.getHttpClientBuilder().setSSLContext(sslb.build());
            }
            String sourceLocation = getParam(SOURCE_LOCATION_PARAM);
            String sourceLocator = getParam(SOURCE_LOCATOR_PARAM);
            if (isNotBlank(sourceLocation)) {
                // newlines separate multiple
                String[] sources = sourceLocation.split(SOURCE_LOCATOR_SPLIT_REGEX);
                ArrayList<URI> sourceURIs = new ArrayList<URI>(sources.length);
                for (String source : sources) {
                    if (isNotBlank(source)) {
                        sourceURIs.add(new URI(source));
                    }
                }
                builder.setSourceLocations(sourceURIs);
            } else if (isNotBlank(sourceLocator)) {
                String[] sources = sourceLocator.split(SOURCE_LOCATOR_SPLIT_REGEX);
                ArrayList<GroovitySourceLocator> sourceLocators = new ArrayList<GroovitySourceLocator>(sources.length);
                for (String source : sources) {
                    if (isNotBlank(source)) {
                        sourceLocators.add((GroovitySourceLocator) loadInstance(source));
                    }
                }
                builder.setSourceLocators(sourceLocators);
            }
            // we want to allow unconfigured groovities to run, presuming there are embedded
            // groovity classes
            BindingDecorator userDecorator = null;
            String userDecoratorClass = getParam(BINDING_DECORATOR);
            if (isNotBlank(userDecoratorClass)) {
                userDecorator = (BindingDecorator) loadInstance(userDecoratorClass);
            }
            builder.setBindingDecorator(new BindingDecorator(userDecorator) {

                @Override
                public void decorate(Map<String, Object> binding) {
                    binding.put("servletContext", GroovityServlet.this.getServletContext());
                }
            });
            builder.setArgsLookup(new ArgsLookup(new RequestArgsLookup()));
            GroovityErrorHandlerChain errorHandlers = GroovityErrorHandlerChain.createDefault();
            String chainDecorator = getParam(ERROR_CHAIN_DECORATOR);
            if (isNotBlank(chainDecorator)) {
                ((GroovityErrorHandlerChainDecorator) loadInstance(chainDecorator)).decorate(errorHandlers);
            }
            ServiceLoader.load(GroovityErrorHandlerChainDecorator.class).forEach(decorator -> {
                decorator.decorate(errorHandlers);
            });
            Groovity groovity = builder.build();
            groovityScriptViewFactory = new GroovityScriptViewFactory();
            groovityScriptViewFactory.setGroovity(groovity);
            groovityScriptViewFactory.setServletContext(getServletContext());
            groovityScriptViewFactory.setErrorHandlers(errorHandlers);
            groovityScriptViewFactory.init();
            config.getServletContext().setAttribute(SERVLET_CONTEXT_GROOVITY_VIEW_FACTORY, groovityScriptViewFactory);
            config.getServletContext().setAttribute(SERVLET_CONTEXT_GROOVITY_INSTANCE, groovity);
        }
        javax.websocket.server.ServerContainer webSocketServer = (javax.websocket.server.ServerContainer) config.getServletContext().getAttribute("javax.websocket.server.ServerContainer");
        if (webSocketServer != null) {
            // register websocket endpoint
            webSocketServer.addEndpoint(ServerEndpointConfig.Builder.create(GroovityServerEndpoint.class, "/ws/{socketName}").configurator(new GroovityServerEndpoint.Configurator(groovityScriptViewFactory)).build());
            LOG.info("Created groovity web socket endpoint");
        }
        LOG.info("Completed initialization of GroovityServlet");
    } catch (Exception e) {
        throw new ServletException(e);
    }
}
Also used : ArrayList(java.util.ArrayList) Properties(java.util.Properties) URI(java.net.URI) URL(java.net.URL) ServletException(javax.servlet.ServletException) GroovityBuilder(com.disney.groovity.GroovityBuilder) Groovity(com.disney.groovity.Groovity) StringReader(java.io.StringReader) SSLContextBuilder(org.apache.http.ssl.SSLContextBuilder) JsonSlurper(groovy.json.JsonSlurper) FileInputStream(java.io.FileInputStream) InputStream(java.io.InputStream) GroovityErrorHandlerChain(com.disney.groovity.servlet.error.GroovityErrorHandlerChain) ServletConfig(javax.servlet.ServletConfig) FileInputStream(java.io.FileInputStream) ServletException(javax.servlet.ServletException) UnsupportedEncodingException(java.io.UnsupportedEncodingException) IOException(java.io.IOException) ArgsLookup(com.disney.groovity.ArgsLookup) GroovitySourceLocator(com.disney.groovity.source.GroovitySourceLocator) GroovityErrorHandlerChainDecorator(com.disney.groovity.servlet.error.GroovityErrorHandlerChainDecorator) BindingDecorator(com.disney.groovity.BindingDecorator) File(java.io.File) Map(java.util.Map)

Aggregations

GroovityErrorHandlerChain (com.disney.groovity.servlet.error.GroovityErrorHandlerChain)2 IOException (java.io.IOException)2 UnsupportedEncodingException (java.io.UnsupportedEncodingException)2 ServletException (javax.servlet.ServletException)2 ArgsLookup (com.disney.groovity.ArgsLookup)1 BindingDecorator (com.disney.groovity.BindingDecorator)1 Groovity (com.disney.groovity.Groovity)1 GroovityBuilder (com.disney.groovity.GroovityBuilder)1 Processor (com.disney.groovity.servlet.GroovityScriptView.Processor)1 GroovityError (com.disney.groovity.servlet.error.GroovityError)1 GroovityErrorHandlerChainDecorator (com.disney.groovity.servlet.error.GroovityErrorHandlerChainDecorator)1 GroovitySourceLocator (com.disney.groovity.source.GroovitySourceLocator)1 JsonSlurper (groovy.json.JsonSlurper)1 File (java.io.File)1 FileInputStream (java.io.FileInputStream)1 InputStream (java.io.InputStream)1 OutputStreamWriter (java.io.OutputStreamWriter)1 PrintWriter (java.io.PrintWriter)1 StringReader (java.io.StringReader)1 URI (java.net.URI)1