From 10da0e1015effb00d650e7e058a580f0520a9854 Mon Sep 17 00:00:00 2001 From: Jan Bartel Date: Wed, 9 Jul 2014 15:02:44 +1000 Subject: 439194 Refactor mvn jetty:run-forked so that it is configurable the same as the other jetty:run-X goals --- .../jetty/quickstart/QuickStartConfiguration.java | 25 +- .../quickstart/QuickStartDescriptorGenerator.java | 669 +++++++++++++++++++++ .../eclipse/jetty/quickstart/QuickStartWebApp.java | 558 +---------------- 3 files changed, 694 insertions(+), 558 deletions(-) create mode 100644 jetty-quickstart/src/main/java/org/eclipse/jetty/quickstart/QuickStartDescriptorGenerator.java (limited to 'jetty-quickstart') diff --git a/jetty-quickstart/src/main/java/org/eclipse/jetty/quickstart/QuickStartConfiguration.java b/jetty-quickstart/src/main/java/org/eclipse/jetty/quickstart/QuickStartConfiguration.java index 313c5c03c8..85f95dcb6a 100644 --- a/jetty-quickstart/src/main/java/org/eclipse/jetty/quickstart/QuickStartConfiguration.java +++ b/jetty-quickstart/src/main/java/org/eclipse/jetty/quickstart/QuickStartConfiguration.java @@ -72,7 +72,23 @@ public class QuickStartConfiguration extends WebInfConfiguration LOG.debug("webapp={}",webApp); - //look for effective-web.xml in WEB-INF of webapp + //look for quickstart-web.xml in WEB-INF of webapp + Resource quickStartWebXml = getQuickStartWebXml(context); + LOG.debug("quickStartWebXml={}",quickStartWebXml); + + context.getMetaData().setWebXml(quickStartWebXml); + } + + + /** + * Get the quickstart-web.xml file as a Resource. + * + * @param context + * @return + * @throws Exception + */ + public Resource getQuickStartWebXml (WebAppContext context) throws Exception + { Resource webInf = context.getWebInf(); if (webInf == null || !webInf.exists()) throw new IllegalStateException("No WEB-INF"); @@ -81,11 +97,10 @@ public class QuickStartConfiguration extends WebInfConfiguration Resource quickStartWebXml = webInf.addPath("quickstart-web.xml"); if (!quickStartWebXml.exists()) throw new IllegalStateException ("No WEB-INF/quickstart-web.xml"); - LOG.debug("quickStartWebXml={}",quickStartWebXml); - - context.getMetaData().setWebXml(quickStartWebXml); + return quickStartWebXml; } - + + /** * @see org.eclipse.jetty.webapp.AbstractConfiguration#configure(org.eclipse.jetty.webapp.WebAppContext) diff --git a/jetty-quickstart/src/main/java/org/eclipse/jetty/quickstart/QuickStartDescriptorGenerator.java b/jetty-quickstart/src/main/java/org/eclipse/jetty/quickstart/QuickStartDescriptorGenerator.java new file mode 100644 index 0000000000..a138ae6e57 --- /dev/null +++ b/jetty-quickstart/src/main/java/org/eclipse/jetty/quickstart/QuickStartDescriptorGenerator.java @@ -0,0 +1,669 @@ +// +// ======================================================================== +// Copyright (c) 1995-2014 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.File; +import java.io.FileNotFoundException; +import java.io.FileOutputStream; +import java.io.IOException; +import java.util.Collection; +import java.util.Collections; +import java.util.EventListener; +import java.util.HashMap; +import java.util.Map; +import java.util.Set; + +import javax.servlet.DispatcherType; +import javax.servlet.MultipartConfigElement; +import javax.servlet.ServletContext; +import javax.servlet.SessionCookieConfig; +import javax.servlet.SessionTrackingMode; +import javax.servlet.descriptor.JspPropertyGroupDescriptor; +import javax.servlet.descriptor.TaglibDescriptor; + +import org.eclipse.jetty.annotations.AnnotationConfiguration; +import org.eclipse.jetty.http.MimeTypes; +import org.eclipse.jetty.plus.annotation.LifeCycleCallback; +import org.eclipse.jetty.plus.annotation.LifeCycleCallbackCollection; +import org.eclipse.jetty.security.ConstraintAware; +import org.eclipse.jetty.security.ConstraintMapping; +import org.eclipse.jetty.security.SecurityHandler; +import org.eclipse.jetty.security.authentication.FormAuthenticator; +import org.eclipse.jetty.servlet.ErrorPageErrorHandler; +import org.eclipse.jetty.servlet.FilterHolder; +import org.eclipse.jetty.servlet.FilterMapping; +import org.eclipse.jetty.servlet.Holder; +import org.eclipse.jetty.servlet.ServletHandler; +import org.eclipse.jetty.servlet.ServletHolder; +import org.eclipse.jetty.servlet.ServletMapping; +import org.eclipse.jetty.servlet.ServletContextHandler.JspConfig; +import org.eclipse.jetty.util.QuotedStringTokenizer; +import org.eclipse.jetty.util.log.Log; +import org.eclipse.jetty.util.log.Logger; +import org.eclipse.jetty.util.security.Constraint; +import org.eclipse.jetty.webapp.MetaData; +import org.eclipse.jetty.webapp.MetaData.OriginInfo; +import org.eclipse.jetty.webapp.MetaInfConfiguration; +import org.eclipse.jetty.webapp.WebAppContext; +import org.eclipse.jetty.xml.XmlAppendable; + + + +/** + * QuickStartDescriptorGenerator + * + * Generate an effective web.xml from a WebAppContext, including all components + * from web.xml, web-fragment.xmls annotations etc. + */ +public class QuickStartDescriptorGenerator +{ + private static final Logger LOG = Log.getLogger(QuickStartDescriptorGenerator.class); + protected WebAppContext _webApp; + protected File _descriptorDir; + protected String _extraXML; + + + + /** + * @param w the source WebAppContext + * @param descriptorDir the directory where quickstart-web.xml should be saved + * @param extraXML any extra xml snippet to append + */ + public QuickStartDescriptorGenerator (WebAppContext w, File descriptorDir, String extraXML) + { + _webApp = w; + _descriptorDir = descriptorDir; + _extraXML = extraXML; + } + + + /** + * Perform the generation of the xml file + * @throws IOException + * @throws FileNotFoundException + * @throws Exception + */ + public File generateQuickStartWebXml () throws FileNotFoundException, IOException + { + if (_webApp == null) + throw new IllegalStateException("No webapp for quickstart-web.xml"); + if (_descriptorDir == null) + throw new IllegalStateException("No location for quickstart-web.xml"); + + _webApp.getMetaData().getOrigins(); + + if (_webApp.getBaseResource()==null) + throw new IllegalArgumentException("No base resource for "+this); + + if (!_descriptorDir.exists()) + _descriptorDir.mkdirs(); + + File webXml = new File(_descriptorDir,"quickstart-web.xml"); + + LOG.info("Quickstart generate {}",webXml); + + try (FileOutputStream fos = new FileOutputStream(webXml)) + { + XmlAppendable out = new XmlAppendable(fos,"UTF-8"); + + MetaData md = _webApp.getMetaData(); + + Map webappAttr = new HashMap<>(); + webappAttr.put("xmlns","http://xmlns.jcp.org/xml/ns/javaee"); + webappAttr.put("xmlns:xsi","http://www.w3.org/2001/XMLSchema-instance"); + webappAttr.put("xsi:schemaLocation","http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd"); + webappAttr.put("metadata-complete","true"); + webappAttr.put("version","3.1"); + + out.openTag("web-app",webappAttr); + if (_webApp.getDisplayName() != null) + out.tag("display-name",_webApp.getDisplayName()); + + // Set some special context parameters + + // The location of the war file on disk + String resourceBase = _webApp.getBaseResource().getFile().getCanonicalFile().getAbsoluteFile().toURI().toString(); + + // The library order + addContextParamFromAttribute(out,ServletContext.ORDERED_LIBS); + //the servlet container initializers + addContextParamFromAttribute(out,AnnotationConfiguration.CONTAINER_INITIALIZERS); + //the tlds discovered + addContextParamFromAttribute(out,MetaInfConfiguration.METAINF_TLDS,resourceBase); + //the META-INF/resources discovered + addContextParamFromAttribute(out,MetaInfConfiguration.METAINF_RESOURCES,resourceBase); + + + // init params + for (String p : _webApp.getInitParams().keySet()) + out.openTag("context-param",origin(md,"context-param." + p)) + .tag("param-name",p) + .tag("param-value",_webApp.getInitParameter(p)) + .closeTag(); + + if (_webApp.getEventListeners() != null) + for (EventListener e : _webApp.getEventListeners()) + out.openTag("listener",origin(md,e.getClass().getCanonicalName() + ".listener")) + .tag("listener-class",e.getClass().getCanonicalName()) + .closeTag(); + + ServletHandler servlets = _webApp.getServletHandler(); + + if (servlets.getFilters() != null) + { + for (FilterHolder holder : servlets.getFilters()) + outholder(out,md,"filter",holder); + } + + if (servlets.getFilterMappings() != null) + { + for (FilterMapping mapping : servlets.getFilterMappings()) + { + out.openTag("filter-mapping"); + out.tag("filter-name",mapping.getFilterName()); + if (mapping.getPathSpecs() != null) + for (String s : mapping.getPathSpecs()) + out.tag("url-pattern",s); + if (mapping.getServletNames() != null) + for (String n : mapping.getServletNames()) + out.tag("servlet-name",n); + + if (!mapping.isDefaultDispatches()) + { + if (mapping.appliesTo(DispatcherType.REQUEST)) + out.tag("dispatcher","REQUEST"); + if (mapping.appliesTo(DispatcherType.ASYNC)) + out.tag("dispatcher","ASYNC"); + if (mapping.appliesTo(DispatcherType.ERROR)) + out.tag("dispatcher","ERROR"); + if (mapping.appliesTo(DispatcherType.FORWARD)) + out.tag("dispatcher","FORWARD"); + if (mapping.appliesTo(DispatcherType.INCLUDE)) + out.tag("dispatcher","INCLUDE"); + } + out.closeTag(); + } + } + + if (servlets.getServlets() != null) + { + for (ServletHolder holder : servlets.getServlets()) + outholder(out,md,"servlet",holder); + } + + if (servlets.getServletMappings() != null) + { + for (ServletMapping mapping : servlets.getServletMappings()) + { + out.openTag("servlet-mapping",origin(md,mapping.getServletName() + ".servlet.mappings")); + out.tag("servlet-name",mapping.getServletName()); + if (mapping.getPathSpecs() != null) + for (String s : mapping.getPathSpecs()) + out.tag("url-pattern",s); + out.closeTag(); + } + } + + // Security elements + SecurityHandler security =_webApp. getSecurityHandler(); + + if (security!=null && (security.getRealmName()!=null || security.getAuthMethod()!=null)) + { + out.openTag("login-config"); + if (security.getAuthMethod()!=null) + out.tag("auth-method",origin(md,"auth-method"),security.getAuthMethod()); + if (security.getRealmName()!=null) + out.tag("realm-name",origin(md,"realm-name"),security.getRealmName()); + + + if (Constraint.__FORM_AUTH.equalsIgnoreCase(security.getAuthMethod())) + { + out.openTag("form-login-config"); + out.tag("form-login-page",origin(md,"form-login-page"),security.getInitParameter(FormAuthenticator.__FORM_LOGIN_PAGE)); + out.tag("form-error-page",origin(md,"form-error-page"),security.getInitParameter(FormAuthenticator.__FORM_ERROR_PAGE)); + out.closeTag(); + } + + out.closeTag(); + } + + if (security instanceof ConstraintAware) + { + ConstraintAware ca = (ConstraintAware)security; + for (String r:ca.getRoles()) + out.openTag("security-role") + .tag("role-name",r) + .closeTag(); + + for (ConstraintMapping m : ca.getConstraintMappings()) + { + out.openTag("security-constraint"); + + if (m.getConstraint().getAuthenticate()) + { + out.openTag("auth-constraint"); + if (m.getConstraint().getRoles()!=null) + for (String r : m.getConstraint().getRoles()) + out.tag("role-name",r); + + out.closeTag(); + } + + switch (m.getConstraint().getDataConstraint()) + { + case Constraint.DC_NONE: + out.openTag("user-data-constraint").tag("transport-guarantee","NONE").closeTag(); + break; + + case Constraint.DC_INTEGRAL: + out.openTag("user-data-constraint").tag("transport-guarantee","INTEGRAL").closeTag(); + break; + + case Constraint.DC_CONFIDENTIAL: + out.openTag("user-data-constraint").tag("transport-guarantee","CONFIDENTIAL").closeTag(); + break; + + default: + break; + + } + + out.openTag("web-resource-collection"); + { + if (m.getConstraint().getName()!=null) + out.tag("web-resource-name",m.getConstraint().getName()); + if (m.getPathSpec()!=null) + out.tag("url-pattern",origin(md,"constraint.url."+m.getPathSpec()),m.getPathSpec()); + if (m.getMethod()!=null) + out.tag("http-method",m.getMethod()); + + if (m.getMethodOmissions()!=null) + for (String o:m.getMethodOmissions()) + out.tag("http-method-omission",o); + + out.closeTag(); + } + + out.closeTag(); + + } + } + + if (_webApp.getWelcomeFiles() != null) + { + out.openTag("welcome-file-list"); + for (String welcomeFile:_webApp.getWelcomeFiles()) + { + out.tag("welcome-file", welcomeFile); + } + out.closeTag(); + } + + Map localeEncodings = _webApp.getLocaleEncodings(); + if (localeEncodings != null && !localeEncodings.isEmpty()) + { + out.openTag("locale-encoding-mapping-list"); + for (Map.Entry entry:localeEncodings.entrySet()) + { + out.openTag("locale-encoding-mapping", origin(md,"locale-encoding."+entry.getKey())); + out.tag("locale", entry.getKey()); + out.tag("encoding", entry.getValue()); + out.closeTag(); + } + out.closeTag(); + } + + //session-config + if (_webApp.getSessionHandler().getSessionManager() != null) + { + out.openTag("session-config"); + int maxInactiveSec = _webApp.getSessionHandler().getSessionManager().getMaxInactiveInterval(); + out.tag("session-timeout", (maxInactiveSec==0?"0":Integer.toString(maxInactiveSec/60))); + + Set modes =_webApp. getSessionHandler().getSessionManager().getEffectiveSessionTrackingModes(); + if (modes != null) + { + for (SessionTrackingMode mode:modes) + out.tag("tracking-mode", mode.toString()); + } + + //cookie-config + SessionCookieConfig cookieConfig = _webApp.getSessionHandler().getSessionManager().getSessionCookieConfig(); + if (cookieConfig != null) + { + out.openTag("cookie-config"); + if (cookieConfig.getName() != null) + out.tag("name", origin(md,"cookie-config.name"), cookieConfig.getName()); + + if (cookieConfig.getDomain() != null) + out.tag("domain", origin(md, "cookie-config.domain"), cookieConfig.getDomain()); + + if (cookieConfig.getPath() != null) + out.tag("path", origin(md, "cookie-config.path"), cookieConfig.getPath()); + + if (cookieConfig.getComment() != null) + out.tag("comment", origin(md, "cookie-config.comment"), cookieConfig.getComment()); + + out.tag("http-only", origin(md, "cookie-config.http-only"), Boolean.toString(cookieConfig.isHttpOnly())); + out.tag("secure", origin(md, "cookie-config.secure"), Boolean.toString(cookieConfig.isSecure())); + out.tag("max-age", origin(md, "cookie-config.max-age"), Integer.toString(cookieConfig.getMaxAge())); + out.closeTag(); + } + out.closeTag(); + } + + //error-pages + Map errorPages = ((ErrorPageErrorHandler)_webApp.getErrorHandler()).getErrorPages(); + if (errorPages != null) + { + for (Map.Entry entry:errorPages.entrySet()) + { + out.openTag("error-page", origin(md, "error."+entry.getKey())); + //a global or default error page has no code or exception + if (!ErrorPageErrorHandler.GLOBAL_ERROR_PAGE.equals(entry.getKey())) + { + if (entry.getKey().matches("\\d{3}")) + out.tag("error-code", entry.getKey()); + else + out.tag("exception-type", entry.getKey()); + } + out.tag("location", entry.getValue()); + out.closeTag(); + } + } + + //mime-types + MimeTypes mimeTypes = _webApp.getMimeTypes(); + if (mimeTypes != null) + { + for (Map.Entry entry:mimeTypes.getMimeMap().entrySet()) + { + out.openTag("mime-mapping"); + out.tag("extension", origin(md, "extension."+entry.getKey()), entry.getKey()); + out.tag("mime-type", entry.getValue()); + out.closeTag(); + } + } + + //jsp-config + JspConfig jspConfig = (JspConfig)_webApp.getServletContext().getJspConfigDescriptor(); + if (jspConfig != null) + { + out.openTag("jsp-config"); + Collection tlds = jspConfig.getTaglibs(); + if (tlds != null && !tlds.isEmpty()) + { + for (TaglibDescriptor tld:tlds) + { + out.openTag("taglib"); + out.tag("taglib-uri", tld.getTaglibURI()); + out.tag("taglib-location", tld.getTaglibLocation()); + out.closeTag(); + } + } + + Collection jspPropertyGroups = jspConfig.getJspPropertyGroups(); + if (jspPropertyGroups != null && !jspPropertyGroups.isEmpty()) + { + for (JspPropertyGroupDescriptor jspPropertyGroup:jspPropertyGroups) + { + out.openTag("jsp-property-group"); + Collection strings = jspPropertyGroup.getUrlPatterns(); + if (strings != null && !strings.isEmpty()) + { + for (String urlPattern:strings) + out.tag("url-pattern", urlPattern); + } + + if (jspPropertyGroup.getElIgnored() != null) + out.tag("el-ignored", jspPropertyGroup.getElIgnored()); + + if (jspPropertyGroup.getPageEncoding() != null) + out.tag("page-encoding", jspPropertyGroup.getPageEncoding()); + + if (jspPropertyGroup.getScriptingInvalid() != null) + out.tag("scripting-invalid", jspPropertyGroup.getScriptingInvalid()); + + if (jspPropertyGroup.getIsXml() != null) + out.tag("is-xml", jspPropertyGroup.getIsXml()); + + if (jspPropertyGroup.getDeferredSyntaxAllowedAsLiteral() != null) + out.tag("deferred-syntax-allowed-as-literal", jspPropertyGroup.getDeferredSyntaxAllowedAsLiteral()); + + if (jspPropertyGroup.getTrimDirectiveWhitespaces() != null) + out.tag("trim-directive-whitespaces", jspPropertyGroup.getTrimDirectiveWhitespaces()); + + if (jspPropertyGroup.getDefaultContentType() != null) + out.tag("default-content-type", jspPropertyGroup.getDefaultContentType()); + + if (jspPropertyGroup.getBuffer() != null) + out.tag("buffer", jspPropertyGroup.getBuffer()); + + if (jspPropertyGroup.getErrorOnUndeclaredNamespace() != null) + out.tag("error-on-undeclared-namespace", jspPropertyGroup.getErrorOnUndeclaredNamespace()); + + strings = jspPropertyGroup.getIncludePreludes(); + if (strings != null && !strings.isEmpty()) + { + for (String prelude:strings) + out.tag("include-prelude", prelude); + } + + strings = jspPropertyGroup.getIncludeCodas(); + if (strings != null && !strings.isEmpty()) + { + for (String coda:strings) + out.tag("include-coda", coda); + } + + out.closeTag(); + } + } + + out.closeTag(); + } + + //lifecycle: post-construct, pre-destroy + LifeCycleCallbackCollection lifecycles = ((LifeCycleCallbackCollection)_webApp.getAttribute(LifeCycleCallbackCollection.LIFECYCLE_CALLBACK_COLLECTION)); + if (lifecycles != null) + { + Collection tmp = lifecycles.getPostConstructCallbacks(); + + for (LifeCycleCallback c:tmp) + { + out.openTag("post-construct"); + out.tag("lifecycle-callback-class", c.getTargetClassName()); + out.tag("lifecycle-callback-method", c.getMethodName()); + out.closeTag(); + } + + tmp = lifecycles.getPreDestroyCallbacks(); + for (LifeCycleCallback c:tmp) + { + out.openTag("pre-destroy"); + out.tag("lifecycle-callback-class", c.getTargetClassName()); + out.tag("lifecycle-callback-method", c.getMethodName()); + out.closeTag(); + } + } + + out.literal(_extraXML); + + out.closeTag(); + } + catch (Exception e) + { + if (e.getSuppressed() != null) + { + for (Throwable t:e.getSuppressed()) + t.printStackTrace(); + } + } + + return webXml; + } + + /** + * Turn attribute into context-param to store. + * + * @param out + * @param attribute + * @throws IOException + */ + private void addContextParamFromAttribute(XmlAppendable out, String attribute) throws IOException + { + addContextParamFromAttribute(out,attribute,null); + } + + /** + * Turn context attribute into context-param to store. + * + * @param out + * @param attribute + * @param resourceBase + * @throws IOException + */ + private void addContextParamFromAttribute(XmlAppendable out, String attribute, String resourceBase) throws IOException + { + Object o = _webApp.getAttribute(attribute); + if (o == null) + return; + + Collection c = (o instanceof Collection)? (Collection)o:Collections.singletonList(o); + StringBuilder v=new StringBuilder(); + for (Object i:c) + { + if (i!=null) + { + if (v.length()>0) + v.append(",\n "); + else + v.append("\n "); + if (resourceBase==null) + QuotedStringTokenizer.quote(v,i.toString()); + else + QuotedStringTokenizer.quote(v,i.toString().replace(resourceBase,"${WAR}/")); + } + } + out.openTag("context-param") + .tag("param-name",attribute) + .tagCDATA("param-value",v.toString()) + .closeTag(); + } + + /** + * Generate xml for a Holder (Filter/Servlet) + * + * @param out + * @param md + * @param tag + * @param holder + * @throws IOException + */ + private void outholder(XmlAppendable out, MetaData md, String tag, Holder holder) throws IOException + { + out.openTag(tag,Collections.singletonMap("source",holder.getSource().toString())); + String n = holder.getName(); + out.tag(tag + "-name",n); + + String ot = n + "." + tag + "."; + + out.tag(tag + "-class",origin(md,ot + tag + "-class"),holder.getClassName()); + + for (String p : holder.getInitParameters().keySet()) + { + if ("scratchdir".equalsIgnoreCase(p)) //don't preconfigure the temp dir for jsp output + continue; + out.openTag("init-param",origin(md,ot + "init-param." + p)) + .tag("param-name",p) + .tag("param-value",holder.getInitParameter(p)) + .closeTag(); + } + + if (holder instanceof ServletHolder) + { + ServletHolder s = (ServletHolder)holder; + if (s.getForcedPath() != null) + out.tag("jsp-file",s.getForcedPath()); + + if (s.getInitOrder() != 0) + out.tag("load-on-startup",Integer.toString(s.getInitOrder())); + + if (s.getRunAsRole() != null) + out.openTag("run-as",origin(md,ot + "run-as")) + .tag("role-name",s.getRunAsRole()) + .closeTag(); + + Map roles = s.getRoleRefMap(); + if (roles!=null) + { + for (Map.Entry e : roles.entrySet()) + { + out.openTag("security-role-ref",origin(md,ot+"role-name."+e.getKey())) + .tag("role-name",e.getKey()) + .tag("role-link",e.getValue()) + .closeTag(); + } + } + + if (!s.isEnabled()) + out.tag("enabled",origin(md,ot + "enabled"),"false"); + + //multipart-config + MultipartConfigElement multipartConfig = ((ServletHolder.Registration)s.getRegistration()).getMultipartConfig(); + if (multipartConfig != null) + { + out.openTag("multipart-config", origin(md, s.getName()+".servlet.multipart-config")); + if (multipartConfig.getLocation() != null) + out.tag("location", multipartConfig.getLocation()); + out.tag("max-file-size", Long.toString(multipartConfig.getMaxFileSize())); + out.tag("max-request-size", Long.toString(multipartConfig.getMaxRequestSize())); + out.tag("file-size-threshold", Long.toString(multipartConfig.getFileSizeThreshold())); + out.closeTag(); + } + } + + out.tag("async-supported",origin(md,ot + "async-supported"),holder.isAsyncSupported()?"true":"false"); + out.closeTag(); + } + + + + /** + * Find the origin (web.xml, fragment, annotation etc) of a web artifact from MetaData. + * + * @param md + * @param name + * @return + */ + public Map origin(MetaData md, String name) + { + if (!LOG.isDebugEnabled()) + return Collections.emptyMap(); + if (name == null) + return Collections.emptyMap(); + OriginInfo origin = md.getOriginInfo(name); + if (LOG.isDebugEnabled()) LOG.debug("origin of "+name+" is "+origin); + if (origin == null) + return Collections.emptyMap(); + return Collections.singletonMap("origin",origin.toString()); + } + +} diff --git a/jetty-quickstart/src/main/java/org/eclipse/jetty/quickstart/QuickStartWebApp.java b/jetty-quickstart/src/main/java/org/eclipse/jetty/quickstart/QuickStartWebApp.java index bcbcab8080..959cf8015c 100644 --- a/jetty-quickstart/src/main/java/org/eclipse/jetty/quickstart/QuickStartWebApp.java +++ b/jetty-quickstart/src/main/java/org/eclipse/jetty/quickstart/QuickStartWebApp.java @@ -18,51 +18,11 @@ package org.eclipse.jetty.quickstart; -import java.io.File; -import java.io.FileOutputStream; -import java.io.IOException; -import java.util.Arrays; -import java.util.Collection; -import java.util.Collections; -import java.util.EventListener; -import java.util.HashMap; -import java.util.Map; -import java.util.Set; - -import javax.servlet.DispatcherType; -import javax.servlet.MultipartConfigElement; -import javax.servlet.ServletContext; -import javax.servlet.SessionCookieConfig; -import javax.servlet.SessionTrackingMode; -import javax.servlet.descriptor.JspPropertyGroupDescriptor; -import javax.servlet.descriptor.TaglibDescriptor; - -import org.eclipse.jetty.annotations.AnnotationConfiguration; -import org.eclipse.jetty.http.MimeTypes; -import org.eclipse.jetty.plus.annotation.LifeCycleCallback; -import org.eclipse.jetty.plus.annotation.LifeCycleCallbackCollection; -import org.eclipse.jetty.security.ConstraintAware; -import org.eclipse.jetty.security.ConstraintMapping; -import org.eclipse.jetty.security.SecurityHandler; -import org.eclipse.jetty.security.authentication.FormAuthenticator; -import org.eclipse.jetty.servlet.ErrorPageErrorHandler; -import org.eclipse.jetty.servlet.FilterHolder; -import org.eclipse.jetty.servlet.FilterMapping; -import org.eclipse.jetty.servlet.Holder; -import org.eclipse.jetty.servlet.ServletHandler; -import org.eclipse.jetty.servlet.ServletHolder; -import org.eclipse.jetty.servlet.ServletMapping; -import org.eclipse.jetty.util.QuotedStringTokenizer; import org.eclipse.jetty.util.log.Log; import org.eclipse.jetty.util.log.Logger; import org.eclipse.jetty.util.resource.JarResource; import org.eclipse.jetty.util.resource.Resource; -import org.eclipse.jetty.util.security.Constraint; -import org.eclipse.jetty.webapp.MetaData; -import org.eclipse.jetty.webapp.MetaData.OriginInfo; -import org.eclipse.jetty.webapp.MetaInfConfiguration; import org.eclipse.jetty.webapp.WebAppContext; -import org.eclipse.jetty.xml.XmlAppendable; /** * QuickStartWar @@ -190,8 +150,7 @@ public class QuickStartWebApp extends WebAppContext { LOG.info("Quickstart preconfigure: {}(war={},dir={})",this,war,dir); - _preconfigProcessor = new PreconfigureDescriptorProcessor(); - + _preconfigProcessor = new PreconfigureDescriptorProcessor(); getMetaData().addDescriptorProcessor(_preconfigProcessor); setPreconfigure(true); _startWebapp=true; @@ -203,518 +162,11 @@ public class QuickStartWebApp extends WebAppContext } - public void generateQuickstartWebXml(String extraXML) throws IOException + public void generateQuickstartWebXml(String extraXML) throws Exception { - getMetaData().getOrigins(); - // dumpStdErr(); - - if (getBaseResource()==null) - throw new IllegalArgumentException("No base resource for "+this); - - File webxml = new File(getWebInf().getFile(),"quickstart-web.xml"); - - LOG.info("Quickstart generate {}",webxml); - - XmlAppendable out = new XmlAppendable(new FileOutputStream(webxml),"UTF-8"); - MetaData md = getMetaData(); - - Map webappAttr = new HashMap<>(); - webappAttr.put("xmlns","http://xmlns.jcp.org/xml/ns/javaee"); - webappAttr.put("xmlns:xsi","http://www.w3.org/2001/XMLSchema-instance"); - webappAttr.put("xsi:schemaLocation","http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd"); - webappAttr.put("metadata-complete","true"); - webappAttr.put("version","3.1"); - - out.open("web-app",webappAttr); - - if (getDisplayName() != null) - out.tag("display-name",getDisplayName()); - - // Set some special context parameters - - // The location of the war file on disk - String resourceBase=getBaseResource().getFile().getCanonicalFile().getAbsoluteFile().toURI().toString(); - - // The library order - addContextParamFromAttribute(out,ServletContext.ORDERED_LIBS); - //the servlet container initializers - addContextParamFromAttribute(out,AnnotationConfiguration.CONTAINER_INITIALIZERS); - //the tlds discovered - addContextParamFromAttribute(out,MetaInfConfiguration.METAINF_TLDS,resourceBase); - //the META-INF/resources discovered - addContextParamFromAttribute(out,MetaInfConfiguration.METAINF_RESOURCES,resourceBase); - - - // init params - for (String p : getInitParams().keySet()) - out.open("context-param",origin(md,"context-param." + p)) - .tag("param-name",p) - .tag("param-value",getInitParameter(p)) - .close(); - - if (getEventListeners() != null) - for (EventListener e : getEventListeners()) - out.open("listener",origin(md,e.getClass().getCanonicalName() + ".listener")) - .tag("listener-class",e.getClass().getCanonicalName()) - .close(); - - ServletHandler servlets = getServletHandler(); - - if (servlets.getFilters() != null) - { - for (FilterHolder holder : servlets.getFilters()) - outholder(out,md,"filter",holder); - } - - if (servlets.getFilterMappings() != null) - { - for (FilterMapping mapping : servlets.getFilterMappings()) - { - out.open("filter-mapping"); - out.tag("filter-name",mapping.getFilterName()); - if (mapping.getPathSpecs() != null) - for (String s : mapping.getPathSpecs()) - out.tag("url-pattern",s); - if (mapping.getServletNames() != null) - for (String n : mapping.getServletNames()) - out.tag("servlet-name",n); - - if (!mapping.isDefaultDispatches()) - { - if (mapping.appliesTo(DispatcherType.REQUEST)) - out.tag("dispatcher","REQUEST"); - if (mapping.appliesTo(DispatcherType.ASYNC)) - out.tag("dispatcher","ASYNC"); - if (mapping.appliesTo(DispatcherType.ERROR)) - out.tag("dispatcher","ERROR"); - if (mapping.appliesTo(DispatcherType.FORWARD)) - out.tag("dispatcher","FORWARD"); - if (mapping.appliesTo(DispatcherType.INCLUDE)) - out.tag("dispatcher","INCLUDE"); - } - out.close(); - } - } - - if (servlets.getServlets() != null) - { - for (ServletHolder holder : servlets.getServlets()) - outholder(out,md,"servlet",holder); - } - - if (servlets.getServletMappings() != null) - { - for (ServletMapping mapping : servlets.getServletMappings()) - { - out.open("servlet-mapping",origin(md,mapping.getServletName() + ".servlet.mappings")); - out.tag("servlet-name",mapping.getServletName()); - if (mapping.getPathSpecs() != null) - for (String s : mapping.getPathSpecs()) - out.tag("url-pattern",s); - out.close(); - } - } - - // Security elements - SecurityHandler security = getSecurityHandler(); - - if (security!=null && (security.getRealmName()!=null || security.getAuthMethod()!=null)) - { - out.open("login-config"); - if (security.getAuthMethod()!=null) - out.tag("auth-method",origin(md,"auth-method"),security.getAuthMethod()); - if (security.getRealmName()!=null) - out.tag("realm-name",origin(md,"realm-name"),security.getRealmName()); - - - if (Constraint.__FORM_AUTH.equalsIgnoreCase(security.getAuthMethod())) - { - out.open("form-login-config"); - out.tag("form-login-page",origin(md,"form-login-page"),security.getInitParameter(FormAuthenticator.__FORM_LOGIN_PAGE)); - out.tag("form-error-page",origin(md,"form-error-page"),security.getInitParameter(FormAuthenticator.__FORM_ERROR_PAGE)); - out.close(); - } - - out.close(); - } - - if (security instanceof ConstraintAware) - { - ConstraintAware ca = (ConstraintAware)security; - for (String r:ca.getRoles()) - out.open("security-role") - .tag("role-name",r) - .close(); - - for (ConstraintMapping m : ca.getConstraintMappings()) - { - out.open("security-constraint"); - - if (m.getConstraint().getAuthenticate()) - { - out.open("auth-constraint"); - if (m.getConstraint().getRoles()!=null) - for (String r : m.getConstraint().getRoles()) - out.tag("role-name",r); - - out.close(); - } - - switch (m.getConstraint().getDataConstraint()) - { - case Constraint.DC_NONE: - out.open("user-data-constraint").tag("transport-guarantee","NONE").close(); - break; - - case Constraint.DC_INTEGRAL: - out.open("user-data-constraint").tag("transport-guarantee","INTEGRAL").close(); - break; - - case Constraint.DC_CONFIDENTIAL: - out.open("user-data-constraint").tag("transport-guarantee","CONFIDENTIAL").close(); - break; - - default: - break; - - } - - out.open("web-resource-collection"); - { - if (m.getConstraint().getName()!=null) - out.tag("web-resource-name",m.getConstraint().getName()); - if (m.getPathSpec()!=null) - out.tag("url-pattern",origin(md,"constraint.url."+m.getPathSpec()),m.getPathSpec()); - if (m.getMethod()!=null) - out.tag("http-method",m.getMethod()); - - if (m.getMethodOmissions()!=null) - for (String o:m.getMethodOmissions()) - out.tag("http-method-omission",o); - - out.close(); - } - - out.close(); - - } - } - - if (getWelcomeFiles() != null) - { - out.open("welcome-file-list"); - for (String welcomeFile:getWelcomeFiles()) - { - out.tag("welcome-file", welcomeFile); - } - out.close(); - } - - Map localeEncodings = getLocaleEncodings(); - if (localeEncodings != null && !localeEncodings.isEmpty()) - { - out.open("locale-encoding-mapping-list"); - for (Map.Entry entry:localeEncodings.entrySet()) - { - out.open("locale-encoding-mapping", origin(md,"locale-encoding."+entry.getKey())); - out.tag("locale", entry.getKey()); - out.tag("encoding", entry.getValue()); - out.close(); - } - out.close(); - } - - //session-config - if (getSessionHandler().getSessionManager() != null) - { - out.open("session-config"); - int maxInactiveSec = getSessionHandler().getSessionManager().getMaxInactiveInterval(); - out.tag("session-timeout", (maxInactiveSec==0?"0":Integer.toString(maxInactiveSec/60))); - - Set modes = getSessionHandler().getSessionManager().getEffectiveSessionTrackingModes(); - if (modes != null) - { - for (SessionTrackingMode mode:modes) - out.tag("tracking-mode", mode.toString()); - } - - //cookie-config - SessionCookieConfig cookieConfig = getSessionHandler().getSessionManager().getSessionCookieConfig(); - if (cookieConfig != null) - { - out.open("cookie-config"); - if (cookieConfig.getName() != null) - out.tag("name", origin(md,"cookie-config.name"), cookieConfig.getName()); - - if (cookieConfig.getDomain() != null) - out.tag("domain", origin(md, "cookie-config.domain"), cookieConfig.getDomain()); - - if (cookieConfig.getPath() != null) - out.tag("path", origin(md, "cookie-config.path"), cookieConfig.getPath()); - - if (cookieConfig.getComment() != null) - out.tag("comment", origin(md, "cookie-config.comment"), cookieConfig.getComment()); - - out.tag("http-only", origin(md, "cookie-config.http-only"), Boolean.toString(cookieConfig.isHttpOnly())); - out.tag("secure", origin(md, "cookie-config.secure"), Boolean.toString(cookieConfig.isSecure())); - out.tag("max-age", origin(md, "cookie-config.max-age"), Integer.toString(cookieConfig.getMaxAge())); - out.close(); - } - out.close(); - } - - //error-pages - Map errorPages = ((ErrorPageErrorHandler)getErrorHandler()).getErrorPages(); - if (errorPages != null) - { - for (Map.Entry entry:errorPages.entrySet()) - { - out.open("error-page", origin(md, "error."+entry.getKey())); - //a global or default error page has no code or exception - if (!ErrorPageErrorHandler.GLOBAL_ERROR_PAGE.equals(entry.getKey())) - { - if (entry.getKey().matches("\\d{3}")) - out.tag("error-code", entry.getKey()); - else - out.tag("exception-type", entry.getKey()); - } - out.tag("location", entry.getValue()); - out.close(); - } - } - - //mime-types - MimeTypes mimeTypes = getMimeTypes(); - if (mimeTypes != null) - { - for (Map.Entry entry:mimeTypes.getMimeMap().entrySet()) - { - out.open("mime-mapping"); - out.tag("extension", origin(md, "extension."+entry.getKey()), entry.getKey()); - out.tag("mime-type", entry.getValue()); - out.close(); - } - } - - //jsp-config - JspConfig jspConfig = (JspConfig)getServletContext().getJspConfigDescriptor(); - if (jspConfig != null) - { - out.open("jsp-config"); - Collection tlds = jspConfig.getTaglibs(); - if (tlds != null && !tlds.isEmpty()) - { - for (TaglibDescriptor tld:tlds) - { - out.open("taglib"); - out.tag("taglib-uri", tld.getTaglibURI()); - out.tag("taglib-location", tld.getTaglibLocation()); - out.close(); - } - } - - Collection jspPropertyGroups = jspConfig.getJspPropertyGroups(); - if (jspPropertyGroups != null && !jspPropertyGroups.isEmpty()) - { - for (JspPropertyGroupDescriptor jspPropertyGroup:jspPropertyGroups) - { - out.open("jsp-property-group"); - Collection strings = jspPropertyGroup.getUrlPatterns(); - if (strings != null && !strings.isEmpty()) - { - for (String urlPattern:strings) - out.tag("url-pattern", urlPattern); - } - - if (jspPropertyGroup.getElIgnored() != null) - out.tag("el-ignored", jspPropertyGroup.getElIgnored()); - - if (jspPropertyGroup.getPageEncoding() != null) - out.tag("page-encoding", jspPropertyGroup.getPageEncoding()); - - if (jspPropertyGroup.getScriptingInvalid() != null) - out.tag("scripting-invalid", jspPropertyGroup.getScriptingInvalid()); - - if (jspPropertyGroup.getIsXml() != null) - out.tag("is-xml", jspPropertyGroup.getIsXml()); - - if (jspPropertyGroup.getDeferredSyntaxAllowedAsLiteral() != null) - out.tag("deferred-syntax-allowed-as-literal", jspPropertyGroup.getDeferredSyntaxAllowedAsLiteral()); - - if (jspPropertyGroup.getTrimDirectiveWhitespaces() != null) - out.tag("trim-directive-whitespaces", jspPropertyGroup.getTrimDirectiveWhitespaces()); - - if (jspPropertyGroup.getDefaultContentType() != null) - out.tag("default-content-type", jspPropertyGroup.getDefaultContentType()); - - if (jspPropertyGroup.getBuffer() != null) - out.tag("buffer", jspPropertyGroup.getBuffer()); - - if (jspPropertyGroup.getErrorOnUndeclaredNamespace() != null) - out.tag("error-on-undeclared-namespace", jspPropertyGroup.getErrorOnUndeclaredNamespace()); - - strings = jspPropertyGroup.getIncludePreludes(); - if (strings != null && !strings.isEmpty()) - { - for (String prelude:strings) - out.tag("include-prelude", prelude); - } - - strings = jspPropertyGroup.getIncludeCodas(); - if (strings != null && !strings.isEmpty()) - { - for (String coda:strings) - out.tag("include-coda", coda); - } - - out.close(); - } - } - - out.close(); - } - - //lifecycle: post-construct, pre-destroy - LifeCycleCallbackCollection lifecycles = ((LifeCycleCallbackCollection)getAttribute(LifeCycleCallbackCollection.LIFECYCLE_CALLBACK_COLLECTION)); - if (lifecycles != null) - { - Collection tmp = lifecycles.getPostConstructCallbacks(); - - for (LifeCycleCallback c:tmp) - { - out.open("post-construct"); - out.tag("lifecycle-callback-class", c.getTargetClassName()); - out.tag("lifecycle-callback-method", c.getMethodName()); - out.close(); - } - - tmp = lifecycles.getPreDestroyCallbacks(); - for (LifeCycleCallback c:tmp) - { - out.open("pre-destroy"); - out.tag("lifecycle-callback-class", c.getTargetClassName()); - out.tag("lifecycle-callback-method", c.getMethodName()); - out.close(); - } - } - - out.literal(extraXML); - - out.close(); - } - - private void addContextParamFromAttribute(XmlAppendable out, String attribute) throws IOException - { - addContextParamFromAttribute(out,attribute,null); - } - - private void addContextParamFromAttribute(XmlAppendable out, String attribute, String resourceBase) throws IOException - { - Object o=getAttribute(attribute); - if (o==null) - return; - - Collection c = (o instanceof Collection)? (Collection)o:Collections.singletonList(o); - StringBuilder v=new StringBuilder(); - for (Object i:c) - { - if (i!=null) - { - if (v.length()>0) - v.append(",\n "); - else - v.append("\n "); - if (resourceBase==null) - QuotedStringTokenizer.quote(v,i.toString()); - else - QuotedStringTokenizer.quote(v,i.toString().replace(resourceBase,"${WAR}/")); - } - } - out.open("context-param") - .tag("param-name",attribute) - .tagCDATA("param-value",v.toString()) - .close(); - } - - private static void outholder(XmlAppendable out, MetaData md, String tag, Holder holder) throws IOException - { - out.open(tag,Collections.singletonMap("source",holder.getSource().toString())); - String n = holder.getName(); - out.tag(tag + "-name",n); - - String ot = n + "." + tag + "."; - - out.tag(tag + "-class",origin(md,ot + tag + "-class"),holder.getClassName()); - - for (String p : holder.getInitParameters().keySet()) - { - if ("scratchdir".equalsIgnoreCase(p)) //don't preconfigure the temp dir for jsp output - continue; - out.open("init-param",origin(md,ot + "init-param." + p)) - .tag("param-name",p) - .tag("param-value",holder.getInitParameter(p)) - .close(); - } - - if (holder instanceof ServletHolder) - { - ServletHolder s = (ServletHolder)holder; - if (s.getForcedPath() != null) - out.tag("jsp-file",s.getForcedPath()); - - if (s.getInitOrder() != 0) - out.tag("load-on-startup",Integer.toString(s.getInitOrder())); - - if (s.getRunAsRole() != null) - out.open("run-as",origin(md,ot + "run-as")) - .tag("role-name",s.getRunAsRole()) - .close(); - - Map roles = s.getRoleRefMap(); - if (roles!=null) - { - for (Map.Entry e : roles.entrySet()) - { - out.open("security-role-ref",origin(md,ot+"role-name."+e.getKey())) - .tag("role-name",e.getKey()) - .tag("role-link",e.getValue()) - .close(); - } - } - - if (!s.isEnabled()) - out.tag("enabled",origin(md,ot + "enabled"),"false"); - - //multipart-config - MultipartConfigElement multipartConfig = ((ServletHolder.Registration)s.getRegistration()).getMultipartConfig(); - if (multipartConfig != null) - { - out.open("multipart-config", origin(md, s.getName()+".servlet.multipart-config")); - if (multipartConfig.getLocation() != null) - out.tag("location", multipartConfig.getLocation()); - out.tag("max-file-size", Long.toString(multipartConfig.getMaxFileSize())); - out.tag("max-request-size", Long.toString(multipartConfig.getMaxRequestSize())); - out.tag("file-size-threshold", Long.toString(multipartConfig.getFileSizeThreshold())); - out.close(); - } - } - - out.tag("async-supported",origin(md,ot + "async-supported"),holder.isAsyncSupported()?"true":"false"); - out.close(); + QuickStartDescriptorGenerator generator = new QuickStartDescriptorGenerator(this, this.getWebInf().getFile(), extraXML); + generator.generateQuickStartWebXml(); } - public static Map origin(MetaData md, String name) - { - if (!LOG.isDebugEnabled()) - return Collections.emptyMap(); - if (name == null) - return Collections.emptyMap(); - OriginInfo origin = md.getOriginInfo(name); - // System.err.println("origin of "+name+" is "+origin); - if (origin == null) - return Collections.emptyMap(); - return Collections.singletonMap("origin",origin.toString()); - - } - + } -- cgit v1.2.3