Merge branch 'master' into release

This commit is contained in:
Jesse McConnell 2012-01-20 08:41:12 -06:00
commit 5fbe21dbee
42 changed files with 1074 additions and 408 deletions

View File

@ -9,11 +9,9 @@ jetty-7.6.0.RC4 - 13 January 2012
+ 368035 WebSocketClientFactory does not invoke super.doStop(). + 368035 WebSocketClientFactory does not invoke super.doStop().
+ 368060 do not encode sendRedirect URLs + 368060 do not encode sendRedirect URLs
+ 368114 Protect against non-Strings in System properties for Log + 368114 Protect against non-Strings in System properties for Log
+ 368189 WebSocketClientFactory should not manage external thread pool. 368240 + 368189 WebSocketClientFactory should not manage external thread pool.
- Improve AggregateLifeCycle handling of shared lifecycles
+ 368215 Remove debug from jaspi + 368215 Remove debug from jaspi
+ 368240 Better handling of locally created ThreadPool. Forgot to null out + 368240 Improve AggregateLifeCycle handling of shared lifecycles
field.
+ 368291 Change warning to info for NoSuchFieldException on + 368291 Change warning to info for NoSuchFieldException on
BeanELResolver.properties BeanELResolver.properties

View File

@ -10,6 +10,7 @@ import java.net.SocketTimeoutException;
import java.nio.channels.SocketChannel; import java.nio.channels.SocketChannel;
import java.util.Arrays; import java.util.Arrays;
import java.util.concurrent.Callable; import java.util.concurrent.Callable;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.ExecutorService; import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors; import java.util.concurrent.Executors;
import java.util.concurrent.Future; import java.util.concurrent.Future;
@ -42,6 +43,7 @@ import org.eclipse.jetty.server.handler.AbstractHandler;
import org.eclipse.jetty.server.ssl.SslSelectChannelConnector; import org.eclipse.jetty.server.ssl.SslSelectChannelConnector;
import org.eclipse.jetty.toolchain.test.MavenTestingUtils; import org.eclipse.jetty.toolchain.test.MavenTestingUtils;
import org.eclipse.jetty.toolchain.test.OS; import org.eclipse.jetty.toolchain.test.OS;
import org.eclipse.jetty.util.component.Dumpable;
import org.eclipse.jetty.util.ssl.SslContextFactory; import org.eclipse.jetty.util.ssl.SslContextFactory;
import org.junit.After; import org.junit.After;
import org.junit.Assert; import org.junit.Assert;
@ -51,6 +53,8 @@ import org.junit.Test;
import static org.hamcrest.Matchers.greaterThan; import static org.hamcrest.Matchers.greaterThan;
import static org.hamcrest.Matchers.lessThan; import static org.hamcrest.Matchers.lessThan;
import static org.hamcrest.Matchers.containsString;
import static org.hamcrest.Matchers.not;
public class SslBytesServerTest extends SslBytesTest public class SslBytesServerTest extends SslBytesTest
{ {
@ -61,8 +65,10 @@ public class SslBytesServerTest extends SslBytesTest
private final int idleTimeout = 2000; private final int idleTimeout = 2000;
private ExecutorService threadPool; private ExecutorService threadPool;
private Server server; private Server server;
private int serverPort;
private SSLContext sslContext; private SSLContext sslContext;
private SimpleProxy proxy; private SimpleProxy proxy;
private Runnable idleHook;
@Before @Before
public void init() throws Exception public void init() throws Exception
@ -98,6 +104,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 +181,7 @@ public class SslBytesServerTest extends SslBytesTest
} }
}); });
server.start(); server.start();
int serverPort = connector.getLocalPort(); serverPort = connector.getLocalPort();
sslContext = cf.getSslContext(); sslContext = cf.getSslContext();
@ -606,10 +621,10 @@ public class SslBytesServerTest extends SslBytesTest
} }
// Check that we did not spin // Check that we did not spin
TimeUnit.MILLISECONDS.sleep(500); TimeUnit.MILLISECONDS.sleep(1000);
Assert.assertThat(sslHandles.get(), lessThan(750)); Assert.assertThat(sslHandles.get(), lessThan(750));
Assert.assertThat(sslFlushes.get(), lessThan(750)); Assert.assertThat(sslFlushes.get(), lessThan(750));
Assert.assertThat(httpParses.get(), lessThan(150)); Assert.assertThat(httpParses.get(), lessThan(1000));
client.close(); client.close();
@ -1512,6 +1527,172 @@ public class SslBytesServerTest extends SslBytesTest
Assert.assertFalse(serverEndPoint.get().isOpen()); 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() private void assumeJavaVersionSupportsTLSRenegotiations()
{ {
// Due to a security bug, TLS renegotiations were disabled in JDK 1.6.0_19-21 // 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 // Close Alert
record = proxy.readFromServer(); record = proxy.readFromServer();
proxy.flushToClient(record); proxy.flushToClient(record);
// Socket close // Socket close
record = proxy.readFromServer(); record = proxy.readFromServer();
Assert.assertNull(String.valueOf(record), record); Assert.assertNull(String.valueOf(record), record);
proxy.flushToClient(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);
}
} }

View File

@ -1,5 +1,5 @@
<?xml version="1.0" encoding="ISO-8859-1"?> <?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"> <Configure class="org.eclipse.jetty.webapp.WebAppContext">
<Set name="contextPath">/foo</Set> <Set name="contextPath">/foo</Set>
<Set name="war"> <Set name="war">

View File

@ -63,8 +63,8 @@ public class HttpParser implements Parser
private Buffer _body; // Buffer for large content private Buffer _body; // Buffer for large content
private Buffer _buffer; // The current buffer in use (either _header or _content) private Buffer _buffer; // The current buffer in use (either _header or _content)
private CachedBuffer _cached; private CachedBuffer _cached;
private View.CaseInsensitive _tok0; // Saved token: header name, request method or response version private final 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 _tok1; // Saved token: header value, request URI or response code
private String _multiLineValue; private String _multiLineValue;
private int _responseStatus; // If >0 then we are parsing a response private int _responseStatus; // If >0 then we are parsing a response
private boolean _forceContentBuffer; private boolean _forceContentBuffer;
@ -93,13 +93,8 @@ public class HttpParser implements Parser
_buffer=buffer; _buffer=buffer;
_handler=handler; _handler=handler;
if (buffer != null) _tok0=new View.CaseInsensitive(_header);
{ _tok1=new View.CaseInsensitive(_header);
_tok0=new View.CaseInsensitive(buffer);
_tok1=new View.CaseInsensitive(buffer);
_tok0.setPutIndex(_tok0.getIndex());
_tok1.setPutIndex(_tok1.getIndex());
}
} }
/* ------------------------------------------------------------------------------- */ /* ------------------------------------------------------------------------------- */
@ -114,6 +109,8 @@ public class HttpParser implements Parser
_buffers=buffers; _buffers=buffers;
_endp=endp; _endp=endp;
_handler=handler; _handler=handler;
_tok0=new View.CaseInsensitive();
_tok1=new View.CaseInsensitive();
} }
/* ------------------------------------------------------------------------------- */ /* ------------------------------------------------------------------------------- */
@ -197,7 +194,7 @@ public class HttpParser implements Parser
public void setPersistent(boolean persistent) public void setPersistent(boolean persistent)
{ {
_persistent = persistent; _persistent = persistent;
if (_state==STATE_END) if (!_persistent &&(_state==STATE_END || _state==STATE_START))
_state=STATE_SEEKING_EOF; _state=STATE_SEEKING_EOF;
} }
@ -256,17 +253,7 @@ public class HttpParser implements Parser
return 0; return 0;
if (_buffer==null) if (_buffer==null)
{ _buffer=getHeaderBuffer();
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());
}
if (_state == STATE_CONTENT && _contentPosition == _contentLength) if (_state == STATE_CONTENT && _contentPosition == _contentLength)
@ -1013,11 +1000,7 @@ public class HttpParser implements Parser
{ {
// Do we have a buffer? // Do we have a buffer?
if (_buffer==null) if (_buffer==null)
{ _buffer=getHeaderBuffer();
_buffer=_header=getHeaderBuffer();
_tok0=new View.CaseInsensitive(_buffer);
_tok1=new View.CaseInsensitive(_buffer);
}
// Is there unconsumed content in body buffer // Is there unconsumed content in body buffer
if (_state>STATE_END && _buffer==_header && _header!=null && !_header.hasContent() && _body!=null && _body.hasContent()) 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 // This is probably a pipelined header of the next request, so we need to
// copy it to the header buffer. // copy it to the header buffer.
if (_header==null) if (_header==null)
{ getHeaderBuffer();
_header=_buffers.getHeader();
}
else else
{ {
_header.setMarkIndex(-1); _header.setMarkIndex(-1);
@ -1165,6 +1146,8 @@ public class HttpParser implements Parser
if (_header == null) if (_header == null)
{ {
_header=_buffers.getHeader(); _header=_buffers.getHeader();
_tok0.update(_header);
_tok1.update(_header);
} }
return _header; return _header;
} }

View File

@ -176,9 +176,12 @@ public class SelectChannelEndPoint extends ChannelEndPoint implements AsyncEndPo
_writable = true; // Once writable is in ops, only removed with dispatch. _writable = true; // Once writable is in ops, only removed with dispatch.
} }
// Dispatch if we are not already // If dispatched, then deregister interest
if (!_dispatched) if (_dispatched)
_key.interestOps(0);
else
{ {
// other wise do the dispatch
dispatch(); dispatch();
if (_dispatched && !_selectSet.getManager().isDeferringInterestedOps0()) if (_dispatched && !_selectSet.getManager().isDeferringInterestedOps0())
{ {
@ -280,7 +283,7 @@ public class SelectChannelEndPoint extends ChannelEndPoint implements AsyncEndPo
public void checkIdleTimestamp(long now) public void checkIdleTimestamp(long now)
{ {
long idleTimestamp=_idleTimestamp; long idleTimestamp=_idleTimestamp;
if (idleTimestamp!=0 && _maxIdleTime>0) if (idleTimestamp!=0 && _maxIdleTime>0)
{ {
long idleForMs=now-idleTimestamp; long idleForMs=now-idleTimestamp;
@ -454,14 +457,7 @@ public class SelectChannelEndPoint extends ChannelEndPoint implements AsyncEndPo
} }
return true; return true;
} }
/* ------------------------------------------------------------ */
/* short cut for busyselectChannelServerTest */
public void clearWritable()
{
_writable=false;
}
/* ------------------------------------------------------------ */ /* ------------------------------------------------------------ */
/** /**
* @see org.eclipse.jetty.io.AsyncEndPoint#scheduleWrite() * @see org.eclipse.jetty.io.AsyncEndPoint#scheduleWrite()
@ -637,7 +633,6 @@ public class SelectChannelEndPoint extends ChannelEndPoint implements AsyncEndPo
catch (IOException e) catch (IOException e)
{ {
LOG.warn(e.toString()); LOG.warn(e.toString());
LOG.debug(e);
try{close();} try{close();}
catch(IOException e2){LOG.ignore(e2);} catch(IOException e2){LOG.ignore(e2);}
} }

View File

@ -24,6 +24,7 @@ import java.nio.channels.ServerSocketChannel;
import java.nio.channels.SocketChannel; import java.nio.channels.SocketChannel;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentLinkedQueue; import java.util.concurrent.ConcurrentLinkedQueue;
import java.util.concurrent.ConcurrentMap; import java.util.concurrent.ConcurrentMap;
@ -303,7 +304,7 @@ public abstract class SelectorManager extends AbstractLifeCycle implements Dumpa
} }
}); });
if (!selecting) if (!selecting)
throw new IllegalStateException("!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 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)); AggregateLifeCycle.dump(out,indent,TypeUtil.asList(_selectSet));
} }
@ -960,7 +961,7 @@ public abstract class SelectorManager extends AbstractLifeCycle implements Dumpa
{ {
LOG.ignore(e); LOG.ignore(e);
} }
AggregateLifeCycle.dump(out,indent,dump); AggregateLifeCycle.dump(out,indent,dump);
} }
} }
@ -969,8 +970,9 @@ public abstract class SelectorManager extends AbstractLifeCycle implements Dumpa
public void dumpKeyState(List<Object> dumpto) public void dumpKeyState(List<Object> dumpto)
{ {
Selector selector=_selector; Selector selector=_selector;
dumpto.add(selector+" keys="+selector.keys().size()); Set<SelectionKey> keys = selector.keys();
for (SelectionKey key: selector.keys()) dumpto.add(selector + " keys=" + keys.size());
for (SelectionKey key: keys)
{ {
if (key.isValid()) if (key.isValid())
dumpto.add(key.attachment()+" iOps="+key.interestOps()+" rOps="+key.readyOps()); 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() public String toString()
{ {
Selector selector=_selector; Selector selector=_selector;
return String.format("%s %s keys=%d selected=%d", return String.format("%s keys=%d selected=%d",
super.toString(), super.toString(),
SelectorManager.this.getState(),
selector != null && selector.isOpen() ? selector.keys().size() : -1, selector != null && selector.isOpen() ? selector.keys().size() : -1,
selector != null && selector.isOpen() ? selector.selectedKeys().size() : -1); selector != null && selector.isOpen() ? selector.selectedKeys().size() : -1);
} }

View File

@ -42,7 +42,7 @@ import org.eclipse.jetty.util.thread.Timeout.Task;
*/ */
public class SslConnection extends AbstractConnection implements AsyncConnection 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); 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 we are handshook let the delegate connection
if (_engine.getHandshakeStatus()!=HandshakeStatus.NOT_HANDSHAKING) if (_engine.getHandshakeStatus()!=HandshakeStatus.NOT_HANDSHAKING)
{
progress=process(null,null); progress=process(null,null);
}
else // handle the delegate connection
AsyncConnection next = (AsyncConnection)_connection.handle();
if (next!=_connection && next!=null)
{ {
// handle the delegate connection _connection=next;
AsyncConnection next = (AsyncConnection)_connection.handle(); progress=true;
if (next!=_connection && next!=null)
{
_connection=next;
progress=true;
}
// TODO: consider moving here hasProgressed() - it's only used in SSL
} }
LOG.debug("{} handle {} progress={}", _session, this, progress); _logger.debug("{} handle {} progress={}", _session, this, progress);
} }
} }
finally finally
@ -216,9 +211,10 @@ public class SslConnection extends AbstractConnection implements AsyncConnection
} }
catch(Throwable x) catch(Throwable x)
{ {
LOG.warn("onInputShutdown failed", x); _logger.warn("onInputShutdown failed", x);
try{_sslEndPoint.close();} 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 try
{ {
LOG.debug("onIdleExpired {}ms on {}",idleForMs,this); _logger.debug("onIdleExpired {}ms on {}",idleForMs,this);
if (_endp.isOutputShutdown()) if (_endp.isOutputShutdown())
_sslEndPoint.close(); _sslEndPoint.close();
else else
@ -257,7 +253,7 @@ public class SslConnection extends AbstractConnection implements AsyncConnection
} }
catch (IOException e) catch (IOException e)
{ {
LOG.warn(e); _logger.warn(e);
super.onIdleExpired(idleForMs); super.onIdleExpired(idleForMs);
} }
} }
@ -274,40 +270,55 @@ public class SslConnection extends AbstractConnection implements AsyncConnection
boolean some_progress=false; boolean some_progress=false;
try try
{ {
// We need buffers to progress
allocateBuffers(); allocateBuffers();
// if we don't have a buffer to put received data into
if (toFill==null) if (toFill==null)
{ {
// use the unwrapbuffer to hold received data.
_unwrapBuf.compact(); _unwrapBuf.compact();
toFill=_unwrapBuf; toFill=_unwrapBuf;
} }
// Else if the fill buffer is too small for the SSL session
else if (toFill.capacity()<_session.getApplicationBufferSize()) else if (toFill.capacity()<_session.getApplicationBufferSize())
{ {
// fill to the temporary unwrapBuffer
boolean progress=process(null,toFlush); boolean progress=process(null,toFlush);
// if we received any data,
if (_unwrapBuf!=null && _unwrapBuf.hasContent()) if (_unwrapBuf!=null && _unwrapBuf.hasContent())
{ {
// transfer from temp buffer to fill buffer
_unwrapBuf.skip(toFill.put(_unwrapBuf)); _unwrapBuf.skip(toFill.put(_unwrapBuf));
return true; return true;
} }
else else
// return progress from recursive call
return progress; return progress;
} }
// Else if there is some temporary data
else if (_unwrapBuf!=null && _unwrapBuf.hasContent()) else if (_unwrapBuf!=null && _unwrapBuf.hasContent())
{ {
// transfer from temp buffer to fill buffer
_unwrapBuf.skip(toFill.put(_unwrapBuf)); _unwrapBuf.skip(toFill.put(_unwrapBuf));
return true; 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) if (toFlush==null)
toFlush=__ZERO_BUFFER; toFlush=__ZERO_BUFFER;
// While we are making progress processing SSL engine
boolean progress=true; boolean progress=true;
while (progress) while (progress)
{ {
progress=false; progress=false;
int filled=0,flushed=0;
// Do any real IO
int filled=0,flushed=0;
try try
{ {
// Read any available data // Read any available data
@ -325,7 +336,7 @@ public class SslConnection extends AbstractConnection implements AsyncConnection
} }
finally 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 // handle the current hand share status
@ -356,20 +367,6 @@ public class SslConnection extends AbstractConnection implements AsyncConnection
task.run(); 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; break;
@ -388,6 +385,11 @@ public class SslConnection extends AbstractConnection implements AsyncConnection
// The SSL needs to receive some handshake data from the other side // The SSL needs to receive some handshake data from the other side
if (_handshook && !_allowRenegotiate) if (_handshook && !_allowRenegotiate)
_endp.close(); _endp.close();
else if (!_inbound.hasContent()&&filled==-1)
{
// No more input coming
_endp.shutdownInput();
}
else if (unwrap(toFill)) else if (unwrap(toFill))
progress=true; progress=true;
} }
@ -401,10 +403,12 @@ public class SslConnection extends AbstractConnection implements AsyncConnection
if (_endp.isOpen() && _engine.isOutboundDone() && !_outbound.hasContent()) if (_endp.isOpen() && _engine.isOutboundDone() && !_outbound.hasContent())
_endp.shutdownOutput(); _endp.shutdownOutput();
// remember if any progress has been made
some_progress|=progress; 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(); _aEndp.asyncDispatch();
} }
finally finally
@ -434,8 +438,8 @@ public class SslConnection extends AbstractConnection implements AsyncConnection
out_buffer.position(_outbound.putIndex()); out_buffer.position(_outbound.putIndex());
out_buffer.limit(out_buffer.capacity()); out_buffer.limit(out_buffer.capacity());
result=_engine.wrap(bbuf,out_buffer); result=_engine.wrap(bbuf,out_buffer);
if (LOG.isDebugEnabled()) if (_logger.isDebugEnabled())
LOG.debug("{} wrap {} {} consumed={} produced={}", _logger.debug("{} wrap {} {} consumed={} produced={}",
_session, _session,
result.getStatus(), result.getStatus(),
result.getHandshakeStatus(), result.getHandshakeStatus(),
@ -448,7 +452,7 @@ public class SslConnection extends AbstractConnection implements AsyncConnection
} }
catch(SSLException e) catch(SSLException e)
{ {
LOG.warn(String.valueOf(_endp), e); _logger.debug(String.valueOf(_endp), e);
_endp.close(); _endp.close();
throw e; throw e;
} }
@ -476,13 +480,13 @@ public class SslConnection extends AbstractConnection implements AsyncConnection
break; break;
case CLOSED: case CLOSED:
LOG.debug("wrap CLOSE {} {}",this,result); _logger.debug("wrap CLOSE {} {}",this,result);
if (result.getHandshakeStatus()==HandshakeStatus.FINISHED) if (result.getHandshakeStatus()==HandshakeStatus.FINISHED)
_endp.close(); _endp.close();
break; break;
default: default:
LOG.warn("{} wrap default {}",_session,result); _logger.debug("{} wrap default {}",_session,result);
throw new IOException(result.toString()); throw new IOException(result.toString());
} }
@ -510,8 +514,8 @@ public class SslConnection extends AbstractConnection implements AsyncConnection
in_buffer.limit(_inbound.putIndex()); in_buffer.limit(_inbound.putIndex());
result=_engine.unwrap(in_buffer,bbuf); result=_engine.unwrap(in_buffer,bbuf);
if (LOG.isDebugEnabled()) if (_logger.isDebugEnabled())
LOG.debug("{} unwrap {} {} consumed={} produced={}", _logger.debug("{} unwrap {} {} consumed={} produced={}",
_session, _session,
result.getStatus(), result.getStatus(),
result.getHandshakeStatus(), result.getHandshakeStatus(),
@ -524,7 +528,7 @@ public class SslConnection extends AbstractConnection implements AsyncConnection
} }
catch(SSLException e) catch(SSLException e)
{ {
LOG.warn(String.valueOf(_endp), e); _logger.debug(String.valueOf(_endp), e);
_endp.close(); _endp.close();
throw e; throw e;
} }
@ -546,7 +550,7 @@ public class SslConnection extends AbstractConnection implements AsyncConnection
break; break;
case BUFFER_OVERFLOW: case BUFFER_OVERFLOW:
LOG.debug("{} unwrap {} {}->{}",_session,result.getStatus(),_inbound.toDetailString(),buffer.toDetailString()); _logger.debug("{} unwrap {} {}->{}",_session,result.getStatus(),_inbound.toDetailString(),buffer.toDetailString());
break; break;
case OK: case OK:
@ -555,13 +559,13 @@ public class SslConnection extends AbstractConnection implements AsyncConnection
break; break;
case CLOSED: case CLOSED:
LOG.debug("unwrap CLOSE {} {}",this,result); _logger.debug("unwrap CLOSE {} {}",this,result);
if (result.getHandshakeStatus()==HandshakeStatus.FINISHED) if (result.getHandshakeStatus()==HandshakeStatus.FINISHED)
_endp.close(); _endp.close();
break; break;
default: default:
LOG.warn("{} wrap default {}",_session,result); _logger.debug("{} wrap default {}",_session,result);
throw new IOException(result.toString()); throw new IOException(result.toString());
} }
@ -610,7 +614,7 @@ public class SslConnection extends AbstractConnection implements AsyncConnection
{ {
synchronized (SslConnection.this) synchronized (SslConnection.this)
{ {
LOG.debug("{} ssl endp.oshut {}",_session,this); _logger.debug("{} ssl endp.oshut {}",_session,this);
_engine.closeOutbound(); _engine.closeOutbound();
_oshut=true; _oshut=true;
} }
@ -627,7 +631,7 @@ public class SslConnection extends AbstractConnection implements AsyncConnection
public void shutdownInput() throws IOException 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. // 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. // 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 public void close() throws IOException
{ {
LOG.debug("{} ssl endp.close",_session); _logger.debug("{} ssl endp.close",_session);
_endp.close(); _endp.close();
} }

View File

@ -5,7 +5,6 @@ import java.io.IOException;
import java.net.Socket; import java.net.Socket;
import java.nio.ByteBuffer; import java.nio.ByteBuffer;
import java.nio.channels.SocketChannel; import java.nio.channels.SocketChannel;
import javax.net.ssl.SSLEngine; import javax.net.ssl.SSLEngine;
import javax.net.ssl.SSLEngineResult; import javax.net.ssl.SSLEngineResult;
import javax.net.ssl.SSLEngineResult.HandshakeStatus; import javax.net.ssl.SSLEngineResult.HandshakeStatus;
@ -22,7 +21,7 @@ import org.junit.Test;
public class SelectChannelEndPointSslTest extends SelectChannelEndPointTest public class SelectChannelEndPointSslTest extends SelectChannelEndPointTest
{ {
static SslContextFactory __sslCtxFactory=new SslContextFactory(); static SslContextFactory __sslCtxFactory=new SslContextFactory();
@BeforeClass @BeforeClass
public static void initSslEngine() throws Exception public static void initSslEngine() throws Exception
{ {
@ -32,7 +31,7 @@ public class SelectChannelEndPointSslTest extends SelectChannelEndPointTest
__sslCtxFactory.setKeyManagerPassword("keypwd"); __sslCtxFactory.setKeyManagerPassword("keypwd");
__sslCtxFactory.start(); __sslCtxFactory.start();
} }
@Override @Override
protected Socket newClient() throws IOException protected Socket newClient() throws IOException
{ {
@ -60,46 +59,46 @@ public class SelectChannelEndPointSslTest extends SelectChannelEndPointTest
super.testEcho(); super.testEcho();
} }
@Test @Test
@Override @Override
public void testShutdown() throws Exception public void testShutdown() throws Exception
{ {
// SSL does not do half closes // SSL does not do half closes
} }
@Test @Test
public void testTcpClose() throws Exception public void testTcpClose() throws Exception
{ {
// This test replaces SSLSocket() with a very manual SSL client // This test replaces SSLSocket() with a very manual SSL client
// so we can close TCP underneath SSL. // so we can close TCP underneath SSL.
SocketChannel client = SocketChannel.open(_connector.socket().getLocalSocketAddress()); SocketChannel client = SocketChannel.open(_connector.socket().getLocalSocketAddress());
client.socket().setSoTimeout(500); client.socket().setSoTimeout(500);
SocketChannel server = _connector.accept(); SocketChannel server = _connector.accept();
server.configureBlocking(false); server.configureBlocking(false);
_manager.register(server); _manager.register(server);
SSLEngine engine = __sslCtxFactory.newSslEngine(); SSLEngine engine = __sslCtxFactory.newSslEngine();
engine.setUseClientMode(true); engine.setUseClientMode(true);
engine.beginHandshake(); engine.beginHandshake();
ByteBuffer appOut = ByteBuffer.allocate(engine.getSession().getApplicationBufferSize()); ByteBuffer appOut = ByteBuffer.allocate(engine.getSession().getApplicationBufferSize());
ByteBuffer sslOut = ByteBuffer.allocate(engine.getSession().getPacketBufferSize()*2); ByteBuffer sslOut = ByteBuffer.allocate(engine.getSession().getPacketBufferSize()*2);
ByteBuffer appIn = ByteBuffer.allocate(engine.getSession().getApplicationBufferSize()); ByteBuffer appIn = ByteBuffer.allocate(engine.getSession().getApplicationBufferSize());
ByteBuffer sslIn = ByteBuffer.allocate(engine.getSession().getPacketBufferSize()*2); ByteBuffer sslIn = ByteBuffer.allocate(engine.getSession().getPacketBufferSize()*2);
boolean debug=SslConnection.LOG.isDebugEnabled(); boolean debug=false;
if (debug) System.err.println(engine.getHandshakeStatus()); if (debug) System.err.println(engine.getHandshakeStatus());
int loop=20; int loop=20;
while (engine.getHandshakeStatus()!=HandshakeStatus.NOT_HANDSHAKING) while (engine.getHandshakeStatus()!=HandshakeStatus.NOT_HANDSHAKING)
{ {
if (--loop==0) if (--loop==0)
throw new IllegalStateException(); throw new IllegalStateException();
if (engine.getHandshakeStatus()==HandshakeStatus.NEED_WRAP) if (engine.getHandshakeStatus()==HandshakeStatus.NEED_WRAP)
{ {
if (debug) System.err.printf("sslOut %d-%d-%d%n",sslOut.position(),sslOut.limit(),sslOut.capacity()); 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) if (engine.getHandshakeStatus()==HandshakeStatus.NEED_TASK)
{ {
Runnable task; Runnable task;
while ((task=engine.getDelegatedTask())!=null) while ((task=engine.getDelegatedTask())!=null)
task.run(); task.run();
if (debug) System.err.println(engine.getHandshakeStatus()); if (debug) System.err.println(engine.getHandshakeStatus());
} }
} }
if (debug) System.err.println("\nSay Hello"); if (debug) System.err.println("\nSay Hello");
// write a message // write a message
appOut.put("HelloWorld".getBytes("UTF-8")); appOut.put("HelloWorld".getBytes("UTF-8"));
appOut.flip(); appOut.flip();
@ -164,11 +163,11 @@ public class SelectChannelEndPointSslTest extends SelectChannelEndPointTest
sslIn.compact(); sslIn.compact();
else else
sslIn.clear(); sslIn.clear();
appIn.flip(); appIn.flip();
String reply= new String(appIn.array(),appIn.arrayOffset(),appIn.remaining()); String reply= new String(appIn.array(),appIn.arrayOffset(),appIn.remaining());
appIn.clear(); appIn.clear();
Assert.assertEquals("HelloWorld",reply); Assert.assertEquals("HelloWorld",reply);
SelectorManager.LOG.info("javax.net.ssl.SSLException: Inbound closed... is expected soon"); SelectorManager.LOG.info("javax.net.ssl.SSLException: Inbound closed... is expected soon");

View File

@ -1,6 +1,8 @@
package org.eclipse.jetty.io.nio; package org.eclipse.jetty.io.nio;
import static org.hamcrest.Matchers.greaterThanOrEqualTo; import static org.hamcrest.Matchers.greaterThanOrEqualTo;
import static org.hamcrest.Matchers.greaterThan;
import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue; import static org.junit.Assert.assertTrue;
@ -196,7 +198,8 @@ public class SelectChannelEndPointTest
} }
catch(SocketTimeoutException e) catch(SocketTimeoutException e)
{ {
assertTrue(System.currentTimeMillis()-start>=400); long duration = System.currentTimeMillis()-start;
Assert.assertThat("timeout duration", duration, greaterThanOrEqualTo(400L));
} }
// write then shutdown // write then shutdown
@ -206,8 +209,8 @@ public class SelectChannelEndPointTest
for (char c : "Goodbye Cruel TLS".toCharArray()) for (char c : "Goodbye Cruel TLS".toCharArray())
{ {
int b = client.getInputStream().read(); int b = client.getInputStream().read();
assertTrue(b>0); Assert.assertThat("expect valid char integer", b, greaterThan(0));
assertEquals(c,(char)b); assertEquals("expect characters to be same", c,(char)b);
} }
client.close(); client.close();

View File

@ -211,11 +211,20 @@ public class FormAuthModule extends BaseAuthModule
// Check if the session is already authenticated. // Check if the session is already authenticated.
FormCredential form_cred = (FormCredential) session.getAttribute(__J_AUTHENTICATED); FormCredential form_cred = (FormCredential) session.getAttribute(__J_AUTHENTICATED);
if (form_cred != null) 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 //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
boolean success = tryLogin(messageInfo, clientSubject, response, session, form_cred._jUserName, new Password(new String(form_cred._jPassword))); //to FormAuthModule
if (success) { return AuthStatus.SUCCESS; } 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) else if (ssoSource != null)
{ {

View File

@ -337,7 +337,7 @@ public class MBeanContainer extends AbstractLifeCycle implements Container.Liste
public void dump(Appendable out, String indent) throws IOException public void dump(Appendable out, String indent) throws IOException
{ {
out.append(toString()).append("\n"); AggregateLifeCycle.dumpObject(out,this);
AggregateLifeCycle.dump(out, indent, _beans.entrySet()); AggregateLifeCycle.dump(out, indent, _beans.entrySet());
} }

View File

@ -66,26 +66,26 @@
<dependency> <dependency>
<groupId>javax.mail</groupId> <groupId>javax.mail</groupId>
<artifactId>mail</artifactId> <artifactId>mail</artifactId>
<exclusions> <exclusions>
<exclusion> <exclusion>
<groupId>javax.activation</groupId> <groupId>javax.activation</groupId>
<artifactId>activation</artifactId> <artifactId>activation</artifactId>
</exclusion> </exclusion>
</exclusions> </exclusions>
</dependency> </dependency>
</dependencies> </dependencies>
<profiles> <profiles>
<profile> <profile>
<id>below-jdk1.6</id> <id>below-jdk1.6</id>
<activation> <activation>
<jdk>!1.6</jdk> <jdk>(,1.6)</jdk>
</activation> </activation>
<dependencies> <dependencies>
<dependency> <dependency>
<groupId>javax.activation</groupId> <groupId>javax.activation</groupId>
<artifactId>activation</artifactId> <artifactId>activation</artifactId>
<version>${javax-activation-version}</version> <version>1.1</version>
</dependency> </dependency>
</dependencies> </dependencies>
</profile> </profile>
</profiles> </profiles>

View File

@ -358,7 +358,7 @@ public class ConstraintSecurityHandler extends SecurityHandler implements Constr
{ {
if (connector.isIntegral(request)) if (connector.isIntegral(request))
return true; return true;
if (connector.getConfidentialPort() > 0) if (connector.getIntegralPort() > 0)
{ {
String url = connector.getIntegralScheme() + "://" + request.getServerName() + ":" + connector.getIntegralPort() + request.getRequestURI(); String url = connector.getIntegralScheme() + "://" + request.getServerName() + ":" + connector.getIntegralPort() + request.getRequestURI();
if (request.getQueryString() != null) if (request.getQueryString() != null)
@ -440,6 +440,13 @@ public class ConstraintSecurityHandler extends SecurityHandler implements Constr
public void dump(Appendable out,String indent) throws IOException public void dump(Appendable out,String indent) throws IOException
{ {
dumpThis(out); 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()));
} }
} }

View File

@ -244,16 +244,19 @@ public abstract class SecurityHandler extends HandlerWrapper implements Authenti
return _initParameters.put(key,value); return _initParameters.put(key,value);
} }
/* ------------------------------------------------------------ */ /* ------------------------------------------------------------ */
protected LoginService findLoginService() protected LoginService findLoginService()
{ {
List<LoginService> list = getServer().getBeans(LoginService.class); List<LoginService> list = getServer().getBeans(LoginService.class);
for (LoginService service : list) String realm=getRealmName();
if (service.getName()!=null && service.getName().equals(getRealmName())) if (realm!=null)
return service; {
if (list.size()>0) for (LoginService service : list)
if (service.getName()!=null && service.getName().equals(realm))
return service;
}
else if (list.size()==1)
return list.get(0); return list.get(0);
return null; return null;
} }
@ -414,7 +417,7 @@ public abstract class SecurityHandler extends HandlerWrapper implements Authenti
final Authenticator authenticator = _authenticator; final Authenticator authenticator = _authenticator;
if (authenticator!=null && checkSecurity(baseRequest)) if (checkSecurity(baseRequest))
{ {
Object constraintInfo = prepareConstraintInfo(pathInContext, baseRequest); Object constraintInfo = prepareConstraintInfo(pathInContext, baseRequest);
@ -433,13 +436,24 @@ public abstract class SecurityHandler extends HandlerWrapper implements Authenti
boolean isAuthMandatory = boolean isAuthMandatory =
isAuthMandatory(baseRequest, base_response, constraintInfo); 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 // check authentication
Object previousIdentity = null; Object previousIdentity = null;
try try
{ {
Authentication authentication = baseRequest.getAuthentication(); Authentication authentication = baseRequest.getAuthentication();
if (authentication==null || authentication==Authentication.NOT_CHECKED) 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) if (authentication instanceof Authentication.Wrapped)
{ {
@ -500,9 +514,11 @@ public abstract class SecurityHandler extends HandlerWrapper implements Authenti
else else
{ {
baseRequest.setAuthentication(authentication); baseRequest.setAuthentication(authentication);
previousIdentity = _identityService.associate(null); if (_identityService!=null)
previousIdentity = _identityService.associate(null);
handler.handle(pathInContext, baseRequest, request, response); handler.handle(pathInContext, baseRequest, request, response);
authenticator.secureResponse(request, response, isAuthMandatory, null); if (authenticator!=null)
authenticator.secureResponse(request, response, isAuthMandatory, null);
} }
} }
catch (ServerAuthException e) catch (ServerAuthException e)
@ -513,7 +529,8 @@ public abstract class SecurityHandler extends HandlerWrapper implements Authenti
} }
finally finally
{ {
_identityService.disassociate(previousIdentity); if (_identityService!=null)
_identityService.disassociate(previousIdentity);
} }
} }
else else

View File

@ -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)
{
}
}
}

View File

@ -889,11 +889,10 @@ public abstract class AbstractConnector extends AggregateLifeCycle implements Ht
@Override @Override
public String toString() public String toString()
{ {
return String.format("%s@%s:%d %s", return String.format("%s@%s:%d",
getClass().getSimpleName(), getClass().getSimpleName(),
getHost()==null?"0.0.0.0":getHost(), getHost()==null?"0.0.0.0":getHost(),
getLocalPort()<=0?getPort():getLocalPort(), getLocalPort()<=0?getPort():getLocalPort());
AbstractLifeCycle.getState(this));
} }
/* ------------------------------------------------------------ */ /* ------------------------------------------------------------ */

View File

@ -102,14 +102,14 @@ public abstract class AbstractHttpConnection extends AbstractConnection
protected final Parser _parser; protected final Parser _parser;
protected final HttpFields _requestFields; protected final HttpFields _requestFields;
protected final Request _request; protected final Request _request;
protected ServletInputStream _in; protected volatile ServletInputStream _in;
protected final Generator _generator; protected final Generator _generator;
protected final HttpFields _responseFields; protected final HttpFields _responseFields;
protected final Response _response; protected final Response _response;
protected Output _out; protected volatile Output _out;
protected OutputWriter _writer; protected volatile OutputWriter _writer;
protected PrintWriter _printWriter; protected volatile PrintWriter _printWriter;
int _include; int _include;
@ -122,7 +122,7 @@ public abstract class AbstractHttpConnection extends AbstractConnection
private boolean _expect102Processing = false; private boolean _expect102Processing = false;
private boolean _head = false; private boolean _head = false;
private boolean _host = false; private boolean _host = false;
private boolean _delayedHandling=false; private boolean _delayedHandling=false;
/* ------------------------------------------------------------ */ /* ------------------------------------------------------------ */
public static AbstractHttpConnection getCurrentConnection() public static AbstractHttpConnection getCurrentConnection()

View File

@ -177,6 +177,10 @@ public class AsyncHttpConnection extends AbstractHttpConnection implements Async
// then no more can happen, so close. // then no more can happen, so close.
_endp.close(); _endp.close();
} }
// Make idle parser seek EOF
if (_parser.isIdle())
_parser.setPersistent(false);
} }
} }

View File

@ -131,7 +131,7 @@ public class Dispatcher implements RequestDispatcher
public void include(ServletRequest request, ServletResponse response) throws ServletException, IOException public void include(ServletRequest request, ServletResponse response) throws ServletException, IOException
{ {
Request baseRequest=(request instanceof Request)?((Request)request):AbstractHttpConnection.getCurrentConnection().getRequest(); 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)) if (!(request instanceof HttpServletRequest))
request = new ServletRequestHttpWrapper(request); request = new ServletRequestHttpWrapper(request);
@ -215,7 +215,7 @@ public class Dispatcher implements RequestDispatcher
Response base_response=baseRequest.getResponse(); Response base_response=baseRequest.getResponse();
response.resetBuffer(); response.resetBuffer();
base_response.fwdReset(); base_response.fwdReset();
request.removeAttribute(__JSP_FILE); // TODO remove when glassfish 1044 is fixed
if (!(request instanceof HttpServletRequest)) if (!(request instanceof HttpServletRequest))
request = new ServletRequestHttpWrapper(request); request = new ServletRequestHttpWrapper(request);

View File

@ -135,8 +135,8 @@ public class HttpOutput extends ServletOutputStream
// Add the _content // Add the _content
if (_generator.addContent((byte)b)) if (_generator.addContent((byte)b))
// Buffers are full so flush. // Buffers are full so commit.
flush(); _connection.commitResponse(Generator.MORE);
if (_generator.isAllContentWritten()) if (_generator.isAllContentWritten())
{ {
@ -174,7 +174,7 @@ public class HttpOutput extends ServletOutputStream
close(); close();
} }
else if (_generator.isBufferFull()) else if (_generator.isBufferFull())
flush(); _connection.commitResponse(Generator.MORE);
// Block until our buffer is free // Block until our buffer is free
while (buffer.length() > 0 && _generator.isOpen()) while (buffer.length() > 0 && _generator.isOpen())

View File

@ -81,7 +81,7 @@ public class Response implements HttpServletResponse
private String _characterEncoding; private String _characterEncoding;
private boolean _explicitEncoding; private boolean _explicitEncoding;
private String _contentType; private String _contentType;
private int _outputState; private volatile int _outputState;
private PrintWriter _writer; private PrintWriter _writer;
/* ------------------------------------------------------------ */ /* ------------------------------------------------------------ */
@ -108,8 +108,8 @@ public class Response implements HttpServletResponse
_characterEncoding=null; _characterEncoding=null;
_explicitEncoding=false; _explicitEncoding=false;
_contentType=null; _contentType=null;
_outputState=NONE;
_writer=null; _writer=null;
_outputState=NONE;
} }
/* ------------------------------------------------------------ */ /* ------------------------------------------------------------ */
@ -646,8 +646,9 @@ public class Response implements HttpServletResponse
if (_outputState!=NONE && _outputState!=STREAM) if (_outputState!=NONE && _outputState!=STREAM)
throw new IllegalStateException("WRITER"); throw new IllegalStateException("WRITER");
ServletOutputStream out = _connection.getOutputStream();
_outputState=STREAM; _outputState=STREAM;
return _connection.getOutputStream(); return out;
} }
/* ------------------------------------------------------------ */ /* ------------------------------------------------------------ */
@ -1065,8 +1066,8 @@ public class Response implements HttpServletResponse
{ {
resetBuffer(); resetBuffer();
_outputState=NONE;
_writer=null; _writer=null;
_outputState=NONE;
} }
/* ------------------------------------------------------------ */ /* ------------------------------------------------------------ */

View File

@ -94,7 +94,7 @@ public abstract class AbstractHandler extends AggregateLifeCycle implements Hand
/* ------------------------------------------------------------ */ /* ------------------------------------------------------------ */
public void dumpThis(Appendable out) throws IOException public void dumpThis(Appendable out) throws IOException
{ {
out.append(toString()).append(' ').append(getState()).append('\n'); out.append(toString()).append(" - ").append(getState()).append('\n');
} }
} }

View File

@ -113,6 +113,6 @@ public abstract class AbstractHandlerContainer extends AbstractHandler implement
public void dump(Appendable out,String indent) throws IOException public void dump(Appendable out,String indent) throws IOException
{ {
dumpThis(out); dumpThis(out);
dump(out,indent,TypeUtil.asList(getHandlers()),getBeans()); dump(out,indent,getBeans(),TypeUtil.asList(getHandlers()));
} }
} }

View File

@ -448,8 +448,8 @@ public class HttpConnectionTest
PrintWriter writer = response.getWriter(); PrintWriter writer = response.getWriter();
writer.write("<html><h1>FOO</h1></html>"); writer.write("<html><h1>FOO</h1></html>");
writer.flush(); writer.flush();
writer.close(); if (!writer.checkError())
throw new RuntimeException("SHOULD NOT GET HERE"); throw new RuntimeException("SHOULD NOT GET HERE");
} }
catch(Exception e) catch(Exception e)
{ {

View File

@ -31,16 +31,21 @@ import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse; import javax.servlet.http.HttpServletResponse;
import junit.framework.Assert; import junit.framework.Assert;
import org.eclipse.jetty.http.HttpParser;
import org.eclipse.jetty.io.EndPoint; import org.eclipse.jetty.io.EndPoint;
import org.eclipse.jetty.server.handler.AbstractHandler; import org.eclipse.jetty.server.handler.AbstractHandler;
import org.eclipse.jetty.util.IO; 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.Log;
import org.eclipse.jetty.util.log.StdErrLog; import org.eclipse.jetty.util.log.StdErrLog;
import org.junit.Test; import org.junit.Test;
import static org.hamcrest.Matchers.greaterThanOrEqualTo;
import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotSame; import static org.junit.Assert.assertNotSame;
import static org.junit.Assert.assertTrue; import static org.junit.Assert.assertTrue;
import static org.junit.Assert.assertThat;
/** /**
* *
@ -492,7 +497,7 @@ public abstract class HttpServerTestBase extends HttpServerTestFixture
} }
finally finally
{ {
System.err.println("Got "+total+" of "+(512*1024)); //System.err.println("Got "+total+" of "+(512*1024));
client.close(); client.close();
} }
} }
@ -739,7 +744,7 @@ public abstract class HttpServerTestBase extends HttpServerTestFixture
IO.copy(is,bout); IO.copy(is,bout);
byte[] b=bout.toByteArray(); byte[] b=bout.toByteArray();
System.err.println("OUTPUT: "+new String(b)); //System.err.println("OUTPUT: "+new String(b));
int i=0; int i=0;
while (b[i]!='Z') while (b[i]!='Z')
i++; 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);
}
}
} }

View File

@ -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);
}
}
}

View File

@ -260,7 +260,8 @@ public class Holder<T> extends AbstractLifeCycle implements Dumpable
/* ------------------------------------------------------------ */ /* ------------------------------------------------------------ */
public void dump(Appendable out, String indent) throws IOException 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()); AggregateLifeCycle.dump(out,indent,_initParams.entrySet());
} }

View File

@ -739,8 +739,14 @@ public class ProxyServlet implements Servlet
*/ */
protected void handleOnException(Throwable ex, HttpServletRequest request, HttpServletResponse response) protected void handleOnException(Throwable ex, HttpServletRequest request, HttpServletResponse response)
{ {
_log.warn(ex.toString()); if (ex instanceof IOException)
_log.debug(ex); {
_log.warn(ex.toString());
_log.debug(ex);
}
else
_log.warn(ex);
if (!response.isCommitted()) if (!response.isCommitted())
{ {
response.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR); response.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);

View File

@ -209,9 +209,4 @@ public abstract class AbstractLifeCycle implements LifeCycle
public void lifeCycleStopped(LifeCycle event) {} public void lifeCycleStopped(LifeCycle event) {}
public void lifeCycleStopping(LifeCycle event) {} public void lifeCycleStopping(LifeCycle event) {}
} }
public String toString()
{
return super.toString()+"#"+getState();
}
} }

View File

@ -339,7 +339,16 @@ public class AggregateLifeCycle extends AbstractLifeCycle implements Destroyable
/* ------------------------------------------------------------ */ /* ------------------------------------------------------------ */
protected void dumpThis(Appendable out) throws IOException 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(" +- "); out.append(indent).append(" +- ");
if (b._bean instanceof Dumpable) if (b._bean instanceof Dumpable)
((Dumpable)b._bean).dump(out,indent+(i==size?" ":" | ")); ((Dumpable)b._bean).dump(out,indent+(i==size?" ":" | "));
else else
out.append(String.valueOf(b._bean)).append("\n"); dumpObject(out,b._bean);
} }
else else
{ dumpObject(out,b._bean);
out.append(indent).append(" +~ ");
out.append(String.valueOf(b._bean)).append("\n");
}
} }
if (i!=size) if (i!=size)
@ -395,16 +400,12 @@ public class AggregateLifeCycle extends AbstractLifeCycle implements Destroyable
if (o instanceof Dumpable) if (o instanceof Dumpable)
((Dumpable)o).dump(out,indent+(i==size?" ":" | ")); ((Dumpable)o).dump(out,indent+(i==size?" ":" | "));
else else
out.append(String.valueOf(o)).append("\n"); dumpObject(out,o);
} }
if (i!=size) if (i!=size)
out.append(indent).append(" |\n"); out.append(indent).append(" |\n");
} }
} }
} }

View File

@ -4,11 +4,11 @@
// All rights reserved. This program and the accompanying materials // All rights reserved. This program and the accompanying materials
// are made available under the terms of the Eclipse Public License v1.0 // are made available under the terms of the Eclipse Public License v1.0
// and Apache License v2.0 which accompanies this distribution. // 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 // http://www.eclipse.org/legal/epl-v10.html
// The Apache License v2.0 is available at // The Apache License v2.0 is available at
// http://www.opensource.org/licenses/apache2.0.php // 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; 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 * JettyAwareLogger is used to fix a FQCN bug that arises from how Jetty
* Log uses an indirect slf4j implementation. * Log uses an indirect slf4j implementation.
* *
* https://bugs.eclipse.org/bugs/show_bug.cgi?id=276670 * 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 DEBUG = org.slf4j.spi.LocationAwareLogger.DEBUG_INT;
private static final int ERROR = org.slf4j.spi.LocationAwareLogger.ERROR_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 INFO = org.slf4j.spi.LocationAwareLogger.INFO_INT;
private static final int TRACE = org.slf4j.spi.LocationAwareLogger.TRACE_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 int WARN = org.slf4j.spi.LocationAwareLogger.WARN_INT;
private static final String FQCN = Slf4jLog.class.getName(); private static final String FQCN = Slf4jLog.class.getName();
private final org.slf4j.spi.LocationAwareLogger _logger; private final org.slf4j.spi.LocationAwareLogger _logger;
public JettyAwareLogger(org.slf4j.spi.LocationAwareLogger logger) public JettyAwareLogger(org.slf4j.spi.LocationAwareLogger logger)
{ {
_logger = logger; _logger = logger;
@ -586,26 +586,33 @@ class JettyAwareLogger implements org.slf4j.Logger
{ {
log(marker, ERROR, msg, null, t); log(marker, ERROR, msg, null, t);
} }
@Override @Override
public String toString() public String toString()
{ {
return _logger.toString(); return _logger.toString();
} }
private void log(Marker marker, int level, String msg, Object[] argArray, Throwable t) private void log(Marker marker, int level, String msg, Object[] argArray, Throwable t)
{ {
if (argArray == null) if (argArray == null)
{ {
// Simple SLF4J Message (no args) // Simple SLF4J Message (no args)
_logger.log(marker,FQCN,level,msg,null,t); _logger.log(marker, FQCN, level, msg, null, t);
} }
else else
{ {
// Don't assume downstream handles argArray properly. int loggerLevel = _logger.isTraceEnabled() ? TRACE :
// Do it the SLF4J way here to eliminate that as a bug. _logger.isDebugEnabled() ? DEBUG :
FormattingTuple ft = MessageFormatter.arrayFormat(msg,argArray); _logger.isInfoEnabled() ? INFO :
_logger.log(marker,FQCN,level,ft.getMessage(),null,t); _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);
}
} }
} }
} }

View File

@ -16,8 +16,6 @@ package org.eclipse.jetty.util.log;
import java.io.PrintStream; import java.io.PrintStream;
import java.security.AccessControlException; import java.security.AccessControlException;
import java.util.Properties; import java.util.Properties;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
import org.eclipse.jetty.util.DateCache; import org.eclipse.jetty.util.DateCache;

View File

@ -1524,11 +1524,10 @@ public class SslContextFactory extends AbstractLifeCycle
/* ------------------------------------------------------------ */ /* ------------------------------------------------------------ */
public String toString() public String toString()
{ {
return String.format("%s@%x(%s,%s)#%s", return String.format("%s@%x(%s,%s)",
getClass().getSimpleName(), getClass().getSimpleName(),
hashCode(), hashCode(),
_keyStorePath, _keyStorePath,
_trustStorePath, _trustStorePath);
getState());
} }
} }

View File

@ -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); AggregateLifeCycle.dump(out,indent,dump);
} }
@ -508,7 +508,7 @@ public class QueuedThreadPool extends AbstractLifeCycle implements SizedThreadPo
@Override @Override
public String toString() 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())+"}";
} }
/* ------------------------------------------------------------ */ /* ------------------------------------------------------------ */

View File

@ -354,7 +354,7 @@ public class WebSocketClientFactory extends AggregateLifeCycle
private final HttpParser _parser; private final HttpParser _parser;
private String _accept; private String _accept;
private String _error; private String _error;
private boolean _handshaken; private ByteArrayBuffer _handshake;
public HandshakeConnection(AsyncEndPoint endpoint, WebSocketClient.WebSocketFuture future) 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 (_handshake==null)
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()) String path = _future.getURI().getPath();
request.append("Cookie: ") if (path == null || path.length() == 0)
.append(QuotedStringTokenizer.quoteIfNeeded(cookie, HttpFields.__COOKIE_DELIM)) path = "/";
.append("=")
.append(QuotedStringTokenizer.quoteIfNeeded(cookies.get(cookie), HttpFields.__COOKIE_DELIM)) if (_future.getURI().getRawQuery() != null)
.append("\r\n"); 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 // TODO extensions
try try
{ {
Buffer handshake = new ByteArrayBuffer(request.toString(), false); int len = _handshake.length();
int len = handshake.length(); int flushed = _endp.flush(_handshake);
if (len != _endp.flush(handshake)) if (flushed<0)
throw new IOException("incomplete"); throw new IOException("incomplete handshake");
} }
catch (IOException e) catch (IOException e)
{ {
_future.handshakeFailed(e); _future.handshakeFailed(e);
} }
finally return _handshake.length()==0;
{
_handshaken = true;
}
} }
public Connection handle() throws IOException public Connection handle() throws IOException
{ {
while (_endp.isOpen() && !_parser.isComplete()) while (_endp.isOpen() && !_parser.isComplete())
{ {
if (!_handshaken) if (_handshake==null || _handshake.length()>0)
handshake(); if (!handshake())
return this;
if (!_parser.parseAvailable()) if (!_parser.parseAvailable())
{ {

View File

@ -15,6 +15,9 @@
*******************************************************************************/ *******************************************************************************/
package org.eclipse.jetty.websocket; package org.eclipse.jetty.websocket;
import static org.hamcrest.Matchers.*;
import static org.junit.Assert.*;
import java.io.EOFException; import java.io.EOFException;
import java.io.IOException; import java.io.IOException;
import java.io.InputStream; import java.io.InputStream;
@ -28,9 +31,9 @@ import java.util.concurrent.atomic.AtomicLong;
import java.util.concurrent.atomic.AtomicReference; import java.util.concurrent.atomic.AtomicReference;
import java.util.zip.Deflater; import java.util.zip.Deflater;
import java.util.zip.Inflater; import java.util.zip.Inflater;
import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletRequest;
import junit.framework.Assert;
import org.eclipse.jetty.io.Buffer; import org.eclipse.jetty.io.Buffer;
import org.eclipse.jetty.io.ByteArrayEndPoint; import org.eclipse.jetty.io.ByteArrayEndPoint;
import org.eclipse.jetty.server.Connector; 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.TypeUtil;
import org.eclipse.jetty.util.Utf8StringBuilder; import org.eclipse.jetty.util.Utf8StringBuilder;
import org.junit.AfterClass; import org.junit.AfterClass;
import org.junit.Assert;
import org.junit.BeforeClass; import org.junit.BeforeClass;
import org.junit.Test; 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 public class WebSocketMessageRFC6455Test
{ {
private static Server __server; private static Server __server;
@ -606,7 +606,7 @@ public class WebSocketMessageRFC6455Test
Thread.sleep(100); Thread.sleep(100);
assertEquals(count*(mesg.length()+2),totalB.get()); // all messages 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 @Test

View File

@ -111,21 +111,22 @@ public class XmlConfiguration
try try
{ {
URL config60 = Loader.getResource(XmlConfiguration.class,"org/eclipse/jetty/xml/configure_6_0.dtd",true); 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); URL config76 = Loader.getResource(XmlConfiguration.class,"org/eclipse/jetty/xml/configure_7_6.dtd",true);
__parser.redirectEntity("configure.dtd",config71); __parser.redirectEntity("configure.dtd",config76);
__parser.redirectEntity("configure_1_0.dtd",config60); __parser.redirectEntity("configure_1_0.dtd",config60);
__parser.redirectEntity("configure_1_1.dtd",config60); __parser.redirectEntity("configure_1_1.dtd",config60);
__parser.redirectEntity("configure_1_2.dtd",config60); __parser.redirectEntity("configure_1_2.dtd",config60);
__parser.redirectEntity("configure_1_3.dtd",config60); __parser.redirectEntity("configure_1_3.dtd",config60);
__parser.redirectEntity("configure_6_0.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://jetty.mortbay.org/configure.dtd",config76);
__parser.redirectEntity("http://www.eclipse.org/jetty/configure.dtd",config71); __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("-//Mort Bay Consulting//DTD Configure//EN",config76);
__parser.redirectEntity("-//Jetty//Configure//EN",config71); __parser.redirectEntity("-//Jetty//Configure//EN",config76);
} }
catch (ClassNotFoundException e) catch (ClassNotFoundException e)
{ {

View File

@ -25,6 +25,14 @@ import org.junit.Test;
public class XmlConfigurationTest public class XmlConfigurationTest
{ {
protected String _configure="org/eclipse/jetty/xml/configure.xml"; 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 @Test
public void testPassedObject() throws Exception public void testPassedObject() throws Exception

View File

@ -1,5 +1,5 @@
<?xml version="1.0" encoding="ISO-8859-1"?> <?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"> <Configure class="org.eclipse.jetty.xml.TestConfiguration">

View File

@ -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>

View File

@ -16,8 +16,8 @@
package org.eclipse.jetty.test.rfcs; package org.eclipse.jetty.test.rfcs;
import static org.junit.Assert.assertThat; import static org.junit.Assert.*;
import static org.junit.matchers.JUnitMatchers.containsString; import static org.junit.matchers.JUnitMatchers.*;
import java.io.File; import java.io.File;
import java.io.IOException; import java.io.IOException;
@ -42,6 +42,7 @@ import org.eclipse.jetty.toolchain.test.StringAssert;
import org.junit.AfterClass; import org.junit.AfterClass;
import org.junit.Assert; import org.junit.Assert;
import org.junit.Before; import org.junit.Before;
import org.junit.Ignore;
import org.junit.Test; 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> * @see <a href="http://tools.ietf.org/html/rfc2616#section-9.8">RFC 2616 (section 9.8)</a>
*/ */
@Test @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 public void test9_8() throws Exception
{ {

View File

@ -1,5 +1,5 @@
<?xml version="1.0" encoding="ISO-8859-1"?> <?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"> <Configure class="org.eclipse.jetty.webapp.WebAppContext">
<Set name="contextPath">/rfc2616-webapp</Set> <Set name="contextPath">/rfc2616-webapp</Set>
<Set name="war"> <Set name="war">