/* * JBoss, Home of Professional Open Source. * Copyright 2016 Red Hat, Inc., and individual contributors * as indicated by the @author tags. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package io.undertow.js; import java.io.IOException; import java.io.InputStream; import java.security.AccessController; import java.security.PrivilegedAction; import java.util.ArrayList; import java.util.Iterator; import java.util.List; import java.util.ServiceConfigurationError; import java.util.ServiceLoader; import javax.servlet.ServletContext; import io.undertow.js.templates.TemplateProvider; import io.undertow.server.HandlerWrapper; import io.undertow.server.HttpHandler; import io.undertow.server.HttpServerExchange; import io.undertow.server.handlers.resource.Resource; import io.undertow.server.handlers.resource.ResourceManager; import io.undertow.servlet.ServletExtension; import io.undertow.servlet.api.DeploymentInfo; import io.undertow.servlet.api.ThreadSetupAction; import io.undertow.servlet.handlers.ServletRequestContext; import io.undertow.util.FileUtils; /** * @author Stuart Douglas */ public class UndertowJSServletExtension implements ServletExtension { private final String SCRIPTS_FILE = "WEB-INF/undertow-scripts.conf"; @Override public void handleDeployment(DeploymentInfo deploymentInfo, ServletContext servletContext) { try { ResourceManager resourceManager = deploymentInfo.getResourceManager(); if (resourceManager == null) { return; } Resource scripts = resourceManager.getResource(SCRIPTS_FILE); if (scripts == null) { return; } try (InputStream data = scripts.getUrl().openStream()) { UndertowJS.Builder builder = UndertowJS.builder(); List<String> files = new ArrayList<>(); String contents = FileUtils.readFile(data); String[] lines = contents.split("\n"); for (String line : lines) { String trimmed = line; int commentIndex = trimmed.indexOf("#"); if (commentIndex > -1) { trimmed = trimmed.substring(0, commentIndex); } trimmed = trimmed.trim(); if (trimmed.isEmpty()) { continue; } Resource path = resourceManager.getResource(trimmed); if (path != null) { files.add(trimmed); } else { throw UndertowScriptLogger.ROOT_LOGGER.couldNotFileScript(trimmed); } } builder.addResources(resourceManager, files); ClassLoader classLoader = deploymentInfo.getClassLoader() != null ? deploymentInfo.getClassLoader() : getClass().getClassLoader(); ServiceLoader<InjectionProvider> loader = ServiceLoader.load(InjectionProvider.class, classLoader); for(InjectionProvider provider : loader) { builder.addInjectionProvider(provider); } Iterator<TemplateProvider> iterator = ServiceLoader.load(TemplateProvider.class, classLoader).iterator(); while (iterator.hasNext()) { try { builder.addTemplateProvider(iterator.next()); } catch (ServiceConfigurationError ignored) { // Catching errors is bad but this should be safe } } builder.addHandlerWrapper(new HandlerWrapper() { @Override public HttpHandler wrap(final HttpHandler handler) { return new HttpHandler() { @Override public void handleRequest(HttpServerExchange exchange) throws Exception { ServletRequestContext current; if(System.getSecurityManager() != null) { current = AccessController.doPrivileged(new PrivilegedAction<ServletRequestContext>() { @Override public ServletRequestContext run() { return ServletRequestContext.current(); } }); } else { current = ServletRequestContext.current(); } if(current == null) { ServletRequestContext src = exchange.getAttachment(ServletRequestContext.ATTACHMENT_KEY); if(src != null) { ThreadSetupAction.Handle handle = src.getDeployment().getThreadSetupAction().setup(exchange); try { handler.handleRequest(exchange); } finally { handle.tearDown(); } } else { handler.handleRequest(exchange); } } else { handler.handleRequest(exchange); } } }; } }); builder.setHotDeployment(true); //todo: configurable? builder.setClassLoader(classLoader); builder.setResourceManager(resourceManager); UndertowJS js = builder.build(); js.start(); deploymentInfo.addInnerHandlerChainWrapper(js.getHandlerWrapper()); } catch (IOException e) { throw new RuntimeException(e); } } catch (Exception e) { throw new RuntimeException(e); } } }