Merge remote-tracking branch 'origin/jetty-10.0.x' into jetty-10.0.x-5320-WebSocketHttpClient2
This commit is contained in:
commit
8ff545f696
|
@ -4,7 +4,10 @@ updates:
|
|||
directory: "/"
|
||||
schedule:
|
||||
interval: "weekly"
|
||||
time: "14:00"
|
||||
target-branch: "jetty-9.4.x"
|
||||
# Encourage more pull requests from oldest branch
|
||||
open-pull-requests-limit: 20
|
||||
|
||||
- package-ecosystem: "github-actions"
|
||||
directory: "/"
|
||||
|
|
|
@ -14,7 +14,7 @@ pipeline {
|
|||
steps {
|
||||
container( 'jetty-build' ) {
|
||||
timeout( time: 120, unit: 'MINUTES' ) {
|
||||
mavenBuild( "jdk11", "-T3 clean install", "maven3", true ) // -Pautobahn
|
||||
mavenBuild( "jdk11", "-T3 clean install -Premote-session-tests", "maven3", true ) // -Pautobahn
|
||||
// Collect up the jacoco execution results (only on main build)
|
||||
jacoco inclusionPattern: '**/org/eclipse/jetty/**/*.class',
|
||||
exclusionPattern: '' +
|
||||
|
@ -40,12 +40,13 @@ pipeline {
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
stage("Build / Test - JDK15") {
|
||||
agent { node { label 'linux' } }
|
||||
steps {
|
||||
container( 'jetty-build' ) {
|
||||
timeout( time: 120, unit: 'MINUTES' ) {
|
||||
mavenBuild( "jdk15", "-T3 clean install", "maven3", true )
|
||||
mavenBuild( "jdk15", "-T3 clean install -Premote-session-tests", "maven3", true )
|
||||
warnings consoleParsers: [[parserName: 'Maven'], [parserName: 'Java']]
|
||||
junit testResults: '**/target/surefire-reports/*.xml,**/target/invoker-reports/TEST*.xml'
|
||||
}
|
||||
|
@ -109,7 +110,7 @@ def mavenBuild(jdk, cmdline, mvnName, junitPublishDisabled) {
|
|||
mavenOpts: mavenOpts,
|
||||
mavenLocalRepo: localRepo) {
|
||||
// Some common Maven command line + provided command line
|
||||
sh "mvn -Premote-session-tests -Pci -V -B -e -fae -Dmaven.test.failure.ignore=true -Djetty.testtracker.log=true $cmdline -Dunix.socket.tmp=" + env.JENKINS_HOME
|
||||
sh "mvn -Pci -V -B -e -fae -Dmaven.test.failure.ignore=true -Djetty.testtracker.log=true $cmdline -Dunix.socket.tmp=" + env.JENKINS_HOME
|
||||
}
|
||||
}
|
||||
|
||||
|
|
1
KEYS.txt
1
KEYS.txt
|
@ -6,3 +6,4 @@ Joakim Erdfelt <joakime@apache.org> B59B 67FD 7904 9843 67F9 3180 0818
|
|||
Joakim Erdfelt <joakim@erdfelt.com> BFBB 21C2 46D7 7768 3628 7A48 A04E 0C74 ABB3 5FEA
|
||||
Simone Bordet <simone.bordet@gmail.com> 8B09 6546 B1A8 F026 56B1 5D3B 1677 D141 BCF3 584D
|
||||
Olivier Lamy <olamy@apache.org> F254 B356 17DC 255D 9344 BCFA 873A 8E86 B437 2146
|
||||
Ludovic Orban <lorban@bitronix.be> E224 88CC 94F6 3E3F C928 536C 4241 C082 70D9 99C3
|
||||
|
|
|
@ -31,7 +31,7 @@
|
|||
<Arg><Ref refid='wac'/></Arg>
|
||||
<Arg>svr</Arg>
|
||||
<Arg type="java.lang.String">
|
||||
<Ref id="Server">
|
||||
<Ref refid="Server">
|
||||
<Get name="class">
|
||||
<Get name="name"/>
|
||||
</Get>
|
||||
|
|
|
@ -21,7 +21,7 @@
|
|||
|
||||
==== List of Security Reports
|
||||
|
||||
A current list of Jetty security reports can be viewed on the link:https://www.eclipse.org/jetty/security-reports.htmlhttps://www.eclipse.org/jetty/security-reports.html[Project Home Page.]
|
||||
A current list of Jetty security reports can be viewed on the link:https://www.eclipse.org/jetty/security-reports.html[Project Home Page.]
|
||||
|
||||
==== Reporting Security Issues
|
||||
|
||||
|
|
|
@ -83,7 +83,7 @@
|
|||
<configuration>
|
||||
<instructions>
|
||||
<Export-Package>
|
||||
org.eclipse.jetty.gcloud.session.*;version="${parsedVersion.majorVersion}.${parsedVersion.minorVersion}.${parsedVersion.incrementalVersion}";
|
||||
org.eclipse.jetty.gcloud.session.*;version="${parsedVersion.majorVersion}.${parsedVersion.minorVersion}.${parsedVersion.incrementalVersion}"
|
||||
</Export-Package>
|
||||
</instructions>
|
||||
</configuration>
|
||||
|
|
|
@ -876,7 +876,7 @@ public class GCloudSessionDataStore extends AbstractSessionDataStore
|
|||
if (e.isRetryable())
|
||||
{
|
||||
if (LOG.isDebugEnabled())
|
||||
LOG.debug("Datastore put retry {} waiting {}ms", attempts, backoff);
|
||||
LOG.debug(String.format("Datastore put retry=%s backoff=%s", attempts, backoff), e);
|
||||
|
||||
try
|
||||
{
|
||||
|
|
|
@ -13,7 +13,7 @@ session-store
|
|||
sessions
|
||||
|
||||
[files]
|
||||
maven://com.hazelcast/hazelcast/4.0.1|lib/hazelcast/hazelcast-4.0.1.jar
|
||||
maven://com.hazelcast/hazelcast/4.1|lib/hazelcast/hazelcast-4.1.jar
|
||||
|
||||
[xml]
|
||||
etc/sessions/hazelcast/default.xml
|
||||
|
|
|
@ -13,7 +13,7 @@ session-store
|
|||
sessions
|
||||
|
||||
[files]
|
||||
maven://com.hazelcast/hazelcast/4.0.1|lib/hazelcast/hazelcast-4.0.1.jar
|
||||
maven://com.hazelcast/hazelcast/4.1|lib/hazelcast/hazelcast-4.1.jar
|
||||
|
||||
[xml]
|
||||
etc/sessions/hazelcast/remote.xml
|
||||
|
|
|
@ -26,137 +26,72 @@ import org.eclipse.jetty.util.StringUtil;
|
|||
import org.eclipse.jetty.util.Trie;
|
||||
|
||||
/**
|
||||
*
|
||||
* Known HTTP Methods
|
||||
*/
|
||||
public enum HttpMethod
|
||||
{
|
||||
GET,
|
||||
POST,
|
||||
HEAD,
|
||||
PUT,
|
||||
OPTIONS,
|
||||
DELETE,
|
||||
TRACE,
|
||||
CONNECT,
|
||||
MOVE,
|
||||
PROXY,
|
||||
PRI;
|
||||
// From https://www.iana.org/assignments/http-methods/http-methods.xhtml
|
||||
ACL(Type.IDEMPOTENT),
|
||||
BASELINE_CONTROL(Type.IDEMPOTENT),
|
||||
BIND(Type.IDEMPOTENT),
|
||||
CHECKIN(Type.IDEMPOTENT),
|
||||
CHECKOUT(Type.IDEMPOTENT),
|
||||
CONNECT(Type.NORMAL),
|
||||
COPY(Type.IDEMPOTENT),
|
||||
DELETE(Type.IDEMPOTENT),
|
||||
GET(Type.SAFE),
|
||||
HEAD(Type.SAFE),
|
||||
LABEL(Type.IDEMPOTENT),
|
||||
LINK(Type.IDEMPOTENT),
|
||||
LOCK(Type.NORMAL),
|
||||
MERGE(Type.IDEMPOTENT),
|
||||
MKACTIVITY(Type.IDEMPOTENT),
|
||||
MKCALENDAR(Type.IDEMPOTENT),
|
||||
MKCOL(Type.IDEMPOTENT),
|
||||
MKREDIRECTREF(Type.IDEMPOTENT),
|
||||
MKWORKSPACE(Type.IDEMPOTENT),
|
||||
MOVE(Type.IDEMPOTENT),
|
||||
OPTIONS(Type.SAFE),
|
||||
ORDERPATCH(Type.IDEMPOTENT),
|
||||
PATCH(Type.NORMAL),
|
||||
POST(Type.NORMAL),
|
||||
PRI(Type.SAFE),
|
||||
PROPFIND(Type.SAFE),
|
||||
PROPPATCH(Type.IDEMPOTENT),
|
||||
PUT(Type.IDEMPOTENT),
|
||||
REBIND(Type.IDEMPOTENT),
|
||||
REPORT(Type.SAFE),
|
||||
SEARCH(Type.SAFE),
|
||||
TRACE(Type.SAFE),
|
||||
UNBIND(Type.IDEMPOTENT),
|
||||
UNCHECKOUT(Type.IDEMPOTENT),
|
||||
UNLINK(Type.IDEMPOTENT),
|
||||
UNLOCK(Type.IDEMPOTENT),
|
||||
UPDATE(Type.IDEMPOTENT),
|
||||
UPDATEREDIRECTREF(Type.IDEMPOTENT),
|
||||
VERSION_CONTROL(Type.IDEMPOTENT),
|
||||
|
||||
/**
|
||||
* Optimized lookup to find a method name and trailing space in a byte array.
|
||||
*
|
||||
* @param bytes Array containing ISO-8859-1 characters
|
||||
* @param position The first valid index
|
||||
* @param limit The first non valid index
|
||||
* @return An HttpMethod if a match or null if no easy match.
|
||||
*/
|
||||
public static HttpMethod lookAheadGet(byte[] bytes, final int position, int limit)
|
||||
// Other methods
|
||||
PROXY(Type.NORMAL);
|
||||
|
||||
// The type of the method
|
||||
private enum Type
|
||||
{
|
||||
int length = limit - position;
|
||||
if (length < 4)
|
||||
return null;
|
||||
switch (bytes[position])
|
||||
{
|
||||
case 'G':
|
||||
if (bytes[position + 1] == 'E' && bytes[position + 2] == 'T' && bytes[position + 3] == ' ')
|
||||
return GET;
|
||||
break;
|
||||
case 'P':
|
||||
if (bytes[position + 1] == 'O' && bytes[position + 2] == 'S' && bytes[position + 3] == 'T' && length >= 5 && bytes[position + 4] == ' ')
|
||||
return POST;
|
||||
if (bytes[position + 1] == 'R' && bytes[position + 2] == 'O' && bytes[position + 3] == 'X' && length >= 6 && bytes[position + 4] == 'Y' && bytes[position + 5] == ' ')
|
||||
return PROXY;
|
||||
if (bytes[position + 1] == 'U' && bytes[position + 2] == 'T' && bytes[position + 3] == ' ')
|
||||
return PUT;
|
||||
if (bytes[position + 1] == 'R' && bytes[position + 2] == 'I' && bytes[position + 3] == ' ')
|
||||
return PRI;
|
||||
break;
|
||||
case 'H':
|
||||
if (bytes[position + 1] == 'E' && bytes[position + 2] == 'A' && bytes[position + 3] == 'D' && length >= 5 && bytes[position + 4] == ' ')
|
||||
return HEAD;
|
||||
break;
|
||||
case 'O':
|
||||
if (bytes[position + 1] == 'P' && bytes[position + 2] == 'T' && bytes[position + 3] == 'I' && length >= 8 &&
|
||||
bytes[position + 4] == 'O' && bytes[position + 5] == 'N' && bytes[position + 6] == 'S' && bytes[position + 7] == ' ')
|
||||
return OPTIONS;
|
||||
break;
|
||||
case 'D':
|
||||
if (bytes[position + 1] == 'E' && bytes[position + 2] == 'L' && bytes[position + 3] == 'E' && length >= 7 &&
|
||||
bytes[position + 4] == 'T' && bytes[position + 5] == 'E' && bytes[position + 6] == ' ')
|
||||
return DELETE;
|
||||
break;
|
||||
case 'T':
|
||||
if (bytes[position + 1] == 'R' && bytes[position + 2] == 'A' && bytes[position + 3] == 'C' && length >= 6 &&
|
||||
bytes[position + 4] == 'E' && bytes[position + 5] == ' ')
|
||||
return TRACE;
|
||||
break;
|
||||
case 'C':
|
||||
if (bytes[position + 1] == 'O' && bytes[position + 2] == 'N' && bytes[position + 3] == 'N' && length >= 8 &&
|
||||
bytes[position + 4] == 'E' && bytes[position + 5] == 'C' && bytes[position + 6] == 'T' && bytes[position + 7] == ' ')
|
||||
return CONNECT;
|
||||
break;
|
||||
case 'M':
|
||||
if (bytes[position + 1] == 'O' && bytes[position + 2] == 'V' && bytes[position + 3] == 'E' && length >= 5 && bytes[position + 4] == ' ')
|
||||
return MOVE;
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return null;
|
||||
NORMAL,
|
||||
IDEMPOTENT,
|
||||
SAFE
|
||||
}
|
||||
|
||||
/**
|
||||
* Optimized lookup to find a method name and trailing space in a byte array.
|
||||
*
|
||||
* @param buffer buffer containing ISO-8859-1 characters, it is not modified.
|
||||
* @return An HttpMethod if a match or null if no easy match.
|
||||
*/
|
||||
public static HttpMethod lookAheadGet(ByteBuffer buffer)
|
||||
{
|
||||
if (buffer.hasArray())
|
||||
return lookAheadGet(buffer.array(), buffer.arrayOffset() + buffer.position(), buffer.arrayOffset() + buffer.limit());
|
||||
|
||||
int l = buffer.remaining();
|
||||
if (l >= 4)
|
||||
{
|
||||
HttpMethod m = CACHE.getBest(buffer, 0, l);
|
||||
if (m != null)
|
||||
{
|
||||
int ml = m.asString().length();
|
||||
if (l > ml && buffer.get(buffer.position() + ml) == ' ')
|
||||
return m;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public static final Trie<HttpMethod> INSENSITIVE_CACHE = new ArrayTrie<>();
|
||||
|
||||
static
|
||||
{
|
||||
for (HttpMethod method : HttpMethod.values())
|
||||
{
|
||||
INSENSITIVE_CACHE.put(method.toString(), method);
|
||||
}
|
||||
}
|
||||
|
||||
public static final Trie<HttpMethod> CACHE = new ArrayTernaryTrie<>(false);
|
||||
|
||||
static
|
||||
{
|
||||
for (HttpMethod method : HttpMethod.values())
|
||||
{
|
||||
CACHE.put(method.toString(), method);
|
||||
}
|
||||
}
|
||||
|
||||
private final ByteBuffer _buffer;
|
||||
private final String _method;
|
||||
private final byte[] _bytes;
|
||||
private final ByteBuffer _buffer;
|
||||
private final Type _type;
|
||||
|
||||
HttpMethod()
|
||||
HttpMethod(Type type)
|
||||
{
|
||||
_bytes = StringUtil.getBytes(toString());
|
||||
_method = name().replace('_', '-');
|
||||
_type = type;
|
||||
_bytes = StringUtil.getBytes(_method);
|
||||
_buffer = ByteBuffer.wrap(_bytes);
|
||||
}
|
||||
|
||||
|
@ -170,6 +105,28 @@ public enum HttpMethod
|
|||
return toString().equalsIgnoreCase(s);
|
||||
}
|
||||
|
||||
/**
|
||||
* An HTTP method is safe if it doesn't alter the state of the server.
|
||||
* In other words, a method is safe if it leads to a read-only operation.
|
||||
* Several common HTTP methods are safe: GET , HEAD , or OPTIONS .
|
||||
* All safe methods are also idempotent, but not all idempotent methods are safe
|
||||
* @return if the method is safe.
|
||||
*/
|
||||
public boolean isSafe()
|
||||
{
|
||||
return _type == Type.SAFE;
|
||||
}
|
||||
|
||||
/**
|
||||
* An idempotent HTTP method is an HTTP method that can be called many times without different outcomes.
|
||||
* It would not matter if the method is called only once, or ten times over. The result should be the same.
|
||||
* @return true if the method is idempotent.
|
||||
*/
|
||||
public boolean isIdempotent()
|
||||
{
|
||||
return _type.ordinal() >= Type.IDEMPOTENT.ordinal();
|
||||
}
|
||||
|
||||
public ByteBuffer asBuffer()
|
||||
{
|
||||
return _buffer.asReadOnlyBuffer();
|
||||
|
@ -177,11 +134,94 @@ public enum HttpMethod
|
|||
|
||||
public String asString()
|
||||
{
|
||||
return toString();
|
||||
return _method;
|
||||
}
|
||||
|
||||
public String toString()
|
||||
{
|
||||
return _method;
|
||||
}
|
||||
|
||||
public static final Trie<HttpMethod> INSENSITIVE_CACHE = new ArrayTrie<>(252);
|
||||
public static final Trie<HttpMethod> CACHE = new ArrayTernaryTrie<>(false, 300);
|
||||
public static final Trie<HttpMethod> LOOK_AHEAD = new ArrayTernaryTrie<>(false, 330);
|
||||
public static final int ACL_AS_INT = ('A' & 0xff) << 24 | ('C' & 0xFF) << 16 | ('L' & 0xFF) << 8 | (' ' & 0xFF);
|
||||
public static final int GET_AS_INT = ('G' & 0xff) << 24 | ('E' & 0xFF) << 16 | ('T' & 0xFF) << 8 | (' ' & 0xFF);
|
||||
public static final int PRI_AS_INT = ('P' & 0xff) << 24 | ('R' & 0xFF) << 16 | ('I' & 0xFF) << 8 | (' ' & 0xFF);
|
||||
public static final int PUT_AS_INT = ('P' & 0xff) << 24 | ('U' & 0xFF) << 16 | ('T' & 0xFF) << 8 | (' ' & 0xFF);
|
||||
public static final int POST_AS_INT = ('P' & 0xff) << 24 | ('O' & 0xFF) << 16 | ('S' & 0xFF) << 8 | ('T' & 0xFF);
|
||||
public static final int HEAD_AS_INT = ('H' & 0xff) << 24 | ('E' & 0xFF) << 16 | ('A' & 0xFF) << 8 | ('D' & 0xFF);
|
||||
static
|
||||
{
|
||||
for (HttpMethod method : HttpMethod.values())
|
||||
{
|
||||
if (!INSENSITIVE_CACHE.put(method.asString(), method))
|
||||
throw new IllegalStateException("INSENSITIVE_CACHE too small: " + method);
|
||||
|
||||
if (!CACHE.put(method.asString(), method))
|
||||
throw new IllegalStateException("CACHE too small: " + method);
|
||||
|
||||
if (!LOOK_AHEAD.put(method.asString() + ' ', method))
|
||||
throw new IllegalStateException("LOOK_AHEAD too small: " + method);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts the given String parameter to an HttpMethod
|
||||
* Optimized lookup to find a method name and trailing space in a byte array.
|
||||
*
|
||||
* @param bytes Array containing ISO-8859-1 characters
|
||||
* @param position The first valid index
|
||||
* @param limit The first non valid index
|
||||
* @return An HttpMethod if a match or null if no easy match.
|
||||
* @deprecated Not used
|
||||
*/
|
||||
@Deprecated
|
||||
public static HttpMethod lookAheadGet(byte[] bytes, final int position, int limit)
|
||||
{
|
||||
return LOOK_AHEAD.getBest(bytes, position, limit - position);
|
||||
}
|
||||
|
||||
/**
|
||||
* Optimized lookup to find a method name and trailing space in a byte array.
|
||||
*
|
||||
* @param buffer buffer containing ISO-8859-1 characters, it is not modified.
|
||||
* @return An HttpMethod if a match or null if no easy match.
|
||||
*/
|
||||
public static HttpMethod lookAheadGet(ByteBuffer buffer)
|
||||
{
|
||||
int len = buffer.remaining();
|
||||
// Short cut for 3 char methods, mostly for GET optimisation
|
||||
if (len > 3)
|
||||
{
|
||||
switch (buffer.getInt(buffer.position()))
|
||||
{
|
||||
case ACL_AS_INT:
|
||||
return ACL;
|
||||
case GET_AS_INT:
|
||||
return GET;
|
||||
case PRI_AS_INT:
|
||||
return PRI;
|
||||
case PUT_AS_INT:
|
||||
return PUT;
|
||||
case POST_AS_INT:
|
||||
if (len > 4 && buffer.get(buffer.position() + 4) == ' ')
|
||||
return POST;
|
||||
break;
|
||||
case HEAD_AS_INT:
|
||||
if (len > 4 && buffer.get(buffer.position() + 4) == ' ')
|
||||
return HEAD;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
return LOOK_AHEAD.getBest(buffer, 0, len);
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts the given String parameter to an HttpMethod.
|
||||
* The string may differ from the Enum name as a '-' in the method
|
||||
* name is represented as a '_' in the Enum name.
|
||||
*
|
||||
* @param method the String to get the equivalent HttpMethod from
|
||||
* @return the HttpMethod or null if the parameter method is unknown
|
||||
|
|
|
@ -22,6 +22,7 @@ import java.nio.ByteBuffer;
|
|||
import java.nio.charset.StandardCharsets;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
|
||||
import org.eclipse.jetty.http.HttpParser.State;
|
||||
import org.eclipse.jetty.logging.StacklessLogging;
|
||||
|
@ -31,6 +32,8 @@ import org.hamcrest.Matchers;
|
|||
import org.junit.jupiter.api.Assumptions;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.params.ParameterizedTest;
|
||||
import org.junit.jupiter.params.provider.ValueSource;
|
||||
|
||||
import static org.eclipse.jetty.http.HttpCompliance.Violation.CASE_INSENSITIVE_METHOD;
|
||||
import static org.eclipse.jetty.http.HttpCompliance.Violation.CASE_SENSITIVE_FIELD_NAME;
|
||||
|
@ -81,12 +84,20 @@ public class HttpParserTest
|
|||
@Test
|
||||
public void testHttpMethod()
|
||||
{
|
||||
assertNull(HttpMethod.lookAheadGet(BufferUtil.toBuffer("Wibble ")));
|
||||
assertNull(HttpMethod.lookAheadGet(BufferUtil.toBuffer("GET")));
|
||||
assertNull(HttpMethod.lookAheadGet(BufferUtil.toBuffer("MO")));
|
||||
for (HttpMethod m : HttpMethod.values())
|
||||
{
|
||||
assertNull(HttpMethod.lookAheadGet(BufferUtil.toBuffer(m.asString().substring(0,2))));
|
||||
assertNull(HttpMethod.lookAheadGet(BufferUtil.toBuffer(m.asString())));
|
||||
assertNull(HttpMethod.lookAheadGet(BufferUtil.toBuffer(m.asString() + "FOO")));
|
||||
assertEquals(m, HttpMethod.lookAheadGet(BufferUtil.toBuffer(m.asString() + " ")));
|
||||
assertEquals(m, HttpMethod.lookAheadGet(BufferUtil.toBuffer(m.asString() + " /foo/bar")));
|
||||
|
||||
assertEquals(HttpMethod.GET, HttpMethod.lookAheadGet(BufferUtil.toBuffer("GET ")));
|
||||
assertEquals(HttpMethod.MOVE, HttpMethod.lookAheadGet(BufferUtil.toBuffer("MOVE ")));
|
||||
assertNull(HttpMethod.lookAheadGet(m.asString().substring(0,2).getBytes(), 0,2));
|
||||
assertNull(HttpMethod.lookAheadGet(m.asString().getBytes(), 0, m.asString().length()));
|
||||
assertNull(HttpMethod.lookAheadGet((m.asString() + "FOO").getBytes(), 0, m.asString().length() + 3));
|
||||
assertEquals(m, HttpMethod.lookAheadGet(("\n" + m.asString() + " ").getBytes(), 1, m.asString().length() + 2));
|
||||
assertEquals(m, HttpMethod.lookAheadGet(("\n" + m.asString() + " /foo").getBytes(), 1, m.asString().length() + 6));
|
||||
}
|
||||
|
||||
ByteBuffer b = BufferUtil.allocateDirect(128);
|
||||
BufferUtil.append(b, BufferUtil.toBuffer("GET"));
|
||||
|
@ -96,6 +107,15 @@ public class HttpParserTest
|
|||
assertEquals(HttpMethod.GET, HttpMethod.lookAheadGet(b));
|
||||
}
|
||||
|
||||
@ParameterizedTest
|
||||
@ValueSource(strings = {"GET", "POST", "VERSION-CONTROL"})
|
||||
public void httpMethodNameTest(String methodName)
|
||||
{
|
||||
HttpMethod method = HttpMethod.fromString(methodName);
|
||||
assertNotNull(method, "Method should have been found: " + methodName);
|
||||
assertEquals(methodName.toUpperCase(Locale.US), method.toString());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testLineParseMockIP()
|
||||
{
|
||||
|
|
|
@ -266,9 +266,9 @@ public class HpackEncoder
|
|||
if (_maxHeaderListSize > 0 && _headerListSize > _maxHeaderListSize)
|
||||
{
|
||||
if (LOG.isDebugEnabled())
|
||||
LOG.warn("Header list size too large {} > {} metadata={}", _headerListSize, _maxHeaderListSize, metadata);
|
||||
LOG.warn("Header list size too large {} > {} metadata={}", _headerListSize, _maxHeaderListSize, metadata);
|
||||
else
|
||||
LOG.warn("Header list size too large {} > {}", _headerListSize, _maxHeaderListSize);
|
||||
LOG.warn("Header list size too large {} > {}", _headerListSize, _maxHeaderListSize);
|
||||
}
|
||||
|
||||
if (LOG.isDebugEnabled())
|
||||
|
|
|
@ -66,10 +66,14 @@
|
|||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.apache.directory.server</groupId>
|
||||
<artifactId>apacheds-all</artifactId>
|
||||
<artifactId>apacheds-test-framework</artifactId>
|
||||
<version>${apacheds.version}</version>
|
||||
<scope>test</scope>
|
||||
<exclusions>
|
||||
<exclusion>
|
||||
<groupId>junit</groupId>
|
||||
<artifactId>junit</artifactId>
|
||||
</exclusion>
|
||||
<!-- exclude additional LDIF schema files to avoid conflicts through
|
||||
multiple copies -->
|
||||
<exclusion>
|
||||
|
|
|
@ -27,4 +27,5 @@ module org.eclipse.jetty.jaas
|
|||
|
||||
// Only required if using JDBCLoginModule.
|
||||
requires static java.sql;
|
||||
requires org.eclipse.jetty.util;
|
||||
}
|
||||
|
|
|
@ -20,15 +20,16 @@ package org.eclipse.jetty.jaas;
|
|||
|
||||
import java.io.IOException;
|
||||
import java.security.Principal;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
import java.util.LinkedHashSet;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
import javax.security.auth.Subject;
|
||||
import javax.security.auth.callback.Callback;
|
||||
import javax.security.auth.callback.CallbackHandler;
|
||||
import javax.security.auth.callback.NameCallback;
|
||||
import javax.security.auth.callback.PasswordCallback;
|
||||
import javax.security.auth.callback.UnsupportedCallbackException;
|
||||
import javax.security.auth.login.Configuration;
|
||||
import javax.security.auth.login.FailedLoginException;
|
||||
|
@ -37,9 +38,6 @@ import javax.security.auth.login.LoginException;
|
|||
import javax.servlet.ServletRequest;
|
||||
|
||||
import org.eclipse.jetty.jaas.callback.DefaultCallbackHandler;
|
||||
import org.eclipse.jetty.jaas.callback.ObjectCallback;
|
||||
import org.eclipse.jetty.jaas.callback.RequestParameterCallback;
|
||||
import org.eclipse.jetty.jaas.callback.ServletRequestCallback;
|
||||
import org.eclipse.jetty.security.DefaultIdentityService;
|
||||
import org.eclipse.jetty.security.IdentityService;
|
||||
import org.eclipse.jetty.security.LoginService;
|
||||
|
@ -47,7 +45,7 @@ import org.eclipse.jetty.server.Request;
|
|||
import org.eclipse.jetty.server.UserIdentity;
|
||||
import org.eclipse.jetty.util.ArrayUtil;
|
||||
import org.eclipse.jetty.util.Loader;
|
||||
import org.eclipse.jetty.util.component.AbstractLifeCycle;
|
||||
import org.eclipse.jetty.util.component.ContainerLifeCycle;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
|
@ -58,13 +56,14 @@ import org.slf4j.LoggerFactory;
|
|||
* Implementation of jetty's LoginService that works with JAAS for
|
||||
* authorization and authentication.
|
||||
*/
|
||||
public class JAASLoginService extends AbstractLifeCycle implements LoginService
|
||||
public class JAASLoginService extends ContainerLifeCycle implements LoginService
|
||||
{
|
||||
private static final Logger LOG = LoggerFactory.getLogger(JAASLoginService.class);
|
||||
|
||||
public static final String DEFAULT_ROLE_CLASS_NAME = "org.eclipse.jetty.jaas.JAASRole";
|
||||
public static final String[] DEFAULT_ROLE_CLASS_NAMES = {DEFAULT_ROLE_CLASS_NAME};
|
||||
|
||||
public static final ThreadLocal<JAASLoginService> INSTANCE = new ThreadLocal<>();
|
||||
|
||||
protected String[] _roleClassNames = DEFAULT_ROLE_CLASS_NAMES;
|
||||
protected String _callbackHandlerClass;
|
||||
protected String _realmName;
|
||||
|
@ -183,6 +182,7 @@ public class JAASLoginService extends AbstractLifeCycle implements LoginService
|
|||
{
|
||||
if (_identityService == null)
|
||||
_identityService = new DefaultIdentityService();
|
||||
addBean(new PropertyUserStoreManager());
|
||||
super.doStart();
|
||||
}
|
||||
|
||||
|
@ -193,59 +193,27 @@ public class JAASLoginService extends AbstractLifeCycle implements LoginService
|
|||
{
|
||||
CallbackHandler callbackHandler = null;
|
||||
if (_callbackHandlerClass == null)
|
||||
{
|
||||
callbackHandler = new CallbackHandler()
|
||||
{
|
||||
@Override
|
||||
public void handle(Callback[] callbacks) throws IOException, UnsupportedCallbackException
|
||||
{
|
||||
for (Callback callback : callbacks)
|
||||
{
|
||||
if (callback instanceof NameCallback)
|
||||
{
|
||||
((NameCallback)callback).setName(username);
|
||||
}
|
||||
else if (callback instanceof PasswordCallback)
|
||||
{
|
||||
((PasswordCallback)callback).setPassword(credentials.toString().toCharArray());
|
||||
}
|
||||
else if (callback instanceof ObjectCallback)
|
||||
{
|
||||
((ObjectCallback)callback).setObject(credentials);
|
||||
}
|
||||
else if (callback instanceof RequestParameterCallback)
|
||||
{
|
||||
RequestParameterCallback rpc = (RequestParameterCallback)callback;
|
||||
if (request != null)
|
||||
rpc.setParameterValues(Arrays.asList(request.getParameterValues(rpc.getParameterName())));
|
||||
}
|
||||
else if (callback instanceof ServletRequestCallback)
|
||||
{
|
||||
((ServletRequestCallback)callback).setRequest(request);
|
||||
}
|
||||
else
|
||||
throw new UnsupportedCallbackException(callback);
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
callbackHandler = new DefaultCallbackHandler();
|
||||
else
|
||||
{
|
||||
Class<?> clazz = Loader.loadClass(_callbackHandlerClass);
|
||||
callbackHandler = (CallbackHandler)clazz.getDeclaredConstructor().newInstance();
|
||||
if (DefaultCallbackHandler.class.isAssignableFrom(clazz))
|
||||
{
|
||||
DefaultCallbackHandler dch = (DefaultCallbackHandler)callbackHandler;
|
||||
if (request instanceof Request)
|
||||
dch.setRequest((Request)request);
|
||||
dch.setCredential(credentials);
|
||||
dch.setUserName(username);
|
||||
}
|
||||
}
|
||||
|
||||
if (callbackHandler instanceof DefaultCallbackHandler)
|
||||
{
|
||||
DefaultCallbackHandler dch = (DefaultCallbackHandler)callbackHandler;
|
||||
if (request instanceof Request)
|
||||
dch.setRequest((Request)request);
|
||||
dch.setCredential(credentials);
|
||||
dch.setUserName(username);
|
||||
}
|
||||
|
||||
//set up the login context
|
||||
Subject subject = new Subject();
|
||||
LoginContext loginContext = (_configuration == null ? new LoginContext(_loginModuleName, subject, callbackHandler)
|
||||
INSTANCE.set(this);
|
||||
LoginContext loginContext =
|
||||
(_configuration == null ? new LoginContext(_loginModuleName, subject, callbackHandler)
|
||||
: new LoginContext(_loginModuleName, subject, callbackHandler, _configuration));
|
||||
|
||||
loginContext.login();
|
||||
|
@ -265,6 +233,10 @@ public class JAASLoginService extends AbstractLifeCycle implements LoginService
|
|||
{
|
||||
LOG.trace("IGNORED", e);
|
||||
}
|
||||
finally
|
||||
{
|
||||
INSTANCE.remove();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
|
@ -306,52 +278,36 @@ public class JAASLoginService extends AbstractLifeCycle implements LoginService
|
|||
protected String[] getGroups(Subject subject)
|
||||
{
|
||||
Collection<String> groups = new LinkedHashSet<>();
|
||||
Set<Principal> principals = subject.getPrincipals();
|
||||
for (Principal principal : principals)
|
||||
for (Principal principal : subject.getPrincipals())
|
||||
{
|
||||
Class<?> c = principal.getClass();
|
||||
while (c != null)
|
||||
{
|
||||
if (roleClassNameMatches(c.getName()))
|
||||
{
|
||||
groups.add(principal.getName());
|
||||
break;
|
||||
}
|
||||
|
||||
boolean added = false;
|
||||
for (Class<?> ci : c.getInterfaces())
|
||||
{
|
||||
if (roleClassNameMatches(ci.getName()))
|
||||
{
|
||||
groups.add(principal.getName());
|
||||
added = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!added)
|
||||
{
|
||||
c = c.getSuperclass();
|
||||
}
|
||||
else
|
||||
break;
|
||||
}
|
||||
if (isRoleClass(principal.getClass(), Arrays.asList(getRoleClassNames())))
|
||||
groups.add(principal.getName());
|
||||
}
|
||||
|
||||
return groups.toArray(new String[groups.size()]);
|
||||
}
|
||||
|
||||
private boolean roleClassNameMatches(String classname)
|
||||
|
||||
/**
|
||||
* Check whether the class, its superclasses or any interfaces they implement
|
||||
* is one of the classes that represents a role.
|
||||
*
|
||||
* @param clazz the class to check
|
||||
* @param roleClassNames the list of classnames that represent roles
|
||||
* @return true if the class is a role class
|
||||
*/
|
||||
private static boolean isRoleClass(Class<?> clazz, List<String> roleClassNames)
|
||||
{
|
||||
boolean result = false;
|
||||
for (String roleClassName : getRoleClassNames())
|
||||
Class<?> c = clazz;
|
||||
|
||||
//add the class, its interfaces and superclasses to the list to test
|
||||
List<String> classnames = new ArrayList<>();
|
||||
while (c != null)
|
||||
{
|
||||
if (roleClassName.equals(classname))
|
||||
{
|
||||
result = true;
|
||||
break;
|
||||
}
|
||||
classnames.add(c.getName());
|
||||
Arrays.stream(c.getInterfaces()).map(Class::getName).forEach(classnames::add);
|
||||
c = c.getSuperclass();
|
||||
}
|
||||
return result;
|
||||
|
||||
return roleClassNames.stream().anyMatch(classnames::contains);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,99 @@
|
|||
//
|
||||
// ========================================================================
|
||||
// Copyright (c) 1995-2020 Mort Bay Consulting Pty Ltd and others.
|
||||
//
|
||||
// This program and the accompanying materials are made available under
|
||||
// the terms of the Eclipse Public License 2.0 which is available at
|
||||
// https://www.eclipse.org/legal/epl-2.0
|
||||
//
|
||||
// This Source Code may also be made available under the following
|
||||
// Secondary Licenses when the conditions for such availability set
|
||||
// forth in the Eclipse Public License, v. 2.0 are satisfied:
|
||||
// the Apache License v2.0 which is available at
|
||||
// https://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// SPDX-License-Identifier: EPL-2.0 OR Apache-2.0
|
||||
// ========================================================================
|
||||
//
|
||||
|
||||
package org.eclipse.jetty.jaas;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
|
||||
import org.eclipse.jetty.security.PropertyUserStore;
|
||||
import org.eclipse.jetty.util.component.AbstractLifeCycle;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
/**
|
||||
* PropertyUserStoreManager
|
||||
*
|
||||
* Maintains a map of PropertyUserStores, keyed off the location of the property file containing
|
||||
* the authentication and authorization information.
|
||||
*
|
||||
* This class is used to enable the PropertyUserStores to be cached and shared. This is essential
|
||||
* for the PropertyFileLoginModules, whose lifecycle is controlled by the JAAS api and instantiated
|
||||
* afresh whenever a user needs to be authenticated. Without this class, every PropertyFileLoginModule
|
||||
* instantiation would re-read and reload in all the user information just to authenticate a single user.
|
||||
*/
|
||||
public class PropertyUserStoreManager extends AbstractLifeCycle
|
||||
{
|
||||
private static final Logger LOG = LoggerFactory.getLogger(PropertyUserStoreManager.class);
|
||||
/**
|
||||
* Map of user authentication and authorization information loaded in from a property file.
|
||||
* The map is keyed off the location of the file.
|
||||
*/
|
||||
private Map<String, PropertyUserStore> _propertyUserStores;
|
||||
|
||||
public PropertyUserStore getPropertyUserStore(String file)
|
||||
{
|
||||
synchronized (this)
|
||||
{
|
||||
if (_propertyUserStores == null)
|
||||
return null;
|
||||
|
||||
return _propertyUserStores.get(file);
|
||||
}
|
||||
}
|
||||
|
||||
public PropertyUserStore addPropertyUserStore(String file, PropertyUserStore store)
|
||||
{
|
||||
synchronized (this)
|
||||
{
|
||||
Objects.requireNonNull(_propertyUserStores);
|
||||
PropertyUserStore existing = _propertyUserStores.get(file);
|
||||
if (existing != null)
|
||||
return existing;
|
||||
|
||||
_propertyUserStores.put(file, store);
|
||||
return store;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void doStart() throws Exception
|
||||
{
|
||||
_propertyUserStores = new HashMap<String, PropertyUserStore>();
|
||||
super.doStart();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void doStop() throws Exception
|
||||
{
|
||||
for (Map.Entry<String,PropertyUserStore> entry: _propertyUserStores.entrySet())
|
||||
{
|
||||
try
|
||||
{
|
||||
entry.getValue().stop();
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
LOG.warn("Error stopping PropertyUserStore at {}", entry.getKey(), e);
|
||||
}
|
||||
}
|
||||
_propertyUserStores = null;
|
||||
super.doStop();
|
||||
}
|
||||
}
|
|
@ -26,7 +26,6 @@ import javax.security.auth.callback.PasswordCallback;
|
|||
import javax.security.auth.callback.UnsupportedCallbackException;
|
||||
|
||||
import org.eclipse.jetty.server.Request;
|
||||
import org.eclipse.jetty.util.security.Password;
|
||||
|
||||
/**
|
||||
* DefaultCallbackHandler
|
||||
|
@ -47,39 +46,34 @@ public class DefaultCallbackHandler extends AbstractCallbackHandler
|
|||
public void handle(Callback[] callbacks)
|
||||
throws IOException, UnsupportedCallbackException
|
||||
{
|
||||
for (int i = 0; i < callbacks.length; i++)
|
||||
for (Callback callback : callbacks)
|
||||
{
|
||||
if (callbacks[i] instanceof NameCallback)
|
||||
if (callback instanceof NameCallback)
|
||||
{
|
||||
((NameCallback)callbacks[i]).setName(getUserName());
|
||||
((NameCallback)callback).setName(getUserName());
|
||||
}
|
||||
else if (callbacks[i] instanceof ObjectCallback)
|
||||
else if (callback instanceof ObjectCallback)
|
||||
{
|
||||
((ObjectCallback)callbacks[i]).setObject(getCredential());
|
||||
((ObjectCallback)callback).setObject(getCredential());
|
||||
}
|
||||
else if (callbacks[i] instanceof PasswordCallback)
|
||||
else if (callback instanceof PasswordCallback)
|
||||
{
|
||||
if (getCredential() instanceof Password)
|
||||
((PasswordCallback)callbacks[i]).setPassword(((Password)getCredential()).toString().toCharArray());
|
||||
else if (getCredential() instanceof String)
|
||||
((PasswordCallback)callback).setPassword(getCredential().toString().toCharArray());
|
||||
}
|
||||
else if (callback instanceof RequestParameterCallback)
|
||||
{
|
||||
if (_request != null)
|
||||
{
|
||||
((PasswordCallback)callbacks[i]).setPassword(((String)getCredential()).toCharArray());
|
||||
RequestParameterCallback rpc = (RequestParameterCallback)callback;
|
||||
rpc.setParameterValues(Arrays.asList(_request.getParameterValues(rpc.getParameterName())));
|
||||
}
|
||||
else
|
||||
throw new UnsupportedCallbackException(callbacks[i], "User supplied credentials cannot be converted to char[] for PasswordCallback: try using an ObjectCallback instead");
|
||||
}
|
||||
else if (callbacks[i] instanceof RequestParameterCallback)
|
||||
else if (callback instanceof ServletRequestCallback)
|
||||
{
|
||||
RequestParameterCallback callback = (RequestParameterCallback)callbacks[i];
|
||||
callback.setParameterValues(Arrays.asList(_request.getParameterValues(callback.getParameterName())));
|
||||
}
|
||||
else if (callbacks[i] instanceof ServletRequestCallback)
|
||||
{
|
||||
((ServletRequestCallback)callbacks[i]).setRequest(_request);
|
||||
((ServletRequestCallback)callback).setRequest(_request);
|
||||
}
|
||||
else
|
||||
throw new UnsupportedCallbackException(callbacks[i]);
|
||||
throw new UnsupportedCallbackException(callback);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -21,11 +21,12 @@ package org.eclipse.jetty.jaas.spi;
|
|||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.stream.Collectors;
|
||||
import javax.security.auth.Subject;
|
||||
import javax.security.auth.callback.CallbackHandler;
|
||||
|
||||
import org.eclipse.jetty.jaas.JAASLoginService;
|
||||
import org.eclipse.jetty.jaas.PropertyUserStoreManager;
|
||||
import org.eclipse.jetty.security.AbstractLoginService;
|
||||
import org.eclipse.jetty.security.PropertyUserStore;
|
||||
import org.eclipse.jetty.server.UserIdentity;
|
||||
|
@ -39,16 +40,13 @@ import org.slf4j.LoggerFactory;
|
|||
public class PropertyFileLoginModule extends AbstractLoginModule
|
||||
{
|
||||
public static final String DEFAULT_FILENAME = "realm.properties";
|
||||
|
||||
private static final Logger LOG = LoggerFactory.getLogger(PropertyFileLoginModule.class);
|
||||
|
||||
private static ConcurrentHashMap<String, PropertyUserStore> _propertyUserStores = new ConcurrentHashMap<String, PropertyUserStore>();
|
||||
|
||||
private int _refreshInterval = 0;
|
||||
private String _filename = DEFAULT_FILENAME;
|
||||
private PropertyUserStore _store;
|
||||
|
||||
/**
|
||||
* Read contents of the configured property file.
|
||||
* Use a PropertyUserStore to read the authentication and authorizaton information contained in
|
||||
* the file named by the option "file".
|
||||
*
|
||||
* @param subject the subject
|
||||
* @param callbackHandler the callback handler
|
||||
|
@ -64,40 +62,61 @@ public class PropertyFileLoginModule extends AbstractLoginModule
|
|||
setupPropertyUserStore(options);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get an existing, or create a new PropertyUserStore to read the
|
||||
* authentication and authorization information from the file named by
|
||||
* the option "file".
|
||||
*
|
||||
* @param options configuration options
|
||||
*/
|
||||
private void setupPropertyUserStore(Map<String, ?> options)
|
||||
{
|
||||
parseConfig(options);
|
||||
String filename = (String)options.get("file");
|
||||
filename = (filename == null ? DEFAULT_FILENAME : filename);
|
||||
|
||||
if (_propertyUserStores.get(_filename) == null)
|
||||
PropertyUserStoreManager mgr = JAASLoginService.INSTANCE.get().getBean(PropertyUserStoreManager.class);
|
||||
if (mgr == null)
|
||||
throw new IllegalStateException("No PropertyUserStoreManager");
|
||||
|
||||
_store = mgr.getPropertyUserStore(filename);
|
||||
if (_store == null)
|
||||
{
|
||||
PropertyUserStore propertyUserStore = new PropertyUserStore();
|
||||
propertyUserStore.setConfig(_filename);
|
||||
|
||||
PropertyUserStore prev = _propertyUserStores.putIfAbsent(_filename, propertyUserStore);
|
||||
if (prev == null)
|
||||
boolean hotReload = false;
|
||||
String tmp = (String)options.get("hotReload");
|
||||
if (tmp != null)
|
||||
hotReload = Boolean.parseBoolean(tmp);
|
||||
else
|
||||
{
|
||||
LOG.debug("setupPropertyUserStore: Starting new PropertyUserStore. PropertiesFile: {} refreshInterval: {}", _filename, _refreshInterval);
|
||||
|
||||
try
|
||||
//refreshInterval is deprecated, use hotReload instead
|
||||
tmp = (String)options.get("refreshInterval");
|
||||
if (tmp != null)
|
||||
{
|
||||
propertyUserStore.start();
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
LOG.warn("Exception while starting propertyUserStore: ", e);
|
||||
LOG.warn("Use 'hotReload' boolean property instead of 'refreshInterval'");
|
||||
try
|
||||
{
|
||||
hotReload = (Integer.parseInt(tmp) > 0);
|
||||
}
|
||||
catch (NumberFormatException e)
|
||||
{
|
||||
LOG.warn("'refreshInterval' is not an integer");
|
||||
}
|
||||
}
|
||||
}
|
||||
PropertyUserStore newStore = new PropertyUserStore();
|
||||
newStore.setConfig(filename);
|
||||
newStore.setHotReload(hotReload);
|
||||
_store = mgr.addPropertyUserStore(filename, newStore);
|
||||
try
|
||||
{
|
||||
_store.start();
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
LOG.warn("Exception starting propertyUserStore {} ", filename, e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void parseConfig(Map<String, ?> options)
|
||||
{
|
||||
String tmp = (String)options.get("file");
|
||||
_filename = (tmp == null ? DEFAULT_FILENAME : tmp);
|
||||
tmp = (String)options.get("refreshInterval");
|
||||
_refreshInterval = (tmp == null ? _refreshInterval : Integer.parseInt(tmp));
|
||||
}
|
||||
|
||||
/**
|
||||
* @param userName the user name
|
||||
* @throws Exception if unable to get the user information
|
||||
|
@ -105,13 +124,8 @@ public class PropertyFileLoginModule extends AbstractLoginModule
|
|||
@Override
|
||||
public UserInfo getUserInfo(String userName) throws Exception
|
||||
{
|
||||
PropertyUserStore propertyUserStore = _propertyUserStores.get(_filename);
|
||||
if (propertyUserStore == null)
|
||||
throw new IllegalStateException("PropertyUserStore should never be null here!");
|
||||
|
||||
if (LOG.isDebugEnabled())
|
||||
LOG.debug("Checking PropertyUserStore {} for {}", _filename, userName);
|
||||
UserIdentity userIdentity = propertyUserStore.getUserIdentity(userName);
|
||||
LOG.debug("Checking PropertyUserStore {} for {}", _store.getConfig(), userName);
|
||||
UserIdentity userIdentity = _store.getUserIdentity(userName);
|
||||
if (userIdentity == null)
|
||||
return null;
|
||||
|
||||
|
@ -124,8 +138,6 @@ public class PropertyFileLoginModule extends AbstractLoginModule
|
|||
.collect(Collectors.toList());
|
||||
|
||||
Credential credential = (Credential)userIdentity.getSubject().getPrivateCredentials().iterator().next();
|
||||
if (LOG.isDebugEnabled())
|
||||
LOG.debug("Found: {} in PropertyUserStore {}", userName, _filename);
|
||||
return new UserInfo(userName, credential, roles);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -19,6 +19,7 @@
|
|||
package org.eclipse.jetty.jaas;
|
||||
|
||||
import java.security.Principal;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import javax.security.auth.Subject;
|
||||
import javax.security.auth.login.AppConfigurationEntry;
|
||||
|
@ -29,25 +30,17 @@ import org.eclipse.jetty.security.DefaultIdentityService;
|
|||
import org.eclipse.jetty.server.Request;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import static org.hamcrest.MatcherAssert.assertThat;
|
||||
import static org.hamcrest.Matchers.containsInAnyOrder;
|
||||
import static org.hamcrest.Matchers.is;
|
||||
import static org.hamcrest.Matchers.notNullValue;
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
import static org.junit.jupiter.api.Assertions.assertTrue;
|
||||
|
||||
/**
|
||||
* JAASLoginServiceTest
|
||||
*/
|
||||
public class JAASLoginServiceTest
|
||||
{
|
||||
public static class TestConfiguration extends Configuration
|
||||
{
|
||||
AppConfigurationEntry _entry = new AppConfigurationEntry(TestLoginModule.class.getCanonicalName(), LoginModuleControlFlag.REQUIRED, Collections.emptyMap());
|
||||
|
||||
@Override
|
||||
public AppConfigurationEntry[] getAppConfigurationEntry(String name)
|
||||
{
|
||||
return new AppConfigurationEntry[]{_entry};
|
||||
}
|
||||
}
|
||||
|
||||
interface SomeRole
|
||||
{
|
||||
|
||||
|
@ -94,18 +87,31 @@ public class JAASLoginServiceTest
|
|||
@Test
|
||||
public void testServletRequestCallback() throws Exception
|
||||
{
|
||||
Configuration config = new Configuration()
|
||||
{
|
||||
@Override
|
||||
public AppConfigurationEntry[] getAppConfigurationEntry(String name)
|
||||
{
|
||||
return new AppConfigurationEntry[] {
|
||||
new AppConfigurationEntry(TestLoginModule.class.getCanonicalName(),
|
||||
LoginModuleControlFlag.REQUIRED,
|
||||
Collections.emptyMap())
|
||||
};
|
||||
}
|
||||
};
|
||||
|
||||
//Test with the DefaultCallbackHandler
|
||||
JAASLoginService ls = new JAASLoginService("foo");
|
||||
ls.setCallbackHandlerClass("org.eclipse.jetty.jaas.callback.DefaultCallbackHandler");
|
||||
ls.setIdentityService(new DefaultIdentityService());
|
||||
ls.setConfiguration(new TestConfiguration());
|
||||
ls.setConfiguration(config);
|
||||
Request request = new Request(null, null);
|
||||
ls.login("aaardvaark", "aaa", request);
|
||||
|
||||
//Test with the fallback CallbackHandler
|
||||
ls = new JAASLoginService("foo");
|
||||
ls.setIdentityService(new DefaultIdentityService());
|
||||
ls.setConfiguration(new TestConfiguration());
|
||||
ls.setConfiguration(config);
|
||||
ls.login("aaardvaark", "aaa", request);
|
||||
}
|
||||
|
||||
|
@ -137,12 +143,8 @@ public class JAASLoginServiceTest
|
|||
subject.getPrincipals().add(new AnotherTestRole("z"));
|
||||
|
||||
String[] groups = ls.getGroups(subject);
|
||||
assertEquals(3, groups.length);
|
||||
for (String g : groups)
|
||||
{
|
||||
assertTrue(g.equals("x") || g.equals("y") || g.equals("z"));
|
||||
}
|
||||
|
||||
assertThat(Arrays.asList(groups), containsInAnyOrder("x", "y", "z"));
|
||||
|
||||
//test a custom role class
|
||||
ls.setRoleClassNames(new String[]{AnotherTestRole.class.getName()});
|
||||
Subject subject2 = new Subject();
|
||||
|
@ -150,8 +152,9 @@ public class JAASLoginServiceTest
|
|||
subject2.getPrincipals().add(new TestRole("x"));
|
||||
subject2.getPrincipals().add(new TestRole("y"));
|
||||
subject2.getPrincipals().add(new AnotherTestRole("z"));
|
||||
assertEquals(1, ls.getGroups(subject2).length);
|
||||
assertEquals("z", ls.getGroups(subject2)[0]);
|
||||
String[] s2groups = ls.getGroups(subject2);
|
||||
assertThat(s2groups, is(notNullValue()));
|
||||
assertThat(Arrays.asList(s2groups), containsInAnyOrder("z"));
|
||||
|
||||
//test a custom role class that implements an interface
|
||||
ls.setRoleClassNames(new String[]{SomeRole.class.getName()});
|
||||
|
@ -160,11 +163,9 @@ public class JAASLoginServiceTest
|
|||
subject3.getPrincipals().add(new TestRole("x"));
|
||||
subject3.getPrincipals().add(new TestRole("y"));
|
||||
subject3.getPrincipals().add(new AnotherTestRole("z"));
|
||||
assertEquals(3, ls.getGroups(subject3).length);
|
||||
for (String g : groups)
|
||||
{
|
||||
assertTrue(g.equals("x") || g.equals("y") || g.equals("z"));
|
||||
}
|
||||
String[] s3groups = ls.getGroups(subject3);
|
||||
assertThat(s3groups, is(notNullValue()));
|
||||
assertThat(Arrays.asList(s3groups), containsInAnyOrder("x", "y", "z"));
|
||||
|
||||
//test a class that doesn't match
|
||||
ls.setRoleClassNames(new String[]{NotTestRole.class.getName()});
|
||||
|
|
|
@ -19,34 +19,72 @@
|
|||
package org.eclipse.jetty.jaas.spi;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.HashMap;
|
||||
import javax.security.auth.Subject;
|
||||
import java.util.Collections;
|
||||
import javax.security.auth.login.AppConfigurationEntry;
|
||||
import javax.security.auth.login.AppConfigurationEntry.LoginModuleControlFlag;
|
||||
import javax.security.auth.login.Configuration;
|
||||
|
||||
import org.eclipse.jetty.jaas.callback.DefaultCallbackHandler;
|
||||
import org.eclipse.jetty.jaas.JAASLoginService;
|
||||
import org.eclipse.jetty.jaas.PropertyUserStoreManager;
|
||||
import org.eclipse.jetty.security.DefaultIdentityService;
|
||||
import org.eclipse.jetty.security.PropertyUserStore;
|
||||
import org.eclipse.jetty.server.Request;
|
||||
import org.eclipse.jetty.server.UserIdentity;
|
||||
import org.eclipse.jetty.toolchain.test.MavenTestingUtils;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import static org.hamcrest.MatcherAssert.assertThat;
|
||||
import static org.hamcrest.Matchers.contains;
|
||||
import static org.hamcrest.Matchers.containsInAnyOrder;
|
||||
import static org.hamcrest.Matchers.not;
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
import static org.hamcrest.Matchers.is;
|
||||
import static org.hamcrest.Matchers.notNullValue;
|
||||
import static org.hamcrest.Matchers.nullValue;
|
||||
|
||||
public class PropertyFileLoginModuleTest
|
||||
{
|
||||
@Test
|
||||
public void testRoles()
|
||||
throws Exception
|
||||
public void testPropertyFileLoginModule() throws Exception
|
||||
{
|
||||
File file = MavenTestingUtils.getTestResourceFile("login.properties");
|
||||
PropertyFileLoginModule module = new PropertyFileLoginModule();
|
||||
Subject subject = new Subject();
|
||||
HashMap<String, String> options = new HashMap<>();
|
||||
options.put("file", file.getCanonicalPath());
|
||||
module.initialize(subject, new DefaultCallbackHandler(), new HashMap<String, String>(), options);
|
||||
UserInfo fred = module.getUserInfo("fred");
|
||||
assertEquals("fred", fred.getUserName());
|
||||
assertThat(fred.getRoleNames(), containsInAnyOrder("role1", "role2", "role3"));
|
||||
assertThat(fred.getRoleNames(), not(contains("fred")));
|
||||
//configure for PropertyFileLoginModule
|
||||
File loginProperties = MavenTestingUtils.getTestResourceFile("login.properties");
|
||||
|
||||
Configuration testConfig = new Configuration()
|
||||
{
|
||||
@Override
|
||||
public AppConfigurationEntry[] getAppConfigurationEntry(String name)
|
||||
{
|
||||
return new AppConfigurationEntry[]{new AppConfigurationEntry(PropertyFileLoginModule.class.getName(),
|
||||
LoginModuleControlFlag.REQUIRED,
|
||||
Collections.singletonMap("file", loginProperties.getAbsolutePath()))};
|
||||
}
|
||||
};
|
||||
|
||||
JAASLoginService ls = new JAASLoginService("foo");
|
||||
ls.setCallbackHandlerClass("org.eclipse.jetty.jaas.callback.DefaultCallbackHandler");
|
||||
ls.setIdentityService(new DefaultIdentityService());
|
||||
ls.setConfiguration(testConfig);
|
||||
ls.start();
|
||||
|
||||
//test that the manager is created when the JAASLoginService starts
|
||||
PropertyUserStoreManager mgr = ls.getBean(PropertyUserStoreManager.class);
|
||||
assertThat(mgr, notNullValue());
|
||||
|
||||
//test the PropertyFileLoginModule authentication and authorization
|
||||
Request request = new Request(null, null);
|
||||
UserIdentity uid = ls.login("fred", "pwd", request);
|
||||
assertThat(uid.isUserInRole("role1", null), is(true));
|
||||
assertThat(uid.isUserInRole("role2", null), is(true));
|
||||
assertThat(uid.isUserInRole("role3", null), is(true));
|
||||
assertThat(uid.isUserInRole("role4", null), is(false));
|
||||
|
||||
//Test that the PropertyUserStore is created by the PropertyFileLoginModule
|
||||
PropertyUserStore store = mgr.getPropertyUserStore(loginProperties.getAbsolutePath());
|
||||
assertThat(store, is(notNullValue()));
|
||||
assertThat(store.isRunning(), is(true));
|
||||
assertThat(store.isHotReload(), is(false));
|
||||
|
||||
//test that the PropertyUserStoreManager is stopped and all PropertyUserStores stopped
|
||||
ls.stop();
|
||||
assertThat(mgr.isStopped(), is(true));
|
||||
assertThat(mgr.getPropertyUserStore(loginProperties.getAbsolutePath()), is(nullValue()));
|
||||
assertThat(store.isStopped(), is(true));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,127 @@
|
|||
//
|
||||
// ========================================================================
|
||||
// Copyright (c) 1995-2020 Mort Bay Consulting Pty Ltd and others.
|
||||
//
|
||||
// This program and the accompanying materials are made available under
|
||||
// the terms of the Eclipse Public License 2.0 which is available at
|
||||
// https://www.eclipse.org/legal/epl-2.0
|
||||
//
|
||||
// This Source Code may also be made available under the following
|
||||
// Secondary Licenses when the conditions for such availability set
|
||||
// forth in the Eclipse Public License, v. 2.0 are satisfied:
|
||||
// the Apache License v2.0 which is available at
|
||||
// https://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// SPDX-License-Identifier: EPL-2.0 OR Apache-2.0
|
||||
// ========================================================================
|
||||
//
|
||||
|
||||
package org.eclipse.jetty.http.jmh;
|
||||
|
||||
import java.nio.ByteBuffer;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
import org.eclipse.jetty.http.HttpMethod;
|
||||
import org.eclipse.jetty.util.BufferUtil;
|
||||
import org.openjdk.jmh.annotations.Benchmark;
|
||||
import org.openjdk.jmh.annotations.BenchmarkMode;
|
||||
import org.openjdk.jmh.annotations.Measurement;
|
||||
import org.openjdk.jmh.annotations.Mode;
|
||||
import org.openjdk.jmh.annotations.Scope;
|
||||
import org.openjdk.jmh.annotations.State;
|
||||
import org.openjdk.jmh.annotations.Threads;
|
||||
import org.openjdk.jmh.annotations.Warmup;
|
||||
import org.openjdk.jmh.profile.GCProfiler;
|
||||
import org.openjdk.jmh.runner.Runner;
|
||||
import org.openjdk.jmh.runner.RunnerException;
|
||||
import org.openjdk.jmh.runner.options.Options;
|
||||
import org.openjdk.jmh.runner.options.OptionsBuilder;
|
||||
|
||||
@State(Scope.Benchmark)
|
||||
@Threads(4)
|
||||
@Warmup(iterations = 5, time = 2000, timeUnit = TimeUnit.MILLISECONDS)
|
||||
@Measurement(iterations = 5, time = 2000, timeUnit = TimeUnit.MILLISECONDS)
|
||||
public class HttpMethodBenchmark
|
||||
{
|
||||
private static final ByteBuffer GET = BufferUtil.toBuffer("GET / HTTP/1.1\r\n\r\n");
|
||||
private static final ByteBuffer POST = BufferUtil.toBuffer("POST / HTTP/1.1\r\n\r\n");
|
||||
private static final ByteBuffer MOVE = BufferUtil.toBuffer("MOVE / HTTP/1.1\r\n\r\n");
|
||||
private static final Map<String, HttpMethod> MAP = new HashMap<>();
|
||||
|
||||
static
|
||||
{
|
||||
for (HttpMethod m : HttpMethod.values())
|
||||
MAP.put(m.asString(), m);
|
||||
}
|
||||
|
||||
@Benchmark
|
||||
@BenchmarkMode({Mode.Throughput})
|
||||
public HttpMethod testTrieGetBest() throws Exception
|
||||
{
|
||||
return HttpMethod.LOOK_AHEAD.getBest(GET, 0, GET.remaining());
|
||||
}
|
||||
|
||||
@Benchmark
|
||||
@BenchmarkMode({Mode.Throughput})
|
||||
public HttpMethod testIntSwitch() throws Exception
|
||||
{
|
||||
switch (GET.getInt(0))
|
||||
{
|
||||
case HttpMethod.ACL_AS_INT:
|
||||
return HttpMethod.ACL;
|
||||
case HttpMethod.GET_AS_INT:
|
||||
return HttpMethod.GET;
|
||||
case HttpMethod.PRI_AS_INT:
|
||||
return HttpMethod.PRI;
|
||||
case HttpMethod.PUT_AS_INT:
|
||||
return HttpMethod.PUT;
|
||||
default:
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
@Benchmark
|
||||
@BenchmarkMode({Mode.Throughput})
|
||||
public HttpMethod testMapGet() throws Exception
|
||||
{
|
||||
for (int i = 0; i < GET.remaining(); i++)
|
||||
{
|
||||
if (GET.get(i) == (byte)' ')
|
||||
return MAP.get(BufferUtil.toString(GET, 0, i, StandardCharsets.US_ASCII));
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Benchmark
|
||||
@BenchmarkMode({Mode.Throughput})
|
||||
public HttpMethod testHttpMethodPost() throws Exception
|
||||
{
|
||||
return HttpMethod.lookAheadGet(POST);
|
||||
}
|
||||
|
||||
@Benchmark
|
||||
@BenchmarkMode({Mode.Throughput})
|
||||
public HttpMethod testHttpMethodMove() throws Exception
|
||||
{
|
||||
return HttpMethod.lookAheadGet(MOVE);
|
||||
}
|
||||
|
||||
public static void main(String[] args) throws RunnerException
|
||||
{
|
||||
Options opt = new OptionsBuilder()
|
||||
.include(HttpMethodBenchmark.class.getSimpleName())
|
||||
.warmupIterations(10)
|
||||
.measurementIterations(10)
|
||||
.addProfiler(GCProfiler.class)
|
||||
.forks(1)
|
||||
.threads(1)
|
||||
.build();
|
||||
|
||||
new Runner(opt).run();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -2,7 +2,7 @@
|
|||
<!DOCTYPE Configure PUBLIC "-//Jetty//Configure//EN" "https://www.eclipse.org/jetty/configure_9_3.dtd">
|
||||
|
||||
<Configure id="Server" class="org.eclipse.jetty.server.Server">
|
||||
<Ref id="httpConnector">
|
||||
<Ref refid="httpConnector">
|
||||
<Call name="addEventListener">
|
||||
<Arg>
|
||||
<New class="org.eclipse.jetty.maven.plugin.ServerConnectorListener">
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
<!DOCTYPE Configure PUBLIC "-//Jetty//Configure//EN" "https://www.eclipse.org/jetty/configure_9_3.dtd">
|
||||
|
||||
<Configure id="Server" class="org.eclipse.jetty.server.Server">
|
||||
<Ref id="httpConnector">
|
||||
<Ref refid="httpConnector">
|
||||
<Call name="addEventListener">
|
||||
<Arg>
|
||||
<New class="org.eclipse.jetty.maven.plugin.ServerConnectorListener">
|
||||
|
|
|
@ -19,7 +19,7 @@
|
|||
<dependency>
|
||||
<groupId>com.googlecode.xmemcached</groupId>
|
||||
<artifactId>xmemcached</artifactId>
|
||||
<version>2.4.5</version>
|
||||
<version>2.4.6</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.slf4j</groupId>
|
||||
|
|
|
@ -193,7 +193,7 @@
|
|||
<dependency>
|
||||
<groupId>org.glassfish.web</groupId>
|
||||
<artifactId>javax.servlet.jsp.jstl</artifactId>
|
||||
<version>1.2.2</version>
|
||||
<version>1.2.5</version>
|
||||
<exclusions>
|
||||
<exclusion>
|
||||
<groupId>javax.servlet.jsp.jstl</groupId>
|
||||
|
|
|
@ -1,6 +1,10 @@
|
|||
<?xml version="1.0"?><!DOCTYPE Configure PUBLIC "-//Jetty//Configure//EN" "http://www.eclipse.org/jetty/configure_9_3.dtd">
|
||||
|
||||
<!-- ============================================================= --><!-- Configure the Jetty Server instance with an ID "Server" --><!-- by adding an HTTP connector. --><!-- This configuration must be used in conjunction with jetty.xml --><!-- ============================================================= -->
|
||||
<!-- ============================================================= -->
|
||||
<!-- Configure the Jetty Server instance with an ID "Server" -->
|
||||
<!-- by adding an HTTP connector. -->
|
||||
<!-- This configuration must be used in conjunction with jetty.xml -->
|
||||
<!-- ============================================================= -->
|
||||
<Configure id="Server" class="org.eclipse.jetty.server.Server">
|
||||
|
||||
<!-- =========================================================== -->
|
||||
|
|
|
@ -4,5 +4,4 @@
|
|||
<!-- ============================================================= -->
|
||||
<!-- Display a Warning Message if {jetty.home} == {jetty.base} -->
|
||||
<!-- ============================================================= -->
|
||||
<Configure id="homeBaseWarning" class="org.eclipse.jetty.server.HomeBaseWarning">
|
||||
</Configure>
|
||||
<Configure id="homeBaseWarning" class="org.eclipse.jetty.server.HomeBaseWarning"/>
|
||||
|
|
|
@ -3,7 +3,6 @@
|
|||
|
||||
<Configure id="Server" class="org.eclipse.jetty.server.Server">
|
||||
|
||||
|
||||
<!-- ===================================================================== -->
|
||||
<!-- Configure a factory for FileSessionStores -->
|
||||
<!-- ===================================================================== -->
|
||||
|
|
|
@ -2,10 +2,10 @@
|
|||
<!DOCTYPE Configure PUBLIC "-//Jetty//Configure//EN" "https://www.eclipse.org/jetty/configure_10_0.dtd">
|
||||
|
||||
<Configure id="Server" class="org.eclipse.jetty.server.Server">
|
||||
<New id="databaseAdaptor" class="org.eclipse.jetty.server.session.DatabaseAdaptor">
|
||||
<Set name="DatasourceName" property="jetty.session.jdbc.datasourceName"/>
|
||||
<Set name="blobType" property="jetty.session.jdbc.blobType"/>
|
||||
<Set name="longType" property="jetty.session.jdbc.longType"/>
|
||||
<Set name="stringType" property="jetty.session.jdbc.stringType"/>
|
||||
</New>
|
||||
<New id="databaseAdaptor" class="org.eclipse.jetty.server.session.DatabaseAdaptor">
|
||||
<Set name="DatasourceName" property="jetty.session.jdbc.datasourceName"/>
|
||||
<Set name="blobType" property="jetty.session.jdbc.blobType"/>
|
||||
<Set name="longType" property="jetty.session.jdbc.longType"/>
|
||||
<Set name="stringType" property="jetty.session.jdbc.stringType"/>
|
||||
</New>
|
||||
</Configure>
|
||||
|
|
|
@ -3,14 +3,14 @@
|
|||
|
||||
<Configure id="Server" class="org.eclipse.jetty.server.Server">
|
||||
|
||||
<New id="databaseAdaptor" class="org.eclipse.jetty.server.session.DatabaseAdaptor">
|
||||
<Call name="setDriverInfo">
|
||||
<Arg><Property name="jetty.session.jdbc.driverClass"/></Arg>
|
||||
<Arg><Property name="jetty.session.jdbc.driverUrl"/></Arg>
|
||||
</Call>
|
||||
<Set name="blobType" property="jetty.session.jdbc.blobType"/>
|
||||
<Set name="longType" property="jetty.session.jdbc.longType"/>
|
||||
<Set name="stringType" property="jetty.session.jdbc.stringType"/>
|
||||
</New>
|
||||
<New id="databaseAdaptor" class="org.eclipse.jetty.server.session.DatabaseAdaptor">
|
||||
<Call name="setDriverInfo">
|
||||
<Arg><Property name="jetty.session.jdbc.driverClass"/></Arg>
|
||||
<Arg><Property name="jetty.session.jdbc.driverUrl"/></Arg>
|
||||
</Call>
|
||||
<Set name="blobType" property="jetty.session.jdbc.blobType"/>
|
||||
<Set name="longType" property="jetty.session.jdbc.longType"/>
|
||||
<Set name="stringType" property="jetty.session.jdbc.stringType"/>
|
||||
</New>
|
||||
|
||||
</Configure>
|
||||
|
|
|
@ -1,72 +1,69 @@
|
|||
<?xml version="1.0"?>
|
||||
<!DOCTYPE Configure PUBLIC "-//Jetty//Configure//EN" "https://www.eclipse.org/jetty/configure_10_0.dtd">
|
||||
<?xml version="1.0"?><!DOCTYPE Configure PUBLIC "-//Jetty//Configure//EN" "https://www.eclipse.org/jetty/configure_10_0.dtd">
|
||||
|
||||
<Configure id="Server" class="org.eclipse.jetty.server.Server">
|
||||
|
||||
|
||||
<!-- ===================================================================== -->
|
||||
<!-- Configure a factory for JDBCSessionStores -->
|
||||
<!-- ===================================================================== -->
|
||||
<Call name="addBean">
|
||||
<Arg>
|
||||
<New id="sessionDataStoreFactory" class="org.eclipse.jetty.server.session.JDBCSessionDataStoreFactory">
|
||||
<Set name="gracePeriodSec"><Property name="jetty.session.gracePeriod.seconds" default="3600" /></Set>
|
||||
<Set name="savePeriodSec"><Property name="jetty.session.savePeriod.seconds" default="0" /></Set>
|
||||
<Set name="databaseAdaptor">
|
||||
<Ref id="databaseAdaptor"/>
|
||||
</Set>
|
||||
<Set name="sessionTableSchema">
|
||||
<New
|
||||
class="org.eclipse.jetty.server.session.JDBCSessionDataStore$SessionTableSchema">
|
||||
<Set name="accessTimeColumn">
|
||||
<Property name="jetty.session.jdbc.schema.accessTimeColumn" default="accessTime" />
|
||||
</Set>
|
||||
<Set name="contextPathColumn">
|
||||
<Property name="jetty.session.jdbc.schema.contextPathColumn" default="contextPath" />
|
||||
</Set>
|
||||
<Set name="cookieTimeColumn">
|
||||
<Property name="jetty.session.jdbc.schema.cookieTimeColumn" default="cookieTime" />
|
||||
</Set>
|
||||
<Set name="createTimeColumn">
|
||||
<Property name="jetty.session.jdbc.schema.createTimeColumn" default="createTime" />
|
||||
</Set>
|
||||
<Set name="expiryTimeColumn">
|
||||
<Property name="jetty.session.jdbc.schema.expiryTimeColumn" default="expiryTime" />
|
||||
</Set>
|
||||
<Set name="lastAccessTimeColumn">
|
||||
<Property name="jetty.session.jdbc.schema.lastAccessTimeColumn" default="lastAccessTime" />
|
||||
</Set>
|
||||
<Set name="lastSavedTimeColumn">
|
||||
<Property name="jetty.session.jdbc.schema.lastSavedTimeColumn" default="lastSavedTime" />
|
||||
</Set>
|
||||
<Set name="idColumn">
|
||||
<Property name="jetty.session.jdbc.schema.idColumn" default="sessionId" />
|
||||
</Set>
|
||||
<Set name="lastNodeColumn">
|
||||
<Property name="jetty.session.jdbc.schema.lastNodeColumn" default="lastNode" />
|
||||
</Set>
|
||||
<Set name="virtualHostColumn">
|
||||
<Property name="jetty.session.jdbc.schema.virtualHostColumn" default="virtualHost" />
|
||||
</Set>
|
||||
<Set name="maxIntervalColumn">
|
||||
<Property name="jetty.session.jdbc.schema.maxIntervalColumn" default="maxInterval" />
|
||||
</Set>
|
||||
<Set name="mapColumn">
|
||||
<Property name="jetty.session.jdbc.schema.mapColumn" default="map" />
|
||||
</Set>
|
||||
<Arg>
|
||||
<New id="sessionDataStoreFactory" class="org.eclipse.jetty.server.session.JDBCSessionDataStoreFactory">
|
||||
<Set name="gracePeriodSec"><Property name="jetty.session.gracePeriod.seconds" default="3600" /></Set>
|
||||
<Set name="savePeriodSec"><Property name="jetty.session.savePeriod.seconds" default="0" /></Set>
|
||||
<Set name="databaseAdaptor">
|
||||
<Ref refid="databaseAdaptor" />
|
||||
</Set>
|
||||
<Set name="sessionTableSchema">
|
||||
<New class="org.eclipse.jetty.server.session.JDBCSessionDataStore$SessionTableSchema">
|
||||
<Set name="accessTimeColumn">
|
||||
<Property name="jetty.session.jdbc.schema.accessTimeColumn" default="accessTime" />
|
||||
</Set>
|
||||
<Set name="contextPathColumn">
|
||||
<Property name="jetty.session.jdbc.schema.contextPathColumn" default="contextPath" />
|
||||
</Set>
|
||||
<Set name="cookieTimeColumn">
|
||||
<Property name="jetty.session.jdbc.schema.cookieTimeColumn" default="cookieTime" />
|
||||
</Set>
|
||||
<Set name="createTimeColumn">
|
||||
<Property name="jetty.session.jdbc.schema.createTimeColumn" default="createTime" />
|
||||
</Set>
|
||||
<Set name="expiryTimeColumn">
|
||||
<Property name="jetty.session.jdbc.schema.expiryTimeColumn" default="expiryTime" />
|
||||
</Set>
|
||||
<Set name="lastAccessTimeColumn">
|
||||
<Property name="jetty.session.jdbc.schema.lastAccessTimeColumn" default="lastAccessTime" />
|
||||
</Set>
|
||||
<Set name="lastSavedTimeColumn">
|
||||
<Property name="jetty.session.jdbc.schema.lastSavedTimeColumn" default="lastSavedTime" />
|
||||
</Set>
|
||||
<Set name="idColumn">
|
||||
<Property name="jetty.session.jdbc.schema.idColumn" default="sessionId" />
|
||||
</Set>
|
||||
<Set name="lastNodeColumn">
|
||||
<Property name="jetty.session.jdbc.schema.lastNodeColumn" default="lastNode" />
|
||||
</Set>
|
||||
<Set name="virtualHostColumn">
|
||||
<Property name="jetty.session.jdbc.schema.virtualHostColumn" default="virtualHost" />
|
||||
</Set>
|
||||
<Set name="maxIntervalColumn">
|
||||
<Property name="jetty.session.jdbc.schema.maxIntervalColumn" default="maxInterval" />
|
||||
</Set>
|
||||
<Set name="mapColumn">
|
||||
<Property name="jetty.session.jdbc.schema.mapColumn" default="map" />
|
||||
</Set>
|
||||
<Set name="schemaName">
|
||||
<Property name="jetty.session.jdbc.schema.schemaName" />
|
||||
<Property name="jetty.session.jdbc.schema.schemaName" />
|
||||
</Set>
|
||||
<Set name="catalogName">
|
||||
<Property name="jetty.session.jdbc.schema.catalogName" />
|
||||
<Property name="jetty.session.jdbc.schema.catalogName" />
|
||||
</Set>
|
||||
<Set name="tableName">
|
||||
<Property name="jetty.session.jdbc.schema.table" default="JettySessions" />
|
||||
</Set>
|
||||
</New>
|
||||
</Set>
|
||||
</New>
|
||||
</Arg>
|
||||
<Set name="tableName">
|
||||
<Property name="jetty.session.jdbc.schema.table" default="JettySessions" />
|
||||
</Set>
|
||||
</New>
|
||||
</Set>
|
||||
</New>
|
||||
</Arg>
|
||||
</Call>
|
||||
|
||||
</Configure>
|
||||
|
|
|
@ -3,21 +3,20 @@
|
|||
|
||||
<Configure id="Server" class="org.eclipse.jetty.server.Server">
|
||||
|
||||
|
||||
<!-- ===================================================================== -->
|
||||
<!-- Configure a factory for DefaultSessionCache -->
|
||||
<!-- ===================================================================== -->
|
||||
<Call name="addBean">
|
||||
<Arg>
|
||||
<New class="org.eclipse.jetty.server.session.DefaultSessionCacheFactory">
|
||||
<Set name="evictionPolicy"><Property name="jetty.session.evictionPolicy" default="-1" /></Set>
|
||||
<Set name="saveOnInactiveEvict"><Property name="jetty.session.saveOnInactiveEvict" default="false" /></Set>
|
||||
<Set name="saveOnCreate"><Property name="jetty.session.saveOnCreate" default="false" /></Set>
|
||||
<Set name="removeUnloadableSessions"><Property name="jetty.session.removeUnloadableSessions" default="false"/></Set>
|
||||
<Set name="flushOnResponseCommit"><Property name="jetty.session.flushOnResponseCommit" default="false"/></Set>
|
||||
<Set name="invalidateOnShutdown"><Property name="jetty.session.invalidateOnShutdown" default="false"/></Set>
|
||||
</New>
|
||||
</Arg>
|
||||
<Arg>
|
||||
<New class="org.eclipse.jetty.server.session.DefaultSessionCacheFactory">
|
||||
<Set name="evictionPolicy"><Property name="jetty.session.evictionPolicy" default="-1" /></Set>
|
||||
<Set name="saveOnInactiveEvict"><Property name="jetty.session.saveOnInactiveEvict" default="false" /></Set>
|
||||
<Set name="saveOnCreate"><Property name="jetty.session.saveOnCreate" default="false" /></Set>
|
||||
<Set name="removeUnloadableSessions"><Property name="jetty.session.removeUnloadableSessions" default="false"/></Set>
|
||||
<Set name="flushOnResponseCommit"><Property name="jetty.session.flushOnResponseCommit" default="false"/></Set>
|
||||
<Set name="invalidateOnShutdown"><Property name="jetty.session.invalidateOnShutdown" default="false"/></Set>
|
||||
</New>
|
||||
</Arg>
|
||||
</Call>
|
||||
|
||||
</Configure>
|
||||
|
|
|
@ -3,18 +3,17 @@
|
|||
|
||||
<Configure id="Server" class="org.eclipse.jetty.server.Server">
|
||||
|
||||
|
||||
<!-- ===================================================================== -->
|
||||
<!-- Configure a factory for NullSessionCache -->
|
||||
<!-- ===================================================================== -->
|
||||
<Call name="addBean">
|
||||
<Arg>
|
||||
<New class="org.eclipse.jetty.server.session.NullSessionCacheFactory">
|
||||
<Set name="saveOnCreate"><Property name="jetty.session.saveOnCreate" default="false" /></Set>
|
||||
<Set name="removeUnloadableSessions"><Property name="jetty.session.removeUnloadableSessions" default="false"/></Set>
|
||||
<Set name="flushOnResponseCommit"><Property name="jetty.session.flushOnResponseCommit" default="false"/></Set>
|
||||
</New>
|
||||
</Arg>
|
||||
<Arg>
|
||||
<New class="org.eclipse.jetty.server.session.NullSessionCacheFactory">
|
||||
<Set name="saveOnCreate"><Property name="jetty.session.saveOnCreate" default="false" /></Set>
|
||||
<Set name="removeUnloadableSessions"><Property name="jetty.session.removeUnloadableSessions" default="false" /></Set>
|
||||
<Set name="flushOnResponseCommit"><Property name="jetty.session.flushOnResponseCommit" default="false" /></Set>
|
||||
</New>
|
||||
</Arg>
|
||||
</Call>
|
||||
|
||||
</Configure>
|
||||
|
|
|
@ -13,8 +13,6 @@
|
|||
</Arg>
|
||||
</Call>
|
||||
|
||||
|
||||
|
||||
<Call name="addBean">
|
||||
<Arg>
|
||||
<New class="org.eclipse.jetty.server.session.CachingSessionDataStoreFactory">
|
||||
|
|
|
@ -2,38 +2,38 @@
|
|||
<!DOCTYPE Configure PUBLIC "-//Jetty//Configure//EN" "https://www.eclipse.org/jetty/configure_10_0.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>
|
||||
<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>
|
||||
|
|
|
@ -1227,7 +1227,7 @@ public class ServletHolder extends Holder<Servlet> implements UserIdentity.Scope
|
|||
public void service(ServletRequest req, ServletResponse res) throws ServletException, IOException
|
||||
{
|
||||
if (LOG.isDebugEnabled())
|
||||
LOG.debug("Unavailable {}", req, _unavailableException);
|
||||
LOG.debug("Unavailable {}", req, _unavailableException);
|
||||
if (_unavailableStart == null)
|
||||
{
|
||||
((HttpServletResponse)res).sendError(HttpServletResponse.SC_NOT_FOUND);
|
||||
|
|
|
@ -368,6 +368,12 @@ public class ArrayTernaryTrie<V> extends AbstractTrie<V>
|
|||
return getBest(0, b, offset, len);
|
||||
}
|
||||
|
||||
@Override
|
||||
public V getBest(byte[] b, int offset, int len)
|
||||
{
|
||||
return getBest(0, b, offset, len);
|
||||
}
|
||||
|
||||
private V getBest(int t, byte[] b, int offset, int len)
|
||||
{
|
||||
int node = t;
|
||||
|
|
|
@ -301,7 +301,7 @@ public class WebInfConfiguration extends AbstractConfiguration
|
|||
if (webApp.isAlias())
|
||||
{
|
||||
if (LOG.isDebugEnabled())
|
||||
LOG.debug("{} anti-aliased to {}", webApp, webApp.getAlias());
|
||||
LOG.debug("{} anti-aliased to {}", webApp, webApp.getAlias());
|
||||
webApp = context.newResource(webApp.getAlias());
|
||||
}
|
||||
|
||||
|
@ -431,7 +431,7 @@ public class WebInfConfiguration extends AbstractConfiguration
|
|||
webInfLibDir.mkdir();
|
||||
|
||||
if (LOG.isDebugEnabled())
|
||||
LOG.debug("Copying WEB-INF/lib {} to {}", webInfLib, webInfLibDir);
|
||||
LOG.debug("Copying WEB-INF/lib {} to {}", webInfLib, webInfLibDir);
|
||||
webInfLib.copyTo(webInfLibDir);
|
||||
}
|
||||
|
||||
|
|
38
pom.xml
38
pom.xml
|
@ -18,7 +18,7 @@
|
|||
<jetty.url>https://www.eclipse.org/jetty/</jetty.url>
|
||||
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
||||
<build-support.version>1.5</build-support.version>
|
||||
<checkstyle.version>8.36.2</checkstyle.version>
|
||||
<checkstyle.version>8.37</checkstyle.version>
|
||||
<slf4j.version>2.0.0-alpha1</slf4j.version>
|
||||
<log4j2.version>2.13.0</log4j2.version>
|
||||
<logback.version>1.3.0-alpha5</logback.version>
|
||||
|
@ -31,12 +31,12 @@
|
|||
<infinispan.protostream.version>4.3.4.Final</infinispan.protostream.version>
|
||||
<gson.version>2.8.6</gson.version>
|
||||
<alpn.agent.version>2.0.10</alpn.agent.version>
|
||||
<hazelcast.version>4.0.1</hazelcast.version>
|
||||
<hazelcast.version>4.1</hazelcast.version>
|
||||
<conscrypt.version>2.5.1</conscrypt.version>
|
||||
<asm.version>9.0</asm.version>
|
||||
<jmh.version>1.26</jmh.version>
|
||||
<jmhjar.name>benchmarks</jmhjar.name>
|
||||
<tycho-version>2.0.0</tycho-version>
|
||||
<tycho-version>2.1.0</tycho-version>
|
||||
<junit.version>5.7.0</junit.version>
|
||||
<maven.version>3.6.3</maven.version>
|
||||
<maven.resolver.version>1.6.1</maven.resolver.version>
|
||||
|
@ -56,7 +56,7 @@
|
|||
<maven.resources.plugin.version>3.2.0</maven.resources.plugin.version>
|
||||
<maven.source.plugin.version>3.2.1</maven.source.plugin.version>
|
||||
<maven.war.plugin.version>3.3.1</maven.war.plugin.version>
|
||||
<maven.plugin-tools.version>3.5.2</maven.plugin-tools.version>
|
||||
<maven.plugin-tools.version>3.6.0</maven.plugin-tools.version>
|
||||
<maven.install.plugin.version>3.0.0-M1</maven.install.plugin.version>
|
||||
<maven.deploy.plugin.version>3.0.0-M1</maven.deploy.plugin.version>
|
||||
|
||||
|
@ -74,7 +74,8 @@
|
|||
<settingsPath>src/it/settings.xml</settingsPath>
|
||||
<invoker.mergeUserSettings>false</invoker.mergeUserSettings>
|
||||
<surefire.rerunFailingTestsCount>0</surefire.rerunFailingTestsCount>
|
||||
<testcontainers.version>1.15.0-rc2</testcontainers.version>
|
||||
<testcontainers.version>1.15.0</testcontainers.version>
|
||||
<derby.version>10.14.2.0</derby.version>
|
||||
</properties>
|
||||
|
||||
<licenses>
|
||||
|
@ -506,7 +507,7 @@
|
|||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-enforcer-plugin</artifactId>
|
||||
<version>3.0.0-M2</version>
|
||||
<version>3.0.0-M3</version>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
|
@ -600,7 +601,7 @@
|
|||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-project-info-reports-plugin</artifactId>
|
||||
<version>3.0.0</version>
|
||||
<version>3.1.1</version>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
|
@ -625,7 +626,7 @@
|
|||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-site-plugin</artifactId>
|
||||
<version>3.7.1</version>
|
||||
<version>3.9.1</version>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
|
@ -702,7 +703,7 @@
|
|||
<plugin>
|
||||
<groupId>org.apache.felix</groupId>
|
||||
<artifactId>maven-bundle-plugin</artifactId>
|
||||
<version>3.5.1</version>
|
||||
<version>5.1.1</version>
|
||||
<extensions>true</extensions>
|
||||
<configuration>
|
||||
<supportedProjectTypes>
|
||||
|
@ -1081,6 +1082,7 @@
|
|||
<artifactId>junit-jupiter</artifactId>
|
||||
<version>${junit.version}</version>
|
||||
</dependency>
|
||||
<!-- Test Container Deps -->
|
||||
<dependency>
|
||||
<groupId>org.hamcrest</groupId>
|
||||
<artifactId>hamcrest</artifactId>
|
||||
|
@ -1099,7 +1101,7 @@
|
|||
<dependency>
|
||||
<groupId>net.java.dev.jna</groupId>
|
||||
<artifactId>jna</artifactId>
|
||||
<version>5.5.0</version>
|
||||
<version>5.6.0</version>
|
||||
</dependency>
|
||||
<!-- Old Deps -->
|
||||
<dependency>
|
||||
|
@ -1151,12 +1153,12 @@
|
|||
<dependency>
|
||||
<groupId>org.apache.derby</groupId>
|
||||
<artifactId>derby</artifactId>
|
||||
<version>10.15.2.0</version>
|
||||
<version>${derby.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.apache.derby</groupId>
|
||||
<artifactId>derbytools</artifactId>
|
||||
<version>10.15.2.0</version>
|
||||
<version>${derby.version}</version>
|
||||
</dependency>
|
||||
<!-- avoid depending on a range dependency from a transitive dependency -->
|
||||
<dependency>
|
||||
|
@ -1221,7 +1223,7 @@
|
|||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-project-info-reports-plugin</artifactId>
|
||||
<version>3.0.0</version>
|
||||
<version>3.1.1</version>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
|
@ -1241,7 +1243,7 @@
|
|||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-site-plugin</artifactId>
|
||||
<version>3.7.1</version>
|
||||
<version>3.9.1</version>
|
||||
<executions>
|
||||
<execution>
|
||||
<id>build-site</id>
|
||||
|
@ -1599,6 +1601,14 @@
|
|||
<organizationUrl>https://webtide.com</organizationUrl>
|
||||
<timezone>Australia/Brisbane</timezone>
|
||||
</developer>
|
||||
<developer>
|
||||
<id>lorban</id>
|
||||
<name>Ludovic Orban</name>
|
||||
<email>lorban@bitronix.be</email>
|
||||
<organization>Webtide, LLC</organization>
|
||||
<organizationUrl>https://webtide.com</organizationUrl>
|
||||
<timezone>1</timezone>
|
||||
</developer>
|
||||
</developers>
|
||||
|
||||
<organization>
|
||||
|
|
|
@ -51,7 +51,9 @@ public class InfoServlet extends HttpServlet
|
|||
{
|
||||
out.printf("%16s => %s%n", bean.getName(), bean);
|
||||
for (InjectionPoint ij : bean.getInjectionPoints())
|
||||
out.printf("%16s -> %s%n", "", ij);
|
||||
{
|
||||
out.printf("%16s -> %s%n", "", ij);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -55,7 +55,7 @@
|
|||
<dependency>
|
||||
<groupId>org.apache.geronimo.specs</groupId>
|
||||
<artifactId>geronimo-interceptor_1.2_spec</artifactId>
|
||||
<version>1.1</version>
|
||||
<version>1.2</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.apache.openwebbeans</groupId>
|
||||
|
|
Loading…
Reference in New Issue