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

This commit is contained in:
Jan Bartel 2017-09-27 15:44:55 +10:00
commit ee4fd24cb1
25 changed files with 377 additions and 308 deletions

View File

@ -15,7 +15,7 @@
<properties>
<bundle-symbolic-name>${project.groupId}.alpn.java.client</bundle-symbolic-name>
<conscrypt.version>1.0.0.RC10</conscrypt.version>
<conscrypt.version>1.0.0.RC11</conscrypt.version>
</properties>
<dependencies>

View File

@ -59,7 +59,7 @@ public class ConscryptClientALPNProcessor implements ALPNProcessor.Client
{
try
{
Method setAlpnProtocols = sslEngine.getClass().getDeclaredMethod("setAlpnProtocols", String[].class);
Method setAlpnProtocols = sslEngine.getClass().getDeclaredMethod("setApplicationProtocols", String[].class);
setAlpnProtocols.setAccessible(true);
ALPNClientConnection alpn = (ALPNClientConnection)connection;
String[] protocols = alpn.getProtocols().toArray(new String[0]);
@ -92,9 +92,9 @@ public class ConscryptClientALPNProcessor implements ALPNProcessor.Client
try
{
SSLEngine sslEngine = alpnConnection.getSSLEngine();
Method method = sslEngine.getClass().getDeclaredMethod("getAlpnSelectedProtocol");
Method method = sslEngine.getClass().getDeclaredMethod("getApplicationProtocol");
method.setAccessible(true);
String protocol = new String((byte[])method.invoke(sslEngine), StandardCharsets.US_ASCII);
String protocol = (String)method.invoke(sslEngine);
alpnConnection.selected(protocol);
}
catch (Throwable e)

View File

@ -13,7 +13,7 @@
<properties>
<bundle-symbolic-name>${project.groupId}.alpn.conscrypt.server</bundle-symbolic-name>
<conscrypt.version>1.0.0.RC10</conscrypt.version>
<conscrypt.version>1.0.0.RC11</conscrypt.version>
</properties>
<dependencies>

View File

@ -116,6 +116,26 @@
<artifactId>jetty-alpn-java-server</artifactId>
<version>9.4.8-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-alpn-openjdk8-client</artifactId>
<version>9.4.8-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-alpn-openjdk8-server</artifactId>
<version>9.4.8-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-alpn-conscrypt-client</artifactId>
<version>9.4.8-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-alpn-conscrypt-server</artifactId>
<version>9.4.8-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-alpn-server</artifactId>

View File

@ -729,7 +729,7 @@ public class HttpClient extends ContainerLifeCycle
*/
public void setUserAgentField(HttpField agent)
{
if (agent.getHeader() != HttpHeader.USER_AGENT)
if (agent != null && agent.getHeader() != HttpHeader.USER_AGENT)
throw new IllegalArgumentException();
this.agentField = agent;
}

View File

@ -26,7 +26,7 @@ The modules and XML files involved can be seen with the following commands:
....
$ java -jar $JETTY_HOME/start.jar --list-modules
...
1) protonego-boot <transitive>
1) alpn-impl <transitive>
...
2) http ${jetty.base}/start.d/http.ini
2) ssl ${jetty.base}/start.d/ssl.ini
@ -64,6 +64,7 @@ Currently there are very few HTTP/2 configuration properties and the default val
[cols=",",options="header",]
|=======================================================================
|Property |Description
|jetty.http2.maxConcurrentStreams |The maximum number of concurrently open streams allowed on a single HTTP/2 connection (default 1024). Larger values increase parallelism but cost a memory commitment.
|jetty.http2.initialStreamRecvWindow |The initial receive flow control window size for a new stream (default 65535). Larger values may allow greater throughput but also risk head of line blocking if TCP/IP flow control is triggered.
|jetty.http2.maxConcurrentStreams |The maximum number of concurrently open streams allowed on a single HTTP/2 connection (default 128). Larger values increase parallelism but cost a memory commitment.
|jetty.http2.initialSessionRecvWindow |The initial receive flow control window size for a new session (default 1048576). Larger values may allow greater throughput but also risk head of line blocking if TCP/IP flow control is triggered.
|jetty.http2.initialStreamRecvWindow |The initial receive flow control window size for a new stream (default 524288). Larger values may allow greater throughput but also risk head of line blocking if TCP/IP flow control is triggered.
|=======================================================================

View File

@ -136,7 +136,7 @@ Here's an example of an xml file that defines an in-memory type of LoginService
<New class="org.eclipse.jetty.security.HashLoginService">
<Set name="name">Test Realm</Set>
<Set name="config"><SystemProperty name="jetty.home" default="."/>/etc/realm.properties</Set>
<Set name="refreshInterval">0</Set>
<Set name="hotReload">true</Set>
</New>
</Arg>
</Call>
@ -264,8 +264,7 @@ You configure the `HashLoginService` with a name and a reference to the location
----
You can also configure it to check the properties file regularly for changes and reload when changes are detected.
The `reloadInterval` is in seconds:
You can also configure it to reload the configuration file when changes to it are detected.
[source, xml, subs="{sub-order}"]
----
@ -273,7 +272,7 @@ The `reloadInterval` is in seconds:
<New class="org.eclipse.jetty.security.HashLoginService">
<Set name="name">Test Realm</Set>
<Set name="config"><SystemProperty name="jetty.home" default="."/>/etc/realm.properties</Set>
<Set name="reloadInterval">5</Set>
<Set name="hotReload">true</Set>
<Call name="start"></Call>
</New>

View File

@ -227,7 +227,7 @@ include::{SRCDIR}/examples/embedded/src/main/java/org/eclipse/jetty/embedded/One
The typical way to configure an instance of the Jetty server is via `jetty.xml` and associated configuration files.
However the Jetty XML configuration format is just a simple rendering of what you can do in code; it is very simple to write embedded code that does precisely what the jetty.xml configuration does.
The link:{JDURL}/org/eclipse/jetty/embedded/LikeJettyXml.html[LikeJettyXml example] following renders in code the behavior obtained from the configuration files:
The link:{GITBROWSEURL}/examples/embedded/src/main/java/org/eclipse/jetty/embedded/LikeJettyXml.java[LikeJettyXml example] following renders in code the behavior obtained from the configuration files:
* link:{GITBROWSEURL}/jetty-server/src/main/config/etc/jetty.xml[jetty.xml]
* link:{GITBROWSEURL}/jetty-jmx/src/main/config/etc/jetty-jmx.xml[jetty-jmx.xml]

View File

@ -1,5 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
<parent>
<groupId>org.eclipse.jetty.gcloud</groupId>
<artifactId>gcloud-parent</artifactId>
@ -22,12 +24,12 @@
<version>${gcloud.version}</version>
<exclusions>
<exclusion>
<groupId>javax.servlet</groupId>
<artifactId>servlet-api</artifactId>
<groupId>javax.servlet</groupId>
<artifactId>servlet-api</artifactId>
</exclusion>
<exclusion>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
</exclusion>
</exclusions>
@ -57,50 +59,51 @@
</dependency>
</dependencies>
<properties>
<bundle-symbolic-name>${project.groupId}.session</bundle-symbolic-name>
</properties>
<properties>
<bundle-symbolic-name>${project.groupId}.session</bundle-symbolic-name>
</properties>
<build>
<plugins>
<plugin>
<groupId>org.apache.felix</groupId>
<artifactId>maven-bundle-plugin</artifactId>
<extensions>true</extensions>
<executions>
<execution>
<goals>
<goal>manifest</goal>
</goals>
<configuration>
<instructions>
<Export-Package>org.eclipse.jetty.gcloud.session.*;version="${parsedVersion.majorVersion}.${parsedVersion.minorVersion}.${parsedVersion.incrementalVersion}";</Export-Package>
</instructions>
</configuration>
</execution>
</executions>
<groupId>org.apache.felix</groupId>
<artifactId>maven-bundle-plugin</artifactId>
<extensions>true</extensions>
<executions>
<execution>
<goals>
<goal>manifest</goal>
</goals>
<configuration>
<instructions>
<Export-Package>
org.eclipse.jetty.gcloud.session.*;version="${parsedVersion.majorVersion}.${parsedVersion.minorVersion}.${parsedVersion.incrementalVersion}";
</Export-Package>
</instructions>
</configuration>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-dependency-plugin</artifactId>
<version>3.0.0</version>
<executions>
<execution>
<id>build-deps-file</id>
<phase>generate-resources</phase>
<goals>
<goal>list</goal>
</goals>
<configuration>
<appendOutput>false</appendOutput>
<outputFile>${project.build.directory}/deps.txt</outputFile>
<sort>true</sort>
<excludeGroupIds>org.eclipse.jetty</excludeGroupIds>
<prependGroupId>true</prependGroupId>
<includeScope>runtime</includeScope>
</configuration>
</execution>
</executions>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-dependency-plugin</artifactId>
<executions>
<execution>
<id>build-deps-file</id>
<phase>generate-resources</phase>
<goals>
<goal>list</goal>
</goals>
<configuration>
<appendOutput>false</appendOutput>
<outputFile>${project.build.directory}/deps.txt</outputFile>
<sort>true</sort>
<excludeGroupIds>org.eclipse.jetty</excludeGroupIds>
<prependGroupId>true</prependGroupId>
<includeScope>runtime</includeScope>
</configuration>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
@ -118,15 +121,15 @@
match=" *(.*):(.*):jar:(.*):[a-z]*"
replace="maven://\1/\2/\3|lib/gcloud/\2-\3.jar"
byline="true"
/>
/>
<replaceregexp file="${project.build.directory}/deps.txt"
match="The following files have been resolved:"
replace="[files]"
/>
</tasks>
</configuration>
</execution>
<execution>
</execution>
<execution>
<id>process-mod</id>
<phase>process-resources</phase>
<goals>
@ -141,8 +144,7 @@
</tasks>
</configuration>
</execution>
</executions>
</executions>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
@ -161,7 +163,7 @@
</execution>
</executions>
</plugin>
</plugins>
</plugins>
</build>
</project>

View File

@ -288,7 +288,9 @@ public class HTTP2CServerTest extends AbstractServerTest
{
AtomicLong fills = new AtomicLong();
// Remove "h2c", leaving only "http/1.1".
connector.clearConnectionFactories();
connector.stop();
connector.removeConnectionFactory("h2c");
connector.start();
HttpConnectionFactory connectionFactory = new HttpConnectionFactory()
{
@Override
@ -306,8 +308,10 @@ public class HTTP2CServerTest extends AbstractServerTest
return configure(connection, connector, endPoint);
}
};
connector.stop();
connector.addConnectionFactory(connectionFactory);
connector.setDefaultProtocol(connectionFactory.getProtocol());
connector.start();
// Now send a HTTP/2 direct request, which
// will have the PRI * HTTP/2.0 preface.

View File

@ -61,11 +61,11 @@ public abstract class SelectorManager extends ContainerLifeCycle implements Dump
private long _selectorIndex;
private int _reservedThreads = -1;
public static int defaultSchedulers(Executor executor)
private static int defaultSelectors(Executor executor)
{
if (executor instanceof ThreadPool)
if (executor instanceof ThreadPool.SizedThreadPool)
{
int threads = ((ThreadPool)executor).getThreads();
int threads = ((ThreadPool.SizedThreadPool)executor).getMaxThreads();
int cpus = Runtime.getRuntime().availableProcessors();
return Math.max(1,Math.min(cpus/2,threads/16));
}
@ -87,7 +87,7 @@ public abstract class SelectorManager extends ContainerLifeCycle implements Dump
protected SelectorManager(Executor executor, Scheduler scheduler, int selectors)
{
if (selectors <= 0)
selectors = defaultSchedulers(executor);
selectors = defaultSelectors(executor);
this.executor = executor;
this.scheduler = scheduler;
_selectors = new ManagedSelector[selectors];

View File

@ -289,7 +289,7 @@ public abstract class AbstractConnector extends ContainerLifeCycle implements Co
protected void interruptAcceptors()
{
try (Locker.Lock lock = _locker.lockIfNotHeld())
try (Locker.Lock lock = _locker.lock())
{
for (Thread thread : _acceptors)
{
@ -363,7 +363,6 @@ public abstract class AbstractConnector extends ContainerLifeCycle implements Co
_setAccepting.signalAll();
}
}
@Override
public ConnectionFactory getConnectionFactory(String protocol)
@ -388,108 +387,105 @@ public abstract class AbstractConnector extends ContainerLifeCycle implements Co
public void addConnectionFactory(ConnectionFactory factory)
{
try (Locker.Lock lock = _locker.lockIfNotHeld())
if (isRunning())
throw new IllegalStateException(getState());
Set<ConnectionFactory> to_remove = new HashSet<>();
for (String key:factory.getProtocols())
{
Set<ConnectionFactory> to_remove = new HashSet<>();
for (String key:factory.getProtocols())
key=StringUtil.asciiToLowerCase(key);
ConnectionFactory old=_factories.remove(key);
if (old!=null)
{
key=StringUtil.asciiToLowerCase(key);
ConnectionFactory old=_factories.remove(key);
if (old!=null)
{
if (old.getProtocol().equals(_defaultProtocol))
_defaultProtocol=null;
to_remove.add(old);
}
_factories.put(key, factory);
if (old.getProtocol().equals(_defaultProtocol))
_defaultProtocol=null;
to_remove.add(old);
}
// keep factories still referenced
for (ConnectionFactory f : _factories.values())
to_remove.remove(f);
// remove old factories
for (ConnectionFactory old: to_remove)
{
removeBean(old);
if (LOG.isDebugEnabled())
LOG.debug("{} removed {}", this, old);
}
// add new Bean
addBean(factory);
if (_defaultProtocol==null)
_defaultProtocol=factory.getProtocol();
if (LOG.isDebugEnabled())
LOG.debug("{} added {}", this, factory);
_factories.put(key, factory);
}
// keep factories still referenced
for (ConnectionFactory f : _factories.values())
to_remove.remove(f);
// remove old factories
for (ConnectionFactory old: to_remove)
{
removeBean(old);
if (LOG.isDebugEnabled())
LOG.debug("{} removed {}", this, old);
}
// add new Bean
addBean(factory);
if (_defaultProtocol==null)
_defaultProtocol=factory.getProtocol();
if (LOG.isDebugEnabled())
LOG.debug("{} added {}", this, factory);
}
public void addFirstConnectionFactory(ConnectionFactory factory)
{
try (Locker.Lock lock = _locker.lock())
{
List<ConnectionFactory> existings = new ArrayList<>(_factories.values());
_factories.clear();
addConnectionFactory(factory);
for (ConnectionFactory existing : existings)
addConnectionFactory(existing);
_defaultProtocol = factory.getProtocol();
}
if (isRunning())
throw new IllegalStateException(getState());
List<ConnectionFactory> existings = new ArrayList<>(_factories.values());
_factories.clear();
addConnectionFactory(factory);
for (ConnectionFactory existing : existings)
addConnectionFactory(existing);
_defaultProtocol = factory.getProtocol();
}
public void addIfAbsentConnectionFactory(ConnectionFactory factory)
{
try (Locker.Lock lock = _locker.lock())
if (isRunning())
throw new IllegalStateException(getState());
String key=StringUtil.asciiToLowerCase(factory.getProtocol());
if (_factories.containsKey(key))
{
String key=StringUtil.asciiToLowerCase(factory.getProtocol());
if (_factories.containsKey(key))
{
if (LOG.isDebugEnabled())
LOG.debug("{} addIfAbsent ignored {}", this, factory);
}
else
{
_factories.put(key, factory);
addBean(factory);
if (_defaultProtocol==null)
_defaultProtocol=factory.getProtocol();
if (LOG.isDebugEnabled())
LOG.debug("{} addIfAbsent added {}", this, factory);
}
if (LOG.isDebugEnabled())
LOG.debug("{} addIfAbsent ignored {}", this, factory);
}
else
{
_factories.put(key, factory);
addBean(factory);
if (_defaultProtocol==null)
_defaultProtocol=factory.getProtocol();
if (LOG.isDebugEnabled())
LOG.debug("{} addIfAbsent added {}", this, factory);
}
}
public ConnectionFactory removeConnectionFactory(String protocol)
{
try (Locker.Lock lock = _locker.lock())
{
ConnectionFactory factory= _factories.remove(StringUtil.asciiToLowerCase(protocol));
removeBean(factory);
return factory;
}
if (isRunning())
throw new IllegalStateException(getState());
ConnectionFactory factory= _factories.remove(StringUtil.asciiToLowerCase(protocol));
removeBean(factory);
return factory;
}
@Override
public Collection<ConnectionFactory> getConnectionFactories()
{
try (Locker.Lock lock = _locker.lock())
{
return _factories.values();
}
return _factories.values();
}
public void setConnectionFactories(Collection<ConnectionFactory> factories)
{
try (Locker.Lock lock = _locker.lock())
{
List<ConnectionFactory> existing = new ArrayList<>(_factories.values());
for (ConnectionFactory factory: existing)
removeConnectionFactory(factory.getProtocol());
for (ConnectionFactory factory: factories)
if (factory!=null)
addConnectionFactory(factory);
}
if (isRunning())
throw new IllegalStateException(getState());
List<ConnectionFactory> existing = new ArrayList<>(_factories.values());
for (ConnectionFactory factory: existing)
removeConnectionFactory(factory.getProtocol());
for (ConnectionFactory factory: factories)
if (factory!=null)
addConnectionFactory(factory);
}
@ManagedAttribute("The priority delta to apply to acceptor threads")
@ -521,18 +517,15 @@ public abstract class AbstractConnector extends ContainerLifeCycle implements Co
@ManagedAttribute("Protocols supported by this connector")
public List<String> getProtocols()
{
synchronized (_factories)
{
return new ArrayList<>(_factories.keySet());
}
return new ArrayList<>(_factories.keySet());
}
public void clearConnectionFactories()
{
synchronized (_factories)
{
_factories.clear();
}
if (isRunning())
throw new IllegalStateException(getState());
_factories.clear();
}
@ManagedAttribute("This connector's default protocol")
@ -616,10 +609,7 @@ public abstract class AbstractConnector extends ContainerLifeCycle implements Co
if (_acceptorPriorityDelta!=0)
thread.setPriority(Math.max(Thread.MIN_PRIORITY,Math.min(Thread.MAX_PRIORITY,priority+_acceptorPriorityDelta)));
synchronized (AbstractConnector.this)
{
_acceptors[_id] = thread;
}
_acceptors[_id] = thread;
try
{
@ -676,26 +666,6 @@ public abstract class AbstractConnector extends ContainerLifeCycle implements Co
}
// protected void connectionOpened(Connection connection)
// {
// _stats.connectionOpened();
// connection.onOpen();
// }
//
// protected void connectionClosed(Connection connection)
// {
// connection.onClose();
// long duration = System.currentTimeMillis() - connection.getEndPoint().getCreatedTimeStamp();
// _stats.connectionClosed(duration, connection.getMessagesIn(), connection.getMessagesOut());
// }
//
// public void connectionUpgraded(Connection oldConnection, Connection newConnection)
// {
// oldConnection.onClose();
// _stats.connectionUpgraded(oldConnection.getMessagesIn(), oldConnection.getMessagesOut());
// newConnection.onOpen();
// }
@Override
public Collection<EndPoint> getConnectedEndPoints()
{

View File

@ -137,7 +137,7 @@ public class Session implements SessionHandler.SessionIf
// True if:
// 1. the session is still valid
// BUT if passivated out to disk, do we really want this timer to keep going off?
try (Lock lock = _lock.lockIfNotHeld())
try (Lock lock = _lock.lock())
{
return isValid() && isResident();
}
@ -198,7 +198,7 @@ public class Session implements SessionHandler.SessionIf
*/
public long getRequests()
{
try (Lock lock = _lock.lockIfNotHeld())
try (Lock lock = _lock.lock())
{
return _requests;
}
@ -217,7 +217,7 @@ public class Session implements SessionHandler.SessionIf
/* ------------------------------------------------------------- */
protected void cookieSet()
{
try (Lock lock = _lock.lockIfNotHeld())
try (Lock lock = _lock.lock())
{
_sessionData.setCookieSet(_sessionData.getAccessed());
}
@ -225,7 +225,7 @@ public class Session implements SessionHandler.SessionIf
/* ------------------------------------------------------------ */
protected boolean access(long time)
{
try (Lock lock = _lock.lockIfNotHeld())
try (Lock lock = _lock.lock())
{
if (!isValid())
return false;
@ -249,7 +249,7 @@ public class Session implements SessionHandler.SessionIf
/* ------------------------------------------------------------ */
protected void complete()
{
try (Lock lock = _lock.lockIfNotHeld())
try (Lock lock = _lock.lock())
{
_requests--;
}
@ -265,7 +265,7 @@ public class Session implements SessionHandler.SessionIf
*/
protected boolean isExpiredAt(long time)
{
try (Lock lock = _lock.lockIfNotHeld())
try (Lock lock = _lock.lock())
{
return _sessionData.isExpiredAt(time);
}
@ -281,7 +281,7 @@ public class Session implements SessionHandler.SessionIf
protected boolean isIdleLongerThan (int sec)
{
long now = System.currentTimeMillis();
try (Lock lock = _lock.lockIfNotHeld())
try (Lock lock = _lock.lock())
{
return ((_sessionData.getAccessed() + (sec*1000)) <= now);
}
@ -384,7 +384,7 @@ public class Session implements SessionHandler.SessionIf
/* ------------------------------------------------------------ */
public boolean isValid()
{
try (Lock lock = _lock.lockIfNotHeld())
try (Lock lock = _lock.lock())
{
return _state==State.VALID;
}
@ -394,7 +394,7 @@ public class Session implements SessionHandler.SessionIf
/* ------------------------------------------------------------- */
public long getCookieSetTime()
{
try (Lock lock = _lock.lockIfNotHeld())
try (Lock lock = _lock.lock())
{
return _sessionData.getCookieSet();
}
@ -405,7 +405,7 @@ public class Session implements SessionHandler.SessionIf
@Override
public long getCreationTime() throws IllegalStateException
{
try (Lock lock = _lock.lockIfNotHeld())
try (Lock lock = _lock.lock())
{
checkValidForRead();
return _sessionData.getCreated();
@ -420,7 +420,7 @@ public class Session implements SessionHandler.SessionIf
@Override
public String getId()
{
try (Lock lock = _lock.lockIfNotHeld())
try (Lock lock = _lock.lock())
{
return _sessionData.getId();
}
@ -450,7 +450,7 @@ public class Session implements SessionHandler.SessionIf
@Override
public long getLastAccessedTime()
{
try (Lock lock = _lock.lockIfNotHeld())
try (Lock lock = _lock.lock())
{
return _sessionData.getLastAccessed();
}
@ -473,7 +473,7 @@ public class Session implements SessionHandler.SessionIf
@Override
public void setMaxInactiveInterval(int secs)
{
try (Lock lock = _lock.lockIfNotHeld())
try (Lock lock = _lock.lock())
{
_sessionData.setMaxInactiveMs((long)secs*1000L);
_sessionData.calcAndSetExpiry();
@ -496,7 +496,7 @@ public class Session implements SessionHandler.SessionIf
*/
public void updateInactivityTimer ()
{
try (Lock lock = _lock.lockIfNotHeld())
try (Lock lock = _lock.lock())
{
if (LOG.isDebugEnabled())LOG.debug("updateInactivityTimer");
@ -556,7 +556,7 @@ public class Session implements SessionHandler.SessionIf
*/
public void stopInactivityTimer ()
{
try (Lock lock = _lock.lockIfNotHeld())
try (Lock lock = _lock.lock())
{
if (_sessionInactivityTimer != null)
{
@ -573,7 +573,7 @@ public class Session implements SessionHandler.SessionIf
@Override
public int getMaxInactiveInterval()
{
try (Lock lock = _lock.lockIfNotHeld())
try (Lock lock = _lock.lock())
{
return (int)(_sessionData.getMaxInactiveMs()/1000);
}
@ -653,7 +653,7 @@ public class Session implements SessionHandler.SessionIf
@Override
public Object getAttribute(String name)
{
try (Lock lock = _lock.lockIfNotHeld())
try (Lock lock = _lock.lock())
{
checkValidForRead();
return _sessionData.getAttribute(name);
@ -667,7 +667,7 @@ public class Session implements SessionHandler.SessionIf
@Deprecated
public Object getValue(String name)
{
try (Lock lock = _lock.lockIfNotHeld())
try (Lock lock = _lock.lock())
{
return _sessionData.getAttribute(name);
}
@ -679,7 +679,7 @@ public class Session implements SessionHandler.SessionIf
@Override
public Enumeration<String> getAttributeNames()
{
try (Lock lock = _lock.lockIfNotHeld())
try (Lock lock = _lock.lock())
{
checkValidForRead();
final Iterator<String> itor = _sessionData.getKeys().iterator();
@ -730,7 +730,7 @@ public class Session implements SessionHandler.SessionIf
@Override
public String[] getValueNames() throws IllegalStateException
{
try (Lock lock = _lock.lockIfNotHeld())
try (Lock lock = _lock.lock())
{
checkValidForRead();
Iterator<String> itor = _sessionData.getKeys().iterator();
@ -751,7 +751,7 @@ public class Session implements SessionHandler.SessionIf
public void setAttribute(String name, Object value)
{
Object old=null;
try (Lock lock = _lock.lockIfNotHeld())
try (Lock lock = _lock.lock())
{
//if session is not valid, don't accept the set
checkValidForWrite();
@ -812,7 +812,7 @@ public class Session implements SessionHandler.SessionIf
String id = null;
String extendedId = null;
try (Lock lock = _lock.lockIfNotHeld())
try (Lock lock = _lock.lock())
{
checkValidForWrite(); //don't renew id on a session that is not valid
id = _sessionData.getId(); //grab the values as they are now
@ -820,7 +820,7 @@ public class Session implements SessionHandler.SessionIf
}
String newId = _handler._sessionIdManager.renewSessionId(id, extendedId, request);
try (Lock lock = _lock.lockIfNotHeld())
try (Lock lock = _lock.lock())
{
checkValidForWrite();
_sessionData.setId(newId);
@ -877,7 +877,7 @@ public class Session implements SessionHandler.SessionIf
*/
public Lock lockIfNotHeld ()
{
return _lock.lockIfNotHeld();
return _lock.lock();
}
/* ------------------------------------------------------------- */
@ -888,7 +888,7 @@ public class Session implements SessionHandler.SessionIf
{
boolean result = false;
try (Lock lock = _lock.lockIfNotHeld())
try (Lock lock = _lock.lock())
{
switch (_state)
{
@ -934,7 +934,7 @@ public class Session implements SessionHandler.SessionIf
*/
protected void finishInvalidate() throws IllegalStateException
{
try (Lock lock = _lock.lockIfNotHeld())
try (Lock lock = _lock.lock())
{
try
{
@ -970,7 +970,7 @@ public class Session implements SessionHandler.SessionIf
@Override
public boolean isNew() throws IllegalStateException
{
try (Lock lock = _lock.lockIfNotHeld())
try (Lock lock = _lock.lock())
{
checkValidForRead();
return _newSession;
@ -982,7 +982,7 @@ public class Session implements SessionHandler.SessionIf
/* ------------------------------------------------------------- */
public void setIdChanged(boolean changed)
{
try (Lock lock = _lock.lockIfNotHeld())
try (Lock lock = _lock.lock())
{
_idChanged=changed;
}
@ -992,7 +992,7 @@ public class Session implements SessionHandler.SessionIf
/* ------------------------------------------------------------- */
public boolean isIdChanged ()
{
try (Lock lock = _lock.lockIfNotHeld())
try (Lock lock = _lock.lock())
{
return _idChanged;
}

View File

@ -357,7 +357,7 @@ public abstract class HttpServerTestBase extends HttpServerTestFixture
try (Socket client = newSocket(_serverURI.getHost(), _serverURI.getPort());
StacklessLogging stackless = new StacklessLogging(HttpConnection.class))
{
Log.getLogger(HttpConnection.class).info("expect header is too large, then ISE extra data ...");
Log.getLogger(HttpConnection.class).info("expect header is too large ...");
OutputStream os = client.getOutputStream();
byte[] buffer = new byte[64 * 1024];
@ -379,9 +379,16 @@ public abstract class HttpServerTestBase extends HttpServerTestFixture
buffer[15]='H';
buffer[16]=':';
Arrays.fill(buffer,17,buffer.length-1,(byte)'A');
os.write(buffer);
os.flush();
// write the request.
try
{
os.write(buffer);
os.flush();
}
catch(Exception e)
{
// Ignore exceptions during writing, so long as we can read response below
}
// Read the response.
try
@ -391,7 +398,8 @@ public abstract class HttpServerTestBase extends HttpServerTestFixture
}
catch(Exception e)
{
// TODO evaluate why we sometimes get an early close on this test
Log.getLogger(HttpServerTestBase.class).warn("TODO Early close???");
// TODO #1832 evaluate why we sometimes get an early close on this test
}
}
}

View File

@ -40,6 +40,7 @@ import java.util.regex.Pattern;
import javax.net.ssl.HttpsURLConnection;
import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLException;
import javax.net.ssl.SSLSession;
import javax.net.ssl.TrustManagerFactory;
import javax.servlet.ServletException;
@ -118,14 +119,7 @@ public class SelectChannelServerSslTest extends HttpServerTestBase
@Override
public void testFullHeader() throws Exception
{
try
{
super.testFullHeader();
}
catch (SocketException e)
{
Log.getLogger(SslConnection.class).warn("Close overtook 400 response");
}
super.testFullHeader();
}
@Before
@ -167,7 +161,6 @@ public class SelectChannelServerSslTest extends HttpServerTestBase
}
catch(Exception e)
{
e.printStackTrace();
throw new RuntimeException(e);
}
}

View File

@ -81,11 +81,11 @@ public class ServletHolder extends Holder<Servlet> implements UserIdentity.Scope
private ServletRegistration.Dynamic _registration;
private JspContainer _jspContainer;
private transient Servlet _servlet;
private transient Config _config;
private transient long _unavailable;
private transient boolean _enabled = true;
private transient UnavailableException _unavailableEx;
private Servlet _servlet;
private long _unavailable;
private Config _config;
private boolean _enabled = true;
private UnavailableException _unavailableEx;
public static final String APACHE_SENTINEL_CLASS = "org.apache.tomcat.InstanceManager";
@ -400,9 +400,11 @@ public class ServletHolder extends Holder<Servlet> implements UserIdentity.Scope
_config=new Config();
if (_class!=null && javax.servlet.SingleThreadModel.class.isAssignableFrom(_class))
_servlet = new SingleThreadedWrapper();
synchronized (this)
{
if (_class!=null && javax.servlet.SingleThreadModel.class.isAssignableFrom(_class))
_servlet = new SingleThreadedWrapper();
}
}
@ -485,18 +487,38 @@ public class ServletHolder extends Holder<Servlet> implements UserIdentity.Scope
public synchronized Servlet getServlet()
throws ServletException
{
// Handle previous unavailability
if (_unavailable!=0)
{
if (_unavailable<0 || _unavailable>0 && System.currentTimeMillis()<_unavailable)
throw _unavailableEx;
_unavailable=0;
_unavailableEx=null;
}
Servlet servlet=_servlet;
if (servlet!=null && _unavailable==0)
return servlet;
if (_servlet==null)
initServlet();
return _servlet;
synchronized(this)
{
// Handle previous unavailability
if (_unavailable!=0)
{
if (_unavailable<0 || _unavailable>0 && System.currentTimeMillis()<_unavailable)
throw _unavailableEx;
_unavailable=0;
_unavailableEx=null;
}
servlet=_servlet;
if (servlet!=null)
return servlet;
if (isRunning())
{
if (_class == null)
throw new UnavailableException("Servlet Not Initialized");
if (_unavailable != 0 || !_initOnStartup)
initServlet();
servlet=_servlet;
if (servlet == null)
throw new UnavailableException("Could not instantiate " + _class);
}
return servlet;
}
}
/* ------------------------------------------------------------ */
@ -505,7 +527,13 @@ public class ServletHolder extends Holder<Servlet> implements UserIdentity.Scope
*/
public Servlet getServletInstance()
{
return _servlet;
Servlet servlet=_servlet;
if (servlet!=null)
return servlet;
synchronized(this)
{
return _servlet;
}
}
/* ------------------------------------------------------------ */
@ -528,7 +556,7 @@ public class ServletHolder extends Holder<Servlet> implements UserIdentity.Scope
*/
public boolean isAvailable()
{
if (isStarted()&& _unavailable==0)
if (isStarted() && _unavailable==0)
return true;
try
{
@ -539,7 +567,7 @@ public class ServletHolder extends Holder<Servlet> implements UserIdentity.Scope
LOG.ignore(e);
}
return isStarted()&& _unavailable==0;
return isStarted() && _unavailable==0;
}
/* ------------------------------------------------------------ */
@ -604,7 +632,7 @@ public class ServletHolder extends Holder<Servlet> implements UserIdentity.Scope
}
/* ------------------------------------------------------------ */
private void initServlet()
private synchronized void initServlet()
throws ServletException
{
Object old_run_as = null;
@ -767,26 +795,17 @@ public class ServletHolder extends Holder<Servlet> implements UserIdentity.Scope
protected void prepare (Request baseRequest, ServletRequest request, ServletResponse response)
throws ServletException, UnavailableException
{
ensureInstance();
getServlet();
MultipartConfigElement mpce = ((Registration)getRegistration()).getMultipartConfig();
if (mpce != null)
baseRequest.setAttribute(Request.__MULTIPART_CONFIG_ELEMENT, mpce);
}
public synchronized Servlet ensureInstance()
throws ServletException, UnavailableException
@Deprecated
public Servlet ensureInstance()
throws ServletException, UnavailableException
{
if (_class==null)
throw new UnavailableException("Servlet Not Initialized");
Servlet servlet=_servlet;
if (!isStarted())
throw new UnavailableException("Servlet not initialized", -1);
if (_unavailable!=0 || (!_initOnStartup && servlet==null))
servlet=getServlet();
if (servlet==null)
throw new UnavailableException("Could not instantiate "+_class);
return servlet;
return getServlet();
}
/* ------------------------------------------------------------ */
@ -810,7 +829,7 @@ public class ServletHolder extends Holder<Servlet> implements UserIdentity.Scope
if (_class==null)
throw new UnavailableException("Servlet Not Initialized");
Servlet servlet = ensureInstance();
Servlet servlet = getServlet();
// Service the request
Object old_run_as = null;
@ -855,26 +874,23 @@ public class ServletHolder extends Holder<Servlet> implements UserIdentity.Scope
/* ------------------------------------------------------------ */
private boolean isJspServlet ()
protected boolean isJspServlet ()
{
if (_servlet == null)
return false;
Servlet servlet = getServletInstance();
Class<?> c = servlet==null?_class:servlet.getClass();
Class<?> c = _servlet.getClass();
boolean result = false;
while (c != null && !result)
while (c != null)
{
result = isJspServlet(c.getName());
if (isJspServlet(c.getName()))
return true;
c = c.getSuperclass();
}
return result;
return false;
}
/* ------------------------------------------------------------ */
private boolean isJspServlet (String classname)
protected boolean isJspServlet (String classname)
{
if (classname == null)
return false;

View File

@ -447,8 +447,8 @@ public abstract class Resource implements ResourceFactory, Closeable
/* ------------------------------------------------------------ */
/**
* list of resource names contained in the given resource.
*
* @return a list of resource names contained in the given resource.
* Ordering is unspecified, so callers may wish to sort the return value to ensure deterministic behavior.
* @return a list of resource names contained in the given resource, or null.
* Note: The resource names are not URL encoded.
*/
public abstract String[] list();

View File

@ -22,10 +22,10 @@ import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.ReentrantLock;
/**
* Convenience Lock Wrapper.
* <p>Convenience auto closeable {@link java.util.concurrent.locks.ReentrantLock} wrapper.</p>
*
* <pre>
* try(Locker.Lock lock = locker.lock())
* try (Locker.Lock lock = locker.lock())
* {
* // something
* }
@ -33,44 +33,49 @@ import java.util.concurrent.locks.ReentrantLock;
*/
public class Locker
{
private static final Lock LOCKED = new Lock();
private final ReentrantLock _lock = new ReentrantLock();
private final Lock _unlock = new UnLock();
public Locker()
{
}
private final Lock _unlock = new Lock();
/**
* <p>Acquires the lock.</p>
*
* @return the lock to unlock
*/
public Lock lock()
{
if (_lock.isHeldByCurrentThread())
throw new IllegalStateException("Locker is not reentrant");
_lock.lock();
return _unlock;
}
public Lock lockIfNotHeld ()
{
if (_lock.isHeldByCurrentThread())
return LOCKED;
_lock.lock();
return _unlock;
}
/**
* @deprecated use {@link #lock()} instead
*/
@Deprecated
public Lock lockIfNotHeld()
{
return lock();
}
/**
* @return whether this lock has been acquired
*/
public boolean isLocked()
{
return _lock.isLocked();
}
public static class Lock implements AutoCloseable
/**
* @return a {@link Condition} associated with this lock
*/
public Condition newCondition()
{
@Override
public void close()
{
}
return _lock.newCondition();
}
public class UnLock extends Lock
/**
* <p>The unlocker object that unlocks when it is closed.</p>
*/
public class Lock implements AutoCloseable
{
@Override
public void close()
@ -78,9 +83,9 @@ public class Locker
_lock.unlock();
}
}
public Condition newCondition()
@Deprecated
public class UnLock extends Lock
{
return _lock.newCondition();
}
}

View File

@ -29,6 +29,7 @@ import java.security.CodeSource;
import java.security.PermissionCollection;
import java.security.PrivilegedExceptionAction;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.Enumeration;
import java.util.HashSet;
@ -327,6 +328,10 @@ public class WebAppClassLoader extends URLClassLoader
if (lib.exists() && lib.isDirectory())
{
String[] files=lib.list();
if (files != null)
{
Arrays.sort(files);
}
for (int f=0;files!=null && f<files.length;f++)
{
try

View File

@ -25,6 +25,7 @@ import java.net.URISyntaxException;
import java.net.URL;
import java.net.URLClassLoader;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Locale;
import java.util.Set;
@ -702,7 +703,7 @@ public class WebInfConfiguration extends AbstractConfiguration
* Look for jars in <code>WEB-INF/lib</code>
*
* @param context the context to find the lib jars in
* @return the list of jars as {@link Resource}
* @return the list of jars as {@link Resource}, or null
* @throws Exception if unable to scan for lib jars
*/
protected List<Resource> findWebInfLibJars(WebAppContext context)
@ -717,6 +718,10 @@ public class WebInfConfiguration extends AbstractConfiguration
if (web_inf_lib.exists() && web_inf_lib.isDirectory())
{
String[] files=web_inf_lib.list();
if (files != null)
{
Arrays.sort(files);
}
for (int f=0;files!=null && f<files.length;f++)
{
try

View File

@ -22,10 +22,13 @@ import static org.eclipse.jetty.toolchain.test.ExtraMatchers.ordered;
import static org.hamcrest.Matchers.contains;
import static org.hamcrest.Matchers.notNullValue;
import static org.hamcrest.Matchers.nullValue;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertThat;
import static org.junit.Assert.assertTrue;
import static org.junit.Assume.assumeThat;
import java.io.InputStream;
import java.lang.instrument.ClassFileTransformer;
import java.lang.instrument.IllegalClassFormatException;
import java.net.URI;
@ -34,9 +37,11 @@ import java.nio.file.Path;
import java.security.ProtectionDomain;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Enumeration;
import java.util.List;
import org.eclipse.jetty.toolchain.test.MavenTestingUtils;
import org.eclipse.jetty.util.IO;
import org.eclipse.jetty.util.resource.PathResource;
import org.eclipse.jetty.util.resource.Resource;
import org.junit.Before;
@ -323,4 +328,26 @@ public class WebAppClassLoaderTest
}
@Test
public void ordering() throws Exception
{
// The existence of a URLStreamHandler changes the behavior
assumeThat("URLStreamHandler changes behavior, skip test", URLStreamHandlerUtil.getFactory(), nullValue());
Enumeration<URL> resources = _loader.getResources("org/acme/clashing.txt");
assertTrue(resources.hasMoreElements());
URL resource = resources.nextElement();
try (InputStream data = resource.openStream())
{
assertEquals("correct contents of " + resource, "alpha", IO.toString(data));
}
assertTrue(resources.hasMoreElements());
resource = resources.nextElement();
try (InputStream data = resource.openStream())
{
assertEquals("correct contents of " + resource, "omega", IO.toString(data));
}
assertFalse(resources.hasMoreElements());
}
}

View File

@ -25,9 +25,11 @@ import static org.junit.Assert.assertTrue;
import java.io.File;
import java.io.IOException;
import java.nio.file.Path;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;
import javax.servlet.GenericServlet;
import javax.servlet.ServletContext;
@ -44,7 +46,9 @@ import org.eclipse.jetty.server.handler.HandlerList;
import org.eclipse.jetty.server.handler.HotSwapHandler;
import org.eclipse.jetty.servlet.ErrorPageErrorHandler;
import org.eclipse.jetty.servlet.ServletContextHandler;
import org.eclipse.jetty.toolchain.test.MavenTestingUtils;
import org.eclipse.jetty.util.log.Log;
import org.eclipse.jetty.util.resource.PathResource;
import org.eclipse.jetty.util.resource.Resource;
import org.eclipse.jetty.util.resource.ResourceCollection;
import org.hamcrest.Matchers;
@ -378,4 +382,18 @@ public class WebAppContextTest
server.stop();
}
@Test
public void ordering() throws Exception
{
Path testWebappDir = MavenTestingUtils.getProjectDirPath("src/test/webapp");
Resource webapp = new PathResource(testWebappDir);
WebAppContext context = new WebAppContext();
context.setBaseResource(webapp);
context.setContextPath("/test");
new WebInfConfiguration().preConfigure(context);
assertEquals(Arrays.asList("acme.jar", "alpha.jar", "omega.jar"),
context.getMetaData().getWebInfJars().stream().map(r -> r.getURI().toString().replaceFirst(".+/", "")).collect(Collectors.toList()));
}
}

Binary file not shown.

Binary file not shown.

10
pom.xml
View File

@ -393,7 +393,7 @@
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-dependency-plugin</artifactId>
<version>3.0.1</version>
<version>3.0.2</version>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
@ -1138,12 +1138,8 @@
</profile>
<!--
Usage:
configure settings.xml for jetty.eclipse.website server entry
> mvn -Paggregate-site javadoc:aggregate
then
> mvn -N site:deploy
or
> mvn -N site:sshdeploy (for ssh users w/passphrase and ssh-agent)
Javadoc aggregation for Jetty website
> mvn -Paggregate-site clean install javadoc:aggregate -Dtest=foo
-->
<profile>
<id>aggregate-site</id>