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.EnumSet;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.ListIterator;
import java.util.Map;
@ -109,6 +110,7 @@ public class ServletHandler extends ScopedHandler
private ServletHolder[] _servlets=new ServletHolder[0];
private ServletMapping[] _servletMappings;
private Map<String,ServletMapping> _servletPathMappings = new HashMap<String,ServletMapping>();
private final Map<String,FilterHolder> _filterNameMap= new HashMap<>();
private List<FilterMapping> _filterPathMappings;
@ -264,6 +266,7 @@ public class ServletHandler extends ScopedHandler
_filterPathMappings=null;
_filterNameMappings=null;
_servletPathMap=null;
_servletPathMappings=null;
}
/* ------------------------------------------------------------ */
@ -329,31 +332,26 @@ public class ServletHandler extends ScopedHandler
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 (_servletMappings!=null)
{
for (ServletMapping m:_servletMappings)
{
String[] paths=m.getPathSpecs();
if (paths!=null)
{
for (String path:paths)
{
if (pattern.equals(path))
theMapping = m;
}
}
}
}
return theMapping;
if (pathSpec == null || _servletPathMappings == null)
return null;
return _servletPathMappings.get(pathSpec);
}
/* ------------------------------------------------------------ */
/** Get Servlets.
* @return Array of defined servlets
@ -1319,27 +1317,75 @@ public class ServletHandler extends ScopedHandler
else
{
PathMap<ServletHolder> pm = new PathMap<>();
// update the maps
for (ServletMapping servletmapping : _servletMappings)
Map<String,ServletMapping> servletPathMappings = new HashMap<String,ServletMapping>();
//create a map of paths to set of ServletMappings that define that mapping
HashMap<String, Set<ServletMapping>> sms = new HashMap<String, Set<ServletMapping>>();
for (ServletMapping servletMapping : _servletMappings)
{
ServletHolder servlet_holder = _servletNameMap.get(servletmapping.getServletName());
if (servlet_holder == null)
throw new IllegalStateException("No such servlet: " + servletmapping.getServletName());
else if (servlet_holder.isEnabled() && servletmapping.getPathSpecs() != null)
String[] pathSpecs = servletMapping.getPathSpecs();
if (pathSpecs != null)
{
String[] pathSpecs = servletmapping.getPathSpecs();
for (String pathSpec : pathSpecs)
if (pathSpec != null)
{
Set<ServletMapping> mappings = sms.get(pathSpec);
if (mappings == null)
{
ServletHolder previous = pm.put(pathSpec, servlet_holder);
if (previous != null)
throw new IllegalStateException("Multiple servlets map to path: "+pathSpec);
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);
}
}
}
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;
_servletPathMappings=servletPathMappings;
}
// flush filter chain cache

View File

@ -623,16 +623,15 @@ public class StandardDescriptorProcessor extends IterativeDescriptorProcessor
{
//no servlet mappings
context.getMetaData().setOrigin(servlet_name+".servlet.mappings", descriptor);
ServletMapping mapping = addServletMapping(servlet_name, node, context, descriptor);
mapping.setDefault(context.getMetaData().getOrigin(servlet_name+".servlet.mappings") == Origin.WebDefaults);
addServletMapping(servlet_name, node, context, descriptor);
break;
}
case WebXml:
case WebDefaults:
case WebXml:
case WebOverride:
{
//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))
{
addServletMapping(servlet_name, node, context, descriptor);
@ -1181,7 +1180,8 @@ public class StandardDescriptorProcessor extends IterativeDescriptorProcessor
{
ServletMapping mapping = new ServletMapping();
mapping.setServletName(servletName);
mapping.setDefault(descriptor instanceof DefaultsDescriptor);
List<String> paths = new ArrayList<String>();
Iterator<XmlParser.Node> iter = node.iterator("url-pattern");
while (iter.hasNext())