412829 Allow any mappings from web-default.xml to be overridden by web.xml

This commit is contained in:
Jan Bartel 2013-07-23 12:18:18 +10:00
parent b8f7637e7d
commit ca37782229
2 changed files with 82 additions and 36 deletions

View File

@ -25,6 +25,7 @@ import java.util.Collection;
import java.util.Collections; import java.util.Collections;
import java.util.EnumSet; import java.util.EnumSet;
import java.util.HashMap; import java.util.HashMap;
import java.util.HashSet;
import java.util.List; import java.util.List;
import java.util.ListIterator; import java.util.ListIterator;
import java.util.Map; import java.util.Map;
@ -109,6 +110,7 @@ public class ServletHandler extends ScopedHandler
private ServletHolder[] _servlets=new ServletHolder[0]; private ServletHolder[] _servlets=new ServletHolder[0];
private ServletMapping[] _servletMappings; private ServletMapping[] _servletMappings;
private Map<String,ServletMapping> _servletPathMappings = new HashMap<String,ServletMapping>();
private final Map<String,FilterHolder> _filterNameMap= new HashMap<>(); private final Map<String,FilterHolder> _filterNameMap= new HashMap<>();
private List<FilterMapping> _filterPathMappings; private List<FilterMapping> _filterPathMappings;
@ -264,6 +266,7 @@ public class ServletHandler extends ScopedHandler
_filterPathMappings=null; _filterPathMappings=null;
_filterNameMappings=null; _filterNameMappings=null;
_servletPathMap=null; _servletPathMap=null;
_servletPathMappings=null;
} }
/* ------------------------------------------------------------ */ /* ------------------------------------------------------------ */
@ -329,31 +332,26 @@ public class ServletHandler extends ScopedHandler
return _servletMappings; return _servletMappings;
} }
/* ------------------------------------------------------------ */ /* ------------------------------------------------------------ */
/** /**
* @return Returns the servletMappings. * Get the ServletMapping matching the path
*
* @param pathSpec
* @return
*/ */
public ServletMapping getServletMapping(String pattern) public ServletMapping getServletMapping(String pathSpec)
{ {
ServletMapping theMapping = null; if (pathSpec == null || _servletPathMappings == null)
if (_servletMappings!=null) return null;
{
for (ServletMapping m:_servletMappings) return _servletPathMappings.get(pathSpec);
{
String[] paths=m.getPathSpecs();
if (paths!=null)
{
for (String path:paths)
{
if (pattern.equals(path))
theMapping = m;
}
}
}
}
return theMapping;
} }
/* ------------------------------------------------------------ */ /* ------------------------------------------------------------ */
/** Get Servlets. /** Get Servlets.
* @return Array of defined servlets * @return Array of defined servlets
@ -1319,27 +1317,75 @@ public class ServletHandler extends ScopedHandler
else else
{ {
PathMap<ServletHolder> pm = new PathMap<>(); PathMap<ServletHolder> pm = new PathMap<>();
Map<String,ServletMapping> servletPathMappings = new HashMap<String,ServletMapping>();
// update the maps //create a map of paths to set of ServletMappings that define that mapping
for (ServletMapping servletmapping : _servletMappings) HashMap<String, Set<ServletMapping>> sms = new HashMap<String, Set<ServletMapping>>();
for (ServletMapping servletMapping : _servletMappings)
{ {
ServletHolder servlet_holder = _servletNameMap.get(servletmapping.getServletName()); String[] pathSpecs = servletMapping.getPathSpecs();
if (servlet_holder == null) if (pathSpecs != null)
throw new IllegalStateException("No such servlet: " + servletmapping.getServletName());
else if (servlet_holder.isEnabled() && servletmapping.getPathSpecs() != null)
{ {
String[] pathSpecs = servletmapping.getPathSpecs();
for (String pathSpec : pathSpecs) for (String pathSpec : pathSpecs)
if (pathSpec != null)
{ {
ServletHolder previous = pm.put(pathSpec, servlet_holder); Set<ServletMapping> mappings = sms.get(pathSpec);
if (previous != null) if (mappings == null)
{
mappings = new HashSet<ServletMapping>();
sms.put(pathSpec, mappings);
}
mappings.add(servletMapping);
}
}
}
//evaluate path to servlet map based on servlet mappings
for (String pathSpec : sms.keySet())
{
//for each path, look at the mappings where it is referenced
//if a mapping is for a servlet that is not enabled, skip it
Set<ServletMapping> mappings = sms.get(pathSpec);
ServletMapping finalMapping = null;
for (ServletMapping mapping : mappings)
{
//Get servlet associated with the mapping and check it is enabled
ServletHolder servlet_holder = _servletNameMap.get(mapping.getServletName());
if (servlet_holder == null)
throw new IllegalStateException("No such servlet: " + mapping.getServletName());
//if the servlet related to the mapping is not enabled, skip it from consideration
if (!servlet_holder.isEnabled())
continue;
//only accept a default mapping if we don't have any other
if (finalMapping == null)
finalMapping = mapping;
else
{
//already have a candidate - only accept another one if the candidate is a default
if (finalMapping.isDefault())
finalMapping = mapping;
else
{
//existing candidate isn't a default, if the one we're looking at isn't a default either, then its an error
if (!mapping.isDefault())
throw new IllegalStateException("Multiple servlets map to path: "+pathSpec); throw new IllegalStateException("Multiple servlets map to path: "+pathSpec);
} }
} }
} }
if (finalMapping == null)
throw new IllegalStateException ("No acceptable servlet mappings for "+pathSpec);
if (LOG.isDebugEnabled()) LOG.debug("Chose path={} mapped to servlet={} from default={}", pathSpec, finalMapping.getServletName(), finalMapping.isDefault());
servletPathMappings.put(pathSpec, finalMapping);
pm.put(pathSpec,_servletNameMap.get(finalMapping.getServletName()));
}
_servletPathMap=pm; _servletPathMap=pm;
_servletPathMappings=servletPathMappings;
} }
// flush filter chain cache // flush filter chain cache

View File

@ -623,16 +623,15 @@ public class StandardDescriptorProcessor extends IterativeDescriptorProcessor
{ {
//no servlet mappings //no servlet mappings
context.getMetaData().setOrigin(servlet_name+".servlet.mappings", descriptor); context.getMetaData().setOrigin(servlet_name+".servlet.mappings", descriptor);
ServletMapping mapping = addServletMapping(servlet_name, node, context, descriptor); addServletMapping(servlet_name, node, context, descriptor);
mapping.setDefault(context.getMetaData().getOrigin(servlet_name+".servlet.mappings") == Origin.WebDefaults);
break; break;
} }
case WebXml:
case WebDefaults: case WebDefaults:
case WebXml:
case WebOverride: case WebOverride:
{ {
//previously set by a web xml descriptor, if we're parsing another web xml descriptor allow override //previously set by a web xml descriptor, if we're parsing another web xml descriptor allow override
//otherwise just ignore it //otherwise just ignore it as web.xml takes precedence (pg 8-81 5.g.vi)
if (!(descriptor instanceof FragmentDescriptor)) if (!(descriptor instanceof FragmentDescriptor))
{ {
addServletMapping(servlet_name, node, context, descriptor); addServletMapping(servlet_name, node, context, descriptor);
@ -1181,6 +1180,7 @@ public class StandardDescriptorProcessor extends IterativeDescriptorProcessor
{ {
ServletMapping mapping = new ServletMapping(); ServletMapping mapping = new ServletMapping();
mapping.setServletName(servletName); mapping.setServletName(servletName);
mapping.setDefault(descriptor instanceof DefaultsDescriptor);
List<String> paths = new ArrayList<String>(); List<String> paths = new ArrayList<String>();
Iterator<XmlParser.Node> iter = node.iterator("url-pattern"); Iterator<XmlParser.Node> iter = node.iterator("url-pattern");