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> <properties>
<bundle-symbolic-name>${project.groupId}.alpn.java.client</bundle-symbolic-name> <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> </properties>
<dependencies> <dependencies>

View File

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

View File

@ -13,7 +13,7 @@
<properties> <properties>
<bundle-symbolic-name>${project.groupId}.alpn.conscrypt.server</bundle-symbolic-name> <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> </properties>
<dependencies> <dependencies>

View File

@ -116,6 +116,26 @@
<artifactId>jetty-alpn-java-server</artifactId> <artifactId>jetty-alpn-java-server</artifactId>
<version>9.4.8-SNAPSHOT</version> <version>9.4.8-SNAPSHOT</version>
</dependency> </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> <dependency>
<groupId>org.eclipse.jetty</groupId> <groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-alpn-server</artifactId> <artifactId>jetty-alpn-server</artifactId>

View File

@ -729,7 +729,7 @@ public class HttpClient extends ContainerLifeCycle
*/ */
public void setUserAgentField(HttpField agent) public void setUserAgentField(HttpField agent)
{ {
if (agent.getHeader() != HttpHeader.USER_AGENT) if (agent != null && agent.getHeader() != HttpHeader.USER_AGENT)
throw new IllegalArgumentException(); throw new IllegalArgumentException();
this.agentField = agent; 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 $ 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) http ${jetty.base}/start.d/http.ini
2) ssl ${jetty.base}/start.d/ssl.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",] [cols=",",options="header",]
|======================================================================= |=======================================================================
|Property |Description |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.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.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.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"> <New class="org.eclipse.jetty.security.HashLoginService">
<Set name="name">Test Realm</Set> <Set name="name">Test Realm</Set>
<Set name="config"><SystemProperty name="jetty.home" default="."/>/etc/realm.properties</Set> <Set name="config"><SystemProperty name="jetty.home" default="."/>/etc/realm.properties</Set>
<Set name="refreshInterval">0</Set> <Set name="hotReload">true</Set>
</New> </New>
</Arg> </Arg>
</Call> </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. You can also configure it to reload the configuration file when changes to it are detected.
The `reloadInterval` is in seconds:
[source, xml, subs="{sub-order}"] [source, xml, subs="{sub-order}"]
---- ----
@ -273,7 +272,7 @@ The `reloadInterval` is in seconds:
<New class="org.eclipse.jetty.security.HashLoginService"> <New class="org.eclipse.jetty.security.HashLoginService">
<Set name="name">Test Realm</Set> <Set name="name">Test Realm</Set>
<Set name="config"><SystemProperty name="jetty.home" default="."/>/etc/realm.properties</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> <Call name="start"></Call>
</New> </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. 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. 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-server/src/main/config/etc/jetty.xml[jetty.xml]
* link:{GITBROWSEURL}/jetty-jmx/src/main/config/etc/jetty-jmx.xml[jetty-jmx.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"?> <?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> <parent>
<groupId>org.eclipse.jetty.gcloud</groupId> <groupId>org.eclipse.jetty.gcloud</groupId>
<artifactId>gcloud-parent</artifactId> <artifactId>gcloud-parent</artifactId>
@ -22,12 +24,12 @@
<version>${gcloud.version}</version> <version>${gcloud.version}</version>
<exclusions> <exclusions>
<exclusion> <exclusion>
<groupId>javax.servlet</groupId> <groupId>javax.servlet</groupId>
<artifactId>servlet-api</artifactId> <artifactId>servlet-api</artifactId>
</exclusion> </exclusion>
<exclusion> <exclusion>
<groupId>javax.servlet</groupId> <groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId> <artifactId>javax.servlet-api</artifactId>
</exclusion> </exclusion>
</exclusions> </exclusions>
@ -57,50 +59,51 @@
</dependency> </dependency>
</dependencies> </dependencies>
<properties> <properties>
<bundle-symbolic-name>${project.groupId}.session</bundle-symbolic-name> <bundle-symbolic-name>${project.groupId}.session</bundle-symbolic-name>
</properties> </properties>
<build> <build>
<plugins> <plugins>
<plugin> <plugin>
<groupId>org.apache.felix</groupId> <groupId>org.apache.felix</groupId>
<artifactId>maven-bundle-plugin</artifactId> <artifactId>maven-bundle-plugin</artifactId>
<extensions>true</extensions> <extensions>true</extensions>
<executions> <executions>
<execution> <execution>
<goals> <goals>
<goal>manifest</goal> <goal>manifest</goal>
</goals> </goals>
<configuration> <configuration>
<instructions> <instructions>
<Export-Package>org.eclipse.jetty.gcloud.session.*;version="${parsedVersion.majorVersion}.${parsedVersion.minorVersion}.${parsedVersion.incrementalVersion}";</Export-Package> <Export-Package>
</instructions> org.eclipse.jetty.gcloud.session.*;version="${parsedVersion.majorVersion}.${parsedVersion.minorVersion}.${parsedVersion.incrementalVersion}";
</configuration> </Export-Package>
</execution> </instructions>
</executions> </configuration>
</execution>
</executions>
</plugin> </plugin>
<plugin> <plugin>
<groupId>org.apache.maven.plugins</groupId> <groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-dependency-plugin</artifactId> <artifactId>maven-dependency-plugin</artifactId>
<version>3.0.0</version> <executions>
<executions> <execution>
<execution> <id>build-deps-file</id>
<id>build-deps-file</id> <phase>generate-resources</phase>
<phase>generate-resources</phase> <goals>
<goals> <goal>list</goal>
<goal>list</goal> </goals>
</goals> <configuration>
<configuration> <appendOutput>false</appendOutput>
<appendOutput>false</appendOutput> <outputFile>${project.build.directory}/deps.txt</outputFile>
<outputFile>${project.build.directory}/deps.txt</outputFile> <sort>true</sort>
<sort>true</sort> <excludeGroupIds>org.eclipse.jetty</excludeGroupIds>
<excludeGroupIds>org.eclipse.jetty</excludeGroupIds> <prependGroupId>true</prependGroupId>
<prependGroupId>true</prependGroupId> <includeScope>runtime</includeScope>
<includeScope>runtime</includeScope> </configuration>
</configuration> </execution>
</execution> </executions>
</executions>
</plugin> </plugin>
<plugin> <plugin>
<groupId>org.apache.maven.plugins</groupId> <groupId>org.apache.maven.plugins</groupId>
@ -118,15 +121,15 @@
match=" *(.*):(.*):jar:(.*):[a-z]*" match=" *(.*):(.*):jar:(.*):[a-z]*"
replace="maven://\1/\2/\3|lib/gcloud/\2-\3.jar" replace="maven://\1/\2/\3|lib/gcloud/\2-\3.jar"
byline="true" byline="true"
/> />
<replaceregexp file="${project.build.directory}/deps.txt" <replaceregexp file="${project.build.directory}/deps.txt"
match="The following files have been resolved:" match="The following files have been resolved:"
replace="[files]" replace="[files]"
/> />
</tasks> </tasks>
</configuration> </configuration>
</execution> </execution>
<execution> <execution>
<id>process-mod</id> <id>process-mod</id>
<phase>process-resources</phase> <phase>process-resources</phase>
<goals> <goals>
@ -141,8 +144,7 @@
</tasks> </tasks>
</configuration> </configuration>
</execution> </execution>
</executions>
</executions>
</plugin> </plugin>
<plugin> <plugin>
<groupId>org.apache.maven.plugins</groupId> <groupId>org.apache.maven.plugins</groupId>
@ -161,7 +163,7 @@
</execution> </execution>
</executions> </executions>
</plugin> </plugin>
</plugins> </plugins>
</build> </build>
</project> </project>

View File

@ -288,7 +288,9 @@ public class HTTP2CServerTest extends AbstractServerTest
{ {
AtomicLong fills = new AtomicLong(); AtomicLong fills = new AtomicLong();
// Remove "h2c", leaving only "http/1.1". // Remove "h2c", leaving only "http/1.1".
connector.clearConnectionFactories(); connector.stop();
connector.removeConnectionFactory("h2c");
connector.start();
HttpConnectionFactory connectionFactory = new HttpConnectionFactory() HttpConnectionFactory connectionFactory = new HttpConnectionFactory()
{ {
@Override @Override
@ -306,8 +308,10 @@ public class HTTP2CServerTest extends AbstractServerTest
return configure(connection, connector, endPoint); return configure(connection, connector, endPoint);
} }
}; };
connector.stop();
connector.addConnectionFactory(connectionFactory); connector.addConnectionFactory(connectionFactory);
connector.setDefaultProtocol(connectionFactory.getProtocol()); connector.setDefaultProtocol(connectionFactory.getProtocol());
connector.start();
// Now send a HTTP/2 direct request, which // Now send a HTTP/2 direct request, which
// will have the PRI * HTTP/2.0 preface. // 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 long _selectorIndex;
private int _reservedThreads = -1; 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(); int cpus = Runtime.getRuntime().availableProcessors();
return Math.max(1,Math.min(cpus/2,threads/16)); 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) protected SelectorManager(Executor executor, Scheduler scheduler, int selectors)
{ {
if (selectors <= 0) if (selectors <= 0)
selectors = defaultSchedulers(executor); selectors = defaultSelectors(executor);
this.executor = executor; this.executor = executor;
this.scheduler = scheduler; this.scheduler = scheduler;
_selectors = new ManagedSelector[selectors]; _selectors = new ManagedSelector[selectors];

View File

@ -289,7 +289,7 @@ public abstract class AbstractConnector extends ContainerLifeCycle implements Co
protected void interruptAcceptors() protected void interruptAcceptors()
{ {
try (Locker.Lock lock = _locker.lockIfNotHeld()) try (Locker.Lock lock = _locker.lock())
{ {
for (Thread thread : _acceptors) for (Thread thread : _acceptors)
{ {
@ -363,7 +363,6 @@ public abstract class AbstractConnector extends ContainerLifeCycle implements Co
_setAccepting.signalAll(); _setAccepting.signalAll();
} }
} }
@Override @Override
public ConnectionFactory getConnectionFactory(String protocol) public ConnectionFactory getConnectionFactory(String protocol)
@ -388,108 +387,105 @@ public abstract class AbstractConnector extends ContainerLifeCycle implements Co
public void addConnectionFactory(ConnectionFactory factory) 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<>(); key=StringUtil.asciiToLowerCase(key);
for (String key:factory.getProtocols()) ConnectionFactory old=_factories.remove(key);
if (old!=null)
{ {
key=StringUtil.asciiToLowerCase(key); if (old.getProtocol().equals(_defaultProtocol))
ConnectionFactory old=_factories.remove(key); _defaultProtocol=null;
if (old!=null) to_remove.add(old);
{
if (old.getProtocol().equals(_defaultProtocol))
_defaultProtocol=null;
to_remove.add(old);
}
_factories.put(key, 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);
} }
// 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) public void addFirstConnectionFactory(ConnectionFactory factory)
{ {
try (Locker.Lock lock = _locker.lock()) if (isRunning())
{ throw new IllegalStateException(getState());
List<ConnectionFactory> existings = new ArrayList<>(_factories.values());
_factories.clear(); List<ConnectionFactory> existings = new ArrayList<>(_factories.values());
addConnectionFactory(factory); _factories.clear();
for (ConnectionFactory existing : existings) addConnectionFactory(factory);
addConnectionFactory(existing); for (ConnectionFactory existing : existings)
_defaultProtocol = factory.getProtocol(); addConnectionFactory(existing);
} _defaultProtocol = factory.getProtocol();
} }
public void addIfAbsentConnectionFactory(ConnectionFactory factory) 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 (LOG.isDebugEnabled())
if (_factories.containsKey(key)) LOG.debug("{} addIfAbsent ignored {}", this, factory);
{ }
if (LOG.isDebugEnabled()) else
LOG.debug("{} addIfAbsent ignored {}", this, factory); {
} _factories.put(key, factory);
else addBean(factory);
{ if (_defaultProtocol==null)
_factories.put(key, factory); _defaultProtocol=factory.getProtocol();
addBean(factory); if (LOG.isDebugEnabled())
if (_defaultProtocol==null) LOG.debug("{} addIfAbsent added {}", this, factory);
_defaultProtocol=factory.getProtocol();
if (LOG.isDebugEnabled())
LOG.debug("{} addIfAbsent added {}", this, factory);
}
} }
} }
public ConnectionFactory removeConnectionFactory(String protocol) public ConnectionFactory removeConnectionFactory(String protocol)
{ {
try (Locker.Lock lock = _locker.lock()) if (isRunning())
{ throw new IllegalStateException(getState());
ConnectionFactory factory= _factories.remove(StringUtil.asciiToLowerCase(protocol));
removeBean(factory); ConnectionFactory factory= _factories.remove(StringUtil.asciiToLowerCase(protocol));
return factory; removeBean(factory);
} return factory;
} }
@Override @Override
public Collection<ConnectionFactory> getConnectionFactories() public Collection<ConnectionFactory> getConnectionFactories()
{ {
try (Locker.Lock lock = _locker.lock()) return _factories.values();
{
return _factories.values();
}
} }
public void setConnectionFactories(Collection<ConnectionFactory> factories) public void setConnectionFactories(Collection<ConnectionFactory> factories)
{ {
try (Locker.Lock lock = _locker.lock()) if (isRunning())
{ throw new IllegalStateException(getState());
List<ConnectionFactory> existing = new ArrayList<>(_factories.values());
for (ConnectionFactory factory: existing) List<ConnectionFactory> existing = new ArrayList<>(_factories.values());
removeConnectionFactory(factory.getProtocol()); for (ConnectionFactory factory: existing)
for (ConnectionFactory factory: factories) removeConnectionFactory(factory.getProtocol());
if (factory!=null) for (ConnectionFactory factory: factories)
addConnectionFactory(factory); if (factory!=null)
} addConnectionFactory(factory);
} }
@ManagedAttribute("The priority delta to apply to acceptor threads") @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") @ManagedAttribute("Protocols supported by this connector")
public List<String> getProtocols() public List<String> getProtocols()
{ {
synchronized (_factories) return new ArrayList<>(_factories.keySet());
{
return new ArrayList<>(_factories.keySet());
}
} }
public void clearConnectionFactories() public void clearConnectionFactories()
{ {
synchronized (_factories) if (isRunning())
{ throw new IllegalStateException(getState());
_factories.clear();
} _factories.clear();
} }
@ManagedAttribute("This connector's default protocol") @ManagedAttribute("This connector's default protocol")
@ -616,10 +609,7 @@ public abstract class AbstractConnector extends ContainerLifeCycle implements Co
if (_acceptorPriorityDelta!=0) if (_acceptorPriorityDelta!=0)
thread.setPriority(Math.max(Thread.MIN_PRIORITY,Math.min(Thread.MAX_PRIORITY,priority+_acceptorPriorityDelta))); thread.setPriority(Math.max(Thread.MIN_PRIORITY,Math.min(Thread.MAX_PRIORITY,priority+_acceptorPriorityDelta)));
synchronized (AbstractConnector.this) _acceptors[_id] = thread;
{
_acceptors[_id] = thread;
}
try 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 @Override
public Collection<EndPoint> getConnectedEndPoints() public Collection<EndPoint> getConnectedEndPoints()
{ {

View File

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

View File

@ -357,7 +357,7 @@ public abstract class HttpServerTestBase extends HttpServerTestFixture
try (Socket client = newSocket(_serverURI.getHost(), _serverURI.getPort()); try (Socket client = newSocket(_serverURI.getHost(), _serverURI.getPort());
StacklessLogging stackless = new StacklessLogging(HttpConnection.class)) 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(); OutputStream os = client.getOutputStream();
byte[] buffer = new byte[64 * 1024]; byte[] buffer = new byte[64 * 1024];
@ -379,9 +379,16 @@ public abstract class HttpServerTestBase extends HttpServerTestFixture
buffer[15]='H'; buffer[15]='H';
buffer[16]=':'; buffer[16]=':';
Arrays.fill(buffer,17,buffer.length-1,(byte)'A'); Arrays.fill(buffer,17,buffer.length-1,(byte)'A');
// write the request.
os.write(buffer); try
os.flush(); {
os.write(buffer);
os.flush();
}
catch(Exception e)
{
// Ignore exceptions during writing, so long as we can read response below
}
// Read the response. // Read the response.
try try
@ -391,7 +398,8 @@ public abstract class HttpServerTestBase extends HttpServerTestFixture
} }
catch(Exception e) 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.HttpsURLConnection;
import javax.net.ssl.SSLContext; import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLException;
import javax.net.ssl.SSLSession; import javax.net.ssl.SSLSession;
import javax.net.ssl.TrustManagerFactory; import javax.net.ssl.TrustManagerFactory;
import javax.servlet.ServletException; import javax.servlet.ServletException;
@ -118,14 +119,7 @@ public class SelectChannelServerSslTest extends HttpServerTestBase
@Override @Override
public void testFullHeader() throws Exception public void testFullHeader() throws Exception
{ {
try super.testFullHeader();
{
super.testFullHeader();
}
catch (SocketException e)
{
Log.getLogger(SslConnection.class).warn("Close overtook 400 response");
}
} }
@Before @Before
@ -167,7 +161,6 @@ public class SelectChannelServerSslTest extends HttpServerTestBase
} }
catch(Exception e) catch(Exception e)
{ {
e.printStackTrace();
throw new RuntimeException(e); throw new RuntimeException(e);
} }
} }

View File

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

View File

@ -447,8 +447,8 @@ public abstract class Resource implements ResourceFactory, Closeable
/* ------------------------------------------------------------ */ /* ------------------------------------------------------------ */
/** /**
* list of resource names contained in the given resource. * 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. * @return a list of resource names contained in the given resource, or null.
* Note: The resource names are not URL encoded. * Note: The resource names are not URL encoded.
*/ */
public abstract String[] list(); public abstract String[] list();

View File

@ -22,10 +22,10 @@ import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.ReentrantLock; import java.util.concurrent.locks.ReentrantLock;
/** /**
* Convenience Lock Wrapper. * <p>Convenience auto closeable {@link java.util.concurrent.locks.ReentrantLock} wrapper.</p>
* *
* <pre> * <pre>
* try(Locker.Lock lock = locker.lock()) * try (Locker.Lock lock = locker.lock())
* { * {
* // something * // something
* } * }
@ -33,44 +33,49 @@ import java.util.concurrent.locks.ReentrantLock;
*/ */
public class Locker public class Locker
{ {
private static final Lock LOCKED = new Lock();
private final ReentrantLock _lock = new ReentrantLock(); private final ReentrantLock _lock = new ReentrantLock();
private final Lock _unlock = new UnLock(); private final Lock _unlock = new Lock();
public Locker()
{
}
/**
* <p>Acquires the lock.</p>
*
* @return the lock to unlock
*/
public Lock lock() 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(); _lock.lock();
return _unlock; return _unlock;
} }
/**
* @deprecated use {@link #lock()} instead
*/
@Deprecated
public Lock lockIfNotHeld()
{
return lock();
}
/**
* @return whether this lock has been acquired
*/
public boolean isLocked() public boolean isLocked()
{ {
return _lock.isLocked(); return _lock.isLocked();
} }
public static class Lock implements AutoCloseable /**
* @return a {@link Condition} associated with this lock
*/
public Condition newCondition()
{ {
@Override return _lock.newCondition();
public void close()
{
}
} }
public class UnLock extends Lock /**
* <p>The unlocker object that unlocks when it is closed.</p>
*/
public class Lock implements AutoCloseable
{ {
@Override @Override
public void close() public void close()
@ -78,9 +83,9 @@ public class Locker
_lock.unlock(); _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.PermissionCollection;
import java.security.PrivilegedExceptionAction; import java.security.PrivilegedExceptionAction;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections; import java.util.Collections;
import java.util.Enumeration; import java.util.Enumeration;
import java.util.HashSet; import java.util.HashSet;
@ -327,6 +328,10 @@ public class WebAppClassLoader extends URLClassLoader
if (lib.exists() && lib.isDirectory()) if (lib.exists() && lib.isDirectory())
{ {
String[] files=lib.list(); String[] files=lib.list();
if (files != null)
{
Arrays.sort(files);
}
for (int f=0;files!=null && f<files.length;f++) for (int f=0;files!=null && f<files.length;f++)
{ {
try try

View File

@ -25,6 +25,7 @@ import java.net.URISyntaxException;
import java.net.URL; import java.net.URL;
import java.net.URLClassLoader; import java.net.URLClassLoader;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Arrays;
import java.util.List; import java.util.List;
import java.util.Locale; import java.util.Locale;
import java.util.Set; import java.util.Set;
@ -702,7 +703,7 @@ public class WebInfConfiguration extends AbstractConfiguration
* Look for jars in <code>WEB-INF/lib</code> * Look for jars in <code>WEB-INF/lib</code>
* *
* @param context the context to find the lib jars in * @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 * @throws Exception if unable to scan for lib jars
*/ */
protected List<Resource> findWebInfLibJars(WebAppContext context) protected List<Resource> findWebInfLibJars(WebAppContext context)
@ -717,6 +718,10 @@ public class WebInfConfiguration extends AbstractConfiguration
if (web_inf_lib.exists() && web_inf_lib.isDirectory()) if (web_inf_lib.exists() && web_inf_lib.isDirectory())
{ {
String[] files=web_inf_lib.list(); String[] files=web_inf_lib.list();
if (files != null)
{
Arrays.sort(files);
}
for (int f=0;files!=null && f<files.length;f++) for (int f=0;files!=null && f<files.length;f++)
{ {
try 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.contains;
import static org.hamcrest.Matchers.notNullValue; import static org.hamcrest.Matchers.notNullValue;
import static org.hamcrest.Matchers.nullValue; 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.assertThat;
import static org.junit.Assert.assertTrue; import static org.junit.Assert.assertTrue;
import static org.junit.Assume.assumeThat; import static org.junit.Assume.assumeThat;
import java.io.InputStream;
import java.lang.instrument.ClassFileTransformer; import java.lang.instrument.ClassFileTransformer;
import java.lang.instrument.IllegalClassFormatException; import java.lang.instrument.IllegalClassFormatException;
import java.net.URI; import java.net.URI;
@ -34,9 +37,11 @@ import java.nio.file.Path;
import java.security.ProtectionDomain; import java.security.ProtectionDomain;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Collections; import java.util.Collections;
import java.util.Enumeration;
import java.util.List; import java.util.List;
import org.eclipse.jetty.toolchain.test.MavenTestingUtils; 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.PathResource;
import org.eclipse.jetty.util.resource.Resource; import org.eclipse.jetty.util.resource.Resource;
import org.junit.Before; 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.File;
import java.io.IOException; import java.io.IOException;
import java.nio.file.Path;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Arrays; import java.util.Arrays;
import java.util.List; import java.util.List;
import java.util.stream.Collectors;
import javax.servlet.GenericServlet; import javax.servlet.GenericServlet;
import javax.servlet.ServletContext; 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.server.handler.HotSwapHandler;
import org.eclipse.jetty.servlet.ErrorPageErrorHandler; import org.eclipse.jetty.servlet.ErrorPageErrorHandler;
import org.eclipse.jetty.servlet.ServletContextHandler; 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.log.Log;
import org.eclipse.jetty.util.resource.PathResource;
import org.eclipse.jetty.util.resource.Resource; import org.eclipse.jetty.util.resource.Resource;
import org.eclipse.jetty.util.resource.ResourceCollection; import org.eclipse.jetty.util.resource.ResourceCollection;
import org.hamcrest.Matchers; import org.hamcrest.Matchers;
@ -378,4 +382,18 @@ public class WebAppContextTest
server.stop(); 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> <plugin>
<groupId>org.apache.maven.plugins</groupId> <groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-dependency-plugin</artifactId> <artifactId>maven-dependency-plugin</artifactId>
<version>3.0.1</version> <version>3.0.2</version>
</plugin> </plugin>
<plugin> <plugin>
<groupId>org.apache.maven.plugins</groupId> <groupId>org.apache.maven.plugins</groupId>
@ -1138,12 +1138,8 @@
</profile> </profile>
<!-- <!--
Usage: Usage:
configure settings.xml for jetty.eclipse.website server entry Javadoc aggregation for Jetty website
> mvn -Paggregate-site javadoc:aggregate > mvn -Paggregate-site clean install javadoc:aggregate -Dtest=foo
then
> mvn -N site:deploy
or
> mvn -N site:sshdeploy (for ssh users w/passphrase and ssh-agent)
--> -->
<profile> <profile>
<id>aggregate-site</id> <id>aggregate-site</id>