the defaultConfig Method
defaultConfig方法读取和解析默认的web.xml文件,这个文件在CATALINA_HOME/conf目录下。其代码清单如15.13所示:
private void defaultConfig() {
// Open the default web.xml file, if it exists
File file = new File(Constants.DefaultWebXml);
if (!file.isAbsolute())
file = new File(System.getProperty("catalina.base"),Constants.DefaultWebXml);
FileInputStream stream = null;
try{
stream = new FileInputStream(file.getCanonicalPath());
stream.close();
stream = null;
}
catch (FileNotFoundException e) {
log(sm.getString("contextConfig.defaultMissing"));
return;
}
catch (IOException e) {
log(sm.getString("contextConfig.defaultMissing"), e);
return;
}
// Process the default web.xml file
synchronized (webDigester) {
try {
InputSource is =new InputSource("file://" + file.getAbsolutePath());
stream = new FileInputStream(file);
is.setByteStream(stream);
webDigester.setDebug(getDebug());
if (context instanceof StandardContext)
((StandardContext) context).setReplaceWelcomeFiles(true);
webDigester.clear();
webDigester.push(context);
webDigester.parse(is);
catch (SAXParseException e) {
log(sm.getString("contextConfig.defaultParse"), e);
log(sm.getString("contextConfig.defaultPosition","" + e.getLineNumber(), "" + e.getColumnNumber()));
ok = false;
}
catch (Exception e) {
log(sm.getString("contextConfig.defaultParse"), e);
ok = false;
}
finally {
try {
if (stream != null) {
stream.close();
}
}
catch (IOException e) {
log(sm.getString("contextConfig.defaultClose"), e);
}
}
}
}
defaultConfig方法首先创建一个与default.xml文件相关联的文件对象。
File file = new File(Constants.DefaultWebXml);
DefaultWebXML的值是在一个常量类中定义:
public static final String DefaultWebXml = "conf/web.xml";
defaultConfig方法稍后处理web.xml文件。其持有webDigester的内部锁,之后解析文件:
synchronized (webDigester) {
try {
InputSource is =
new InputSource("file://" + file.getAbsolutePath());
stream = new FileInputStream(file);
is.setByteStream(stream);
webDigester.setDebug(getDebug());
if (context instanceof StandardContext)
((StandardContext) context).setReplaceWelcomeFiles(true);
webDigester.clear();
webDigester.push(context);
webDigester.parse(is);
与Digester实例关联的webDigester对象已经设置了处理web.xml文件的规则。这会在稍后的章节中讲解。
the applicationConfig method
这个方法与defaultConfig方法相似,除了它处理的是应用部署描述符。部署描述符位于应用程序目录的WEB-INF目录下。
private void applicationConfig() {
// Open the application web.xml file, if it exists
InputStream stream = null;
ServletContext servletContext = context.getServletContext();
if (servletContext != null)
stream = servletContext.getResourceAsStream(Constants.ApplicationWebXml);
if (stream == null) {
log(sm.getString("contextConfig.applicationMissing"));
return;
}
// Process the application web.xml file
synchronized (webDigester) {
try {
URL url =
servletContext.getResource(Constants.ApplicationWebXml);
InputSource is = new InputSource(url.toExternalForm());
is.setByteStream(stream);
webDigester.setDebug(getDebug());
if (context instanceof StandardContext) {
((StandardContext) context).setReplaceWelcomeFiles(true);
}
webDigester.clear();
webDigester.push(context);
webDigester.parse(is);
}
catch (SAXParseException e) {
log(sm.getString("contextConfig.applicationParse"), e);
log(sm.getString("contextConfig.applicationPosition","" + e.getLineNumber(),"" + e.getColumnNumber()));
ok = false;
}
catch (Exception e) {
log(sm.getString("contextConfig.applicationParse"), e);
ok = false;
}
finally {
try {
if (stream != null){
stream.close();
}
}
catch (IOException e) {
log(sm.getString("contextConfig.applicationClose"),e);
}
}
}
}
create Web Digester
一个Digester对象引用,叫做webDigester,存在于ContextConfig类中:
private static Digester webDigester = createWebDigester();
Digester用于解析默认的web.xml和应用程序中的web.xml文件。当调用createWebDigester方式时,添加处理web.xml文件的规则。其代码清单如下:
private static Digester createWebDigester() {
URL url = null;
Digester webDigester = new Digester();
webDigester.setValidating(true);
url = ContextConfig.class.getResource(Constants.WebDtdResourcePath_22);
webDigester.register(Constants.WebDtdPublicId_22,url.toString());
url = ContextConfig.class.getResource(Constants.WebDtdResourcePath_23);
webDigester.register(Constants.WebDtdPublicId_23,url.toString());
url.toString());
webDigester.addRuleSet(new WebRuleSet());
return (webDigester);
}
注意 createWebDigester方法调用了webDigester的addRuleSet方法,来解析WebRuleSet的一个实例。WebRuleSet是RuleSetBase的一个子类。如果熟悉一个Servlet应用程序的部署描述符的语法并且阅读了这章开头的Digester部分,你应该能够理解其实如何工作的。
WebRuleSet的代码清单如下。注意为了节省空间,移除了addRuleInstance部分。
package org.apache.catalina.startup;
import java.lang.reflect.Method;
import org.apache.catalina.Context;
import org.apache.catalina.Wrapper;
import org.apache.catalina.deploy.SecurityConstraint;
import org.apache.commons.digester.Digester;
import org.apache.commons.digester.Rule;
import org.apache.commons.digester.RuleSetBase;
import org.xml.sax.Attributes;
public class WebRuleSet extends RuleSetBase {
protected String prefix = null;
public WebRuleSet () {
this("");
}
public WebRuleSet(String prefix) {
super();
this.namespaceURI = null;
this.prefix = prefix;
}
public void addRuleInstances(Digester digester) {
digester.addRule(prefix + "web-app",new SetPublicIdRule(digester, "setPublicId"));
digester.addCallMethod(prefix + "web-app/context-param","addParameter", 2);
digester.addCallParam(prefix +"web-app/context-param/param-name", 0);
digester.addCallParam(prefix +"web-app/context-param/param-value", 1);
digester.addCallMethod(prefix + "web-app/display-name","setDisplayName", 0);
digester.addRule(prefix + "web-app/distributable",new SetDistributableRule(digester));
...
digester.addObjectCreate(prefix + "web-app/filter","org.apache.catalina.deploy.FilterDef");
digester.addSetNext(prefix + "web-app/filter", "addFilterDef","org.apache.catalina.deploy.FilterDef");
digester.addCallMethod(prefix + "web-app/filter/description","setDescription", 0);
digester.addCallMethod(prefix + "web-app/filter/display-name", "setDisplayName", 0);
digester.addCallMethod(prefix + "web-app/filter/filter-class","setFilterClass", 0);
digester.addCallMethod(prefix + "web-app/filter/filter-name","setFilterName", 0);
digester.addCallMethod(prefix + "web-app/filter/large-icon","setLargeIcon", 0);
digester.addCallMethod(prefix + "web-app/filter/small-icon","setSmallIcon", 0);
digester.addCallMethod(prefix + "web-app/filter/init-param","addInitParameter", 2);
digester.addCallParam(prefix +"web-app/filter/init-param/param-name", 0);
digester.addCallParam(prefix +"web-app/filter/init-param/param-value", 1);
digester.addObjectCreate(prefix + "web-app/filter-mapping","org.apache.catalina.deploy.FilterMap");
digester.addSetNext(prefix + "web-app/filter-mapping","addFilterMap", "org.apache.catalina.deploy.FilterMap");
digester.addCallMethod(prefix +"web-app/filter-mapping/filter-name", "setFilterName", 0);
digester.addCallMethod(prefix +"web-app/filter-mapping/servlet-name", "setServletName", 0);
digester.addCallMethod(prefix +"web-app/filter-mapping/url-pattern", "setURLPattern", 0);
digester.addCallMethod (prefix +"web-app/listener/listener-class", "addApplicationListener", 0);
...
digester.addRule(prefix + "web-app/servlet",new WrapperCreateRule(digester));
digester.addSetNext(prefix + "web-app/servlet","addChild", "org.apache.catalina.Container");
digester.addCallMethod(prefix + "web-app/servlet/init-param","addInitParameter", 2);
digester.addCallParam(prefix +"web-app/servlet/init-param/param-name", 0);
digester.addCallParam(prefix +"web-app/servlet/init-param/param-value", 1);
digester.addCallMethod(prefix + "web-app/servlet/jsp-file","setJspFile", 0);
digester.addCallMethod(prefix +"web-app/servlet/load-on-startup", "setLoadOnStartupString", 0);
digester.addCallMethod(prefix +"web-app/servlet/run-as/role-name", "setRunAs", 0);
digester.addCallMethod(prefix +"web-app/servlet/security-role-ref", "addSecurityReference", 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","setServletdass", 0);
digester.addCallMethod(prefix + "web-app/servlet/servlet-name","setName", 0);
digester.addCallMethod(prefix + "web-app/servlet-mapping","addServletMapping", 2);
digester.addCallParam(prefix +"web-app/servlet-mapping/servlet-name"/ 1);
digester.addCallParam(prefix +"web-app/servlet-mapping/url-pattern", 0);
digester.addCallMethod (prefix +"web-app/session-config/session-timeout", "setSessionTimeout", 1,new Class[] { Integer.TYPE });
digester.addCallParam(prefix +"web-app/session-config/session-timeout", 0);
digester.addCallMethod(prefix + "web-app/taglib","addTaglib", 2);
digester.addCallParam(prefix + "web-app/taglib/taglib-location",1);
digester.addCallParam(prefix + "web-app/taglib/taglib-uri", 0);
digester.addCallMethod(prefix +"web-app/welcome-file-list/welcome-file", "addWelcomeFile", 0);
}
}
// --------------------------------------------- Private Classes
final class SetAuthConstraintRule extends Rule {
public SetAuthConstraintRule(Digester digester) {
super(digester);
}
public void begin(Attributes attributes) throws Exception {
SecurityConstraint securityConstraint = (SecurityConstraint) digester.peek();
securityConstraint.setAuthConstraint(true);
if (digester.getDebug() > 0)
digester.log("Calling
SecurityConstraint.setAuthConstraint(true)");
}
}
...
final class WrapperCreateRule extends Rule {
public WrapperCreateRule(Digester digester) {
super(digester);
}
public void begin(Attributes attributes) throws Exception {
Context context =(Context) digester.peek(digester.getCount() - 1);
Wrapper wrapper = context.createWrapper();
digester.push(wrapper);
if (digester.getDebug() > 0)
digester.log("new " + wrapper.getClass().getName());
}
public void end() throws Exception {
Wrapper wrapper = (Wrapper) digester.pop();
if (digester.getDebug() > 0)
digester.log("pop " + wrapper.getclass().getName());
}
}