Merge branch 'jetty-8' into release-8
This commit is contained in:
commit
b794ad4633
33
VERSION.txt
33
VERSION.txt
|
@ -71,6 +71,37 @@ jetty-8.1.0.RC0 - 30 November 2011
|
|||
+ 364283 can't parse the servlet multipart-config for the web.xml
|
||||
+ 364430 Support web.xml enabled state for servlets
|
||||
|
||||
jetty-7.6.0.RC5 - 20 January 2012
|
||||
+ 359329 Prevent reinvocation of LoginModule.login with jaspi for already
|
||||
authed user
|
||||
+ 368632 Remove superfluous removal of org.apache.catalina.jsp_file
|
||||
+ 368633 fixed configure.dtd resource mappings
|
||||
+ 368635 moved lifecycle state reporting from toString to dump
|
||||
+ 368773 process data constraints without realm
|
||||
+ 368787 always set token view to new header buffers in httpparser
|
||||
+ 368821 improved test harness
|
||||
+ 368920 JettyAwareLogger always formats the arguments.
|
||||
+ 368948 POM for jetty-jndi references unknown version for javax.activation.
|
||||
+ 368992 avoid non-blocking flush when writing to avoid setting !_writable
|
||||
without _writeblocked
|
||||
+ JETTY-1475 made output state fields volatile to provide memory barrier for
|
||||
non dispatched thread IO
|
||||
|
||||
jetty-7.6.0.RC4 - 13 January 2012
|
||||
+ 365048 jetty Http client does not send proxy authentication when requesting
|
||||
a Https-resource through a web-proxy.
|
||||
+ 366774 removed XSS vulnerbility
|
||||
+ 367099 Upgrade jetty-websocket for RFC 6455 - Addendum.
|
||||
+ 367716 simplified maxIdleTime logic
|
||||
+ 368035 WebSocketClientFactory does not invoke super.doStop().
|
||||
+ 368060 do not encode sendRedirect URLs
|
||||
+ 368114 Protect against non-Strings in System properties for Log
|
||||
+ 368189 WebSocketClientFactory should not manage external thread pool.
|
||||
+ 368215 Remove debug from jaspi
|
||||
+ 368240 Improve AggregateLifeCycle handling of shared lifecycles
|
||||
+ 368291 Change warning to info for NoSuchFieldException on
|
||||
BeanELResolver.properties
|
||||
|
||||
jetty-7.6.0.RC3 - 05 January 2012
|
||||
+ 367433 added tests to investigate
|
||||
+ 367435 improved D00 test harness
|
||||
|
@ -79,7 +110,7 @@ jetty-7.6.0.RC3 - 05 January 2012
|
|||
stopped.
|
||||
+ 367591 corrected configuration.xml version to 7.6
|
||||
+ 367635 Added support for start.d directory
|
||||
+ 637638 limit number of form parameters to avoid DOS
|
||||
+ 367638 limit number of form parameters to avoid DOS
|
||||
+ JETTY-1467 close half closed when idle
|
||||
|
||||
jetty-7.6.0.RC2 - 22 December 2011
|
||||
|
|
|
@ -1,5 +1,7 @@
|
|||
package org.eclipse.jetty.client;
|
||||
|
||||
import static org.hamcrest.Matchers.*;
|
||||
|
||||
import java.io.BufferedReader;
|
||||
import java.io.EOFException;
|
||||
import java.io.File;
|
||||
|
@ -10,6 +12,7 @@ import java.net.SocketTimeoutException;
|
|||
import java.nio.channels.SocketChannel;
|
||||
import java.util.Arrays;
|
||||
import java.util.concurrent.Callable;
|
||||
import java.util.concurrent.CountDownLatch;
|
||||
import java.util.concurrent.ExecutorService;
|
||||
import java.util.concurrent.Executors;
|
||||
import java.util.concurrent.Future;
|
||||
|
@ -18,6 +21,7 @@ import java.util.concurrent.atomic.AtomicInteger;
|
|||
import java.util.concurrent.atomic.AtomicReference;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
import javax.net.ssl.SSLContext;
|
||||
import javax.net.ssl.SSLEngine;
|
||||
import javax.net.ssl.SSLSocket;
|
||||
|
@ -42,6 +46,7 @@ import org.eclipse.jetty.server.handler.AbstractHandler;
|
|||
import org.eclipse.jetty.server.ssl.SslSelectChannelConnector;
|
||||
import org.eclipse.jetty.toolchain.test.MavenTestingUtils;
|
||||
import org.eclipse.jetty.toolchain.test.OS;
|
||||
import org.eclipse.jetty.util.component.Dumpable;
|
||||
import org.eclipse.jetty.util.ssl.SslContextFactory;
|
||||
import org.junit.After;
|
||||
import org.junit.Assert;
|
||||
|
@ -49,9 +54,6 @@ import org.junit.Assume;
|
|||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
|
||||
import static org.hamcrest.Matchers.greaterThan;
|
||||
import static org.hamcrest.Matchers.lessThan;
|
||||
|
||||
public class SslBytesServerTest extends SslBytesTest
|
||||
{
|
||||
private final AtomicInteger sslHandles = new AtomicInteger();
|
||||
|
@ -61,8 +63,10 @@ public class SslBytesServerTest extends SslBytesTest
|
|||
private final int idleTimeout = 2000;
|
||||
private ExecutorService threadPool;
|
||||
private Server server;
|
||||
private int serverPort;
|
||||
private SSLContext sslContext;
|
||||
private SimpleProxy proxy;
|
||||
private Runnable idleHook;
|
||||
|
||||
@Before
|
||||
public void init() throws Exception
|
||||
|
@ -98,6 +102,15 @@ public class SslBytesServerTest extends SslBytesTest
|
|||
}
|
||||
};
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onIdleExpired(long idleForMs)
|
||||
{
|
||||
final Runnable idleHook = SslBytesServerTest.this.idleHook;
|
||||
if (idleHook != null)
|
||||
idleHook.run();
|
||||
super.onIdleExpired(idleForMs);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
|
@ -166,7 +179,7 @@ public class SslBytesServerTest extends SslBytesTest
|
|||
}
|
||||
});
|
||||
server.start();
|
||||
int serverPort = connector.getLocalPort();
|
||||
serverPort = connector.getLocalPort();
|
||||
|
||||
sslContext = cf.getSslContext();
|
||||
|
||||
|
@ -606,10 +619,12 @@ public class SslBytesServerTest extends SslBytesTest
|
|||
}
|
||||
|
||||
// Check that we did not spin
|
||||
TimeUnit.MILLISECONDS.sleep(500);
|
||||
TimeUnit.MILLISECONDS.sleep(1000);
|
||||
Assert.assertThat(sslHandles.get(), lessThan(750));
|
||||
Assert.assertThat(sslFlushes.get(), lessThan(750));
|
||||
Assert.assertThat(httpParses.get(), lessThan(150));
|
||||
// An average of 958 httpParses is seen in standard Oracle JDK's
|
||||
// An average of 1183 httpParses is seen in OpenJDK JVMs.
|
||||
Assert.assertThat(httpParses.get(), lessThan(1500));
|
||||
|
||||
client.close();
|
||||
|
||||
|
@ -1512,6 +1527,172 @@ public class SslBytesServerTest extends SslBytesTest
|
|||
Assert.assertFalse(serverEndPoint.get().isOpen());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testPlainText() throws Exception
|
||||
{
|
||||
final SSLSocket client = newClient();
|
||||
|
||||
threadPool.submit(new Callable<Object>()
|
||||
{
|
||||
public Object call() throws Exception
|
||||
{
|
||||
client.startHandshake();
|
||||
return null;
|
||||
}
|
||||
});
|
||||
|
||||
// Instead of passing the Client Hello, we simulate plain text was passed in
|
||||
proxy.flushToServer(0, "GET / HTTP/1.1\r\n".getBytes("UTF-8"));
|
||||
|
||||
// We expect that the server closes the connection immediately
|
||||
TLSRecord record = proxy.readFromServer();
|
||||
Assert.assertNull(String.valueOf(record), record);
|
||||
|
||||
// Check that we did not spin
|
||||
TimeUnit.MILLISECONDS.sleep(500);
|
||||
Assert.assertThat(sslHandles.get(), lessThan(20));
|
||||
Assert.assertThat(sslFlushes.get(), lessThan(20));
|
||||
Assert.assertThat(httpParses.get(), lessThan(50));
|
||||
|
||||
client.close();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testRequestConcurrentWithIdleExpiration() throws Exception
|
||||
{
|
||||
final SSLSocket client = newClient();
|
||||
final OutputStream clientOutput = client.getOutputStream();
|
||||
final CountDownLatch latch = new CountDownLatch(1);
|
||||
|
||||
idleHook = new Runnable()
|
||||
{
|
||||
public void run()
|
||||
{
|
||||
if (latch.getCount()==0)
|
||||
return;
|
||||
try
|
||||
{
|
||||
// Send request
|
||||
clientOutput.write(("" +
|
||||
"GET / HTTP/1.1\r\n" +
|
||||
"Host: localhost\r\n" +
|
||||
"\r\n").getBytes("UTF-8"));
|
||||
clientOutput.flush();
|
||||
latch.countDown();
|
||||
}
|
||||
catch (Exception x)
|
||||
{
|
||||
// Latch won't trigger and test will fail
|
||||
x.printStackTrace();
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
SimpleProxy.AutomaticFlow automaticProxyFlow = proxy.startAutomaticFlow();
|
||||
client.startHandshake();
|
||||
Assert.assertTrue(automaticProxyFlow.stop(5, TimeUnit.SECONDS));
|
||||
|
||||
Assert.assertTrue(latch.await(idleTimeout * 2, TimeUnit.MILLISECONDS));
|
||||
|
||||
// Be sure that the server sent a SSL close alert
|
||||
TLSRecord record = proxy.readFromServer();
|
||||
Assert.assertNotNull(record);
|
||||
Assert.assertEquals(TLSRecord.Type.ALERT, record.getType());
|
||||
|
||||
// Write the request to the server, to simulate a request
|
||||
// concurrent with the SSL close alert
|
||||
record = proxy.readFromClient();
|
||||
Assert.assertEquals(TLSRecord.Type.APPLICATION, record.getType());
|
||||
proxy.flushToServer(record, 0);
|
||||
|
||||
// Check that we did not spin
|
||||
TimeUnit.MILLISECONDS.sleep(500);
|
||||
Assert.assertThat(sslHandles.get(), lessThan(20));
|
||||
Assert.assertThat(sslFlushes.get(), lessThan(20));
|
||||
Assert.assertThat(httpParses.get(), lessThan(50));
|
||||
|
||||
//System.err.println(((Dumpable)server.getConnectors()[0]).dump());
|
||||
Assert.assertThat(((Dumpable)server.getConnectors()[0]).dump(),containsString("SCEP@"));
|
||||
|
||||
completeClose(client);
|
||||
|
||||
TimeUnit.MILLISECONDS.sleep(200);
|
||||
//System.err.println(((Dumpable)server.getConnectors()[0]).dump());
|
||||
Assert.assertThat(((Dumpable)server.getConnectors()[0]).dump(),not(containsString("SCEP@")));
|
||||
|
||||
}
|
||||
/*
|
||||
@Test
|
||||
public void testRequestWriteBlockedWithPipelinedRequest() throws Exception
|
||||
{
|
||||
final SSLSocket client = newClient();
|
||||
final OutputStream clientOutput = client.getOutputStream();
|
||||
|
||||
SimpleProxy.AutomaticFlow automaticProxyFlow = proxy.startAutomaticFlow();
|
||||
client.startHandshake();
|
||||
Assert.assertTrue(automaticProxyFlow.stop(5, TimeUnit.SECONDS));
|
||||
|
||||
byte[] data = new byte[128 * 1024];
|
||||
Arrays.fill(data, (byte)'X');
|
||||
final String content = new String(data, "UTF-8");
|
||||
Future<Object> request = threadPool.submit(new Callable<Object>()
|
||||
{
|
||||
public Object call() throws Exception
|
||||
{
|
||||
clientOutput.write(("" +
|
||||
"POST /echo HTTP/1.1\r\n" +
|
||||
"Host: localhost\r\n" +
|
||||
"Content-Length: " + content.length() + "\r\n" +
|
||||
"\r\n" +
|
||||
content).getBytes("UTF-8"));
|
||||
clientOutput.flush();
|
||||
return null;
|
||||
}
|
||||
});
|
||||
|
||||
// Nine TLSRecords will be generated for the request
|
||||
for (int i = 0; i < 9; ++i)
|
||||
{
|
||||
// Application data
|
||||
TLSRecord record = proxy.readFromClient();
|
||||
Assert.assertEquals(TLSRecord.Type.APPLICATION, record.getType());
|
||||
proxy.flushToServer(record, 0);
|
||||
}
|
||||
Assert.assertNull(request.get(5, TimeUnit.SECONDS));
|
||||
|
||||
// We do not read the big request to cause a write blocked on the server
|
||||
TimeUnit.MILLISECONDS.sleep(500);
|
||||
|
||||
// Now send the pipelined request
|
||||
Future<Object> pipelined = threadPool.submit(new Callable<Object>()
|
||||
{
|
||||
public Object call() throws Exception
|
||||
{
|
||||
clientOutput.write(("" +
|
||||
"GET /pipelined HTTP/1.1\r\n" +
|
||||
"Host: localhost\r\n" +
|
||||
"\r\n").getBytes("UTF-8"));
|
||||
clientOutput.flush();
|
||||
return null;
|
||||
}
|
||||
});
|
||||
|
||||
TLSRecord record = proxy.readFromClient();
|
||||
Assert.assertEquals(TLSRecord.Type.APPLICATION, record.getType());
|
||||
proxy.flushToServer(record, 0);
|
||||
Assert.assertNull(pipelined.get(5, TimeUnit.SECONDS));
|
||||
|
||||
// Check that we did not spin
|
||||
TimeUnit.MILLISECONDS.sleep(500);
|
||||
Assert.assertThat(sslHandles.get(), lessThan(20));
|
||||
Assert.assertThat(sslFlushes.get(), lessThan(20));
|
||||
Assert.assertThat(httpParses.get(), lessThan(50));
|
||||
|
||||
Thread.sleep(5000);
|
||||
|
||||
// closeClient(client);
|
||||
}
|
||||
*/
|
||||
private void assumeJavaVersionSupportsTLSRenegotiations()
|
||||
{
|
||||
// Due to a security bug, TLS renegotiations were disabled in JDK 1.6.0_19-21
|
||||
|
@ -1549,9 +1730,28 @@ public class SslBytesServerTest extends SslBytesTest
|
|||
// Close Alert
|
||||
record = proxy.readFromServer();
|
||||
proxy.flushToClient(record);
|
||||
|
||||
// Socket close
|
||||
record = proxy.readFromServer();
|
||||
Assert.assertNull(String.valueOf(record), record);
|
||||
proxy.flushToClient(record);
|
||||
}
|
||||
|
||||
private void completeClose(SSLSocket client) throws Exception
|
||||
{
|
||||
client.close();
|
||||
|
||||
// Close Alert
|
||||
TLSRecord record = proxy.readFromClient();
|
||||
proxy.flushToServer(record);
|
||||
// Socket close
|
||||
record = proxy.readFromClient();
|
||||
Assert.assertNull(String.valueOf(record), record);
|
||||
proxy.flushToServer(record);
|
||||
|
||||
// Close Alert
|
||||
record = proxy.readFromServer();
|
||||
proxy.flushToClient(record);
|
||||
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
<?xml version="1.0" encoding="ISO-8859-1"?>
|
||||
<!DOCTYPE Configure PUBLIC "-//Mort Bay Consulting//DTD Configure//EN" "http://jetty.mortbay.org/configure.dtd">
|
||||
<!DOCTYPE Configure PUBLIC "-//Mort Bay Consulting//DTD Configure//EN" "http://www.eclipse.org/jetty/configure.dtd">
|
||||
<Configure class="org.eclipse.jetty.webapp.WebAppContext">
|
||||
<Set name="contextPath">/foo</Set>
|
||||
<Set name="war">
|
||||
|
|
|
@ -12,7 +12,7 @@
|
|||
<jetty-orbit-url>http://download.eclipse.org/jetty/orbit</jetty-orbit-url>
|
||||
<assembly-directory>target/distribution</assembly-directory>
|
||||
<eclipse-ecj-version>3.6</eclipse-ecj-version>
|
||||
<orbit-javax-activation-version>${javax-activation-version}.0.v201105071233</orbit-javax-activation-version>
|
||||
<orbit-javax-activation-version>${javax-activation-version}.0.v201005080500</orbit-javax-activation-version>
|
||||
<orbit-javax-annotation-version>1.1.0.v201105051105</orbit-javax-annotation-version>
|
||||
<orbit-javax-el-version>2.2.0.v201105051105</orbit-javax-el-version>
|
||||
<orbit-javax-mail-glassfish-version>${javax-mail-version}.v201005082020</orbit-javax-mail-glassfish-version>
|
||||
|
|
|
@ -63,8 +63,8 @@ public class HttpParser implements Parser
|
|||
private Buffer _body; // Buffer for large content
|
||||
private Buffer _buffer; // The current buffer in use (either _header or _content)
|
||||
private CachedBuffer _cached;
|
||||
private View.CaseInsensitive _tok0; // Saved token: header name, request method or response version
|
||||
private View.CaseInsensitive _tok1; // Saved token: header value, request URI or response code
|
||||
private final View.CaseInsensitive _tok0; // Saved token: header name, request method or response version
|
||||
private final View.CaseInsensitive _tok1; // Saved token: header value, request URI or response code
|
||||
private String _multiLineValue;
|
||||
private int _responseStatus; // If >0 then we are parsing a response
|
||||
private boolean _forceContentBuffer;
|
||||
|
@ -93,13 +93,8 @@ public class HttpParser implements Parser
|
|||
_buffer=buffer;
|
||||
_handler=handler;
|
||||
|
||||
if (buffer != null)
|
||||
{
|
||||
_tok0=new View.CaseInsensitive(buffer);
|
||||
_tok1=new View.CaseInsensitive(buffer);
|
||||
_tok0.setPutIndex(_tok0.getIndex());
|
||||
_tok1.setPutIndex(_tok1.getIndex());
|
||||
}
|
||||
_tok0=new View.CaseInsensitive(_header);
|
||||
_tok1=new View.CaseInsensitive(_header);
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------------------------- */
|
||||
|
@ -114,6 +109,8 @@ public class HttpParser implements Parser
|
|||
_buffers=buffers;
|
||||
_endp=endp;
|
||||
_handler=handler;
|
||||
_tok0=new View.CaseInsensitive();
|
||||
_tok1=new View.CaseInsensitive();
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------------------------- */
|
||||
|
@ -197,7 +194,7 @@ public class HttpParser implements Parser
|
|||
public void setPersistent(boolean persistent)
|
||||
{
|
||||
_persistent = persistent;
|
||||
if (_state==STATE_END)
|
||||
if (!_persistent &&(_state==STATE_END || _state==STATE_START))
|
||||
_state=STATE_SEEKING_EOF;
|
||||
}
|
||||
|
||||
|
@ -256,17 +253,7 @@ public class HttpParser implements Parser
|
|||
return 0;
|
||||
|
||||
if (_buffer==null)
|
||||
{
|
||||
if (_header == null)
|
||||
{
|
||||
_header=_buffers.getHeader();
|
||||
}
|
||||
_buffer=_header;
|
||||
_tok0=new View.CaseInsensitive(_header);
|
||||
_tok1=new View.CaseInsensitive(_header);
|
||||
_tok0.setPutIndex(_tok0.getIndex());
|
||||
_tok1.setPutIndex(_tok1.getIndex());
|
||||
}
|
||||
_buffer=getHeaderBuffer();
|
||||
|
||||
|
||||
if (_state == STATE_CONTENT && _contentPosition == _contentLength)
|
||||
|
@ -1013,11 +1000,7 @@ public class HttpParser implements Parser
|
|||
{
|
||||
// Do we have a buffer?
|
||||
if (_buffer==null)
|
||||
{
|
||||
_buffer=_header=getHeaderBuffer();
|
||||
_tok0=new View.CaseInsensitive(_buffer);
|
||||
_tok1=new View.CaseInsensitive(_buffer);
|
||||
}
|
||||
_buffer=getHeaderBuffer();
|
||||
|
||||
// Is there unconsumed content in body buffer
|
||||
if (_state>STATE_END && _buffer==_header && _header!=null && !_header.hasContent() && _body!=null && _body.hasContent())
|
||||
|
@ -1086,9 +1069,7 @@ public class HttpParser implements Parser
|
|||
// This is probably a pipelined header of the next request, so we need to
|
||||
// copy it to the header buffer.
|
||||
if (_header==null)
|
||||
{
|
||||
_header=_buffers.getHeader();
|
||||
}
|
||||
getHeaderBuffer();
|
||||
else
|
||||
{
|
||||
_header.setMarkIndex(-1);
|
||||
|
@ -1165,6 +1146,8 @@ public class HttpParser implements Parser
|
|||
if (_header == null)
|
||||
{
|
||||
_header=_buffers.getHeader();
|
||||
_tok0.update(_header);
|
||||
_tok1.update(_header);
|
||||
}
|
||||
return _header;
|
||||
}
|
||||
|
|
|
@ -176,9 +176,12 @@ public class SelectChannelEndPoint extends ChannelEndPoint implements AsyncEndPo
|
|||
_writable = true; // Once writable is in ops, only removed with dispatch.
|
||||
}
|
||||
|
||||
// Dispatch if we are not already
|
||||
if (!_dispatched)
|
||||
// If dispatched, then deregister interest
|
||||
if (_dispatched)
|
||||
_key.interestOps(0);
|
||||
else
|
||||
{
|
||||
// other wise do the dispatch
|
||||
dispatch();
|
||||
if (_dispatched && !_selectSet.getManager().isDeferringInterestedOps0())
|
||||
{
|
||||
|
@ -280,7 +283,7 @@ public class SelectChannelEndPoint extends ChannelEndPoint implements AsyncEndPo
|
|||
public void checkIdleTimestamp(long now)
|
||||
{
|
||||
long idleTimestamp=_idleTimestamp;
|
||||
|
||||
|
||||
if (idleTimestamp!=0 && _maxIdleTime>0)
|
||||
{
|
||||
long idleForMs=now-idleTimestamp;
|
||||
|
@ -454,14 +457,7 @@ public class SelectChannelEndPoint extends ChannelEndPoint implements AsyncEndPo
|
|||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
/* short cut for busyselectChannelServerTest */
|
||||
public void clearWritable()
|
||||
{
|
||||
_writable=false;
|
||||
}
|
||||
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
/**
|
||||
* @see org.eclipse.jetty.io.AsyncEndPoint#scheduleWrite()
|
||||
|
@ -637,7 +633,6 @@ public class SelectChannelEndPoint extends ChannelEndPoint implements AsyncEndPo
|
|||
catch (IOException e)
|
||||
{
|
||||
LOG.warn(e.toString());
|
||||
LOG.debug(e);
|
||||
try{close();}
|
||||
catch(IOException e2){LOG.ignore(e2);}
|
||||
}
|
||||
|
|
|
@ -24,6 +24,7 @@ import java.nio.channels.ServerSocketChannel;
|
|||
import java.nio.channels.SocketChannel;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.concurrent.ConcurrentLinkedQueue;
|
||||
import java.util.concurrent.ConcurrentMap;
|
||||
|
@ -303,7 +304,7 @@ public abstract class SelectorManager extends AbstractLifeCycle implements Dumpa
|
|||
}
|
||||
|
||||
});
|
||||
|
||||
|
||||
if (!selecting)
|
||||
throw new IllegalStateException("!Selecting");
|
||||
}
|
||||
|
@ -372,7 +373,7 @@ public abstract class SelectorManager extends AbstractLifeCycle implements Dumpa
|
|||
/* ------------------------------------------------------------ */
|
||||
public void dump(Appendable out, String indent) throws IOException
|
||||
{
|
||||
out.append(String.valueOf(this)).append("\n");
|
||||
AggregateLifeCycle.dumpObject(out,this);
|
||||
AggregateLifeCycle.dump(out,indent,TypeUtil.asList(_selectSet));
|
||||
}
|
||||
|
||||
|
@ -960,7 +961,7 @@ public abstract class SelectorManager extends AbstractLifeCycle implements Dumpa
|
|||
{
|
||||
LOG.ignore(e);
|
||||
}
|
||||
|
||||
|
||||
AggregateLifeCycle.dump(out,indent,dump);
|
||||
}
|
||||
}
|
||||
|
@ -969,8 +970,9 @@ public abstract class SelectorManager extends AbstractLifeCycle implements Dumpa
|
|||
public void dumpKeyState(List<Object> dumpto)
|
||||
{
|
||||
Selector selector=_selector;
|
||||
dumpto.add(selector+" keys="+selector.keys().size());
|
||||
for (SelectionKey key: selector.keys())
|
||||
Set<SelectionKey> keys = selector.keys();
|
||||
dumpto.add(selector + " keys=" + keys.size());
|
||||
for (SelectionKey key: keys)
|
||||
{
|
||||
if (key.isValid())
|
||||
dumpto.add(key.attachment()+" iOps="+key.interestOps()+" rOps="+key.readyOps());
|
||||
|
@ -983,9 +985,8 @@ public abstract class SelectorManager extends AbstractLifeCycle implements Dumpa
|
|||
public String toString()
|
||||
{
|
||||
Selector selector=_selector;
|
||||
return String.format("%s %s keys=%d selected=%d",
|
||||
return String.format("%s keys=%d selected=%d",
|
||||
super.toString(),
|
||||
SelectorManager.this.getState(),
|
||||
selector != null && selector.isOpen() ? selector.keys().size() : -1,
|
||||
selector != null && selector.isOpen() ? selector.selectedKeys().size() : -1);
|
||||
}
|
||||
|
|
|
@ -42,7 +42,7 @@ import org.eclipse.jetty.util.thread.Timeout.Task;
|
|||
*/
|
||||
public class SslConnection extends AbstractConnection implements AsyncConnection
|
||||
{
|
||||
static final Logger LOG=Log.getLogger("org.eclipse.jetty.io.nio.ssl");
|
||||
private final Logger _logger = Log.getLogger("org.eclipse.jetty.io.nio.ssl");
|
||||
|
||||
private static final NIOBuffer __ZERO_BUFFER=new IndirectNIOBuffer(0);
|
||||
|
||||
|
@ -185,22 +185,17 @@ public class SslConnection extends AbstractConnection implements AsyncConnection
|
|||
|
||||
// If we are handshook let the delegate connection
|
||||
if (_engine.getHandshakeStatus()!=HandshakeStatus.NOT_HANDSHAKING)
|
||||
{
|
||||
progress=process(null,null);
|
||||
}
|
||||
else
|
||||
|
||||
// handle the delegate connection
|
||||
AsyncConnection next = (AsyncConnection)_connection.handle();
|
||||
if (next!=_connection && next!=null)
|
||||
{
|
||||
// handle the delegate connection
|
||||
AsyncConnection next = (AsyncConnection)_connection.handle();
|
||||
if (next!=_connection && next!=null)
|
||||
{
|
||||
_connection=next;
|
||||
progress=true;
|
||||
}
|
||||
// TODO: consider moving here hasProgressed() - it's only used in SSL
|
||||
_connection=next;
|
||||
progress=true;
|
||||
}
|
||||
|
||||
LOG.debug("{} handle {} progress={}", _session, this, progress);
|
||||
_logger.debug("{} handle {} progress={}", _session, this, progress);
|
||||
}
|
||||
}
|
||||
finally
|
||||
|
@ -216,9 +211,10 @@ public class SslConnection extends AbstractConnection implements AsyncConnection
|
|||
}
|
||||
catch(Throwable x)
|
||||
{
|
||||
LOG.warn("onInputShutdown failed", x);
|
||||
_logger.warn("onInputShutdown failed", x);
|
||||
try{_sslEndPoint.close();}
|
||||
catch(IOException e2){LOG.ignore(e2);}
|
||||
catch(IOException e2){
|
||||
_logger.ignore(e2);}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -249,7 +245,7 @@ public class SslConnection extends AbstractConnection implements AsyncConnection
|
|||
{
|
||||
try
|
||||
{
|
||||
LOG.debug("onIdleExpired {}ms on {}",idleForMs,this);
|
||||
_logger.debug("onIdleExpired {}ms on {}",idleForMs,this);
|
||||
if (_endp.isOutputShutdown())
|
||||
_sslEndPoint.close();
|
||||
else
|
||||
|
@ -257,7 +253,7 @@ public class SslConnection extends AbstractConnection implements AsyncConnection
|
|||
}
|
||||
catch (IOException e)
|
||||
{
|
||||
LOG.warn(e);
|
||||
_logger.warn(e);
|
||||
super.onIdleExpired(idleForMs);
|
||||
}
|
||||
}
|
||||
|
@ -274,40 +270,55 @@ public class SslConnection extends AbstractConnection implements AsyncConnection
|
|||
boolean some_progress=false;
|
||||
try
|
||||
{
|
||||
// We need buffers to progress
|
||||
allocateBuffers();
|
||||
|
||||
// if we don't have a buffer to put received data into
|
||||
if (toFill==null)
|
||||
{
|
||||
// use the unwrapbuffer to hold received data.
|
||||
_unwrapBuf.compact();
|
||||
toFill=_unwrapBuf;
|
||||
}
|
||||
// Else if the fill buffer is too small for the SSL session
|
||||
else if (toFill.capacity()<_session.getApplicationBufferSize())
|
||||
{
|
||||
// fill to the temporary unwrapBuffer
|
||||
boolean progress=process(null,toFlush);
|
||||
|
||||
// if we received any data,
|
||||
if (_unwrapBuf!=null && _unwrapBuf.hasContent())
|
||||
{
|
||||
// transfer from temp buffer to fill buffer
|
||||
_unwrapBuf.skip(toFill.put(_unwrapBuf));
|
||||
return true;
|
||||
}
|
||||
else
|
||||
// return progress from recursive call
|
||||
return progress;
|
||||
}
|
||||
// Else if there is some temporary data
|
||||
else if (_unwrapBuf!=null && _unwrapBuf.hasContent())
|
||||
{
|
||||
// transfer from temp buffer to fill buffer
|
||||
_unwrapBuf.skip(toFill.put(_unwrapBuf));
|
||||
return true;
|
||||
}
|
||||
|
||||
// If we are here, we have a buffer ready into which we can put some read data.
|
||||
|
||||
// If we have no data to flush, flush the empty buffer
|
||||
if (toFlush==null)
|
||||
toFlush=__ZERO_BUFFER;
|
||||
|
||||
// While we are making progress processing SSL engine
|
||||
boolean progress=true;
|
||||
|
||||
while (progress)
|
||||
{
|
||||
progress=false;
|
||||
int filled=0,flushed=0;
|
||||
|
||||
// Do any real IO
|
||||
int filled=0,flushed=0;
|
||||
try
|
||||
{
|
||||
// Read any available data
|
||||
|
@ -325,7 +336,7 @@ public class SslConnection extends AbstractConnection implements AsyncConnection
|
|||
}
|
||||
finally
|
||||
{
|
||||
LOG.debug("{} {} {} filled={}/{} flushed={}/{}",_session,this,_engine.getHandshakeStatus(),filled,_inbound.length(),flushed,_outbound.length());
|
||||
_logger.debug("{} {} {} filled={}/{} flushed={}/{}",_session,this,_engine.getHandshakeStatus(),filled,_inbound.length(),flushed,_outbound.length());
|
||||
}
|
||||
|
||||
// handle the current hand share status
|
||||
|
@ -356,20 +367,6 @@ public class SslConnection extends AbstractConnection implements AsyncConnection
|
|||
task.run();
|
||||
}
|
||||
|
||||
// Detect SUN JVM Bug!!!
|
||||
/* TODO
|
||||
if(initialStatus==HandshakeStatus.NOT_HANDSHAKING &&
|
||||
_engine.getHandshakeStatus()==HandshakeStatus.NEED_UNWRAP && sent==0 )
|
||||
{
|
||||
// This should be NEED_WRAP
|
||||
// The fix simply detects the signature of the bug and then close the connection (fail-fast) so that ff3 will delegate to using SSL instead of TLS.
|
||||
// This is a jvm bug on java1.6 where the SSLEngine expects more data from the initial handshake when the client(ff3-tls) already had given it.
|
||||
// See http://jira.codehaus.org/browse/JETTY-567 for more details
|
||||
LOG.warn("{} JETTY-567",_session);
|
||||
_endp.close();
|
||||
return false;
|
||||
}
|
||||
*/
|
||||
}
|
||||
break;
|
||||
|
||||
|
@ -388,6 +385,11 @@ public class SslConnection extends AbstractConnection implements AsyncConnection
|
|||
// The SSL needs to receive some handshake data from the other side
|
||||
if (_handshook && !_allowRenegotiate)
|
||||
_endp.close();
|
||||
else if (!_inbound.hasContent()&&filled==-1)
|
||||
{
|
||||
// No more input coming
|
||||
_endp.shutdownInput();
|
||||
}
|
||||
else if (unwrap(toFill))
|
||||
progress=true;
|
||||
}
|
||||
|
@ -401,10 +403,12 @@ public class SslConnection extends AbstractConnection implements AsyncConnection
|
|||
if (_endp.isOpen() && _engine.isOutboundDone() && !_outbound.hasContent())
|
||||
_endp.shutdownOutput();
|
||||
|
||||
// remember if any progress has been made
|
||||
some_progress|=progress;
|
||||
}
|
||||
|
||||
if (toFill.hasContent())
|
||||
// If we are reading into the temp buffer and it has some content, then we should be dispatched.
|
||||
if (toFill==_unwrapBuf && _unwrapBuf.hasContent())
|
||||
_aEndp.asyncDispatch();
|
||||
}
|
||||
finally
|
||||
|
@ -434,8 +438,8 @@ public class SslConnection extends AbstractConnection implements AsyncConnection
|
|||
out_buffer.position(_outbound.putIndex());
|
||||
out_buffer.limit(out_buffer.capacity());
|
||||
result=_engine.wrap(bbuf,out_buffer);
|
||||
if (LOG.isDebugEnabled())
|
||||
LOG.debug("{} wrap {} {} consumed={} produced={}",
|
||||
if (_logger.isDebugEnabled())
|
||||
_logger.debug("{} wrap {} {} consumed={} produced={}",
|
||||
_session,
|
||||
result.getStatus(),
|
||||
result.getHandshakeStatus(),
|
||||
|
@ -448,7 +452,7 @@ public class SslConnection extends AbstractConnection implements AsyncConnection
|
|||
}
|
||||
catch(SSLException e)
|
||||
{
|
||||
LOG.warn(String.valueOf(_endp), e);
|
||||
_logger.debug(String.valueOf(_endp), e);
|
||||
_endp.close();
|
||||
throw e;
|
||||
}
|
||||
|
@ -476,13 +480,13 @@ public class SslConnection extends AbstractConnection implements AsyncConnection
|
|||
break;
|
||||
|
||||
case CLOSED:
|
||||
LOG.debug("wrap CLOSE {} {}",this,result);
|
||||
_logger.debug("wrap CLOSE {} {}",this,result);
|
||||
if (result.getHandshakeStatus()==HandshakeStatus.FINISHED)
|
||||
_endp.close();
|
||||
break;
|
||||
|
||||
default:
|
||||
LOG.warn("{} wrap default {}",_session,result);
|
||||
_logger.debug("{} wrap default {}",_session,result);
|
||||
throw new IOException(result.toString());
|
||||
}
|
||||
|
||||
|
@ -510,8 +514,8 @@ public class SslConnection extends AbstractConnection implements AsyncConnection
|
|||
in_buffer.limit(_inbound.putIndex());
|
||||
|
||||
result=_engine.unwrap(in_buffer,bbuf);
|
||||
if (LOG.isDebugEnabled())
|
||||
LOG.debug("{} unwrap {} {} consumed={} produced={}",
|
||||
if (_logger.isDebugEnabled())
|
||||
_logger.debug("{} unwrap {} {} consumed={} produced={}",
|
||||
_session,
|
||||
result.getStatus(),
|
||||
result.getHandshakeStatus(),
|
||||
|
@ -524,7 +528,7 @@ public class SslConnection extends AbstractConnection implements AsyncConnection
|
|||
}
|
||||
catch(SSLException e)
|
||||
{
|
||||
LOG.warn(String.valueOf(_endp), e);
|
||||
_logger.debug(String.valueOf(_endp), e);
|
||||
_endp.close();
|
||||
throw e;
|
||||
}
|
||||
|
@ -546,7 +550,7 @@ public class SslConnection extends AbstractConnection implements AsyncConnection
|
|||
break;
|
||||
|
||||
case BUFFER_OVERFLOW:
|
||||
LOG.debug("{} unwrap {} {}->{}",_session,result.getStatus(),_inbound.toDetailString(),buffer.toDetailString());
|
||||
_logger.debug("{} unwrap {} {}->{}",_session,result.getStatus(),_inbound.toDetailString(),buffer.toDetailString());
|
||||
break;
|
||||
|
||||
case OK:
|
||||
|
@ -555,13 +559,13 @@ public class SslConnection extends AbstractConnection implements AsyncConnection
|
|||
break;
|
||||
|
||||
case CLOSED:
|
||||
LOG.debug("unwrap CLOSE {} {}",this,result);
|
||||
_logger.debug("unwrap CLOSE {} {}",this,result);
|
||||
if (result.getHandshakeStatus()==HandshakeStatus.FINISHED)
|
||||
_endp.close();
|
||||
break;
|
||||
|
||||
default:
|
||||
LOG.warn("{} wrap default {}",_session,result);
|
||||
_logger.debug("{} wrap default {}",_session,result);
|
||||
throw new IOException(result.toString());
|
||||
}
|
||||
|
||||
|
@ -610,7 +614,7 @@ public class SslConnection extends AbstractConnection implements AsyncConnection
|
|||
{
|
||||
synchronized (SslConnection.this)
|
||||
{
|
||||
LOG.debug("{} ssl endp.oshut {}",_session,this);
|
||||
_logger.debug("{} ssl endp.oshut {}",_session,this);
|
||||
_engine.closeOutbound();
|
||||
_oshut=true;
|
||||
}
|
||||
|
@ -627,7 +631,7 @@ public class SslConnection extends AbstractConnection implements AsyncConnection
|
|||
|
||||
public void shutdownInput() throws IOException
|
||||
{
|
||||
LOG.debug("{} ssl endp.ishut!",_session);
|
||||
_logger.debug("{} ssl endp.ishut!",_session);
|
||||
// We do not do a closeInput here, as SSL does not support half close.
|
||||
// isInputShutdown works it out itself from buffer state and underlying endpoint state.
|
||||
}
|
||||
|
@ -644,7 +648,7 @@ public class SslConnection extends AbstractConnection implements AsyncConnection
|
|||
|
||||
public void close() throws IOException
|
||||
{
|
||||
LOG.debug("{} ssl endp.close",_session);
|
||||
_logger.debug("{} ssl endp.close",_session);
|
||||
_endp.close();
|
||||
}
|
||||
|
||||
|
|
|
@ -5,7 +5,6 @@ import java.io.IOException;
|
|||
import java.net.Socket;
|
||||
import java.nio.ByteBuffer;
|
||||
import java.nio.channels.SocketChannel;
|
||||
|
||||
import javax.net.ssl.SSLEngine;
|
||||
import javax.net.ssl.SSLEngineResult;
|
||||
import javax.net.ssl.SSLEngineResult.HandshakeStatus;
|
||||
|
@ -22,7 +21,7 @@ import org.junit.Test;
|
|||
public class SelectChannelEndPointSslTest extends SelectChannelEndPointTest
|
||||
{
|
||||
static SslContextFactory __sslCtxFactory=new SslContextFactory();
|
||||
|
||||
|
||||
@BeforeClass
|
||||
public static void initSslEngine() throws Exception
|
||||
{
|
||||
|
@ -32,7 +31,7 @@ public class SelectChannelEndPointSslTest extends SelectChannelEndPointTest
|
|||
__sslCtxFactory.setKeyManagerPassword("keypwd");
|
||||
__sslCtxFactory.start();
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
protected Socket newClient() throws IOException
|
||||
{
|
||||
|
@ -60,46 +59,46 @@ public class SelectChannelEndPointSslTest extends SelectChannelEndPointTest
|
|||
super.testEcho();
|
||||
}
|
||||
|
||||
|
||||
|
||||
@Test
|
||||
@Override
|
||||
public void testShutdown() throws Exception
|
||||
{
|
||||
// SSL does not do half closes
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void testTcpClose() throws Exception
|
||||
{
|
||||
|
||||
|
||||
// This test replaces SSLSocket() with a very manual SSL client
|
||||
// so we can close TCP underneath SSL.
|
||||
|
||||
SocketChannel client = SocketChannel.open(_connector.socket().getLocalSocketAddress());
|
||||
client.socket().setSoTimeout(500);
|
||||
|
||||
|
||||
SocketChannel server = _connector.accept();
|
||||
server.configureBlocking(false);
|
||||
_manager.register(server);
|
||||
|
||||
|
||||
SSLEngine engine = __sslCtxFactory.newSslEngine();
|
||||
engine.setUseClientMode(true);
|
||||
engine.beginHandshake();
|
||||
|
||||
|
||||
ByteBuffer appOut = ByteBuffer.allocate(engine.getSession().getApplicationBufferSize());
|
||||
ByteBuffer sslOut = ByteBuffer.allocate(engine.getSession().getPacketBufferSize()*2);
|
||||
ByteBuffer appIn = ByteBuffer.allocate(engine.getSession().getApplicationBufferSize());
|
||||
ByteBuffer sslIn = ByteBuffer.allocate(engine.getSession().getPacketBufferSize()*2);
|
||||
|
||||
boolean debug=SslConnection.LOG.isDebugEnabled();
|
||||
|
||||
|
||||
boolean debug=false;
|
||||
|
||||
if (debug) System.err.println(engine.getHandshakeStatus());
|
||||
int loop=20;
|
||||
while (engine.getHandshakeStatus()!=HandshakeStatus.NOT_HANDSHAKING)
|
||||
{
|
||||
if (--loop==0)
|
||||
throw new IllegalStateException();
|
||||
|
||||
|
||||
if (engine.getHandshakeStatus()==HandshakeStatus.NEED_WRAP)
|
||||
{
|
||||
if (debug) System.err.printf("sslOut %d-%d-%d%n",sslOut.position(),sslOut.limit(),sslOut.capacity());
|
||||
|
@ -133,16 +132,16 @@ public class SelectChannelEndPointSslTest extends SelectChannelEndPointTest
|
|||
}
|
||||
|
||||
if (engine.getHandshakeStatus()==HandshakeStatus.NEED_TASK)
|
||||
{
|
||||
{
|
||||
Runnable task;
|
||||
while ((task=engine.getDelegatedTask())!=null)
|
||||
task.run();
|
||||
if (debug) System.err.println(engine.getHandshakeStatus());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (debug) System.err.println("\nSay Hello");
|
||||
|
||||
|
||||
// write a message
|
||||
appOut.put("HelloWorld".getBytes("UTF-8"));
|
||||
appOut.flip();
|
||||
|
@ -164,11 +163,11 @@ public class SelectChannelEndPointSslTest extends SelectChannelEndPointTest
|
|||
sslIn.compact();
|
||||
else
|
||||
sslIn.clear();
|
||||
|
||||
|
||||
appIn.flip();
|
||||
String reply= new String(appIn.array(),appIn.arrayOffset(),appIn.remaining());
|
||||
appIn.clear();
|
||||
|
||||
|
||||
Assert.assertEquals("HelloWorld",reply);
|
||||
|
||||
SelectorManager.LOG.info("javax.net.ssl.SSLException: Inbound closed... is expected soon");
|
||||
|
|
|
@ -1,6 +1,8 @@
|
|||
package org.eclipse.jetty.io.nio;
|
||||
|
||||
import static org.hamcrest.Matchers.greaterThanOrEqualTo;
|
||||
import static org.hamcrest.Matchers.greaterThan;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertFalse;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
|
@ -196,7 +198,8 @@ public class SelectChannelEndPointTest
|
|||
}
|
||||
catch(SocketTimeoutException e)
|
||||
{
|
||||
assertTrue(System.currentTimeMillis()-start>=400);
|
||||
long duration = System.currentTimeMillis()-start;
|
||||
Assert.assertThat("timeout duration", duration, greaterThanOrEqualTo(400L));
|
||||
}
|
||||
|
||||
// write then shutdown
|
||||
|
@ -206,8 +209,8 @@ public class SelectChannelEndPointTest
|
|||
for (char c : "Goodbye Cruel TLS".toCharArray())
|
||||
{
|
||||
int b = client.getInputStream().read();
|
||||
assertTrue(b>0);
|
||||
assertEquals(c,(char)b);
|
||||
Assert.assertThat("expect valid char integer", b, greaterThan(0));
|
||||
assertEquals("expect characters to be same", c,(char)b);
|
||||
}
|
||||
client.close();
|
||||
|
||||
|
|
|
@ -211,11 +211,20 @@ public class FormAuthModule extends BaseAuthModule
|
|||
// Check if the session is already authenticated.
|
||||
FormCredential form_cred = (FormCredential) session.getAttribute(__J_AUTHENTICATED);
|
||||
if (form_cred != null)
|
||||
{
|
||||
//TODO: we would like the form auth module to be able to invoke the loginservice.validate() method to check the previously authed user
|
||||
|
||||
boolean success = tryLogin(messageInfo, clientSubject, response, session, form_cred._jUserName, new Password(new String(form_cred._jPassword)));
|
||||
if (success) { return AuthStatus.SUCCESS; }
|
||||
{
|
||||
//TODO: ideally we would like the form auth module to be able to invoke the
|
||||
//loginservice.validate() method to check the previously authed user, but it is not visible
|
||||
//to FormAuthModule
|
||||
if (form_cred._subject == null)
|
||||
return AuthStatus.SEND_FAILURE;
|
||||
Set<Object> credentials = form_cred._subject.getPrivateCredentials();
|
||||
if (credentials == null || credentials.isEmpty())
|
||||
return AuthStatus.SEND_FAILURE; //if no private credentials, assume it cannot be authenticated
|
||||
|
||||
clientSubject.getPrivateCredentials().addAll(credentials);
|
||||
|
||||
//boolean success = tryLogin(messageInfo, clientSubject, response, session, form_cred._jUserName, new Password(new String(form_cred._jPassword)));
|
||||
return AuthStatus.SUCCESS;
|
||||
}
|
||||
else if (ssoSource != null)
|
||||
{
|
||||
|
|
|
@ -337,7 +337,7 @@ public class MBeanContainer extends AbstractLifeCycle implements Container.Liste
|
|||
|
||||
public void dump(Appendable out, String indent) throws IOException
|
||||
{
|
||||
out.append(toString()).append("\n");
|
||||
AggregateLifeCycle.dumpObject(out,this);
|
||||
AggregateLifeCycle.dump(out, indent, _beans.entrySet());
|
||||
}
|
||||
|
||||
|
|
|
@ -66,26 +66,26 @@
|
|||
<dependency>
|
||||
<groupId>javax.mail</groupId>
|
||||
<artifactId>mail</artifactId>
|
||||
<exclusions>
|
||||
<exclusion>
|
||||
<groupId>javax.activation</groupId>
|
||||
<artifactId>activation</artifactId>
|
||||
</exclusion>
|
||||
</exclusions>
|
||||
<exclusions>
|
||||
<exclusion>
|
||||
<groupId>javax.activation</groupId>
|
||||
<artifactId>activation</artifactId>
|
||||
</exclusion>
|
||||
</exclusions>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
<profiles>
|
||||
<profile>
|
||||
<id>below-jdk1.6</id>
|
||||
<activation>
|
||||
<jdk>!1.6</jdk>
|
||||
<jdk>(,1.6)</jdk>
|
||||
</activation>
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>javax.activation</groupId>
|
||||
<artifactId>activation</artifactId>
|
||||
<version>${javax-activation-version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>javax.activation</groupId>
|
||||
<artifactId>activation</artifactId>
|
||||
<version>1.1</version>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
</profile>
|
||||
</profiles>
|
||||
|
|
|
@ -14,7 +14,7 @@
|
|||
<jetty-orbit-url>http://download.eclipse.org/jetty/orbit</jetty-orbit-url>
|
||||
<assembly-directory>target/distribution</assembly-directory>
|
||||
<eclipse-ecj-version>3.6</eclipse-ecj-version>
|
||||
<orbit-javax-activation-version>${javax-activation-version}.0.v201105071233</orbit-javax-activation-version>
|
||||
<orbit-javax-activation-version>${javax-activation-version}.0.v201005080500</orbit-javax-activation-version>
|
||||
<orbit-javax-annotation-version>1.1.0.v201105051105</orbit-javax-annotation-version>
|
||||
<orbit-javax-el-version>2.2.0.v201105051105</orbit-javax-el-version>
|
||||
<orbit-javax-mail-glassfish-version>${javax-mail-version}.v201005082020</orbit-javax-mail-glassfish-version>
|
||||
|
|
|
@ -358,7 +358,7 @@ public class ConstraintSecurityHandler extends SecurityHandler implements Constr
|
|||
{
|
||||
if (connector.isIntegral(request))
|
||||
return true;
|
||||
if (connector.getConfidentialPort() > 0)
|
||||
if (connector.getIntegralPort() > 0)
|
||||
{
|
||||
String url = connector.getIntegralScheme() + "://" + request.getServerName() + ":" + connector.getIntegralPort() + request.getRequestURI();
|
||||
if (request.getQueryString() != null)
|
||||
|
@ -440,6 +440,13 @@ public class ConstraintSecurityHandler extends SecurityHandler implements Constr
|
|||
public void dump(Appendable out,String indent) throws IOException
|
||||
{
|
||||
dumpThis(out);
|
||||
dump(out,indent,TypeUtil.asList(getHandlers()),getBeans(),Collections.singleton(_roles),_constraintMap.entrySet());
|
||||
dump(out,indent,
|
||||
Collections.singleton(getLoginService()),
|
||||
Collections.singleton(getIdentityService()),
|
||||
Collections.singleton(getAuthenticator()),
|
||||
Collections.singleton(_roles),
|
||||
_constraintMap.entrySet(),
|
||||
getBeans(),
|
||||
TypeUtil.asList(getHandlers()));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -244,16 +244,19 @@ public abstract class SecurityHandler extends HandlerWrapper implements Authenti
|
|||
return _initParameters.put(key,value);
|
||||
}
|
||||
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
protected LoginService findLoginService()
|
||||
{
|
||||
List<LoginService> list = getServer().getBeans(LoginService.class);
|
||||
|
||||
for (LoginService service : list)
|
||||
if (service.getName()!=null && service.getName().equals(getRealmName()))
|
||||
return service;
|
||||
if (list.size()>0)
|
||||
String realm=getRealmName();
|
||||
if (realm!=null)
|
||||
{
|
||||
for (LoginService service : list)
|
||||
if (service.getName()!=null && service.getName().equals(realm))
|
||||
return service;
|
||||
}
|
||||
else if (list.size()==1)
|
||||
return list.get(0);
|
||||
return null;
|
||||
}
|
||||
|
@ -414,7 +417,7 @@ public abstract class SecurityHandler extends HandlerWrapper implements Authenti
|
|||
|
||||
final Authenticator authenticator = _authenticator;
|
||||
|
||||
if (authenticator!=null && checkSecurity(baseRequest))
|
||||
if (checkSecurity(baseRequest))
|
||||
{
|
||||
Object constraintInfo = prepareConstraintInfo(pathInContext, baseRequest);
|
||||
|
||||
|
@ -433,13 +436,24 @@ public abstract class SecurityHandler extends HandlerWrapper implements Authenti
|
|||
boolean isAuthMandatory =
|
||||
isAuthMandatory(baseRequest, base_response, constraintInfo);
|
||||
|
||||
if (isAuthMandatory && authenticator==null)
|
||||
{
|
||||
LOG.warn("No authenticator for: "+constraintInfo);
|
||||
if (!baseRequest.isHandled())
|
||||
{
|
||||
response.sendError(Response.SC_FORBIDDEN);
|
||||
baseRequest.setHandled(true);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
// check authentication
|
||||
Object previousIdentity = null;
|
||||
try
|
||||
{
|
||||
Authentication authentication = baseRequest.getAuthentication();
|
||||
if (authentication==null || authentication==Authentication.NOT_CHECKED)
|
||||
authentication=authenticator.validateRequest(request, response, isAuthMandatory);
|
||||
authentication=authenticator==null?Authentication.UNAUTHENTICATED:authenticator.validateRequest(request, response, isAuthMandatory);
|
||||
|
||||
if (authentication instanceof Authentication.Wrapped)
|
||||
{
|
||||
|
@ -500,9 +514,11 @@ public abstract class SecurityHandler extends HandlerWrapper implements Authenti
|
|||
else
|
||||
{
|
||||
baseRequest.setAuthentication(authentication);
|
||||
previousIdentity = _identityService.associate(null);
|
||||
if (_identityService!=null)
|
||||
previousIdentity = _identityService.associate(null);
|
||||
handler.handle(pathInContext, baseRequest, request, response);
|
||||
authenticator.secureResponse(request, response, isAuthMandatory, null);
|
||||
if (authenticator!=null)
|
||||
authenticator.secureResponse(request, response, isAuthMandatory, null);
|
||||
}
|
||||
}
|
||||
catch (ServerAuthException e)
|
||||
|
@ -513,7 +529,8 @@ public abstract class SecurityHandler extends HandlerWrapper implements Authenti
|
|||
}
|
||||
finally
|
||||
{
|
||||
_identityService.disassociate(previousIdentity);
|
||||
if (_identityService!=null)
|
||||
_identityService.disassociate(previousIdentity);
|
||||
}
|
||||
}
|
||||
else
|
||||
|
|
|
@ -0,0 +1,469 @@
|
|||
// ========================================================================
|
||||
// Copyright (c) 2004-2009 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.security;
|
||||
|
||||
import static org.junit.Assert.assertThat;
|
||||
import static org.junit.matchers.JUnitMatchers.containsString;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.Arrays;
|
||||
|
||||
import javax.servlet.ServletException;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
|
||||
import org.eclipse.jetty.http.HttpMethods;
|
||||
import org.eclipse.jetty.http.HttpSchemes;
|
||||
import org.eclipse.jetty.io.EndPoint;
|
||||
import org.eclipse.jetty.security.authentication.BasicAuthenticator;
|
||||
import org.eclipse.jetty.server.Connector;
|
||||
import org.eclipse.jetty.server.LocalConnector;
|
||||
import org.eclipse.jetty.server.Request;
|
||||
import org.eclipse.jetty.server.Server;
|
||||
import org.eclipse.jetty.server.UserIdentity;
|
||||
import org.eclipse.jetty.server.handler.AbstractHandler;
|
||||
import org.eclipse.jetty.server.handler.ContextHandler;
|
||||
import org.eclipse.jetty.server.session.SessionHandler;
|
||||
import org.eclipse.jetty.util.security.Constraint;
|
||||
import org.junit.After;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
|
||||
/**
|
||||
* @version $Revision: 1441 $ $Date: 2010-04-02 12:28:17 +0200 (Fri, 02 Apr 2010) $
|
||||
*/
|
||||
public class DataConstraintsTest
|
||||
{
|
||||
private Server _server;
|
||||
private LocalConnector _connector;
|
||||
private LocalConnector _connectorS;
|
||||
private SessionHandler _session;
|
||||
private ConstraintSecurityHandler _security;
|
||||
|
||||
@Before
|
||||
public void startServer()
|
||||
{
|
||||
_server = new Server();
|
||||
_connector = new LocalConnector();
|
||||
_connector.setMaxIdleTime(300000);
|
||||
_connector.setIntegralPort(9998);
|
||||
_connector.setIntegralScheme("FTP");
|
||||
_connector.setConfidentialPort(9999);
|
||||
_connector.setConfidentialScheme("SPDY");
|
||||
_connectorS = new LocalConnector()
|
||||
{
|
||||
@Override
|
||||
public void customize(EndPoint endpoint, Request request) throws IOException
|
||||
{
|
||||
super.customize(endpoint,request);
|
||||
request.setScheme(HttpSchemes.HTTPS);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isIntegral(Request request)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isConfidential(Request request)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
};
|
||||
_server.setConnectors(new Connector[]{_connector,_connectorS});
|
||||
|
||||
ContextHandler _context = new ContextHandler();
|
||||
_session = new SessionHandler();
|
||||
|
||||
_context.setContextPath("/ctx");
|
||||
_server.setHandler(_context);
|
||||
_context.setHandler(_session);
|
||||
|
||||
_security = new ConstraintSecurityHandler();
|
||||
_session.setHandler(_security);
|
||||
|
||||
_security.setHandler(new AbstractHandler()
|
||||
{
|
||||
public void handle(String target, Request baseRequest, HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException
|
||||
{
|
||||
baseRequest.setHandled(true);
|
||||
response.sendError(404);
|
||||
}
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
@After
|
||||
public void stopServer() throws Exception
|
||||
{
|
||||
if (_server.isRunning())
|
||||
{
|
||||
_server.stop();
|
||||
_server.join();
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testIntegral() throws Exception
|
||||
{
|
||||
Constraint constraint0 = new Constraint();
|
||||
constraint0.setAuthenticate(false);
|
||||
constraint0.setName("integral");
|
||||
constraint0.setDataConstraint(Constraint.DC_INTEGRAL);
|
||||
ConstraintMapping mapping0 = new ConstraintMapping();
|
||||
mapping0.setPathSpec("/integral/*");
|
||||
mapping0.setConstraint(constraint0);
|
||||
|
||||
_security.setConstraintMappings(Arrays.asList(new ConstraintMapping[]
|
||||
{
|
||||
mapping0
|
||||
}));
|
||||
|
||||
_server.start();
|
||||
|
||||
String response;
|
||||
response = _connector.getResponses("GET /ctx/some/thing HTTP/1.0\r\n\r\n");
|
||||
assertThat(response, containsString("HTTP/1.1 404 Not Found"));
|
||||
|
||||
response = _connector.getResponses("GET /ctx/integral/info HTTP/1.0\r\n\r\n");
|
||||
assertThat(response, containsString("HTTP/1.1 302 Found"));
|
||||
assertThat(response, containsString("Location: FTP://"));
|
||||
assertThat(response, containsString(":9998"));
|
||||
|
||||
response = _connectorS.getResponses("GET /ctx/integral/info HTTP/1.0\r\n\r\n");
|
||||
assertThat(response, containsString("HTTP/1.1 404 Not Found"));
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testConfidential() throws Exception
|
||||
{
|
||||
Constraint constraint0 = new Constraint();
|
||||
constraint0.setAuthenticate(false);
|
||||
constraint0.setName("confid");
|
||||
constraint0.setDataConstraint(Constraint.DC_CONFIDENTIAL);
|
||||
ConstraintMapping mapping0 = new ConstraintMapping();
|
||||
mapping0.setPathSpec("/confid/*");
|
||||
mapping0.setConstraint(constraint0);
|
||||
|
||||
_security.setConstraintMappings(Arrays.asList(new ConstraintMapping[]
|
||||
{
|
||||
mapping0
|
||||
}));
|
||||
|
||||
_server.start();
|
||||
|
||||
String response;
|
||||
response = _connector.getResponses("GET /ctx/some/thing HTTP/1.0\r\n\r\n");
|
||||
assertThat(response, containsString("HTTP/1.1 404 Not Found"));
|
||||
|
||||
response = _connector.getResponses("GET /ctx/confid/info HTTP/1.0\r\n\r\n");
|
||||
assertThat(response, containsString("HTTP/1.1 302 Found"));
|
||||
assertThat(response, containsString("Location: SPDY://"));
|
||||
assertThat(response, containsString(":9999"));
|
||||
|
||||
response = _connectorS.getResponses("GET /ctx/confid/info HTTP/1.0\r\n\r\n");
|
||||
assertThat(response, containsString("HTTP/1.1 404 Not Found"));
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testConfidentialWithNoRolesSetAndNoMethodRestriction() throws Exception
|
||||
{
|
||||
Constraint constraint0 = new Constraint();
|
||||
constraint0.setName("confid");
|
||||
constraint0.setDataConstraint(Constraint.DC_CONFIDENTIAL);
|
||||
ConstraintMapping mapping0 = new ConstraintMapping();
|
||||
mapping0.setPathSpec("/confid/*");
|
||||
mapping0.setConstraint(constraint0);
|
||||
|
||||
_security.setConstraintMappings(Arrays.asList(new ConstraintMapping[]
|
||||
{
|
||||
mapping0
|
||||
}));
|
||||
|
||||
_server.start();
|
||||
|
||||
String response;
|
||||
|
||||
response = _connector.getResponses("GET /ctx/confid/info HTTP/1.0\r\n\r\n");
|
||||
assertThat(response, containsString("HTTP/1.1 302 Found"));
|
||||
|
||||
response = _connectorS.getResponses("GET /ctx/confid/info HTTP/1.0\r\n\r\n");
|
||||
assertThat(response, containsString("HTTP/1.1 404 Not Found"));
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testConfidentialWithNoRolesSetAndMethodRestriction() throws Exception
|
||||
{
|
||||
Constraint constraint0 = new Constraint();
|
||||
constraint0.setName("confid");
|
||||
constraint0.setDataConstraint(Constraint.DC_CONFIDENTIAL);
|
||||
ConstraintMapping mapping0 = new ConstraintMapping();
|
||||
mapping0.setPathSpec("/confid/*");
|
||||
mapping0.setMethod(HttpMethods.POST);
|
||||
mapping0.setConstraint(constraint0);
|
||||
|
||||
_security.setConstraintMappings(Arrays.asList(new ConstraintMapping[]
|
||||
{
|
||||
mapping0
|
||||
}));
|
||||
|
||||
_server.start();
|
||||
|
||||
String response;
|
||||
|
||||
response = _connector.getResponses("GET /ctx/confid/info HTTP/1.0\r\n\r\n");
|
||||
assertThat(response, containsString("HTTP/1.1 404 Not Found"));
|
||||
|
||||
response = _connectorS.getResponses("GET /ctx/confid/info HTTP/1.0\r\n\r\n");
|
||||
assertThat(response, containsString("HTTP/1.1 404 Not Found"));
|
||||
|
||||
response = _connector.getResponses("POST /ctx/confid/info HTTP/1.0\r\n\r\n");
|
||||
assertThat(response, containsString("HTTP/1.1 302 Found"));
|
||||
|
||||
response = _connectorS.getResponses("POST /ctx/confid/info HTTP/1.0\r\n\r\n");
|
||||
assertThat(response, containsString("HTTP/1.1 404 Not Found"));
|
||||
|
||||
}
|
||||
@Test
|
||||
public void testConfidentialWithRolesSetAndMethodRestriction() throws Exception
|
||||
{
|
||||
Constraint constraint0 = new Constraint();
|
||||
constraint0.setRoles(new String[] { "admin" } );
|
||||
constraint0.setName("confid");
|
||||
constraint0.setDataConstraint(Constraint.DC_CONFIDENTIAL);
|
||||
ConstraintMapping mapping0 = new ConstraintMapping();
|
||||
mapping0.setPathSpec("/confid/*");
|
||||
mapping0.setMethod(HttpMethods.POST);
|
||||
mapping0.setConstraint(constraint0);
|
||||
|
||||
_security.setConstraintMappings(Arrays.asList(new ConstraintMapping[]
|
||||
{
|
||||
mapping0
|
||||
}));
|
||||
|
||||
_server.start();
|
||||
|
||||
String response;
|
||||
|
||||
response = _connector.getResponses("GET /ctx/confid/info HTTP/1.0\r\n\r\n");
|
||||
assertThat(response, containsString("HTTP/1.1 404 Not Found"));
|
||||
|
||||
response = _connectorS.getResponses("GET /ctx/confid/info HTTP/1.0\r\n\r\n");
|
||||
assertThat(response, containsString("HTTP/1.1 404 Not Found"));
|
||||
|
||||
response = _connector.getResponses("POST /ctx/confid/info HTTP/1.0\r\n\r\n");
|
||||
assertThat(response, containsString("HTTP/1.1 302 Found"));
|
||||
|
||||
response = _connectorS.getResponses("POST /ctx/confid/info HTTP/1.0\r\n\r\n");
|
||||
assertThat(response, containsString("HTTP/1.1 404 Not Found"));
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testConfidentialWithRolesSetAndMethodRestrictionAndAuthenticationRequired() throws Exception
|
||||
{
|
||||
Constraint constraint0 = new Constraint();
|
||||
constraint0.setRoles(new String[] { "admin" } );
|
||||
constraint0.setAuthenticate(true);
|
||||
constraint0.setName("confid");
|
||||
constraint0.setDataConstraint(Constraint.DC_CONFIDENTIAL);
|
||||
ConstraintMapping mapping0 = new ConstraintMapping();
|
||||
mapping0.setPathSpec("/confid/*");
|
||||
mapping0.setMethod(HttpMethods.POST);
|
||||
mapping0.setConstraint(constraint0);
|
||||
|
||||
_security.setConstraintMappings(Arrays.asList(new ConstraintMapping[]
|
||||
{
|
||||
mapping0
|
||||
}));
|
||||
DefaultIdentityService identityService = new DefaultIdentityService();
|
||||
_security.setLoginService(new CustomLoginService(identityService));
|
||||
_security.setIdentityService(identityService);
|
||||
_security.setAuthenticator(new BasicAuthenticator());
|
||||
_server.start();
|
||||
|
||||
String response;
|
||||
|
||||
response = _connector.getResponses("GET /ctx/confid/info HTTP/1.0\r\n\r\n");
|
||||
assertThat(response, containsString("HTTP/1.1 404 Not Found"));
|
||||
|
||||
response = _connectorS.getResponses("GET /ctx/confid/info HTTP/1.0\r\n\r\n");
|
||||
assertThat(response, containsString("HTTP/1.1 404 Not Found"));
|
||||
|
||||
response = _connector.getResponses("POST /ctx/confid/info HTTP/1.0\r\n\r\n");
|
||||
assertThat(response, containsString("HTTP/1.1 302 Found"));
|
||||
|
||||
response = _connectorS.getResponses("POST /ctx/confid/info HTTP/1.0\r\n\r\n");
|
||||
assertThat(response, containsString("HTTP/1.1 401 Unauthorized"));
|
||||
|
||||
response = _connector.getResponses("GET /ctx/confid/info HTTP/1.0\r\nAuthorization: Basic YWRtaW46cGFzc3dvcmQ=\r\n\r\n");
|
||||
assertThat(response, containsString("HTTP/1.1 404 Not Found"));
|
||||
|
||||
response = _connector.getResponses("POST /ctx/confid/info HTTP/1.0\r\nAuthorization: Basic YWRtaW46cGFzc3dvcmQ=\r\n\r\n");
|
||||
assertThat(response, containsString("HTTP/1.1 302 Found"));
|
||||
|
||||
response = _connectorS.getResponses("POST /ctx/confid/info HTTP/1.0\r\nAuthorization: Basic YWRtaW46cGFzc3dvcmQ=\r\n\r\n");
|
||||
assertThat(response, containsString("HTTP/1.1 404 Not Found"));
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testRestrictedWithoutAuthenticator() throws Exception
|
||||
{
|
||||
Constraint constraint0 = new Constraint();
|
||||
constraint0.setAuthenticate(true);
|
||||
constraint0.setRoles(new String[] { "admin" } );
|
||||
constraint0.setName("restricted");
|
||||
ConstraintMapping mapping0 = new ConstraintMapping();
|
||||
mapping0.setPathSpec("/restricted/*");
|
||||
mapping0.setConstraint(constraint0);
|
||||
|
||||
_security.setConstraintMappings(Arrays.asList(new ConstraintMapping[]
|
||||
{
|
||||
mapping0
|
||||
}));
|
||||
_server.start();
|
||||
|
||||
String response;
|
||||
|
||||
response = _connector.getResponses("GET /ctx/restricted/info HTTP/1.0\r\n\r\n");
|
||||
assertThat(response, containsString("HTTP/1.1 403 Forbidden"));
|
||||
|
||||
response = _connectorS.getResponses("GET /ctx/restricted/info HTTP/1.0\r\n\r\n");
|
||||
assertThat(response, containsString("HTTP/1.1 403 Forbidden"));
|
||||
|
||||
response = _connector.getResponses("GET /ctx/restricted/info HTTP/1.0\r\n Authorization: Basic YWRtaW46cGFzc3dvcmQ=\r\n\r\n");
|
||||
assertThat(response, containsString("HTTP/1.1 403 Forbidden"));
|
||||
|
||||
response = _connectorS.getResponses("GET /ctx/restricted/info HTTP/1.0\r\n Authorization: Basic YWRtaW46cGFzc3dvcmQ=\r\n\r\n");
|
||||
assertThat(response, containsString("HTTP/1.1 403 Forbidden"));
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testRestrictedWithoutAuthenticatorAndMethod() throws Exception
|
||||
{
|
||||
Constraint constraint0 = new Constraint();
|
||||
constraint0.setAuthenticate(true);
|
||||
constraint0.setRoles(new String[] { "admin" } );
|
||||
constraint0.setName("restricted");
|
||||
ConstraintMapping mapping0 = new ConstraintMapping();
|
||||
mapping0.setPathSpec("/restricted/*");
|
||||
mapping0.setMethod("GET");
|
||||
mapping0.setConstraint(constraint0);
|
||||
|
||||
_security.setConstraintMappings(Arrays.asList(new ConstraintMapping[]
|
||||
{
|
||||
mapping0
|
||||
}));
|
||||
_server.start();
|
||||
|
||||
String response;
|
||||
|
||||
response = _connector.getResponses("GET /ctx/restricted/info HTTP/1.0\r\n\r\n");
|
||||
assertThat(response, containsString("HTTP/1.1 403 Forbidden"));
|
||||
|
||||
response = _connectorS.getResponses("GET /ctx/restricted/info HTTP/1.0\r\n\r\n");
|
||||
assertThat(response, containsString("HTTP/1.1 403 Forbidden"));
|
||||
|
||||
response = _connector.getResponses("GET /ctx/restricted/info HTTP/1.0\r\n Authorization: Basic YWRtaW46cGFzc3dvcmQ=\r\n\r\n");
|
||||
assertThat(response, containsString("HTTP/1.1 403 Forbidden"));
|
||||
|
||||
response = _connectorS.getResponses("GET /ctx/restricted/info HTTP/1.0\r\n Authorization: Basic YWRtaW46cGFzc3dvcmQ=\r\n\r\n");
|
||||
assertThat(response, containsString("HTTP/1.1 403 Forbidden"));
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testRestricted() throws Exception
|
||||
{
|
||||
Constraint constraint0 = new Constraint();
|
||||
constraint0.setAuthenticate(true);
|
||||
constraint0.setRoles(new String[] { "admin" } );
|
||||
constraint0.setName("restricted");
|
||||
ConstraintMapping mapping0 = new ConstraintMapping();
|
||||
mapping0.setPathSpec("/restricted/*");
|
||||
mapping0.setMethod("GET");
|
||||
mapping0.setConstraint(constraint0);
|
||||
|
||||
_security.setConstraintMappings(Arrays.asList(new ConstraintMapping[]
|
||||
{
|
||||
mapping0
|
||||
}));
|
||||
DefaultIdentityService identityService = new DefaultIdentityService();
|
||||
_security.setLoginService(new CustomLoginService(identityService));
|
||||
_security.setIdentityService(identityService);
|
||||
_security.setAuthenticator(new BasicAuthenticator());
|
||||
_server.start();
|
||||
|
||||
String response;
|
||||
|
||||
response = _connector.getResponses("GET /ctx/restricted/info HTTP/1.0\r\n\r\n");
|
||||
assertThat(response, containsString("HTTP/1.1 401 Unauthorized"));
|
||||
|
||||
response = _connectorS.getResponses("GET /ctx/restricted/info HTTP/1.0\r\n\r\n");
|
||||
assertThat(response, containsString("HTTP/1.1 401 Unauthorized"));
|
||||
|
||||
response = _connector.getResponses("GET /ctx/restricted/info HTTP/1.0\nAuthorization: Basic YWRtaW46cGFzc3dvcmQ=\n\n");
|
||||
assertThat(response, containsString("HTTP/1.1 404 Not Found"));
|
||||
|
||||
response = _connectorS.getResponses("GET /ctx/restricted/info HTTP/1.0\nAuthorization: Basic YWRtaW46cGFzc3dvcmQ=\n\n");
|
||||
assertThat(response, containsString("HTTP/1.1 404 Not Found"));
|
||||
|
||||
}
|
||||
|
||||
private class CustomLoginService implements LoginService{
|
||||
private IdentityService identityService;
|
||||
|
||||
public CustomLoginService(IdentityService identityService)
|
||||
{
|
||||
this.identityService = identityService;
|
||||
}
|
||||
public String getName()
|
||||
{
|
||||
return "name";
|
||||
}
|
||||
|
||||
public UserIdentity login(String username, Object credentials)
|
||||
{
|
||||
if("admin".equals(username) && "password".equals(credentials))
|
||||
return new DefaultUserIdentity(null,null,new String[] { "admin" } );
|
||||
return null;
|
||||
}
|
||||
|
||||
public boolean validate(UserIdentity user)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
public IdentityService getIdentityService()
|
||||
{
|
||||
return identityService;
|
||||
}
|
||||
|
||||
public void setIdentityService(IdentityService service)
|
||||
{
|
||||
}
|
||||
|
||||
public void logout(UserIdentity user)
|
||||
{
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
|
@ -889,11 +889,10 @@ public abstract class AbstractConnector extends AggregateLifeCycle implements Ht
|
|||
@Override
|
||||
public String toString()
|
||||
{
|
||||
return String.format("%s@%s:%d %s",
|
||||
return String.format("%s@%s:%d",
|
||||
getClass().getSimpleName(),
|
||||
getHost()==null?"0.0.0.0":getHost(),
|
||||
getLocalPort()<=0?getPort():getLocalPort(),
|
||||
AbstractLifeCycle.getState(this));
|
||||
getLocalPort()<=0?getPort():getLocalPort());
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
|
|
|
@ -103,14 +103,14 @@ public abstract class AbstractHttpConnection extends AbstractConnection
|
|||
protected final Parser _parser;
|
||||
protected final HttpFields _requestFields;
|
||||
protected final Request _request;
|
||||
protected ServletInputStream _in;
|
||||
protected volatile ServletInputStream _in;
|
||||
|
||||
protected final Generator _generator;
|
||||
protected final HttpFields _responseFields;
|
||||
protected final Response _response;
|
||||
protected Output _out;
|
||||
protected OutputWriter _writer;
|
||||
protected PrintWriter _printWriter;
|
||||
protected volatile Output _out;
|
||||
protected volatile OutputWriter _writer;
|
||||
protected volatile PrintWriter _printWriter;
|
||||
|
||||
int _include;
|
||||
|
||||
|
@ -123,7 +123,7 @@ public abstract class AbstractHttpConnection extends AbstractConnection
|
|||
private boolean _expect102Processing = false;
|
||||
private boolean _head = false;
|
||||
private boolean _host = false;
|
||||
private boolean _delayedHandling=false;
|
||||
private boolean _delayedHandling=false;
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
public static AbstractHttpConnection getCurrentConnection()
|
||||
|
|
|
@ -177,6 +177,10 @@ public class AsyncHttpConnection extends AbstractHttpConnection implements Async
|
|||
// then no more can happen, so close.
|
||||
_endp.close();
|
||||
}
|
||||
|
||||
// Make idle parser seek EOF
|
||||
if (_parser.isIdle())
|
||||
_parser.setPersistent(false);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -114,7 +114,7 @@ public class Dispatcher implements RequestDispatcher
|
|||
public void include(ServletRequest request, ServletResponse response) throws ServletException, IOException
|
||||
{
|
||||
Request baseRequest=(request instanceof Request)?((Request)request):AbstractHttpConnection.getCurrentConnection().getRequest();
|
||||
request.removeAttribute(__JSP_FILE); // TODO remove when glassfish 1044 is fixed
|
||||
|
||||
|
||||
if (!(request instanceof HttpServletRequest))
|
||||
request = new ServletRequestHttpWrapper(request);
|
||||
|
@ -198,7 +198,7 @@ public class Dispatcher implements RequestDispatcher
|
|||
Response base_response=baseRequest.getResponse();
|
||||
response.resetBuffer();
|
||||
base_response.fwdReset();
|
||||
request.removeAttribute(__JSP_FILE); // TODO remove when glassfish 1044 is fixed
|
||||
|
||||
|
||||
if (!(request instanceof HttpServletRequest))
|
||||
request = new ServletRequestHttpWrapper(request);
|
||||
|
|
|
@ -135,8 +135,8 @@ public class HttpOutput extends ServletOutputStream
|
|||
|
||||
// Add the _content
|
||||
if (_generator.addContent((byte)b))
|
||||
// Buffers are full so flush.
|
||||
flush();
|
||||
// Buffers are full so commit.
|
||||
_connection.commitResponse(Generator.MORE);
|
||||
|
||||
if (_generator.isAllContentWritten())
|
||||
{
|
||||
|
@ -174,7 +174,7 @@ public class HttpOutput extends ServletOutputStream
|
|||
close();
|
||||
}
|
||||
else if (_generator.isBufferFull())
|
||||
flush();
|
||||
_connection.commitResponse(Generator.MORE);
|
||||
|
||||
// Block until our buffer is free
|
||||
while (buffer.length() > 0 && _generator.isOpen())
|
||||
|
|
|
@ -82,7 +82,7 @@ public class Response implements HttpServletResponse
|
|||
private String _characterEncoding;
|
||||
private boolean _explicitEncoding;
|
||||
private String _contentType;
|
||||
private int _outputState;
|
||||
private volatile int _outputState;
|
||||
private PrintWriter _writer;
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
|
@ -109,8 +109,8 @@ public class Response implements HttpServletResponse
|
|||
_characterEncoding=null;
|
||||
_explicitEncoding=false;
|
||||
_contentType=null;
|
||||
_outputState=NONE;
|
||||
_writer=null;
|
||||
_outputState=NONE;
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
|
@ -656,8 +656,9 @@ public class Response implements HttpServletResponse
|
|||
if (_outputState!=NONE && _outputState!=STREAM)
|
||||
throw new IllegalStateException("WRITER");
|
||||
|
||||
ServletOutputStream out = _connection.getOutputStream();
|
||||
_outputState=STREAM;
|
||||
return _connection.getOutputStream();
|
||||
return out;
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
|
@ -1075,8 +1076,8 @@ public class Response implements HttpServletResponse
|
|||
{
|
||||
resetBuffer();
|
||||
|
||||
_outputState=NONE;
|
||||
_writer=null;
|
||||
_outputState=NONE;
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
|
|
|
@ -94,7 +94,7 @@ public abstract class AbstractHandler extends AggregateLifeCycle implements Hand
|
|||
/* ------------------------------------------------------------ */
|
||||
public void dumpThis(Appendable out) throws IOException
|
||||
{
|
||||
out.append(toString()).append(' ').append(getState()).append('\n');
|
||||
out.append(toString()).append(" - ").append(getState()).append('\n');
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -113,6 +113,6 @@ public abstract class AbstractHandlerContainer extends AbstractHandler implement
|
|||
public void dump(Appendable out,String indent) throws IOException
|
||||
{
|
||||
dumpThis(out);
|
||||
dump(out,indent,TypeUtil.asList(getHandlers()),getBeans());
|
||||
dump(out,indent,getBeans(),TypeUtil.asList(getHandlers()));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -448,8 +448,8 @@ public class HttpConnectionTest
|
|||
PrintWriter writer = response.getWriter();
|
||||
writer.write("<html><h1>FOO</h1></html>");
|
||||
writer.flush();
|
||||
writer.close();
|
||||
throw new RuntimeException("SHOULD NOT GET HERE");
|
||||
if (!writer.checkError())
|
||||
throw new RuntimeException("SHOULD NOT GET HERE");
|
||||
}
|
||||
catch(Exception e)
|
||||
{
|
||||
|
|
|
@ -31,16 +31,21 @@ import javax.servlet.http.HttpServletRequest;
|
|||
import javax.servlet.http.HttpServletResponse;
|
||||
|
||||
import junit.framework.Assert;
|
||||
|
||||
import org.eclipse.jetty.http.HttpParser;
|
||||
import org.eclipse.jetty.io.EndPoint;
|
||||
import org.eclipse.jetty.server.handler.AbstractHandler;
|
||||
import org.eclipse.jetty.util.IO;
|
||||
import org.eclipse.jetty.util.StringUtil;
|
||||
import org.eclipse.jetty.util.log.Log;
|
||||
import org.eclipse.jetty.util.log.StdErrLog;
|
||||
import org.junit.Test;
|
||||
|
||||
import static org.hamcrest.Matchers.greaterThanOrEqualTo;
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertNotSame;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
import static org.junit.Assert.assertThat;
|
||||
|
||||
/**
|
||||
*
|
||||
|
@ -492,7 +497,7 @@ public abstract class HttpServerTestBase extends HttpServerTestFixture
|
|||
}
|
||||
finally
|
||||
{
|
||||
System.err.println("Got "+total+" of "+(512*1024));
|
||||
//System.err.println("Got "+total+" of "+(512*1024));
|
||||
client.close();
|
||||
}
|
||||
}
|
||||
|
@ -739,7 +744,7 @@ public abstract class HttpServerTestBase extends HttpServerTestFixture
|
|||
IO.copy(is,bout);
|
||||
byte[] b=bout.toByteArray();
|
||||
|
||||
System.err.println("OUTPUT: "+new String(b));
|
||||
//System.err.println("OUTPUT: "+new String(b));
|
||||
int i=0;
|
||||
while (b[i]!='Z')
|
||||
i++;
|
||||
|
@ -1205,4 +1210,69 @@ public abstract class HttpServerTestBase extends HttpServerTestFixture
|
|||
|
||||
|
||||
|
||||
@Test
|
||||
public void testUnreadInput () throws Exception
|
||||
{
|
||||
configureServer(new NoopHandler());
|
||||
final int REQS=5;
|
||||
String content="This is a loooooooooooooooooooooooooooooooooo"+
|
||||
"ooooooooooooooooooooooooooooooooooooooooooooo"+
|
||||
"ooooooooooooooooooooooooooooooooooooooooooooo"+
|
||||
"ooooooooooooooooooooooooooooooooooooooooooooo"+
|
||||
"ooooooooooooooooooooooooooooooooooooooooooooo"+
|
||||
"ooooooooooooooooooooooooooooooooooooooooooooo"+
|
||||
"ooooooooooooooooooooooooooooooooooooooooooooo"+
|
||||
"ooooooooooooooooooooooooooooooooooooooooooooo"+
|
||||
"ooooooooooooooooooooooooooooooooooooooooooooo"+
|
||||
"oooooooooooonnnnnnnnnnnnnnnnggggggggg content"+
|
||||
new String(new char[65*1024]);
|
||||
final byte[] bytes = content.getBytes();
|
||||
|
||||
Socket client=newSocket(HOST,_connector.getLocalPort());
|
||||
final OutputStream out=client.getOutputStream();
|
||||
|
||||
new Thread()
|
||||
{
|
||||
public void run()
|
||||
{
|
||||
try
|
||||
{
|
||||
for (int i=0; i<REQS; i++)
|
||||
{
|
||||
out.write("GET / HTTP/1.1\r\nHost: localhost\r\n".getBytes(StringUtil.__ISO_8859_1));
|
||||
out.write(("Content-Length: "+bytes.length+"\r\n" + "\r\n").getBytes(StringUtil.__ISO_8859_1));
|
||||
out.write(bytes,0,bytes.length);
|
||||
}
|
||||
out.write("GET / HTTP/1.1\r\nHost: localhost\r\nConnection: close\r\n\r\n".getBytes(StringUtil.__ISO_8859_1));
|
||||
out.flush();
|
||||
}
|
||||
catch(Exception e)
|
||||
{
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}.start();
|
||||
|
||||
String resps = readResponse(client);
|
||||
|
||||
int offset=0;
|
||||
for (int i=0;i<(REQS+1);i++)
|
||||
{
|
||||
int ok=resps.indexOf("HTTP/1.1 200 OK",offset);
|
||||
assertThat("resp"+i,ok,greaterThanOrEqualTo(offset));
|
||||
offset=ok+15;
|
||||
}
|
||||
}
|
||||
|
||||
public class NoopHandler extends AbstractHandler
|
||||
{
|
||||
public void handle(String target, Request baseRequest,
|
||||
HttpServletRequest request, HttpServletResponse response) throws IOException,
|
||||
ServletException
|
||||
{
|
||||
//don't read the input, just send something back
|
||||
((Request)request).setHandled(true);
|
||||
response.setStatus(200);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,118 +0,0 @@
|
|||
// ========================================================================
|
||||
// Copyright (c) 2008-2009 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;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.OutputStream;
|
||||
import java.net.Socket;
|
||||
|
||||
import javax.servlet.ServletException;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
|
||||
import org.eclipse.jetty.server.bio.SocketConnector;
|
||||
import org.eclipse.jetty.server.handler.AbstractHandler;
|
||||
import org.junit.After;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
|
||||
public class UnreadInputTest
|
||||
{
|
||||
public static final String __OK_RESPONSE = "HTTP/1.1 200 OK\r\nContent-Length: 0\r\nServer: Jetty(7.0.x)\r\n\r\n";
|
||||
protected Server _server = new Server();
|
||||
protected SocketConnector _connector;
|
||||
protected int _port;
|
||||
protected Socket _socket;
|
||||
protected OutputStream _outputStream;
|
||||
protected InputStream _inputStream;
|
||||
|
||||
@Before
|
||||
public void init() throws Exception
|
||||
{
|
||||
//server side
|
||||
_connector = new SocketConnector();
|
||||
_server.setConnectors(new Connector[]{ _connector });
|
||||
_server.setHandler(new NoopHandler());
|
||||
_server.start();
|
||||
_port = _connector.getLocalPort();
|
||||
|
||||
//client side
|
||||
_socket = new Socket((String)null, _port);
|
||||
_outputStream = _socket.getOutputStream();
|
||||
_inputStream = _socket.getInputStream();
|
||||
}
|
||||
|
||||
@After
|
||||
public void destroy() throws Exception
|
||||
{
|
||||
_socket.close();
|
||||
|
||||
_server.stop();
|
||||
_server.join();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testUnreadInput () throws Exception
|
||||
{
|
||||
for (int i=0; i<2; i++)
|
||||
{
|
||||
String content = "This is a loooooooooooooooooooooooooooooooooo"+
|
||||
"ooooooooooooooooooooooooooooooooooooooooooooo"+
|
||||
"ooooooooooooooooooooooooooooooooooooooooooooo"+
|
||||
"ooooooooooooooooooooooooooooooooooooooooooooo"+
|
||||
"ooooooooooooooooooooooooooooooooooooooooooooo"+
|
||||
"ooooooooooooooooooooooooooooooooooooooooooooo"+
|
||||
"ooooooooooooooooooooooooooooooooooooooooooooo"+
|
||||
"ooooooooooooooooooooooooooooooooooooooooooooo"+
|
||||
"ooooooooooooooooooooooooooooooooooooooooooooo"+
|
||||
"ooooooooooooooooooooooonnnnnnnnnnnnnnnnggggggggg content";
|
||||
byte[] bytes = content.getBytes();
|
||||
|
||||
_outputStream.write("GET / HTTP/1.1\r\nHost: localhost\r\n".getBytes());
|
||||
Thread.currentThread();
|
||||
Thread.sleep(500L);
|
||||
|
||||
String str = "Content-Length: "+bytes.length+"\r\n" + "\r\n";
|
||||
_outputStream.write(str.getBytes());
|
||||
Thread.currentThread();
|
||||
Thread.sleep(500L);
|
||||
|
||||
//write some bytes of the content
|
||||
_outputStream.write(bytes, 0, (bytes.length/2));
|
||||
Thread.currentThread();
|
||||
Thread.sleep(1000L);
|
||||
|
||||
//write the rest
|
||||
_outputStream.write(bytes, bytes.length/2, (bytes.length - bytes.length/2));
|
||||
}
|
||||
|
||||
|
||||
byte[] inbuf = new byte[__OK_RESPONSE.getBytes().length*2];
|
||||
int x = _inputStream.read(inbuf);
|
||||
System.err.println(new String(inbuf, 0, x));
|
||||
}
|
||||
|
||||
public class NoopHandler extends AbstractHandler
|
||||
{
|
||||
public void handle(String target, Request baseRequest,
|
||||
HttpServletRequest request, HttpServletResponse response) throws IOException,
|
||||
ServletException
|
||||
{
|
||||
//don't read the input, just send something back
|
||||
((Request)request).setHandled(true);
|
||||
response.setStatus(200);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -268,7 +268,8 @@ public class Holder<T> extends AbstractLifeCycle implements Dumpable
|
|||
/* ------------------------------------------------------------ */
|
||||
public void dump(Appendable out, String indent) throws IOException
|
||||
{
|
||||
out.append(_name).append("==").append(_className).append("\n");
|
||||
out.append(_name).append("==").append(_className)
|
||||
.append(" - ").append(AbstractLifeCycle.getState(this)).append("\n");
|
||||
AggregateLifeCycle.dump(out,indent,_initParams.entrySet());
|
||||
}
|
||||
|
||||
|
|
|
@ -739,8 +739,14 @@ public class ProxyServlet implements Servlet
|
|||
*/
|
||||
protected void handleOnException(Throwable ex, HttpServletRequest request, HttpServletResponse response)
|
||||
{
|
||||
_log.warn(ex.toString());
|
||||
_log.debug(ex);
|
||||
if (ex instanceof IOException)
|
||||
{
|
||||
_log.warn(ex.toString());
|
||||
_log.debug(ex);
|
||||
}
|
||||
else
|
||||
_log.warn(ex);
|
||||
|
||||
if (!response.isCommitted())
|
||||
{
|
||||
response.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
|
||||
|
|
|
@ -0,0 +1,146 @@
|
|||
package org.eclipse.jetty.servlets;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.net.MalformedURLException;
|
||||
import java.util.Arrays;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import javax.servlet.ServletException;
|
||||
import javax.servlet.ServletOutputStream;
|
||||
import javax.servlet.http.HttpServlet;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
|
||||
import junit.framework.Assert;
|
||||
import org.eclipse.jetty.client.ContentExchange;
|
||||
import org.eclipse.jetty.client.HttpClient;
|
||||
import org.eclipse.jetty.client.HttpExchange;
|
||||
import org.eclipse.jetty.http.HttpStatus;
|
||||
import org.eclipse.jetty.http.HttpURI;
|
||||
import org.eclipse.jetty.io.Buffer;
|
||||
import org.eclipse.jetty.server.Connector;
|
||||
import org.eclipse.jetty.server.Server;
|
||||
import org.eclipse.jetty.server.handler.HandlerCollection;
|
||||
import org.eclipse.jetty.server.nio.SelectChannelConnector;
|
||||
import org.eclipse.jetty.servlet.ServletContextHandler;
|
||||
import org.eclipse.jetty.servlet.ServletHolder;
|
||||
import org.eclipse.jetty.toolchain.test.MavenTestingUtils;
|
||||
import org.junit.After;
|
||||
import org.junit.Test;
|
||||
|
||||
public class ProxyServletTest
|
||||
{
|
||||
private Server server;
|
||||
private Connector connector;
|
||||
private HttpClient client;
|
||||
|
||||
public void init(HttpServlet servlet) throws Exception
|
||||
{
|
||||
server = new Server();
|
||||
|
||||
connector = new SelectChannelConnector();
|
||||
server.addConnector(connector);
|
||||
|
||||
HandlerCollection handlers = new HandlerCollection();
|
||||
server.setHandler(handlers);
|
||||
|
||||
ServletContextHandler proxyCtx = new ServletContextHandler(handlers, "/proxy", ServletContextHandler.NO_SESSIONS);
|
||||
ServletHolder proxyServletHolder = new ServletHolder(new ProxyServlet()
|
||||
{
|
||||
@Override
|
||||
protected HttpURI proxyHttpURI(String scheme, String serverName, int serverPort, String uri) throws MalformedURLException
|
||||
{
|
||||
// Proxies any call to "/proxy" to "/"
|
||||
return new HttpURI(scheme + "://" + serverName + ":" + serverPort + uri.substring("/proxy".length()));
|
||||
}
|
||||
});
|
||||
proxyServletHolder.setInitParameter("timeout", String.valueOf(5 * 60 * 1000L));
|
||||
proxyCtx.addServlet(proxyServletHolder, "/*");
|
||||
|
||||
ServletContextHandler appCtx = new ServletContextHandler(handlers, "/", ServletContextHandler.SESSIONS);
|
||||
ServletHolder appServletHolder = new ServletHolder(servlet);
|
||||
appCtx.addServlet(appServletHolder, "/*");
|
||||
|
||||
handlers.addHandler(proxyCtx);
|
||||
handlers.addHandler(appCtx);
|
||||
|
||||
server.start();
|
||||
|
||||
client = new HttpClient();
|
||||
client.start();
|
||||
}
|
||||
|
||||
@After
|
||||
public void destroy() throws Exception
|
||||
{
|
||||
if (client != null)
|
||||
client.stop();
|
||||
|
||||
if (server != null)
|
||||
{
|
||||
server.stop();
|
||||
server.join();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void testBigDownloadWithSlowReader() throws Exception
|
||||
{
|
||||
// Create a 6 MiB file
|
||||
final File file = File.createTempFile("test_", null, MavenTestingUtils.getTargetTestingDir());
|
||||
file.deleteOnExit();
|
||||
FileOutputStream fos = new FileOutputStream(file);
|
||||
byte[] buffer = new byte[1024];
|
||||
Arrays.fill(buffer, (byte)'X');
|
||||
for (int i = 0; i < 6 * 1024; ++i)
|
||||
fos.write(buffer);
|
||||
fos.close();
|
||||
|
||||
init(new HttpServlet()
|
||||
{
|
||||
@Override
|
||||
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException
|
||||
{
|
||||
FileInputStream fis = new FileInputStream(file);
|
||||
ServletOutputStream output = response.getOutputStream();
|
||||
byte[] buffer = new byte[1024];
|
||||
int read;
|
||||
while ((read = fis.read(buffer)) >= 0)
|
||||
output.write(buffer, 0, read);
|
||||
fis.close();
|
||||
}
|
||||
});
|
||||
|
||||
String url = "http://localhost:" + connector.getLocalPort() + "/proxy" + "/test";
|
||||
ContentExchange exchange = new ContentExchange(true)
|
||||
{
|
||||
@Override
|
||||
protected void onResponseContent(Buffer content) throws IOException
|
||||
{
|
||||
try
|
||||
{
|
||||
// Slow down the reader
|
||||
TimeUnit.MILLISECONDS.sleep(10);
|
||||
super.onResponseContent(content);
|
||||
}
|
||||
catch (InterruptedException x)
|
||||
{
|
||||
throw (IOException)new IOException().initCause(x);
|
||||
}
|
||||
}
|
||||
};
|
||||
exchange.setURL(url);
|
||||
long start = System.nanoTime();
|
||||
client.send(exchange);
|
||||
Assert.assertEquals(HttpExchange.STATUS_COMPLETED, exchange.waitForDone());
|
||||
long elapsed = System.nanoTime() - start;
|
||||
Assert.assertEquals(HttpStatus.OK_200, exchange.getResponseStatus());
|
||||
Assert.assertEquals(file.length(), exchange.getResponseContentBytes().length);
|
||||
long millis = TimeUnit.NANOSECONDS.toMillis(elapsed);
|
||||
long rate = file.length() / 1024 * 1000 / millis;
|
||||
System.out.printf("download rate = %d KiB/s%n", rate);
|
||||
}
|
||||
}
|
|
@ -209,9 +209,4 @@ public abstract class AbstractLifeCycle implements LifeCycle
|
|||
public void lifeCycleStopped(LifeCycle event) {}
|
||||
public void lifeCycleStopping(LifeCycle event) {}
|
||||
}
|
||||
|
||||
public String toString()
|
||||
{
|
||||
return super.toString()+"#"+getState();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -339,7 +339,16 @@ public class AggregateLifeCycle extends AbstractLifeCycle implements Destroyable
|
|||
/* ------------------------------------------------------------ */
|
||||
protected void dumpThis(Appendable out) throws IOException
|
||||
{
|
||||
out.append(String.valueOf(this)).append("\n");
|
||||
out.append(String.valueOf(this)).append(" - ").append(getState()).append("\n");
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
public static void dumpObject(Appendable out,Object o) throws IOException
|
||||
{
|
||||
if (o instanceof LifeCycle)
|
||||
out.append(String.valueOf(o)).append(" - ").append((AbstractLifeCycle.getState((LifeCycle)o))).append("\n");
|
||||
else
|
||||
out.append(String.valueOf(o)).append("\n");
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
|
@ -359,15 +368,11 @@ public class AggregateLifeCycle extends AbstractLifeCycle implements Destroyable
|
|||
out.append(indent).append(" +- ");
|
||||
if (b._bean instanceof Dumpable)
|
||||
((Dumpable)b._bean).dump(out,indent+(i==size?" ":" | "));
|
||||
else
|
||||
out.append(String.valueOf(b._bean)).append("\n");
|
||||
else
|
||||
dumpObject(out,b._bean);
|
||||
}
|
||||
else
|
||||
{
|
||||
out.append(indent).append(" +~ ");
|
||||
out.append(String.valueOf(b._bean)).append("\n");
|
||||
}
|
||||
|
||||
else
|
||||
dumpObject(out,b._bean);
|
||||
}
|
||||
|
||||
if (i!=size)
|
||||
|
@ -395,16 +400,12 @@ public class AggregateLifeCycle extends AbstractLifeCycle implements Destroyable
|
|||
|
||||
if (o instanceof Dumpable)
|
||||
((Dumpable)o).dump(out,indent+(i==size?" ":" | "));
|
||||
else
|
||||
out.append(String.valueOf(o)).append("\n");
|
||||
else
|
||||
dumpObject(out,o);
|
||||
}
|
||||
|
||||
if (i!=size)
|
||||
out.append(indent).append(" |\n");
|
||||
|
||||
out.append(indent).append(" |\n");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
|
|
@ -4,11 +4,11 @@
|
|||
// 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
|
||||
// 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.
|
||||
// You may elect to redistribute this code under either of these licenses.
|
||||
// ========================================================================
|
||||
package org.eclipse.jetty.util.log;
|
||||
|
||||
|
@ -19,20 +19,20 @@ import org.slf4j.helpers.MessageFormatter;
|
|||
/**
|
||||
* JettyAwareLogger is used to fix a FQCN bug that arises from how Jetty
|
||||
* Log uses an indirect slf4j implementation.
|
||||
*
|
||||
*
|
||||
* https://bugs.eclipse.org/bugs/show_bug.cgi?id=276670
|
||||
*/
|
||||
class JettyAwareLogger implements org.slf4j.Logger
|
||||
class JettyAwareLogger implements org.slf4j.Logger
|
||||
{
|
||||
private static final int DEBUG = org.slf4j.spi.LocationAwareLogger.DEBUG_INT;
|
||||
private static final int ERROR = org.slf4j.spi.LocationAwareLogger.ERROR_INT;
|
||||
private static final int INFO = org.slf4j.spi.LocationAwareLogger.INFO_INT;
|
||||
private static final int TRACE = org.slf4j.spi.LocationAwareLogger.TRACE_INT;
|
||||
private static final int WARN = org.slf4j.spi.LocationAwareLogger.WARN_INT;
|
||||
|
||||
|
||||
private static final String FQCN = Slf4jLog.class.getName();
|
||||
private final org.slf4j.spi.LocationAwareLogger _logger;
|
||||
|
||||
|
||||
public JettyAwareLogger(org.slf4j.spi.LocationAwareLogger logger)
|
||||
{
|
||||
_logger = logger;
|
||||
|
@ -586,26 +586,33 @@ class JettyAwareLogger implements org.slf4j.Logger
|
|||
{
|
||||
log(marker, ERROR, msg, null, t);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public String toString()
|
||||
{
|
||||
return _logger.toString();
|
||||
}
|
||||
|
||||
|
||||
private void log(Marker marker, int level, String msg, Object[] argArray, Throwable t)
|
||||
{
|
||||
if (argArray == null)
|
||||
{
|
||||
// Simple SLF4J Message (no args)
|
||||
_logger.log(marker,FQCN,level,msg,null,t);
|
||||
_logger.log(marker, FQCN, level, msg, null, t);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Don't assume downstream handles argArray properly.
|
||||
// Do it the SLF4J way here to eliminate that as a bug.
|
||||
FormattingTuple ft = MessageFormatter.arrayFormat(msg,argArray);
|
||||
_logger.log(marker,FQCN,level,ft.getMessage(),null,t);
|
||||
int loggerLevel = _logger.isTraceEnabled() ? TRACE :
|
||||
_logger.isDebugEnabled() ? DEBUG :
|
||||
_logger.isInfoEnabled() ? INFO :
|
||||
_logger.isWarnEnabled() ? WARN : ERROR;
|
||||
if (loggerLevel <= level)
|
||||
{
|
||||
// Don't assume downstream handles argArray properly.
|
||||
// Do it the SLF4J way here to eliminate that as a bug.
|
||||
FormattingTuple ft = MessageFormatter.arrayFormat(msg, argArray);
|
||||
_logger.log(marker, FQCN, level, ft.getMessage(), null, t);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -16,8 +16,6 @@ package org.eclipse.jetty.util.log;
|
|||
import java.io.PrintStream;
|
||||
import java.security.AccessControlException;
|
||||
import java.util.Properties;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.concurrent.ConcurrentMap;
|
||||
|
||||
import org.eclipse.jetty.util.DateCache;
|
||||
|
||||
|
|
|
@ -1524,11 +1524,10 @@ public class SslContextFactory extends AbstractLifeCycle
|
|||
/* ------------------------------------------------------------ */
|
||||
public String toString()
|
||||
{
|
||||
return String.format("%s@%x(%s,%s)#%s",
|
||||
return String.format("%s@%x(%s,%s)",
|
||||
getClass().getSimpleName(),
|
||||
hashCode(),
|
||||
_keyStorePath,
|
||||
_trustStorePath,
|
||||
getState());
|
||||
_trustStorePath);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -498,7 +498,7 @@ public class QueuedThreadPool extends AbstractLifeCycle implements SizedThreadPo
|
|||
}
|
||||
}
|
||||
|
||||
out.append(String.valueOf(this)).append("\n");
|
||||
AggregateLifeCycle.dumpObject(out,this);
|
||||
AggregateLifeCycle.dump(out,indent,dump);
|
||||
|
||||
}
|
||||
|
@ -508,7 +508,7 @@ public class QueuedThreadPool extends AbstractLifeCycle implements SizedThreadPo
|
|||
@Override
|
||||
public String toString()
|
||||
{
|
||||
return _name+"{"+getMinThreads()+"<="+getIdleThreads()+"<="+getThreads()+"/"+getMaxThreads()+","+(_jobs==null?-1:_jobs.size())+"}#"+getState();
|
||||
return _name+"{"+getMinThreads()+"<="+getIdleThreads()+"<="+getThreads()+"/"+getMaxThreads()+","+(_jobs==null?-1:_jobs.size())+"}";
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
|
|
|
@ -354,7 +354,7 @@ public class WebSocketClientFactory extends AggregateLifeCycle
|
|||
private final HttpParser _parser;
|
||||
private String _accept;
|
||||
private String _error;
|
||||
private boolean _handshaken;
|
||||
private ByteArrayBuffer _handshake;
|
||||
|
||||
public HandshakeConnection(AsyncEndPoint endpoint, WebSocketClient.WebSocketFuture future)
|
||||
{
|
||||
|
@ -404,72 +404,75 @@ public class WebSocketClientFactory extends AggregateLifeCycle
|
|||
});
|
||||
}
|
||||
|
||||
private void handshake()
|
||||
private boolean handshake()
|
||||
{
|
||||
String path = _future.getURI().getPath();
|
||||
if (path == null || path.length() == 0)
|
||||
path = "/";
|
||||
|
||||
if (_future.getURI().getRawQuery() != null)
|
||||
path += "?" + _future.getURI().getRawQuery();
|
||||
|
||||
String origin = _future.getOrigin();
|
||||
|
||||
StringBuilder request = new StringBuilder(512);
|
||||
request.append("GET ").append(path).append(" HTTP/1.1\r\n")
|
||||
.append("Host: ").append(_future.getURI().getHost()).append(":")
|
||||
.append(_future.getURI().getPort()).append("\r\n")
|
||||
.append("Upgrade: websocket\r\n")
|
||||
.append("Connection: Upgrade\r\n")
|
||||
.append("Sec-WebSocket-Key: ")
|
||||
.append(_key).append("\r\n");
|
||||
|
||||
if (origin != null)
|
||||
request.append("Origin: ").append(origin).append("\r\n");
|
||||
|
||||
request.append("Sec-WebSocket-Version: ").append(WebSocketConnectionRFC6455.VERSION).append("\r\n");
|
||||
|
||||
if (_future.getProtocol() != null)
|
||||
request.append("Sec-WebSocket-Protocol: ").append(_future.getProtocol()).append("\r\n");
|
||||
|
||||
Map<String, String> cookies = _future.getCookies();
|
||||
if (cookies != null && cookies.size() > 0)
|
||||
if (_handshake==null)
|
||||
{
|
||||
for (String cookie : cookies.keySet())
|
||||
request.append("Cookie: ")
|
||||
.append(QuotedStringTokenizer.quoteIfNeeded(cookie, HttpFields.__COOKIE_DELIM))
|
||||
.append("=")
|
||||
.append(QuotedStringTokenizer.quoteIfNeeded(cookies.get(cookie), HttpFields.__COOKIE_DELIM))
|
||||
.append("\r\n");
|
||||
String path = _future.getURI().getPath();
|
||||
if (path == null || path.length() == 0)
|
||||
path = "/";
|
||||
|
||||
if (_future.getURI().getRawQuery() != null)
|
||||
path += "?" + _future.getURI().getRawQuery();
|
||||
|
||||
String origin = _future.getOrigin();
|
||||
|
||||
StringBuilder request = new StringBuilder(512);
|
||||
request.append("GET ").append(path).append(" HTTP/1.1\r\n")
|
||||
.append("Host: ").append(_future.getURI().getHost()).append(":")
|
||||
.append(_future.getURI().getPort()).append("\r\n")
|
||||
.append("Upgrade: websocket\r\n")
|
||||
.append("Connection: Upgrade\r\n")
|
||||
.append("Sec-WebSocket-Key: ")
|
||||
.append(_key).append("\r\n");
|
||||
|
||||
if (origin != null)
|
||||
request.append("Origin: ").append(origin).append("\r\n");
|
||||
|
||||
request.append("Sec-WebSocket-Version: ").append(WebSocketConnectionRFC6455.VERSION).append("\r\n");
|
||||
|
||||
if (_future.getProtocol() != null)
|
||||
request.append("Sec-WebSocket-Protocol: ").append(_future.getProtocol()).append("\r\n");
|
||||
|
||||
Map<String, String> cookies = _future.getCookies();
|
||||
if (cookies != null && cookies.size() > 0)
|
||||
{
|
||||
for (String cookie : cookies.keySet())
|
||||
request.append("Cookie: ")
|
||||
.append(QuotedStringTokenizer.quoteIfNeeded(cookie, HttpFields.__COOKIE_DELIM))
|
||||
.append("=")
|
||||
.append(QuotedStringTokenizer.quoteIfNeeded(cookies.get(cookie), HttpFields.__COOKIE_DELIM))
|
||||
.append("\r\n");
|
||||
}
|
||||
|
||||
request.append("\r\n");
|
||||
|
||||
_handshake=new ByteArrayBuffer(request.toString(), false);
|
||||
}
|
||||
|
||||
request.append("\r\n");
|
||||
|
||||
|
||||
// TODO extensions
|
||||
|
||||
try
|
||||
{
|
||||
Buffer handshake = new ByteArrayBuffer(request.toString(), false);
|
||||
int len = handshake.length();
|
||||
if (len != _endp.flush(handshake))
|
||||
throw new IOException("incomplete");
|
||||
int len = _handshake.length();
|
||||
int flushed = _endp.flush(_handshake);
|
||||
if (flushed<0)
|
||||
throw new IOException("incomplete handshake");
|
||||
}
|
||||
catch (IOException e)
|
||||
{
|
||||
_future.handshakeFailed(e);
|
||||
}
|
||||
finally
|
||||
{
|
||||
_handshaken = true;
|
||||
}
|
||||
return _handshake.length()==0;
|
||||
}
|
||||
|
||||
public Connection handle() throws IOException
|
||||
{
|
||||
while (_endp.isOpen() && !_parser.isComplete())
|
||||
{
|
||||
if (!_handshaken)
|
||||
handshake();
|
||||
if (_handshake==null || _handshake.length()>0)
|
||||
if (!handshake())
|
||||
return this;
|
||||
|
||||
if (!_parser.parseAvailable())
|
||||
{
|
||||
|
|
|
@ -15,6 +15,9 @@
|
|||
*******************************************************************************/
|
||||
package org.eclipse.jetty.websocket;
|
||||
|
||||
import static org.hamcrest.Matchers.*;
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
import java.io.EOFException;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
|
@ -28,9 +31,9 @@ import java.util.concurrent.atomic.AtomicLong;
|
|||
import java.util.concurrent.atomic.AtomicReference;
|
||||
import java.util.zip.Deflater;
|
||||
import java.util.zip.Inflater;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
|
||||
import junit.framework.Assert;
|
||||
import org.eclipse.jetty.io.Buffer;
|
||||
import org.eclipse.jetty.io.ByteArrayEndPoint;
|
||||
import org.eclipse.jetty.server.Connector;
|
||||
|
@ -41,13 +44,10 @@ import org.eclipse.jetty.util.StringUtil;
|
|||
import org.eclipse.jetty.util.TypeUtil;
|
||||
import org.eclipse.jetty.util.Utf8StringBuilder;
|
||||
import org.junit.AfterClass;
|
||||
import org.junit.Assert;
|
||||
import org.junit.BeforeClass;
|
||||
import org.junit.Test;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertNotNull;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
|
||||
public class WebSocketMessageRFC6455Test
|
||||
{
|
||||
private static Server __server;
|
||||
|
@ -606,7 +606,7 @@ public class WebSocketMessageRFC6455Test
|
|||
Thread.sleep(100);
|
||||
|
||||
assertEquals(count*(mesg.length()+2),totalB.get()); // all messages
|
||||
assertTrue(max>1000); // was blocked
|
||||
Assert.assertThat("Was blocked (max time)", max, greaterThan(1000L)); // was blocked
|
||||
}
|
||||
|
||||
@Test
|
||||
|
|
|
@ -111,21 +111,22 @@ public class XmlConfiguration
|
|||
try
|
||||
{
|
||||
URL config60 = Loader.getResource(XmlConfiguration.class,"org/eclipse/jetty/xml/configure_6_0.dtd",true);
|
||||
URL config71 = Loader.getResource(XmlConfiguration.class,"org/eclipse/jetty/xml/configure_7_1.dtd",true);
|
||||
__parser.redirectEntity("configure.dtd",config71);
|
||||
URL config76 = Loader.getResource(XmlConfiguration.class,"org/eclipse/jetty/xml/configure_7_6.dtd",true);
|
||||
__parser.redirectEntity("configure.dtd",config76);
|
||||
__parser.redirectEntity("configure_1_0.dtd",config60);
|
||||
__parser.redirectEntity("configure_1_1.dtd",config60);
|
||||
__parser.redirectEntity("configure_1_2.dtd",config60);
|
||||
__parser.redirectEntity("configure_1_3.dtd",config60);
|
||||
__parser.redirectEntity("configure_6_0.dtd",config60);
|
||||
__parser.redirectEntity("configure_7_1.dtd",config71);
|
||||
__parser.redirectEntity("configure_7_6.dtd",config76);
|
||||
|
||||
__parser.redirectEntity("http://jetty.mortbay.org/configure.dtd",config71);
|
||||
__parser.redirectEntity("http://jetty.eclipse.org/configure.dtd",config71);
|
||||
__parser.redirectEntity("http://www.eclipse.org/jetty/configure.dtd",config71);
|
||||
|
||||
__parser.redirectEntity("http://jetty.mortbay.org/configure.dtd",config76);
|
||||
__parser.redirectEntity("http://jetty.eclipse.org/configure.dtd",config76);
|
||||
__parser.redirectEntity("http://www.eclipse.org/jetty/configure.dtd",config76);
|
||||
|
||||
__parser.redirectEntity("-//Mort Bay Consulting//DTD Configure//EN",config71);
|
||||
__parser.redirectEntity("-//Jetty//Configure//EN",config71);
|
||||
__parser.redirectEntity("-//Mort Bay Consulting//DTD Configure//EN",config76);
|
||||
__parser.redirectEntity("-//Jetty//Configure//EN",config76);
|
||||
}
|
||||
catch (ClassNotFoundException e)
|
||||
{
|
||||
|
|
|
@ -25,6 +25,14 @@ import org.junit.Test;
|
|||
public class XmlConfigurationTest
|
||||
{
|
||||
protected String _configure="org/eclipse/jetty/xml/configure.xml";
|
||||
|
||||
@Test
|
||||
public void testMortBay() throws Exception
|
||||
{
|
||||
URL url = XmlConfigurationTest.class.getClassLoader().getResource("org/eclipse/jetty/xml/mortbay.xml");
|
||||
XmlConfiguration configuration = new XmlConfiguration(url);
|
||||
Object o=configuration.configure();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testPassedObject() throws Exception
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
<?xml version="1.0" encoding="ISO-8859-1"?>
|
||||
<!DOCTYPE Configure PUBLIC "-//Mort Bay Consulting//DTD Configure 1.2//EN" "http://www.eclipse.org/jetty/configure_1_2.dtd">
|
||||
<!DOCTYPE Configure PUBLIC "-//Mort Bay Consulting//DTD Configure//EN" "http://www.eclipse.org/jetty/configure.dtd">
|
||||
|
||||
<Configure class="org.eclipse.jetty.xml.TestConfiguration">
|
||||
|
||||
|
|
|
@ -0,0 +1,4 @@
|
|||
<?xml version="1.0" encoding="ISO-8859-1"?>
|
||||
<!DOCTYPE Configure PUBLIC "-//Mort Bay Consulting//DTD Configure//EN" "http://jetty.mortbay.org/configure.dtd">
|
||||
<Configure class="java.lang.Object">
|
||||
</Configure>
|
|
@ -16,8 +16,8 @@
|
|||
|
||||
package org.eclipse.jetty.test.rfcs;
|
||||
|
||||
import static org.junit.Assert.assertThat;
|
||||
import static org.junit.matchers.JUnitMatchers.containsString;
|
||||
import static org.junit.Assert.*;
|
||||
import static org.junit.matchers.JUnitMatchers.*;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
|
@ -42,6 +42,7 @@ import org.eclipse.jetty.toolchain.test.StringAssert;
|
|||
import org.junit.AfterClass;
|
||||
import org.junit.Assert;
|
||||
import org.junit.Before;
|
||||
import org.junit.Ignore;
|
||||
import org.junit.Test;
|
||||
|
||||
/**
|
||||
|
@ -955,6 +956,7 @@ public abstract class RFC2616BaseTest
|
|||
* @see <a href="http://tools.ietf.org/html/rfc2616#section-9.8">RFC 2616 (section 9.8)</a>
|
||||
*/
|
||||
@Test
|
||||
@Ignore("Introduction of fix for realm-less security constraints has rendered this test invalid due to default configuration preventing use of TRACE in webdefault.xml")
|
||||
public void test9_8() throws Exception
|
||||
{
|
||||
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
<?xml version="1.0" encoding="ISO-8859-1"?>
|
||||
<!DOCTYPE Configure PUBLIC "-//Mort Bay Consulting//DTD Configure//EN" "http://jetty.mortbay.org/configure.dtd">
|
||||
<!DOCTYPE Configure PUBLIC "-//Mort Bay Consulting//DTD Configure//EN" "http://www.eclipse.org/jetty/configure.dtd">
|
||||
<Configure class="org.eclipse.jetty.webapp.WebAppContext">
|
||||
<Set name="contextPath">/rfc2616-webapp</Set>
|
||||
<Set name="war">
|
||||
|
|
Loading…
Reference in New Issue