Bug 63740

Summary: Host-specific xml files are not processed when xmlBase is not null
Product: Tomcat 9 Reporter: uk4sx
Component: CatalinaAssignee: Tomcat Developers Mailing List <dev>
Status: RESOLVED FIXED    
Severity: regression Keywords: PatchAvailable
Priority: P2    
Version: 9.0.24   
Target Milestone: -----   
Hardware: PC   
OS: All   
Attachments: proposed fix
additional fix (RewriteValve)

Description uk4sx 2019-09-09 11:54:25 UTC
Created attachment 36769 [details]
proposed fix

This is a Tomcat 9 - specific bug. Tested with Tomcat 9.0.24. Tomcat 8.5.43 works correctly. Earlier versions not tested.
 
When using a Host with xmlBase attribute the Host-specific context.xml.default and web.xml.default files are not processed at all (because they are not found).

Debugging the problem reveals that Tomcat searches for them in the wrong place:
always in ${catalina.base}/conf/${xmlBase} instead of ${xmlBase} (when xmlBase is absolute) or ${catalina.base}/${xmlBase} (when xmlBase is relative).

Examples:
for xmlBase="conf/cx" tomcat searches in "${catalina.base}/conf/conf/cx"
but should search in "${catalina.base}/conf/cx"

for xmlBase="H:/myhost" tomcat searches in "${catalina.base}/conf/H:/myhost"
but should search in "H:/myhost"

Workarounds: using symlinks (a nuisance at best) or using Tomcat 8.5.

Analysis: the documentation says that when xmlBase is not specified then "conf/<engine_name>/<host_name>" will be used as default. However, Container.getConfigPath() does not prepend "conf/" when xmlBase is null,
and to compensate for this error the (only) 2 callers use
ConfigFileLoader.getSource().getConfResource()
instead of the correct
ConfigFileLoader.getSource().getResource()
This becomes a problem when xmlBase is not null: getConfResouce() prepends "conf/".

Proposed fix (see attached patch):
- Container.getConfigPath(): prepend "conf/" when xmlBase is null
- ContextConfig.contextConfig() and ContextConfig.getWebXmlSource():
call ConfigFileLoader.getSource().getResource() when working with the result of Container.getConfigPath()

Proposed fix tested successfully in 3 scenarios:
- no xmlBase: OK
- relative xmlBase: OK
- absolute xmlBase: OK

How to easily test that the fix works:
- for context.xml.default: the log contains (example)
  "Successfully processed context [/my-ws] configuration file [file:/H:/myhost/context.xml.default]"
- for web.xml.default: declare a filter in it with a (unique) nonexistent className and expect to see a "ClassNotFoundException" with that className

Thanks for fixing this.
Comment 1 uk4sx 2019-09-09 14:56:26 UTC
Created attachment 36771 [details]
additional fix (RewriteValve)

Somehow I missed one callsite of Container.getConfigPath(): it is also used in RewriteValve. The proposed fix is the same: use getResource() instead of getConfResource(). Added patch #2.
Comment 2 Mark Thomas 2019-09-10 17:33:33 UTC
Thanks for the patch and the explanation.

Fixed in:
- master for 9.0.25 onwards