Author: markt Date: Tue Dec 29 12:50:54 2009 New Revision: 894372 URL: http://svn.apache.org/viewvc?rev=894372&view=rev Log: Add configuration option that allows the effective web.xml to be logged on context start. Expose the effective web.xml through a context attribute so other components (eg Jasper) can use it.
Modified: tomcat/trunk/java/org/apache/catalina/Context.java tomcat/trunk/java/org/apache/catalina/core/StandardContext.java tomcat/trunk/java/org/apache/catalina/startup/ContextConfig.java tomcat/trunk/java/org/apache/catalina/startup/WebXml.java tomcat/trunk/java/org/apache/tomcat/util/scan/Constants.java tomcat/trunk/webapps/docs/config/context.xml Modified: tomcat/trunk/java/org/apache/catalina/Context.java URL: http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/catalina/Context.java?rev=894372&r1=894371&r2=894372&view=diff ============================================================================== --- tomcat/trunk/java/org/apache/catalina/Context.java (original) +++ tomcat/trunk/java/org/apache/catalina/Context.java Tue Dec 29 12:50:54 2009 @@ -1101,5 +1101,16 @@ * <code>null</code> if none is used. */ public Authenticator getAuthenticator(); + + /** + * Set whether or not the effective web.xml for this context should be + * logged on context start. + */ + public void setLogEffectiveWebXml(boolean logEffectiveWebXml); + + /** + * Should the effective web.xml for this context be logged on context start? + */ + public boolean getLogEffectiveWebXml(); } Modified: tomcat/trunk/java/org/apache/catalina/core/StandardContext.java URL: http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/catalina/core/StandardContext.java?rev=894372&r1=894371&r2=894372&view=diff ============================================================================== --- tomcat/trunk/java/org/apache/catalina/core/StandardContext.java (original) +++ tomcat/trunk/java/org/apache/catalina/core/StandardContext.java Tue Dec 29 12:50:54 2009 @@ -758,8 +758,20 @@ */ private boolean clearReferencesStopThreads = false; + /** + * Should the effective web.xml be logged when the context starts? + */ + private boolean logEffectiveWebXml = false; + // ----------------------------------------------------- Context Properties + public void setLogEffectiveWebXml(boolean logEffectiveWebXml) { + this.logEffectiveWebXml = logEffectiveWebXml; + } + + public boolean getLogEffectiveWebXml() { + return logEffectiveWebXml; + } public Authenticator getAuthenticator() { if (this instanceof Authenticator) Modified: tomcat/trunk/java/org/apache/catalina/startup/ContextConfig.java URL: http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/catalina/startup/ContextConfig.java?rev=894372&r1=894371&r2=894372&view=diff ============================================================================== --- tomcat/trunk/java/org/apache/catalina/startup/ContextConfig.java (original) +++ tomcat/trunk/java/org/apache/catalina/startup/ContextConfig.java Tue Dec 29 12:50:54 2009 @@ -32,7 +32,6 @@ import java.util.ArrayList; import java.util.Enumeration; import java.util.HashMap; -import java.util.HashSet; import java.util.Map; import java.util.Properties; import java.util.Set; @@ -1224,6 +1223,15 @@ // Apply merged web.xml to Context webXml.configureContext(context); } + // Make the merged web.xml available to other components, specifically + // Jasper, to save those components from having to re-generate it. + String mergedWebXml = webXml.toXml(); + context.getServletContext().setAttribute( + org.apache.tomcat.util.scan.Constants.MERGED_WEB_XML, + mergedWebXml); + if (context.getLogEffectiveWebXml()) { + log.info("web.xml:\n" + mergedWebXml); + } } Modified: tomcat/trunk/java/org/apache/catalina/startup/WebXml.java URL: http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/catalina/startup/WebXml.java?rev=894372&r1=894371&r2=894372&view=diff ============================================================================== --- tomcat/trunk/java/org/apache/catalina/startup/WebXml.java (original) +++ tomcat/trunk/java/org/apache/catalina/startup/WebXml.java Tue Dec 29 12:50:54 2009 @@ -21,6 +21,7 @@ import java.net.URL; import java.util.HashMap; import java.util.HashSet; +import java.util.Iterator; import java.util.LinkedHashMap; import java.util.LinkedHashSet; import java.util.LinkedList; @@ -34,6 +35,7 @@ import org.apache.catalina.Wrapper; import org.apache.catalina.deploy.ContextEjb; import org.apache.catalina.deploy.ContextEnvironment; +import org.apache.catalina.deploy.ContextHandler; import org.apache.catalina.deploy.ContextLocalEjb; import org.apache.catalina.deploy.ContextResource; import org.apache.catalina.deploy.ContextResourceEnvRef; @@ -41,12 +43,14 @@ import org.apache.catalina.deploy.ErrorPage; import org.apache.catalina.deploy.FilterDef; import org.apache.catalina.deploy.FilterMap; +import org.apache.catalina.deploy.InjectionTarget; import org.apache.catalina.deploy.JspPropertyGroup; import org.apache.catalina.deploy.LoginConfig; import org.apache.catalina.deploy.MessageDestination; import org.apache.catalina.deploy.MessageDestinationRef; import org.apache.catalina.deploy.MultipartDef; import org.apache.catalina.deploy.ResourceBase; +import org.apache.catalina.deploy.SecurityCollection; import org.apache.catalina.deploy.SecurityConstraint; import org.apache.catalina.deploy.SecurityRoleRef; import org.apache.catalina.deploy.ServletDef; @@ -65,7 +69,7 @@ protected static final String ORDER_OTHERS = "org.apache.catalina.order.others"; - protected static final StringManager sm = + private static final StringManager sm = StringManager.getManager(Constants.Package); private static final org.apache.juli.logging.Log log= @@ -461,8 +465,563 @@ return buf.toString(); } + private static final String INDENT2 = " "; + private static final String INDENT4 = " "; + private static final String INDENT6 = " "; /** + * Generate a web.xml in String form that matches the representation stored + * in this object. + * + * @return The complete contents of web.xml as a String + */ + public String toXml() { + StringBuilder sb = new StringBuilder(2048); + + // TODO - Various, icon, description etc elements are skipped - mainly + // because they are ignored when web.xml is parsed - see above + + // Declaration + sb.append("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"); + + // Root element + sb.append("<web-app xmlns=\"http://java.sun.com/xml/ns/javaee\"\n"); + sb.append(" xmlns:xsi="); + sb.append("\"http://www.w3.org/2001/XMLSchema-instance\"\n"); + sb.append(" xsi:schemaLocation="); + sb.append("\"http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd\"\n"); + sb.append(" version=\"3.0\"\n"); + sb.append(" metadata-complete=\"true\">\n\n"); + + appendElement(sb, INDENT2, "display-name", displayName); + + if (isDistributable()) { + sb.append(" <distributable/>\n\n"); + } + + for (Map.Entry<String, String> entry : contextParams.entrySet()) { + sb.append(" <context-param>\n"); + appendElement(sb, INDENT4, "param-name", entry.getKey()); + appendElement(sb, INDENT4, "param-valuee", entry.getValue()); + sb.append(" </context-param>\n"); + } + sb.append('\n'); + + for (Map.Entry<String, FilterDef> entry : filters.entrySet()) { + FilterDef filterDef = entry.getValue(); + sb.append(" <filter>\n"); + appendElement(sb, INDENT4, "description", + filterDef.getDescription()); + appendElement(sb, INDENT4, "display-name", + filterDef.getDisplayName()); + appendElement(sb, INDENT4, "filter-name", + filterDef.getFilterName()); + appendElement(sb, INDENT4, "filter-class", + filterDef.getFilterClass()); + appendElement(sb, INDENT4, "async-supported", + filterDef.getAsyncSupported()); + for (Map.Entry<String, String> param : + filterDef.getParameterMap().entrySet()) { + sb.append(" <init-param>\n"); + appendElement(sb, INDENT6, "param-name", param.getKey()); + appendElement(sb, INDENT6, "param-value", param.getValue()); + sb.append(" </init-param>\n"); + } + sb.append(" </filter>\n"); + } + sb.append('\n'); + + for (FilterMap filterMap : filterMaps) { + sb.append(" <filter-mapping>\n"); + appendElement(sb, INDENT4, "filter-name", + filterMap.getFilterName()); + if (filterMap.getMatchAllServletNames()) { + sb.append(" <servlet-name>*</servlet-name>\n"); + } else { + for (String servletName : filterMap.getServletNames()) { + appendElement(sb, INDENT4, "servlet-name", servletName); + } + } + if (filterMap.getMatchAllUrlPatterns()) { + sb.append(" <url-pattern>*</url-pattern>\n"); + } else { + for (String urlPattern : filterMap.getURLPatterns()) { + appendElement(sb, INDENT4, "url-pattern", urlPattern); + } + } + for (String dispatcher : filterMap.getDispatcherNames()) { + appendElement(sb, INDENT4, "dispatcher", dispatcher); + } + sb.append(" </filter-mapping>\n"); + } + sb.append('\n'); + + for (String listener : listeners) { + sb.append(" <listener>\n"); + appendElement(sb, INDENT4, "listener-class", listener); + sb.append(" </listener>\n"); + } + sb.append('\n'); + + for (Map.Entry<String, ServletDef> entry : servlets.entrySet()) { + ServletDef servletDef = entry.getValue(); + sb.append(" <servlet>\n"); + appendElement(sb, INDENT4, "description", + servletDef.getDescription()); + appendElement(sb, INDENT4, "display-name", + servletDef.getDisplayName()); + appendElement(sb, INDENT4, "servlet-name", entry.getKey()); + appendElement(sb, INDENT4, "servlet-class", + servletDef.getServletClass()); + appendElement(sb, INDENT4, "jsp-file", servletDef.getJspFile()); + for (Map.Entry<String, String> param : + servletDef.getParameterMap().entrySet()) { + sb.append(" <init-param>\n"); + appendElement(sb, INDENT6, "param-name", param.getKey()); + appendElement(sb, INDENT6, "param-value", param.getValue()); + sb.append(" </init-param>\n"); + } + appendElement(sb, INDENT4, "load-on-startup", + servletDef.getLoadOnStartup()); + // TODO enabled + appendElement(sb, INDENT4, "async-supported", + servletDef.getAsyncSupported()); + sb.append(" <run-as>\n"); + appendElement(sb, INDENT6, "role-name", servletDef.getRunAs()); + sb.append(" </run-as>\n"); + for (SecurityRoleRef roleRef : servletDef.getSecurityRoleRefs()) { + sb.append(" <security-role-ref>\n"); + appendElement(sb, INDENT6, "role-name", roleRef.getName()); + appendElement(sb, INDENT6, "role-link", roleRef.getLink()); + sb.append(" </security-role-ref>\n"); + } + MultipartDef multipartDef = servletDef.getMultipartDef(); + if (multipartDef != null) { + sb.append(" <multipart-config>\n"); + appendElement(sb, INDENT6, "location", + multipartDef.getLocation()); + appendElement(sb, INDENT6, "max-file-size", + multipartDef.getMaxFileSize()); + appendElement(sb, INDENT6, "max-request-size", + multipartDef.getMaxRequestSize()); + appendElement(sb, INDENT6, "file-size-threshold", + multipartDef.getFileSizeThreshold()); + sb.append(" </multipart-config>\n"); + } + sb.append(" </servlet>\n"); + } + sb.append('\n'); + + for (Map.Entry<String, String> entry : servletMappings.entrySet()) { + sb.append(" <servlet-mapping>\n"); + appendElement(sb, INDENT4, "servlet-name", entry.getValue()); + appendElement(sb, INDENT4, "url-pattern", entry.getKey()); + sb.append(" </servlet-mapping>\n"); + } + sb.append('\n'); + + if (sessionTimeout != null) { + sb.append(" <session-config>\n"); + appendElement(sb, INDENT4, "session-timeout", + sessionTimeout.toString()); + // TODO cookie-config + // TODO tracking-mode + sb.append(" </session-config>\n\n"); + } + + for (Map.Entry<String, String> entry : mimeMappings.entrySet()) { + sb.append(" <mime-mapping>\n"); + appendElement(sb, INDENT4, "extension", entry.getKey()); + appendElement(sb, INDENT4, "mime-type", entry.getValue()); + sb.append(" </mime-mapping>\n"); + } + sb.append('\n'); + + if (welcomeFiles.size() > 0) { + sb.append(" <welcome-file-list>\n"); + for (String welcomeFile : welcomeFiles) { + appendElement(sb, INDENT4, "welcome-file", welcomeFile); + } + sb.append(" </welcome-file-list>\n\n"); + } + + for (ErrorPage errorPage : errorPages.values()) { + sb.append(" <error-page>\n"); + if (errorPage.getExceptionType() == null) { + appendElement(sb, INDENT4, "error-code", + Integer.toString(errorPage.getErrorCode())); + } else { + appendElement(sb, INDENT4, "exception-type", + errorPage.getExceptionType()); + } + appendElement(sb, INDENT4, "location", errorPage.getLocation()); + sb.append(" </error-page>\n"); + } + sb.append('\n'); + + if (taglibs.size() > 0 || jspPropertyGroups.size() > 0) { + sb.append(" <jsp-config>\n"); + for (Map.Entry<String, String> entry : taglibs.entrySet()) { + sb.append(" <taglib>\n"); + appendElement(sb, INDENT6, "taglib-uri", entry.getKey()); + appendElement(sb, INDENT6, "taglib-location", entry.getValue()); + sb.append(" </taglib>\n"); + } + for (JspPropertyGroup jpg : jspPropertyGroups) { + sb.append(" <jsp-property-group>\n"); + appendElement(sb, INDENT6, "url-pattern", jpg.getUrlPattern()); + appendElement(sb, INDENT6, "el-ignored", jpg.getElIgnored()); + appendElement(sb, INDENT6, "scripting-invalid", + jpg.getScriptingInvalid()); + appendElement(sb, INDENT6, "page-encoding", + jpg.getPageEncoding()); + for (String prelude : jpg.getIncludePreludes()) { + appendElement(sb, INDENT6, "include-prelude", prelude); + } + for (String coda : jpg.getIncludeCodas()) { + appendElement(sb, INDENT6, "include-coda", coda); + } + appendElement(sb, INDENT6, "is-xml", jpg.getIsXml()); + appendElement(sb, INDENT6, "deferred-syntax-allowed-as-literal", + jpg.getDeferredSyntax()); + appendElement(sb, INDENT6, "trim-directive-whitespaces", + jpg.getTrimWhitespace()); + appendElement(sb, INDENT6, "default-content-type", + jpg.getDefaultContentType()); + appendElement(sb, INDENT6, "buffer", jpg.getBuffer()); + appendElement(sb, INDENT6, "error-on-undeclared-namespace", + jpg.getErrorOnUndeclaredNamespace()); + sb.append(" </jsp-property-group>\n"); + } + sb.append(" </jsp-config>\n\n"); + } + + for (SecurityConstraint constraint : securityConstraints) { + sb.append(" <security-constraint>\n"); + appendElement(sb, INDENT4, "display-name", + constraint.getDisplayName()); + for (SecurityCollection collection : constraint.findCollections()) { + sb.append(" <web-resource-collection>\n"); + appendElement(sb, INDENT6, "web-resource-name", + collection.getName()); + appendElement(sb, INDENT6, "description", + collection.getDescription()); + for (String urlPattern : collection.findPatterns()) { + appendElement(sb, INDENT6, "url-pattern", urlPattern); + } + for (String method : collection.findMethods()) { + appendElement(sb, INDENT6, "http-method", method); + } + sb.append(" </web-resource-collection>\n"); + } + if (constraint.findAuthRoles().length > 0) { + sb.append(" <auth-constraint>\n"); + for (String role : constraint.findAuthRoles()) { + appendElement(sb, INDENT6, "role-name", role); + } + sb.append(" </auth-constraint>\n"); + } + if (constraint.getUserConstraint() != null) { + sb.append(" <user-data-constraint>\n"); + appendElement(sb, INDENT6, "transport-guarantee", + constraint.getUserConstraint()); + sb.append(" </user-data-constraint>\n"); + } + sb.append(" </security-constraint>\n"); + } + sb.append('\n'); + + if (loginConfig != null) { + sb.append(" <login-config>\n"); + appendElement(sb, INDENT4, "auth-method", + loginConfig.getAuthMethod()); + appendElement(sb,INDENT4, "realm-name", + loginConfig.getRealmName()); + if (loginConfig.getErrorPage() != null || + loginConfig.getLoginPage() != null) { + sb.append(" <form-login-config>\n"); + appendElement(sb, INDENT6, "form-login-page", + loginConfig.getLoginPage()); + appendElement(sb, INDENT6, "form-error-page", + loginConfig.getErrorPage()); + sb.append(" </form-login-config>\n"); + } + sb.append(" </login-config>\n\n"); + } + + for (String roleName : securityRoles) { + sb.append(" <security-role>\n"); + appendElement(sb, INDENT4, "role-name", roleName); + sb.append(" </security-role>\n"); + } + + for (ContextEnvironment envEntry : envEntries.values()) { + sb.append(" <env-entry>\n"); + appendElement(sb, INDENT4, "description", + envEntry.getDescription()); + appendElement(sb, INDENT4, "env-entry-name", envEntry.getName()); + appendElement(sb, INDENT4, "env-entry-type", envEntry.getType()); + appendElement(sb, INDENT4, "env-entry-value", envEntry.getValue()); + // TODO mapped-name + for (InjectionTarget target : envEntry.getInjectionTargets()) { + sb.append(" <injection-target>\n"); + appendElement(sb, INDENT6, "injection-target-class", + target.getTargetClass()); + appendElement(sb, INDENT6, "injection-target-name", + target.getTargetName()); + sb.append(" </injection-target>\n"); + } + // TODO lookup-name + sb.append(" </env-entry>\n"); + } + sb.append('\n'); + + for (ContextEjb ejbRef : ejbRefs.values()) { + sb.append(" <ejb-ref>\n"); + appendElement(sb, INDENT4, "description", ejbRef.getDescription()); + appendElement(sb, INDENT4, "ejb-ref-name", ejbRef.getName()); + appendElement(sb, INDENT4, "ejb-ref-type", ejbRef.getType()); + appendElement(sb, INDENT4, "home", ejbRef.getHome()); + appendElement(sb, INDENT4, "remote", ejbRef.getRemote()); + appendElement(sb, INDENT4, "ejb-link", ejbRef.getLink()); + // TODO mapped-name + for (InjectionTarget target : ejbRef.getInjectionTargets()) { + sb.append(" <injection-target>\n"); + appendElement(sb, INDENT6, "injection-target-class", + target.getTargetClass()); + appendElement(sb, INDENT6, "injection-target-name", + target.getTargetName()); + sb.append(" </injection-target>\n"); + } + // TODO lookup-name + sb.append(" </ejb-ref>\n"); + } + sb.append('\n'); + + for (ContextLocalEjb ejbLocalRef : ejbLocalRefs.values()) { + sb.append(" <ejb-local-ref>\n"); + appendElement(sb, INDENT4, "description", + ejbLocalRef.getDescription()); + appendElement(sb, INDENT4, "ejb-ref-name", ejbLocalRef.getName()); + appendElement(sb, INDENT4, "ejb-ref-type", ejbLocalRef.getType()); + appendElement(sb, INDENT4, "local-home", ejbLocalRef.getHome()); + appendElement(sb, INDENT4, "local", ejbLocalRef.getLocal()); + appendElement(sb, INDENT4, "ejb-link", ejbLocalRef.getLink()); + // TODO mapped-name + for (InjectionTarget target : ejbLocalRef.getInjectionTargets()) { + sb.append(" <injection-target>\n"); + appendElement(sb, INDENT6, "injection-target-class", + target.getTargetClass()); + appendElement(sb, INDENT6, "injection-target-name", + target.getTargetName()); + sb.append(" </injection-target>\n"); + } + // TODO lookup-name + sb.append(" </ejb-local-ref>\n"); + } + sb.append('\n'); + + for (ContextService serviceRef : serviceRefs.values()) { + sb.append(" <service-ref>\n"); + appendElement(sb, INDENT4, "description", + serviceRef.getDescription()); + appendElement(sb, INDENT4, "display-name", + serviceRef.getDisplayname()); + appendElement(sb, INDENT4, "service-ref-name", + serviceRef.getName()); + appendElement(sb, INDENT4, "service-interface", + serviceRef.getInterface()); + appendElement(sb, INDENT4, "service-ref-type", + serviceRef.getType()); + appendElement(sb, INDENT4, "wsdl-file", serviceRef.getWsdlfile()); + appendElement(sb, INDENT4, "jaxrpc-mapping-file", + serviceRef.getJaxrpcmappingfile()); + String qname = serviceRef.getServiceqnameNamespaceURI(); + if (qname != null) { + qname = qname + ":"; + } + qname = qname + serviceRef.getServiceqnameLocalpart(); + appendElement(sb, INDENT4, "service-qname", qname); + Iterator<String> endpointIter = serviceRef.getServiceendpoints(); + while (endpointIter.hasNext()) { + String endpoint = endpointIter.next(); + sb.append(" <port-component-ref>\n"); + appendElement(sb, INDENT6, "service-endpoint-interface", + endpoint); + appendElement(sb, INDENT6, "port-component-link", + serviceRef.getProperty(endpoint)); + sb.append(" </port-component-ref>\n"); + } + Iterator<String> handlerIter = serviceRef.getHandlers(); + while (handlerIter.hasNext()) { + String handler = handlerIter.next(); + sb.append(" <handler>\n"); + ContextHandler ch = serviceRef.getHandler(handler); + appendElement(sb, INDENT6, "handler-name", ch.getName()); + appendElement(sb, INDENT6, "handler-class", + ch.getHandlerclass()); + sb.append(" </handler>\n"); + } + // TODO handler-chains + // TODO mapped-name + for (InjectionTarget target : serviceRef.getInjectionTargets()) { + sb.append(" <injection-target>\n"); + appendElement(sb, INDENT6, "injection-target-class", + target.getTargetClass()); + appendElement(sb, INDENT6, "injection-target-name", + target.getTargetName()); + sb.append(" </injection-target>\n"); + } + // TODO lookup-name + sb.append(" </service-ref>\n"); + } + sb.append('\n'); + + for (ContextResource resourceRef : resourceRefs.values()) { + sb.append(" <resource-ref>\n"); + appendElement(sb, INDENT4, "description", + resourceRef.getDescription()); + appendElement(sb, INDENT4, "res-ref-name", resourceRef.getName()); + appendElement(sb, INDENT4, "res-type", resourceRef.getType()); + appendElement(sb, INDENT4, "res-auth", resourceRef.getAuth()); + appendElement(sb, INDENT4, "res-sharing-scope", + resourceRef.getScope()); + // TODO mapped-name + for (InjectionTarget target : resourceRef.getInjectionTargets()) { + sb.append(" <injection-target>\n"); + appendElement(sb, INDENT6, "injection-target-class", + target.getTargetClass()); + appendElement(sb, INDENT6, "injection-target-name", + target.getTargetName()); + sb.append(" </injection-target>\n"); + } + // TODO lookup-name + sb.append(" </resource-ref>\n"); + } + sb.append('\n'); + + for (ContextResourceEnvRef resourceEnvRef : resourceEnvRefs.values()) { + sb.append(" <resource-env-ref>\n"); + appendElement(sb, INDENT4, "description", + resourceEnvRef.getDescription()); + appendElement(sb, INDENT4, "resource-env-ref-name", + resourceEnvRef.getName()); + appendElement(sb, INDENT4, "resource-env-ref-type", + resourceEnvRef.getType()); + // TODO mapped-name + for (InjectionTarget target : + resourceEnvRef.getInjectionTargets()) { + sb.append(" <injection-target>\n"); + appendElement(sb, INDENT6, "injection-target-class", + target.getTargetClass()); + appendElement(sb, INDENT6, "injection-target-name", + target.getTargetName()); + sb.append(" </injection-target>\n"); + } + // TODO lookup-name + sb.append(" </resource-env-ref>\n"); + } + sb.append('\n'); + + for (MessageDestinationRef mdr : messageDestinationRefs.values()) { + sb.append(" <message-destination-ref>\n"); + appendElement(sb, INDENT4, "description", mdr.getDescription()); + appendElement(sb, INDENT4, "message-destination-ref-name", + mdr.getName()); + appendElement(sb, INDENT4, "message-destination-type", + mdr.getType()); + appendElement(sb, INDENT4, "message-destination-usage", + mdr.getUsage()); + appendElement(sb, INDENT4, "message-destination-link", + mdr.getLink()); + // TODO mapped-name + for (InjectionTarget target : mdr.getInjectionTargets()) { + sb.append(" <injection-target>\n"); + appendElement(sb, INDENT6, "injection-target-class", + target.getTargetClass()); + appendElement(sb, INDENT6, "injection-target-name", + target.getTargetName()); + sb.append(" </injection-target>\n"); + } + // TODO lookup-name + sb.append(" </message-destination-ref>\n"); + } + sb.append('\n'); + + for (MessageDestination md : messageDestinations.values()) { + sb.append(" <message-destination>\n"); + appendElement(sb, INDENT4, "description", md.getDescription()); + appendElement(sb, INDENT4, "display-name", md.getDisplayName()); + appendElement(sb, INDENT4, "message-destination-name", + md.getName()); + // TODO mapped-name + sb.append(" </message-destination>\n"); + } + sb.append('\n'); + + if (localeEncodingMappings.size() > 0) { + sb.append(" <locale-encoding-mapping-list>\n"); + for (Map.Entry<String, String> entry : + localeEncodingMappings.entrySet()) { + sb.append(" <locale-encoding-mapping>\n"); + appendElement(sb, INDENT6, "locale", entry.getKey()); + appendElement(sb, INDENT6, "encoding", entry.getValue()); + sb.append(" </locale-encoding-mapping>\n"); + } + sb.append(" </locale-encoding-mapping-list>\n"); + } + sb.append("</web-app>"); + return sb.toString(); + } + + private static void appendElement(StringBuilder sb, String indent, + String elementName, String value) { + if (value == null || value.length() == 0) return; + sb.append(indent); + sb.append('<'); + sb.append(elementName); + sb.append('>'); + sb.append(escapeXml(value)); + sb.append("</"); + sb.append(elementName); + sb.append(">\n"); + } + + private static void appendElement(StringBuilder sb, String indent, + String elementName, Object value) { + if (value == null) return; + appendElement(sb, indent, elementName, value.toString()); + } + + + /** + * Escape the 5 entities defined by XML. + */ + private static String escapeXml(String s) { + if (s == null) + return null; + StringBuilder sb = new StringBuilder(); + for (int i = 0; i < s.length(); i++) { + char c = s.charAt(i); + if (c == '<') { + sb.append("<"); + } else if (c == '>') { + sb.append(">"); + } else if (c == '\'') { + sb.append("'"); + } else if (c == '&') { + sb.append("&"); + } else if (c == '"') { + sb.append("""); + } else { + sb.append(c); + } + } + return sb.toString(); + } + + + /** * Configure a {...@link Context} using the stored web.xml representation. * * @param context The context to be configured @@ -726,7 +1285,8 @@ filters.putAll(temp.getFilters()); for (WebXml fragment : fragments) { - for (JspPropertyGroup jspPropertyGroup : fragment.getJspPropertyGroups()) { + for (JspPropertyGroup jspPropertyGroup : + fragment.getJspPropertyGroups()) { // Always additive addJspPropertyGroup(jspPropertyGroup); } @@ -904,7 +1464,7 @@ return true; } - private <T extends ResourceBase> boolean mergeResourceMap( + private static <T extends ResourceBase> boolean mergeResourceMap( Map<String, T> fragmentResources, Map<String, T> mainResources, Map<String, T> tempResources, Map<String,Boolean> mergeInjectionFlags, WebXml fragment) { @@ -943,7 +1503,7 @@ return true; } - private <T> boolean mergeMap(Map<String,T> fragmentMap, + private static <T> boolean mergeMap(Map<String,T> fragmentMap, Map<String,T> mainMap, Map<String,T> tempMap, WebXml fragment, String mapName) { for (String key : fragmentMap.keySet()) { @@ -969,7 +1529,8 @@ return true; } - private boolean mergeFilter(FilterDef src, FilterDef dest, boolean failOnConflict) { + private static boolean mergeFilter(FilterDef src, FilterDef dest, + boolean failOnConflict) { if (dest.getAsyncSupported() == null) { dest.setAsyncSupported(src.getAsyncSupported()); } else if (src.getAsyncSupported() != null) { @@ -1002,7 +1563,8 @@ return true; } - private boolean mergeServlet(ServletDef src, ServletDef dest, boolean failOnConflict) { + private static boolean mergeServlet(ServletDef src, ServletDef dest, + boolean failOnConflict) { // These tests should be unnecessary... if (dest.getServletClass() != null && dest.getJspFile() != null) { return false; @@ -1073,7 +1635,7 @@ return true; } - private boolean mergeMultipartDef(MultipartDef src, MultipartDef dest, + private static boolean mergeMultipartDef(MultipartDef src, MultipartDef dest, boolean failOnConflict) { if (dest.getLocation() == null) { @@ -1228,4 +1790,3 @@ } } - Modified: tomcat/trunk/java/org/apache/tomcat/util/scan/Constants.java URL: http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/tomcat/util/scan/Constants.java?rev=894372&r1=894371&r2=894372&view=diff ============================================================================== --- tomcat/trunk/java/org/apache/tomcat/util/scan/Constants.java (original) +++ tomcat/trunk/java/org/apache/tomcat/util/scan/Constants.java Tue Dec 29 12:50:54 2009 @@ -24,11 +24,15 @@ public static final String Package = "org.apache.tomcat.util.scan"; + /* System properties */ public static final String SKIP_JARS_PROPERTY = "tomcat.util.scan.DefaultJarScanner.jarsToSkip"; + /* Commons strings */ public static final String JAR_EXT = ".jar"; public static final String WEB_INF_LIB = "/WEB-INF/lib/"; - + /* Context attributes - used to pass short-cuts to Jasper */ + public static final String MERGED_WEB_XML = + "org.apache.tomcat.util.scan.MergedWebXml"; } Modified: tomcat/trunk/webapps/docs/config/context.xml URL: http://svn.apache.org/viewvc/tomcat/trunk/webapps/docs/config/context.xml?rev=894372&r1=894371&r2=894372&view=diff ============================================================================== --- tomcat/trunk/webapps/docs/config/context.xml (original) +++ tomcat/trunk/webapps/docs/config/context.xml Tue Dec 29 12:50:54 2009 @@ -177,6 +177,15 @@ inferred by the automatic deployment process.</p> </attribute> + <attribute name="logEffectiveWebXml" required="false"> + <p>Set to <code>true</code> if you want the effective web.xml used for a + web application to be logged (at INFO level) when the application + starts. The effective web.xml is the result of combining the + application's web.xml with any defaults configured by Tomcat and any + web-fragment.xml files and annotations discovered. If not specified, the + default value of <code>false</code> is used.</p> + </attribute> + <attribute name="override" required="false"> <p>Set to <code>true</code> to have explicit settings in this Context element override any corresponding settings in either the global --------------------------------------------------------------------- To unsubscribe, e-mail: dev-unsubscr...@tomcat.apache.org For additional commands, e-mail: dev-h...@tomcat.apache.org