Merge branch 'jetty-9.3.x'
This commit is contained in:
commit
2aee8a7893
|
@ -18,8 +18,9 @@
|
|||
|
||||
package org.eclipse.jetty.jstl;
|
||||
|
||||
import static org.hamcrest.Matchers.*;
|
||||
import static org.junit.Assert.*;
|
||||
import static org.hamcrest.Matchers.containsString;
|
||||
import static org.hamcrest.Matchers.not;
|
||||
import static org.junit.Assert.assertThat;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
|
@ -75,6 +76,16 @@ public class JstlTest
|
|||
WebAppContext context = new WebAppContext();
|
||||
context.setContextPath("/");
|
||||
|
||||
/* TODO: Bug #486530 - sub-handler on WebAppContext prevents startup
|
||||
context.setHandler(new AbstractHandler()
|
||||
{
|
||||
public void handle(String target, Request baseRequest, HttpServletRequest request, HttpServletResponse response)
|
||||
throws IOException, ServletException
|
||||
{
|
||||
}
|
||||
});
|
||||
*/
|
||||
|
||||
File scratchDir = MavenTestingUtils.getTargetFile("tests/" + JstlTest.class.getSimpleName() + "-scratch");
|
||||
FS.ensureEmpty(scratchDir);
|
||||
JspConfig.init(context,testWebAppDir.toURI(),scratchDir);
|
||||
|
|
|
@ -0,0 +1,3 @@
|
|||
org.eclipse.jetty.util.log.class=org.eclipse.jetty.util.log.StdErrLog
|
||||
# org.eclipse.jetty.LEVEL=INFO
|
||||
# org.eclipse.jetty.util.LEVEL=DEBUG
|
|
@ -66,7 +66,7 @@
|
|||
|
||||
<div id='blog'>
|
||||
<h1>Jetty Blog</h1>
|
||||
<iframe src="http://www.webtide.com/blog.jsp" />
|
||||
<iframe src="https://webtide.com/blog.jsp" />
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
|
|
|
@ -7,13 +7,13 @@
|
|||
|
||||
<Configure id="Server" class="org.eclipse.jetty.server.Server">
|
||||
|
||||
<Get id="oldhandler" name="handler" />
|
||||
<Set name="handler">
|
||||
<New id="JamonHandler" class="com.jamonapi.http.JAMonJettyHandlerNew">
|
||||
<Set name="handler"><Ref refid="oldhandler" /></Set>
|
||||
<Set name="summaryLabels"><Property name="jamon.summaryLabels" /></Set>
|
||||
</New>
|
||||
</Set>
|
||||
<Call name="insertHandler">
|
||||
<Arg>
|
||||
<New id="JamonHandler" class="com.jamonapi.http.JAMonJettyHandlerNew">
|
||||
<Set name="summaryLabels"><Property name="jamon.summaryLabels" /></Set>
|
||||
</New>
|
||||
</Arg>
|
||||
</Call>
|
||||
|
||||
<Ref refid="Contexts">
|
||||
<Call name="addHandler">
|
||||
|
|
|
@ -334,6 +334,8 @@ public class HttpURI
|
|||
state=State.PORT;
|
||||
break;
|
||||
case '@':
|
||||
if (_user!=null)
|
||||
throw new IllegalArgumentException("Bad authority");
|
||||
_user=uri.substring(mark,i);
|
||||
mark=i+1;
|
||||
break;
|
||||
|
@ -372,7 +374,16 @@ public class HttpURI
|
|||
|
||||
case PORT:
|
||||
{
|
||||
if (c=='/')
|
||||
if (c=='@')
|
||||
{
|
||||
if (_user!=null)
|
||||
throw new IllegalArgumentException("Bad authority");
|
||||
// It wasn't a port, but a password!
|
||||
_user=_host+":"+uri.substring(mark,i);
|
||||
mark=i+1;
|
||||
state=State.HOST;
|
||||
}
|
||||
else if (c=='/')
|
||||
{
|
||||
_port=TypeUtil.parseInt(uri,mark,i-mark,10);
|
||||
path_mark=mark=i;
|
||||
|
@ -746,5 +757,11 @@ public class HttpURI
|
|||
return _host;
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
public String getUser()
|
||||
{
|
||||
return _user;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
|
|
@ -22,6 +22,7 @@ package org.eclipse.jetty.http;
|
|||
import static org.junit.Assert.*;
|
||||
|
||||
import java.io.UnsupportedEncodingException;
|
||||
import java.net.URI;
|
||||
import java.net.URLDecoder;
|
||||
import java.net.URLEncoder;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
|
@ -193,4 +194,13 @@ public class HttpURITest
|
|||
assertEquals("http:/path/info",uri.toString());
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testBasicAuthCredentials() throws Exception
|
||||
{
|
||||
HttpURI uri = new HttpURI("http://user:password@example.com:8888/blah");
|
||||
assertEquals("http://user:password@example.com:8888/blah", uri.toString());
|
||||
assertEquals(uri.getAuthority(), "example.com:8888");
|
||||
assertEquals(uri.getUser(), "user:password");
|
||||
}
|
||||
}
|
||||
|
|
|
@ -43,6 +43,7 @@ import org.eclipse.jetty.util.component.Dumpable;
|
|||
import org.eclipse.jetty.util.log.Log;
|
||||
import org.eclipse.jetty.util.log.Logger;
|
||||
import org.eclipse.jetty.util.thread.ExecutionStrategy;
|
||||
import org.eclipse.jetty.util.thread.ExecutionStrategy.Rejectable;
|
||||
import org.eclipse.jetty.util.thread.Locker;
|
||||
import org.eclipse.jetty.util.thread.Scheduler;
|
||||
|
||||
|
@ -536,7 +537,7 @@ public class ManagedSelector extends AbstractLifeCycle implements Runnable, Dump
|
|||
}
|
||||
}
|
||||
|
||||
class Accept implements Runnable
|
||||
class Accept implements Runnable, Rejectable
|
||||
{
|
||||
private final SelectableChannel channel;
|
||||
private final Object attachment;
|
||||
|
@ -547,6 +548,13 @@ public class ManagedSelector extends AbstractLifeCycle implements Runnable, Dump
|
|||
this.attachment = attachment;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void reject()
|
||||
{
|
||||
LOG.debug("rejected accept {}",channel);
|
||||
closeNoExceptions(channel);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void run()
|
||||
{
|
||||
|
@ -563,7 +571,7 @@ public class ManagedSelector extends AbstractLifeCycle implements Runnable, Dump
|
|||
}
|
||||
}
|
||||
|
||||
private class CreateEndPoint implements Product
|
||||
private class CreateEndPoint implements Product, Rejectable
|
||||
{
|
||||
private final SelectableChannel channel;
|
||||
private final SelectionKey key;
|
||||
|
@ -588,6 +596,13 @@ public class ManagedSelector extends AbstractLifeCycle implements Runnable, Dump
|
|||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void reject()
|
||||
{
|
||||
LOG.debug("rejected create {}",channel);
|
||||
closeNoExceptions(channel);
|
||||
}
|
||||
|
||||
protected void failed(Throwable failure)
|
||||
{
|
||||
closeNoExceptions(channel);
|
||||
|
|
|
@ -18,8 +18,8 @@
|
|||
|
||||
package org.eclipse.jetty.io;
|
||||
|
||||
import java.nio.channels.SelectableChannel;
|
||||
import java.nio.channels.SelectionKey;
|
||||
import java.nio.channels.SocketChannel;
|
||||
|
||||
import org.eclipse.jetty.util.log.Log;
|
||||
import org.eclipse.jetty.util.log.Logger;
|
||||
|
@ -33,7 +33,7 @@ public class SelectChannelEndPoint extends SocketChannelEndPoint implements Mana
|
|||
{
|
||||
public static final Logger LOG = Log.getLogger(SelectChannelEndPoint.class);
|
||||
|
||||
public SelectChannelEndPoint(SocketChannel channel, ManagedSelector selector, SelectionKey key, Scheduler scheduler, long idleTimeout)
|
||||
public SelectChannelEndPoint(SelectableChannel channel, ManagedSelector selector, SelectionKey key, Scheduler scheduler, long idleTimeout)
|
||||
{
|
||||
super(channel,selector,key,scheduler);
|
||||
setIdleTimeout(idleTimeout);
|
||||
|
|
|
@ -37,9 +37,12 @@ import java.nio.channels.SelectionKey;
|
|||
import java.nio.channels.ServerSocketChannel;
|
||||
import java.nio.channels.SocketChannel;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.util.concurrent.ArrayBlockingQueue;
|
||||
import java.util.concurrent.BlockingQueue;
|
||||
import java.util.concurrent.CountDownLatch;
|
||||
import java.util.concurrent.ExecutionException;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
|
||||
import org.eclipse.jetty.util.BufferUtil;
|
||||
import org.eclipse.jetty.util.Callback;
|
||||
|
@ -49,9 +52,11 @@ import org.eclipse.jetty.util.log.Logger;
|
|||
import org.eclipse.jetty.util.thread.QueuedThreadPool;
|
||||
import org.eclipse.jetty.util.thread.Scheduler;
|
||||
import org.eclipse.jetty.util.thread.TimerScheduler;
|
||||
import org.hamcrest.Matchers;
|
||||
import org.junit.After;
|
||||
import org.junit.Assert;
|
||||
import org.junit.Before;
|
||||
import org.junit.Ignore;
|
||||
import org.junit.Test;
|
||||
|
||||
public class SelectChannelEndPointTest
|
||||
|
@ -124,10 +129,18 @@ public class SelectChannelEndPointTest
|
|||
ByteBuffer _in = BufferUtil.allocate(32 * 1024);
|
||||
ByteBuffer _out = BufferUtil.allocate(32 * 1024);
|
||||
long _last = -1;
|
||||
final CountDownLatch _latch;
|
||||
|
||||
public TestConnection(EndPoint endp)
|
||||
{
|
||||
super(endp, _threadPool);
|
||||
_latch=null;
|
||||
}
|
||||
|
||||
public TestConnection(EndPoint endp,CountDownLatch latch)
|
||||
{
|
||||
super(endp, _threadPool);
|
||||
_latch=latch;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -153,6 +166,18 @@ public class SelectChannelEndPointTest
|
|||
@Override
|
||||
public void onFillable()
|
||||
{
|
||||
if (_latch!=null)
|
||||
{
|
||||
try
|
||||
{
|
||||
_latch.await();
|
||||
}
|
||||
catch (InterruptedException e)
|
||||
{
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
Callback blocking = _blockingRead;
|
||||
if (blocking!=null)
|
||||
{
|
||||
|
@ -671,4 +696,132 @@ public class SelectChannelEndPointTest
|
|||
}
|
||||
assertFalse(server.isOpen());
|
||||
}
|
||||
|
||||
|
||||
// TODO make this test reliable
|
||||
@Test
|
||||
@Ignore
|
||||
public void testRejectedExecution() throws Exception
|
||||
{
|
||||
_manager.stop();
|
||||
_threadPool.stop();
|
||||
|
||||
final CountDownLatch latch = new CountDownLatch(1);
|
||||
|
||||
BlockingQueue<Runnable> q = new ArrayBlockingQueue<>(4);
|
||||
_threadPool = new QueuedThreadPool(4,4,60000,q);
|
||||
_manager = new SelectorManager(_threadPool, _scheduler, 1)
|
||||
{
|
||||
@Override
|
||||
public Connection newConnection(SelectableChannel channel, EndPoint endpoint, Object attachment) throws IOException
|
||||
{
|
||||
return new TestConnection(endpoint,latch);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected EndPoint newEndPoint(SelectableChannel channel, ManagedSelector selector, SelectionKey selectionKey) throws IOException
|
||||
{
|
||||
SelectChannelEndPoint endp = new SelectChannelEndPoint(channel, selector, selectionKey, getScheduler(), 60000);
|
||||
_lastEndPoint = endp;
|
||||
_lastEndPointLatch.countDown();
|
||||
return endp;
|
||||
}
|
||||
};
|
||||
|
||||
_threadPool.start();
|
||||
_manager.start();
|
||||
|
||||
AtomicInteger timeout = new AtomicInteger();
|
||||
AtomicInteger rejections = new AtomicInteger();
|
||||
AtomicInteger echoed = new AtomicInteger();
|
||||
|
||||
CountDownLatch closed = new CountDownLatch(20);
|
||||
for (int i=0;i<20;i++)
|
||||
{
|
||||
new Thread()
|
||||
{
|
||||
public void run()
|
||||
{
|
||||
try(Socket client = newClient();)
|
||||
{
|
||||
client.setSoTimeout(5000);
|
||||
|
||||
SocketChannel server = _connector.accept();
|
||||
server.configureBlocking(false);
|
||||
|
||||
_manager.accept(server);
|
||||
|
||||
// Write client to server
|
||||
client.getOutputStream().write("HelloWorld".getBytes(StandardCharsets.UTF_8));
|
||||
client.getOutputStream().flush();
|
||||
client.shutdownOutput();
|
||||
|
||||
// Verify echo server to client
|
||||
for (char c : "HelloWorld".toCharArray())
|
||||
{
|
||||
int b = client.getInputStream().read();
|
||||
assertTrue(b > 0);
|
||||
assertEquals(c, (char)b);
|
||||
}
|
||||
assertEquals(-1,client.getInputStream().read());
|
||||
echoed.incrementAndGet();
|
||||
}
|
||||
catch(SocketTimeoutException x)
|
||||
{
|
||||
x.printStackTrace();
|
||||
timeout.incrementAndGet();
|
||||
}
|
||||
catch(Throwable x)
|
||||
{
|
||||
rejections.incrementAndGet();
|
||||
}
|
||||
finally
|
||||
{
|
||||
closed.countDown();
|
||||
}
|
||||
}
|
||||
}.start();
|
||||
}
|
||||
|
||||
// unblock the handling
|
||||
latch.countDown();
|
||||
|
||||
// wait for all clients to complete or fail
|
||||
closed.await();
|
||||
|
||||
// assert some clients must have been rejected
|
||||
Assert.assertThat(rejections.get(),Matchers.greaterThan(0));
|
||||
// but not all of them
|
||||
Assert.assertThat(rejections.get(),Matchers.lessThan(20));
|
||||
// none should have timed out
|
||||
Assert.assertThat(timeout.get(),Matchers.equalTo(0));
|
||||
// and the rest should have worked
|
||||
Assert.assertThat(echoed.get(),Matchers.equalTo(20-rejections.get()));
|
||||
|
||||
// and the selector is still working for new requests
|
||||
try(Socket client = newClient();)
|
||||
{
|
||||
client.setSoTimeout(5000);
|
||||
|
||||
SocketChannel server = _connector.accept();
|
||||
server.configureBlocking(false);
|
||||
|
||||
_manager.accept(server);
|
||||
|
||||
// Write client to server
|
||||
client.getOutputStream().write("HelloWorld".getBytes(StandardCharsets.UTF_8));
|
||||
client.getOutputStream().flush();
|
||||
client.shutdownOutput();
|
||||
|
||||
// Verify echo server to client
|
||||
for (char c : "HelloWorld".toCharArray())
|
||||
{
|
||||
int b = client.getInputStream().read();
|
||||
assertTrue(b > 0);
|
||||
assertEquals(c, (char)b);
|
||||
}
|
||||
assertEquals(-1,client.getInputStream().read());
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
|
|
@ -19,9 +19,19 @@
|
|||
package org.eclipse.jetty.quickstart;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.net.URI;
|
||||
import java.net.URL;
|
||||
import java.nio.file.FileSystems;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.Comparator;
|
||||
import java.util.List;
|
||||
import java.util.Stack;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
import org.eclipse.jetty.util.URIUtil;
|
||||
import org.eclipse.jetty.util.log.Log;
|
||||
|
@ -30,7 +40,8 @@ import org.eclipse.jetty.util.resource.Resource;
|
|||
|
||||
/**
|
||||
* Normalize Attribute to String.
|
||||
* <p>Replaces and expands:
|
||||
* <p>
|
||||
* Replaces and expands:
|
||||
* <ul>
|
||||
* <li>${WAR}</li>
|
||||
* <li>${jetty.base}</li>
|
||||
|
@ -42,72 +53,151 @@ import org.eclipse.jetty.util.resource.Resource;
|
|||
public class AttributeNormalizer
|
||||
{
|
||||
private static final Logger LOG = Log.getLogger(AttributeNormalizer.class);
|
||||
private final Path _warPath;
|
||||
private final Path _jettyBasePath;
|
||||
private final Path _jettyHomePath;
|
||||
private final Path _userHomePath;
|
||||
private final Path _userDirPath;
|
||||
private static final Pattern __propertyPattern = Pattern.compile("(?<=[^$]|^)\\$\\{([^}]*)\\}");
|
||||
|
||||
private static class PathAttribute
|
||||
{
|
||||
public final Path path;
|
||||
public final String key;
|
||||
private int weight = -1;
|
||||
|
||||
public PathAttribute(String key, Path path) throws IOException
|
||||
{
|
||||
this.key = key;
|
||||
this.path = toCanonicalPath(path);
|
||||
// TODO: Don't allow non-directory paths? (but what if the path doesn't exist?)
|
||||
}
|
||||
|
||||
public PathAttribute(String key, String systemPropertyKey) throws IOException
|
||||
{
|
||||
this(key, toCanonicalPath(System.getProperty(systemPropertyKey)));
|
||||
}
|
||||
|
||||
private static Path toCanonicalPath(String path) throws IOException
|
||||
{
|
||||
if (path == null)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
return toCanonicalPath(FileSystems.getDefault().getPath(path));
|
||||
}
|
||||
|
||||
private static Path toCanonicalPath(Path path) throws IOException
|
||||
{
|
||||
if (path == null)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
if (Files.exists(path))
|
||||
{
|
||||
return path.toRealPath();
|
||||
}
|
||||
return path.toAbsolutePath();
|
||||
}
|
||||
|
||||
public PathAttribute weight(int newweight)
|
||||
{
|
||||
this.weight = newweight;
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString()
|
||||
{
|
||||
return String.format("PathAttribute[%s=>%s,%d]",key,path,weight);
|
||||
}
|
||||
}
|
||||
|
||||
private static class PathAttributeComparator implements Comparator<PathAttribute>
|
||||
{
|
||||
@Override
|
||||
public int compare(PathAttribute o1, PathAttribute o2)
|
||||
{
|
||||
if( (o1.path == null) && (o2.path != null) )
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
if( (o1.path != null) && (o2.path == null) )
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
// Different lengths?
|
||||
int diff = o2.path.getNameCount() - o1.path.getNameCount();
|
||||
if(diff != 0)
|
||||
{
|
||||
return diff;
|
||||
}
|
||||
|
||||
// Different names?
|
||||
diff = o2.path.compareTo(o1.path);
|
||||
if(diff != 0)
|
||||
{
|
||||
return diff;
|
||||
}
|
||||
|
||||
// The paths are the same, base now on weight
|
||||
return o2.weight - o1.weight;
|
||||
}
|
||||
}
|
||||
|
||||
private List<PathAttribute> attributes = new ArrayList<>();
|
||||
|
||||
public AttributeNormalizer(Resource baseResource)
|
||||
{
|
||||
try
|
||||
{
|
||||
_warPath=baseResource==null?null:baseResource.getFile().toPath();
|
||||
_jettyBasePath=systemPath("jetty.base");
|
||||
_jettyHomePath=systemPath("jetty.home");
|
||||
_userHomePath=systemPath("user.home");
|
||||
_userDirPath=systemPath("user.dir");
|
||||
// Track path attributes for expansion
|
||||
attributes.add(new PathAttribute("WAR", baseResource == null ? null : baseResource.getFile().toPath()).weight(10));
|
||||
attributes.add(new PathAttribute("jetty.base", "jetty.base").weight(9));
|
||||
attributes.add(new PathAttribute("jetty.home", "jetty.home").weight(8));
|
||||
attributes.add(new PathAttribute("user.home", "user.home").weight(7));
|
||||
attributes.add(new PathAttribute("user.dir", "user.dir").weight(6));
|
||||
|
||||
Collections.sort(attributes, new PathAttributeComparator());
|
||||
}
|
||||
catch(Exception e)
|
||||
catch (Exception e)
|
||||
{
|
||||
throw new IllegalArgumentException(e);
|
||||
}
|
||||
}
|
||||
|
||||
private static Path systemPath(String property) throws Exception
|
||||
{
|
||||
String p=System.getProperty(property);
|
||||
if (p!=null)
|
||||
return new File(p).getAbsoluteFile().getCanonicalFile().toPath();
|
||||
return null;
|
||||
}
|
||||
|
||||
public String normalize(Object o)
|
||||
{
|
||||
try
|
||||
{
|
||||
// Find a URI
|
||||
URI uri=null;
|
||||
URI uri = null;
|
||||
if (o instanceof URI)
|
||||
uri=(URI)o;
|
||||
uri = (URI)o;
|
||||
else if (o instanceof URL)
|
||||
uri = ((URL)o).toURI();
|
||||
else if (o instanceof File)
|
||||
uri = ((File)o).toURI();
|
||||
else
|
||||
{
|
||||
String s=o.toString();
|
||||
uri=new URI(s);
|
||||
if (uri.getScheme()==null)
|
||||
String s = o.toString();
|
||||
uri = new URI(s);
|
||||
if (uri.getScheme() == null)
|
||||
return s;
|
||||
}
|
||||
|
||||
if ("jar".equalsIgnoreCase(uri.getScheme()))
|
||||
{
|
||||
String raw = uri.getRawSchemeSpecificPart();
|
||||
int bang=raw.indexOf("!/");
|
||||
String normal=normalize(raw.substring(0,bang));
|
||||
String suffix=raw.substring(bang);
|
||||
return "jar:"+normal+suffix;
|
||||
int bang = raw.indexOf("!/");
|
||||
String normal = normalize(raw.substring(0,bang));
|
||||
String suffix = raw.substring(bang);
|
||||
return "jar:" + normal + suffix;
|
||||
}
|
||||
else if ("file".equalsIgnoreCase(uri.getScheme()))
|
||||
{
|
||||
return "file:"+normalizePath(new File(uri).toPath());
|
||||
return "file:" + normalizePath(new File(uri).toPath());
|
||||
}
|
||||
|
||||
}
|
||||
catch(Exception e)
|
||||
catch (Exception e)
|
||||
{
|
||||
LOG.warn(e);
|
||||
}
|
||||
|
@ -116,42 +206,116 @@ public class AttributeNormalizer
|
|||
|
||||
public String normalizePath(Path path)
|
||||
{
|
||||
if (_warPath!=null && path.startsWith(_warPath))
|
||||
return URIUtil.addPaths("${WAR}",_warPath.relativize(path).toString());
|
||||
if (_jettyBasePath!=null && path.startsWith(_jettyBasePath))
|
||||
return URIUtil.addPaths("${jetty.base}",_jettyBasePath.relativize(path).toString());
|
||||
if (_jettyHomePath!=null && path.startsWith(_jettyHomePath))
|
||||
return URIUtil.addPaths("${jetty.home}",_jettyHomePath.relativize(path).toString());
|
||||
if (_userHomePath!=null && path.startsWith(_userHomePath))
|
||||
return URIUtil.addPaths("${user.home}",_userHomePath.relativize(path).toString());
|
||||
if (_userDirPath!=null && path.startsWith(_userDirPath))
|
||||
return URIUtil.addPaths("${user.dir}",_userDirPath.relativize(path).toString());
|
||||
for (PathAttribute attr : attributes)
|
||||
{
|
||||
if (attr.path == null)
|
||||
continue;
|
||||
|
||||
try
|
||||
{
|
||||
if (path.startsWith(attr.path) || path.equals(attr.path) || Files.isSameFile(path,attr.path))
|
||||
{
|
||||
return URIUtil.addPaths("${" + attr.key + "}",attr.path.relativize(path).toString());
|
||||
}
|
||||
}
|
||||
catch (IOException ignore)
|
||||
{
|
||||
LOG.ignore(ignore);
|
||||
}
|
||||
}
|
||||
|
||||
return path.toString();
|
||||
}
|
||||
|
||||
|
||||
public String expand(String s)
|
||||
public String expand(String str)
|
||||
{
|
||||
int i=s.indexOf("${");
|
||||
if (i<0)
|
||||
return s;
|
||||
int e=s.indexOf('}',i+3);
|
||||
String prop=s.substring(i+2,e);
|
||||
switch(prop)
|
||||
return expand(str,new Stack<String>());
|
||||
}
|
||||
|
||||
public String expand(String str, Stack<String> seenStack)
|
||||
{
|
||||
if (str == null)
|
||||
{
|
||||
case "WAR":
|
||||
return s.substring(0,i)+_warPath+expand(s.substring(e+1));
|
||||
case "jetty.base":
|
||||
return s.substring(0,i)+_jettyBasePath+expand(s.substring(e+1));
|
||||
case "jetty.home":
|
||||
return s.substring(0,i)+_jettyHomePath+expand(s.substring(e+1));
|
||||
case "user.home":
|
||||
return s.substring(0,i)+_userHomePath+expand(s.substring(e+1));
|
||||
case "user.dir":
|
||||
return s.substring(0,i)+_userDirPath+expand(s.substring(e+1));
|
||||
default:
|
||||
return s;
|
||||
return str;
|
||||
}
|
||||
|
||||
if (str.indexOf("${") < 0)
|
||||
{
|
||||
// Contains no potential expressions.
|
||||
return str;
|
||||
}
|
||||
|
||||
Matcher mat = __propertyPattern.matcher(str);
|
||||
StringBuilder expanded = new StringBuilder();
|
||||
int offset = 0;
|
||||
String property;
|
||||
String value;
|
||||
|
||||
while (mat.find(offset))
|
||||
{
|
||||
property = mat.group(1);
|
||||
|
||||
// Loop detection
|
||||
if (seenStack.contains(property))
|
||||
{
|
||||
StringBuilder err = new StringBuilder();
|
||||
err.append("Property expansion loop detected: ");
|
||||
int idx = seenStack.lastIndexOf(property);
|
||||
for (int i = idx; i < seenStack.size(); i++)
|
||||
{
|
||||
err.append(seenStack.get(i));
|
||||
err.append(" -> ");
|
||||
}
|
||||
err.append(property);
|
||||
throw new RuntimeException(err.toString());
|
||||
}
|
||||
|
||||
seenStack.push(property);
|
||||
|
||||
// find property name
|
||||
expanded.append(str.subSequence(offset,mat.start()));
|
||||
// get property value
|
||||
value = getString(property);
|
||||
if (value == null)
|
||||
{
|
||||
if(LOG.isDebugEnabled())
|
||||
LOG.debug("Unable to expand: {}",property);
|
||||
expanded.append(mat.group());
|
||||
}
|
||||
else
|
||||
{
|
||||
// recursively expand
|
||||
value = expand(value,seenStack);
|
||||
expanded.append(value);
|
||||
}
|
||||
// update offset
|
||||
offset = mat.end();
|
||||
}
|
||||
|
||||
// leftover
|
||||
expanded.append(str.substring(offset));
|
||||
|
||||
// special case for "$$"
|
||||
if (expanded.indexOf("$$") >= 0)
|
||||
{
|
||||
return expanded.toString().replaceAll("\\$\\$","\\$");
|
||||
}
|
||||
|
||||
return expanded.toString();
|
||||
}
|
||||
|
||||
private String getString(String property)
|
||||
{
|
||||
// Use known attributes first
|
||||
for (PathAttribute attr : attributes)
|
||||
{
|
||||
if (attr.key.equalsIgnoreCase(property))
|
||||
{
|
||||
return attr.path.toString();
|
||||
}
|
||||
}
|
||||
|
||||
// Use system properties next
|
||||
return System.getProperty(property);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,47 +1,41 @@
|
|||
<?xml version="1.0"?>
|
||||
<!DOCTYPE Configure PUBLIC "-//Jetty//Configure//EN" "http://www.eclipse.org/jetty/configure_9_3.dtd">
|
||||
|
||||
<!-- =============================================================== -->
|
||||
<!-- Mixin the RewriteHandler -->
|
||||
<!-- =============================================================== -->
|
||||
|
||||
|
||||
<Configure id="Server" class="org.eclipse.jetty.server.Server">
|
||||
|
||||
<!-- =========================================================== -->
|
||||
<!-- configure rewrite handler -->
|
||||
<!-- =========================================================== -->
|
||||
<Get id="oldhandler" name="handler"/>
|
||||
<Call name="insertHandler">
|
||||
<Arg>
|
||||
<New id="Rewrite" class="org.eclipse.jetty.rewrite.handler.RewriteHandler">
|
||||
<Set name="rewriteRequestURI"><Property name="jetty.rewrite.rewriteRequestURI" deprecated="rewrite.rewriteRequestURI" default="true"/></Set>
|
||||
<Set name="rewritePathInfo"><Property name="jetty.rewrite.rewritePathInfo" deprecated="rewrite.rewritePathInfo" default="false"/></Set>
|
||||
<Set name="originalPathAttribute"><Property name="jetty.rewrite.originalPathAttribute" deprecated="rewrite.originalPathAttribute" default="requestedPath"/></Set>
|
||||
|
||||
<Set name="handler">
|
||||
<New id="Rewrite" class="org.eclipse.jetty.rewrite.handler.RewriteHandler">
|
||||
<Set name="handler"><Ref refid="oldhandler"/></Set>
|
||||
<Set name="rewriteRequestURI"><Property name="jetty.rewrite.rewriteRequestURI" deprecated="rewrite.rewriteRequestURI" default="true"/></Set>
|
||||
<Set name="rewritePathInfo"><Property name="jetty.rewrite.rewritePathInfo" deprecated="rewrite.rewritePathInfo" default="false"/></Set>
|
||||
<Set name="originalPathAttribute"><Property name="jetty.rewrite.originalPathAttribute" deprecated="rewrite.originalPathAttribute" default="requestedPath"/></Set>
|
||||
<!-- Set DispatcherTypes -->
|
||||
<Set name="dispatcherTypes">
|
||||
<Array type="javax.servlet.DispatcherType">
|
||||
<Item><Call class="javax.servlet.DispatcherType" name="valueOf"><Arg>REQUEST</Arg></Call></Item>
|
||||
<Item><Call class="javax.servlet.DispatcherType" name="valueOf"><Arg>ASYNC</Arg></Call></Item>
|
||||
</Array>
|
||||
</Set>
|
||||
|
||||
<!-- Set DispatcherTypes -->
|
||||
<Set name="dispatcherTypes">
|
||||
<Array type="javax.servlet.DispatcherType">
|
||||
<Item><Call class="javax.servlet.DispatcherType" name="valueOf"><Arg>REQUEST</Arg></Call></Item>
|
||||
<Item><Call class="javax.servlet.DispatcherType" name="valueOf"><Arg>ASYNC</Arg></Call></Item>
|
||||
</Array>
|
||||
</Set>
|
||||
<!-- example rule -->
|
||||
<!--
|
||||
<Call name="addRule">
|
||||
<Arg>
|
||||
<New class="org.eclipse.jetty.rewrite.handler.HeaderPatternRule">
|
||||
<Set name="pattern">/favicon.ico</Set>
|
||||
<Set name="name">Cache-Control</Set>
|
||||
<Set name="value">Max-Age=3600,public</Set>
|
||||
<Set name="terminating">true</Set>
|
||||
</New>
|
||||
</Arg>
|
||||
</Call>
|
||||
-->
|
||||
|
||||
<!-- example rule -->
|
||||
<!--
|
||||
<Call name="addRule">
|
||||
<Arg>
|
||||
<New class="org.eclipse.jetty.rewrite.handler.HeaderPatternRule">
|
||||
<Set name="pattern">/favicon.ico</Set>
|
||||
<Set name="name">Cache-Control</Set>
|
||||
<Set name="value">Max-Age=3600,public</Set>
|
||||
<Set name="terminating">true</Set>
|
||||
</New>
|
||||
</Arg>
|
||||
</Call>
|
||||
-->
|
||||
|
||||
</New>
|
||||
</Set>
|
||||
</New>
|
||||
</Arg>
|
||||
</Call>
|
||||
</Configure>
|
||||
|
|
|
@ -6,20 +6,20 @@
|
|||
<!-- =============================================================== -->
|
||||
|
||||
<Configure id="Server" class="org.eclipse.jetty.server.Server">
|
||||
<Get id="oldhandler" name="handler"/>
|
||||
<Set name="handler">
|
||||
<New id="DebugHandler" class="org.eclipse.jetty.server.handler.DebugHandler">
|
||||
<Set name="handler"><Ref refid="oldhandler"/></Set>
|
||||
<Set name="outputStream">
|
||||
<New class="org.eclipse.jetty.util.RolloverFileOutputStream">
|
||||
<Arg type="String"><Property name="jetty.debuglog.dir" deprecated="jetty.logs" default="./logs"/>/yyyy_mm_dd.debug.log</Arg>
|
||||
<Arg type="boolean"><Property name="jetty.debuglog.append" default="true"/></Arg>
|
||||
<Arg type="int"><Property name="jetty.debuglog.retainDays" default="90"/></Arg>
|
||||
<Arg>
|
||||
<Call class="java.util.TimeZone" name="getTimeZone"><Arg><Property name="jetty.debuglog.timezone" default="GMT"/></Arg></Call>
|
||||
</Arg>
|
||||
</New>
|
||||
</Set>
|
||||
</New>
|
||||
</Set>
|
||||
<Call name="insertHandler">
|
||||
<Arg>
|
||||
<New id="DebugHandler" class="org.eclipse.jetty.server.handler.DebugHandler">
|
||||
<Set name="outputStream">
|
||||
<New class="org.eclipse.jetty.util.RolloverFileOutputStream">
|
||||
<Arg type="String"><Property name="jetty.debuglog.dir" deprecated="jetty.logs" default="./logs"/>/yyyy_mm_dd.debug.log</Arg>
|
||||
<Arg type="boolean"><Property name="jetty.debuglog.append" default="true"/></Arg>
|
||||
<Arg type="int"><Property name="jetty.debuglog.retainDays" default="90"/></Arg>
|
||||
<Arg>
|
||||
<Call class="java.util.TimeZone" name="getTimeZone"><Arg><Property name="jetty.debuglog.timezone" default="GMT"/></Arg></Call>
|
||||
</Arg>
|
||||
</New>
|
||||
</Set>
|
||||
</New>
|
||||
</Arg>
|
||||
</Call>
|
||||
</Configure>
|
||||
|
|
|
@ -9,59 +9,59 @@
|
|||
<!-- =============================================================== -->
|
||||
|
||||
<Configure id="Server" class="org.eclipse.jetty.server.Server">
|
||||
<Get id="next" name="handler" />
|
||||
<Set name="handler">
|
||||
<New id="GzipHandler" class="org.eclipse.jetty.server.handler.gzip.GzipHandler">
|
||||
<Set name="handler"><Ref refid="next" /></Set>
|
||||
<Set name="minGzipSize"><Property name="jetty.gzip.minGzipSize" deprecated="gzip.minGzipSize" default="2048"/></Set>
|
||||
<Set name="checkGzExists"><Property name="jetty.gzip.checkGzExists" deprecated="gzip.checkGzExists" default="false"/></Set>
|
||||
<Set name="compressionLevel"><Property name="jetty.gzip.compressionLevel" deprecated="gzip.compressionLevel" default="-1"/></Set>
|
||||
<Set name="excludedAgentPatterns">
|
||||
<Array type="String">
|
||||
<Item><Property name="jetty.gzip.excludedUserAgent" deprecated="gzip.excludedUserAgent" default=".*MSIE.6\.0.*"/></Item>
|
||||
</Array>
|
||||
</Set>
|
||||
<Call name="insertHandler">
|
||||
<Arg>
|
||||
<New id="GzipHandler" class="org.eclipse.jetty.server.handler.gzip.GzipHandler">
|
||||
<Set name="minGzipSize"><Property name="jetty.gzip.minGzipSize" deprecated="gzip.minGzipSize" default="2048"/></Set>
|
||||
<Set name="checkGzExists"><Property name="jetty.gzip.checkGzExists" deprecated="gzip.checkGzExists" default="false"/></Set>
|
||||
<Set name="compressionLevel"><Property name="jetty.gzip.compressionLevel" deprecated="gzip.compressionLevel" default="-1"/></Set>
|
||||
<Set name="excludedAgentPatterns">
|
||||
<Array type="String">
|
||||
<Item><Property name="jetty.gzip.excludedUserAgent" deprecated="gzip.excludedUserAgent" default=".*MSIE.6\.0.*"/></Item>
|
||||
</Array>
|
||||
</Set>
|
||||
|
||||
<Set name="includedMethods">
|
||||
<Array type="String">
|
||||
<Item>GET</Item>
|
||||
</Array>
|
||||
</Set>
|
||||
<Set name="includedMethods">
|
||||
<Array type="String">
|
||||
<Item>GET</Item>
|
||||
</Array>
|
||||
</Set>
|
||||
|
||||
<!--
|
||||
<Set name="includedPaths">
|
||||
<Array type="String">
|
||||
<Item>/*</Item>
|
||||
</Array>
|
||||
</Set>
|
||||
-->
|
||||
<!--
|
||||
<Set name="includedPaths">
|
||||
<Array type="String">
|
||||
<Item>/*</Item>
|
||||
</Array>
|
||||
</Set>
|
||||
-->
|
||||
|
||||
<!--
|
||||
<Set name="excludedPaths">
|
||||
<Array type="String">
|
||||
<Item>*.gz</Item>
|
||||
</Array>
|
||||
</Set>
|
||||
-->
|
||||
<!--
|
||||
<Set name="excludedPaths">
|
||||
<Array type="String">
|
||||
<Item>*.gz</Item>
|
||||
</Array>
|
||||
</Set>
|
||||
-->
|
||||
|
||||
<!--
|
||||
<Call name="addIncludedMimeTypes">
|
||||
<Arg><Array type="String">
|
||||
<Item>some/type</Item>
|
||||
</Array></Arg>
|
||||
</Call>
|
||||
-->
|
||||
<!--
|
||||
<Call name="addIncludedMimeTypes">
|
||||
<Arg><Array type="String">
|
||||
<Item>some/type</Item>
|
||||
</Array></Arg>
|
||||
</Call>
|
||||
-->
|
||||
|
||||
<!--
|
||||
<Call name="addExcludedMimeTypes">
|
||||
<Arg><Array type="String">
|
||||
<Item>some/type</Item>
|
||||
</Array></Arg>
|
||||
</Call>
|
||||
-->
|
||||
<!--
|
||||
<Call name="addExcludedMimeTypes">
|
||||
<Arg><Array type="String">
|
||||
<Item>some/type</Item>
|
||||
</Array></Arg>
|
||||
</Call>
|
||||
-->
|
||||
|
||||
</New>
|
||||
</Set>
|
||||
</New>
|
||||
</Arg>
|
||||
</Call>
|
||||
</Configure>
|
||||
|
||||
|
||||
|
|
|
@ -6,26 +6,23 @@
|
|||
<!-- =============================================================== -->
|
||||
|
||||
<Configure id="Server" class="org.eclipse.jetty.server.Server">
|
||||
|
||||
<Get id="oldhandler" name="handler"/>
|
||||
|
||||
<Set name="handler">
|
||||
<New id="IPAccessHandler" class="org.eclipse.jetty.server.handler.IPAccessHandler">
|
||||
<Set name="handler"><Ref refid="oldhandler"/></Set>
|
||||
<Set name="white">
|
||||
<Array type="String">
|
||||
<Item>127.0.0.1</Item>
|
||||
<Item>127.0.0.2/*.html</Item>
|
||||
</Array>
|
||||
</Set>
|
||||
<Set name="black">
|
||||
<Array type="String">
|
||||
<Item>127.0.0.1/blacklisted</Item>
|
||||
<Item>127.0.0.2/black.html</Item>
|
||||
</Array>
|
||||
</Set>
|
||||
<Set name="whiteListByPath">false</Set>
|
||||
</New>
|
||||
</Set>
|
||||
|
||||
<Call name="insertHandler">
|
||||
<Arg>
|
||||
<New id="IPAccessHandler" class="org.eclipse.jetty.server.handler.IPAccessHandler">
|
||||
<Set name="white">
|
||||
<Array type="String">
|
||||
<Item>127.0.0.1</Item>
|
||||
<Item>127.0.0.2/*.html</Item>
|
||||
</Array>
|
||||
</Set>
|
||||
<Set name="black">
|
||||
<Array type="String">
|
||||
<Item>127.0.0.1/blacklisted</Item>
|
||||
<Item>127.0.0.2/black.html</Item>
|
||||
</Array>
|
||||
</Set>
|
||||
<Set name="whiteListByPath">false</Set>
|
||||
</New>
|
||||
</Arg>
|
||||
</Call>
|
||||
</Configure>
|
||||
|
|
|
@ -17,16 +17,8 @@
|
|||
<Set name="EndpointIdentificationAlgorithm"></Set>
|
||||
<Set name="NeedClientAuth"><Property name="jetty.sslContext.needClientAuth" deprecated="jetty.ssl.needClientAuth" default="false"/></Set>
|
||||
<Set name="WantClientAuth"><Property name="jetty.sslContext.wantClientAuth" deprecated="jetty.ssl.wantClientAuth" default="false"/></Set>
|
||||
<Set name="ExcludeCipherSuites">
|
||||
<Array type="String">
|
||||
<Item>SSL_RSA_WITH_DES_CBC_SHA</Item>
|
||||
<Item>SSL_DHE_RSA_WITH_DES_CBC_SHA</Item>
|
||||
<Item>SSL_DHE_DSS_WITH_DES_CBC_SHA</Item>
|
||||
<Item>SSL_RSA_EXPORT_WITH_RC4_40_MD5</Item>
|
||||
<Item>SSL_RSA_EXPORT_WITH_DES40_CBC_SHA</Item>
|
||||
<Item>SSL_DHE_RSA_EXPORT_WITH_DES40_CBC_SHA</Item>
|
||||
<Item>SSL_DHE_DSS_EXPORT_WITH_DES40_CBC_SHA</Item>
|
||||
</Array>
|
||||
</Set>
|
||||
<!-- To configure Includes / Excludes for Cipher Suites or Protocols see tweak-ssl.xml example at
|
||||
https://www.eclipse.org/jetty/documentation/current/configuring-ssl.html#configuring-sslcontextfactory-cipherSuites
|
||||
-->
|
||||
<Set name="useCipherSuitesOrder"><Property name="jetty.sslContext.useCipherSuitesOrder" default="true"/></Set>
|
||||
</Configure>
|
||||
|
|
|
@ -6,12 +6,12 @@
|
|||
<!-- =============================================================== -->
|
||||
|
||||
<Configure id="Server" class="org.eclipse.jetty.server.Server">
|
||||
<Get id="oldhandler" name="handler" />
|
||||
<Set name="handler">
|
||||
<New id="StatsHandler" class="org.eclipse.jetty.server.handler.StatisticsHandler">
|
||||
<Set name="handler"><Ref refid="oldhandler" /></Set>
|
||||
</New>
|
||||
</Set>
|
||||
<Call name="insertHandler">
|
||||
<Arg>
|
||||
<New id="StatsHandler" class="org.eclipse.jetty.server.handler.StatisticsHandler">
|
||||
</New>
|
||||
</Arg>
|
||||
</Call>
|
||||
<Call class="org.eclipse.jetty.server.ConnectorStatistics" name="addToAllConnectors">
|
||||
<Arg><Ref refid="Server"/></Arg>
|
||||
</Call>
|
||||
|
|
|
@ -88,3 +88,6 @@ http://git.eclipse.org/c/jetty/org.eclipse.jetty.project.git/plain/jetty-server/
|
|||
## Whether cipher order is significant (since java 8 only)
|
||||
# jetty.sslContext.useCipherSuitesOrder=true
|
||||
|
||||
## To configure Includes / Excludes for Cipher Suites or Protocols see tweak-ssl.xml example at
|
||||
## https://www.eclipse.org/jetty/documentation/current/configuring-ssl.html#configuring-sslcontextfactory-cipherSuites
|
||||
|
||||
|
|
|
@ -654,7 +654,6 @@ public class Server extends HandlerWrapper implements Attributes
|
|||
/**
|
||||
* @return The URI of the first {@link NetworkConnector} and first {@link ContextHandler}, or null
|
||||
*/
|
||||
@SuppressWarnings("resource")
|
||||
public URI getURI()
|
||||
{
|
||||
NetworkConnector connector=null;
|
||||
|
@ -674,7 +673,10 @@ public class Server extends HandlerWrapper implements Attributes
|
|||
|
||||
try
|
||||
{
|
||||
String scheme=connector.getDefaultConnectionFactory().getProtocol().startsWith("SSL-")?"https":"http";
|
||||
String protocol = connector.getDefaultConnectionFactory().getProtocol();
|
||||
String scheme="http";
|
||||
if (protocol.startsWith("SSL-") || protocol.equals("SSL"))
|
||||
scheme = "https";
|
||||
|
||||
String host=connector.getHost();
|
||||
if (context!=null && context.getVirtualHosts()!=null && context.getVirtualHosts().length>0)
|
||||
|
|
|
@ -100,7 +100,7 @@ import org.eclipse.jetty.util.resource.Resource;
|
|||
* The maximum size of a form that can be processed by this context is controlled by the system properties org.eclipse.jetty.server.Request.maxFormKeys
|
||||
* and org.eclipse.jetty.server.Request.maxFormContentSize. These can also be configured with {@link #setMaxFormContentSize(int)} and {@link #setMaxFormKeys(int)}
|
||||
* <p>
|
||||
* This servers executore is made available via a context attributed "org.eclipse.jetty.server.Executor".
|
||||
* This servers executor is made available via a context attributed "org.eclipse.jetty.server.Executor".
|
||||
* <p>
|
||||
* By default, the context is created with alias checkers for {@link AllowSymLinkAliasChecker} (unix only) and {@link ApproveNonExistentDirectoryAliases}.
|
||||
* If these alias checkers are not required, then {@link #clearAliasChecks()} or {@link #setAliasChecks(List)} should be called.
|
||||
|
|
|
@ -99,6 +99,11 @@ public class ErrorHandler extends AbstractHandler
|
|||
throw new IOException(x);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (LOG.isDebugEnabled())
|
||||
{
|
||||
LOG.debug("No Error Page mapping for request({} {}) (using default)",request.getMethod(),request.getRequestURI());
|
||||
}
|
||||
else
|
||||
{
|
||||
LOG.warn("Could not dispatch to error page: {}", error_page);
|
||||
|
|
|
@ -27,6 +27,7 @@ import javax.servlet.http.HttpServletRequest;
|
|||
import javax.servlet.http.HttpServletResponse;
|
||||
|
||||
import org.eclipse.jetty.server.Handler;
|
||||
import org.eclipse.jetty.server.HandlerContainer;
|
||||
import org.eclipse.jetty.server.Request;
|
||||
import org.eclipse.jetty.util.ArrayUtil;
|
||||
import org.eclipse.jetty.util.MultiException;
|
||||
|
@ -81,9 +82,18 @@ public class HandlerCollection extends AbstractHandlerContainer
|
|||
throw new IllegalStateException(STARTED);
|
||||
|
||||
if (handlers!=null)
|
||||
{
|
||||
// check for loops
|
||||
for (Handler handler:handlers)
|
||||
if (handler == this || (handler instanceof HandlerContainer &&
|
||||
Arrays.asList(((HandlerContainer)handler).getChildHandlers()).contains(this)))
|
||||
throw new IllegalStateException("setHandler loop");
|
||||
|
||||
// Set server
|
||||
for (Handler handler:handlers)
|
||||
if (handler.getServer()!=getServer())
|
||||
handler.setServer(getServer());
|
||||
}
|
||||
Handler[] old=_handlers;;
|
||||
_handlers = handlers;
|
||||
updateBeans(old, handlers);
|
||||
|
|
|
@ -19,6 +19,7 @@
|
|||
package org.eclipse.jetty.server.handler;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
import javax.servlet.ServletException;
|
||||
|
@ -26,6 +27,7 @@ import javax.servlet.http.HttpServletRequest;
|
|||
import javax.servlet.http.HttpServletResponse;
|
||||
|
||||
import org.eclipse.jetty.server.Handler;
|
||||
import org.eclipse.jetty.server.HandlerContainer;
|
||||
import org.eclipse.jetty.server.Request;
|
||||
import org.eclipse.jetty.util.annotation.ManagedAttribute;
|
||||
import org.eclipse.jetty.util.annotation.ManagedObject;
|
||||
|
@ -80,6 +82,11 @@ public class HandlerWrapper extends AbstractHandlerContainer
|
|||
if (isStarted())
|
||||
throw new IllegalStateException(STARTED);
|
||||
|
||||
// check for loops
|
||||
if (handler==this || (handler instanceof HandlerContainer &&
|
||||
Arrays.asList(((HandlerContainer)handler).getChildHandlers()).contains(this)))
|
||||
throw new IllegalStateException("setHandler loop");
|
||||
|
||||
if (handler!=null)
|
||||
handler.setServer(getServer());
|
||||
|
||||
|
@ -102,10 +109,18 @@ public class HandlerWrapper extends AbstractHandlerContainer
|
|||
*/
|
||||
public void insertHandler(HandlerWrapper wrapper)
|
||||
{
|
||||
if (wrapper==null || wrapper.getHandler()!=null)
|
||||
if (wrapper==null)
|
||||
throw new IllegalArgumentException();
|
||||
wrapper.setHandler(getHandler());
|
||||
|
||||
HandlerWrapper tail = wrapper;
|
||||
while(tail.getHandler() instanceof HandlerWrapper)
|
||||
tail=(HandlerWrapper)tail.getHandler();
|
||||
if (tail.getHandler()!=null)
|
||||
throw new IllegalArgumentException("bad tail of inserted wrapper chain");
|
||||
|
||||
Handler next=getHandler();
|
||||
setHandler(wrapper);
|
||||
tail.setHandler(next);
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
|
|
|
@ -0,0 +1,342 @@
|
|||
//
|
||||
// ========================================================================
|
||||
// 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.handler;
|
||||
|
||||
import static org.hamcrest.Matchers.containsString;
|
||||
import static org.hamcrest.Matchers.equalTo;
|
||||
import static org.hamcrest.Matchers.nullValue;
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
import javax.servlet.ServletException;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
|
||||
import org.eclipse.jetty.server.Server;
|
||||
import org.eclipse.jetty.server.Handler;
|
||||
import org.eclipse.jetty.server.Request;
|
||||
import org.eclipse.jetty.server.handler.HandlerWrapper;
|
||||
import org.hamcrest.Matchers;
|
||||
import org.junit.Test;
|
||||
|
||||
public class HandlerTest
|
||||
{
|
||||
|
||||
@Test
|
||||
public void testWrapperSetServer()
|
||||
{
|
||||
Server s=new Server();
|
||||
HandlerWrapper a = new HandlerWrapper();
|
||||
HandlerWrapper b = new HandlerWrapper();
|
||||
HandlerWrapper c = new HandlerWrapper();
|
||||
a.setHandler(b);
|
||||
b.setHandler(c);
|
||||
|
||||
a.setServer(s);
|
||||
assertThat(b.getServer(),equalTo(s));
|
||||
assertThat(c.getServer(),equalTo(s));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testWrapperServerSet()
|
||||
{
|
||||
Server s=new Server();
|
||||
HandlerWrapper a = new HandlerWrapper();
|
||||
HandlerWrapper b = new HandlerWrapper();
|
||||
HandlerWrapper c = new HandlerWrapper();
|
||||
a.setServer(s);
|
||||
b.setHandler(c);
|
||||
a.setHandler(b);
|
||||
|
||||
assertThat(b.getServer(),equalTo(s));
|
||||
assertThat(c.getServer(),equalTo(s));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testWrapperThisLoop()
|
||||
{
|
||||
HandlerWrapper a = new HandlerWrapper();
|
||||
|
||||
try
|
||||
{
|
||||
a.setHandler(a);
|
||||
fail();
|
||||
}
|
||||
catch(IllegalStateException e)
|
||||
{
|
||||
assertThat(e.getMessage(),containsString("loop"));
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testWrapperSimpleLoop()
|
||||
{
|
||||
HandlerWrapper a = new HandlerWrapper();
|
||||
HandlerWrapper b = new HandlerWrapper();
|
||||
|
||||
a.setHandler(b);
|
||||
|
||||
try
|
||||
{
|
||||
b.setHandler(a);
|
||||
fail();
|
||||
}
|
||||
catch(IllegalStateException e)
|
||||
{
|
||||
assertThat(e.getMessage(),containsString("loop"));
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testWrapperDeepLoop()
|
||||
{
|
||||
HandlerWrapper a = new HandlerWrapper();
|
||||
HandlerWrapper b = new HandlerWrapper();
|
||||
HandlerWrapper c = new HandlerWrapper();
|
||||
|
||||
a.setHandler(b);
|
||||
b.setHandler(c);
|
||||
|
||||
try
|
||||
{
|
||||
c.setHandler(a);
|
||||
fail();
|
||||
}
|
||||
catch(IllegalStateException e)
|
||||
{
|
||||
assertThat(e.getMessage(),containsString("loop"));
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testWrapperChainLoop()
|
||||
{
|
||||
HandlerWrapper a = new HandlerWrapper();
|
||||
HandlerWrapper b = new HandlerWrapper();
|
||||
HandlerWrapper c = new HandlerWrapper();
|
||||
|
||||
a.setHandler(b);
|
||||
c.setHandler(a);
|
||||
|
||||
try
|
||||
{
|
||||
b.setHandler(c);
|
||||
fail();
|
||||
}
|
||||
catch(IllegalStateException e)
|
||||
{
|
||||
assertThat(e.getMessage(),containsString("loop"));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void testCollectionSetServer()
|
||||
{
|
||||
Server s=new Server();
|
||||
HandlerCollection a = new HandlerCollection();
|
||||
HandlerCollection b = new HandlerCollection();
|
||||
HandlerCollection b1 = new HandlerCollection();
|
||||
HandlerCollection b2 = new HandlerCollection();
|
||||
HandlerCollection c = new HandlerCollection();
|
||||
HandlerCollection c1 = new HandlerCollection();
|
||||
HandlerCollection c2 = new HandlerCollection();
|
||||
|
||||
a.addHandler(b);
|
||||
a.addHandler(c);
|
||||
b.setHandlers(new Handler[]{b1,b2});
|
||||
c.setHandlers(new Handler[]{c1,c2});
|
||||
a.setServer(s);
|
||||
|
||||
assertThat(b.getServer(),equalTo(s));
|
||||
assertThat(c.getServer(),equalTo(s));
|
||||
assertThat(b1.getServer(),equalTo(s));
|
||||
assertThat(b2.getServer(),equalTo(s));
|
||||
assertThat(c1.getServer(),equalTo(s));
|
||||
assertThat(c2.getServer(),equalTo(s));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCollectionServerSet()
|
||||
{
|
||||
Server s=new Server();
|
||||
HandlerCollection a = new HandlerCollection();
|
||||
HandlerCollection b = new HandlerCollection();
|
||||
HandlerCollection b1 = new HandlerCollection();
|
||||
HandlerCollection b2 = new HandlerCollection();
|
||||
HandlerCollection c = new HandlerCollection();
|
||||
HandlerCollection c1 = new HandlerCollection();
|
||||
HandlerCollection c2 = new HandlerCollection();
|
||||
|
||||
a.setServer(s);
|
||||
a.addHandler(b);
|
||||
a.addHandler(c);
|
||||
b.setHandlers(new Handler[]{b1,b2});
|
||||
c.setHandlers(new Handler[]{c1,c2});
|
||||
|
||||
assertThat(b.getServer(),equalTo(s));
|
||||
assertThat(c.getServer(),equalTo(s));
|
||||
assertThat(b1.getServer(),equalTo(s));
|
||||
assertThat(b2.getServer(),equalTo(s));
|
||||
assertThat(c1.getServer(),equalTo(s));
|
||||
assertThat(c2.getServer(),equalTo(s));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCollectionThisLoop()
|
||||
{
|
||||
HandlerCollection a = new HandlerCollection();
|
||||
|
||||
try
|
||||
{
|
||||
a.addHandler(a);
|
||||
fail();
|
||||
}
|
||||
catch(IllegalStateException e)
|
||||
{
|
||||
assertThat(e.getMessage(),containsString("loop"));
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCollectionDeepLoop()
|
||||
{
|
||||
HandlerCollection a = new HandlerCollection();
|
||||
HandlerCollection b = new HandlerCollection();
|
||||
HandlerCollection b1 = new HandlerCollection();
|
||||
HandlerCollection b2 = new HandlerCollection();
|
||||
HandlerCollection c = new HandlerCollection();
|
||||
HandlerCollection c1 = new HandlerCollection();
|
||||
HandlerCollection c2 = new HandlerCollection();
|
||||
|
||||
a.addHandler(b);
|
||||
a.addHandler(c);
|
||||
b.setHandlers(new Handler[]{b1,b2});
|
||||
c.setHandlers(new Handler[]{c1,c2});
|
||||
|
||||
try
|
||||
{
|
||||
b2.addHandler(a);
|
||||
fail();
|
||||
}
|
||||
catch(IllegalStateException e)
|
||||
{
|
||||
assertThat(e.getMessage(),containsString("loop"));
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCollectionChainLoop()
|
||||
{
|
||||
HandlerCollection a = new HandlerCollection();
|
||||
HandlerCollection b = new HandlerCollection();
|
||||
HandlerCollection b1 = new HandlerCollection();
|
||||
HandlerCollection b2 = new HandlerCollection();
|
||||
HandlerCollection c = new HandlerCollection();
|
||||
HandlerCollection c1 = new HandlerCollection();
|
||||
HandlerCollection c2 = new HandlerCollection();
|
||||
|
||||
a.addHandler(c);
|
||||
b.setHandlers(new Handler[]{b1,b2});
|
||||
c.setHandlers(new Handler[]{c1,c2});
|
||||
b2.addHandler(a);
|
||||
|
||||
try
|
||||
{
|
||||
a.addHandler(b);
|
||||
fail();
|
||||
}
|
||||
catch(IllegalStateException e)
|
||||
{
|
||||
assertThat(e.getMessage(),containsString("loop"));
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testInsertWrapperTail()
|
||||
{
|
||||
HandlerWrapper a = new HandlerWrapper();
|
||||
HandlerWrapper b = new HandlerWrapper();
|
||||
|
||||
a.insertHandler(b);
|
||||
assertThat(a.getHandler(),equalTo(b));
|
||||
assertThat(b.getHandler(),nullValue());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testInsertWrapper()
|
||||
{
|
||||
HandlerWrapper a = new HandlerWrapper();
|
||||
HandlerWrapper b = new HandlerWrapper();
|
||||
HandlerWrapper c = new HandlerWrapper();
|
||||
|
||||
a.insertHandler(c);
|
||||
a.insertHandler(b);
|
||||
assertThat(a.getHandler(),equalTo(b));
|
||||
assertThat(b.getHandler(),equalTo(c));
|
||||
assertThat(c.getHandler(),nullValue());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testInsertWrapperChain()
|
||||
{
|
||||
HandlerWrapper a = new HandlerWrapper();
|
||||
HandlerWrapper b = new HandlerWrapper();
|
||||
HandlerWrapper c = new HandlerWrapper();
|
||||
HandlerWrapper d = new HandlerWrapper();
|
||||
|
||||
a.insertHandler(d);
|
||||
b.insertHandler(c);
|
||||
a.insertHandler(b);
|
||||
assertThat(a.getHandler(),equalTo(b));
|
||||
assertThat(b.getHandler(),equalTo(c));
|
||||
assertThat(c.getHandler(),equalTo(d));
|
||||
assertThat(d.getHandler(),nullValue());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testInsertWrapperBadChain()
|
||||
{
|
||||
HandlerWrapper a = new HandlerWrapper();
|
||||
HandlerWrapper b = new HandlerWrapper();
|
||||
HandlerWrapper c = new HandlerWrapper();
|
||||
HandlerWrapper d = new HandlerWrapper();
|
||||
|
||||
a.insertHandler(d);
|
||||
b.insertHandler(c);
|
||||
c.setHandler(new AbstractHandler()
|
||||
{
|
||||
@Override
|
||||
public void handle(String target, Request baseRequest, HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException
|
||||
{
|
||||
}
|
||||
});
|
||||
|
||||
try
|
||||
{
|
||||
a.insertHandler(b);
|
||||
fail();
|
||||
}
|
||||
catch(IllegalArgumentException e)
|
||||
{
|
||||
assertThat(e.getMessage(),containsString("bad tail"));
|
||||
}
|
||||
}
|
||||
}
|
|
@ -18,12 +18,16 @@
|
|||
|
||||
package org.eclipse.jetty.server.ssl;
|
||||
|
||||
import static org.hamcrest.Matchers.is;
|
||||
import static org.junit.Assert.assertThat;
|
||||
|
||||
import java.io.BufferedReader;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.InputStreamReader;
|
||||
import java.io.OutputStream;
|
||||
import java.net.URI;
|
||||
import java.security.KeyStore;
|
||||
import java.util.Arrays;
|
||||
import java.util.Random;
|
||||
|
@ -92,6 +96,15 @@ public class SSLSelectChannelConnectorLoadTest
|
|||
server.join();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetURI()
|
||||
{
|
||||
URI uri = server.getURI();
|
||||
assertThat("Server.uri.scheme", uri.getScheme(), is("https"));
|
||||
assertThat("Server.uri.port", uri.getPort(), is(connector.getLocalPort()));
|
||||
assertThat("Server.uri.path", uri.getPath(), is("/"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testLongLivedConnections() throws Exception
|
||||
{
|
||||
|
|
|
@ -30,6 +30,8 @@ import javax.servlet.http.HttpServletRequest;
|
|||
import org.eclipse.jetty.server.Dispatcher;
|
||||
import org.eclipse.jetty.server.handler.ContextHandler;
|
||||
import org.eclipse.jetty.server.handler.ErrorHandler;
|
||||
import org.eclipse.jetty.util.log.Log;
|
||||
import org.eclipse.jetty.util.log.Logger;
|
||||
|
||||
/**
|
||||
* An ErrorHandler that maps exceptions and status codes to URIs for dispatch using
|
||||
|
@ -38,6 +40,8 @@ import org.eclipse.jetty.server.handler.ErrorHandler;
|
|||
public class ErrorPageErrorHandler extends ErrorHandler implements ErrorHandler.ErrorPageMapper
|
||||
{
|
||||
public final static String GLOBAL_ERROR_PAGE = "org.eclipse.jetty.server.error_page.global";
|
||||
private static final Logger LOG = Log.getLogger(ErrorPageErrorHandler.class);
|
||||
enum PageLookupTechnique{ THROWABLE, STATUS_CODE, GLOBAL }
|
||||
|
||||
protected ServletContext _servletContext;
|
||||
private final Map<String,String> _errorPages= new HashMap<>(); // code or exception to URL
|
||||
|
@ -48,11 +52,15 @@ public class ErrorPageErrorHandler extends ErrorHandler implements ErrorHandler.
|
|||
{
|
||||
String error_page= null;
|
||||
|
||||
PageLookupTechnique pageSource = null;
|
||||
|
||||
Throwable th = (Throwable)request.getAttribute(Dispatcher.ERROR_EXCEPTION);
|
||||
|
||||
// Walk the cause hierarchy
|
||||
while (error_page == null && th != null )
|
||||
{
|
||||
pageSource = PageLookupTechnique.THROWABLE;
|
||||
|
||||
Class<?> exClass=th.getClass();
|
||||
error_page = _errorPages.get(exClass.getName());
|
||||
|
||||
|
@ -68,13 +76,17 @@ public class ErrorPageErrorHandler extends ErrorHandler implements ErrorHandler.
|
|||
th=(th instanceof ServletException)?((ServletException)th).getRootCause():null;
|
||||
}
|
||||
|
||||
Integer errorStatusCode = null;
|
||||
|
||||
if (error_page == null)
|
||||
{
|
||||
pageSource = PageLookupTechnique.STATUS_CODE;
|
||||
|
||||
// look for an exact code match
|
||||
Integer code=(Integer)request.getAttribute(Dispatcher.ERROR_STATUS_CODE);
|
||||
if (code!=null)
|
||||
errorStatusCode = (Integer)request.getAttribute(Dispatcher.ERROR_STATUS_CODE);
|
||||
if (errorStatusCode!=null)
|
||||
{
|
||||
error_page=_errorPages.get(Integer.toString(code));
|
||||
error_page= (String)_errorPages.get(Integer.toString(errorStatusCode));
|
||||
|
||||
// if still not found
|
||||
if ((error_page == null) && (_errorPageList != null))
|
||||
|
@ -83,7 +95,7 @@ public class ErrorPageErrorHandler extends ErrorHandler implements ErrorHandler.
|
|||
for (int i = 0; i < _errorPageList.size(); i++)
|
||||
{
|
||||
ErrorCodeRange errCode = _errorPageList.get(i);
|
||||
if (errCode.isInRange(code))
|
||||
if (errCode.isInRange(errorStatusCode))
|
||||
{
|
||||
error_page = errCode.getUri();
|
||||
break;
|
||||
|
@ -95,7 +107,38 @@ public class ErrorPageErrorHandler extends ErrorHandler implements ErrorHandler.
|
|||
|
||||
// Try servlet 3.x global error page.
|
||||
if (error_page == null)
|
||||
{
|
||||
pageSource = PageLookupTechnique.GLOBAL;
|
||||
error_page = _errorPages.get(GLOBAL_ERROR_PAGE);
|
||||
}
|
||||
|
||||
if (LOG.isDebugEnabled())
|
||||
{
|
||||
StringBuilder dbg = new StringBuilder();
|
||||
dbg.append("getErrorPage(");
|
||||
dbg.append(request.getMethod()).append(' ');
|
||||
dbg.append(request.getRequestURI());
|
||||
dbg.append(") => error_page=").append(error_page);
|
||||
switch (pageSource)
|
||||
{
|
||||
case THROWABLE:
|
||||
dbg.append(" (from Throwable ");
|
||||
dbg.append(th.getClass().getName());
|
||||
dbg.append(')');
|
||||
LOG.debug(dbg.toString(),th);
|
||||
break;
|
||||
case STATUS_CODE:
|
||||
dbg.append(" (from status code ");
|
||||
dbg.append(errorStatusCode);
|
||||
dbg.append(')');
|
||||
LOG.debug(dbg.toString());
|
||||
break;
|
||||
case GLOBAL:
|
||||
dbg.append(" (from global default)");
|
||||
LOG.debug(dbg.toString());
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return error_page;
|
||||
}
|
||||
|
|
|
@ -66,6 +66,8 @@ import org.eclipse.jetty.util.DeprecationWarning;
|
|||
import org.eclipse.jetty.util.annotation.ManagedAttribute;
|
||||
import org.eclipse.jetty.util.annotation.ManagedObject;
|
||||
import org.eclipse.jetty.util.component.LifeCycle;
|
||||
import org.eclipse.jetty.util.log.Log;
|
||||
import org.eclipse.jetty.util.log.Logger;
|
||||
|
||||
/**
|
||||
* Servlet Context.
|
||||
|
@ -83,6 +85,8 @@ import org.eclipse.jetty.util.component.LifeCycle;
|
|||
@ManagedObject("Servlet Context Handler")
|
||||
public class ServletContextHandler extends ContextHandler
|
||||
{
|
||||
private static final Logger LOG = Log.getLogger(ServletContextHandler.class);
|
||||
|
||||
public final static int SESSIONS=1;
|
||||
public final static int SECURITY=2;
|
||||
public final static int GZIP=4;
|
||||
|
@ -169,7 +173,21 @@ public class ServletContextHandler extends ContextHandler
|
|||
|
||||
if (errorHandler!=null)
|
||||
setErrorHandler(errorHandler);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setHandler(Handler handler)
|
||||
{
|
||||
LOG.warn("ServletContextHandler.setHandler should not be called directly. Use insertHandler or setSessionHandler etc.");
|
||||
super.setHandler(handler);
|
||||
}
|
||||
|
||||
private void doSetHandler(HandlerWrapper wrapper, Handler handler)
|
||||
{
|
||||
if (wrapper==this)
|
||||
super.setHandler(handler);
|
||||
else
|
||||
wrapper.setHandler(handler);
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
|
@ -189,12 +207,7 @@ public class ServletContextHandler extends ContextHandler
|
|||
handler=(HandlerWrapper)handler.getHandler();
|
||||
|
||||
if (handler.getHandler()!=_sessionHandler)
|
||||
{
|
||||
if (handler== this)
|
||||
super.setHandler(_sessionHandler);
|
||||
else
|
||||
handler.setHandler(_sessionHandler);
|
||||
}
|
||||
doSetHandler(handler,_sessionHandler);
|
||||
handler=_sessionHandler;
|
||||
}
|
||||
|
||||
|
@ -208,12 +221,7 @@ public class ServletContextHandler extends ContextHandler
|
|||
handler=(HandlerWrapper)handler.getHandler();
|
||||
|
||||
if (handler.getHandler()!=_securityHandler)
|
||||
{
|
||||
if (handler== this)
|
||||
super.setHandler(_securityHandler);
|
||||
else
|
||||
handler.setHandler(_securityHandler);
|
||||
}
|
||||
doSetHandler(handler,_securityHandler);
|
||||
handler=_securityHandler;
|
||||
}
|
||||
|
||||
|
@ -226,12 +234,7 @@ public class ServletContextHandler extends ContextHandler
|
|||
handler=(HandlerWrapper)handler.getHandler();
|
||||
|
||||
if (handler.getHandler()!=_gzipHandler)
|
||||
{
|
||||
if (handler== this)
|
||||
super.setHandler(_gzipHandler);
|
||||
else
|
||||
handler.setHandler(_gzipHandler);
|
||||
}
|
||||
doSetHandler(handler,_gzipHandler);
|
||||
handler=_gzipHandler;
|
||||
}
|
||||
|
||||
|
@ -244,12 +247,7 @@ public class ServletContextHandler extends ContextHandler
|
|||
handler=(HandlerWrapper)handler.getHandler();
|
||||
|
||||
if (handler.getHandler()!=_servletHandler)
|
||||
{
|
||||
if (handler== this)
|
||||
super.setHandler(_servletHandler);
|
||||
else
|
||||
handler.setHandler(_servletHandler);
|
||||
}
|
||||
doSetHandler(handler,_servletHandler);
|
||||
handler=_servletHandler;
|
||||
}
|
||||
|
||||
|
@ -554,7 +552,7 @@ public class ServletContextHandler extends ContextHandler
|
|||
{
|
||||
if (wrapper.getHandler()==handler)
|
||||
{
|
||||
wrapper.setHandler(replace);
|
||||
doSetHandler(wrapper,replace);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -664,20 +662,38 @@ public class ServletContextHandler extends ContextHandler
|
|||
*/
|
||||
public void insertHandler(HandlerWrapper handler)
|
||||
{
|
||||
HandlerWrapper h=this;
|
||||
|
||||
// Skip any injected handlers
|
||||
while (h.getHandler() instanceof HandlerWrapper)
|
||||
if (handler instanceof SessionHandler)
|
||||
setSessionHandler((SessionHandler)handler);
|
||||
else if (handler instanceof SecurityHandler)
|
||||
setSecurityHandler((SecurityHandler)handler);
|
||||
else if (handler instanceof GzipHandler)
|
||||
setGzipHandler((GzipHandler)handler);
|
||||
else if (handler instanceof ServletHandler)
|
||||
setServletHandler((ServletHandler)handler);
|
||||
else
|
||||
{
|
||||
HandlerWrapper wrapper = (HandlerWrapper)h.getHandler();
|
||||
if (wrapper instanceof SessionHandler ||
|
||||
wrapper instanceof SecurityHandler ||
|
||||
wrapper instanceof ServletHandler)
|
||||
break;
|
||||
h=wrapper;
|
||||
}
|
||||
HandlerWrapper tail = handler;
|
||||
while(tail.getHandler() instanceof HandlerWrapper)
|
||||
tail=(HandlerWrapper)tail.getHandler();
|
||||
if (tail.getHandler()!=null)
|
||||
throw new IllegalArgumentException("bad tail of inserted wrapper chain");
|
||||
|
||||
h.setHandler(handler);
|
||||
// Skip any injected handlers
|
||||
HandlerWrapper h=this;
|
||||
while (h.getHandler() instanceof HandlerWrapper)
|
||||
{
|
||||
HandlerWrapper wrapper = (HandlerWrapper)h.getHandler();
|
||||
if (wrapper instanceof SessionHandler ||
|
||||
wrapper instanceof SecurityHandler ||
|
||||
wrapper instanceof ServletHandler)
|
||||
break;
|
||||
h=wrapper;
|
||||
}
|
||||
|
||||
Handler next=h.getHandler();
|
||||
doSetHandler(h,handler);
|
||||
doSetHandler(tail,next);
|
||||
}
|
||||
relinkHandlers();
|
||||
}
|
||||
|
||||
|
|
|
@ -81,7 +81,6 @@ public class GzipHandlerTest
|
|||
|
||||
_server.setHandler(gzipHandler);
|
||||
gzipHandler.setHandler(context);
|
||||
context.setHandler(servlets);
|
||||
servlets.addServletWithMapping(TestServlet.class,"/content");
|
||||
servlets.addServletWithMapping(ForwardServlet.class,"/forward");
|
||||
servlets.addServletWithMapping(IncludeServlet.class,"/include");
|
||||
|
@ -91,7 +90,6 @@ public class GzipHandlerTest
|
|||
|
||||
public static class TestServlet extends HttpServlet
|
||||
{
|
||||
|
||||
@Override
|
||||
protected void doGet(HttpServletRequest req, HttpServletResponse response) throws ServletException, IOException
|
||||
{
|
||||
|
|
|
@ -0,0 +1,146 @@
|
|||
//
|
||||
// ========================================================================
|
||||
// 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.servlet;
|
||||
|
||||
import static org.hamcrest.Matchers.containsString;
|
||||
import static org.hamcrest.Matchers.is;
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertThat;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.io.PrintWriter;
|
||||
import java.nio.file.Path;
|
||||
|
||||
import javax.servlet.MultipartConfigElement;
|
||||
import javax.servlet.ServletException;
|
||||
import javax.servlet.http.HttpServlet;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import javax.servlet.http.Part;
|
||||
|
||||
import org.eclipse.jetty.http.HttpTester;
|
||||
import org.eclipse.jetty.server.LocalConnector;
|
||||
import org.eclipse.jetty.server.Server;
|
||||
import org.eclipse.jetty.toolchain.test.FS;
|
||||
import org.eclipse.jetty.toolchain.test.MavenTestingUtils;
|
||||
import org.junit.AfterClass;
|
||||
import org.junit.BeforeClass;
|
||||
import org.junit.Test;
|
||||
|
||||
public class RequestGetPartsTest
|
||||
{
|
||||
@SuppressWarnings("serial")
|
||||
public static class DumpPartInfoServlet extends HttpServlet
|
||||
{
|
||||
@Override
|
||||
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException
|
||||
{
|
||||
resp.setContentType("text/plain");
|
||||
PrintWriter out = resp.getWriter();
|
||||
|
||||
for(Part part: req.getParts())
|
||||
{
|
||||
out.printf("Got part: name=%s, size=%,d, filename=%s%n",part.getName(), part.getSize(), part.getSubmittedFileName());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static Server server;
|
||||
private static LocalConnector connector;
|
||||
private static File locationDir;
|
||||
|
||||
@BeforeClass
|
||||
public static void startServer() throws Exception
|
||||
{
|
||||
Path tmpDir = MavenTestingUtils.getTargetTestingPath("testrequest_getparts");
|
||||
FS.ensureEmpty(tmpDir);
|
||||
|
||||
locationDir = tmpDir.toFile();
|
||||
|
||||
server = new Server();
|
||||
connector = new LocalConnector(server);
|
||||
server.addConnector(connector);
|
||||
|
||||
ServletContextHandler context = new ServletContextHandler();
|
||||
context.setContextPath("/");
|
||||
server.setHandler(context);
|
||||
|
||||
ServletHolder holder = context.addServlet(DumpPartInfoServlet.class,"/dump/*");
|
||||
String location = locationDir.getAbsolutePath();
|
||||
long maxFileSize = 1024*1024*5;
|
||||
long maxRequestSize = 1024*1024*10;
|
||||
int fileSizeThreshold = 1;
|
||||
MultipartConfigElement multipartConfig = new MultipartConfigElement(location,maxFileSize,maxRequestSize,fileSizeThreshold);
|
||||
((ServletHolder.Registration) holder.getRegistration()).setMultipartConfig(multipartConfig);
|
||||
|
||||
server.start();
|
||||
}
|
||||
|
||||
@AfterClass
|
||||
public static void stopServer() throws Exception
|
||||
{
|
||||
server.stop();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testMultiFileUpload_SameName() throws Exception
|
||||
{
|
||||
// generated and parsed test
|
||||
HttpTester.Request request = HttpTester.newRequest();
|
||||
HttpTester.Response response;
|
||||
|
||||
// test GET
|
||||
request.setMethod("POST");
|
||||
request.setURI("/dump/");
|
||||
request.setVersion("HTTP/1.1");
|
||||
request.setHeader("Host","tester");
|
||||
request.setHeader("Connection","close");
|
||||
|
||||
String boundary="XyXyXy";
|
||||
request.setHeader("Content-Type","multipart/form-data; boundary=" + boundary);
|
||||
|
||||
String crocMsg = "See ya later, aligator.";
|
||||
String aligMsg = "In a while, crocodile.";
|
||||
|
||||
StringBuilder content = new StringBuilder();
|
||||
content.append("--").append(boundary).append("\r\n");
|
||||
content.append("Content-Disposition: form-data; name=\"same\"; filename=\"crocodile.dat\"\r\n");
|
||||
content.append("Content-Type: application/octet-stream\r\n");
|
||||
content.append("\r\n");
|
||||
content.append(crocMsg).append("\r\n");
|
||||
content.append("--").append(boundary).append("\r\n");
|
||||
content.append("Content-Disposition: form-data; name=\"same\"; filename=\"aligator.dat\"\r\n");
|
||||
content.append("Content-Type: application/octet-stream\r\n");
|
||||
content.append("\r\n");
|
||||
content.append(aligMsg).append("\r\n");
|
||||
content.append("--").append(boundary).append("--\r\n");
|
||||
content.append("\r\n");
|
||||
|
||||
request.setContent(content.toString());
|
||||
|
||||
response = HttpTester.parseResponse(connector.getResponses(request.generate()));
|
||||
assertThat("Response status", response.getStatus(), is(HttpServletResponse.SC_OK));
|
||||
assertEquals(HttpServletResponse.SC_OK,response.getStatus());
|
||||
|
||||
String responseContents = response.getContent();
|
||||
assertThat("response.contents", responseContents, containsString(String.format("Got part: name=same, size=%d, filename=crocodile.dat",crocMsg.length())));
|
||||
assertThat("response.contents", responseContents, containsString(String.format("Got part: name=same, size=%d, filename=aligator.dat",aligMsg.length())));
|
||||
}
|
||||
}
|
|
@ -26,6 +26,7 @@ import java.util.EnumSet;
|
|||
|
||||
import javax.servlet.DispatcherType;
|
||||
|
||||
import org.eclipse.jetty.server.handler.HandlerWrapper;
|
||||
import org.eclipse.jetty.servlet.BaseHolder.Source;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
|
@ -428,5 +429,4 @@ public class ServletHandlerTest
|
|||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
|
|
@ -104,6 +104,7 @@ public class MultiPartFilter implements Filter
|
|||
private boolean _deleteFiles;
|
||||
private ServletContext _context;
|
||||
private int _fileOutputBuffer = 0;
|
||||
private boolean _writeFilesWithFilenames = false;
|
||||
private long _maxFileSize = -1L;
|
||||
private long _maxRequestSize = -1L;
|
||||
private int _maxFormKeys = Integer.getInteger("org.eclipse.jetty.server.Request.maxFormKeys", 1000);
|
||||
|
@ -130,6 +131,7 @@ public class MultiPartFilter implements Filter
|
|||
String mfks = filterConfig.getInitParameter("maxFormKeys");
|
||||
if (mfks!=null)
|
||||
_maxFormKeys=Integer.parseInt(mfks);
|
||||
_writeFilesWithFilenames = "true".equalsIgnoreCase(filterConfig.getInitParameter("writeFilesWithFilenames"));
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------------------------- */
|
||||
|
@ -164,6 +166,7 @@ public class MultiPartFilter implements Filter
|
|||
MultipartConfigElement config = new MultipartConfigElement(tempdir.getCanonicalPath(), _maxFileSize, _maxRequestSize, _fileOutputBuffer);
|
||||
MultiPartInputStreamParser mpis = new MultiPartInputStreamParser(in, content_type, config, tempdir);
|
||||
mpis.setDeleteOnExit(_deleteFiles);
|
||||
mpis.setWriteFilesWithFilenames(_writeFilesWithFilenames);
|
||||
request.setAttribute(MULTIPART, mpis);
|
||||
try
|
||||
{
|
||||
|
|
|
@ -89,8 +89,7 @@ public class IncludedGzipTest
|
|||
tester.getContext().addServlet(org.eclipse.jetty.servlet.DefaultServlet.class, "/");
|
||||
|
||||
GzipHandler gzipHandler = new GzipHandler();
|
||||
gzipHandler.setHandler(tester.getContext().getHandler());
|
||||
tester.getContext().setHandler(gzipHandler);
|
||||
tester.getContext().insertHandler(gzipHandler);
|
||||
tester.start();
|
||||
}
|
||||
|
||||
|
|
|
@ -18,9 +18,10 @@
|
|||
|
||||
package org.eclipse.jetty.servlets;
|
||||
|
||||
|
||||
import static org.hamcrest.Matchers.containsString;
|
||||
import static org.hamcrest.Matchers.is;
|
||||
import static org.hamcrest.Matchers.notNullValue;
|
||||
import static org.hamcrest.Matchers.nullValue;
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertNotNull;
|
||||
import static org.junit.Assert.assertNull;
|
||||
|
@ -30,10 +31,15 @@ import static org.junit.Assert.assertTrue;
|
|||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.FileNotFoundException;
|
||||
import java.io.FileReader;
|
||||
import java.io.IOException;
|
||||
import java.io.PrintWriter;
|
||||
import java.io.Reader;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.nio.file.Path;
|
||||
import java.util.EnumSet;
|
||||
import java.util.Enumeration;
|
||||
import java.util.Map;
|
||||
|
||||
import javax.servlet.DispatcherType;
|
||||
|
@ -45,17 +51,59 @@ import javax.servlet.http.HttpServletResponse;
|
|||
import org.eclipse.jetty.http.HttpTester;
|
||||
import org.eclipse.jetty.servlet.FilterHolder;
|
||||
import org.eclipse.jetty.servlet.ServletTester;
|
||||
import org.eclipse.jetty.toolchain.test.FS;
|
||||
import org.eclipse.jetty.toolchain.test.MavenTestingUtils;
|
||||
import org.eclipse.jetty.util.IO;
|
||||
import org.junit.After;
|
||||
import org.junit.Before;
|
||||
import org.junit.Ignore;
|
||||
import org.junit.Test;
|
||||
|
||||
public class MultipartFilterTest
|
||||
{
|
||||
private File _dir;
|
||||
private ServletTester tester;
|
||||
FilterHolder multipartFilter;
|
||||
|
||||
@SuppressWarnings("serial")
|
||||
public static class FilenameServlet extends TestServlet
|
||||
{
|
||||
@Override
|
||||
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException
|
||||
{
|
||||
assertThat(req.getAttribute("fileup"), notNullValue());
|
||||
super.doPost(req, resp);
|
||||
}
|
||||
}
|
||||
|
||||
@SuppressWarnings("serial")
|
||||
public static class ParameterListServlet extends TestServlet
|
||||
{
|
||||
@Override
|
||||
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException
|
||||
{
|
||||
resp.setContentType("text/plain");
|
||||
PrintWriter out = resp.getWriter();
|
||||
|
||||
Enumeration<String> pnames = req.getParameterNames();
|
||||
while (pnames.hasMoreElements())
|
||||
{
|
||||
String pname = pnames.nextElement();
|
||||
Object param = req.getParameter(pname);
|
||||
out.printf("Parameter[%s] = ",pname);
|
||||
if (param == null)
|
||||
{
|
||||
out.println(" <null>");
|
||||
}
|
||||
else
|
||||
{
|
||||
out.printf("(%s) %s%n",param.getClass().getName(),param);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@SuppressWarnings("serial")
|
||||
public static class BoundaryServlet extends TestServlet
|
||||
{
|
||||
@Override
|
||||
|
@ -63,9 +111,11 @@ public class MultipartFilterTest
|
|||
{
|
||||
//we have configured the multipart filter to always store to disk (file size threshold == 1)
|
||||
//but fileName has no filename param, so only the attribute should be set
|
||||
assertNull(req.getParameter("fileName"));
|
||||
assertNotNull(req.getAttribute("fileName"));
|
||||
assertThat("getParameter('fileName')", req.getParameter("fileName"), nullValue());
|
||||
assertThat("getAttribute('fileName')", req.getAttribute("fileName"), notNullValue());
|
||||
|
||||
File f = (File)req.getAttribute("fileName");
|
||||
assertThat("File exists", f.exists(), is(true));
|
||||
ByteArrayOutputStream baos = new ByteArrayOutputStream();
|
||||
IO.copy(new FileInputStream(f), baos);
|
||||
assertEquals(getServletContext().getAttribute("fileName"), baos.toString());
|
||||
|
@ -83,37 +133,39 @@ public class MultipartFilterTest
|
|||
}
|
||||
}
|
||||
|
||||
@SuppressWarnings("serial")
|
||||
public static class TestServlet extends DumpServlet
|
||||
{
|
||||
|
||||
@SuppressWarnings("deprecation")
|
||||
@Override
|
||||
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException
|
||||
{
|
||||
assertNotNull(req.getParameter("fileup"));
|
||||
System.err.println("Fileup="+req.getParameter("fileup"));
|
||||
assertNotNull(req.getParameter("fileup"+MultiPartFilter.CONTENT_TYPE_SUFFIX));
|
||||
assertEquals(req.getParameter("fileup"+MultiPartFilter.CONTENT_TYPE_SUFFIX), "application/octet-stream");
|
||||
String fileup = req.getParameter("fileup");
|
||||
assertThat("getParameter('fileup')",fileup,notNullValue());
|
||||
|
||||
System.err.println("Fileup=" + req.getParameter("fileup"));
|
||||
|
||||
String fileupType = req.getParameter("fileup" + MultiPartFilter.CONTENT_TYPE_SUFFIX);
|
||||
assertThat("req.getParameter('fileup'+CONTENT_TYPE_SUFFIX)",fileupType,is("application/octet-stream"));
|
||||
super.doPost(req, resp);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
@SuppressWarnings("deprecation")
|
||||
@Before
|
||||
public void setUp() throws Exception
|
||||
{
|
||||
_dir = File.createTempFile("testmultupart",null);
|
||||
assertTrue(_dir.delete());
|
||||
assertTrue(_dir.mkdir());
|
||||
_dir.deleteOnExit();
|
||||
assertTrue(_dir.isDirectory());
|
||||
Path tmpDir = MavenTestingUtils.getTargetTestingPath("testmultupart");
|
||||
FS.ensureEmpty(tmpDir);
|
||||
|
||||
_dir = tmpDir.toFile();
|
||||
|
||||
tester=new ServletTester("/context");
|
||||
tester.getContext().setResourceBase(_dir.getCanonicalPath());
|
||||
tester.getContext().setResourceBase(tmpDir.toString());
|
||||
tester.getContext().addServlet(TestServlet.class, "/");
|
||||
tester.getContext().setAttribute("javax.servlet.context.tempdir", _dir);
|
||||
FilterHolder multipartFilter = tester.getContext().addFilter(MultiPartFilter.class,"/*", EnumSet.of(DispatcherType.REQUEST));
|
||||
multipartFilter = tester.getContext().addFilter(MultiPartFilter.class,"/*", EnumSet.of(DispatcherType.REQUEST));
|
||||
multipartFilter.setInitParameter("deleteFiles", "true");
|
||||
multipartFilter.setInitParameter("fileOutputBuffer", "1"); //write a file if there's more than 1 byte content
|
||||
tester.start();
|
||||
|
@ -780,6 +832,7 @@ public class MultipartFilterTest
|
|||
assertEquals(HttpServletResponse.SC_INTERNAL_SERVER_ERROR, response.getStatus());
|
||||
}
|
||||
|
||||
@SuppressWarnings("serial")
|
||||
public static class TestServletParameterMap extends DumpServlet
|
||||
{
|
||||
@Override
|
||||
|
@ -820,7 +873,7 @@ public class MultipartFilterTest
|
|||
"Content-Type: application/octet-stream\r\n\r\n"+
|
||||
"How now brown cow."+
|
||||
"\r\n--" + boundary + "\r\n"+
|
||||
"Content-Disposition: form-data; name=\"strup\""+
|
||||
"Content-Disposition: form-data; name=\"strup\""+ // FIXME: this is missing a "\r\n"??
|
||||
"Content-Type: application/octet-stream\r\n\r\n"+
|
||||
"How now brown cow."+
|
||||
"\r\n--" + boundary + "--\r\n\r\n";
|
||||
|
@ -832,6 +885,119 @@ public class MultipartFilterTest
|
|||
assertTrue(response.getContent().indexOf("brown cow")>=0);
|
||||
}
|
||||
|
||||
/**
|
||||
* Validate that the uploaded file can be accessed on the name it was given
|
||||
* @throws Exception on test failure
|
||||
*/
|
||||
@Test
|
||||
@Ignore("Fails for Bug #486394")
|
||||
public void testFileUpload_AccessViaFilename() throws Exception
|
||||
{
|
||||
tester.addServlet(ParameterListServlet.class,"/paramlist");
|
||||
|
||||
multipartFilter.setInitParameter("fileOutputBuffer", "1");
|
||||
multipartFilter.setInitParameter("deleteFiles", "false");
|
||||
multipartFilter.setInitParameter("writeFilesWithFilenames", "true");
|
||||
|
||||
// generated and parsed test
|
||||
HttpTester.Request request = HttpTester.newRequest();
|
||||
HttpTester.Response response;
|
||||
|
||||
// test GET
|
||||
request.setMethod("POST");
|
||||
request.setURI("/context/paramlist");
|
||||
request.setVersion("HTTP/1.1");
|
||||
request.setHeader("Host","tester");
|
||||
request.setHeader("Connection","close");
|
||||
String boundary="XyXyXy";
|
||||
request.setHeader("Content-Type","multipart/form-data; boundary=" + boundary);
|
||||
|
||||
StringBuilder content = new StringBuilder();
|
||||
content.append("--").append(boundary).append("\r\n");
|
||||
content.append("Content-Disposition: form-data; name=\"file\"; filename=\"tiny.dat\"\r\n");
|
||||
content.append("Content-Type: application/octet-stream\r\n");
|
||||
content.append("\r\n");
|
||||
content.append("How now brown cow.\r\n");
|
||||
content.append("--").append(boundary).append("--\r\n");
|
||||
content.append("\r\n");
|
||||
|
||||
request.setContent(content.toString());
|
||||
|
||||
response = HttpTester.parseResponse(tester.getResponses(request.generate()));
|
||||
assertThat("Response status", response.getStatus(), is(HttpServletResponse.SC_OK));
|
||||
assertEquals(HttpServletResponse.SC_OK,response.getStatus());
|
||||
|
||||
String contents = assertUploadedFileExists("tiny.dat");
|
||||
assertThat("contents", contents, containsString("How now brown cow."));
|
||||
}
|
||||
|
||||
/**
|
||||
* Validate that the two upload files, with the same name="" on two different parts,
|
||||
* can be accessed with the filename="" portions.
|
||||
* @throws Exception on test failure
|
||||
*/
|
||||
@Test
|
||||
@Ignore("Fails for Bug #486394")
|
||||
public void testTwoFileUploads_AccessViaFilename() throws Exception
|
||||
{
|
||||
tester.addServlet(ParameterListServlet.class,"/paramlist");
|
||||
|
||||
multipartFilter.setInitParameter("fileOutputBuffer", "1");
|
||||
multipartFilter.setInitParameter("deleteFiles", "false");
|
||||
multipartFilter.setInitParameter("writeFilesWithFilenames", "true");
|
||||
|
||||
// generated and parsed test
|
||||
HttpTester.Request request = HttpTester.newRequest();
|
||||
HttpTester.Response response;
|
||||
|
||||
// test GET
|
||||
request.setMethod("POST");
|
||||
request.setURI("/context/paramlist");
|
||||
request.setVersion("HTTP/1.1");
|
||||
request.setHeader("Host","tester");
|
||||
request.setHeader("Connection","close");
|
||||
|
||||
String boundary="XyXyXy";
|
||||
request.setHeader("Content-Type","multipart/form-data; boundary=" + boundary);
|
||||
|
||||
StringBuilder content = new StringBuilder();
|
||||
content.append("--").append(boundary).append("\r\n");
|
||||
content.append("Content-Disposition: form-data; name=\"same\"; filename=\"crocodile.dat\"\r\n");
|
||||
content.append("Content-Type: application/octet-stream\r\n");
|
||||
content.append("\r\n");
|
||||
content.append("See ya later, aligator.\r\n");
|
||||
content.append("--").append(boundary).append("\r\n");
|
||||
content.append("Content-Disposition: form-data; name=\"same\"; filename=\"aligator.dat\"\r\n");
|
||||
content.append("Content-Type: application/octet-stream\r\n");
|
||||
content.append("\r\n");
|
||||
content.append("In a while, crocodile.\r\n");
|
||||
content.append("--").append(boundary).append("--\r\n");
|
||||
content.append("\r\n");
|
||||
|
||||
request.setContent(content.toString());
|
||||
|
||||
response = HttpTester.parseResponse(tester.getResponses(request.generate()));
|
||||
assertThat("Response status", response.getStatus(), is(HttpServletResponse.SC_OK));
|
||||
assertEquals(HttpServletResponse.SC_OK,response.getStatus());
|
||||
|
||||
String contents = assertUploadedFileExists("crocodile.dat");
|
||||
assertThat("contents", contents, containsString("See ya later, aligator."));
|
||||
|
||||
contents = assertUploadedFileExists("aligator.dat");
|
||||
assertThat("contents", contents, containsString("In a while, crocodile."));
|
||||
}
|
||||
|
||||
private String assertUploadedFileExists(String filename) throws IOException
|
||||
{
|
||||
File uploadedFile = new File(_dir,filename);
|
||||
assertThat("Uploaded File[" + uploadedFile + "].exists",uploadedFile.exists(),is(true));
|
||||
|
||||
try (Reader reader = new FileReader(uploadedFile))
|
||||
{
|
||||
return IO.toString(reader);
|
||||
}
|
||||
}
|
||||
|
||||
public static class TestServletCharSet extends HttpServlet
|
||||
{
|
||||
|
||||
|
@ -885,11 +1051,61 @@ public class MultipartFilterTest
|
|||
response = HttpTester.parseResponse(tester.getResponses(request.generate()));
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void testFilesWithFilenames ()
|
||||
throws Exception
|
||||
{
|
||||
multipartFilter.setInitParameter("fileOutputBuffer", "0");
|
||||
multipartFilter.setInitParameter("writeFilesWithFilenames", "true");
|
||||
|
||||
|
||||
String boundary="XyXyXy";
|
||||
HttpTester.Request request = HttpTester.newRequest();
|
||||
HttpTester.Response response;
|
||||
tester.addServlet(FilenameServlet.class,"/testf");
|
||||
// test GET
|
||||
request.setMethod("POST");
|
||||
request.setVersion("HTTP/1.0");
|
||||
request.setHeader("Host","tester");
|
||||
request.setURI("/context/testf");
|
||||
request.setHeader("Content-Type","multipart/form-data; boundary="+boundary);
|
||||
|
||||
String content = "--XyXyXy\r"+
|
||||
"Content-Disposition: form-data; name=\"fileName\"\r"+
|
||||
"Content-Type: text/plain; charset=US-ASCII\r"+
|
||||
"Content-Transfer-Encoding: 8bit\r"+
|
||||
"\r"+
|
||||
"abc\r"+
|
||||
"--XyXyXy\r"+
|
||||
"Content-Disposition: form-data; name=\"desc\"\r"+
|
||||
"Content-Type: text/plain; charset=US-ASCII\r"+
|
||||
"Content-Transfer-Encoding: 8bit\r"+
|
||||
"\r"+
|
||||
"123\r"+
|
||||
"--XyXyXy\r"+
|
||||
"Content-Disposition: form-data; name=\"title\"\r"+
|
||||
"Content-Type: text/plain; charset=US-ASCII\r"+
|
||||
"Content-Transfer-Encoding: 8bit\r"+
|
||||
"\r"+
|
||||
"ttt\r"+
|
||||
"--XyXyXy\r"+
|
||||
"Content-Disposition: form-data; name=\"fileup\"; filename=\"test.upload\"\r"+
|
||||
"Content-Type: application/octet-stream\r"+
|
||||
"Content-Transfer-Encoding: binary\r"+
|
||||
"\r"+
|
||||
"000\r"+
|
||||
"--XyXyXy--\r";
|
||||
request.setContent(content);
|
||||
|
||||
response = HttpTester.parseResponse(tester.getResponses(request.generate()));
|
||||
assertEquals(HttpServletResponse.SC_OK,response.getStatus());
|
||||
assertTrue(response.getContent().indexOf("000")>=0);
|
||||
}
|
||||
|
||||
@SuppressWarnings("serial")
|
||||
public static class DumpServlet extends HttpServlet
|
||||
{
|
||||
private static final long serialVersionUID = 201012011130L;
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
/**
|
||||
* @see javax.servlet.http.HttpServlet#doPost(javax.servlet.http.HttpServletRequest, javax.servlet.http.HttpServletResponse)
|
||||
*/
|
||||
|
|
|
@ -63,6 +63,7 @@ public class MultiPartInputStreamParser
|
|||
protected File _tmpDir;
|
||||
protected File _contextTmpDir;
|
||||
protected boolean _deleteOnExit;
|
||||
protected boolean _writeFilesWithFilenames;
|
||||
|
||||
|
||||
|
||||
|
@ -94,9 +95,19 @@ public class MultiPartInputStreamParser
|
|||
protected void open()
|
||||
throws IOException
|
||||
{
|
||||
//Write to a buffer in memory until we discover we've exceed the
|
||||
//MultipartConfig fileSizeThreshold
|
||||
_out = _bout= new ByteArrayOutputStream2();
|
||||
//We will either be writing to a file, if it has a filename on the content-disposition
|
||||
//and otherwise a byte-array-input-stream, OR if we exceed the getFileSizeThreshold, we
|
||||
//will need to change to write to a file.
|
||||
if (isWriteFilesWithFilenames() && _filename != null && _filename.trim().length() > 0)
|
||||
{
|
||||
createFile();
|
||||
}
|
||||
else
|
||||
{
|
||||
//Write to a buffer in memory until we discover we've exceed the
|
||||
//MultipartConfig fileSizeThreshold
|
||||
_out = _bout= new ByteArrayOutputStream2();
|
||||
}
|
||||
}
|
||||
|
||||
protected void close()
|
||||
|
@ -751,6 +762,15 @@ public class MultiPartInputStreamParser
|
|||
_deleteOnExit = deleteOnExit;
|
||||
}
|
||||
|
||||
public void setWriteFilesWithFilenames (boolean writeFilesWithFilenames)
|
||||
{
|
||||
_writeFilesWithFilenames = writeFilesWithFilenames;
|
||||
}
|
||||
|
||||
public boolean isWriteFilesWithFilenames ()
|
||||
{
|
||||
return _writeFilesWithFilenames;
|
||||
}
|
||||
|
||||
public boolean isDeleteOnExit()
|
||||
{
|
||||
|
|
|
@ -20,6 +20,7 @@ package org.eclipse.jetty.util.thread;
|
|||
|
||||
import java.lang.reflect.Constructor;
|
||||
import java.util.concurrent.Executor;
|
||||
import java.util.concurrent.RejectedExecutionException;
|
||||
|
||||
import org.eclipse.jetty.util.Loader;
|
||||
import org.eclipse.jetty.util.log.Log;
|
||||
|
@ -53,6 +54,15 @@ public interface ExecutionStrategy
|
|||
*/
|
||||
public void execute();
|
||||
|
||||
|
||||
/**
|
||||
* A task that can handle {@link RejectedExecutionException}
|
||||
*/
|
||||
public interface Rejectable
|
||||
{
|
||||
public void reject();
|
||||
}
|
||||
|
||||
/**
|
||||
* <p>A producer of {@link Runnable} tasks to run.</p>
|
||||
* <p>The {@link ExecutionStrategy} will repeatedly invoke {@link #produce()} until
|
||||
|
|
|
@ -19,6 +19,7 @@
|
|||
package org.eclipse.jetty.util.thread.strategy;
|
||||
|
||||
import java.util.concurrent.Executor;
|
||||
import java.util.concurrent.RejectedExecutionException;
|
||||
|
||||
import org.eclipse.jetty.util.log.Log;
|
||||
import org.eclipse.jetty.util.log.Logger;
|
||||
|
@ -140,7 +141,15 @@ public class ExecuteProduceConsume implements ExecutionStrategy, Runnable
|
|||
while (_threadpool!=null && _threadpool.isLowOnThreads())
|
||||
{
|
||||
LOG.debug("EWYK low resources {}",this);
|
||||
_lowresources.execute();
|
||||
try
|
||||
{
|
||||
_lowresources.execute();
|
||||
}
|
||||
catch(Throwable e)
|
||||
{
|
||||
// just warn if lowresources execute fails and keep producing
|
||||
LOG.warn(e);
|
||||
}
|
||||
}
|
||||
|
||||
// no longer low resources so produceAndRun normally
|
||||
|
@ -204,13 +213,37 @@ public class ExecuteProduceConsume implements ExecutionStrategy, Runnable
|
|||
// Spawn a new thread to continue production by running the produce loop.
|
||||
if (LOG.isDebugEnabled())
|
||||
LOG.debug("{} dispatch",this);
|
||||
_executor.execute(this);
|
||||
try
|
||||
{
|
||||
_executor.execute(this);
|
||||
}
|
||||
catch(RejectedExecutionException e)
|
||||
{
|
||||
// If we cannot execute, then discard/reject the task and keep producing
|
||||
LOG.debug(e);
|
||||
LOG.warn("RejectedExecution {}",task);
|
||||
try
|
||||
{
|
||||
if (task instanceof Rejectable)
|
||||
((Rejectable)task).reject();
|
||||
}
|
||||
catch (Exception x)
|
||||
{
|
||||
e.addSuppressed(x);
|
||||
LOG.warn(e);
|
||||
}
|
||||
finally
|
||||
{
|
||||
task=null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Run the task.
|
||||
if (LOG.isDebugEnabled())
|
||||
LOG.debug("{} run {}",this,task);
|
||||
task.run();
|
||||
if (task != null)
|
||||
task.run();
|
||||
if (LOG.isDebugEnabled())
|
||||
LOG.debug("{} ran {}",this,task);
|
||||
|
||||
|
|
|
@ -19,6 +19,7 @@
|
|||
package org.eclipse.jetty.util.thread.strategy;
|
||||
|
||||
import java.util.concurrent.Executor;
|
||||
import java.util.concurrent.RejectedExecutionException;
|
||||
|
||||
import org.eclipse.jetty.util.log.Log;
|
||||
import org.eclipse.jetty.util.log.Logger;
|
||||
|
@ -55,7 +56,26 @@ public class ProduceExecuteConsume implements ExecutionStrategy
|
|||
break;
|
||||
|
||||
// Execute the task.
|
||||
_executor.execute(task);
|
||||
try
|
||||
{
|
||||
_executor.execute(task);
|
||||
}
|
||||
catch(RejectedExecutionException e)
|
||||
{
|
||||
// Discard/reject tasks that cannot be executed
|
||||
if (task instanceof Rejectable)
|
||||
{
|
||||
try
|
||||
{
|
||||
((Rejectable)task).reject();
|
||||
}
|
||||
catch (Throwable x)
|
||||
{
|
||||
e.addSuppressed(x);
|
||||
LOG.warn(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -657,6 +657,38 @@ public class MultiPartInputStreamTest
|
|||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void testWriteFilesIfContentDispositionFilename ()
|
||||
throws Exception
|
||||
{
|
||||
String s = "--AaB03x\r\n"+
|
||||
"content-disposition: form-data; name=\"field1\"; filename=\"frooble.txt\"\r\n"+
|
||||
"\r\n"+
|
||||
"Joe Blow\r\n"+
|
||||
"--AaB03x\r\n"+
|
||||
"content-disposition: form-data; name=\"stuff\"\r\n"+
|
||||
"Content-Type: text/plain\r\n"+
|
||||
"\r\n"+"sss"+
|
||||
"aaa"+"\r\n" +
|
||||
"--AaB03x--\r\n";
|
||||
//all default values for multipartconfig, ie file size threshold 0
|
||||
MultipartConfigElement config = new MultipartConfigElement(_dirname);
|
||||
MultiPartInputStreamParser mpis = new MultiPartInputStreamParser(new ByteArrayInputStream(s.getBytes()),
|
||||
_contentType,
|
||||
config,
|
||||
_tmpDir);
|
||||
mpis.setDeleteOnExit(true);
|
||||
mpis.setWriteFilesWithFilenames(true);
|
||||
Collection<Part> parts = mpis.getParts();
|
||||
assertThat(parts.size(), is(2));
|
||||
Part field1 = mpis.getPart("field1"); //has a filename, should be written to a file
|
||||
File f = ((MultiPartInputStreamParser.MultiPart)field1).getFile();
|
||||
assertThat(f,notNullValue()); // longer than 100 bytes, should already be a tmp file
|
||||
|
||||
Part stuff = mpis.getPart("stuff");
|
||||
f = ((MultiPartInputStreamParser.MultiPart)stuff).getFile(); //should only be in memory, no filename
|
||||
assertThat(f, nullValue());
|
||||
}
|
||||
|
||||
|
||||
private void testMulti(String filename) throws IOException, ServletException, InterruptedException
|
||||
|
|
|
@ -51,6 +51,8 @@ public class BinaryFrame extends DataFrame
|
|||
@Override
|
||||
public Type getType()
|
||||
{
|
||||
if (getOpCode() == OpCode.CONTINUATION)
|
||||
return Type.CONTINUATION;
|
||||
return Type.BINARY;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -34,6 +34,8 @@ public class TextFrame extends DataFrame
|
|||
@Override
|
||||
public Type getType()
|
||||
{
|
||||
if (getOpCode() == OpCode.CONTINUATION)
|
||||
return Type.CONTINUATION;
|
||||
return Type.TEXT;
|
||||
}
|
||||
|
||||
|
|
|
@ -41,8 +41,8 @@
|
|||
<New id="defcontext" class="org.eclipse.jetty.server.handler.ContextHandler">
|
||||
<Set name="contextPath">/tests</Set>
|
||||
<Set name="ResourceBase"><Property name="test.docroot.base"/>/default</Set>
|
||||
<Set name="Handler"><New id="reshandler" class="org.eclipse.jetty.server.handler.ResourceHandler"/></Set>
|
||||
<Set name="DisplayName">default</Set>
|
||||
<Set name="Handler"><New id="reshandler" class="org.eclipse.jetty.server.handler.ResourceHandler"/></Set>
|
||||
<Set name="DisplayName">default</Set>
|
||||
</New>
|
||||
</Item>
|
||||
</Array>
|
||||
|
|
|
@ -102,12 +102,10 @@
|
|||
</Arg>
|
||||
</Call>
|
||||
|
||||
|
||||
|
||||
<!-- =========================================================== -->
|
||||
<!-- extra options -->
|
||||
<!-- =========================================================== -->
|
||||
<Set name="stopAtShutdown">true</Set>
|
||||
<Set name="stopTimeout">1000</Set>
|
||||
<!-- =========================================================== -->
|
||||
<!-- extra options -->
|
||||
<!-- =========================================================== -->
|
||||
<Set name="stopAtShutdown">true</Set>
|
||||
<Set name="stopTimeout">1000</Set>
|
||||
|
||||
</Configure>
|
||||
|
|
|
@ -2,53 +2,51 @@
|
|||
<!DOCTYPE Configure PUBLIC "-//Jetty//Configure//EN" "http://www.eclipse.org/jetty/configure_9_3.dtd">
|
||||
|
||||
<Configure id="Server" class="org.eclipse.jetty.server.Server">
|
||||
<!-- =========================================================== -->
|
||||
<!-- Configure Rewrite Handler -->
|
||||
<!-- =========================================================== -->
|
||||
<Get id="oldhandler" name="handler"/>
|
||||
<!-- =========================================================== -->
|
||||
<!-- Configure Rewrite Handler -->
|
||||
<!-- =========================================================== -->
|
||||
|
||||
<Set name="handler">
|
||||
<Call name="insertHandler">
|
||||
<Arg>
|
||||
<New id="Rewrite" class="org.eclipse.jetty.rewrite.handler.RewriteHandler">
|
||||
|
||||
<Set name="handler"><Ref refid="oldhandler"/></Set>
|
||||
<Set name="rewriteRequestURI">true</Set>
|
||||
<Set name="rewritePathInfo">false</Set>
|
||||
<Set name="originalPathAttribute">requestedPath</Set>
|
||||
|
||||
<Set name="rules">
|
||||
<Array type="org.eclipse.jetty.rewrite.handler.Rule">
|
||||
<Array type="org.eclipse.jetty.rewrite.handler.Rule">
|
||||
|
||||
<!-- add a response rule -->
|
||||
<!--
|
||||
<Item>
|
||||
<New id="response" class="org.eclipse.jetty.rewrite.handler.ResponsePatternRule">
|
||||
<Set name="pattern">/rewrite/session/</Set>
|
||||
<Set name="code">401</Set>
|
||||
<Set name="reason">Setting error code 401</Set>
|
||||
</New>
|
||||
</Item>
|
||||
-->
|
||||
<!-- add a response rule -->
|
||||
<!--
|
||||
<Item>
|
||||
<New id="response" class="org.eclipse.jetty.rewrite.handler.ResponsePatternRule">
|
||||
<Set name="pattern">/rewrite/session/</Set>
|
||||
<Set name="code">401</Set>
|
||||
<Set name="reason">Setting error code 401</Set>
|
||||
</New>
|
||||
</Item>
|
||||
-->
|
||||
|
||||
<!-- add a simple redirect -->
|
||||
<!--
|
||||
<Item>
|
||||
<New id="redirect" class="org.eclipse.jetty.rewrite.handler.RedirectPatternRule">
|
||||
<Set name="pattern">/redirect/*</Set>
|
||||
<Set name="location">/tests/</Set>
|
||||
</New>
|
||||
</Item>
|
||||
-->
|
||||
<!-- add a simple redirect -->
|
||||
<!--
|
||||
<Item>
|
||||
<New id="redirect" class="org.eclipse.jetty.rewrite.handler.RedirectPatternRule">
|
||||
<Set name="pattern">/redirect/*</Set>
|
||||
<Set name="location">/tests/</Set>
|
||||
</New>
|
||||
</Item>
|
||||
-->
|
||||
|
||||
<!-- add a regex rewrite redirect -->
|
||||
<Item>
|
||||
<New id="redirect" class="org.eclipse.jetty.rewrite.handler.RedirectRegexRule">
|
||||
<Set name="regex">/redirect/(.*)</Set>
|
||||
<Set name="replacement">/tests/$1</Set>
|
||||
</New>
|
||||
</Item>
|
||||
</Array>
|
||||
</Set>
|
||||
<!-- add a regex rewrite redirect -->
|
||||
<Item>
|
||||
<New id="redirect" class="org.eclipse.jetty.rewrite.handler.RedirectRegexRule">
|
||||
<Set name="regex">/redirect/(.*)</Set>
|
||||
<Set name="replacement">/tests/$1</Set>
|
||||
</New>
|
||||
</Item>
|
||||
</Array>
|
||||
</Set>
|
||||
</New>
|
||||
</Set>
|
||||
|
||||
</Arg>
|
||||
</Call>
|
||||
</Configure>
|
||||
|
|
|
@ -161,12 +161,12 @@ public class JdbcLoginServiceTest
|
|||
}
|
||||
}
|
||||
|
||||
public void testGetWithNonExistantUser() throws Exception
|
||||
@Test
|
||||
public void testGetNonExistantUser () throws Exception
|
||||
{
|
||||
try
|
||||
{
|
||||
startClient("foo", "bar");
|
||||
|
||||
ContentResponse response = _client.GET(_baseUri.resolve("input.txt"));
|
||||
assertEquals(HttpServletResponse.SC_UNAUTHORIZED,response.getStatus());
|
||||
}
|
||||
|
@ -216,7 +216,7 @@ public class JdbcLoginServiceTest
|
|||
}
|
||||
}
|
||||
|
||||
protected void startClient(String username, String pwd)
|
||||
protected void startClient(String user, String pwd)
|
||||
throws Exception
|
||||
{
|
||||
_client = new HttpClient();
|
||||
|
@ -224,7 +224,7 @@ public class JdbcLoginServiceTest
|
|||
executor.setName(executor.getName() + "-client");
|
||||
_client.setExecutor(executor);
|
||||
AuthenticationStore authStore = _client.getAuthenticationStore();
|
||||
authStore.addAuthentication(new BasicAuthentication(_baseUri, __realm, username, pwd));
|
||||
authStore.addAuthentication(new BasicAuthentication(_baseUri, __realm, user, pwd));
|
||||
_client.start();
|
||||
}
|
||||
|
||||
|
|
|
@ -18,12 +18,17 @@
|
|||
|
||||
package org.eclipse.jetty.quickstart;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.hamcrest.Matchers.is;
|
||||
import static org.junit.Assert.assertThat;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.net.MalformedURLException;
|
||||
import java.net.URI;
|
||||
import java.net.URISyntaxException;
|
||||
import java.net.URL;
|
||||
import java.nio.file.FileSystems;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
|
@ -43,16 +48,50 @@ public class AttributeNormalizerTest
|
|||
public static List<String[]> data()
|
||||
{
|
||||
String[][] tests = {
|
||||
{ "WAR", "/opt/jetty-distro/demo.base/webapps/root" },
|
||||
{ "jetty.home", "/opt/jetty-distro" },
|
||||
{ "jetty.base", "/opt/jetty-distro/demo.base" },
|
||||
{ "user.home", "/home/user" },
|
||||
{ "user.dir", "/etc/init.d" },
|
||||
{ "WAR", toSystemPath("/opt/jetty-distro/demo.base/webapps/root") },
|
||||
{ "jetty.home", toSystemPath("/opt/jetty-distro") },
|
||||
{ "jetty.base", toSystemPath("/opt/jetty-distro/demo.base") },
|
||||
{ "user.home", toSystemPath("/home/user") },
|
||||
{ "user.dir", toSystemPath("/etc/init.d") },
|
||||
};
|
||||
|
||||
return Arrays.asList(tests);
|
||||
}
|
||||
|
||||
/**
|
||||
* As the declared paths in this testcase might be actual paths on the system
|
||||
* running these tests, the expected paths should be cleaned up to represent
|
||||
* the actual system paths.
|
||||
* <p>
|
||||
* Eg: on fedora /etc/init.d is a symlink to /etc/rc.d/init.d
|
||||
*/
|
||||
private static String toSystemPath(String rawpath)
|
||||
{
|
||||
Path path = FileSystems.getDefault().getPath(rawpath);
|
||||
if (Files.exists(path))
|
||||
{
|
||||
// It exists, resolve it to the real path
|
||||
try
|
||||
{
|
||||
path = path.toRealPath();
|
||||
}
|
||||
catch (IOException e)
|
||||
{
|
||||
// something prevented us from resolving to real path, fallback to
|
||||
// absolute path resolution (not as accurate)
|
||||
path = path.toAbsolutePath();
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// File doesn't exist, resolve to absolute path
|
||||
// We can't rely on File.toCanonicalPath() here
|
||||
path = path.toAbsolutePath();
|
||||
}
|
||||
return path.toString();
|
||||
}
|
||||
|
||||
private static String origJettyBase;
|
||||
private static String origJettyHome;
|
||||
private static String origUserHome;
|
||||
|
@ -97,108 +136,108 @@ public class AttributeNormalizerTest
|
|||
@Test
|
||||
public void testEqual()
|
||||
{
|
||||
assertEquals("file:${" + key + "}",normalizer.normalize("file:" + path));
|
||||
assertThat(normalizer.normalize("file:" + path), is("file:${" + key + "}"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testEqualsSlash()
|
||||
{
|
||||
assertEquals("file:${" + key + "}",normalizer.normalize("file:" + path + "/"));
|
||||
assertThat(normalizer.normalize("file:" + path + "/"), is("file:${" + key + "}"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testEqualsSlashFile()
|
||||
{
|
||||
assertEquals("file:${" + key + "}/file",normalizer.normalize("file:" + path + "/file"));
|
||||
assertThat(normalizer.normalize("file:" + path + "/file"), is("file:${" + key + "}/file"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testURIEquals() throws URISyntaxException
|
||||
{
|
||||
assertEquals("file:${" + key + "}",normalizer.normalize(new URI("file:" + path)));
|
||||
assertThat(normalizer.normalize(new URI("file:" + path)), is("file:${" + key + "}"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testURIEqualsSlash() throws URISyntaxException
|
||||
{
|
||||
assertEquals("file:${" + key + "}",normalizer.normalize(new URI("file:" + path + "/")));
|
||||
assertThat(normalizer.normalize(new URI("file:" + path + "/")), is("file:${" + key + "}"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testURIEqualsSlashFile() throws URISyntaxException
|
||||
{
|
||||
assertEquals("file:${" + key + "}/file",normalizer.normalize(new URI("file:" + path + "/file")));
|
||||
assertThat(normalizer.normalize(new URI("file:" + path + "/file")), is("file:${" + key + "}/file"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testURLEquals() throws MalformedURLException
|
||||
{
|
||||
assertEquals("file:${" + key + "}",normalizer.normalize(new URL("file:" + path)));
|
||||
assertThat(normalizer.normalize(new URL("file:" + path)), is("file:${" + key + "}"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testURLEqualsSlash() throws MalformedURLException
|
||||
{
|
||||
assertEquals("file:${" + key + "}",normalizer.normalize(new URL("file:" + path + "/")));
|
||||
assertThat(normalizer.normalize(new URL("file:" + path + "/")), is("file:${" + key + "}"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testURLEqualsSlashFile() throws MalformedURLException
|
||||
{
|
||||
assertEquals("file:${" + key + "}/file",normalizer.normalize(new URL("file:" + path + "/file")));
|
||||
assertThat(normalizer.normalize(new URL("file:" + path + "/file")), is("file:${" + key + "}/file"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testJarFileEquals_BangFile()
|
||||
{
|
||||
assertEquals("jar:file:${" + key + "}!/file",normalizer.normalize("jar:file:" + path + "!/file"));
|
||||
assertThat(normalizer.normalize("jar:file:" + path + "!/file"), is("jar:file:${" + key + "}!/file"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testJarFileEquals_SlashBangFile()
|
||||
{
|
||||
assertEquals("jar:file:${" + key + "}!/file",normalizer.normalize("jar:file:" + path + "/!/file"));
|
||||
assertThat(normalizer.normalize("jar:file:" + path + "/!/file"), is("jar:file:${" + key + "}!/file"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testJarFileEquals_FileBangFile()
|
||||
{
|
||||
assertEquals("jar:file:${" + key + "}/file!/file",normalizer.normalize("jar:file:" + path + "/file!/file"));
|
||||
assertThat(normalizer.normalize("jar:file:" + path + "/file!/file"), is("jar:file:${" + key + "}/file!/file"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testJarFileEquals_URIBangFile() throws URISyntaxException
|
||||
{
|
||||
assertEquals("jar:file:${" + key + "}!/file",normalizer.normalize(new URI("jar:file:" + path + "!/file")));
|
||||
assertThat(normalizer.normalize(new URI("jar:file:" + path + "!/file")), is("jar:file:${" + key + "}!/file"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testJarFileEquals_URISlashBangFile() throws URISyntaxException
|
||||
{
|
||||
assertEquals("jar:file:${" + key + "}!/file",normalizer.normalize(new URI("jar:file:" + path + "/!/file")));
|
||||
assertThat(normalizer.normalize(new URI("jar:file:" + path + "/!/file")), is("jar:file:${" + key + "}!/file"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testJarFileEquals_URIFileBangFile() throws URISyntaxException
|
||||
{
|
||||
assertEquals("jar:file:${" + key + "}/file!/file",normalizer.normalize(new URI("jar:file:" + path + "/file!/file")));
|
||||
assertThat(normalizer.normalize(new URI("jar:file:" + path + "/file!/file")), is("jar:file:${" + key + "}/file!/file"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testJarFileEquals_URLBangFile() throws MalformedURLException
|
||||
{
|
||||
assertEquals("jar:file:${" + key + "}!/file",normalizer.normalize(new URL("jar:file:" + path + "!/file")));
|
||||
assertThat(normalizer.normalize(new URL("jar:file:" + path + "!/file")), is("jar:file:${" + key + "}!/file"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testJarFileEquals_URLSlashBangFile() throws MalformedURLException
|
||||
{
|
||||
assertEquals("jar:file:${" + key + "}!/file",normalizer.normalize(new URL("jar:file:" + path + "/!/file")));
|
||||
assertThat(normalizer.normalize(new URL("jar:file:" + path + "/!/file")), is("jar:file:${" + key + "}!/file"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testJarFileEquals_URLFileBangFile() throws MalformedURLException
|
||||
{
|
||||
assertEquals("jar:file:${" + key + "}/file!/file",normalizer.normalize(new URL("jar:file:" + path + "/file!/file")));
|
||||
assertThat(normalizer.normalize(new URL("jar:file:" + path + "/file!/file")), is("jar:file:${" + key + "}/file!/file"));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -21,7 +21,7 @@
|
|||
<parent>
|
||||
<groupId>org.eclipse.jetty.tests</groupId>
|
||||
<artifactId>test-sessions-parent</artifactId>
|
||||
<version>9.3.4-SNAPSHOT</version>
|
||||
<version>9.4.0-SNAPSHOT</version>
|
||||
</parent>
|
||||
<artifactId>test-file-sessions</artifactId>
|
||||
<name>Jetty Tests :: Sessions :: File</name>
|
||||
|
|
|
@ -13,7 +13,6 @@ detected.
|
|||
|
||||
<Configure class="org.eclipse.jetty.webapp.WebAppContext">
|
||||
|
||||
|
||||
<!-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -->
|
||||
<!-- Required minimal context configuration : -->
|
||||
<!-- + contextPath -->
|
||||
|
|
Loading…
Reference in New Issue