Merged branch 'jetty-9.4.x' into 'master'.

This commit is contained in:
Simone Bordet 2017-01-03 11:01:05 +01:00
commit 755de58ab6
18 changed files with 414 additions and 56 deletions

View File

@ -448,7 +448,7 @@ public class HttpClientTimeoutTest extends AbstractHttpClientServerTest
start(new EmptyServerHandler());
long timeout = 1000;
Request request = client.newRequest("badscheme://localhost:badport");
Request request = client.newRequest("badscheme://localhost:" + connector.getLocalPort());
try
{

View File

@ -18,23 +18,33 @@
package org.eclipse.jetty.deploy.providers;
import static org.junit.Assert.assertTrue;
import static org.junit.Assume.assumeTrue;
import java.io.File;
import java.nio.file.FileSystemException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.Arrays;
import org.eclipse.jetty.deploy.test.XmlConfiguredJetty;
import org.eclipse.jetty.toolchain.test.MavenTestingUtils;
import org.eclipse.jetty.toolchain.test.TestingDir;
import org.junit.After;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Ignore;
import org.junit.Rule;
import org.junit.Test;
@Ignore("See issue #1200")
public class WebAppProviderTest
{
@Rule
public TestingDir testdir = new TestingDir();
private static XmlConfiguredJetty jetty;
private boolean symlinkSupported = false;
@Before
public void setupEnvironment() throws Exception
{
@ -45,6 +55,20 @@ public class WebAppProviderTest
// Setup initial context
jetty.copyWebapp("foo-webapp-1.war","foo.war");
// Make symlink
Path pathWar3 = MavenTestingUtils.getTestResourcePathFile("webapps/foo-webapp-3.war");
Path pathBar = jetty.getJettyDir("webapps/bar.war").toPath();
try
{
Files.createSymbolicLink(pathBar, pathWar3);
symlinkSupported = true;
} catch (UnsupportedOperationException | FileSystemException e)
{
// if unable to create symlink, no point testing that feature
// this is the path that Microsoft Windows takes.
symlinkSupported = false;
}
// Should not throw an Exception
jetty.load();
@ -64,18 +88,34 @@ public class WebAppProviderTest
public void testStartupContext()
{
// Check Server for Handlers
jetty.assertWebAppContextsExists("/foo");
jetty.assertWebAppContextsExists("/bar", "/foo");
File workDir = jetty.getJettyDir("workish");
System.err.println("workDir="+workDir);
// Test for regressions
assertDirNotExists("root of work directory",workDir,"webinf");
assertDirNotExists("root of work directory",workDir,"jsp");
// Test for correct behaviour
Assert.assertTrue("Should have generated directory in work directory: " + workDir,hasJettyGeneratedPath(workDir,"foo.war"));
assertTrue("Should have generated directory in work directory: " + workDir,hasJettyGeneratedPath(workDir,"foo.war"));
}
@Test
public void testStartupSymlinkContext()
{
assumeTrue(symlinkSupported);
// Check for path
File barLink = jetty.getJettyDir("webapps/bar.war");
assertTrue("bar.war link exists: " + barLink.toString(), barLink.exists());
assertTrue("bar.war link isFile: " + barLink.toString(), barLink.isFile());
// Check Server for expected Handlers
jetty.assertWebAppContextsExists("/bar", "/foo");
// Test for expected work/temp directory behaviour
File workDir = jetty.getJettyDir("workish");
assertTrue("Should have generated directory in work directory: " + workDir,hasJettyGeneratedPath(workDir,"bar.war"));
}
private static boolean hasJettyGeneratedPath(File basedir, String expectedWarFilename)

View File

@ -75,7 +75,10 @@ server.setRequestLog(requestLog);
This configures a request log in `{$jetty.home}/logs` with filenames including the date.
Existing log files are appended to and the extended NCSA format is used in the GMT time zone.
You can customize the number of days you wish to keep request logs.
The above configuration enables Log Latency, which is the amount of time it took the server to handle the request.
This value is measured in milliseconds and is appended to the the log file for each request.
You can also customize the number of days you wish to keep request logs.
By default, log files are kept for 90 days before being deleted.
The value for `retainDays` (xml) or `setRetainDays` (Java) should be configured as _1 + n_ days.
For example, if you wanted to keep the logs for the current day and the day prior you would set the `retainDays` (or `setRetainDays`) value to 2.

View File

@ -21,6 +21,8 @@ package org.eclipse.jetty.http2.client;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.util.EnumSet;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;
@ -42,6 +44,7 @@ import org.eclipse.jetty.http2.frames.DataFrame;
import org.eclipse.jetty.http2.frames.HeadersFrame;
import org.eclipse.jetty.http2.frames.PushPromiseFrame;
import org.eclipse.jetty.http2.frames.ResetFrame;
import org.eclipse.jetty.http2.frames.SettingsFrame;
import org.eclipse.jetty.servlet.ServletContextHandler;
import org.eclipse.jetty.servlets.PushCacheFilter;
import org.eclipse.jetty.util.Callback;
@ -885,4 +888,91 @@ public class PushCacheFilterTest extends AbstractTest
Assert.assertTrue(primaryResponseLatch.await(5, TimeUnit.SECONDS));
Assert.assertFalse(pushLatch.await(1, TimeUnit.SECONDS));
}
@Test
public void testPushDisabled() throws Exception
{
final String primaryResource = "/primary.html";
final String secondaryResource = "/secondary.png";
final byte[] secondaryData = "SECONDARY".getBytes("UTF-8");
start(new HttpServlet()
{
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException
{
String requestURI = req.getRequestURI();
ServletOutputStream output = resp.getOutputStream();
if (requestURI.endsWith(primaryResource))
output.print("<html><head></head><body>PRIMARY</body></html>");
else if (requestURI.endsWith(secondaryResource))
output.write(secondaryData);
}
});
final Session session = newClient(new Session.Listener.Adapter()
{
@Override
public Map<Integer, Integer> onPreface(Session session)
{
Map<Integer, Integer> settings = new HashMap<>();
settings.put(SettingsFrame.ENABLE_PUSH, 0);
return settings;
}
});
// Request for the primary and secondary resource to build the cache.
final String referrerURI = "http://localhost:" + connector.getLocalPort() + servletPath + primaryResource;
HttpFields primaryFields = new HttpFields();
MetaData.Request primaryRequest = newRequest("GET", primaryResource, primaryFields);
final CountDownLatch warmupLatch = new CountDownLatch(1);
session.newStream(new HeadersFrame(primaryRequest, null, true), new Promise.Adapter<>(), new Stream.Listener.Adapter()
{
@Override
public void onData(Stream stream, DataFrame frame, Callback callback)
{
callback.succeeded();
if (frame.isEndStream())
{
// Request for the secondary resource.
HttpFields secondaryFields = new HttpFields();
secondaryFields.put(HttpHeader.REFERER, referrerURI);
MetaData.Request secondaryRequest = newRequest("GET", secondaryResource, secondaryFields);
session.newStream(new HeadersFrame(secondaryRequest, null, true), new Promise.Adapter<>(), new Stream.Listener.Adapter()
{
@Override
public void onData(Stream stream, DataFrame frame, Callback callback)
{
callback.succeeded();
warmupLatch.countDown();
}
});
}
}
});
Assert.assertTrue(warmupLatch.await(5, TimeUnit.SECONDS));
// Request again the primary resource, we should not get the secondary resource pushed.
primaryRequest = newRequest("GET", primaryResource, primaryFields);
final CountDownLatch primaryResponseLatch = new CountDownLatch(1);
final CountDownLatch pushLatch = new CountDownLatch(1);
session.newStream(new HeadersFrame(primaryRequest, null, true), new Promise.Adapter<>(), new Stream.Listener.Adapter()
{
@Override
public Stream.Listener onPush(Stream stream, PushPromiseFrame frame)
{
pushLatch.countDown();
return null;
}
@Override
public void onData(Stream stream, DataFrame frame, Callback callback)
{
callback.succeeded();
if (frame.isEndStream())
primaryResponseLatch.countDown();
}
});
Assert.assertFalse(pushLatch.await(1, TimeUnit.SECONDS));
Assert.assertTrue(primaryResponseLatch.await(5, TimeUnit.SECONDS));
}
}

View File

@ -310,7 +310,7 @@ public abstract class HTTP2Session extends ContainerLifeCycle implements ISessio
case SettingsFrame.HEADER_TABLE_SIZE:
{
if (LOG.isDebugEnabled())
LOG.debug("Update HPACK header table size to {}", value);
LOG.debug("Update HPACK header table size to {} for {}", value, this);
generator.setHeaderTableSize(value);
break;
}
@ -323,26 +323,28 @@ public abstract class HTTP2Session extends ContainerLifeCycle implements ISessio
return;
}
pushEnabled = value == 1;
if (LOG.isDebugEnabled())
LOG.debug("{} push for {}", pushEnabled ? "Enable" : "Disable", this);
break;
}
case SettingsFrame.MAX_CONCURRENT_STREAMS:
{
maxLocalStreams = value;
if (LOG.isDebugEnabled())
LOG.debug("Update max local concurrent streams to {}", maxLocalStreams);
LOG.debug("Update max local concurrent streams to {} for {}", maxLocalStreams, this);
break;
}
case SettingsFrame.INITIAL_WINDOW_SIZE:
{
if (LOG.isDebugEnabled())
LOG.debug("Update initial window size to {}", value);
LOG.debug("Update initial window size to {} for {}", value, this);
flowControl.updateInitialStreamWindow(this, value, false);
break;
}
case SettingsFrame.MAX_FRAME_SIZE:
{
if (LOG.isDebugEnabled())
LOG.debug("Update max frame size to {}", value);
LOG.debug("Update max frame size to {} for {}", value, this);
// SPEC: check the max frame size is sane.
if (value < Frame.DEFAULT_MAX_LENGTH || value > Frame.MAX_MAX_LENGTH)
{
@ -355,14 +357,14 @@ public abstract class HTTP2Session extends ContainerLifeCycle implements ISessio
case SettingsFrame.MAX_HEADER_LIST_SIZE:
{
if (LOG.isDebugEnabled())
LOG.debug("Update max header list size to {}", value);
LOG.debug("Update max header list size to {} for {}", value, this);
generator.setMaxHeaderListSize(value);
break;
}
default:
{
if (LOG.isDebugEnabled())
LOG.debug("Unknown setting {}:{}", key, value);
LOG.debug("Unknown setting {}:{} for {}", key, value, this);
break;
}
}

View File

@ -18,7 +18,6 @@
package org.eclipse.jetty.proxy;
import java.io.IOException;
import java.net.InetAddress;
import java.net.URI;
import java.net.UnknownHostException;
@ -633,10 +632,13 @@ public abstract class AbstractProxyServlet extends HttpServlet
{
// Use Jetty specific behavior to close connection.
proxyResponse.sendError(-1);
AsyncContext asyncContext = clientRequest.getAsyncContext();
asyncContext.complete();
if (clientRequest.isAsyncStarted())
{
AsyncContext asyncContext = clientRequest.getAsyncContext();
asyncContext.complete();
}
}
catch (IOException x)
catch (Throwable x)
{
if (_log.isDebugEnabled())
_log.debug(getRequestId(clientRequest) + " could not close the connection", failure);

View File

@ -11,7 +11,7 @@
<Set name="forwardedServerHeader"><Property name="jetty.httpConfig.forwardedServerHeader" default="X-Forwarded-Server"/></Set>
<Set name="forwardedProtoHeader"><Property name="jetty.httpConfig.forwardedProtoHeader" default="X-Forwarded-Proto"/></Set>
<Set name="forwardedForHeader"><Property name="jetty.httpConfig.forwardedForHeader" default="X-Forwarded-For"/></Set>
<Set name="forwardedForHeader"><Property name="jetty.httpConfig.forwardedHttpsHeader" default="X-Proxied-Https"/></Set>
<Set name="forwardedHttpsHeader"><Property name="jetty.httpConfig.forwardedHttpsHeader" default="X-Proxied-Https"/></Set>
<Set name="forwardedSslSessionIdHeader"><Property name="jetty.httpConfig.forwardedSslSessionIdHeader" default="Proxy-ssl-id" /></Set>
<Set name="forwardedCipherSuiteHeader"><Property name="jetty.httpConfig.forwardedCipherSuiteHeader" default="Proxy-auth-cert"/></Set>
</New>

View File

@ -244,7 +244,7 @@ public class Request implements HttpServletRequest
public PushBuilder getPushBuilder()
{
if (!isPushSupported())
throw new IllegalStateException();
throw new IllegalStateException(String.format("%s,push=%b,channel=%s", this, isPush(), getHttpChannel()));
HttpFields fields = new HttpFields(getHttpFields().size()+5);
boolean conditional=false;

View File

@ -307,6 +307,7 @@ public class Session implements SessionHandler.SessionIf
if (_handler == null)
throw new IllegalStateException ("No session manager for session "+ _sessionData.getId());
_handler.doSessionAttributeListeners(this,name,oldValue,newValue);
}
}
@ -897,10 +898,9 @@ public class Session implements SessionHandler.SessionIf
{
if (LOG.isDebugEnabled())
LOG.debug("invalidate {}",_sessionData.getId());
if (isValid())
if (_state == State.VALID || _state == State.INVALIDATING)
{
Set<String> keys = null;
do
{
keys = _sessionData.getKeys();

View File

@ -202,6 +202,22 @@ public class ForwardedRequestCustomizerTest
assertEquals("0",_results.poll());
}
@Test
public void testFor() throws Exception
{
String response=_connector.getResponse(
"GET / HTTP/1.1\n"+
"Host: myhost\n"+
"X-Forwarded-For: 10.9.8.7,6.5.4.3\n"+
"\n");
assertThat(response, Matchers.containsString("200 OK"));
assertEquals("http",_results.poll());
assertEquals("myhost",_results.poll());
assertEquals("80",_results.poll());
assertEquals("10.9.8.7",_results.poll());
assertEquals("0",_results.poll());
}
@Test
public void testLegacyProto() throws Exception
{

View File

@ -116,9 +116,11 @@ public class PushCacheFilter implements Filter
public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain) throws IOException, ServletException
{
HttpServletRequest request = (HttpServletRequest)req;
Request jettyRequest = Request.getBaseRequest(request);
if (HttpVersion.fromString(req.getProtocol()).getVersion() < 20 ||
!HttpMethod.GET.is(request.getMethod()))
if (HttpVersion.fromString(request.getProtocol()).getVersion() < 20 ||
!HttpMethod.GET.is(request.getMethod()) ||
!jettyRequest.isPushSupported())
{
chain.doFilter(req, resp);
return;
@ -127,7 +129,6 @@ public class PushCacheFilter implements Filter
long now = System.nanoTime();
// Iterating over fields is more efficient than multiple gets
Request jettyRequest = Request.getBaseRequest(request);
HttpFields fields = jettyRequest.getHttpFields();
boolean conditional = false;
String referrer = null;
@ -158,7 +159,7 @@ public class PushCacheFilter implements Filter
}
if (LOG.isDebugEnabled())
LOG.debug("{} {} referrer={} conditional={} synthetic={}", request.getMethod(), request.getRequestURI(), referrer, conditional, isPushRequest(request));
LOG.debug("{} {} referrer={} conditional={}", request.getMethod(), request.getRequestURI(), referrer, conditional);
String path = URIUtil.addPaths(request.getServletPath(), request.getPathInfo());
String query = request.getQueryString();
@ -256,7 +257,7 @@ public class PushCacheFilter implements Filter
}
// Push associated resources.
if (!isPushRequest(request) && !conditional && !primaryResource._associated.isEmpty())
if (!conditional && !primaryResource._associated.isEmpty())
{
PushBuilder pushBuilder = jettyRequest.getPushBuilder();
@ -282,11 +283,6 @@ public class PushCacheFilter implements Filter
chain.doFilter(request, resp);
}
private boolean isPushRequest(HttpServletRequest request)
{
return Boolean.TRUE.equals(request.getAttribute("org.eclipse.jetty.pushed"));
}
@Override
public void destroy()
{

View File

@ -546,6 +546,11 @@ public class StartArgs
{
CommandLineBuilder cmd = new CommandLineBuilder();
// Special Stop/Shutdown properties
ensureSystemPropertySet("STOP.PORT");
ensureSystemPropertySet("STOP.KEY");
ensureSystemPropertySet("STOP.WAIT");
if (addJavaInit)
{
cmd.addRawArg(CommandLineBuilder.findJavaBin());
@ -571,11 +576,7 @@ public class StartArgs
cmd.addRawArg(getMainClassname());
}
// Special Stop/Shutdown properties
ensureSystemPropertySet("STOP.PORT");
ensureSystemPropertySet("STOP.KEY");
ensureSystemPropertySet("STOP.WAIT");
// pass properties as args or as a file
if (dryRun && exec_properties == null)
{

View File

@ -21,7 +21,6 @@ package org.eclipse.jetty.websocket.jsr356;
import java.io.IOException;
import java.net.URI;
import java.security.Principal;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
@ -29,6 +28,7 @@ import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Set;
import java.util.stream.Collectors;
import javax.websocket.CloseReason;
import javax.websocket.EndpointConfig;
@ -42,7 +42,6 @@ import javax.websocket.WebSocketContainer;
import org.eclipse.jetty.util.log.Log;
import org.eclipse.jetty.util.log.Logger;
import org.eclipse.jetty.websocket.api.BatchMode;
import org.eclipse.jetty.websocket.api.extensions.ExtensionConfig;
import org.eclipse.jetty.websocket.common.LogicalConnection;
import org.eclipse.jetty.websocket.common.WebSocketSession;
import org.eclipse.jetty.websocket.common.events.EventDriver;
@ -241,13 +240,9 @@ public class JsrSession extends WebSocketSession implements javax.websocket.Sess
@Override
public List<Extension> getNegotiatedExtensions()
{
if (negotiatedExtensions == null)
if ((negotiatedExtensions == null) && getUpgradeResponse().getExtensions() != null)
{
negotiatedExtensions = new ArrayList<Extension>();
for (ExtensionConfig cfg : getUpgradeResponse().getExtensions())
{
negotiatedExtensions.add(new JsrExtension(cfg));
}
negotiatedExtensions = getUpgradeResponse().getExtensions().stream().map(JsrExtension::new).collect(Collectors.toList());
}
return negotiatedExtensions;
}

View File

@ -20,6 +20,7 @@ package org.eclipse.jetty.websocket.jsr356.server;
import static org.hamcrest.Matchers.is;
import static org.hamcrest.Matchers.nullValue;
import static org.junit.Assert.assertThat;
import java.io.PrintWriter;
import java.io.StringWriter;
@ -36,6 +37,7 @@ import java.util.TimeZone;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.atomic.AtomicReference;
import java.util.stream.Collectors;
import javax.websocket.DecodeException;
import javax.websocket.Decoder;
@ -97,9 +99,19 @@ public class ConfiguratorTest
public static class NoExtensionsSocket
{
@OnMessage
public String echo(String message)
public String echo(Session session, String message)
{
return message;
List<Extension> negotiatedExtensions = session.getNegotiatedExtensions();
if (negotiatedExtensions == null)
{
return "negotiatedExtensions=null";
}
else
{
return "negotiatedExtensions=" + negotiatedExtensions.stream()
.map((ext) -> ext.getName())
.collect(Collectors.joining(",", "[", "]"));
}
}
}
@ -420,8 +432,13 @@ public class ConfiguratorTest
client.addExtensions("identity");
client.connect();
client.sendStandardRequest();
HttpResponse response = client.readResponseHeader();
Assert.assertThat("response.extensions", response.getExtensionsHeader(), nullValue());
HttpResponse response = client.expectUpgradeResponse();
assertThat("response.extensions", response.getExtensionsHeader(), nullValue());
client.write(new TextFrame().setPayload("NegoExts"));
EventQueue<WebSocketFrame> frames = client.readFrames(1, 1, TimeUnit.SECONDS);
WebSocketFrame frame = frames.poll();
assertThat("Frame Response", frame.getPayloadAsUTF8(), is("negotiatedExtensions=[]"));
}
}

View File

@ -53,7 +53,6 @@ import org.eclipse.jetty.io.EndPoint;
import org.eclipse.jetty.util.B64Code;
import org.eclipse.jetty.util.MultiMap;
import org.eclipse.jetty.util.QuotedStringTokenizer;
import org.eclipse.jetty.util.StringUtil;
import org.eclipse.jetty.util.UrlEncoded;
import org.eclipse.jetty.util.log.Log;
import org.eclipse.jetty.util.log.Logger;
@ -91,10 +90,11 @@ public class WebSocketUpgradeRequest extends HttpRequest implements CompleteList
{
this.extensions = new ArrayList<>(request.getExtensions());
this.subProtocols = new ArrayList<>(request.getSubProtocols());
request.getHeaders().forEach((name, values) ->
values.forEach((value) -> header(name, value))
);
// Copy values from ClientUpgradeRequest into place
if (StringUtil.isNotBlank(request.getOrigin()))
header(HttpHeader.ORIGIN,request.getOrigin());
for (HttpCookie cookie : request.getCookies())
{
cookie(cookie);

View File

@ -53,6 +53,7 @@ import org.junit.Test;
/**
* Various connect condition testing
*/
@SuppressWarnings("Duplicates")
public class ClientConnectTest
{
@Rule
@ -161,7 +162,34 @@ public class ClientConnectTest
IBlockheadServerConnection connection = server.accept();
connection.upgrade();
}
@Test
public void testUpgradeWithAuthorizationHeader() throws Exception
{
JettyTrackingSocket wsocket = new JettyTrackingSocket();
URI wsUri = server.getWsUri();
ClientUpgradeRequest upgradeRequest = new ClientUpgradeRequest();
// actual value for this test is irrelevant, its important that this
// header actually be sent with a value (the value specified)
upgradeRequest.setHeader("Authorization", "Bogus SHA1");
Future<Session> future = client.connect(wsocket,wsUri,upgradeRequest);
IBlockheadServerConnection connection = server.accept();
List<String> requestLines = connection.upgrade();
Session sess = future.get(30,TimeUnit.SECONDS);
sess.close();
String authLine = requestLines.stream()
.filter((line) -> line.startsWith("Authorization:"))
.findFirst().get();
assertThat("Request Container Authorization", authLine, is("Authorization: Bogus SHA1"));
assertThat("Connect.UpgradeRequest", wsocket.connectUpgradeRequest, notNullValue());
assertThat("Connect.UpgradeResponse", wsocket.connectUpgradeResponse, notNullValue());
}
@Test
public void testBadHandshake() throws Exception
{

View File

@ -66,6 +66,7 @@ GIT_USER_EMAIL=`git config --get user.email`
#fi
VER_CURRENT=`sed -e "s/xmlns/ignore/" pom.xml | xmllint --xpath "/project/version/text()" -`
echo "Current pom.xml Version: ${VER_CURRENT}"
read -e -p "Release Version ? " VER_RELEASE
read -e -p "Next Dev Version ? " VER_NEXT
# VER_RELEASE=9.3.5.v20151012
@ -87,8 +88,8 @@ if [ ! -d "$ALT_DEPLOY_DIR" ] ; then
mkdir -p "$ALT_DEPLOY_DIR"
fi
DEPLOY_OPTS="-Dmaven.test.failure.ignore=true"
# DEPLOY_OPTS="-Dtest=None"
# DEPLOY_OPTS="-Dmaven.test.failure.ignore=true"
DEPLOY_OPTS="-Dtest=None"
# DEPLOY_OPTS="$DEPLOY_OPTS -DaltDeploymentRepository=intarget::default::file://$ALT_DEPLOY_DIR/"
echo ""
@ -129,10 +130,13 @@ echo ""
if proceedyn "Are you sure you want to release using above? (y/N)" n; then
echo ""
if proceedyn "Update VERSION.txt for $VER_RELEASE? (Y/n)" y; then
mvn -N -Pupdate-version
mvn -N -Pupdate-version generate-resources
cp VERSION.txt VERSION.txt.backup
cat VERSION.txt.backup | sed -e "s/$VER_CURRENT/$VER_RELEASE/" > VERSION.txt
rm VERSION.txt.backup
echo "VERIFY the following files (in a different console window) before continuing."
echo " VERSION.txt - top section"
echo " target/vers-tag.txt - for the tag commit message"
fi
# This is equivalent to 'mvn release:prepare'
@ -146,7 +150,8 @@ if proceedyn "Are you sure you want to release using above? (y/N)" n; then
fi
if proceedyn "Create Tag $TAG_NAME? (Y/n)" y; then
echo "TODO: Sign tags with GIT_USER_EMAIL=$GIT_USER_EMAIL"
git tag -m "Creating tag $TAG_NAME" $TAG_NAME
echo "Using target/vers-tag.txt as tag text"
git tag --file=target/vers-tag.txt $TAG_NAME
fi
# This is equivalent to 'mvn release:perform'

View File

@ -0,0 +1,163 @@
//
// ========================================================================
// Copyright (c) 1995-2016 Mort Bay Consulting Pty. Ltd.
// ------------------------------------------------------------------------
// All rights reserved. This program and the accompanying materials
// are made available under the terms of the Eclipse Public License v1.0
// and Apache License v2.0 which accompanies this distribution.
//
// The Eclipse Public License is available at
// http://www.eclipse.org/legal/epl-v10.html
//
// The Apache License v2.0 is available at
// http://www.opensource.org/licenses/apache2.0.php
//
// You may elect to redistribute this code under either of these licenses.
// ========================================================================
//
package org.eclipse.jetty.server.session;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertTrue;
import java.io.IOException;
import java.io.Serializable;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import javax.servlet.http.HttpSessionBindingEvent;
import javax.servlet.http.HttpSessionBindingListener;
import org.eclipse.jetty.client.HttpClient;
import org.eclipse.jetty.client.api.ContentResponse;
import org.eclipse.jetty.client.api.Request;
import org.eclipse.jetty.servlet.ServletContextHandler;
import org.eclipse.jetty.servlet.ServletHolder;
import org.junit.Test;
/**
* SessionListenerTest
*
* Test that the HttpSessionBindingListeners are called.
*/
public class SessionListenerTest extends AbstractTestBase
{
public static class MySessionBindingListener implements HttpSessionBindingListener, Serializable
{
boolean unbound = false;
boolean bound = false;
public void valueUnbound(HttpSessionBindingEvent event)
{
unbound = true;
}
public void valueBound(HttpSessionBindingEvent event)
{
bound = true;
}
}
public static class Foo implements Serializable
{
public boolean bar = false;
public boolean getBar() { return bar;};
}
@Override
public AbstractTestServer createServer(int port, int max, int scavenge, int evictionPolicy) throws Exception
{
return new HashTestServer(port,max,scavenge,evictionPolicy);
}
@Test
public void testListener() throws Exception
{
String contextPath = "";
String servletMapping = "/server";
int inactivePeriod = 6;
int scavengePeriod = 3;
AbstractTestServer server = createServer(0, inactivePeriod, scavengePeriod, SessionCache.NEVER_EVICT);
ServletContextHandler context = server.addContext(contextPath);
TestServlet servlet = new TestServlet();
ServletHolder holder = new ServletHolder(servlet);
context.addServlet(holder, servletMapping);
try
{
server.start();
int port1 = server.getPort();
HttpClient client = new HttpClient();
client.start();
try
{
String url = "http://localhost:" + port1 + contextPath + servletMapping;
// Create the session
ContentResponse response1 = client.GET(url + "?action=init");
assertEquals(HttpServletResponse.SC_OK,response1.getStatus());
String sessionCookie = response1.getHeaders().get("Set-Cookie");
assertTrue(sessionCookie != null);
// Mangle the cookie, replacing Path with $Path, etc.
sessionCookie = sessionCookie.replaceFirst("(\\W)(P|p)ath=", "$1\\$Path=");
assertTrue (servlet.listener.bound);
// Make a request which will invalidate the existing session
Request request2 = client.newRequest(url + "?action=test");
request2.header("Cookie", sessionCookie);
ContentResponse response2 = request2.send();
assertEquals(HttpServletResponse.SC_OK,response2.getStatus());
assertTrue (servlet.listener.unbound);
}
finally
{
client.stop();
}
}
finally
{
server.stop();
}
}
public static class TestServlet extends HttpServlet
{
public static final MySessionBindingListener listener = new MySessionBindingListener();
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse httpServletResponse) throws ServletException, IOException
{
String action = request.getParameter("action");
if ("init".equals(action))
{
HttpSession session = request.getSession(true);
session.setAttribute("foo", listener);
assertNotNull(session);
}
else if ("test".equals(action))
{
HttpSession session = request.getSession(false);
assertNotNull(session);
//invalidate existing session
session.invalidate();
}
}
}
}