Merge remote-tracking branch 'origin/jetty-9.4.x' into jetty-10.0.x

Signed-off-by: Greg Wilkins <gregw@webtide.com>
This commit is contained in:
Greg Wilkins 2019-05-07 15:37:27 +02:00
commit 2d5984da20
12 changed files with 469 additions and 76 deletions

View File

@ -27,6 +27,7 @@ import javax.servlet.ServletRequest;
import org.eclipse.jetty.server.UserIdentity;
import org.eclipse.jetty.util.component.AbstractLifeCycle;
import org.eclipse.jetty.util.component.ContainerLifeCycle;
import org.eclipse.jetty.util.log.Log;
import org.eclipse.jetty.util.log.Logger;
import org.eclipse.jetty.util.security.Credential;
@ -34,7 +35,7 @@ import org.eclipse.jetty.util.security.Credential;
/**
* AbstractLoginService
*/
public abstract class AbstractLoginService extends AbstractLifeCycle implements LoginService
public abstract class AbstractLoginService extends ContainerLifeCycle implements LoginService
{
private static final Logger LOG = Log.getLogger(AbstractLoginService.class);
@ -116,6 +117,11 @@ public abstract class AbstractLoginService extends AbstractLifeCycle implements
/* ------------------------------------------------------------ */
protected abstract UserPrincipal loadUserInfo (String username);
protected AbstractLoginService()
{
addBean(_identityService);
}
/* ------------------------------------------------------------ */
/**
* @see org.eclipse.jetty.security.LoginService#getName()
@ -135,6 +141,7 @@ public abstract class AbstractLoginService extends AbstractLifeCycle implements
{
if (isRunning())
throw new IllegalStateException("Running");
updateBean(_identityService, identityService);
_identityService = identityService;
}

View File

@ -123,7 +123,8 @@ public class HashLoginService extends AbstractLoginService
*/
public void setUserStore(UserStore userStore)
{
this._userStore = userStore;
updateBean(_userStore, userStore);
_userStore = userStore;
}
/* ------------------------------------------------------------ */
@ -179,12 +180,29 @@ public class HashLoginService extends AbstractLoginService
PropertyUserStore propertyUserStore = new PropertyUserStore();
propertyUserStore.setHotReload(hotReload);
propertyUserStore.setConfig(_config);
propertyUserStore.start();
_userStore = propertyUserStore;
setUserStore(propertyUserStore);
_userStoreAutoCreate = true;
}
}
/**
* To facilitate testing.
* @return the UserStore
*/
UserStore getUserStore ()
{
return _userStore;
}
/**
* To facilitate testing.
* @return true if a UserStore has been created from a config, false if a UserStore was provided.
*/
boolean isUserStoreAutoCreate ()
{
return _userStoreAutoCreate;
}
/* ------------------------------------------------------------ */
/**
* @see org.eclipse.jetty.util.component.AbstractLifeCycle#doStop()
@ -193,8 +211,10 @@ public class HashLoginService extends AbstractLoginService
protected void doStop() throws Exception
{
super.doStop();
if (_userStore != null && _userStoreAutoCreate)
_userStore.stop();
_userStore = null;
if ( _userStoreAutoCreate)
{
setUserStore(null);
_userStoreAutoCreate = false;
}
}
}

View File

@ -0,0 +1,70 @@
//
// ========================================================================
// Copyright (c) 1995-2019 Mort Bay Consulting Pty. Ltd.
// ------------------------------------------------------------------------
// All rights reserved. This program and the accompanying materials
// are made available under the terms of the Eclipse Public License v1.0
// and Apache License v2.0 which accompanies this distribution.
//
// The Eclipse Public License is available at
// http://www.eclipse.org/legal/epl-v10.html
//
// The Apache License v2.0 is available at
// http://www.opensource.org/licenses/apache2.0.php
//
// You may elect to redistribute this code under either of these licenses.
// ========================================================================
//
package org.eclipse.jetty.security;
import static org.junit.jupiter.api.Assertions.assertFalse;
import static org.junit.jupiter.api.Assertions.assertTrue;
import org.eclipse.jetty.toolchain.test.MavenTestingUtils;
import org.junit.jupiter.api.Test;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.Matchers.is;
import static org.hamcrest.Matchers.nullValue;
import static org.hamcrest.Matchers.notNullValue;
/**
* Tests of the HashLoginService.
*/
public class HashLoginServiceTest
{
@Test
public void testAutoCreatedUserStore() throws Exception
{
HashLoginService loginService = new HashLoginService("foo", MavenTestingUtils.getTestResourceFile("foo.properties").getAbsolutePath());
assertThat(loginService.getIdentityService(), is(notNullValue()));
loginService.start();
assertTrue(loginService.getUserStore().isStarted());
assertTrue(loginService.isUserStoreAutoCreate());
loginService.stop();
assertFalse(loginService.isUserStoreAutoCreate());
assertThat(loginService.getUserStore(), is(nullValue()));
}
@Test
public void testProvidedUserStore() throws Exception
{
HashLoginService loginService = new HashLoginService("foo");
assertThat(loginService.getIdentityService(), is(notNullValue()));
UserStore store = new UserStore();
loginService.setUserStore(store);
assertFalse(store.isStarted());
loginService.start();
assertTrue(loginService.getUserStore().isStarted());
assertFalse(loginService.isUserStoreAutoCreate());
loginService.stop();
assertFalse(loginService.isUserStoreAutoCreate());
assertFalse(store.isStarted());
assertThat(loginService.getUserStore(), is(notNullValue()));
}
}

View File

@ -0,0 +1,2 @@
ken=123
amy=456

View File

@ -1,3 +1,5 @@
DO NOT EDIT - See: https://www.eclipse.org/jetty/documentation/current/startup-modules.html
[description]
Enable the InetAccessHandler to apply a include/exclude
control of the remote IP of requests.
@ -9,7 +11,22 @@ handler
server
[files]
basehome:modules/inetaccess/inetaccess.xml|etc/inetaccess.xml
basehome:modules/inetaccess/jetty-inetaccess.xml|etc/jetty-inetaccess.xml
[xml]
etc/inetaccess.xml
etc/jetty-inetaccess.xml
[ini-template]
## List of InetAddress patterns to include
#jetty.inetaccess.include=127.0.0.1,127.0.0.2
## List of InetAddress patterns to exclude
#jetty.inetaccess.exclude=127.0.0.1,127.0.0.2
## List of Connector names to include
#jetty.inetaccess.includeConnectors=http
## List of Connector names to exclude
#jetty.inetaccess.excludeConnectors=tls

View File

@ -0,0 +1,39 @@
<?xml version="1.0"?>
<!DOCTYPE Configure PUBLIC "-//Jetty//Configure//EN" "http://www.eclipse.org/jetty/configure_9_3.dtd">
<Configure id="Server" class="org.eclipse.jetty.server.Server">
<Call name="insertHandler">
<Arg>
<New id="InetAccessHandler" class="org.eclipse.jetty.server.handler.InetAccessHandler">
<Call name="include">
<Arg>
<Call class="org.eclipse.jetty.util.StringUtil" name="csvSplit">
<Arg><Property name="jetty.inetaccess.include" default=""/></Arg>
</Call>
</Arg>
</Call>
<Call name="exclude">
<Arg>
<Call class="org.eclipse.jetty.util.StringUtil" name="csvSplit">
<Arg><Property name="jetty.inetaccess.exclude" default=""/></Arg>
</Call>
</Arg>
</Call>
<Call name="includeConnectors">
<Arg>
<Call class="org.eclipse.jetty.util.StringUtil" name="csvSplit">
<Arg><Property name="jetty.inetaccess.includeConnectors" default=""/></Arg>
</Call>
</Arg>
</Call>
<Call name="excludeConnectors">
<Arg>
<Call class="org.eclipse.jetty.util.StringUtil" name="csvSplit">
<Arg><Property name="jetty.inetaccess.excludeConnectors" default=""/></Arg>
</Call>
</Arg>
</Call>
</New>
</Arg>
</Call>
</Configure>

View File

@ -30,6 +30,7 @@ import org.eclipse.jetty.http.HttpStatus;
import org.eclipse.jetty.io.EndPoint;
import org.eclipse.jetty.server.HttpChannel;
import org.eclipse.jetty.server.Request;
import org.eclipse.jetty.util.IncludeExclude;
import org.eclipse.jetty.util.IncludeExcludeSet;
import org.eclipse.jetty.util.InetAddressSet;
import org.eclipse.jetty.util.component.DumpableCollection;
@ -39,16 +40,32 @@ import org.eclipse.jetty.util.log.Logger;
/**
* InetAddress Access Handler
* <p>
* Controls access to the wrapped handler using the real remote IP. Control is provided
* by and {@link IncludeExcludeSet} over a {@link InetAddressSet}. This handler
* uses the real internet address of the connection, not one reported in the forwarded
* for headers, as this cannot be as easily forged.
* Controls access to the wrapped handler using the real remote IP. Control is
* provided by and {@link IncludeExcludeSet} over a {@link InetAddressSet}. This
* handler uses the real internet address of the connection, not one reported in
* the forwarded for headers, as this cannot be as easily forged.
* <p>
* Additionally, there may be times when you want to only apply this handler to
* a subset of your connectors. In this situation you can use
* <b>connectorNames</b> to specify the connector names that you want this IP
* access filter to apply to.
*/
public class InetAccessHandler extends HandlerWrapper
{
private static final Logger LOG = Log.getLogger(InetAccessHandler.class);
private final IncludeExcludeSet<String, InetAddress> _set = new IncludeExcludeSet<>(InetAddressSet.class);
private final IncludeExcludeSet<String, InetAddress> _addrs = new IncludeExcludeSet<>(InetAddressSet.class);
private final IncludeExclude<String> _names = new IncludeExclude<>();
/**
* Clears all the includes, excludes, included connector names and excluded
* connector names.
*/
public void clear()
{
_addrs.clear();
_names.clear();
}
/**
* Includes an InetAddress pattern
@ -58,7 +75,7 @@ public class InetAccessHandler extends HandlerWrapper
*/
public void include(String pattern)
{
_set.include(pattern);
_addrs.include(pattern);
}
/**
@ -69,7 +86,7 @@ public class InetAccessHandler extends HandlerWrapper
*/
public void include(String... patterns)
{
_set.include(patterns);
_addrs.include(patterns);
}
/**
@ -80,7 +97,7 @@ public class InetAccessHandler extends HandlerWrapper
*/
public void exclude(String pattern)
{
_set.exclude(pattern);
_addrs.exclude(pattern);
}
/**
@ -91,14 +108,55 @@ public class InetAccessHandler extends HandlerWrapper
*/
public void exclude(String... patterns)
{
_set.exclude(patterns);
_addrs.exclude(patterns);
}
/**
* Includes a connector name.
*
* @param name Connector name to include in this handler.
*/
public void includeConnector(String name)
{
_names.include(name);
}
/**
* Excludes a connector name.
*
* @param name Connector name to exclude in this handler.
*/
public void excludeConnector(String name)
{
_names.exclude(name);
}
/**
* Includes connector names.
*
* @param names Connector names to include in this handler.
*/
public void includeConnectors(String... names)
{
_names.include(names);
}
/**
* Excludes connector names.
*
* @param names Connector names to exclude in this handler.
*/
public void excludeConnectors(String... names)
{
_names.exclude(names);
}
/**
* Checks the incoming request against the whitelist and blacklist
*/
@Override
public void handle(String target, Request baseRequest, HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException
public void handle(String target, Request baseRequest, HttpServletRequest request, HttpServletResponse response)
throws IOException, ServletException
{
// Get the real remote IP (not the one set by the forwarded headers (which may be forged))
HttpChannel channel = baseRequest.getHttpChannel();
@ -108,7 +166,7 @@ public class InetAccessHandler extends HandlerWrapper
if (endp != null)
{
InetSocketAddress address = endp.getRemoteAddress();
if (address != null && !isAllowed(address.getAddress(), request))
if (address != null && !isAllowed(address.getAddress(), baseRequest, request))
{
response.sendError(HttpStatus.FORBIDDEN_403);
baseRequest.setHandled(true);
@ -123,23 +181,30 @@ public class InetAccessHandler extends HandlerWrapper
/**
* Checks if specified address and request are allowed by current InetAddress rules.
*
* @param address the inetAddress to check
* @param request the request to check
* @param addr the inetAddress to check
* @param baseRequest the base request to check
* @param request the HttpServletRequest request to check
* @return true if inetAddress and request are allowed
*/
protected boolean isAllowed(InetAddress address, HttpServletRequest request)
protected boolean isAllowed(InetAddress addr, Request baseRequest, HttpServletRequest request)
{
boolean allowed = _set.test(address);
String name = baseRequest.getHttpChannel().getConnector().getName();
if (LOG.isDebugEnabled())
LOG.debug("{} {} {} for {}", this, allowed ? "allowed" : "denied", address, request);
return allowed;
{
Boolean allowedByName = _names.isIncludedAndNotExcluded(name);
Boolean allowedByAddr = _addrs.isIncludedAndNotExcluded(addr);
LOG.debug("{} allowedByName={} allowedByAddr={} for {}/{}", this, allowedByName, allowedByAddr, addr, request);
}
return _names.test(name) && _addrs.test(addr);
}
@Override
public void dump(Appendable out, String indent) throws IOException
{
dumpObjects(out, indent,
DumpableCollection.from("included",_set.getIncluded()),
DumpableCollection.from("excluded",_set.getExcluded()));
new DumpableCollection("included", _addrs.getIncluded()),
new DumpableCollection("excluded", _addrs.getExcluded()),
new DumpableCollection("includedConnector", _names.getIncluded()),
new DumpableCollection("excludedConnector", _names.getExcluded()));
}
}

View File

@ -0,0 +1,174 @@
//
// ========================================================================
// Copyright (c) 1995-2019 Mort Bay Consulting Pty. Ltd.
// ------------------------------------------------------------------------
// All rights reserved. This program and the accompanying materials
// are made available under the terms of the Eclipse Public License v1.0
// and Apache License v2.0 which accompanies this distribution.
//
// The Eclipse Public License is available at
// http://www.eclipse.org/legal/epl-v10.html
//
// The Apache License v2.0 is available at
// http://www.opensource.org/licenses/apache2.0.php
//
// You may elect to redistribute this code under either of these licenses.
// ========================================================================
//
package org.eclipse.jetty.server.handler;
import java.io.IOException;
import java.net.Socket;
import java.nio.ByteBuffer;
import java.util.Arrays;
import java.util.stream.Stream;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.eclipse.jetty.http.HttpStatus;
import org.eclipse.jetty.http.HttpVersion;
import org.eclipse.jetty.http.tools.HttpTester;
import org.eclipse.jetty.server.Connector;
import org.eclipse.jetty.server.Request;
import org.eclipse.jetty.server.Server;
import org.eclipse.jetty.server.ServerConnector;
import org.junit.jupiter.api.AfterAll;
import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.Arguments;
import org.junit.jupiter.params.provider.MethodSource;
import static org.junit.jupiter.api.Assertions.assertEquals;
public class InetAccessHandlerTest
{
private static Server _server;
private static ServerConnector _connector;
private static InetAccessHandler _handler;
@BeforeAll
public static void setUp() throws Exception
{
_server = new Server();
_connector = new ServerConnector(_server);
_connector.setName("http");
_server.setConnectors(new Connector[]
{ _connector });
_handler = new InetAccessHandler();
_handler.setHandler(new AbstractHandler()
{
@Override
public void handle(String target, Request baseRequest, HttpServletRequest request, HttpServletResponse response)
throws IOException, ServletException
{
baseRequest.setHandled(true);
response.setStatus(HttpStatus.OK_200);
}
});
_server.setHandler(_handler);
_server.start();
}
@AfterAll
public static void tearDown() throws Exception
{
_server.stop();
}
@ParameterizedTest
@MethodSource("data")
public void testHandler(String include, String exclude, String includeConnectors, String excludeConnectors, String code)
throws Exception
{
_handler.clear();
for (String inc : include.split(";", -1))
{
if (inc.length() > 0)
{
_handler.include(inc);
}
}
for (String exc : exclude.split(";", -1))
{
if (exc.length() > 0)
{
_handler.exclude(exc);
}
}
for (String inc : includeConnectors.split(";", -1))
{
if (inc.length() > 0)
{
_handler.includeConnector(inc);
}
}
for (String exc : excludeConnectors.split(";", -1))
{
if (exc.length() > 0)
{
_handler.excludeConnector(exc);
}
}
try (Socket socket = new Socket("127.0.0.1", _connector.getLocalPort());)
{
socket.setSoTimeout(5000);
HttpTester.Request request = HttpTester.newRequest();
request.setMethod("GET");
request.setURI("/path");
request.setHeader("Host","127.0.0.1");
request.setVersion(HttpVersion.HTTP_1_0);
ByteBuffer output = request.generate();
socket.getOutputStream().write(output.array(),output.arrayOffset()+output.position(),output.remaining());
HttpTester.Input input = HttpTester.from(socket.getInputStream());
HttpTester.Response response = HttpTester.parseResponse(input);
Object[] params = new Object[]
{ "Request WBHUC", include, exclude, includeConnectors, excludeConnectors, code, "Response", response.getStatus() };
assertEquals(Integer.parseInt(code), response.getStatus(), Arrays.deepToString(params));
}
}
public static Stream<Arguments> data()
{
Object[][] data = new Object[][]
{
// Empty lists
{ "", "", "", "", "200" },
// test simple filters
{ "127.0.0.1", "", "", "", "200" },
{ "127.0.0.1-127.0.0.254", "", "", "", "200" },
{ "192.0.0.1", "", "", "", "403" },
{ "192.0.0.1-192.0.0.254", "", "", "", "403" },
// test connector name filters
{ "127.0.0.1", "", "http", "", "200" },
{ "127.0.0.1-127.0.0.254", "", "http", "", "200" },
{ "192.0.0.1", "", "http", "", "403" },
{ "192.0.0.1-192.0.0.254", "", "http", "", "403" },
{ "127.0.0.1", "", "nothttp", "", "403" },
{ "127.0.0.1-127.0.0.254", "", "nothttp", "", "403" },
{ "192.0.0.1", "", "nothttp", "", "403" },
{ "192.0.0.1-192.0.0.254", "", "nothttp", "", "403" },
{ "127.0.0.1", "", "", "http", "403" },
{ "127.0.0.1-127.0.0.254", "", "", "http", "403" },
{ "192.0.0.1", "", "", "http", "403" },
{ "192.0.0.1-192.0.0.254", "", "", "http", "403" },
{ "127.0.0.1", "", "", "nothttp", "200" },
{ "127.0.0.1-127.0.0.254", "", "", "nothttp", "200" },
{ "192.0.0.1", "", "", "nothttp", "403" },
{ "192.0.0.1-192.0.0.254", "", "", "nothttp", "403" },
};
return Arrays.asList(data).stream().map(Arguments::of);
}
}

View File

@ -40,7 +40,7 @@ public class IncludeExcludeSet<T,P> implements Predicate<P>
private final Predicate<P> _includePredicate;
private final Set<T> _excludes;
private final Predicate<P> _excludePredicate;
private static class SetContainsPredicate<T> implements Predicate<T>
{
private final Set<T> set;
@ -162,14 +162,14 @@ public class IncludeExcludeSet<T,P> implements Predicate<P>
/**
* Test Included and not Excluded
* @param t The item to test
* @return Boolean.TRUE if t is included, Boolean.FALSE if t is excluded and null if neither
* @param item The item to test
* @return Boolean.TRUE if item is included, Boolean.FALSE if item is excluded and null if neither
*/
public Boolean isIncludedAndNotExcluded(P t)
public Boolean isIncludedAndNotExcluded(P item)
{
if (_excludePredicate.test(t))
if (_excludePredicate.test(item))
return Boolean.FALSE;
if (_includePredicate.test(t))
if (_includePredicate.test(item))
return Boolean.TRUE;
return null;
@ -204,7 +204,11 @@ public class IncludeExcludeSet<T,P> implements Predicate<P>
@Override
public String toString()
{
return String.format("%s@%x{i=%s,ip=%s,e=%s,ep=%s}",this.getClass().getSimpleName(),hashCode(),_includes,_includePredicate,_excludes,_excludePredicate);
return String.format("%s@%x{i=%s,ip=%s,e=%s,ep=%s}",this.getClass().getSimpleName(),hashCode(),
_includes,
_includePredicate==_includes?"SELF":_includePredicate,
_excludes,
_excludePredicate==_excludes?"SELF":_excludePredicate);
}
public boolean isEmpty()

View File

@ -394,7 +394,11 @@ public class QueuedThreadPool extends ContainerLifeCycle implements SizedThreadP
public int getReservedThreads()
{
if (isStarted())
return getBean(ReservedThreadExecutor.class).getCapacity();
{
ReservedThreadExecutor reservedThreadExecutor = getBean(ReservedThreadExecutor.class);
if (reservedThreadExecutor != null)
return reservedThreadExecutor.getCapacity();
}
return _reservedThreads;
}

View File

@ -18,17 +18,16 @@
package org.eclipse.jetty.util.component;
import static org.hamcrest.MatcherAssert.assertThat;
import java.util.ArrayList;
import java.util.Collection;
import org.hamcrest.Matchers;
import org.junit.jupiter.api.Test;
public class DumpableCollectionTest
{
import static org.hamcrest.MatcherAssert.assertThat;
public class DumpableTest
{
@Test
public void testNullDumpableCollection () throws Exception
{

View File

@ -23,6 +23,7 @@ import java.io.File;
import java.io.IOException;
import java.io.UncheckedIOException;
import java.net.URI;
import java.net.URISyntaxException;
import java.net.URL;
import java.nio.file.Path;
import java.nio.file.Paths;
@ -36,6 +37,7 @@ import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.function.Predicate;
import java.util.function.Supplier;
import org.eclipse.jetty.util.ArrayTernaryTrie;
import org.eclipse.jetty.util.IncludeExcludeSet;
@ -708,21 +710,7 @@ public class ClassMatcher extends AbstractSet<String>
{
try
{
Boolean byName = _patterns.isIncludedAndNotExcluded(clazz.getName());
if (Boolean.FALSE.equals(byName))
return byName; // Already excluded so no need to check location.
URI location = TypeUtil.getLocationOfClass(clazz);
Boolean byLocation = location == null ? null
: _locations.isIncludedAndNotExcluded(location);
if (LOG.isDebugEnabled())
LOG.debug("match {} from {} byName={} byLocation={} in {}",clazz,location,byName,byLocation,this);
// Combine the tri-state match of both IncludeExclude Sets
boolean included = Boolean.TRUE.equals(byName) || Boolean.TRUE.equals(byLocation)
|| (byName==null && !_patterns.hasIncludes() && byLocation==null && !_locations.hasIncludes());
boolean excluded = Boolean.FALSE.equals(byName) || Boolean.FALSE.equals(byLocation);
return included && !excluded;
return combine(_patterns, clazz.getName(), _locations, ()->TypeUtil.getLocationOfClass(clazz));
}
catch (Exception e)
{
@ -740,29 +728,33 @@ public class ClassMatcher extends AbstractSet<String>
// Treat path elements as packages for name matching
name=name.replace("/",".");
Boolean byName = _patterns.isIncludedAndNotExcluded(name);
if (Boolean.FALSE.equals(byName))
return byName; // Already excluded so no need to check location.
// Try to find a file path for location matching
Boolean byLocation = null;
try
return combine(_patterns, name, _locations, ()->
{
URI jarUri = URIUtil.getJarSource(url.toURI());
if ("file".equalsIgnoreCase(jarUri.getScheme()))
try
{
byLocation = _locations.isIncludedAndNotExcluded(jarUri);
return URIUtil.getJarSource(url.toURI());
}
}
catch(Exception e)
{
LOG.ignore(e);
}
catch (URISyntaxException e)
{
LOG.ignore(e);
return null;
}
});
}
private static boolean combine(IncludeExcludeSet<Entry, String> names, String name, IncludeExcludeSet<Entry, URI> locations, Supplier<URI> location)
{
Boolean byName = names.isIncludedAndNotExcluded(name);
if (Boolean.FALSE==byName)
return false;
Boolean byLocation = locations.isIncludedAndNotExcluded(location.get());
if (Boolean.FALSE==byLocation)
return false;
return Boolean.TRUE.equals(byName)
|| Boolean.TRUE.equals(byLocation)
|| !(names.hasIncludes() || locations.hasIncludes());
}
// Combine the tri-state match of both IncludeExclude Sets
boolean included = Boolean.TRUE.equals(byName) || Boolean.TRUE.equals(byLocation)
|| (byName==null && !_patterns.hasIncludes() && byLocation==null && !_locations.hasIncludes());
boolean excluded = Boolean.FALSE.equals(byName) || Boolean.FALSE.equals(byLocation);
return included && !excluded;
}
}