// // ======================================================================== // Copyright (c) 1995-2017 Mort Bay Consulting Pty. Ltd. // ------------------------------------------------------------------------ // All rights reserved. This program and the accompanying materials // are made available under the terms of the Eclipse Public License v1.0 // and Apache License v2.0 which accompanies this distribution. // // The Eclipse Public License is available at // http://www.eclipse.org/legal/epl-v10.html // // The Apache License v2.0 is available at // http://www.opensource.org/licenses/apache2.0.php // // You may elect to redistribute this code under either of these licenses. // ======================================================================== // package org.eclipse.jetty.quickstart; import java.io.IOException; import java.util.HashSet; import java.util.Set; import java.util.stream.Collectors; import org.eclipse.jetty.annotations.AnnotationConfiguration; import org.eclipse.jetty.annotations.AnnotationDecorator; import org.eclipse.jetty.annotations.ServletContainerInitializersStarter; import org.eclipse.jetty.util.log.Log; import org.eclipse.jetty.util.log.Logger; import org.eclipse.jetty.util.resource.Resource; import org.eclipse.jetty.webapp.AbstractConfiguration; import org.eclipse.jetty.webapp.Configuration; import org.eclipse.jetty.webapp.StandardDescriptorProcessor; import org.eclipse.jetty.webapp.WebAppContext; import org.eclipse.jetty.webapp.WebInfConfiguration; import org.eclipse.jetty.webapp.WebXmlConfiguration; /** * QuickStartConfiguration * <p> * Re-inflate a deployable webapp from a saved effective-web.xml * which combines all pre-parsed web xml descriptors and annotations. */ public class QuickStartConfiguration extends AbstractConfiguration { private static final Logger LOG = Log.getLogger(QuickStartConfiguration.class); public static final Set<Class<? extends Configuration>> __replacedConfigurations = new HashSet<>(); public static final String ORIGIN_ATTRIBUTE = "org.eclipse.jetty.quickstart.ORIGIN_ATTRIBUTE"; public static final String GENERATE_ORIGIN = "org.eclipse.jetty.quickstart.GENERATE_ORIGIN"; public static final String QUICKSTART_WEB_XML = "org.eclipse.jetty.quickstart.QUICKSTART_WEB_XML"; static { __replacedConfigurations.add(org.eclipse.jetty.webapp.WebXmlConfiguration.class); __replacedConfigurations.add(org.eclipse.jetty.webapp.MetaInfConfiguration.class); __replacedConfigurations.add(org.eclipse.jetty.webapp.FragmentConfiguration.class); __replacedConfigurations.add(org.eclipse.jetty.annotations.AnnotationConfiguration.class); }; public enum Mode { DISABLED, // No Quick start GENERATE, // Generate quickstart-web.xml and then stop AUTO, // use or generate depending on the existance of quickstart-web.xml QUICKSTART // Use quickstart-web.xml }; private Mode _mode=Mode.AUTO; private boolean _quickStart; public QuickStartConfiguration() { super(true); addDependencies(WebInfConfiguration.class); addDependents(WebXmlConfiguration.class); } public void setMode(Mode mode) { _mode=mode; } public Mode getMode() { return _mode; } /** * @see org.eclipse.jetty.webapp.AbstractConfiguration#preConfigure(org.eclipse.jetty.webapp.WebAppContext) */ @Override public void preConfigure(WebAppContext context) throws Exception { //check that webapp is suitable for quick start - it is not a packed war String war = context.getWar(); if (war == null || war.length()<=0 || !context.getBaseResource().isDirectory()) throw new IllegalStateException ("Bad Quickstart location"); //look for quickstart-web.xml in WEB-INF of webapp Resource quickStartWebXml = getQuickStartWebXml(context); LOG.debug("quickStartWebXml={} exists={}",quickStartWebXml,quickStartWebXml.exists()); _quickStart=false; switch(_mode) { case DISABLED: super.preConfigure(context); break; case GENERATE: { super.preConfigure(context); QuickStartGeneratorConfiguration generator = new QuickStartGeneratorConfiguration(true); configure(generator, context); context.addConfiguration(generator); break; } case AUTO: { if (quickStartWebXml.exists()) quickStart(context, quickStartWebXml); else { super.preConfigure(context); QuickStartGeneratorConfiguration generator = new QuickStartGeneratorConfiguration(false); configure(generator, context); context.addConfiguration(generator); } break; } case QUICKSTART: if (quickStartWebXml.exists()) quickStart(context,quickStartWebXml); else throw new IllegalStateException ("No "+quickStartWebXml); break; } } protected void configure(QuickStartGeneratorConfiguration generator, WebAppContext context) throws IOException { Object attr; attr = context.getAttribute(GENERATE_ORIGIN); if (attr!=null) generator.setGenerateOrigin(Boolean.valueOf(attr.toString())); attr = context.getAttribute(ORIGIN_ATTRIBUTE); if (attr!=null) generator.setOriginAttribute(attr.toString()); attr = context.getAttribute(QUICKSTART_WEB_XML); if (attr instanceof Resource) generator.setQuickStartWebXml((Resource)attr); else if (attr!=null) generator.setQuickStartWebXml(Resource.newResource(attr.toString())); } protected void quickStart(WebAppContext context, Resource quickStartWebXml) throws Exception { _quickStart=true; context.setConfigurations(context.getWebAppConfigurations().stream() .filter(c->!__replacedConfigurations.contains(c.replaces())&&!__replacedConfigurations.contains(c.getClass())) .collect(Collectors.toList()).toArray(new Configuration[]{})); context.getMetaData().setWebXml(quickStartWebXml); context.getServletContext().setEffectiveMajorVersion(context.getMetaData().getWebXml().getMajorVersion()); context.getServletContext().setEffectiveMinorVersion(context.getMetaData().getWebXml().getMinorVersion()); } /** * @see org.eclipse.jetty.webapp.AbstractConfiguration#configure(org.eclipse.jetty.webapp.WebAppContext) */ @Override public void configure(WebAppContext context) throws Exception { if (!_quickStart) super.configure(context); else { //add the processor to handle normal web.xml content context.getMetaData().addDescriptorProcessor(new StandardDescriptorProcessor()); //add a processor to handle extended web.xml format context.getMetaData().addDescriptorProcessor(new QuickStartDescriptorProcessor()); //add a decorator that will find introspectable annotations context.getObjectFactory().addDecorator(new AnnotationDecorator(context)); //this must be the last Decorator because they are run in reverse order! //add a context bean that will run ServletContainerInitializers as the context starts ServletContainerInitializersStarter starter = (ServletContainerInitializersStarter)context.getAttribute(AnnotationConfiguration.CONTAINER_INITIALIZER_STARTER); if (starter != null) throw new IllegalStateException("ServletContainerInitializersStarter already exists"); starter = new ServletContainerInitializersStarter(context); context.setAttribute(AnnotationConfiguration.CONTAINER_INITIALIZER_STARTER, starter); context.addBean(starter, true); LOG.debug("configured {}",this); } } /** * Get the quickstart-web.xml file as a Resource. * * @param context the web app context * @return the Resource for the quickstart-web.xml * @throws Exception if unable to find the quickstart xml */ public Resource getQuickStartWebXml (WebAppContext context) throws Exception { Resource webInf = context.getWebInf(); if (webInf == null || !webInf.exists()) throw new IllegalStateException("No WEB-INF"); LOG.debug("webinf={}",webInf); Resource quickStartWebXml = webInf.addPath("quickstart-web.xml"); return quickStartWebXml; } }