Return-Path: Delivered-To: apmail-tomcat-dev-archive@www.apache.org Received: (qmail 63362 invoked from network); 19 Sep 2009 20:13:59 -0000 Received: from hermes.apache.org (HELO mail.apache.org) (140.211.11.3) by minotaur.apache.org with SMTP; 19 Sep 2009 20:13:59 -0000 Received: (qmail 60499 invoked by uid 500); 19 Sep 2009 20:13:58 -0000 Delivered-To: apmail-tomcat-dev-archive@tomcat.apache.org Received: (qmail 60425 invoked by uid 500); 19 Sep 2009 20:13:58 -0000 Mailing-List: contact dev-help@tomcat.apache.org; run by ezmlm Precedence: bulk List-Help: List-Unsubscribe: List-Post: List-Id: Reply-To: "Tomcat Developers List" Delivered-To: mailing list dev@tomcat.apache.org Received: (qmail 60414 invoked by uid 99); 19 Sep 2009 20:13:58 -0000 Received: from nike.apache.org (HELO nike.apache.org) (192.87.106.230) by apache.org (qpsmtpd/0.29) with ESMTP; Sat, 19 Sep 2009 20:13:58 +0000 X-ASF-Spam-Status: No, hits=-2000.0 required=10.0 tests=ALL_TRUSTED X-Spam-Check-By: apache.org Received: from [140.211.11.4] (HELO eris.apache.org) (140.211.11.4) by apache.org (qpsmtpd/0.29) with ESMTP; Sat, 19 Sep 2009 20:13:46 +0000 Received: by eris.apache.org (Postfix, from userid 65534) id D150B23888DA; Sat, 19 Sep 2009 20:13:22 +0000 (UTC) Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit Subject: svn commit: r816951 - in /tomcat/trunk/java/org/apache/catalina: deploy/ startup/ Date: Sat, 19 Sep 2009 20:13:22 -0000 To: dev@tomcat.apache.org From: markt@apache.org X-Mailer: svnmailer-1.0.8 Message-Id: <20090919201322.D150B23888DA@eris.apache.org> X-Virus-Checked: Checked by ClamAV on apache.org Author: markt Date: Sat Sep 19 20:13:22 2009 New Revision: 816951 URL: http://svn.apache.org/viewvc?rev=816951&view=rev Log: First part of the Servlet3 web-fragment support. This patch inserts a stage into the web.xml processing. web.xml files are now parsed and loaded into an instance of WebXml and then that WebXml instance is used to configure the context. This will allow the subsequent addition of parsing and merging web-fragment.xml files. The hooks are in place to add this functionality but it has not yet been written. With the patch applied, the Servlet 2.5 TCK and JSP 2.1 TCK pass with the exception of the Servlet version number checks. Added: tomcat/trunk/java/org/apache/catalina/deploy/JspPropertyGroup.java (with props) tomcat/trunk/java/org/apache/catalina/deploy/ServletDef.java (with props) tomcat/trunk/java/org/apache/catalina/startup/WebXml.java - copied, changed from r815972, tomcat/trunk/java/org/apache/catalina/startup/WebXmlCommon.java Removed: tomcat/trunk/java/org/apache/catalina/startup/WebXmlCommon.java tomcat/trunk/java/org/apache/catalina/startup/WebXmlFragment.java Modified: tomcat/trunk/java/org/apache/catalina/startup/ContextConfig.java tomcat/trunk/java/org/apache/catalina/startup/LocalStrings.properties tomcat/trunk/java/org/apache/catalina/startup/LocalStrings_es.properties tomcat/trunk/java/org/apache/catalina/startup/LocalStrings_fr.properties tomcat/trunk/java/org/apache/catalina/startup/LocalStrings_ja.properties tomcat/trunk/java/org/apache/catalina/startup/WebRuleSet.java Added: tomcat/trunk/java/org/apache/catalina/deploy/JspPropertyGroup.java URL: http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/catalina/deploy/JspPropertyGroup.java?rev=816951&view=auto ============================================================================== --- tomcat/trunk/java/org/apache/catalina/deploy/JspPropertyGroup.java (added) +++ tomcat/trunk/java/org/apache/catalina/deploy/JspPropertyGroup.java Sat Sep 19 20:13:22 2009 @@ -0,0 +1,84 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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 org.apache.catalina.deploy; + +import java.util.LinkedHashSet; +import java.util.Set; + +/** + * Representation of a jsp-property-group element in web.xml. + */ +public class JspPropertyGroup { + private Boolean deferredSyntax = null; + public void setDeferredSyntax(String deferredSyntax) { + this.deferredSyntax = Boolean.valueOf(deferredSyntax); + } + public Boolean getDeferredSyntax() { return deferredSyntax; } + + private Boolean elIgnored = null; + public void setElIgnored(String elIgnored) { + this.elIgnored = Boolean.valueOf(elIgnored); + } + public Boolean getElIgnored() { return elIgnored; } + + private Set includeCodas = new LinkedHashSet(); + public void addIncludeCoda(String includeCoda) { + includeCodas.add(includeCoda); + } + public Set getIncludeCodas() { return includeCodas; } + + private Set includePreludes = new LinkedHashSet(); + public void addIncludePrelude(String includePrelude) { + includePreludes.add(includePrelude); + } + public Set getIncludePreludes() { return includePreludes; } + + private Boolean isXml = null; + public void setIsXml(String isXml) { + this.isXml = Boolean.valueOf(isXml); + } + public Boolean getIsXml() { return isXml; } + + private String pageEncoding = null; + public void setPageEncoding(String pageEncoding) { + this.pageEncoding = pageEncoding; + } + public String getPageEncoding() { return this.pageEncoding; } + + private Boolean scriptingInvalid = null; + public void setScriptingInvalid(String scriptingInvalid) { + this.scriptingInvalid = Boolean.valueOf(scriptingInvalid); + } + public Boolean getScriptingInvalid() { return scriptingInvalid; } + + private Boolean trimWhitespace = null; + public void setTrimWhitespace(String trimWhitespace) { + this.trimWhitespace = Boolean.valueOf(trimWhitespace); + } + public Boolean getTrimWhitespace() { return trimWhitespace; } + + private String urlPattern = null; + public void setUrlPattern(String urlPattern) { + this.urlPattern = urlPattern; + } + public String getUrlPattern() { return this.urlPattern; } + +} Propchange: tomcat/trunk/java/org/apache/catalina/deploy/JspPropertyGroup.java ------------------------------------------------------------------------------ svn:eol-style = native Propchange: tomcat/trunk/java/org/apache/catalina/deploy/JspPropertyGroup.java ------------------------------------------------------------------------------ svn:keywords = Date Author Id Revision Added: tomcat/trunk/java/org/apache/catalina/deploy/ServletDef.java URL: http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/catalina/deploy/ServletDef.java?rev=816951&view=auto ============================================================================== --- tomcat/trunk/java/org/apache/catalina/deploy/ServletDef.java (added) +++ tomcat/trunk/java/org/apache/catalina/deploy/ServletDef.java Sat Sep 19 20:13:22 2009 @@ -0,0 +1,209 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You 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 org.apache.catalina.deploy; + + +import java.util.HashMap; +import java.util.HashSet; +import java.util.Map; +import java.util.Set; +import java.io.Serializable; + + +/** + * Representation of a servlet definition for a web application, as represented + * in a <servlet> element in the deployment descriptor. + */ + +public class ServletDef implements Serializable { + + + // ------------------------------------------------------------- Properties + + + /** + * The description of this servlet. + */ + private String description = null; + + public String getDescription() { + return (this.description); + } + + public void setDescription(String description) { + this.description = description; + } + + + /** + * The display name of this servlet. + */ + private String displayName = null; + + public String getDisplayName() { + return (this.displayName); + } + + public void setDisplayName(String displayName) { + this.displayName = displayName; + } + + + /** + * The small icon associated with this servlet. + */ + private String smallIcon = null; + + public String getSmallIcon() { + return (this.smallIcon); + } + + public void setSmallIcon(String smallIcon) { + this.smallIcon = smallIcon; + } + + /** + * The large icon associated with this servlet. + */ + private String largeIcon = null; + + public String getLargeIcon() { + return (this.largeIcon); + } + + public void setLargeIcon(String largeIcon) { + this.largeIcon = largeIcon; + } + + + /** + * The name of this servlet, which must be unique among the servlets + * defined for a particular web application. + */ + private String servletName = null; + + public String getServletName() { + return (this.servletName); + } + + public void setServletName(String servletName) { + this.servletName = servletName; + } + + + /** + * The fully qualified name of the Java class that implements this servlet. + */ + private String servletClass = null; + + public String getServletClass() { + return (this.servletClass); + } + + public void setServletClass(String servletClass) { + this.servletClass = servletClass; + } + + + /** + * The name of the JSP file to which this servlet definition applies + */ + private String jspFile = null; + + public String getJspFile() { + return (this.jspFile); + } + + public void setJspFile(String jspFile) { + this.jspFile = jspFile; + } + + + /** + * The set of initialization parameters for this servlet, keyed by + * parameter name. + */ + private Map parameters = new HashMap(); + + public Map getParameterMap() { + + return (this.parameters); + + } + + /** + * Add an initialization parameter to the set of parameters associated + * with this servlet. + * + * @param name The initialisation parameter name + * @param value The initialisation parameter value + */ + public void addInitParameter(String name, String value) { + + parameters.put(name, value); + + } + + /** + * The load-on-startup order for this servlet + */ + private Integer loadOnStartup = null; + + public Integer getLoadOnStartup() { + return (this.loadOnStartup); + } + + public void setLoadOnStartup(String loadOnStartup) { + this.loadOnStartup = Integer.valueOf(loadOnStartup); + } + + + /** + * The run-as configuration for this servlet + */ + private String runAs = null; + + public String getRunAs() { + return (this.runAs); + } + + public void setRunAs(String runAs) { + this.runAs = runAs; + } + + + /** + * The set of security role references for this servlet + */ + private Set securityRoleRefs = + new HashSet(); + + public Set getSecurityRoleRefs() { + return (this.securityRoleRefs); + } + + /** + * Add a security-role-ref to the set of security-role-refs associated + * with this servlet. + */ + public void addSecurityRoleRef(SecurityRoleRef securityRoleRef) { + securityRoleRefs.add(securityRoleRef); + } + +} Propchange: tomcat/trunk/java/org/apache/catalina/deploy/ServletDef.java ------------------------------------------------------------------------------ svn:eol-style = native Propchange: tomcat/trunk/java/org/apache/catalina/deploy/ServletDef.java ------------------------------------------------------------------------------ svn:keywords = Date Author Id Revision 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=816951&r1=816950&r2=816951&view=diff ============================================================================== --- tomcat/trunk/java/org/apache/catalina/startup/ContextConfig.java (original) +++ tomcat/trunk/java/org/apache/catalina/startup/ContextConfig.java Sat Sep 19 20:13:22 2009 @@ -24,7 +24,9 @@ import java.io.FileNotFoundException; import java.io.IOException; import java.io.InputStream; +import java.net.MalformedURLException; import java.net.URL; +import java.util.HashMap; import java.util.Map; import java.util.Properties; @@ -294,100 +296,6 @@ /** - * Process the application configuration file, if it exists. - */ - protected void applicationWebConfig() { - - String altDDName = null; - - // Open the application web.xml file, if it exists - InputStream stream = null; - ServletContext servletContext = context.getServletContext(); - if (servletContext != null) { - altDDName = (String)servletContext.getAttribute( - Globals.ALT_DD_ATTR); - if (altDDName != null) { - try { - stream = new FileInputStream(altDDName); - } catch (FileNotFoundException e) { - log.error(sm.getString("contextConfig.altDDNotFound", - altDDName)); - } - } - else { - stream = servletContext.getResourceAsStream - (Constants.ApplicationWebXml); - } - } - if (stream == null) { - if (log.isDebugEnabled()) { - log.debug(sm.getString("contextConfig.applicationMissing") + " " + context); - } - return; - } - - long t1=System.currentTimeMillis(); - - URL url=null; - // Process the application web.xml file - synchronized (webDigester) { - try { - if (altDDName != null) { - url = new File(altDDName).toURI().toURL(); - } else { - url = servletContext.getResource( - Constants.ApplicationWebXml); - } - if( url!=null ) { - InputSource is = new InputSource(url.toExternalForm()); - is.setByteStream(stream); - if (context instanceof StandardContext) { - ((StandardContext) context).setReplaceWelcomeFiles(true); - } - webDigester.push(context); - ContextErrorHandler errorHandler = new ContextErrorHandler(); - webDigester.setErrorHandler(errorHandler); - - if(log.isDebugEnabled()) { - log.debug("Parsing application web.xml file at " + url.toExternalForm()); - } - - webDigester.parse(is); - - if (errorHandler.getParseException() != null) { - ok = false; - } - } else { - log.info("No web.xml, using defaults " + context ); - } - } catch (SAXParseException e) { - log.error(sm.getString("contextConfig.applicationParse", url.toExternalForm()), e); - log.error(sm.getString("contextConfig.applicationPosition", - "" + e.getLineNumber(), - "" + e.getColumnNumber())); - ok = false; - } catch (Exception e) { - log.error(sm.getString("contextConfig.applicationParse", url.toExternalForm()), e); - ok = false; - } finally { - webDigester.reset(); - try { - stream.close(); - } catch (IOException e) { - log.error(sm.getString("contextConfig.applicationClose"), e); - } - } - } - webRuleSet.recycle(); - - long t2=System.currentTimeMillis(); - if (context instanceof StandardContext) { - ((StandardContext) context).setStartupTime(t2-t1); - } - } - - - /** * Set up an Authenticator automatically if required, and one has not * already been configured. */ @@ -560,157 +468,7 @@ return System.getProperty("catalina.base"); } - /** - * Process the default configuration file, if it exists. - * The default config must be read with the container loader - so - * container servlets can be loaded - */ - protected void defaultWebConfig() { - long t1=System.currentTimeMillis(); - - // Open the default web.xml file, if it exists - if( defaultWebXml==null && context instanceof StandardContext ) { - defaultWebXml=((StandardContext)context).getDefaultWebXml(); - } - // set the default if we don't have any overrides - if( defaultWebXml==null ) getDefaultWebXml(); - - File file = new File(this.defaultWebXml); - if (!file.isAbsolute()) { - file = new File(getBaseDir(), - this.defaultWebXml); - } - - InputStream stream = null; - InputSource source = null; - - try { - if ( ! file.exists() ) { - // Use getResource and getResourceAsStream - stream = getClass().getClassLoader() - .getResourceAsStream(defaultWebXml); - if( stream != null ) { - source = new InputSource - (getClass().getClassLoader() - .getResource(defaultWebXml).toString()); - } - if( stream== null ) { - // maybe embedded - stream = getClass().getClassLoader() - .getResourceAsStream("web-embed.xml"); - if( stream != null ) { - source = new InputSource - (getClass().getClassLoader() - .getResource("web-embed.xml").toString()); - } - } - - if( stream== null ) { - log.info("No default web.xml"); - } - } else { - source = - new InputSource("file://" + file.getAbsolutePath()); - stream = new FileInputStream(file); - context.addWatchedResource(file.getAbsolutePath()); - } - } catch (Exception e) { - log.error(sm.getString("contextConfig.defaultMissing") - + " " + defaultWebXml + " " + file , e); - } - - if (stream != null) { - processDefaultWebConfig(webDigester, stream, source); - webRuleSet.recycle(); - } - - long t2=System.currentTimeMillis(); - if( (t2-t1) > 200 ) - log.debug("Processed default web.xml " + file + " " + ( t2-t1)); - - stream = null; - source = null; - - String resourceName = getHostConfigPath(Constants.HostWebXml); - file = new File(getConfigBase(), resourceName); - - try { - if ( ! file.exists() ) { - // Use getResource and getResourceAsStream - stream = getClass().getClassLoader() - .getResourceAsStream(resourceName); - if( stream != null ) { - source = new InputSource - (getClass().getClassLoader() - .getResource(resourceName).toString()); - } - } else { - source = - new InputSource("file://" + file.getAbsolutePath()); - stream = new FileInputStream(file); - } - } catch (Exception e) { - log.error(sm.getString("contextConfig.defaultMissing") - + " " + resourceName + " " + file , e); - } - - if (stream != null) { - processDefaultWebConfig(webDigester, stream, source); - webRuleSet.recycle(); - } - - } - - - /** - * Process a default web.xml. - */ - protected void processDefaultWebConfig(Digester digester, InputStream stream, - InputSource source) { - - if (log.isDebugEnabled()) - log.debug("Processing context [" + context.getName() - + "] web configuration resource " + source.getSystemId()); - - // Process the default web.xml file - synchronized (digester) { - try { - source.setByteStream(stream); - - if (context instanceof StandardContext) - ((StandardContext) context).setReplaceWelcomeFiles(true); - digester.setClassLoader(this.getClass().getClassLoader()); - digester.setUseContextClassLoader(false); - digester.push(context); - ContextErrorHandler errorHandler = new ContextErrorHandler(); - digester.setErrorHandler(errorHandler); - digester.parse(source); - if (errorHandler.getParseException() != null) { - ok = false; - } - } catch (SAXParseException e) { - log.error(sm.getString("contextConfig.defaultParse"), e); - log.error(sm.getString("contextConfig.defaultPosition", - "" + e.getLineNumber(), - "" + e.getColumnNumber())); - ok = false; - } catch (Exception e) { - log.error(sm.getString("contextConfig.defaultParse"), e); - ok = false; - } finally { - digester.reset(); - try { - if (stream != null) { - stream.close(); - } - } catch (IOException e) { - log.error(sm.getString("contextConfig.defaultClose"), e); - } - } - } - } - - + /** * Process the default configuration file, if it exists. */ @@ -1060,8 +818,8 @@ } webDigester = createWebXmlDigester(useXmlNamespaceAware, useXmlValidation); - defaultWebConfig(); - applicationWebConfig(); + webConfig(); + if (!context.getIgnoreAnnotations()) { applicationAnnotationsConfig(); } @@ -1360,6 +1118,272 @@ } + /** + * Scan the web.xml files that apply to the web application and merge them + * using the rules defined in the spec. For the global web.xml files, + * where there is duplicate configuration, the most specific level wins. ie + * an application's web.xml takes precedence over the host level or global + * web.xml file. + */ + protected void webConfig() { + WebXml webXml = new WebXml(); + // Parse global web.xml if present + InputSource globalWebXml = getGlobalWebXmlSource(); + if (globalWebXml == null) { + // This is unusual enough to log + log.info(sm.getString("contextConfig.defaultMissing")); + } else { + parseWebXml(globalWebXml, webXml); + } + + // Parse host level web.xml if present + // Additive apart from welcome pages + webXml.setReplaceWelcomeFiles(true); + InputSource hostWebXml = getHostWebXmlSource(); + parseWebXml(hostWebXml, webXml); + + // Parse context level web.xml + webXml.setReplaceWelcomeFiles(true); + InputSource contextWebXml = getContextWebXmlSource(); + parseWebXml(contextWebXml, webXml); + + if (!webXml.isMetadataComplete()) { + // Have to process JARs for fragments + Map fragments = processJarsForWebFragments(); + + // Merge the fragments into the main web.xml + mergeWebFragments(webXml, fragments); + + // Apply merged web.xml to Context + webXml.configureContext(context); + + // Process JARs for annotations + processAnnotationsInJars(fragments); + + // Process /WEB-INF/classes for annotations + // TODO SERVLET3 + } else { + // Apply merged web.xml to Context + webXml.configureContext(context); + } + } + + + /** + * Identify the default web.xml to be used and obtain an input source for + * it. + */ + protected InputSource getGlobalWebXmlSource() { + // Is a default web.xml specified for the Context? + if (defaultWebXml == null && context instanceof StandardContext) { + defaultWebXml = ((StandardContext) context).getDefaultWebXml(); + } + // Set the default if we don't have any overrides + if (defaultWebXml == null) getDefaultWebXml(); + + return getWebXmlSource(defaultWebXml, getBaseDir()); + } + + /** + * Identify the host web.xml to be used and obtain an input source for + * it. + */ + protected InputSource getHostWebXmlSource() { + String resourceName = getHostConfigPath(Constants.HostWebXml); + + String basePath = null; + try { + basePath = getConfigBase().getCanonicalPath(); + } catch (IOException e) { + log.error(sm.getString("contectConfig.baseError"), e); + return null; + } + + return getWebXmlSource(resourceName, basePath); + } + + /** + * Identify the application web.xml to be used and obtain an input source + * for it. + */ + protected InputSource getContextWebXmlSource() { + InputStream stream = null; + InputSource source = null; + URL url = null; + + String altDDName = null; + + // Open the application web.xml file, if it exists + ServletContext servletContext = context.getServletContext(); + if (servletContext != null) { + altDDName = (String)servletContext.getAttribute( + Globals.ALT_DD_ATTR); + if (altDDName != null) { + try { + stream = new FileInputStream(altDDName); + url = new File(altDDName).toURI().toURL(); + } catch (FileNotFoundException e) { + log.error(sm.getString("contextConfig.altDDNotFound", + altDDName)); + } catch (MalformedURLException e) { + log.error(sm.getString("contextConfig.applicationUrl")); + } + } + else { + stream = servletContext.getResourceAsStream + (Constants.ApplicationWebXml); + try { + url = servletContext.getResource( + Constants.ApplicationWebXml); + } catch (MalformedURLException e) { + log.error(sm.getString("contextConfig.applicationUrl")); + } + } + } + if (stream == null || url == null) { + if (log.isDebugEnabled()) { + log.debug(sm.getString("contextConfig.applicationMissing") + " " + context); + } + } else { + source = new InputSource(url.toExternalForm()); + source.setByteStream(stream); + } + + return source; + } + + /** + * + * @param filename Name of the file (possibly with one or more leading path + * segemnts) to read + * @param path Location that filename is relative to + * @return + */ + protected InputSource getWebXmlSource(String filename, String path) { + File file = new File(filename); + if (!file.isAbsolute()) { + file = new File(path, filename); + } + + InputStream stream = null; + InputSource source = null; + + try { + if (!file.exists()) { + // Use getResource and getResourceAsStream + stream = + getClass().getClassLoader().getResourceAsStream(filename); + if(stream != null) { + source = + new InputSource(getClass().getClassLoader().getResource( + filename).toString()); + } + } else { + source = new InputSource("file://" + file.getAbsolutePath()); + stream = new FileInputStream(file); + context.addWatchedResource(file.getAbsolutePath()); + } + + if (stream != null && source != null) { + source.setByteStream(stream); + } + } catch (Exception e) { + log.error(sm.getString( + "contextConfig.defaultError", filename, file), e); + } + + return source; + } + + + protected void parseWebXml(InputSource source, WebXml dest) { + + if (source == null) return; + + ContextErrorHandler handler = new ContextErrorHandler(); + + // Web digesters and rulesets are shared between contexts but are not + // thread safe. Whilst there should only be one thread at a time + // processing a config, play safe and sync. + synchronized(webDigester) { + + webDigester.push(dest); + webDigester.setErrorHandler(handler); + + if(log.isDebugEnabled()) { + log.debug(sm.getString("contextConfig.applicationStart", + source.getSystemId())); + } + + try { + webDigester.parse(source); + + if (handler.getParseException() != null) { + ok = false; + } + } catch (SAXParseException e) { + log.error(sm.getString("contextConfig.applicationParse", + source.getSystemId()), e); + log.error(sm.getString("contextConfig.applicationPosition", + "" + e.getLineNumber(), + "" + e.getColumnNumber())); + ok = false; + } catch (Exception e) { + log.error(sm.getString("contextConfig.applicationParse", + source.getSystemId()), e); + ok = false; + } finally { + webDigester.reset(); + webRuleSet.recycle(); + } + } + } + + + /** + * Scan /META-INF/lib for JARs and for each one found add it and any + * /META-INF/web-fragment.xml to the resulting Map. web-fragment.xml files + * will be parsed before being added to the map. Every JAR will be added and + * null will be used if no web-fragment.xml was found. Any JARs + * known not contain fragments will be skipped. + * + * @return A map of JAR name to processed web fragment (if any) + */ + protected Map processJarsForWebFragments() { + // TODO SERVLET3 + return new HashMap(); + } + + + /** + * Merges the web-fragment.xml and web.xml files as per the rules in the + * Servlet spec. + * + * @param application The application web.xml file + * @param fragments The map of JARs to web fragments + */ + protected void mergeWebFragments(WebXml application, + Map fragments) { + // TODO SERVLET3 + // Check order + + // Merge fragments in order - conflict == error + + // Merge fragment into application - conflict == application wins + } + + + protected void processAnnotationsInJars(Map fragments) { + for(String jar : fragments.keySet()) { + WebXml fragment = fragments.get(jar); + if (fragment == null || !fragment.isMetadataComplete()) { + // Scan jar for annotations + // TODO SERVLET3 + } + } + } + + protected static class ContextErrorHandler implements ErrorHandler { Modified: tomcat/trunk/java/org/apache/catalina/startup/LocalStrings.properties URL: http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/catalina/startup/LocalStrings.properties?rev=816951&r1=816950&r2=816951&view=diff ============================================================================== --- tomcat/trunk/java/org/apache/catalina/startup/LocalStrings.properties (original) +++ tomcat/trunk/java/org/apache/catalina/startup/LocalStrings.properties Sat Sep 19 20:13:22 2009 @@ -14,27 +14,25 @@ # limitations under the License. catalina.stopServer=No shutdown port configured. Shut down server through OS signal. Server not shut down. -contextConfig.applicationClose=Error closing application web.xml -contextConfig.applicationConfig=Configuration error in application web.xml -contextConfig.applicationListener=Exception creating listener of class {0} +contextConfig.altDDNotFound=alt-dd file {0} not found +contextConfig.applicationUrl=Unable to determine URL for application web.xml contextConfig.applicationMissing=Missing application web.xml, using defaults only contextConfig.applicationParse=Parse error in application web.xml file at {0} contextConfig.applicationPosition=Occurred at line {0} column {1} +contextConfig.applicationStart=Parsing application web.xml file at {0} contextConfig.authenticatorConfigured=Configured an authenticator for method {0} contextConfig.authenticatorInstantiate=Cannot instantiate an authenticator of class {0} contextConfig.authenticatorMissing=Cannot configure an authenticator for method {0} contextConfig.authenticatorResources=Cannot load authenticators mapping list +contectConfig.baseError=Unable to determine $CATALINA_BASE contextConfig.cce=Lifecycle event data object {0} is not a Context -contextConfig.certificatesConfig.added=Added certificates -> request attribute Valve -contextConfig.certificatesConfig.error=Exception adding CertificatesValve: contextConfig.contextClose=Error closing context.xml contextConfig.contextMissing=Missing context.xml: {0} contextConfig.contextParse=Parse error in context.xml for {0} -contextConfig.defaultClose=Error closing default web.xml -contextConfig.defaultConfig=Configuration error in default web.xml -contextConfig.defaultMissing=Missing default web.xml, using application web.xml only -contextConfig.defaultParse=Parse error in default web.xml +contextConfig.defaultError=Error processed default web.xml named {0} at {1} +contextConfig.defaultMissing=No global web.xml found contextConfig.defaultPosition=Occurred at line {0} column {1} +contextConfig.destroy=ContextConfig: Destroying contextConfig.fixDocBase=Exception fixing docBase for context [{0}] contextConfig.init=ContextConfig: Initializing contextConfig.missingRealm=No Realm has been configured to authenticate against @@ -43,13 +41,8 @@ contextConfig.role.runas=WARNING: Security role name {0} used in a without being defined in a contextConfig.start=ContextConfig: Processing START contextConfig.stop=ContextConfig: Processing STOP -contextConfig.tldEntryException=Exception processing TLD {0} in JAR at resource path {1} in context {2} -contextConfig.tldFileException=Exception processing TLD at resource path {0} in context {1} -contextConfig.tldJarException=Exception processing JAR at resource path {0} in context {1} -contextConfig.tldResourcePath=Invalid TLD resource path {0} -contextConfig.xmlSettings=Context [{0}] will parse web.xml and web-fragment.xml files with validation:{1} and namespaceAware:{2} contextConfig.unavailable=Marking this application unavailable due to previous error(s) -contextConfig.altDDNotFound=alt-dd file {0} not found +contextConfig.xmlSettings=Context [{0}] will parse web.xml and web-fragment.xml files with validation:{1} and namespaceAware:{2} embedded.alreadyStarted=Embedded service has already been started embedded.noEngines=No engines have been defined yet embedded.notmp=Cannot find specified temporary folder at {0} Modified: tomcat/trunk/java/org/apache/catalina/startup/LocalStrings_es.properties URL: http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/catalina/startup/LocalStrings_es.properties?rev=816951&r1=816950&r2=816951&view=diff ============================================================================== --- tomcat/trunk/java/org/apache/catalina/startup/LocalStrings_es.properties (original) +++ tomcat/trunk/java/org/apache/catalina/startup/LocalStrings_es.properties Sat Sep 19 20:13:22 2009 @@ -12,9 +12,7 @@ # 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. -contextConfig.applicationClose = Error durante el cierre del archivo web.xml de la aplicaci\u00F3n -contextConfig.applicationConfig = Error de configuraci\u00F3n en el archivo web.xml de la aplicaci\u00F3n -contextConfig.applicationListener = Excepci\u00F3n durante la creaci\u00F3n de la clase de escucha (listener) {0} +contextConfig.altDDNotFound = fichero alt-dd {0} no hallado contextConfig.applicationMissing = Falta el archivo web.xml de la aplicaci\u00F3n. Utilizando los par\u00E1metros por defecto contextConfig.applicationParse = Error de evaluaci\u00F3n (parse) en el archivo web.xml de la aplicaci\u00F3n a {0} contextConfig.applicationPosition = Se ha producido en la l\u00EDnea {0} columna {1} @@ -23,15 +21,9 @@ contextConfig.authenticatorMissing = Imposible de configurar un autentificador (authenticator) para el m\u00E9todo {0} contextConfig.authenticatorResources = Imposible de cargar la lista de correspondencia de autenticadores (authenticators) contextConfig.cce = El objeto de los datos de evento de ciclo de vida (Lifecycle event data object) {0} no es un Contexto -contextConfig.certificatesConfig.added = Adici\u00F3n de certificados -> requiere v\u00E1lvula de atributo (attribute Valve) -contextConfig.certificatesConfig.error = Excepci\u00F3n durante la adici\u00F3n de "CertificatesValve"\: contextConfig.contextClose = Error cerrando context.xml\: {0} contextConfig.contextMissing = Falta context.xml\: {0} contextConfig.contextParse = Error de an\u00E1lisis en context.xml\: {0} -contextConfig.defaultClose = Error durante el cierre del archivo web.xml por defecto -contextConfig.defaultConfig = Error de configuraci\u00F3n en el archivo web.xml por defecto -contextConfig.defaultMissing = Falta el archivo web.xml por defecto, utilizando s\u00F3lo el archivo web.xml de la aplicaci\u00F3n -contextConfig.defaultParse = Error de evaluaci\u00F3n (parse) en el arcivo web.xml por defecto contextConfig.defaultPosition = Se ha producido en la l\u00EDnea {0} columna {1} contextConfig.fixDocBase = Excepci\u00F3n arreglando docBase\: {0} contextConfig.init = ContextConfig\: Inicializando @@ -41,12 +33,7 @@ contextConfig.role.runas = ATENCI\u00D3N\: El nombre de papel de seguridad {0} es usado en un sin haber sido definido en contextConfig.start = "ContextConfig"\: Tratamiento del "START" contextConfig.stop = "ContextConfig"\: Tratamiento del "STOP" -contextConfig.tldEntryException = Excepci\u00F3n durante el tratamiento de la TLD {0} en el JAR indicado por la trayectoria de recurso {1} en contexto {2} -contextConfig.tldFileException = Excepci\u00F3n durante el tratamiento de la TLD indicada por la trayectoria de recurso {0} en contexto {1} -contextConfig.tldJarException = Excepci\u00F3n durante el tratamiento del JAR indicado por la trayectoria de recurso {0} en contexto {1} -contextConfig.tldResourcePath = Trayectoria de recurso TLD {0} inv\u00E1lida contextConfig.unavailable = Esta aplicaci\u00F3n est\u00E1 marcada como no disponible debido a los errores precedentes -contextConfig.altDDNotFound = fichero alt-dd {0} no hallado embedded.alreadyStarted = El servicio embebido (embedded service) ya ha sido arrancado embedded.noEngines = Alg\u00FAn motor (engine) no ha sido a\u00FAn definido embedded.notmp = No puedo hallar carpeta temporal especificada en {0} Modified: tomcat/trunk/java/org/apache/catalina/startup/LocalStrings_fr.properties URL: http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/catalina/startup/LocalStrings_fr.properties?rev=816951&r1=816950&r2=816951&view=diff ============================================================================== --- tomcat/trunk/java/org/apache/catalina/startup/LocalStrings_fr.properties (original) +++ tomcat/trunk/java/org/apache/catalina/startup/LocalStrings_fr.properties Sat Sep 19 20:13:22 2009 @@ -13,9 +13,6 @@ # See the License for the specific language governing permissions and # limitations under the License. -contextConfig.applicationClose=Erreur lors de la fermeture du fichier web.xml de l''application -contextConfig.applicationConfig=Erreur de configuration dans le fichier web.xml de l''application -contextConfig.applicationListener=Exception lors de la cr\u00e9ation de la classe d''\u00e9coute (listener) {0} contextConfig.applicationMissing=Le fichier web.xml de l''application est absent, utilisation des param\u00eatres par d\u00e9faut contextConfig.applicationParse=Erreur d''\u00e9valuation (parse) dans le fichier web.xml de l''application \u00e0 {0} contextConfig.applicationPosition=S''est produite \u00e0 la ligne {0} colonne {1} @@ -24,12 +21,6 @@ contextConfig.authenticatorMissing=Impossible de configurer un authentificateur (authenticator) pour la m\u00e9thode {0} contextConfig.authenticatorResources=Impossible de charger la liste de correspondance des authentificateur (authenticators) contextConfig.cce=L''objet donn\u00e9e \u00e9v\u00e8nement cycle de vie (Lifecycle event data object) {0} n''est pas un Contexte -contextConfig.certificatesConfig.added=Ajout de certificats -> requ\u00eate Attribut de Valve (attribute Valve) -contextConfig.certificatesConfig.error=Exception lors de l''ajout des "CertificatesValve": -contextConfig.defaultClose=Erreur lors de la fermeture du fichier web.xml par d\u00e9faut -contextConfig.defaultConfig=Erreur de configuration dans le fichier web.xml par d\u00e9faut -contextConfig.defaultMissing=Le fichier web.xml par d\u00e9faut est absent, utilisation du fichier web.xml de l''application web.xml seulement -contextConfig.defaultParse=Erreur d''\u00e9valuation (parse) dans le fichier web.xml par d\u00e9faut contextConfig.defaultPosition=S''est produite \u00e0 la ligne {0} colonne {1} contextConfig.missingRealm=Aucun royaume (realm) n''a \u00e9t\u00e9 configur\u00e9 pour r\u00e9aliser l''authentification contextConfig.role.auth=ATTENTION: Le nom de r\u00f4le de s\u00e9curit\u00e9 {0} est utilis\u00e9 dans un sans avoir \u00e9t\u00e9 d\u00e9fini dans @@ -37,10 +28,6 @@ contextConfig.role.runas=ATTENTION: Le nom de r\u00f4le de s\u00e9curit\u00e9 {0} est utilis\u00e9 dans un sans avoir \u00e9t\u00e9 d\u00e9fini dans contextConfig.start="ContextConfig": Traitement du "START" contextConfig.stop="ContextConfig": Traitement du "STOP" -contextConfig.tldEntryException=Exception lors du traitement de la TLD {0} dans le JAR indiqu\u00e9 par le chemin de ressource {1} dans le contexte {2} -contextConfig.tldFileException=Exception lors du traitement de la TLD indiqu\u00e9 par le chemin de ressource {0} dans le contexte {1} -contextConfig.tldJarException=Exception lors du traitement du JAR indiqu\u00e9 par le chemin de ressource {0} dans le contexte {1} -contextConfig.tldResourcePath=Chemin de ressource TLD {0} invalide contextConfig.unavailable=Cette application est marqu\u00e9e comme non disponible suite aux erreurs pr\u00e9c\u00e9dentes embedded.alreadyStarted=Le service enfoui (embedded service) a d\u00e9j\u00e0 \u00e9t\u00e9 d\u00e9marr\u00e9 embedded.noEngines=Aucun moteur (engine) n''a encore \u00e9t\u00e9 d\u00e9fini Modified: tomcat/trunk/java/org/apache/catalina/startup/LocalStrings_ja.properties URL: http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/catalina/startup/LocalStrings_ja.properties?rev=816951&r1=816950&r2=816951&view=diff ============================================================================== --- tomcat/trunk/java/org/apache/catalina/startup/LocalStrings_ja.properties (original) +++ tomcat/trunk/java/org/apache/catalina/startup/LocalStrings_ja.properties Sat Sep 19 20:13:22 2009 @@ -13,9 +13,6 @@ # See the License for the specific language governing permissions and # limitations under the License. -contextConfig.applicationClose=\u30a2\u30d7\u30ea\u30b1\u30fc\u30b7\u30e7\u30f3\u306eweb.xml\u3092\u30af\u30ed\u30fc\u30ba\u4e2d\u306e\u30a8\u30e9\u30fc\u3067\u3059 -contextConfig.applicationConfig=\u30a2\u30d7\u30ea\u30b1\u30fc\u30b7\u30e7\u30f3\u306eweb.xml\u306e\u8a2d\u5b9a\u30a8\u30e9\u30fc\u3067\u3059 -contextConfig.applicationListener=\u30af\u30e9\u30b9 {0} \u306e\u30ea\u30b9\u30ca\u3092\u4f5c\u6210\u4e2d\u306e\u4f8b\u5916\u3067\u3059 contextConfig.applicationMissing=\u30a2\u30d7\u30ea\u30b1\u30fc\u30b7\u30e7\u30f3\u306eweb.xml\u304c\u898b\u3064\u304b\u308a\u307e\u305b\u3093\u3001\u30c7\u30d5\u30a9\u30eb\u30c8\u3060\u3051\u3092\u4f7f\u7528\u3057\u307e\u3059 contextConfig.applicationParse=\u30a2\u30d7\u30ea\u30b1\u30fc\u30b7\u30e7\u30f3\u306eweb.xml\u30d5\u30a1\u30a4\u30eb {0} \u306e\u89e3\u6790\u30a8\u30e9\u30fc\u3067\u3059 contextConfig.applicationPosition={0}\u884c\u306e{1}\u5217\u76ee\u3067\u767a\u751f\u3057\u307e\u3057\u305f @@ -24,12 +21,6 @@ contextConfig.authenticatorMissing=\u30e1\u30bd\u30c3\u30c9 {0} \u306e\u30aa\u30fc\u30bb\u30f3\u30c6\u30a3\u30b1\u30fc\u30bf\u3092\u8a2d\u5b9a\u3067\u304d\u307e\u305b\u3093 contextConfig.authenticatorResources=\u30aa\u30fc\u30bb\u30f3\u30c6\u30a3\u30b1\u30fc\u30bf\u306e\u30de\u30c3\u30d7\u30ea\u30b9\u30c8\u3092\u30ed\u30fc\u30c9\u3067\u304d\u307e\u305b\u3093 contextConfig.cce=\u30e9\u30a4\u30d5\u30b5\u30a4\u30af\u30eb\u30a4\u30d9\u30f3\u30c8\u30c7\u30fc\u30bf\u30aa\u30d6\u30b8\u30a7\u30af\u30c8 {0} \u306f\u30b3\u30f3\u30c6\u30ad\u30b9\u30c8\u3067\u306f\u3042\u308a\u307e\u305b\u3093 -contextConfig.certificatesConfig.added=\u8a3c\u660e\u66f8\u3092\u30ea\u30af\u30a8\u30b9\u30c8\u306e\u5c5e\u6027\u5024\u306b\u8ffd\u52a0\u3057\u307e\u3059 -contextConfig.certificatesConfig.error=CertificatesValve\u3092\u8ffd\u52a0\u4e2d\u306b\u4f8b\u5916\u304c\u767a\u751f\u3057\u307e\u3057\u305f: -contextConfig.defaultClose=\u30c7\u30d5\u30a9\u30eb\u30c8\u306eweb.xml\u306e\u30af\u30ed\u30fc\u30ba\u4e2d\u306b\u30a8\u30e9\u30fc\u304c\u767a\u751f\u3057\u307e\u3057\u305f -contextConfig.defaultConfig=\u30c7\u30d5\u30a9\u30eb\u30c8\u306eweb.xml\u306e\u4e2d\u306e\u8a2d\u5b9a\u30a8\u30e9\u30fc\u3067\u3059 -contextConfig.defaultMissing=\u30c7\u30d5\u30a9\u30eb\u30c8\u306eweb.xml\u304c\u898b\u3064\u304b\u308a\u307e\u305b\u3093\u3001\u30a2\u30d7\u30ea\u30b1\u30fc\u30b7\u30e7\u30f3\u306eweb.xml\u3060\u3051\u3092\u4f7f\u7528\u3057\u307e\u3059 -contextConfig.defaultParse=\u30c7\u30d5\u30a9\u30eb\u30c8\u306eweb.xml\u4e2d\u306e\u89e3\u6790\u30a8\u30e9\u30fc\u3067\u3059 contextConfig.defaultPosition={0}\u884c\u306e{1}\u5217\u76ee\u3067\u767a\u751f\u3057\u307e\u3057\u305f contextConfig.missingRealm=\u8a8d\u8a3c\u3059\u308b\u305f\u3081\u306b\u30ec\u30eb\u30e0\u304c\u8a2d\u5b9a\u3055\u308c\u3066\u3044\u307e\u305b\u3093 contextConfig.role.auth=\u8b66\u544a: \u306b\u5b9a\u7fa9\u3055\u308c\u3066\u3044\u306a\u3044\u30bb\u30ad\u30e5\u30ea\u30c6\u30a3\u30ed\u30fc\u30eb\u540d {0} \u304c\u306e\u4e2d\u3067\u4f7f\u7528\u3055\u308c\u307e\u3057\u305f @@ -37,10 +28,6 @@ contextConfig.role.runas=\u8b66\u544a: \u306b\u5b9a\u7fa9\u3055\u308c\u3066\u3044\u306a\u3044\u30bb\u30ad\u30e5\u30ea\u30c6\u30a3\u30ed\u30fc\u30eb\u540d {0} \u304c\u306e\u4e2d\u3067\u4f7f\u7528\u3055\u308c\u307e\u3057\u305f contextConfig.start=ContextConfig: \u51e6\u7406\u3092\u958b\u59cb\u3057\u307e\u3059 contextConfig.stop=ContextConfig: \u51e6\u7406\u3092\u505c\u6b62\u3057\u307e\u3059 -contextConfig.tldEntryException=\u30b3\u30f3\u30c6\u30ad\u30b9\u30c8 {2} \u306e\u30ea\u30bd\u30fc\u30b9\u30d1\u30b9 {1} \u306eJAR\u30d5\u30a1\u30a4\u30eb\u306eTLD {0} \u3092\u51e6\u7406\u4e2d\u306e\u4f8b\u5916\u3067\u3059 -contextConfig.tldFileException=\u30b3\u30f3\u30c6\u30ad\u30b9\u30c8 {1} \u306e\u30ea\u30bd\u30fc\u30b9\u30d1\u30b9 {0} \u306eTLD\u3092\u51e6\u7406\u4e2d\u306e\u4f8b\u5916\u3067\u3059 -contextConfig.tldJarException=\u30b3\u30f3\u30c6\u30ad\u30b9\u30c8 {1} \u306e\u30ea\u30bd\u30fc\u30b9\u30d1\u30b9 {0} \u306eJAR\u30d5\u30a1\u30a4\u30eb\u3092\u51e6\u7406\u4e2d\u306e\u4f8b\u5916\u3067\u3059 -contextConfig.tldResourcePath=\u7121\u52b9\u306aTLD\u306e\u30ea\u30bd\u30fc\u30b9\u30d1\u30b9 {0} contextConfig.unavailable=\u524d\u306e\u30a8\u30e9\u30fc\u306e\u305f\u3081\u306b\u3053\u306e\u30a2\u30d7\u30ea\u30b1\u30fc\u30b7\u30e7\u30f3\u306f\u5229\u7528\u3067\u304d\u306a\u3044\u3088\u3046\u306b\u30de\u30fc\u30af\u3057\u307e\u3059 embedded.alreadyStarted=\u7d44\u307f\u8fbc\u307f\u30b5\u30fc\u30d3\u30b9\u306f\u65e2\u306b\u8d77\u52d5\u3055\u308c\u3066\u3044\u307e\u3059 embedded.noEngines=\u307e\u3060\u30a8\u30f3\u30b8\u30f3\u304c\u5b9a\u7fa9\u3055\u308c\u3066\u3044\u307e\u305b\u3093 Modified: tomcat/trunk/java/org/apache/catalina/startup/WebRuleSet.java URL: http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/catalina/startup/WebRuleSet.java?rev=816951&r1=816950&r2=816951&view=diff ============================================================================== --- tomcat/trunk/java/org/apache/catalina/startup/WebRuleSet.java (original) +++ tomcat/trunk/java/org/apache/catalina/startup/WebRuleSet.java Sat Sep 19 20:13:22 2009 @@ -22,11 +22,10 @@ import java.lang.reflect.Method; import java.util.ArrayList; -import org.apache.catalina.Context; -import org.apache.catalina.Wrapper; import org.apache.catalina.deploy.ContextHandler; import org.apache.catalina.deploy.ContextService; import org.apache.catalina.deploy.SecurityConstraint; +import org.apache.catalina.deploy.ServletDef; import org.apache.tomcat.util.IntrospectionUtils; import org.apache.tomcat.util.digester.CallMethodRule; import org.apache.tomcat.util.digester.CallParamRule; @@ -128,7 +127,7 @@ new IgnoreAnnotationsRule()); digester.addCallMethod(prefix + "web-app/context-param", - "addParameter", 2); + "addContextParam", 2); digester.addCallParam(prefix + "web-app/context-param/param-name", 0); digester.addCallParam(prefix + "web-app/context-param/param-value", 1); @@ -156,7 +155,7 @@ digester.addObjectCreate(prefix + "web-app/filter", "org.apache.catalina.deploy.FilterDef"); digester.addSetNext(prefix + "web-app/filter", - "addFilterDef", + "addFilter", "org.apache.catalina.deploy.FilterDef"); digester.addCallMethod(prefix + "web-app/filter/description", @@ -184,7 +183,7 @@ digester.addObjectCreate(prefix + "web-app/filter-mapping", "org.apache.catalina.deploy.FilterMap"); digester.addSetNext(prefix + "web-app/filter-mapping", - "addFilterMap", + "addFilterMapping", "org.apache.catalina.deploy.FilterMap"); digester.addCallMethod(prefix + "web-app/filter-mapping/filter-name", @@ -198,13 +197,34 @@ "setDispatcher", 0); digester.addCallMethod(prefix + "web-app/listener/listener-class", - "addApplicationListener", 0); + "addListener", 0); digester.addRule(prefix + "web-app/jsp-config", jspConfig); - + + digester.addObjectCreate(prefix + "web-app/jsp-config/jsp-property-group", + "org.apache.catalina.deploy.JspPropertyGroup"); + digester.addSetNext(prefix + "web-app/jsp-config/jsp-property-group", + "addJspPropertyGroup", + "org.apache.catalina.deploy.JspPropertyGroup"); + digester.addCallMethod(prefix + "web-app/jsp-config/jsp-property-group/deferred-syntax-allowed-as-literal", + "setDeferredSyntax", 0); + digester.addCallMethod(prefix + "web-app/jsp-config/jsp-property-group/el-ignored", + "setElIgnored", 0); + digester.addCallMethod(prefix + "web-app/jsp-config/jsp-property-group/include-coda", + "addIncludeCoda", 0); + digester.addCallMethod(prefix + "web-app/jsp-config/jsp-property-group/include-prelude", + "addIncludePrelude", 0); + digester.addCallMethod(prefix + "web-app/jsp-config/jsp-property-group/is-xml", + "setIsXml", 0); + digester.addCallMethod(prefix + "web-app/jsp-config/jsp-property-group/page-encoding", + "setPageEncoding", 0); + digester.addCallMethod(prefix + "web-app/jsp-config/jsp-property-group/scripting-invalid", + "setScriptingInvalid", 0); + digester.addCallMethod(prefix + "web-app/jsp-config/jsp-property-group/trim-directive-whitespaces", + "setTrimWhitespace", 0); digester.addCallMethod(prefix + "web-app/jsp-config/jsp-property-group/url-pattern", - "addJspMapping", 0); + "setUrlPattern", 0); digester.addRule(prefix + "web-app/login-config", loginConfig); @@ -233,7 +253,7 @@ digester.addObjectCreate(prefix + "web-app/security-constraint", "org.apache.catalina.deploy.SecurityConstraint"); digester.addSetNext(prefix + "web-app/security-constraint", - "addConstraint", + "addSecurityConstraint", "org.apache.catalina.deploy.SecurityConstraint"); digester.addRule(prefix + "web-app/security-constraint/auth-constraint", @@ -261,10 +281,10 @@ "addSecurityRole", 0); digester.addRule(prefix + "web-app/servlet", - new WrapperCreateRule()); + new ServletDefCreateRule()); digester.addSetNext(prefix + "web-app/servlet", - "addChild", - "org.apache.catalina.Container"); + "addServlet", + "org.apache.catalina.deploy.ServletDef"); digester.addCallMethod(prefix + "web-app/servlet/init-param", "addInitParameter", 2); @@ -276,19 +296,19 @@ digester.addCallMethod(prefix + "web-app/servlet/jsp-file", "setJspFile", 0); digester.addCallMethod(prefix + "web-app/servlet/load-on-startup", - "setLoadOnStartupString", 0); + "setLoadOnStartup", 0); digester.addCallMethod(prefix + "web-app/servlet/run-as/role-name", "setRunAs", 0); digester.addCallMethod(prefix + "web-app/servlet/security-role-ref", - "addSecurityReference", 2); + "addSecurityRoleRef", 2); digester.addCallParam(prefix + "web-app/servlet/security-role-ref/role-link", 1); digester.addCallParam(prefix + "web-app/servlet/security-role-ref/role-name", 0); digester.addCallMethod(prefix + "web-app/servlet/servlet-class", "setServletClass", 0); digester.addCallMethod(prefix + "web-app/servlet/servlet-name", - "setName", 0); + "setServletName", 0); digester.addRule(prefix + "web-app/servlet-mapping", new CallMethodMultiRule("addServletMapping", 2, 0)); @@ -321,7 +341,7 @@ "addWelcomeFile", 0); digester.addCallMethod(prefix + "web-app/locale-encoding-mapping-list/locale-encoding-mapping", - "addLocaleEncodingMappingParameter", 2); + "addLocaleEncodingMapping", 2); digester.addCallParam(prefix + "web-app/locale-encoding-mapping-list/locale-encoding-mapping/locale", 0); digester.addCallParam(prefix + "web-app/locale-encoding-mapping-list/locale-encoding-mapping/encoding", 1); @@ -331,10 +351,9 @@ //ejb-local-ref digester.addObjectCreate(prefix + "web-app/ejb-local-ref", "org.apache.catalina.deploy.ContextLocalEjb"); - digester.addRule(prefix + "web-app/ejb-local-ref", - new SetNextNamingRule("addLocalEjb", - "org.apache.catalina.deploy.ContextLocalEjb")); - + digester.addSetNext(prefix + "web-app/ejb-local-ref", + "addEjbLocalRef", + "org.apache.catalina.deploy.ContextLocalEjb"); digester.addCallMethod(prefix + "web-app/ejb-local-ref/description", "setDescription", 0); digester.addCallMethod(prefix + "web-app/ejb-local-ref/ejb-link", @@ -352,10 +371,9 @@ //ejb-ref digester.addObjectCreate(prefix + "web-app/ejb-ref", "org.apache.catalina.deploy.ContextEjb"); - digester.addRule(prefix + "web-app/ejb-ref", - new SetNextNamingRule("addEjb", - "org.apache.catalina.deploy.ContextEjb")); - + digester.addSetNext(prefix + "web-app/ejb-ref", + "addEjbRef", + "org.apache.catalina.deploy.ContextEjb"); digester.addCallMethod(prefix + "web-app/ejb-ref/description", "setDescription", 0); digester.addCallMethod(prefix + "web-app/ejb-ref/ejb-link", @@ -373,10 +391,9 @@ //env-entry digester.addObjectCreate(prefix + "web-app/env-entry", "org.apache.catalina.deploy.ContextEnvironment"); - digester.addRule(prefix + "web-app/env-entry", - new SetNextNamingRule("addEnvironment", - "org.apache.catalina.deploy.ContextEnvironment")); - + digester.addSetNext(prefix + "web-app/env-entry", + "addEnvEntry", + "org.apache.catalina.deploy.ContextEnvironment"); digester.addCallMethod(prefix + "web-app/env-entry/description", "setDescription", 0); digester.addCallMethod(prefix + "web-app/env-entry/env-entry-name", @@ -390,10 +407,9 @@ //resource-env-ref digester.addObjectCreate(prefix + "web-app/resource-env-ref", "org.apache.catalina.deploy.ContextResourceEnvRef"); - digester.addRule(prefix + "web-app/resource-env-ref", - new SetNextNamingRule("addResourceEnvRef", - "org.apache.catalina.deploy.ContextResourceEnvRef")); - + digester.addSetNext(prefix + "web-app/resource-env-ref", + "addResourceEnvRef", + "org.apache.catalina.deploy.ContextResourceEnvRef"); digester.addCallMethod(prefix + "web-app/resource-env-ref/resource-env-ref-name", "setName", 0); digester.addCallMethod(prefix + "web-app/resource-env-ref/resource-env-ref-type", @@ -406,7 +422,6 @@ digester.addSetNext(prefix + "web-app/message-destination", "addMessageDestination", "org.apache.catalina.deploy.MessageDestination"); - digester.addCallMethod(prefix + "web-app/message-destination/description", "setDescription", 0); digester.addCallMethod(prefix + "web-app/message-destination/display-name", @@ -424,7 +439,6 @@ digester.addSetNext(prefix + "web-app/message-destination-ref", "addMessageDestinationRef", "org.apache.catalina.deploy.MessageDestinationRef"); - digester.addCallMethod(prefix + "web-app/message-destination-ref/description", "setDescription", 0); digester.addCallMethod(prefix + "web-app/message-destination-ref/message-destination-link", @@ -441,10 +455,9 @@ //resource-ref digester.addObjectCreate(prefix + "web-app/resource-ref", "org.apache.catalina.deploy.ContextResource"); - digester.addRule(prefix + "web-app/resource-ref", - new SetNextNamingRule("addResource", - "org.apache.catalina.deploy.ContextResource")); - + digester.addSetNext(prefix + "web-app/resource-ref", + "addResourceRef", + "org.apache.catalina.deploy.ContextResource"); digester.addCallMethod(prefix + "web-app/resource-ref/description", "setDescription", 0); digester.addCallMethod(prefix + "web-app/resource-ref/res-auth", @@ -460,10 +473,9 @@ //service-ref digester.addObjectCreate(prefix + "web-app/service-ref", "org.apache.catalina.deploy.ContextService"); - digester.addRule(prefix + "web-app/service-ref", - new SetNextNamingRule("addService", - "org.apache.catalina.deploy.ContextService")); - + digester.addSetNext(prefix + "web-app/service-ref", + "addServiceRef", + "org.apache.catalina.deploy.ContextService"); digester.addCallMethod(prefix + "web-app/service-ref/description", "setDescription", 0); digester.addCallMethod(prefix + "web-app/service-ref/display-name", @@ -638,11 +650,11 @@ public void begin(String namespace, String name, Attributes attributes) throws Exception { - Context context = (Context) digester.peek(); - context.setDistributable(true); + WebXml webXml = (WebXml) digester.peek(); + webXml.setDistributable(true); if (digester.getLogger().isDebugEnabled()) { digester.getLogger().debug - (context.getClass().getName() + ".setDistributable( true)"); + (webXml.getClass().getName() + ".setDistributable(true)"); } } @@ -695,26 +707,24 @@ * create the object that is to be added to the stack. */ -final class WrapperCreateRule extends Rule { +final class ServletDefCreateRule extends Rule { - public WrapperCreateRule() { + public ServletDefCreateRule() { } public void begin(String namespace, String name, Attributes attributes) throws Exception { - Context context = - (Context) digester.peek(digester.getCount() - 1); - Wrapper wrapper = context.createWrapper(); - digester.push(wrapper); + ServletDef servletDef = new ServletDef(); + digester.push(servletDef); if (digester.getLogger().isDebugEnabled()) - digester.getLogger().debug("new " + wrapper.getClass().getName()); + digester.getLogger().debug("new " + servletDef.getClass().getName()); } public void end(String namespace, String name) throws Exception { - Wrapper wrapper = (Wrapper) digester.pop(); + ServletDef servletDef = (ServletDef) digester.pop(); if (digester.getLogger().isDebugEnabled()) - digester.getLogger().debug("pop " + wrapper.getClass().getName()); + digester.getLogger().debug("pop " + servletDef.getClass().getName()); } } @@ -857,15 +867,15 @@ public void begin(String namespace, String name, Attributes attributes) throws Exception { - Context context = (Context) digester.peek(digester.getCount() - 1); + WebXml webxml = (WebXml) digester.peek(digester.getCount() - 1); String value = attributes.getValue("metadata-complete"); if ("true".equals(value)) { - context.setIgnoreAnnotations(true); + webxml.setMetadataComplete(true); } if (digester.getLogger().isDebugEnabled()) { digester.getLogger().debug - (context.getClass().getName() + ".setIgnoreAnnotations( " + - context.getIgnoreAnnotations() + ")"); + (webxml.getClass().getName() + ".setMetadataComplete( " + + webxml.isMetadataComplete() + ")"); } } @@ -955,9 +965,9 @@ @Override public void begin(String namespace, String name, Attributes attributes) throws Exception { - Context context = (Context) digester.peek(digester.getCount() - 1); + WebXml webXml = (WebXml) digester.peek(digester.getCount() - 1); // If we have a public ID, this is not a 2.4 or later webapp - boolean havePublicId = (context.getPublicId() != null); + boolean havePublicId = (webXml.getPublicId() != null); // havePublicId and isServlet24OrLater should be mutually exclusive if (havePublicId == isServlet24OrLater) { throw new IllegalArgumentException( Copied: tomcat/trunk/java/org/apache/catalina/startup/WebXml.java (from r815972, tomcat/trunk/java/org/apache/catalina/startup/WebXmlCommon.java) URL: http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/catalina/startup/WebXml.java?p2=tomcat/trunk/java/org/apache/catalina/startup/WebXml.java&p1=tomcat/trunk/java/org/apache/catalina/startup/WebXmlCommon.java&r1=815972&r2=816951&rev=816951&view=diff ============================================================================== --- tomcat/trunk/java/org/apache/catalina/startup/WebXmlCommon.java (original) +++ tomcat/trunk/java/org/apache/catalina/startup/WebXml.java Sat Sep 19 20:13:22 2009 @@ -24,6 +24,7 @@ import java.util.Map; import java.util.Set; +import org.apache.catalina.Context; import org.apache.catalina.Wrapper; import org.apache.catalina.deploy.ContextEjb; import org.apache.catalina.deploy.ContextEnvironment; @@ -34,11 +35,13 @@ import org.apache.catalina.deploy.ErrorPage; import org.apache.catalina.deploy.FilterDef; import org.apache.catalina.deploy.FilterMap; +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.SecurityConstraint; -import org.apache.jasper.compiler.JspConfig; +import org.apache.catalina.deploy.SecurityRoleRef; +import org.apache.catalina.deploy.ServletDef; import org.apache.tomcat.util.res.StringManager; /** @@ -49,7 +52,7 @@ * This class checks for invalid duplicates (eg filter/servlet names) * StandardContext will check validity of values (eg URL formats etc) */ -public abstract class WebXmlCommon { +public class WebXml { protected static final String ORDER_OTHERS = "org.apache.catalina.order.others"; @@ -58,16 +61,58 @@ StringManager.getManager(Constants.Package); private static org.apache.juli.logging.Log log= - org.apache.juli.logging.LogFactory.getLog(WebXmlCommon.class); + org.apache.juli.logging.LogFactory.getLog(WebXml.class); + + // web.xml only elements + // Absolute Ordering + private Set absoluteOrdering = new LinkedHashSet(); + public void addAbsoluteOrdering(String name) { + absoluteOrdering.add(name); + } + public void addAbsoluteOrderingOthers() { + absoluteOrdering.add(ORDER_OTHERS); + } + + // web-fragment.xml only elements + // Relative ordering + private Set after = new LinkedHashSet(); + public void addAfterOrdering(String name) { + after.add(name); + } + public void addAfterOrderingOthers() { + if (before.contains(ORDER_OTHERS)) { + throw new IllegalArgumentException(sm.getString( + "webXmlFragment.multipleOther")); + } + after.add(ORDER_OTHERS); + } + private Set before = new LinkedHashSet(); + public void addBeforeOrdering(String name) { + before.add(name); + } + public void addBeforeOrderingOthers() { + if (after.contains(ORDER_OTHERS)) { + throw new IllegalArgumentException(sm.getString( + "webXmlFragment.multipleOther")); + } + before.add(ORDER_OTHERS); + } + + // Common elements and attributes // Required attribute of web-app element private String version = null; public String getVersion() { return version; } public void setVersion(String version) { this.version = version; } + // Optional publicId attribute + private String publicId = null; + public String getPublicId() { return publicId; } + public void setPublicId(String publicId) { this.publicId = publicId; } + // Optional metadata-complete attribute private boolean metadataComplete = false; - public boolean getMetadataComplete() { return metadataComplete; } + public boolean isMetadataComplete() { return metadataComplete; } public void setMetadataComplete(boolean metadataComplete) { this.metadataComplete = metadataComplete; } @@ -97,7 +142,7 @@ // distributable private boolean distributable = false; - public boolean getDistributable() { return distributable; } + public boolean isDistributable() { return distributable; } public void setDistributable(boolean distributable) { this.distributable = distributable; } @@ -127,11 +172,11 @@ public Map getFilters() { return filters; } // filter-mapping - private Map filterMaps = new HashMap(); + private Set filterMaps = new HashSet(); public void addFilterMapping(FilterMap filterMap) { - filterMaps.put(filterMap.getFilterName(), filterMap); + filterMaps.add(filterMap); } - public Map getFilterMappings() { return filterMaps; } + public Set getFilterMappings() { return filterMaps; } // listener // TODO: description (multiple with language) is ignored @@ -149,16 +194,16 @@ // TODO: icon (multiple) is ignored // TODO: init-param/description (multiple with language) is ignored // TODO: security-role-ref/description (multiple with language) is ignored - private Map servlets = new HashMap(); - public void addServlet(Wrapper wrapper) { - servlets.put(wrapper.getName(), wrapper); + private Map servlets = new HashMap(); + public void addServlet(ServletDef servletDef) { + servlets.put(servletDef.getServletName(), servletDef); } - public Map getServlets() { return servlets; } + public Map getServlets() { return servlets; } // servlet-mapping private Map servletMappings = new HashMap(); - public void addServletMapping(String servletName, String urlPattern) { - servletMappings.put(servletName, urlPattern); + public void addServletMapping(String urlPattern, String servletName) { + servletMappings.put(urlPattern, servletName); } public Map getServletMappings() { return servletMappings; } @@ -178,8 +223,18 @@ public Map getMimeMappings() { return mimeMappings; } // welcome-file-list + // When merging web.xml files it may be necessary for any new welcome files + // to completely replace the current set + private boolean replaceWelcomeFiles = false; + public void setReplaceWelcomeFiles(boolean replaceWelcomeFiles) { + this.replaceWelcomeFiles = replaceWelcomeFiles; + } private Set welcomeFiles = new LinkedHashSet(); public void addWelcomeFile(String welcomeFile) { + if (replaceWelcomeFiles) { + welcomeFiles.clear(); + replaceWelcomeFiles = false; + } welcomeFiles.add(welcomeFile); } @@ -199,12 +254,12 @@ public Map getTaglibs() { return taglibs; } // jsp-config/jsp-property-group - private Set jspPropertyGroups = - new HashSet(); - public void addJspPropertyGroup(JspConfig.JspPropertyGroup propertyGroup) { + private Set jspPropertyGroups = + new HashSet(); + public void addJspPropertyGroup(JspPropertyGroup propertyGroup) { jspPropertyGroups.add(propertyGroup); } - public Set getJspPropertyGroups() { + public Set getJspPropertyGroups() { return jspPropertyGroups; } @@ -357,4 +412,125 @@ public Map getLocalEncodingMappings() { return localeEncodingMappings; } + + /** + * Configure a {@link Context} using the stored web.xml representation. + * + * @param context The context to be configured + */ + public void configureContext(Context context) { + // As far as possible, process in alphabetical order so it is easy to + // check everything is present + // Some validation depends on correct public ID + context.setPublicId(publicId); + + // Everything else in order + for (String contextParam : contextParams.keySet()) { + context.addParameter(contextParam, contextParams.get(contextParam)); + } + context.setDisplayName(displayName); + context.setDistributable(distributable); + for (ContextLocalEjb ejbLocalRef : ejbLocalRefs) { + context.getNamingResources().addLocalEjb(ejbLocalRef); + } + for (ContextEjb ejbRef : ejbRefs) { + context.getNamingResources().addEjb(ejbRef); + } + for (ContextEnvironment environment : envEntries.values()) { + context.getNamingResources().addEnvironment(environment); + } + for (ErrorPage errorPage : errorPages) { + context.addErrorPage(errorPage); + } + for (FilterDef filter : filters.values()) { + context.addFilterDef(filter); + } + for (FilterMap filterMap : filterMaps) { + context.addFilterMap(filterMap); + } + // jsp-property-group needs to be after servlet configuration + for (String listener : listeners) { + context.addApplicationListener(listener); + } + for (String locale : localeEncodingMappings.keySet()) { + context.addLocaleEncodingMappingParameter(locale, + localeEncodingMappings.get(locale)); + } + // Prevents IAE + if (loginConfig != null) { + context.setLoginConfig(loginConfig); + } + for (MessageDestinationRef mdr : messageDestinationRefs.values()) { + context.getNamingResources().addMessageDestinationRef(mdr); + } + + // messageDestinations were ignored in Tomcat 6, so ignore here + + // TODO SERVLET3 - This needs to be more fine-grained. Whether or not to + // process annotations on destroy() will depend on where + // the filter/servlet was loaded from. Joy. + context.setIgnoreAnnotations(metadataComplete); + for (String extension : mimeMappings.keySet()) { + context.addMimeMapping(extension, mimeMappings.get(extension)); + } + // Name is just used for ordering + for (ContextResourceEnvRef resource : resourceEnvRefs.values()) { + context.getNamingResources().addResourceEnvRef(resource); + } + for (ContextResource resource : resourceRefs.values()) { + context.getNamingResources().addResource(resource); + } + for (SecurityConstraint constraint : securityConstraints) { + context.addConstraint(constraint); + } + for (String role : securityRoles) { + context.addSecurityRole(role); + } + for (ContextService service : serviceRefs) { + context.getNamingResources().addService(service); + } + for (ServletDef servlet : servlets.values()) { + Wrapper wrapper = context.createWrapper(); + // Description is ignored + // Display name is ignored + // Icons are ignored + wrapper.setJspFile(servlet.getJspFile()); + if (servlet.getLoadOnStartup() != null) { + wrapper.setLoadOnStartup(servlet.getLoadOnStartup().intValue()); + } + wrapper.setName(servlet.getServletName()); + Map params = servlet.getParameterMap(); + for (String param : params.keySet()) { + wrapper.addInitParameter(param, params.get(param)); + } + wrapper.setRunAs(servlet.getRunAs()); + Set roleRefs = servlet.getSecurityRoleRefs(); + for (SecurityRoleRef roleRef : roleRefs) { + wrapper.addSecurityReference( + roleRef.getName(), roleRef.getLink()); + } + wrapper.setServletClass(servlet.getServletClass()); + context.addChild(wrapper); + } + for (String pattern : servletMappings.keySet()) { + context.addServletMapping(pattern, servletMappings.get(pattern)); + } + if (sessionTimeout != null) { + context.setSessionTimeout(sessionTimeout.intValue()); + } + for (String uri : taglibs.keySet()) { + context.addTaglib(uri, taglibs.get(uri)); + } + + // Context doesn't use version directly + + for (String welcomeFile : welcomeFiles) { + context.addWelcomeFile(welcomeFile); + } + + // Do this last as it depends on servlets + for (JspPropertyGroup jspPropertyGroup : jspPropertyGroups) { + context.addJspMapping(jspPropertyGroup.getUrlPattern()); + } + } } --------------------------------------------------------------------- To unsubscribe, e-mail: dev-unsubscribe@tomcat.apache.org For additional commands, e-mail: dev-help@tomcat.apache.org