Merge remote-tracking branch 'origin/master' into jetty-8

Conflicts:
	VERSION.txt
	example-jetty-embedded/pom.xml
	jetty-aggregate/jetty-all-server/pom.xml
	jetty-aggregate/jetty-all/pom.xml
	jetty-aggregate/jetty-client/pom.xml
	jetty-aggregate/jetty-plus/pom.xml
	jetty-aggregate/jetty-server/pom.xml
	jetty-aggregate/jetty-servlet/pom.xml
	jetty-aggregate/jetty-webapp/pom.xml
	jetty-aggregate/pom.xml
	jetty-ajp/pom.xml
	jetty-annotations/pom.xml
	jetty-client/pom.xml
	jetty-continuation/pom.xml
	jetty-deploy/pom.xml
	jetty-deploy/src/main/config/etc/jetty-deploy.xml
	jetty-distribution/pom.xml
	jetty-http/pom.xml
	jetty-io/pom.xml
	jetty-jaspi/pom.xml
	jetty-jmx/pom.xml
	jetty-jndi/pom.xml
	jetty-jsp-2.1/pom.xml
	jetty-monitor/pom.xml
	jetty-nested/pom.xml
	jetty-nosql/pom.xml
	jetty-osgi/jetty-osgi-boot-jsp/pom.xml
	jetty-osgi/jetty-osgi-boot-jsp/src/main/java/org/eclipse/jetty/osgi/boot/jsp/FragmentActivator.java
	jetty-osgi/jetty-osgi-boot-logback/pom.xml
	jetty-osgi/jetty-osgi-boot-warurl/pom.xml
	jetty-osgi/jetty-osgi-boot/pom.xml
	jetty-osgi/jetty-osgi-equinoxtools/pom.xml
	jetty-osgi/jetty-osgi-httpservice/pom.xml
	jetty-osgi/jetty-osgi-servletbridge/pom.xml
	jetty-osgi/jetty-osgi-servletbridge/src/main/java/org/eclipse/jetty/osgi/servletbridge/FrameworkLauncherExtended.java
	jetty-osgi/jetty-osgi-servletbridge/src/main/webapp/WEB-INF/web.xml
	jetty-osgi/pom.xml
	jetty-osgi/test-jetty-osgi/pom.xml
	jetty-overlay-deployer/pom.xml
	jetty-plus/pom.xml
	jetty-policy/pom.xml
	jetty-rewrite/pom.xml
	jetty-security/pom.xml
	jetty-server/pom.xml
	jetty-server/src/main/java/org/eclipse/jetty/server/HttpOutput.java
	jetty-servlet/pom.xml
	jetty-servlets/pom.xml
	jetty-start/pom.xml
	jetty-util/pom.xml
	jetty-webapp/pom.xml
	jetty-websocket/pom.xml
	jetty-xml/pom.xml
	pom.xml
	test-continuation-jetty6/pom.xml
	test-continuation/pom.xml
	test-jetty-nested/pom.xml
	test-jetty-servlet/pom.xml
	test-jetty-webapp/pom.xml
	tests/pom.xml
	tests/test-integration/pom.xml
	tests/test-loginservice/pom.xml
	tests/test-sessions/pom.xml
	tests/test-sessions/test-hash-sessions/pom.xml
	tests/test-sessions/test-jdbc-sessions/pom.xml
	tests/test-sessions/test-sessions-common/pom.xml
	tests/test-webapps/pom.xml
	tests/test-webapps/test-webapp-rfc2616/pom.xml
This commit is contained in:
Jan Bartel 2011-10-04 17:45:15 +11:00
commit 32dbb1bddb
137 changed files with 6215 additions and 3619 deletions

23
.gitignore vendored
View File

@ -1,14 +1,33 @@
target/
# eclipse
.classpath
.project
.settings
# maven
target/
*/src/main/java/META-INF/
.pmd
# common junk
*.log
*.swp
*.diff
*.patch
# intellij
*.iml
*.ipr
*.iws
.idea/
# Mac filesystem dust
/.DS_Store
# pmd
.pmdruleset
.pmd
# netbeans
/nbproject
# vim
.*.sw[a-p]

View File

@ -1,5 +1,11 @@
jetty-8.0.2-SNAPSHOT
jetty-7.5.2-SNAPSHOT
+ 358121 Implement new UTF8 Algorithm to UTF8Appendable.java
+ 353839 ajp component error when upload file
+ JETTY-1378 new system property to for the use of the JDTCompiler when using the latest jsp-impl
jetty-8.0.1.v20110908 - 08 September 2011
+ 350634 Added Resource.newResource(File)
+ 356190 fix monodb tests for changed test api
@ -12,12 +18,25 @@ jetty-8.0.1.v20110908 - 08 September 2011
+ 356823 correctly decode close codes. Send not utf-8 close code.
+ 357058 Acceptor thread blocking
jetty-7.5.1.v20110908 - 08 September 2011
+ 350634 Added Resource.newResource(File)
+ 356190 fix monodb tests for changed test api
+ 356428 removed timed waits from test
+ 356693 reduce visibility to webapp of websocket implementations
+ 356695 jetty server jars are provided for websockets
+ 356726 Instead of the sessionDestroyed called sessionCreated after
invalidate session
+ 356751 Add null protection to ServletContextHandler.doStop
+ 356823 correctly decode close codes. Send not utf-8 close code.
+ 357058 Acceptor thread blocking
jetty-8.0.0.v20110901 - 01 September 2011
+ 352565 cookie httponly flag ignored
+ 353073 better warnings
+ 353285 ServletSecurity annotation ignored
+ 356421 Upgraded websocket to draft 13 support
jetty-7.5.0.v20110901 - 01 September 2011
+ 356421 Upgraded websocket to draft 13 support
+ 353073 better warnings

View File

@ -33,6 +33,7 @@ import org.eclipse.jetty.server.handler.RequestLogHandler;
import org.eclipse.jetty.server.handler.StatisticsHandler;
import org.eclipse.jetty.server.nio.SelectChannelConnector;
import org.eclipse.jetty.server.ssl.SslSelectChannelConnector;
import org.eclipse.jetty.server.ssl.SslSocketConnector;
import org.eclipse.jetty.util.log.Log;
import org.eclipse.jetty.util.thread.QueuedThreadPool;
@ -87,9 +88,15 @@ public class LikeJettyXml
"SSL_DHE_RSA_EXPORT_WITH_DES40_CBC_SHA",
"SSL_DHE_DSS_EXPORT_WITH_DES40_CBC_SHA"
});
cf.setProtocol("TLSv1.1");
cf.addExcludeProtocols(new String[]{"TLSv1","SSLv3"});
ssl_connector.setStatsOn(true);
server.addConnector(ssl_connector);
ssl_connector.open();
Ajp13SocketConnector ajp = new Ajp13SocketConnector();
ajp.setPort(8009);
server.addConnector(ajp);

View File

@ -29,7 +29,7 @@ public class SecuredHelloHandler
{
public static void main(String[] args) throws Exception
{
Server server = new Server(0);
Server server = new Server(8080);
LoginService loginService = new HashLoginService("MyRealm","src/test/resources/realm.properties");
server.addBean(loginService);

View File

@ -25,7 +25,7 @@
<goal>unpack-dependencies</goal>
</goals>
<configuration>
<includes>META-INF/**,org/eclipse/**</includes>
<includes>META-INF/**,org/eclipse/**,org/apache/jasper/compiler/**</includes>
<excludes>**/MANIFEST.MF,javax/**</excludes>
<outputDirectory>${project.build.directory}/classes</outputDirectory>
<overWriteReleases>false</overWriteReleases>

View File

@ -22,7 +22,7 @@
<goal>unpack-dependencies</goal>
</goals>
<configuration>
<includes>META-INF/**,org/eclipse/**</includes>
<includes>META-INF/**,org/eclipse/**,org/apache/jasper/compiler/*</includes>
<excludes>**/MANIFEST.MF,javax/**</excludes>
<outputDirectory>${project.build.directory}/classes</outputDirectory>
<overWriteReleases>false</overWriteReleases>
@ -75,6 +75,19 @@
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-javadoc-plugin</artifactId>
<executions>
<execution>
<id>javadoc-jar</id>
<phase>compile</phase>
<goals>
<goal>jar</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>

View File

@ -22,7 +22,7 @@
<goal>unpack-dependencies</goal>
</goals>
<configuration>
<includes>META-INF/**,org/eclipse/**</includes>
<includes>META-INF/**,org/eclipse/**,org/apache/jasper/compiler/**</includes>
<excludes>**/MANIFEST.MF,javax/**</excludes>
<outputDirectory>${project.build.directory}/classes</outputDirectory>
<overWriteReleases>false</overWriteReleases>

View File

@ -44,38 +44,38 @@ public class Ajp13Generator extends AbstractGenerator
static
{
byte[] xA001 =
{ (byte) 0xA0, (byte) 0x01 };
{ (byte)0xA0, (byte)0x01 };
byte[] xA002 =
{ (byte) 0xA0, (byte) 0x02 };
{ (byte)0xA0, (byte)0x02 };
byte[] xA003 =
{ (byte) 0xA0, (byte) 0x03 };
{ (byte)0xA0, (byte)0x03 };
byte[] xA004 =
{ (byte) 0xA0, (byte) 0x04 };
{ (byte)0xA0, (byte)0x04 };
byte[] xA005 =
{ (byte) 0xA0, (byte) 0x05 };
{ (byte)0xA0, (byte)0x05 };
byte[] xA006 =
{ (byte) 0xA0, (byte) 0x06 };
{ (byte)0xA0, (byte)0x06 };
byte[] xA007 =
{ (byte) 0xA0, (byte) 0x07 };
{ (byte)0xA0, (byte)0x07 };
byte[] xA008 =
{ (byte) 0xA0, (byte) 0x08 };
{ (byte)0xA0, (byte)0x08 };
byte[] xA009 =
{ (byte) 0xA0, (byte) 0x09 };
{ (byte)0xA0, (byte)0x09 };
byte[] xA00A =
{ (byte) 0xA0, (byte) 0x0A };
{ (byte)0xA0, (byte)0x0A };
byte[] xA00B =
{ (byte) 0xA0, (byte) 0x0B };
__headerHash.put("Content-Type", xA001);
__headerHash.put("Content-Language", xA002);
__headerHash.put("Content-Length", xA003);
__headerHash.put("Date", xA004);
__headerHash.put("Last-Modified", xA005);
__headerHash.put("Location", xA006);
__headerHash.put("Set-Cookie", xA007);
__headerHash.put("Set-Cookie2", xA008);
__headerHash.put("Servlet-Engine", xA009);
__headerHash.put("Status", xA00A);
__headerHash.put("WWW-Authenticate", xA00B);
{ (byte)0xA0, (byte)0x0B };
__headerHash.put("Content-Type",xA001);
__headerHash.put("Content-Language",xA002);
__headerHash.put("Content-Length",xA003);
__headerHash.put("Date",xA004);
__headerHash.put("Last-Modified",xA005);
__headerHash.put("Location",xA006);
__headerHash.put("Set-Cookie",xA007);
__headerHash.put("Set-Cookie2",xA008);
__headerHash.put("Servlet-Engine",xA009);
__headerHash.put("Status",xA00A);
__headerHash.put("WWW-Authenticate",xA00B);
}
@ -83,7 +83,7 @@ public class Ajp13Generator extends AbstractGenerator
// 0, 1 ajp int 1 packet length
// 9 CPONG response Code
private static final byte[] AJP13_CPONG_RESPONSE =
{ 'A', 'B', 0, 1, 9};
{ 'A', 'B', 0, 1, 9 };
private static final byte[] AJP13_END_RESPONSE =
{ 'A', 'B', 0, 2, 5, 1 };
@ -114,7 +114,7 @@ public class Ajp13Generator extends AbstractGenerator
/* ------------------------------------------------------------ */
public Ajp13Generator(Buffers buffers, EndPoint io)
{
super(buffers, io);
super(buffers,io);
}
/* ------------------------------------------------------------ */
@ -130,6 +130,7 @@ public class Ajp13Generator extends AbstractGenerator
{
return true;
}
/* ------------------------------------------------------------ */
@Override
public void reset(boolean returnBuffers)
@ -140,9 +141,7 @@ public class Ajp13Generator extends AbstractGenerator
_needMore = false;
_expectMore = false;
_bufferPrepared = false;
_last=false;
_last = false;
_state = STATE_HEADER;
@ -159,11 +158,9 @@ public class Ajp13Generator extends AbstractGenerator
_noContent = false;
_persistent = true;
_header = null; // Buffer for HTTP header (and maybe small _content)
_buffer = null; // Buffer for copy of passed _content
_content = null; // Buffer passed to addContent
_header = null; // Buffer for HTTP header (and maybe small _content)
_buffer = null; // Buffer for copy of passed _content
_content = null; // Buffer passed to addContent
}
@ -175,13 +172,13 @@ public class Ajp13Generator extends AbstractGenerator
{
initContent();
}
catch(IOException e)
catch (IOException e)
{
throw new RuntimeException(e);
}
return super.getContentBufferSize()-7;
return super.getContentBufferSize() - 7;
}
/* ------------------------------------------------------------ */
@Override
public void increaseContentBufferSize(int contentBufferSize)
@ -196,11 +193,9 @@ public class Ajp13Generator extends AbstractGenerator
* @param content
* @param last
* @throws IllegalArgumentException
* if <code>content</code> is
* {@link Buffer#isImmutable immutable}.
* if <code>content</code> is {@link Buffer#isImmutable immutable}.
* @throws IllegalStateException
* If the request is not expecting any more content, or if the
* buffers are full and cannot be flushed.
* If the request is not expecting any more content, or if the buffers are full and cannot be flushed.
* @throws IOException
* if there is a problem flushing the buffers.
*/
@ -217,13 +212,13 @@ public class Ajp13Generator extends AbstractGenerator
if (_last || _state == STATE_END)
{
LOG.debug("Ignoring extra content {}", content);
LOG.debug("Ignoring extra content {}",content);
content.clear();
return;
}
_last = last;
if(!_endp.isOpen())
if (!_endp.isOpen())
{
_state = STATE_END;
return;
@ -289,8 +284,7 @@ public class Ajp13Generator extends AbstractGenerator
if (_last || _state == STATE_END)
throw new IllegalStateException("Closed");
if(!_endp.isOpen())
if (!_endp.isOpen())
{
_state = STATE_END;
return false;
@ -322,8 +316,7 @@ public class Ajp13Generator extends AbstractGenerator
/* ------------------------------------------------------------ */
/**
* Prepare buffer for unchecked writes. Prepare the generator buffer to
* receive unchecked writes
* Prepare buffer for unchecked writes. Prepare the generator buffer to receive unchecked writes
*
* @return the available space in the buffer.
* @throws IOException
@ -337,8 +330,7 @@ public class Ajp13Generator extends AbstractGenerator
if (_last || _state == STATE_END)
throw new IllegalStateException("Closed");
if(!_endp.isOpen())
if (!_endp.isOpen())
{
_state = STATE_END;
return -1;
@ -377,8 +369,8 @@ public class Ajp13Generator extends AbstractGenerator
_last = _last | allContentAdded;
boolean has_server = false;
if (_persistent==null)
_persistent=(_version > HttpVersions.HTTP_1_0_ORDINAL);
if (_persistent == null)
_persistent = (_version > HttpVersions.HTTP_1_0_ORDINAL);
// get a header buffer
if (_header == null)
@ -390,13 +382,13 @@ public class Ajp13Generator extends AbstractGenerator
try
{
// start the header
_buffer.put((byte) 'A');
_buffer.put((byte) 'B');
_buffer.put((byte)'A');
_buffer.put((byte)'B');
addInt(0);
_buffer.put((byte) 0x4);
_buffer.put((byte)0x4);
addInt(_status);
if (_reason == null)
_reason=HttpGenerator.getReasonBuffer(_status);
_reason = HttpGenerator.getReasonBuffer(_status);
if (_reason == null)
_reason = new ByteArrayBuffer(Integer.toString(_status));
addBuffer(_reason);
@ -407,7 +399,6 @@ public class Ajp13Generator extends AbstractGenerator
_content = null;
}
// allocate 2 bytes for number of headers
int field_index = _buffer.putIndex();
addInt(0);
@ -417,15 +408,15 @@ public class Ajp13Generator extends AbstractGenerator
if (fields != null)
{
// Add headers
int s=fields.size();
for (int f=0;f<s;f++)
int s = fields.size();
for (int f = 0; f < s; f++)
{
HttpFields.Field field = fields.getField(f);
if (field==null)
if (field == null)
continue;
num_fields++;
byte[] codes = (byte[]) __headerHash.get(field.getName());
byte[] codes = (byte[])__headerHash.get(field.getName());
if (codes != null)
{
_buffer.put(codes);
@ -460,14 +451,13 @@ public class Ajp13Generator extends AbstractGenerator
// insert the total packet size on 2nd and 3rd byte that
// was previously
// allocated
addInt(2, payloadSize);
addInt(2,payloadSize);
}
finally
{
_buffer = tmpbuf;
}
_state = STATE_CONTENT;
}
@ -501,7 +491,7 @@ public class Ajp13Generator extends AbstractGenerator
{
try
{
if (_state == STATE_HEADER && !_expectMore)
if (_state == STATE_HEADER && !_expectMore)
throw new IllegalStateException("State==HEADER");
prepareBuffers();
@ -528,90 +518,87 @@ public class Ajp13Generator extends AbstractGenerator
Flushing: while (true)
{
int len = -1;
int to_flush = ((_header != null && _header.length() > 0) ? 4 : 0) | ((_buffer != null && _buffer.length() > 0) ? 2 : 0);
int to_flush = ((_header != null && _header.length() > 0)?4:0) | ((_buffer != null && _buffer.length() > 0)?2:0);
switch (to_flush)
{
case 7:
throw new IllegalStateException(); // should
// never
// happen!
case 6:
len = _endp.flush(_header, _buffer, null);
case 7:
throw new IllegalStateException(); // should
// never
// happen!
case 6:
len = _endp.flush(_header,_buffer,null);
break;
case 5:
throw new IllegalStateException(); // should
// never
// happen!
case 4:
len = _endp.flush(_header);
break;
case 3:
throw new IllegalStateException(); // should
// never
// happen!
case 2:
len = _endp.flush(_buffer);
break;
case 5:
throw new IllegalStateException(); // should
// never
// happen!
case 4:
len = _endp.flush(_header);
break;
case 3:
throw new IllegalStateException(); // should
// never
// happen!
case 2:
len = _endp.flush(_buffer);
break;
case 1:
throw new IllegalStateException(); // should
// never
// happen!
case 0:
{
// Nothing more we can write now.
if (_header != null)
_header.clear();
_bufferPrepared = false;
if (_buffer != null)
break;
case 1:
throw new IllegalStateException(); // should
// never
// happen!
case 0:
{
_buffer.clear();
// Nothing more we can write now.
if (_header != null)
_header.clear();
// reserve some space for the
// header
_buffer.setPutIndex(7);
_buffer.setGetIndex(7);
_bufferPrepared = false;
// Special case handling for
// small left over buffer from
// an addContent that caused a
// buffer flush.
if (_content != null && _content.length() < _buffer.space() && _state != STATE_FLUSHING)
if (_buffer != null)
{
_buffer.clear();
// reserve some space for the
// header
_buffer.setPutIndex(7);
_buffer.setGetIndex(7);
// Special case handling for
// small left over buffer from
// an addContent that caused a
// buffer flush.
if (_content != null && _content.length() < _buffer.space() && _state != STATE_FLUSHING)
{
_buffer.put(_content);
_content.clear();
_content = null;
break Flushing;
}
}
// Are we completely finished for now?
if (!_expectMore && !_needEOC && (_content == null || _content.length() == 0))
{
if (_state == STATE_FLUSHING)
_state = STATE_END;
// if (_state == STATE_END)
// {
// _endp.close();
// }
//
_buffer.put(_content);
_content.clear();
_content = null;
break Flushing;
}
// Try to prepare more to write.
prepareBuffers();
}
// Are we completely finished for now?
if (!_expectMore && !_needEOC && (_content == null || _content.length() == 0))
{
if (_state == STATE_FLUSHING)
_state = STATE_END;
// if (_state == STATE_END)
// {
// _endp.close();
// }
//
break Flushing;
}
// Try to prepare more to write.
prepareBuffers();
}
}
// If we failed to flush anything twice in a row
@ -631,7 +618,7 @@ public class Ajp13Generator extends AbstractGenerator
catch (IOException e)
{
LOG.ignore(e);
throw (e instanceof EofException) ? e : new EofException(e);
throw (e instanceof EofException)?e:new EofException(e);
}
}
@ -680,14 +667,14 @@ public class Ajp13Generator extends AbstractGenerator
{
_bufferPrepared = true;
_buffer.put((byte) 0);
_buffer.put((byte)0);
int put = _buffer.putIndex();
_buffer.setGetIndex(0);
_buffer.setPutIndex(0);
_buffer.put((byte) 'A');
_buffer.put((byte) 'B');
_buffer.put((byte)'A');
_buffer.put((byte)'B');
addInt(payloadSize + 4);
_buffer.put((byte) 3);
_buffer.put((byte)3);
addInt(payloadSize);
_buffer.setPutIndex(put);
}
@ -759,15 +746,15 @@ public class Ajp13Generator extends AbstractGenerator
/* ------------------------------------------------------------ */
private void addInt(int i)
{
_buffer.put((byte) ((i >> 8) & 0xFF));
_buffer.put((byte) (i & 0xFF));
_buffer.put((byte)((i >> 8) & 0xFF));
_buffer.put((byte)(i & 0xFF));
}
/* ------------------------------------------------------------ */
private void addInt(int startIndex, int i)
{
_buffer.poke(startIndex, (byte) ((i >> 8) & 0xFF));
_buffer.poke((startIndex + 1), (byte) (i & 0xFF));
_buffer.poke(startIndex,(byte)((i >> 8) & 0xFF));
_buffer.poke((startIndex + 1),(byte)(i & 0xFF));
}
/* ------------------------------------------------------------ */
@ -786,7 +773,7 @@ public class Ajp13Generator extends AbstractGenerator
addInt(b.length);
_buffer.put(b);
_buffer.put((byte) 0);
_buffer.put((byte)0);
}
/* ------------------------------------------------------------ */
@ -800,15 +787,14 @@ public class Ajp13Generator extends AbstractGenerator
addInt(b.length());
_buffer.put(b);
_buffer.put((byte) 0);
_buffer.put((byte)0);
}
/* ------------------------------------------------------------ */
public void getBodyChunk() throws IOException
{
_needMore = true;
_expectMore = true;
flushBuffer();
ByteArrayBuffer bf = new ByteArrayBuffer(AJP13_MORE_CONTENT);
_endp.flush(bf);
}
/* ------------------------------------------------------------ */
@ -818,7 +804,6 @@ public class Ajp13Generator extends AbstractGenerator
_expectMore = false;
}
/* ------------------------------------------------------------ */
public void sendCPong() throws IOException
{
@ -831,13 +816,11 @@ public class Ajp13Generator extends AbstractGenerator
{
_endp.flush(buff);
}
while(buff.length() >0);
while (buff.length() > 0);
_buffers.returnBuffer(buff);
reset(true);
}
}

View File

@ -178,10 +178,19 @@ public class HttpClient extends HttpBuffers implements Attributes, Dumpable
/* ------------------------------------------------------------ */
/**
* @return the threadPool
* @return the threadpool
*/
public ThreadPool getThreadPool()
{
if (_threadPool==null)
{
QueuedThreadPool pool = new QueuedThreadPool();
pool.setMaxThreads(16);
pool.setDaemon(true);
pool.setName("HttpClient");
_threadPool = pool;
}
return _threadPool;
}
@ -420,13 +429,7 @@ public class HttpClient extends HttpBuffers implements Attributes, Dumpable
_idleTimeoutQ.setNow();
if (_threadPool == null)
{
QueuedThreadPool pool = new QueuedThreadPool();
pool.setMaxThreads(16);
pool.setDaemon(true);
pool.setName("HttpClient");
_threadPool = pool;
}
getThreadPool();
if (_threadPool instanceof LifeCycle)
{

View File

@ -353,8 +353,23 @@ public class HttpConnection extends AbstractConnection implements Dumpable
complete = true;
}
}
// if the endpoint is closed, but the parser incomplete
if (!_endp.isOpen() && !(_parser.isComplete()||_parser.isIdle()))
{
// we wont be called again so let the parser see the close
complete=true;
_parser.parseAvailable();
if (!(_parser.isComplete()||_parser.isIdle()))
{
LOG.warn("Incomplete {} {}",_parser,_endp);
if (_exchange!=null)
_exchange.cancel();
}
}
}
/* TODO - is this needed ?
if (_generator.isComplete() && !_parser.isComplete())
{
if (!_endp.isOpen() || _endp.isInputShutdown())
@ -364,6 +379,7 @@ public class HttpConnection extends AbstractConnection implements Dumpable
close();
}
}
*/
if (complete || failed)
{
@ -433,7 +449,7 @@ public class HttpConnection extends AbstractConnection implements Dumpable
_parser.returnBuffers();
// Do we have more stuff to write?
if (!_generator.isComplete() && _generator.getBytesBuffered()>0 && _endp instanceof AsyncEndPoint)
if (!_generator.isComplete() && _generator.getBytesBuffered()>0 && _endp.isOpen() && _endp instanceof AsyncEndPoint)
{
// Assume we are write blocked!
((AsyncEndPoint)_endp).scheduleWrite();
@ -669,6 +685,9 @@ public class HttpConnection extends AbstractConnection implements Dumpable
case HttpExchange.STATUS_EXCEPTED:
case HttpExchange.STATUS_EXPIRED:
break;
case HttpExchange.STATUS_PARSING_CONTENT:
if (_endp.isInputShutdown() && _parser.isState(HttpParser.STATE_EOF_CONTENT))
break;
default:
String exch= exchange.toString();
String reason = _endp.isOpen()?(_endp.isInputShutdown()?"half closed: ":"local close: "):"closed: ";

View File

@ -584,7 +584,7 @@ public class HttpDestination implements Dumpable
@Override
public synchronized String toString()
{
return "HttpDestination@" + hashCode() + "//" + _address.getHost() + ":" + _address.getPort() + "(" + _connections.size() + "," + _idle.size() + "," + _queue.size() + ")";
return String.format("HttpDestination@%x//%s:%d(%d/%d,%d,%d/%d)%n",hashCode(),_address.getHost(),_address.getPort(),_connections.size(),_maxConnections,_idle.size(),_queue.size(),_maxQueueSize);
}
public synchronized String toDetailString()

View File

@ -35,7 +35,9 @@ import org.eclipse.jetty.util.log.Logger;
import org.eclipse.jetty.util.thread.Timeout;
/**
* <p>An HTTP client API that encapsulates an exchange (a request and its response) with a HTTP server.</p>
* <p>
* An HTTP client API that encapsulates an exchange (a request and its response) with a HTTP server.
* </p>
*
* This object encapsulates:
* <ul>
@ -48,23 +50,25 @@ import org.eclipse.jetty.util.thread.Timeout;
* <li>The ability to intercept callbacks (see {@link #setEventListener(HttpEventListener)}
* </ul>
*
* <p>The HttpExchange class is intended to be used by a developer wishing to have close asynchronous
* interaction with the the exchange.<br />
* Typically a developer will extend the HttpExchange class with a derived
* class that overrides some or all of the onXxx callbacks. <br />
* There are also some predefined HttpExchange subtypes that can be used as a basis,
* see {@link org.eclipse.jetty.client.ContentExchange} and {@link org.eclipse.jetty.client.CachedExchange}.</p>
* <p>
* The HttpExchange class is intended to be used by a developer wishing to have close asynchronous interaction with the the exchange.<br />
* Typically a developer will extend the HttpExchange class with a derived class that overrides some or all of the onXxx callbacks. <br />
* There are also some predefined HttpExchange subtypes that can be used as a basis, see {@link org.eclipse.jetty.client.ContentExchange} and
* {@link org.eclipse.jetty.client.CachedExchange}.
* </p>
*
* <p>Typically the HttpExchange is passed to the {@link HttpClient#send(HttpExchange)} method, which in
* turn selects a {@link HttpDestination} and calls its {@link HttpDestination#send(HttpExchange)}, which
* then creates or selects a {@link HttpConnection} and calls its {@link HttpConnection#send(HttpExchange)}.
* A developer may wish to directly call send on the destination or connection if they wish to bypass
* some handling provided (eg Cookie handling in the HttpDestination).</p>
* <p>
* Typically the HttpExchange is passed to the {@link HttpClient#send(HttpExchange)} method, which in turn selects a {@link HttpDestination} and calls its
* {@link HttpDestination#send(HttpExchange)}, which then creates or selects a {@link HttpConnection} and calls its {@link HttpConnection#send(HttpExchange)}. A
* developer may wish to directly call send on the destination or connection if they wish to bypass some handling provided (eg Cookie handling in the
* HttpDestination).
* </p>
*
* <p>In some circumstances, the HttpClient or HttpDestination may wish to retry a HttpExchange (eg. failed
* pipeline request, authentication retry or redirection). In such cases, the HttpClient and/or HttpDestination
* may insert their own HttpExchangeListener to intercept and filter the call backs intended for the
* HttpExchange.</p>
* <p>
* In some circumstances, the HttpClient or HttpDestination may wish to retry a HttpExchange (eg. failed pipeline request, authentication retry or redirection).
* In such cases, the HttpClient and/or HttpDestination may insert their own HttpExchangeListener to intercept and filter the call backs intended for the
* HttpExchange.
* </p>
*/
public class HttpExchange
{
@ -106,9 +110,10 @@ public class HttpExchange
// a timeout for this exchange
private long _timeout = -1;
private volatile Timeout.Task _timeoutTask;
private long _lastStateChange=-1;
private long _lastStateChange=System.currentTimeMillis();
private long _sent=-1;
private int _lastState=-1;
private int _lastStatePeriod=-1;
boolean _onRequestCompleteDone;
boolean _onResponseCompleteDone;
@ -131,8 +136,10 @@ public class HttpExchange
}
/**
* @param status the status to wait for
* @throws InterruptedException if the waiting thread is interrupted
* @param status
* the status to wait for
* @throws InterruptedException
* if the waiting thread is interrupted
* @deprecated Use {@link #waitForDone()} instead
*/
@Deprecated
@ -142,21 +149,17 @@ public class HttpExchange
}
/**
* Wait until the exchange is "done".
* Done is defined as when a final state has been passed to the
* HttpExchange via the associated onXxx call. Note that an
* exchange can transit a final state when being used as part
* of a dialog (eg {@link SecurityListener}. Done status
* is thus defined as:<pre>
* done == onConnectionFailed
* || onException
* || onExpire
* || onRequestComplete && onResponseComplete
* Wait until the exchange is "done". Done is defined as when a final state has been passed to the HttpExchange via the associated onXxx call. Note that an
* exchange can transit a final state when being used as part of a dialog (eg {@link SecurityListener}. Done status is thus defined as:
*
* <pre>
* done == onConnectionFailed || onException || onExpire || onRequestComplete &amp;&amp; onResponseComplete
* </pre>
*
* @return the done status
* @throws InterruptedException
*/
public int waitForDone () throws InterruptedException
public int waitForDone() throws InterruptedException
{
synchronized (this)
{
@ -170,12 +173,12 @@ public class HttpExchange
{
// TODO - this should do a cancel and wakeup everybody that was waiting.
// might need a version number concept
synchronized(this)
synchronized (this)
{
_timeoutTask=null;
_onRequestCompleteDone=false;
_onResponseCompleteDone=false;
_onDone=false;
_timeoutTask = null;
_onRequestCompleteDone = false;
_onResponseCompleteDone = false;
_onDone = false;
setStatus(STATUS_START);
}
}
@ -186,13 +189,16 @@ public class HttpExchange
{
int oldStatus = _status.get();
boolean set = false;
if (oldStatus!=newStatus)
if (oldStatus != newStatus)
{
_lastStateChange=System.currentTimeMillis();
long now = System.currentTimeMillis();
_lastStatePeriod=(int)(now-_lastStateChange);
_lastState=oldStatus;
_lastStateChange=now;
if (newStatus==STATUS_SENDING_REQUEST)
_sent=_lastStateChange;
}
// State machine: from which old status you can go into which new status
switch (oldStatus)
{
@ -204,7 +210,10 @@ public class HttpExchange
case STATUS_WAITING_FOR_COMMIT:
case STATUS_CANCELLING:
case STATUS_EXCEPTED:
set=_status.compareAndSet(oldStatus,newStatus);
set = _status.compareAndSet(oldStatus,newStatus);
break;
case STATUS_EXPIRED:
set = setStatusExpired(newStatus,oldStatus);
break;
}
break;
@ -214,11 +223,10 @@ public class HttpExchange
case STATUS_WAITING_FOR_COMMIT:
case STATUS_CANCELLING:
case STATUS_EXCEPTED:
set=_status.compareAndSet(oldStatus,newStatus);
set = _status.compareAndSet(oldStatus,newStatus);
break;
case STATUS_EXPIRED:
if (set=_status.compareAndSet(oldStatus,newStatus))
getEventListener().onExpire();
set = setStatusExpired(newStatus,oldStatus);
break;
}
break;
@ -228,11 +236,10 @@ public class HttpExchange
case STATUS_SENDING_REQUEST:
case STATUS_CANCELLING:
case STATUS_EXCEPTED:
set=_status.compareAndSet(oldStatus,newStatus);
set = _status.compareAndSet(oldStatus,newStatus);
break;
case STATUS_EXPIRED:
if (set=_status.compareAndSet(oldStatus,newStatus))
getEventListener().onExpire();
set = setStatusExpired(newStatus,oldStatus);
break;
}
break;
@ -240,16 +247,15 @@ public class HttpExchange
switch (newStatus)
{
case STATUS_WAITING_FOR_RESPONSE:
if (set=_status.compareAndSet(oldStatus,newStatus))
if (set = _status.compareAndSet(oldStatus,newStatus))
getEventListener().onRequestCommitted();
break;
case STATUS_CANCELLING:
case STATUS_EXCEPTED:
set=_status.compareAndSet(oldStatus,newStatus);
set = _status.compareAndSet(oldStatus,newStatus);
break;
case STATUS_EXPIRED:
if (set=_status.compareAndSet(oldStatus,newStatus))
getEventListener().onExpire();
set = setStatusExpired(newStatus,oldStatus);
break;
}
break;
@ -259,11 +265,10 @@ public class HttpExchange
case STATUS_PARSING_HEADERS:
case STATUS_CANCELLING:
case STATUS_EXCEPTED:
set=_status.compareAndSet(oldStatus,newStatus);
set = _status.compareAndSet(oldStatus,newStatus);
break;
case STATUS_EXPIRED:
if (set=_status.compareAndSet(oldStatus,newStatus))
getEventListener().onExpire();
set = setStatusExpired(newStatus,oldStatus);
break;
}
break;
@ -271,16 +276,15 @@ public class HttpExchange
switch (newStatus)
{
case STATUS_PARSING_CONTENT:
if (set=_status.compareAndSet(oldStatus,newStatus))
if (set = _status.compareAndSet(oldStatus,newStatus))
getEventListener().onResponseHeaderComplete();
break;
case STATUS_CANCELLING:
case STATUS_EXCEPTED:
set=_status.compareAndSet(oldStatus,newStatus);
set = _status.compareAndSet(oldStatus,newStatus);
break;
case STATUS_EXPIRED:
if (set=_status.compareAndSet(oldStatus,newStatus))
getEventListener().onExpire();
set = setStatusExpired(newStatus,oldStatus);
break;
}
break;
@ -288,16 +292,15 @@ public class HttpExchange
switch (newStatus)
{
case STATUS_COMPLETED:
if (set=_status.compareAndSet(oldStatus,newStatus))
if (set = _status.compareAndSet(oldStatus,newStatus))
getEventListener().onResponseComplete();
break;
case STATUS_CANCELLING:
case STATUS_EXCEPTED:
set=_status.compareAndSet(oldStatus,newStatus);
set = _status.compareAndSet(oldStatus,newStatus);
break;
case STATUS_EXPIRED:
if (set=_status.compareAndSet(oldStatus,newStatus))
getEventListener().onExpire();
set = setStatusExpired(newStatus,oldStatus);
break;
}
break;
@ -307,12 +310,12 @@ public class HttpExchange
case STATUS_START:
case STATUS_EXCEPTED:
case STATUS_WAITING_FOR_RESPONSE:
set=_status.compareAndSet(oldStatus,newStatus);
set = _status.compareAndSet(oldStatus,newStatus);
break;
case STATUS_CANCELLING:
case STATUS_EXPIRED:
// Don't change the status, it's too late
set=true;
set = true;
break;
}
break;
@ -321,12 +324,12 @@ public class HttpExchange
{
case STATUS_EXCEPTED:
case STATUS_CANCELLED:
if (set=_status.compareAndSet(oldStatus,newStatus))
if (set = _status.compareAndSet(oldStatus,newStatus))
done();
break;
default:
// Ignore other statuses, we're cancelling
set=true;
set = true;
break;
}
break;
@ -336,10 +339,10 @@ public class HttpExchange
switch (newStatus)
{
case STATUS_START:
set=_status.compareAndSet(oldStatus,newStatus);
set = _status.compareAndSet(oldStatus,newStatus);
break;
default:
set=true;
set = true;
break;
}
break;
@ -357,6 +360,14 @@ public class HttpExchange
}
}
private boolean setStatusExpired(int newStatus, int oldStatus)
{
boolean set;
if (set = _status.compareAndSet(oldStatus,newStatus))
getEventListener().onExpire();
return set;
}
public boolean isDone()
{
synchronized (this)
@ -369,7 +380,7 @@ public class HttpExchange
* @deprecated
*/
@Deprecated
public boolean isDone (int status)
public boolean isDone(int status)
{
return isDone();
}
@ -381,10 +392,10 @@ public class HttpExchange
public void setEventListener(HttpEventListener listener)
{
_listener=listener;
_listener = listener;
}
public void setTimeout( long timeout )
public void setTimeout(long timeout)
{
_timeout = timeout;
}
@ -395,7 +406,8 @@ public class HttpExchange
}
/**
* @param url an absolute URL (for example 'http://localhost/foo/bar?a=1')
* @param url
* an absolute URL (for example 'http://localhost/foo/bar?a=1')
*/
public void setURL(String url)
{
@ -403,7 +415,8 @@ public class HttpExchange
}
/**
* @param address the address of the server
* @param address
* the address of the server
*/
public void setAddress(Address address)
{
@ -421,8 +434,7 @@ public class HttpExchange
/**
* the local address used by the connection
*
* Note: this method will not be populated unless the exchange
* has been executed by the HttpClient
* Note: this method will not be populated unless the exchange has been executed by the HttpClient
*
* @return the local address used for the running of the exchange if available, null otherwise.
*/
@ -432,15 +444,17 @@ public class HttpExchange
}
/**
* @param scheme the scheme of the URL (for example 'http')
* @param scheme
* the scheme of the URL (for example 'http')
*/
public void setScheme(Buffer scheme)
{
_scheme = scheme;
}
/**
* @param scheme the scheme of the URL (for example 'http')
* @param scheme
* the scheme of the URL (for example 'http')
*/
public void setScheme(String scheme)
{
@ -464,7 +478,8 @@ public class HttpExchange
}
/**
* @param version the HTTP protocol version as integer, 9, 10 or 11 for 0.9, 1.0 or 1.1
* @param version
* the HTTP protocol version as integer, 9, 10 or 11 for 0.9, 1.0 or 1.1
*/
public void setVersion(int version)
{
@ -472,7 +487,8 @@ public class HttpExchange
}
/**
* @param version the HTTP protocol version as string
* @param version
* the HTTP protocol version as string
*/
public void setVersion(String version)
{
@ -493,7 +509,8 @@ public class HttpExchange
}
/**
* @param method the HTTP method (for example 'GET')
* @param method
* the HTTP method (for example 'GET')
*/
public void setMethod(String method)
{
@ -528,9 +545,10 @@ public class HttpExchange
}
/**
* Set the request URI
* Set the request URI
*
* @param uri new request URI
* @param uri
* new request URI
* @see #setRequestURI(String)
* @deprecated
*/
@ -541,36 +559,41 @@ public class HttpExchange
}
/**
* Set the request URI
* Set the request URI
*
* Per RFC 2616 sec5, Request-URI = "*" | absoluteURI | abs_path | authority<br/>
* where:<br/><br/>
* "*" - request applies to server itself<br/>
* where:<br/>
* <br/>
* "*" - request applies to server itself<br/>
* absoluteURI - required for proxy requests, e.g. http://localhost:8080/context<br/>
* (this form is generated automatically by HttpClient)<br/>
* abs_path - used for most methods, e.g. /context<br/>
* authority - used for CONNECT method only, e.g. localhost:8080<br/>
* (this form is generated automatically by HttpClient)<br/>
* abs_path - used for most methods, e.g. /context<br/>
* authority - used for CONNECT method only, e.g. localhost:8080<br/>
* <br/>
* For complete definition of URI components, see RFC 2396 sec3.<br/>
*
* @param uri new request URI
*
* @param uri
* new request URI
*/
public void setRequestURI(String uri)
{
_uri = uri;
}
/* ------------------------------------------------------------ */
/**
* @param uri an absolute URI (for example 'http://localhost/foo/bar?a=1')
* @param uri
* an absolute URI (for example 'http://localhost/foo/bar?a=1')
*/
public void setURI(URI uri)
{
if (!uri.isAbsolute())
throw new IllegalArgumentException("!Absolute URI: "+uri);
throw new IllegalArgumentException("!Absolute URI: " + uri);
if (uri.isOpaque())
throw new IllegalArgumentException("Opaque URI: "+uri);
throw new IllegalArgumentException("Opaque URI: " + uri);
LOG.debug("URI = {}",uri.toASCIIString());
String scheme = uri.getScheme();
int port = uri.getPort();
@ -582,13 +605,16 @@ public class HttpExchange
HttpURI httpUri = new HttpURI(uri);
String completePath = httpUri.getCompletePath();
setRequestURI(completePath==null ? "/" : completePath);
setRequestURI(completePath == null?"/":completePath);
}
/**
* Adds the specified request header
* @param name the header name
* @param value the header value
*
* @param name
* the header name
* @param value
* the header value
*/
public void addRequestHeader(String name, String value)
{
@ -597,8 +623,11 @@ public class HttpExchange
/**
* Adds the specified request header
* @param name the header name
* @param value the header value
*
* @param name
* the header name
* @param value
* the header value
*/
public void addRequestHeader(Buffer name, Buffer value)
{
@ -607,30 +636,37 @@ public class HttpExchange
/**
* Sets the specified request header
* @param name the header name
* @param value the header value
*
* @param name
* the header name
* @param value
* the header value
*/
public void setRequestHeader(String name, String value)
{
getRequestFields().put(name, value);
getRequestFields().put(name,value);
}
/**
* Sets the specified request header
* @param name the header name
* @param value the header value
*
* @param name
* the header name
* @param value
* the header value
*/
public void setRequestHeader(Buffer name, Buffer value)
{
getRequestFields().put(name, value);
getRequestFields().put(name,value);
}
/**
* @param value the content type of the request
* @param value
* the content type of the request
*/
public void setRequestContentType(String value)
{
getRequestFields().put(HttpHeaders.CONTENT_TYPE_BUFFER, value);
getRequestFields().put(HttpHeaders.CONTENT_TYPE_BUFFER,value);
}
/**
@ -642,7 +678,8 @@ public class HttpExchange
}
/**
* @param requestContent the request content
* @param requestContent
* the request content
*/
public void setRequestContent(Buffer requestContent)
{
@ -650,7 +687,8 @@ public class HttpExchange
}
/**
* @param stream the request content as a stream
* @param stream
* the request content as a stream
*/
public void setRequestContentSource(InputStream stream)
{
@ -708,7 +746,8 @@ public class HttpExchange
}
/**
* @param retryStatus whether a retry will be attempted or not
* @param retryStatus
* whether a retry will be attempted or not
*/
public void setRetryStatus(boolean retryStatus)
{
@ -716,13 +755,10 @@ public class HttpExchange
}
/**
* Initiates the cancelling of this exchange.
* The status of the exchange is set to {@link #STATUS_CANCELLING}.
* Cancelling the exchange is an asynchronous operation with respect to the request/response,
* and as such checking the request/response status of a cancelled exchange may return undefined results
* (for example it may have only some of the response headers being sent by the server).
* The cancelling of the exchange is completed when the exchange status (see {@link #getStatus()}) is
* {@link #STATUS_CANCELLED}, and this can be waited using {@link #waitForDone()}.
* Initiates the cancelling of this exchange. The status of the exchange is set to {@link #STATUS_CANCELLING}. Cancelling the exchange is an asynchronous
* operation with respect to the request/response, and as such checking the request/response status of a cancelled exchange may return undefined results
* (for example it may have only some of the response headers being sent by the server). The cancelling of the exchange is completed when the exchange
* status (see {@link #getStatus()}) is {@link #STATUS_CANCELLED}, and this can be waited using {@link #waitForDone()}.
*/
public void cancel()
{
@ -732,10 +768,10 @@ public class HttpExchange
private void done()
{
synchronized(this)
synchronized (this)
{
disassociate();
_onDone=true;
_onDone = true;
notifyAll();
}
}
@ -764,8 +800,8 @@ public class HttpExchange
void associate(HttpConnection connection)
{
if (connection.getEndPoint().getLocalHost() != null)
_localAddress = new Address(connection.getEndPoint().getLocalHost(), connection.getEndPoint().getLocalPort());
if (connection.getEndPoint().getLocalHost() != null)
_localAddress = new Address(connection.getEndPoint().getLocalHost(),connection.getEndPoint().getLocalPort());
_connection = connection;
if (getStatus() == STATUS_CANCELLING)
@ -789,33 +825,60 @@ public class HttpExchange
public static String toState(int s)
{
String state;
switch(s)
switch (s)
{
case STATUS_START: state="START"; break;
case STATUS_WAITING_FOR_CONNECTION: state="CONNECTING"; break;
case STATUS_WAITING_FOR_COMMIT: state="CONNECTED"; break;
case STATUS_SENDING_REQUEST: state="SENDING"; break;
case STATUS_WAITING_FOR_RESPONSE: state="WAITING"; break;
case STATUS_PARSING_HEADERS: state="HEADERS"; break;
case STATUS_PARSING_CONTENT: state="CONTENT"; break;
case STATUS_COMPLETED: state="COMPLETED"; break;
case STATUS_EXPIRED: state="EXPIRED"; break;
case STATUS_EXCEPTED: state="EXCEPTED"; break;
case STATUS_CANCELLING: state="CANCELLING"; break;
case STATUS_CANCELLED: state="CANCELLED"; break;
default: state="UNKNOWN";
case STATUS_START:
state = "START";
break;
case STATUS_WAITING_FOR_CONNECTION:
state = "CONNECTING";
break;
case STATUS_WAITING_FOR_COMMIT:
state = "CONNECTED";
break;
case STATUS_SENDING_REQUEST:
state = "SENDING";
break;
case STATUS_WAITING_FOR_RESPONSE:
state = "WAITING";
break;
case STATUS_PARSING_HEADERS:
state = "HEADERS";
break;
case STATUS_PARSING_CONTENT:
state = "CONTENT";
break;
case STATUS_COMPLETED:
state = "COMPLETED";
break;
case STATUS_EXPIRED:
state = "EXPIRED";
break;
case STATUS_EXCEPTED:
state = "EXCEPTED";
break;
case STATUS_CANCELLING:
state = "CANCELLING";
break;
case STATUS_CANCELLED:
state = "CANCELLED";
break;
default:
state = "UNKNOWN";
}
return state;
}
@Override
public String toString()
{
String state=toState(getStatus());
long now=System.currentTimeMillis();
long forMs = now -_lastStateChange;
String s= String.format("%s@%x=%s//%s%s#%s(%dms)",getClass().getSimpleName(),hashCode(),_method,_address,_uri,state,forMs);
if (getStatus()>=STATUS_SENDING_REQUEST)
String s= _lastState>=0
?String.format("%s@%x=%s//%s%s#%s(%dms)->%s(%dms)",getClass().getSimpleName(),hashCode(),_method,_address,_uri,toState(_lastState),_lastStatePeriod,state,forMs)
:String.format("%s@%x=%s//%s%s#%s(%dms)",getClass().getSimpleName(),hashCode(),_method,_address,_uri,state,forMs);
if (getStatus()>=STATUS_SENDING_REQUEST && _sent>0)
s+="sent="+(now-_sent)+"ms";
return s;
}
@ -828,79 +891,93 @@ public class HttpExchange
}
/**
* Callback called when the request headers have been sent to the server.
* This implementation does nothing.
* @throws IOException allowed to be thrown by overriding code
* Callback called when the request headers have been sent to the server. This implementation does nothing.
*
* @throws IOException
* allowed to be thrown by overriding code
*/
protected void onRequestCommitted() throws IOException
{
}
/**
* Callback called when the request and its body have been sent to the server.
* This implementation does nothing.
* @throws IOException allowed to be thrown by overriding code
* Callback called when the request and its body have been sent to the server. This implementation does nothing.
*
* @throws IOException
* allowed to be thrown by overriding code
*/
protected void onRequestComplete() throws IOException
{
}
/**
* Callback called when a response status line has been received from the server.
* This implementation does nothing.
* @param version the HTTP version
* @param status the HTTP status code
* @param reason the HTTP status reason string
* @throws IOException allowed to be thrown by overriding code
* Callback called when a response status line has been received from the server. This implementation does nothing.
*
* @param version
* the HTTP version
* @param status
* the HTTP status code
* @param reason
* the HTTP status reason string
* @throws IOException
* allowed to be thrown by overriding code
*/
protected void onResponseStatus(Buffer version, int status, Buffer reason) throws IOException
{
}
/**
* Callback called for each response header received from the server.
* This implementation does nothing.
* @param name the header name
* @param value the header value
* @throws IOException allowed to be thrown by overriding code
* Callback called for each response header received from the server. This implementation does nothing.
*
* @param name
* the header name
* @param value
* the header value
* @throws IOException
* allowed to be thrown by overriding code
*/
protected void onResponseHeader(Buffer name, Buffer value) throws IOException
{
}
/**
* Callback called when the response headers have been completely received from the server.
* This implementation does nothing.
* @throws IOException allowed to be thrown by overriding code
* Callback called when the response headers have been completely received from the server. This implementation does nothing.
*
* @throws IOException
* allowed to be thrown by overriding code
*/
protected void onResponseHeaderComplete() throws IOException
{
}
/**
* Callback called for each chunk of the response content received from the server.
* This implementation does nothing.
* @param content the buffer holding the content chunk
* @throws IOException allowed to be thrown by overriding code
* Callback called for each chunk of the response content received from the server. This implementation does nothing.
*
* @param content
* the buffer holding the content chunk
* @throws IOException
* allowed to be thrown by overriding code
*/
protected void onResponseContent(Buffer content) throws IOException
{
}
/**
* Callback called when the entire response has been received from the server
* This implementation does nothing.
* @throws IOException allowed to be thrown by overriding code
* Callback called when the entire response has been received from the server This implementation does nothing.
*
* @throws IOException
* allowed to be thrown by overriding code
*/
protected void onResponseComplete() throws IOException
{
}
/**
* Callback called when an exception was thrown during an attempt to establish the connection
* with the server (for example the server is not listening).
* Callback called when an exception was thrown during an attempt to establish the connection with the server (for example the server is not listening).
* This implementation logs a warning.
* @param x the exception thrown attempting to establish the connection with the server
*
* @param x
* the exception thrown attempting to establish the connection with the server
*/
protected void onConnectionFailed(Throwable x)
{
@ -908,9 +985,10 @@ public class HttpExchange
}
/**
* Callback called when any other exception occurs during the handling of this exchange.
* This implementation logs a warning.
* @param x the exception thrown during the handling of this exchange
* Callback called when any other exception occurs during the handling of this exchange. This implementation logs a warning.
*
* @param x
* the exception thrown during the handling of this exchange
*/
protected void onException(Throwable x)
{
@ -918,8 +996,7 @@ public class HttpExchange
}
/**
* Callback called when no response has been received within the timeout.
* This implementation logs a warning.
* Callback called when no response has been received within the timeout. This implementation logs a warning.
*/
protected void onExpire()
{
@ -927,9 +1004,10 @@ public class HttpExchange
}
/**
* Callback called when the request is retried (due to failures or authentication).
* Implementations must reset any consumable content that needs to be sent.
* @throws IOException allowed to be thrown by overriding code
* Callback called when the request is retried (due to failures or authentication). Implementations must reset any consumable content that needs to be sent.
*
* @throws IOException
* allowed to be thrown by overriding code
*/
protected void onRetry() throws IOException
{
@ -948,8 +1026,7 @@ public class HttpExchange
}
/**
* @return true if the exchange should have listeners configured for it by the destination,
* false if this is being managed elsewhere
* @return true if the exchange should have listeners configured for it by the destination, false if this is being managed elsewhere
* @see #setConfigureListeners(boolean)
*/
public boolean configureListeners()
@ -958,7 +1035,8 @@ public class HttpExchange
}
/**
* @param autoConfigure whether the listeners are configured by the destination or elsewhere
* @param autoConfigure
* whether the listeners are configured by the destination or elsewhere
*/
public void setConfigureListeners(boolean autoConfigure)
{
@ -981,7 +1059,7 @@ public class HttpExchange
HttpClient httpClient = destination.getHttpClient();
long timeout = getTimeout();
if (timeout > 0)
httpClient.schedule(_timeoutTask, timeout);
httpClient.schedule(_timeoutTask,timeout);
else
httpClient.schedule(_timeoutTask);
}
@ -1045,7 +1123,7 @@ public class HttpExchange
}
finally
{
synchronized(HttpExchange.this)
synchronized (HttpExchange.this)
{
_onRequestCompleteDone = true;
// Member _onDone may already be true, for example
@ -1066,7 +1144,7 @@ public class HttpExchange
}
finally
{
synchronized(HttpExchange.this)
synchronized (HttpExchange.this)
{
_onResponseCompleteDone = true;
// Member _onDone may already be true, for example
@ -1101,7 +1179,7 @@ public class HttpExchange
public void onRetry()
{
HttpExchange.this.setRetryStatus( true );
HttpExchange.this.setRetryStatus(true);
try
{
HttpExchange.this.onRetry();

View File

@ -110,25 +110,49 @@ public class RedirectListener extends HttpEventListenerWrapper
if (_location != null)
{
if (_location.indexOf("://")>0)
{
_exchange.setURL(_location);
}
else
{
_exchange.setRequestURI(_location);
}
// destination may have changed
HttpDestination destination=_destination.getHttpClient().getDestination(_exchange.getAddress(),HttpSchemes.HTTPS.equals(String.valueOf(_exchange.getScheme())));
boolean isHttps = HttpSchemes.HTTPS.equals(String.valueOf(_exchange.getScheme()));
HttpDestination destination=_destination.getHttpClient().getDestination(_exchange.getAddress(),isHttps);
if (_destination==destination)
{
_destination.resend(_exchange);
}
else
{
// unwrap to find ultimate listener.
HttpEventListener listener=this;
while(listener instanceof HttpEventListenerWrapper)
{
listener=((HttpEventListenerWrapper)listener).getEventListener();
}
//reset the listener
_exchange.getEventListener().onRetry();
_exchange.reset();
_exchange.setEventListener(listener);
// Set the new Host header
Address address = _exchange.getAddress();
int port = address.getPort();
StringBuilder hostHeader = new StringBuilder( 64 );
hostHeader.append( address.getHost() );
if( !( ( port == 80 && !isHttps ) || ( port == 443 && isHttps ) ) )
{
hostHeader.append( ':' );
hostHeader.append( port );
}
_exchange.setRequestHeader( HttpHeaders.HOST, hostHeader.toString() );
destination.send(_exchange);
}
@ -156,5 +180,28 @@ public class RedirectListener extends HttpEventListenerWrapper
super.onRetry();
}
}
/**
* Delegate failed connection
*/
@Override
public void onConnectionFailed( Throwable ex )
{
setDelegatingRequests(true);
setDelegatingResponses(true);
super.onConnectionFailed( ex );
}
/**
* Delegate onException
*/
@Override
public void onException( Throwable ex )
{
setDelegatingRequests(true);
setDelegatingResponses(true);
super.onException( ex );
}
}

View File

@ -15,10 +15,13 @@ package org.eclipse.jetty.client;
import java.io.IOException;
import java.net.SocketTimeoutException;
import java.net.UnknownHostException;
import java.nio.channels.SelectionKey;
import java.nio.channels.SocketChannel;
import java.nio.channels.UnresolvedAddressException;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLEngine;
import javax.net.ssl.SSLSession;
@ -48,7 +51,6 @@ class SelectConnector extends AbstractLifeCycle implements HttpClient.Connector
private final HttpClient _httpClient;
private final Manager _selectorManager=new Manager();
private final Map<SocketChannel, Timeout.Task> _connectingChannels = new ConcurrentHashMap<SocketChannel, Timeout.Task>();
private SSLContext _sslContext;
private Buffers _sslBuffers;
/**
@ -89,31 +91,34 @@ class SelectConnector extends AbstractLifeCycle implements HttpClient.Connector
public void startConnection( HttpDestination destination )
throws IOException
{
SocketChannel channel = null;
try
{
SocketChannel channel = SocketChannel.open();
channel = SocketChannel.open();
Address address = destination.isProxied() ? destination.getProxy() : destination.getAddress();
channel.socket().setTcpNoDelay(true);
if (_httpClient.isConnectBlocking())
{
channel.socket().connect(address.toSocketAddress(), _httpClient.getConnectTimeout());
channel.configureBlocking(false);
_selectorManager.register( channel, destination );
channel.socket().connect(address.toSocketAddress(), _httpClient.getConnectTimeout());
channel.configureBlocking(false);
_selectorManager.register( channel, destination );
}
else
{
channel.configureBlocking( false );
channel.connect(address.toSocketAddress());
_selectorManager.register( channel, destination );
ConnectTimeout connectTimeout = new ConnectTimeout(channel, destination);
channel.configureBlocking(false);
channel.connect(address.toSocketAddress());
_selectorManager.register(channel,destination);
ConnectTimeout connectTimeout = new ConnectTimeout(channel,destination);
_httpClient.schedule(connectTimeout,_httpClient.getConnectTimeout());
_connectingChannels.put(channel, connectTimeout);
_connectingChannels.put(channel,connectTimeout);
}
}
catch(IOException ex)
{
if (channel != null)
channel.close();
destination.onConnectionFailed(ex);
}
}
@ -194,19 +199,16 @@ class SelectConnector extends AbstractLifeCycle implements HttpClient.Connector
private synchronized SSLEngine newSslEngine(SocketChannel channel) throws IOException
{
SslContextFactory sslContextFactory = _httpClient.getSslContextFactory();
if (_sslContext == null)
_sslContext = sslContextFactory.getSslContext();
SSLEngine sslEngine;
if (channel != null && sslContextFactory.isSessionCachingEnabled())
if (channel != null)
{
String peerHost = channel.socket().getInetAddress().getHostAddress();
int peerPort = channel.socket().getPort();
sslEngine = _sslContext.createSSLEngine(peerHost, peerPort);
sslEngine = sslContextFactory.newSslEngine(peerHost, peerPort);
}
else
{
sslEngine = _sslContext.createSSLEngine();
sslEngine = sslContextFactory.newSslEngine();
}
sslEngine.setUseClientMode(true);
sslEngine.beginHandshake();

View File

@ -45,18 +45,9 @@ class SocketConnector extends AbstractLifeCycle implements HttpClient.Connector
public void startConnection(final HttpDestination destination) throws IOException
{
Socket socket=null;
if ( destination.isSecure() )
{
SSLContext sslContext = _httpClient.getSSLContext();
socket = sslContext.getSocketFactory().createSocket();
}
else
{
LOG.debug("Using Regular Socket");
socket = SocketFactory.getDefault().createSocket();
}
Socket socket= destination.isSecure()
?_httpClient.getSslContextFactory().newSslSocket()
:SocketFactory.getDefault().createSocket();
socket.setSoTimeout(0);
socket.setTcpNoDelay(true);
@ -97,6 +88,17 @@ class SocketConnector extends AbstractLifeCycle implements HttpClient.Connector
destination.onException(e);
}
}
finally
{
try
{
destination.returnConnection(connection,true);
}
catch (IOException e)
{
LOG.debug(e);
}
}
}
});

View File

@ -14,9 +14,7 @@
package org.eclipse.jetty.client;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.*;
import java.io.IOException;
import java.net.SocketTimeoutException;
@ -34,7 +32,6 @@ import org.eclipse.jetty.server.Server;
import org.eclipse.jetty.server.handler.AbstractHandler;
import org.eclipse.jetty.server.nio.SelectChannelConnector;
import org.eclipse.jetty.util.log.Log;
import org.eclipse.jetty.util.log.Logger;
import org.eclipse.jetty.util.log.StdErrLog;
import org.junit.After;
import org.junit.Before;
@ -45,8 +42,6 @@ import org.junit.Test;
*/
public abstract class AbstractHttpExchangeCancelTest
{
private static final Logger LOG = Log.getLogger(AbstractHttpExchangeCancelTest.class);
private Server server;
private Connector connector;

View File

@ -13,19 +13,31 @@
package org.eclipse.jetty.client;
import org.eclipse.jetty.client.helperClasses.AsyncSslServerAndClientCreator;
import org.eclipse.jetty.client.helperClasses.ServerAndClientCreator;
import org.junit.Before;
import org.junit.BeforeClass;
import org.junit.Test;
public class AsyncSslHttpExchangeTest extends SslHttpExchangeTest
{
@Override
public void setUp() throws Exception
private static ServerAndClientCreator serverAndClientCreator = new AsyncSslServerAndClientCreator();
@Before
public void setUpOnce() throws Exception
{
_scheme="https";
startServer();
_httpClient=new HttpClient();
_httpClient.setIdleTimeout(2000);
_httpClient.setTimeout(2500);
_httpClient.setConnectTimeout(1000);
_httpClient.setConnectorType(HttpClient.CONNECTOR_SELECT_CHANNEL);
_httpClient.setMaxConnectionsPerAddress(2);
_httpClient.start();
_server = serverAndClientCreator.createServer();
_httpClient = serverAndClientCreator.createClient(3000L,3500L,2000);
_port = _server.getConnectors()[0].getLocalPort();
}
@Test
public void testPerf1() throws Exception
{
sender(10,true);
}
}

View File

@ -13,28 +13,23 @@
package org.eclipse.jetty.client;
import java.io.FileInputStream;
import org.eclipse.jetty.toolchain.test.MavenTestingUtils;
import org.eclipse.jetty.client.helperClasses.ExternalKeyStoreAsyncSslServerAndClientCreator;
import org.eclipse.jetty.client.helperClasses.ServerAndClientCreator;
import org.junit.Before;
import org.junit.BeforeClass;
import org.junit.Test;
public class ExternalKeyStoreAsyncSslHttpExchangeTest extends SslHttpExchangeTest
{
@Override
public void setUp() throws Exception
private static ServerAndClientCreator serverAndClientCreator = new ExternalKeyStoreAsyncSslServerAndClientCreator();
@Before
public void setUpOnce() throws Exception
{
_scheme = "https";
startServer();
_httpClient = new HttpClient();
_httpClient.setConnectorType(HttpClient.CONNECTOR_SELECT_CHANNEL);
_httpClient.setMaxConnectionsPerAddress(2);
String keystore = MavenTestingUtils.getTestResourceFile("keystore").getAbsolutePath();
_httpClient.setKeyStoreInputStream(new FileInputStream(keystore));
_httpClient.setKeyStorePassword("storepwd");
_httpClient.setKeyManagerPassword("keypwd");
_httpClient.start();
_scheme="https";
_server = serverAndClientCreator.createServer();
_httpClient = serverAndClientCreator.createClient(3000L,3500L,2000);
_port = _server.getConnectors()[0].getLocalPort();
}
@Override

View File

@ -0,0 +1,29 @@
package org.eclipse.jetty.client;
import java.util.Collections;
import java.util.List;
import org.eclipse.jetty.http.HttpFields;
import org.junit.Assert;
public final class HttpAsserts
{
public static void assertContainsHeaderKey(String expectedKey, HttpFields headers)
{
if (headers.containsKey(expectedKey))
{
return;
}
List<String> names = Collections.list(headers.getFieldNames());
StringBuilder err = new StringBuilder();
err.append("Missing expected header key [").append(expectedKey);
err.append("] (of ").append(names.size()).append(" header fields)");
for (int i = 0; i < names.size(); i++)
{
String value = headers.getStringField(names.get(i));
err.append("\n").append(i).append("] ").append(names.get(i));
err.append(": ").append(value);
}
Assert.fail(err.toString());
}
}

View File

@ -13,14 +13,9 @@
package org.eclipse.jetty.client;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertThat;
import static org.junit.Assert.assertTrue;
import static org.junit.matchers.JUnitMatchers.containsString;
import static org.junit.Assert.*;
import static org.junit.matchers.JUnitMatchers.*;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
@ -30,13 +25,10 @@ import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.atomic.AtomicReference;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.eclipse.jetty.client.helperClasses.HttpServerAndClientCreator;
import org.eclipse.jetty.client.helperClasses.ServerAndClientCreator;
import org.eclipse.jetty.client.security.ProxyAuthorization;
import org.eclipse.jetty.http.HttpFields;
import org.eclipse.jetty.http.HttpHeaders;
import org.eclipse.jetty.http.HttpMethods;
import org.eclipse.jetty.http.HttpStatus;
import org.eclipse.jetty.io.Buffer;
@ -44,17 +36,13 @@ import org.eclipse.jetty.io.ByteArrayBuffer;
import org.eclipse.jetty.io.Connection;
import org.eclipse.jetty.io.EofException;
import org.eclipse.jetty.io.nio.DirectNIOBuffer;
import org.eclipse.jetty.server.Connector;
import org.eclipse.jetty.server.Request;
import org.eclipse.jetty.server.Server;
import org.eclipse.jetty.server.handler.AbstractHandler;
import org.eclipse.jetty.server.nio.SelectChannelConnector;
import org.eclipse.jetty.toolchain.test.Stress;
import org.eclipse.jetty.util.IO;
import org.eclipse.jetty.util.log.Log;
import org.eclipse.jetty.util.log.Logger;
import org.eclipse.jetty.util.component.AbstractLifeCycle;
import org.junit.After;
import org.junit.AfterClass;
import org.junit.Before;
import org.junit.BeforeClass;
import org.junit.Test;
/* ------------------------------------------------------------ */
@ -63,37 +51,44 @@ import org.junit.Test;
*/
public class HttpExchangeTest
{
private static final Logger LOG = Log.getLogger(HttpExchangeTest.class);
protected int _maxConnectionsPerAddress = 2;
protected String _scheme = "http";
protected Server _server;
protected int _port;
protected HttpClient _httpClient;
protected Connector _connector;
protected AtomicInteger _count = new AtomicInteger();
final static boolean verbose=false;
protected static int _maxConnectionsPerAddress = 2;
protected static String _scheme = "http";
protected static Server _server;
protected static int _port;
protected static HttpClient _httpClient;
protected static AtomicInteger _count = new AtomicInteger();
protected static ServerAndClientCreator serverAndClientCreator = new HttpServerAndClientCreator();
protected static URI getBaseURI()
{
return URI.create(_scheme + "://localhost:" + _port + "/");
}
/* ------------------------------------------------------------ */
// TODO work out why BeforeClass does not work here?
@Before
public void setUp() throws Exception
public void setUpOnce() throws Exception
{
startServer();
_httpClient=new HttpClient();
_httpClient.setIdleTimeout(3000);
_httpClient.setTimeout(3500);
_httpClient.setConnectTimeout(2000);
_httpClient.setConnectorType(HttpClient.CONNECTOR_SELECT_CHANNEL);
_httpClient.setMaxConnectionsPerAddress(_maxConnectionsPerAddress);
_httpClient.start();
_scheme = "http";
_server = serverAndClientCreator.createServer();
_httpClient = serverAndClientCreator.createClient(3000L,3500L,2000);
_port = _server.getConnectors()[0].getLocalPort();
}
/* ------------------------------------------------------------ */
@After
public void tearDown() throws Exception
public void tearDownOnce() throws Exception
{
_httpClient.stop();
Thread.sleep(500);
stopServer();
long startTime = System.currentTimeMillis();
while (!_httpClient.getState().equals(AbstractLifeCycle.STOPPED))
{
if (System.currentTimeMillis() - startTime > 1000)
break;
Thread.sleep(5);
}
_server.stop();
}
/* ------------------------------------------------------------ */
@ -110,7 +105,9 @@ public class HttpExchangeTest
{
sender(1,false);
sender(1,true);
sender(10,false);
sender(10,true);
if (Stress.isEnabled())
{
sender(100,false);
@ -118,67 +115,72 @@ public class HttpExchangeTest
sender(10000,false);
sender(10000,true);
}
else
{
sender(10,false);
sender(10,true);
}
}
/* ------------------------------------------------------------ */
/**
* Test sending data through the exchange.
*
*
* @throws IOException
*/
public void sender(final int nb,final boolean close) throws Exception
public void sender(final int nb, final boolean close) throws Exception
{
_count.set(0);
final CountDownLatch complete=new CountDownLatch(nb);
final CountDownLatch latch=new CountDownLatch(nb);
final CountDownLatch complete = new CountDownLatch(nb);
final AtomicInteger allcontent = new AtomicInteger(nb);
HttpExchange[] httpExchange = new HttpExchange[nb];
long start=System.currentTimeMillis();
for (int i=0; i<nb; i++)
long start = System.currentTimeMillis();
for (int i = 0; i < nb; i++)
{
final int n=i;
final int n = i;
httpExchange[n]=new HttpExchange()
httpExchange[n] = new HttpExchange()
{
String result="pending";
int len=0;
String result = "pending";
int len = 0;
/* ------------------------------------------------------------ */
@Override
protected void onRequestCommitted()
{
result="committed";
if (verbose)
System.err.println("[ ");
result = "committed";
}
/* ------------------------------------------------------------ */
@Override
protected void onRequestComplete() throws IOException
{
result="sent";
if (verbose)
System.err.println("[ ==");
result = "sent";
}
@Override
/* ------------------------------------------------------------ */
protected void onResponseStatus(Buffer version, int status, Buffer reason)
{
result="status";
if (verbose)
System.err.println("] "+version+" "+status+" "+reason);
result = "status";
}
/* ------------------------------------------------------------ */
@Override
protected void onResponseHeader(Buffer name, Buffer value)
{
if (verbose)
System.err.println("] "+name+": "+value);
}
/* ------------------------------------------------------------ */
@Override
protected void onResponseHeaderComplete() throws IOException
{
result="content";
if (verbose)
System.err.println("] -");
result = "content";
super.onResponseHeaderComplete();
}
@ -186,20 +188,22 @@ public class HttpExchangeTest
@Override
protected void onResponseContent(Buffer content)
{
len+=content.length();
len += content.length();
if (verbose)
System.err.println("] "+content.length()+" -> "+len);
}
/* ------------------------------------------------------------ */
@Override
protected void onResponseComplete()
{
result="complete";
if (len==2009)
latch.countDown();
if (verbose)
System.err.println("] == "+len+" "+complete.getCount()+"/"+nb);
result = "complete";
if (len == 2009)
allcontent.decrementAndGet();
else
{
System.err.println(n+" ONLY "+len);
}
System.err.println(n + " ONLY " + len+ "/2009");
complete.countDown();
}
@ -207,9 +211,11 @@ public class HttpExchangeTest
@Override
protected void onConnectionFailed(Throwable ex)
{
if (verbose)
System.err.println("] "+ex);
complete.countDown();
result="failed";
System.err.println(n+" FAILED "+ex);
result = "failed";
System.err.println(n + " FAILED " + ex);
super.onConnectionFailed(ex);
}
@ -217,9 +223,11 @@ public class HttpExchangeTest
@Override
protected void onException(Throwable ex)
{
if (verbose)
System.err.println("] "+ex);
complete.countDown();
result="excepted";
System.err.println(n+" EXCEPTED "+ex);
result = "excepted";
System.err.println(n + " EXCEPTED " + ex);
super.onException(ex);
}
@ -227,9 +235,11 @@ public class HttpExchangeTest
@Override
protected void onExpire()
{
if (verbose)
System.err.println("] expired");
complete.countDown();
result="expired";
System.err.println(n+" EXPIRED "+len);
result = "expired";
System.err.println(n + " EXPIRED " + len);
super.onExpire();
}
@ -237,29 +247,24 @@ public class HttpExchangeTest
@Override
public String toString()
{
return n+" "+result+" "+len;
return n+"/"+result+"/"+len+"/"+super.toString();
}
};
httpExchange[n].setURL(_scheme+"://localhost:"+_port+"/"+n);
httpExchange[n].setURI(getBaseURI().resolve("/" + n));
httpExchange[n].addRequestHeader("arbitrary","value");
if (close)
httpExchange[n].setRequestHeader("Connection","close");
_httpClient.send(httpExchange[n]);
}
assertTrue(complete.await(45,TimeUnit.SECONDS));
long elapsed=System.currentTimeMillis()-start;
// make windows-friendly ... System.currentTimeMillis() on windows is dope!
/*
if(elapsed>0)
System.err.println(nb+"/"+_count+" c="+close+" rate="+(nb*1000/elapsed));
*/
if (!complete.await(2,TimeUnit.SECONDS))
System.err.println(_httpClient.dump());
assertEquals("nb="+nb+" close="+close,0,latch.getCount());
assertTrue(complete.await(20,TimeUnit.SECONDS));
assertEquals("nb="+nb+" close="+close,0,allcontent.get());
}
/* ------------------------------------------------------------ */
@ -269,7 +274,7 @@ public class HttpExchangeTest
for (int i=0;i<20;i++)
{
ContentExchange httpExchange=new ContentExchange();
httpExchange.setURI(new URI(_scheme, null, "localhost", _port, null, null, null));
httpExchange.setURI(getBaseURI());
httpExchange.setMethod(HttpMethods.POST);
httpExchange.setRequestContent(new ByteArrayBuffer("<hello />"));
_httpClient.send(httpExchange);
@ -288,12 +293,14 @@ public class HttpExchangeTest
for (int i=0;i<10;i++)
{
ContentExchange httpExchange=new ContentExchange();
httpExchange.setURI(new URI(_scheme, null, "localhost", _port, "/", "i="+i, null));
URI uri = getBaseURI().resolve("?i=" + i);
httpExchange.setURI(uri);
httpExchange.setMethod(HttpMethods.GET);
_httpClient.send(httpExchange);
int status = httpExchange.waitForDone();
//httpExchange.waitForStatus(HttpExchange.STATUS_COMPLETED);
String result=httpExchange.getResponseContent();
assertNotNull("Should have received response content", result);
assertEquals("i="+i,0,result.indexOf("<hello>"));
assertEquals("i="+i,result.length()-10,result.indexOf("</hello>"));
assertEquals(HttpExchange.STATUS_COMPLETED, status);
@ -308,17 +315,16 @@ public class HttpExchangeTest
for (int i=0;i<10;i++)
{
ContentExchange httpExchange=new ContentExchange();
httpExchange.setURL(_scheme+"://localhost:"+_port+"/?i="+i);
URI uri = getBaseURI().resolve("?i=" + i);
httpExchange.setURI(uri);
httpExchange.setMethod(HttpMethods.GET);
_httpClient.send(httpExchange);
int status = httpExchange.waitForDone();
assertNotNull(httpExchange.getLocalAddress());
//System.out.println("Local Address: " + httpExchange.getLocalAddress());
//httpExchange.waitForStatus(HttpExchange.STATUS_COMPLETED);
String result=httpExchange.getResponseContent();
assertNotNull("Should have received response content", result);
assertEquals("i="+i,0,result.indexOf("<hello>"));
assertEquals("i="+i,result.length()-10,result.indexOf("</hello>"));
assertEquals(HttpExchange.STATUS_COMPLETED, status);
@ -355,7 +361,7 @@ public class HttpExchangeTest
throwable.set(x);
}
};
httpExchange.setURL(_scheme+"://localhost:"+_port+"/");
httpExchange.setURI(getBaseURI());
httpExchange.setMethod("SLEEP");
_httpClient.send(httpExchange);
new Thread()
@ -374,6 +380,7 @@ public class HttpExchangeTest
System.err.println(throwable.get());
assertTrue(throwable.get().toString().indexOf("close")>=0);
assertEquals(HttpExchange.STATUS_EXCEPTED, status);
_httpClient.start();
}
/* ------------------------------------------------------------ */
@ -381,7 +388,54 @@ public class HttpExchangeTest
public void testBigPostWithContentExchange() throws Exception
{
int size =32;
ContentExchange httpExchange=new ContentExchange();
ContentExchange httpExchange=new ContentExchange()
{
int total;
@Override
protected synchronized void onResponseStatus(Buffer version, int status, Buffer reason) throws IOException
{
if (verbose)
System.err.println("] "+version+" "+status+" "+reason);
super.onResponseStatus(version,status,reason);
}
@Override
protected synchronized void onResponseHeader(Buffer name, Buffer value) throws IOException
{
if (verbose)
System.err.println("] "+name+": "+value);
super.onResponseHeader(name,value);
}
@Override
protected synchronized void onResponseContent(Buffer content) throws IOException
{
if (verbose)
{
total+=content.length();
System.err.println("] "+content.length()+" -> "+total);
}
super.onResponseContent(content);
}
@Override
protected void onRequestComplete() throws IOException
{
if (verbose)
System.err.println("] ==");
super.onRequestComplete();
}
@Override
protected void onResponseHeaderComplete() throws IOException
{
if (verbose)
System.err.println("] --");
super.onResponseHeaderComplete();
}
};
Buffer babuf = new ByteArrayBuffer(size*36*1024);
Buffer niobuf = new DirectNIOBuffer(size*36*1024);
@ -394,28 +448,27 @@ public class HttpExchangeTest
niobuf.put(bytes);
}
httpExchange.setURL(_scheme+"://localhost:"+_port+"/");
httpExchange.setURI(getBaseURI());
httpExchange.setMethod(HttpMethods.POST);
httpExchange.setRequestContentType("application/data");
httpExchange.setRequestContent(babuf);
_httpClient.send(httpExchange);
int status = httpExchange.waitForDone();
assertEquals(HttpExchange.STATUS_COMPLETED,status);
String result=httpExchange.getResponseContent();
assertEquals(babuf.length(),result.length());
httpExchange.reset();
httpExchange.setURL(_scheme+"://localhost:"+_port+"/");
httpExchange.setURI(getBaseURI());
httpExchange.setMethod(HttpMethods.POST);
httpExchange.setRequestContentType("application/data");
httpExchange.setRequestContent(niobuf);
_httpClient.send(httpExchange);
status = httpExchange.waitForDone();
assertEquals(HttpExchange.STATUS_COMPLETED, status);
result=httpExchange.getResponseContent();
assertEquals(niobuf.length(),result.length());
assertEquals(HttpExchange.STATUS_COMPLETED, status);
}
/* ------------------------------------------------------------ */
@ -426,7 +479,7 @@ public class HttpExchangeTest
{
};
httpExchange.setURL(_scheme+"://localhost:"+_port);
httpExchange.setURI(getBaseURI());
httpExchange.setMethod(HttpMethods.POST);
final String data="012345678901234567890123456789012345678901234567890123456789";
@ -447,7 +500,7 @@ public class HttpExchangeTest
@Override
public int read(byte[] b, int off, int len) throws IOException
{
if (_index>=data.length())
if (_index >= data.length())
return -1;
try
@ -458,28 +511,28 @@ public class HttpExchangeTest
{
e.printStackTrace();
}
int l=0;
while (l<5 && _index<data.length() && l<len)
b[off+l++]=(byte)data.charAt(_index++);
int l = 0;
while (l < 5 && _index < data.length() && l < len)
b[off + l++] = (byte)data.charAt(_index++);
return l;
}
};
httpExchange.setRequestContentSource(content);
//httpExchange.setRequestContent(new ByteArrayBuffer(data));
// httpExchange.setRequestContent(new ByteArrayBuffer(data));
_httpClient.send(httpExchange);
int status = httpExchange.waitForDone();
//httpExchange.waitForStatus(HttpExchange.STATUS_COMPLETED);
String result=httpExchange.getResponseContent();
assertEquals(HttpExchange.STATUS_COMPLETED, status);
// httpExchange.waitForStatus(HttpExchange.STATUS_COMPLETED);
String result = httpExchange.getResponseContent();
assertEquals(HttpExchange.STATUS_COMPLETED,status);
assertEquals(data,result);
}
/* ------------------------------------------------------------ */
@Test
public void testProxy() throws Exception
@ -499,6 +552,7 @@ public class HttpExchangeTest
int status = httpExchange.waitForDone();
//httpExchange.waitForStatus(HttpExchange.STATUS_COMPLETED);
String result=httpExchange.getResponseContent();
assertNotNull("Should have received response content", result);
result=result.trim();
assertEquals(HttpExchange.STATUS_COMPLETED, status);
assertTrue(result.startsWith("Proxy request: http://jetty.eclipse.org:8080/jetty-6"));
@ -515,36 +569,42 @@ public class HttpExchangeTest
@Test
public void testReserveConnections () throws Exception
{
final HttpDestination destination = _httpClient.getDestination (new Address("localhost", _port), _scheme.equalsIgnoreCase("https"));
final org.eclipse.jetty.client.HttpConnection[] connections = new org.eclipse.jetty.client.HttpConnection[_maxConnectionsPerAddress];
for (int i=0; i < _maxConnectionsPerAddress; i++)
{
connections[i] = destination.reserveConnection(200);
assertNotNull(connections[i]);
HttpExchange ex = new ContentExchange();
ex.setURL(_scheme+"://localhost:"+_port+"/?i="+i);
ex.setMethod(HttpMethods.GET);
connections[i].send(ex);
}
_httpClient = serverAndClientCreator.createClient(3000L,3500L,2000);
final HttpDestination destination = _httpClient.getDestination(new Address("localhost",_port),_scheme.equalsIgnoreCase("https"));
final org.eclipse.jetty.client.HttpConnection[] connections = new org.eclipse.jetty.client.HttpConnection[_maxConnectionsPerAddress];
for (int i = 0; i < _maxConnectionsPerAddress; i++)
{
connections[i] = destination.reserveConnection(200);
assertNotNull(connections[i]);
HttpExchange ex = new ContentExchange();
ex.setURI(getBaseURI().resolve("?i=" + i));
ex.setMethod(HttpMethods.GET);
connections[i].send(ex);
}
//try to get a connection, and only wait 500ms, as we have
//already reserved the max, should return null
Connection c = destination.reserveConnection(500);
assertNull(c);
// try to get a connection, and only wait 500ms, as we have
// already reserved the max, should return null
Connection c = destination.reserveConnection(500);
assertNull(c);
//unreserve first connection
destination.returnConnection(connections[0], false);
// unreserve first connection
destination.returnConnection(connections[0],false);
//reserving one should now work
c = destination.reserveConnection(500);
assertNotNull(c);
// reserving one should now work
c = destination.reserveConnection(500);
assertNotNull(c);
// release connections
for (HttpConnection httpConnection : connections){
destination.returnConnection(httpConnection,false);
}
}
@Test
public void testOptionsWithExchange() throws Exception
{
ContentExchange httpExchange = new ContentExchange(true);
httpExchange.setURL(_scheme+"://localhost:"+_port);
httpExchange.setURL(getBaseURI().toASCIIString());
httpExchange.setRequestURI("*");
httpExchange.setMethod(HttpMethods.OPTIONS);
// httpExchange.setRequestHeader("Connection","close");
@ -555,8 +615,10 @@ public class HttpExchangeTest
assertEquals(HttpStatus.OK_200,httpExchange.getResponseStatus());
HttpFields headers = httpExchange.getResponseFields();
assertTrue("Response contains Allow header", headers.containsKey("Allow"));
HttpAsserts.assertContainsHeaderKey("Content-Length", headers);
assertEquals("Content-Length header value", 0, headers.getLongField("Content-Length"));
HttpAsserts.assertContainsHeaderKey("Allow",headers);
String allow = headers.getStringField("Allow");
String expectedMethods[] =
{ "GET", "HEAD", "POST", "PUT", "DELETE", "MOVE", "OPTIONS", "TRACE" };
@ -564,9 +626,6 @@ public class HttpExchangeTest
{
assertThat(allow,containsString(expectedMethod));
}
assertTrue("Response contains Content-Length header", headers.containsKey("Content-Length"));
assertEquals("Content-Length header value", 0, headers.getLongField("Content-Length"));
}
/* ------------------------------------------------------------ */
@ -574,115 +633,20 @@ public class HttpExchangeTest
{
try
{
byte[] buffer=new byte[1024];
byte[] buffer = new byte[1024];
int len;
while ((len=in.read(buffer))>=0)
while ((len = in.read(buffer)) >= 0)
{
out.write(buffer,0,len);
}
}
catch (EofException e)
{
System.err.println("HttpExchangeTest#copyStream: "+e);
System.err.println("HttpExchangeTest#copyStream: " + e);
}
catch (IOException e)
{
e.printStackTrace();
}
}
/* ------------------------------------------------------------ */
protected void newServer() throws Exception
{
_server=new Server();
_server.setGracefulShutdown(500);
_connector=new SelectChannelConnector();
_connector.setMaxIdleTime(3000000);
_connector.setPort(0);
_server.setConnectors(new Connector[] { _connector });
}
/* ------------------------------------------------------------ */
protected void startServer() throws Exception
{
newServer();
_server.setHandler(new AbstractHandler()
{
public void handle(String target, Request baseRequest, HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException
{
int i=0;
try
{
baseRequest.setHandled(true);
response.setStatus(200);
_count.incrementAndGet();
if (request.getServerName().equals("jetty.eclipse.org"))
{
response.getOutputStream().println("Proxy request: "+request.getRequestURL());
response.getOutputStream().println(request.getHeader(HttpHeaders.PROXY_AUTHORIZATION));
}
else if (request.getMethod().equalsIgnoreCase("GET"))
{
response.getOutputStream().println("<hello>");
for (; i<100; i++)
{
response.getOutputStream().println(" <world>"+i+"</world");
if (i%20==0)
response.getOutputStream().flush();
}
response.getOutputStream().println("</hello>");
}
else if (request.getMethod().equalsIgnoreCase("OPTIONS"))
{
if ("*".equals(target))
{
response.setContentLength(0);
response.setHeader("Allow","GET,HEAD,POST,PUT,DELETE,MOVE,OPTIONS,TRACE");
}
}
else if (request.getMethod().equalsIgnoreCase("SLEEP"))
{
Thread.sleep(10000);
}
else
{
response.setContentType(request.getContentType());
int size=request.getContentLength();
ByteArrayOutputStream bout = new ByteArrayOutputStream(size>0?size:32768);
IO.copy(request.getInputStream(),bout);
response.getOutputStream().write(bout.toByteArray());
}
}
catch(InterruptedException e)
{
LOG.debug(e);
}
catch(IOException e)
{
e.printStackTrace();
throw e;
}
catch(Throwable e)
{
e.printStackTrace();
throw new ServletException(e);
}
finally
{
}
}
});
_server.start();
_port=_connector.getLocalPort();
}
/* ------------------------------------------------------------ */
private void stopServer() throws Exception
{
_server.stop();
}
}

View File

@ -13,67 +13,36 @@
package org.eclipse.jetty.client;
import static org.hamcrest.Matchers.containsString;
import static org.hamcrest.Matchers.not;
import static org.hamcrest.Matchers.*;
import org.eclipse.jetty.http.ssl.SslContextFactory;
import org.eclipse.jetty.client.helperClasses.ServerAndClientCreator;
import org.eclipse.jetty.client.helperClasses.SslServerAndClientCreator;
import org.eclipse.jetty.server.Connector;
import org.eclipse.jetty.server.Server;
import org.eclipse.jetty.server.ssl.SslSocketConnector;
import org.eclipse.jetty.toolchain.test.MavenTestingUtils;
import org.eclipse.jetty.toolchain.test.OS;
import org.eclipse.jetty.toolchain.test.Stress;
import org.junit.Assume;
import org.junit.Before;
import org.junit.BeforeClass;
import org.junit.Test;
/**
* Functional testing for HttpExchange.
*
*
*
*/
public class SslHttpExchangeTest extends HttpExchangeTest
{
protected static ServerAndClientCreator serverAndClientCreator = new SslServerAndClientCreator();
/* ------------------------------------------------------------ */
@Before
@Override
public void setUp() throws Exception
public void setUpOnce() throws Exception
{
_scheme="https";
startServer();
_httpClient=new HttpClient();
_httpClient.setIdleTimeout(2000);
_httpClient.setTimeout(2500);
_httpClient.setConnectTimeout(1000);
_httpClient.setConnectorType(HttpClient.CONNECTOR_SELECT_CHANNEL);
_httpClient.setConnectorType(HttpClient.CONNECTOR_SOCKET);
_httpClient.setMaxConnectionsPerAddress(2);
_httpClient.start();
_server = serverAndClientCreator.createServer();
_httpClient = serverAndClientCreator.createClient(3000L,3500L,2000);
Connector[] connectors = _server.getConnectors();
_port = connectors[0].getLocalPort();
}
/* ------------------------------------------------------------ */
@Override
protected void newServer()
{
_server = new Server();
//SslSelectChannelConnector connector = new SslSelectChannelConnector();
SslSocketConnector connector = new SslSocketConnector();
String keystore = MavenTestingUtils.getTestResourceFile("keystore").getAbsolutePath();
connector.setPort(0);
SslContextFactory cf = connector.getSslContextFactory();
cf.setKeyStore(keystore);
cf.setKeyStorePassword("storepwd");
cf.setKeyManagerPassword("keypwd");
connector.setAllowRenegotiate(true);
_server.setConnectors(new Connector[]
{ connector });
_connector=connector;
}
/* ------------------------------------------------------------ */
private void IgnoreTestOnBuggyIBM()
{

View File

@ -0,0 +1,57 @@
// ========================================================================
// Copyright (c) 2009-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.client.helperClasses;
import org.eclipse.jetty.http.ssl.SslContextFactory;
import org.eclipse.jetty.server.Connector;
import org.eclipse.jetty.server.Server;
import org.eclipse.jetty.server.ssl.SslSelectChannelConnector;
import org.eclipse.jetty.server.ssl.SslSocketConnector;
import org.eclipse.jetty.toolchain.test.MavenTestingUtils;
import org.eclipse.jetty.util.log.Log;
import org.eclipse.jetty.util.log.Logger;
/* ------------------------------------------------------------ */
/**
*/
public abstract class AbstractSslServerAndClientCreator implements ServerAndClientCreator
{
private static final Logger LOG = Log.getLogger(AbstractSslServerAndClientCreator.class);
/* ------------------------------------------------------------ */
public Server createServer() throws Exception
{
Server server = new Server();
//SslSelectChannelConnector connector = new SslSelectChannelConnector();
SslSocketConnector connector = new SslSocketConnector();
String keystore = MavenTestingUtils.getTestResourceFile("keystore").getAbsolutePath();
connector.setPort(0);
SslContextFactory cf = connector.getSslContextFactory();
cf.setKeyStore(keystore);
cf.setKeyStorePassword("storepwd");
cf.setKeyManagerPassword("keypwd");
connector.setAllowRenegotiate(true);
server.setConnectors(new Connector[]{ connector });
server.setHandler(new GenericServerHandler());
server.start();
return server;
}
}

View File

@ -0,0 +1,26 @@
package org.eclipse.jetty.client.helperClasses;
import java.io.FileInputStream;
import org.eclipse.jetty.client.HttpClient;
import org.eclipse.jetty.toolchain.test.MavenTestingUtils;
public class AsyncSslServerAndClientCreator extends AbstractSslServerAndClientCreator implements ServerAndClientCreator
{
/* ------------------------------------------------------------ */
public HttpClient createClient(long idleTimeout, long timeout, int connectTimeout) throws Exception
{
HttpClient httpClient = new HttpClient();
httpClient.setConnectorType(HttpClient.CONNECTOR_SELECT_CHANNEL);
httpClient.setMaxConnectionsPerAddress(2);
String keystore = MavenTestingUtils.getTestResourceFile("keystore").getAbsolutePath();
httpClient.setKeyStoreInputStream(new FileInputStream(keystore));
httpClient.setKeyStorePassword("storepwd");
httpClient.setKeyManagerPassword("keypwd");
httpClient.start();
return httpClient;
}
}

View File

@ -0,0 +1,27 @@
package org.eclipse.jetty.client.helperClasses;
import java.io.FileInputStream;
import org.eclipse.jetty.client.HttpClient;
import org.eclipse.jetty.toolchain.test.MavenTestingUtils;
public class ExternalKeyStoreAsyncSslServerAndClientCreator extends AbstractSslServerAndClientCreator implements ServerAndClientCreator
{
public HttpClient createClient(long idleTimeout, long timeout, int connectTimeout) throws Exception
{
HttpClient httpClient = new HttpClient();
httpClient.setConnectorType(HttpClient.CONNECTOR_SELECT_CHANNEL);
httpClient.setMaxConnectionsPerAddress(2);
String keystore = MavenTestingUtils.getTestResourceFile("keystore").getAbsolutePath();
httpClient.setKeyStoreInputStream(new FileInputStream(keystore));
httpClient.setKeyStorePassword("storepwd");
httpClient.setKeyManagerPassword("keypwd");
httpClient.start();
return httpClient;
}
}

View File

@ -0,0 +1,84 @@
package org.eclipse.jetty.client.helperClasses;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.eclipse.jetty.http.HttpHeaders;
import org.eclipse.jetty.server.Request;
import org.eclipse.jetty.server.handler.AbstractHandler;
import org.eclipse.jetty.util.IO;
import org.eclipse.jetty.util.log.Log;
import org.eclipse.jetty.util.log.Logger;
/**
* Generic Server Handler used for various client tests.
*/
public class GenericServerHandler extends AbstractHandler
{
private static final Logger LOG = Log.getLogger(GenericServerHandler.class);
public void handle(String target, Request baseRequest, HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException
{
int i = 0;
try
{
baseRequest.setHandled(true);
response.setStatus(200);
if (request.getServerName().equals("jetty.eclipse.org"))
{
response.getOutputStream().println("Proxy request: " + request.getRequestURL());
response.getOutputStream().println(request.getHeader(HttpHeaders.PROXY_AUTHORIZATION));
}
else if (request.getMethod().equalsIgnoreCase("GET"))
{
response.getOutputStream().println("<hello>");
for (; i < 100; i++)
{
response.getOutputStream().println(" <world>" + i + "</world");
if (i % 20 == 0)
response.getOutputStream().flush();
}
response.getOutputStream().println("</hello>");
}
else if (request.getMethod().equalsIgnoreCase("OPTIONS"))
{
if ("*".equals(target))
{
response.setContentLength(0);
response.setHeader("Allow","GET,HEAD,POST,PUT,DELETE,MOVE,OPTIONS,TRACE");
}
}
else if (request.getMethod().equalsIgnoreCase("SLEEP"))
{
Thread.sleep(10000);
}
else
{
response.setContentType(request.getContentType());
int size = request.getContentLength();
ByteArrayOutputStream bout = new ByteArrayOutputStream(size > 0?size:32768);
IO.copy(request.getInputStream(),bout);
response.getOutputStream().write(bout.toByteArray());
}
}
catch (InterruptedException e)
{
LOG.debug(e);
}
catch (IOException e)
{
LOG.warn(e);
throw e;
}
catch (Throwable e)
{
LOG.warn(e);
throw new ServletException(e);
}
}
}

View File

@ -0,0 +1,36 @@
package org.eclipse.jetty.client.helperClasses;
import org.eclipse.jetty.client.HttpClient;
import org.eclipse.jetty.server.Connector;
import org.eclipse.jetty.server.Server;
import org.eclipse.jetty.server.nio.SelectChannelConnector;
public class HttpServerAndClientCreator implements ServerAndClientCreator
{
public HttpClient createClient(long idleTimeout, long timeout, int connectTimeout) throws Exception
{
HttpClient httpClient = new HttpClient();
httpClient.setIdleTimeout(idleTimeout);
httpClient.setTimeout(timeout);
httpClient.setConnectTimeout(connectTimeout);
httpClient.setConnectorType(HttpClient.CONNECTOR_SELECT_CHANNEL);
httpClient.setMaxConnectionsPerAddress(2);
httpClient.start();
return httpClient;
}
public Server createServer() throws Exception
{
Server _server = new Server();
_server.setGracefulShutdown(500);
Connector _connector = new SelectChannelConnector();
_connector.setMaxIdleTime(3000000);
_connector.setPort(0);
_server.setConnectors(new Connector[]{ _connector });
_server.setHandler(new GenericServerHandler());
_server.start();
return _server;
}
}

View File

@ -0,0 +1,11 @@
package org.eclipse.jetty.client.helperClasses;
import org.eclipse.jetty.client.HttpClient;
import org.eclipse.jetty.server.Server;
public interface ServerAndClientCreator
{
Server createServer() throws Exception;
HttpClient createClient(long idleTimeout, long timeout, int connectTimeout) throws Exception;
}

View File

@ -0,0 +1,19 @@
package org.eclipse.jetty.client.helperClasses;
import org.eclipse.jetty.client.HttpClient;
public class SslServerAndClientCreator extends AbstractSslServerAndClientCreator implements ServerAndClientCreator
{
public HttpClient createClient(long idleTimeout, long timeout, int connectTimeout) throws Exception
{
HttpClient httpClient = new HttpClient();
httpClient.setIdleTimeout(idleTimeout);
httpClient.setTimeout(timeout);
httpClient.setConnectTimeout(connectTimeout);
httpClient.setConnectorType(HttpClient.CONNECTOR_SOCKET);
httpClient.setMaxConnectionsPerAddress(2);
httpClient.start();
return httpClient;
}
}

View File

@ -155,157 +155,6 @@
<plugin>
<artifactId>maven-dependency-plugin</artifactId>
<executions>
<execution>
<id>unpack</id>
<phase>generate-resources</phase>
<goals>
<goal>unpack</goal>
</goals>
<configuration>
<artifactItems>
<artifactItem>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-rewrite</artifactId>
<version>${project.version}</version>
<classifier>config</classifier>
<type>jar</type>
<overWrite>true</overWrite>
<includes>**</includes>
<outputDirectory>${assembly-directory}</outputDirectory>
</artifactItem>
<artifactItem>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-ajp</artifactId>
<version>${project.version}</version>
<classifier>config</classifier>
<type>jar</type>
<overWrite>true</overWrite>
<includes>**</includes>
<outputDirectory>${assembly-directory}</outputDirectory>
</artifactItem>
<artifactItem>
<groupId>org.eclipse.jetty</groupId>
<artifactId>test-jetty-webapp</artifactId>
<version>${project.version}</version>
<classifier>config</classifier>
<type>jar</type>
<overWrite>true</overWrite>
<includes>**</includes>
<outputDirectory>${assembly-directory}</outputDirectory>
</artifactItem>
<artifactItem>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-jmx</artifactId>
<version>${project.version}</version>
<classifier>config</classifier>
<type>jar</type>
<overWrite>true</overWrite>
<includes>**</includes>
<outputDirectory>${assembly-directory}</outputDirectory>
</artifactItem>
<artifactItem>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-util</artifactId>
<version>${project.version}</version>
<classifier>config</classifier>
<type>jar</type>
<overWrite>true</overWrite>
<includes>**</includes>
<outputDirectory>${assembly-directory}</outputDirectory>
</artifactItem>
<artifactItem>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-webapp</artifactId>
<version>${project.version}</version>
<classifier>config</classifier>
<type>jar</type>
<overWrite>true</overWrite>
<includes>**</includes>
<outputDirectory>${assembly-directory}</outputDirectory>
</artifactItem>
<artifactItem>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-deploy</artifactId>
<version>${project.version}</version>
<classifier>config</classifier>
<type>jar</type>
<overWrite>true</overWrite>
<includes>**</includes>
<outputDirectory>${assembly-directory}</outputDirectory>
</artifactItem>
<artifactItem>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-plus</artifactId>
<version>${project.version}</version>
<classifier>config</classifier>
<type>jar</type>
<overWrite>true</overWrite>
<includes>**</includes>
<outputDirectory>${assembly-directory}</outputDirectory>
</artifactItem>
<artifactItem>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-server</artifactId>
<version>${project.version}</version>
<classifier>config</classifier>
<type>jar</type>
<overWrite>true</overWrite>
<includes>**</includes>
<outputDirectory>${assembly-directory}</outputDirectory>
</artifactItem>
<artifactItem>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-security</artifactId>
<version>${project.version}</version>
<classifier>config</classifier>
<type>jar</type>
<overWrite>true</overWrite>
<includes>**</includes>
<outputDirectory>${assembly-directory}</outputDirectory>
</artifactItem>
<artifactItem>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-policy</artifactId>
<version>${project.version}</version>
<classifier>config</classifier>
<type>jar</type>
<overWrite>true</overWrite>
<includes>**</includes>
<outputDirectory>${assembly-directory}</outputDirectory>
</artifactItem>
<artifactItem>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-monitor</artifactId>
<version>${project.version}</version>
<classifier>config</classifier>
<type>jar</type>
<overWrite>true</overWrite>
<includes>**</includes>
<outputDirectory>${assembly-directory}</outputDirectory>
</artifactItem>
<artifactItem>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-overlay-deployer</artifactId>
<version>${project.version}</version>
<classifier>config</classifier>
<type>jar</type>
<overWrite>true</overWrite>
<includes>**</includes>
<outputDirectory>${assembly-directory}</outputDirectory>
</artifactItem>
<artifactItem>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-annotations</artifactId>
<version>${project.version}</version>
<classifier>config</classifier>
<type>jar</type>
<overWrite>true</overWrite>
<includes>**</includes>
<outputDirectory>${assembly-directory}</outputDirectory>
</artifactItem>
</artifactItems>
</configuration>
</execution>
<execution>
<id>copy</id>
<phase>generate-resources</phase>
@ -324,187 +173,6 @@
<outputDirectory>${assembly-directory}/</outputDirectory>
<destFileName>VERSION.txt</destFileName>
</artifactItem>
<artifactItem>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-util</artifactId>
<version>${project.version}</version>
<type>jar</type>
<overWrite>true</overWrite>
<includes>**</includes>
<outputDirectory>${assembly-directory}/lib</outputDirectory>
</artifactItem>
<artifactItem>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-io</artifactId>
<version>${project.version}</version>
<type>jar</type>
<overWrite>true</overWrite>
<includes>**</includes>
<outputDirectory>${assembly-directory}/lib</outputDirectory>
</artifactItem>
<artifactItem>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-http</artifactId>
<version>${project.version}</version>
<type>jar</type>
<overWrite>true</overWrite>
<includes>**</includes>
<outputDirectory>${assembly-directory}/lib</outputDirectory>
</artifactItem>
<artifactItem>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-server</artifactId>
<version>${project.version}</version>
<type>jar</type>
<overWrite>true</overWrite>
<includes>**</includes>
<outputDirectory>${assembly-directory}/lib</outputDirectory>
</artifactItem>
<artifactItem>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-security</artifactId>
<version>${project.version}</version>
<type>jar</type>
<overWrite>true</overWrite>
<includes>**</includes>
<outputDirectory>${assembly-directory}/lib</outputDirectory>
</artifactItem>
<artifactItem>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-servlet</artifactId>
<version>${project.version}</version>
<type>jar</type>
<overWrite>true</overWrite>
<includes>**</includes>
<outputDirectory>${assembly-directory}/lib</outputDirectory>
</artifactItem>
<artifactItem>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-servlets</artifactId>
<version>${project.version}</version>
<type>jar</type>
<overWrite>true</overWrite>
<includes>**</includes>
<outputDirectory>${assembly-directory}/lib</outputDirectory>
</artifactItem>
<artifactItem>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-xml</artifactId>
<version>${project.version}</version>
<type>jar</type>
<overWrite>true</overWrite>
<includes>**</includes>
<outputDirectory>${assembly-directory}/lib</outputDirectory>
</artifactItem>
<artifactItem>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-webapp</artifactId>
<version>${project.version}</version>
<type>jar</type>
<overWrite>true</overWrite>
<includes>**</includes>
<outputDirectory>${assembly-directory}/lib</outputDirectory>
</artifactItem>
<!-- Jetty Deploy -->
<artifactItem>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-deploy</artifactId>
<version>${project.version}</version>
<type>jar</type>
<overWrite>true</overWrite>
<includes>**</includes>
<outputDirectory>${assembly-directory}/lib</outputDirectory>
</artifactItem>
<artifactItem>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-jmx</artifactId>
<version>${project.version}</version>
<type>jar</type>
<overWrite>true</overWrite>
<includes>**</includes>
<outputDirectory>${assembly-directory}/lib</outputDirectory>
</artifactItem>
<artifactItem>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-rewrite</artifactId>
<version>${project.version}</version>
<type>jar</type>
<overWrite>true</overWrite>
<includes>**</includes>
<outputDirectory>${assembly-directory}/lib</outputDirectory>
</artifactItem>
<artifactItem>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-ajp</artifactId>
<version>${project.version}</version>
<type>jar</type>
<overWrite>true</overWrite>
<includes>**</includes>
<outputDirectory>${assembly-directory}/lib</outputDirectory>
</artifactItem>
<artifactItem>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-annotations</artifactId>
<version>${project.version}</version>
<type>jar</type>
<overWrite>true</overWrite>
<includes>**</includes>
<outputDirectory>${assembly-directory}/lib</outputDirectory>
</artifactItem>
<artifactItem>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-client</artifactId>
<version>${project.version}</version>
<type>jar</type>
<overWrite>true</overWrite>
<includes>**</includes>
<outputDirectory>${assembly-directory}/lib</outputDirectory>
</artifactItem>
<artifactItem>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-jndi</artifactId>
<version>${project.version}</version>
<type>jar</type>
<overWrite>true</overWrite>
<includes>**</includes>
<outputDirectory>${assembly-directory}/lib</outputDirectory>
</artifactItem>
<artifactItem>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-policy</artifactId>
<version>${project.version}</version>
<type>jar</type>
<overWrite>true</overWrite>
<includes>**</includes>
<outputDirectory>${assembly-directory}/lib</outputDirectory>
</artifactItem>
<artifactItem>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-monitor</artifactId>
<version>${project.version}</version>
<type>jar</type>
<overWrite>true</overWrite>
<includes>**</includes>
<outputDirectory>${assembly-directory}/lib/monitor</outputDirectory>
</artifactItem>
<artifactItem>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-plus</artifactId>
<version>${project.version}</version>
<type>jar</type>
<overWrite>true</overWrite>
<includes>**</includes>
<outputDirectory>${assembly-directory}/lib</outputDirectory>
</artifactItem>
<artifactItem>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-continuation</artifactId>
<version>${project.version}</version>
<type>jar</type>
<overWrite>true</overWrite>
<includes>**</includes>
<outputDirectory>${assembly-directory}/lib</outputDirectory>
</artifactItem>
<artifactItem>
<groupId>org.eclipse.jetty</groupId>
<artifactId>test-jetty-webapp</artifactId>
@ -525,36 +193,77 @@
<outputDirectory>${assembly-directory}</outputDirectory>
<destFileName>start.jar</destFileName>
</artifactItem>
<artifactItem>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-overlay-deployer</artifactId>
<version>${project.version}</version>
<type>jar</type>
<overWrite>true</overWrite>
<includes>**</includes>
<outputDirectory>${assembly-directory}/lib</outputDirectory>
</artifactItem>
<artifactItem>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-overlay-deployer</artifactId>
<version>${project.version}</version>
<type>jar</type>
<overWrite>true</overWrite>
<includes>**</includes>
<outputDirectory>${assembly-directory}/lib</outputDirectory>
</artifactItem>
<artifactItem>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-websocket</artifactId>
<version>${project.version}</version>
<type>jar</type>
<overWrite>true</overWrite>
<includes>**</includes>
<outputDirectory>${assembly-directory}/lib</outputDirectory>
</artifactItem>
</artifactItems>
</configuration>
</execution>
<execution>
<id>copy-lib-deps</id>
<phase>generate-resources</phase>
<goals>
<goal>copy-dependencies</goal>
</goals>
<configuration>
<includeGroupIds>org.eclipse.jetty</includeGroupIds>
<excludeArtifactIds>jetty-start,jetty-monitor,jetty-jsp-2.1</excludeArtifactIds>
<includeTypes>jar</includeTypes>
<outputDirectory>${assembly-directory}/lib</outputDirectory>
</configuration>
</execution>
<execution>
<id>copy-lib-jsp-deps</id>
<phase>generate-resources</phase>
<goals>
<goal>copy-dependencies</goal>
</goals>
<configuration>
<includeGroupIds>org.eclipse.jetty,org.glassfish.web</includeGroupIds>
<includeArtifactIds>jetty-jsp-2.1,jsp-impl</includeArtifactIds>
<includeTypes>jar</includeTypes>
<outputDirectory>${assembly-directory}/lib/jsp</outputDirectory>
</configuration>
</execution>
<execution>
<id>copy-lib-monitor-deps</id>
<phase>generate-resources</phase>
<goals>
<goal>copy-dependencies</goal>
</goals>
<configuration>
<includeGroupIds>org.eclipse.jetty</includeGroupIds>
<includeArtifactIds>jetty-monitor</includeArtifactIds>
<includeTypes>jar</includeTypes>
<excludeTransitive>true</excludeTransitive>
<outputDirectory>${assembly-directory}/lib/monitor</outputDirectory>
</configuration>
</execution>
<execution>
<id>unpack-config-deps</id>
<phase>generate-resources</phase>
<goals>
<goal>unpack-dependencies</goal>
</goals>
<configuration>
<includeGroupIds>org.eclipse.jetty</includeGroupIds>
<classifier>config</classifier>
<failOnMissingClassifierArtifact>false</failOnMissingClassifierArtifact>
<outputDirectory>${assembly-directory}</outputDirectory>
</configuration>
</execution>
<execution>
<id>unpack-javadoc</id>
<phase>generate-resources</phase>
<goals>
<goal>unpack-dependencies</goal>
</goals>
<configuration>
<!-- Use already generated javadoc, don't bother regenerating again -->
<includeGroupIds>org.eclipse.jetty.aggregate</includeGroupIds>
<includeArtifactIds>jetty-all</includeArtifactIds>
<includeClassifier>javadoc</includeClassifier>
<excludeTransitive>true</excludeTransitive>
<outputDirectory>${assembly-directory}/javadoc</outputDirectory>
</configuration>
</execution>
</executions>
</plugin>
<plugin>
@ -663,12 +372,12 @@
</dependency>
<dependency>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-overlay-deployer</artifactId>
<artifactId>jetty-servlets</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-overlay-deployer</artifactId>
<artifactId>jetty-monitor</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
@ -676,5 +385,17 @@
<artifactId>jetty-websocket</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-overlay-deployer</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>org.eclipse.jetty.aggregate</groupId>
<artifactId>jetty-all</artifactId>
<classifier>javadoc</classifier>
<type>jar</type>
<version>${project.version}</version>
</dependency>
</dependencies>
</project>

View File

@ -266,9 +266,19 @@ public class HttpParser implements Parser
// Fill buffer if we can
if (length == 0)
{
long filled=fill();
long filled=-1;
IOException ex=null;
try
{
filled=fill();
}
catch(IOException e)
{
LOG.debug(this.toString(),e);
ex=e;
}
if (filled < 0)
if (filled < 0 || _endp.isInputShutdown())
{
if (_headResponse && _state>STATE_END)
{
@ -291,6 +301,8 @@ public class HttpParser implements Parser
return 1;
}
if (ex!=null)
throw ex;
return -1;
}
length=_buffer.length();

View File

@ -4,11 +4,11 @@
// All rights reserved. This program and the accompanying materials
// are made available under the terms of the Eclipse Public License v1.0
// and Apache License v2.0 which accompanies this distribution.
// The Eclipse Public License is available at
// The Eclipse Public License is available at
// http://www.eclipse.org/legal/epl-v10.html
// The Apache License v2.0 is available at
// http://www.opensource.org/licenses/apache2.0.php
// You may elect to redistribute this code under either of these licenses.
// You may elect to redistribute this code under either of these licenses.
// ========================================================================
package org.eclipse.jetty.http;
@ -34,7 +34,7 @@ import org.eclipse.jetty.util.URIUtil;
* /foo/bar - an exact path specification.
* /foo/* - a prefix path specification (must end '/*').
* *.ext - a suffix path specification.
* / - the default path specification.
* / - the default path specification.
* </PRE>
* Matching is performed in the following order <NL>
* <LI>Exact match.
@ -43,24 +43,24 @@ import org.eclipse.jetty.util.URIUtil;
* <LI>default.
* </NL>
* Multiple path specifications can be mapped by providing a list of
* specifications. By default this class uses characters ":," as path
* separators, unless configured differently by calling the static
* method @see PathMap#setPathSpecSeparators(String)
* specifications. By default this class uses characters ":," as path
* separators, unless configured differently by calling the static
* method @see PathMap#setPathSpecSeparators(String)
* <P>
* Special characters within paths such as '?<EFBFBD> and ';' are not treated specially
* as it is assumed they would have been either encoded in the original URL or
* as it is assumed they would have been either encoded in the original URL or
* stripped from the path.
* <P>
* This class is not synchronized. If concurrent modifications are
* possible then it should be synchronized at a higher level.
*
*
*
*/
public class PathMap extends HashMap implements Externalizable
{
/* ------------------------------------------------------------ */
private static String __pathSpecSeparators = ":,";
/* ------------------------------------------------------------ */
/** Set the path spec separator.
* Multiple path specification may be included in a single string
@ -72,7 +72,7 @@ public class PathMap extends HashMap implements Externalizable
{
__pathSpecSeparators=s;
}
/* --------------------------------------------------------------- */
final StringMap _prefixMap=new StringMap();
final StringMap _suffixMap=new StringMap();
@ -83,7 +83,7 @@ public class PathMap extends HashMap implements Externalizable
Entry _default=null;
final Set _entrySet;
boolean _nodefault=false;
/* --------------------------------------------------------------- */
/** Construct empty PathMap.
*/
@ -102,7 +102,7 @@ public class PathMap extends HashMap implements Externalizable
_entrySet=entrySet();
_nodefault=nodefault;
}
/* --------------------------------------------------------------- */
/** Construct empty PathMap.
*/
@ -111,7 +111,7 @@ public class PathMap extends HashMap implements Externalizable
super (capacity);
_entrySet=entrySet();
}
/* --------------------------------------------------------------- */
/** Construct from dictionary PathMap.
*/
@ -120,7 +120,7 @@ public class PathMap extends HashMap implements Externalizable
putAll(m);
_entrySet=entrySet();
}
/* ------------------------------------------------------------ */
public void writeExternal(java.io.ObjectOutput out)
throws java.io.IOException
@ -128,7 +128,7 @@ public class PathMap extends HashMap implements Externalizable
HashMap map = new HashMap(this);
out.writeObject(map);
}
/* ------------------------------------------------------------ */
public void readExternal(java.io.ObjectInput in)
throws java.io.IOException, ClassNotFoundException
@ -136,7 +136,7 @@ public class PathMap extends HashMap implements Externalizable
HashMap map = (HashMap)in.readObject();
this.putAll(map);
}
/* --------------------------------------------------------------- */
/** Add a single path match to the PathMap.
* @param pathSpec The path specification, or comma separated list of
@ -148,16 +148,16 @@ public class PathMap extends HashMap implements Externalizable
{
StringTokenizer tok = new StringTokenizer(pathSpec.toString(),__pathSpecSeparators);
Object old =null;
while (tok.hasMoreTokens())
{
String spec=tok.nextToken();
if (!spec.startsWith("/") && !spec.startsWith("*."))
throw new IllegalArgumentException("PathSpec "+spec+". must start with '/' or '*.'");
old = super.put(spec,object);
// Make entry that was just created.
Entry entry = new Entry(spec,object);
@ -176,7 +176,7 @@ public class PathMap extends HashMap implements Externalizable
else if (spec.startsWith("*."))
_suffixMap.put(spec.substring(2),entry);
else if (spec.equals(URIUtil.SLASH))
{
{
if (_nodefault)
_exactMap.put(spec,entry);
else
@ -193,7 +193,7 @@ public class PathMap extends HashMap implements Externalizable
}
}
}
return old;
}
@ -209,8 +209,8 @@ public class PathMap extends HashMap implements Externalizable
return entry.getValue();
return null;
}
/* --------------------------------------------------------------- */
/** Get the entry mapped by the best specification.
* @param path the path.
@ -222,14 +222,14 @@ public class PathMap extends HashMap implements Externalizable
if (path==null)
return null;
int l=path.length();
int l=path.length();
// try exact match
entry=_exactMap.getEntry(path,0,l);
if (entry!=null)
return (Entry) entry.getValue();
// prefix search
int i=l;
while((i=path.lastIndexOf('/',i-1))>=0)
@ -238,11 +238,11 @@ public class PathMap extends HashMap implements Externalizable
if (entry!=null)
return (Entry) entry.getValue();
}
// Prefix Default
if (_prefixDefault!=null)
return _prefixDefault;
// Extension search
i=0;
while ((i=path.indexOf('.',i+1))>0)
@ -250,12 +250,12 @@ public class PathMap extends HashMap implements Externalizable
entry=_suffixMap.getEntry(path,i+1,l-i-1);
if (entry!=null)
return (Entry) entry.getValue();
}
}
// Default
return _default;
}
/* --------------------------------------------------------------- */
/** Get all entries matched by the path.
* Best match first.
@ -263,20 +263,20 @@ public class PathMap extends HashMap implements Externalizable
* @return LazyList of Map.Entry instances key=pathSpec
*/
public Object getLazyMatches(String path)
{
{
Map.Entry entry;
Object entries=null;
if (path==null)
return LazyList.getList(entries);
int l=path.length();
// try exact match
entry=_exactMap.getEntry(path,0,l);
if (entry!=null)
entries=LazyList.add(entries,entry.getValue());
// prefix search
int i=l-1;
while((i=path.lastIndexOf('/',i-1))>=0)
@ -285,11 +285,11 @@ public class PathMap extends HashMap implements Externalizable
if (entry!=null)
entries=LazyList.add(entries,entry.getValue());
}
// Prefix Default
if (_prefixDefault!=null)
entries=LazyList.add(entries,_prefixDefault);
// Extension search
i=0;
while ((i=path.indexOf('.',i+1))>0)
@ -305,13 +305,13 @@ public class PathMap extends HashMap implements Externalizable
// Optimization for just the default
if (entries==null)
return _defaultSingletonList;
entries=LazyList.add(entries,_default);
}
return entries;
}
/* --------------------------------------------------------------- */
/** Get all entries matched by the path.
* Best match first.
@ -319,7 +319,7 @@ public class PathMap extends HashMap implements Externalizable
* @return List of Map.Entry instances key=pathSpec
*/
public List getMatches(String path)
{
{
return LazyList.getList(getLazyMatches(path));
}
@ -330,12 +330,12 @@ public class PathMap extends HashMap implements Externalizable
* @return Whether the PathMap contains any entries that match this
*/
public boolean containsMatch(String path)
{
{
Entry match = getMatch(path);
return match!=null && !match.equals(_default);
}
/* --------------------------------------------------------------- */
/* --------------------------------------------------------------- */
@Override
public Object remove(Object pathSpec)
{
@ -362,7 +362,7 @@ public class PathMap extends HashMap implements Externalizable
}
return super.remove(pathSpec);
}
/* --------------------------------------------------------------- */
@Override
public void clear()
@ -374,7 +374,7 @@ public class PathMap extends HashMap implements Externalizable
_defaultSingletonList=null;
super.clear();
}
/* --------------------------------------------------------------- */
/**
* @return true if match.
@ -397,7 +397,7 @@ public class PathMap extends HashMap implements Externalizable
{
if (!noDefault && pathSpec.length()==1 || pathSpec.equals(path))
return true;
if(isPathWildcardMatch(pathSpec, path))
return true;
}
@ -419,24 +419,24 @@ public class PathMap extends HashMap implements Externalizable
}
return false;
}
/* --------------------------------------------------------------- */
/** Return the portion of a path that matches a path spec.
* @return null if no match at all.
*/
public static String pathMatch(String pathSpec, String path)
{
{
char c = pathSpec.charAt(0);
if (c=='/')
{
if (pathSpec.length()==1)
return path;
if (pathSpec.equals(path))
return path;
if (isPathWildcardMatch(pathSpec, path))
return path.substring(0,pathSpec.length()-2);
}
@ -448,7 +448,7 @@ public class PathMap extends HashMap implements Externalizable
}
return null;
}
/* --------------------------------------------------------------- */
/** Return the portion of a path that is after a path spec.
* @return The path info string
@ -456,12 +456,12 @@ public class PathMap extends HashMap implements Externalizable
public static String pathInfo(String pathSpec, String path)
{
char c = pathSpec.charAt(0);
if (c=='/')
{
if (pathSpec.length()==1)
return null;
boolean wildcard = isPathWildcardMatch(pathSpec, path);
// handle the case where pathSpec uses a wildcard and path info is "/*"
@ -474,7 +474,7 @@ public class PathMap extends HashMap implements Externalizable
return null;
return path.substring(pathSpec.length()-2);
}
}
}
return null;
}
@ -484,7 +484,7 @@ public class PathMap extends HashMap implements Externalizable
* @param base The base the path is relative to.
* @param pathSpec The spec of the path segment to ignore.
* @param path the additional path
* @return base plus path with pathspec removed
* @return base plus path with pathspec removed
*/
public static String relativePath(String base,
String pathSpec,
@ -508,7 +508,7 @@ public class PathMap extends HashMap implements Externalizable
path = base + URIUtil.SLASH + info;
return path;
}
/* ------------------------------------------------------------ */
/* ------------------------------------------------------------ */
/* ------------------------------------------------------------ */
@ -516,7 +516,7 @@ public class PathMap extends HashMap implements Externalizable
{
private final Object key;
private final Object value;
private String mapped;
private String mapped;
private transient String string;
Entry(Object key, Object value)
@ -529,7 +529,7 @@ public class PathMap extends HashMap implements Externalizable
{
return key;
}
public Object getValue()
{
return value;

View File

@ -21,6 +21,7 @@ import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.net.InetAddress;
import java.security.InvalidParameterException;
import java.security.KeyStore;
import java.security.SecureRandom;
@ -42,7 +43,10 @@ import javax.net.ssl.KeyManager;
import javax.net.ssl.KeyManagerFactory;
import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLEngine;
import javax.net.ssl.SSLSessionContext;
import javax.net.ssl.SSLServerSocket;
import javax.net.ssl.SSLServerSocketFactory;
import javax.net.ssl.SSLSocket;
import javax.net.ssl.SSLSocketFactory;
import javax.net.ssl.TrustManager;
import javax.net.ssl.TrustManagerFactory;
import javax.net.ssl.X509KeyManager;
@ -51,6 +55,8 @@ import javax.net.ssl.X509TrustManager;
import org.eclipse.jetty.http.security.Password;
import org.eclipse.jetty.util.IO;
import org.eclipse.jetty.util.component.AbstractLifeCycle;
import org.eclipse.jetty.util.log.Log;
import org.eclipse.jetty.util.log.Logger;
import org.eclipse.jetty.util.resource.Resource;
import org.eclipse.jetty.util.security.CertificateUtils;
import org.eclipse.jetty.util.security.CertificateValidator;
@ -65,6 +71,8 @@ import org.eclipse.jetty.util.security.CertificateValidator;
*/
public class SslContextFactory extends AbstractLifeCycle
{
private static final Logger LOG = Log.getLogger(SslContextFactory.class);
public static final String DEFAULT_KEYMANAGERFACTORY_ALGORITHM =
(Security.getProperty("ssl.KeyManagerFactory.algorithm") == null ?
"SunX509" : Security.getProperty("ssl.KeyManagerFactory.algorithm"));
@ -82,8 +90,14 @@ public class SslContextFactory extends AbstractLifeCycle
/** String name of keystore password property. */
public static final String PASSWORD_PROPERTY = "org.eclipse.jetty.ssl.password";
/** Excluded protocols. */
private final Set<String> _excludeProtocols = new HashSet<String>();
// private final Set<String> _excludeProtocols = new HashSet<String>(Collections.singleton("SSLv2Hello"));
/** Included protocols. */
private Set<String> _includeProtocols = null;
/** Excluded cipher suites. */
private Set<String> _excludeCipherSuites = null;
private final Set<String> _excludeCipherSuites = new HashSet<String>();
/** Included cipher suites. */
private Set<String> _includeCipherSuites = null;
@ -196,6 +210,7 @@ public class SslContextFactory extends AbstractLifeCycle
if (_keyStoreInputStream == null && _keyStorePath == null &&
_trustStoreInputStream == null && _trustStorePath == null )
{
LOG.debug("No keystore or trust store configured. ACCEPTING UNTRUSTED CERTIFICATES!!!!!");
// Create a trust manager that does not validate certificate chains
TrustManager trustAllCerts = new X509TrustManager()
{
@ -218,11 +233,115 @@ public class SslContextFactory extends AbstractLifeCycle
}
else
{
createSSLContext();
// verify that keystore and truststore
// parameters are set up correctly
try
{
checkKeyStore();
}
catch(IllegalStateException e)
{
LOG.ignore(e);
}
KeyStore keyStore = loadKeyStore();
KeyStore trustStore = loadTrustStore();
Collection<? extends CRL> crls = loadCRL(_crlPath);
if (_validateCerts && keyStore != null)
{
if (_certAlias == null)
{
List<String> aliases = Collections.list(keyStore.aliases());
_certAlias = aliases.size() == 1 ? aliases.get(0) : null;
}
Certificate cert = _certAlias == null?null:keyStore.getCertificate(_certAlias);
if (cert == null)
{
throw new Exception("No certificate found in the keystore" + (_certAlias==null ? "":" for alias " + _certAlias));
}
CertificateValidator validator = new CertificateValidator(trustStore, crls);
validator.setMaxCertPathLength(_maxCertPathLength);
validator.setEnableCRLDP(_enableCRLDP);
validator.setEnableOCSP(_enableOCSP);
validator.setOcspResponderURL(_ocspResponderURL);
validator.validate(keyStore, cert);
}
KeyManager[] keyManagers = getKeyManagers(keyStore);
TrustManager[] trustManagers = getTrustManagers(trustStore,crls);
SecureRandom secureRandom = (_secureRandomAlgorithm == null)?null:SecureRandom.getInstance(_secureRandomAlgorithm);
_context = (_sslProvider == null)?SSLContext.getInstance(_sslProtocol):SSLContext.getInstance(_sslProtocol,_sslProvider);
_context.init(keyManagers,trustManagers,secureRandom);
SSLEngine engine=newSslEngine();
LOG.info("Enabled Protocols {} of {}",Arrays.asList(engine.getEnabledProtocols()),Arrays.asList(engine.getSupportedProtocols()));
LOG.debug("Enabled Ciphers {} of {}",Arrays.asList(engine.getEnabledCipherSuites()),Arrays.asList(engine.getSupportedCipherSuites()));
}
}
}
/* ------------------------------------------------------------ */
/**
* @return The array of protocol names to exclude from
* {@link SSLEngine#setEnabledProtocols(String[])}
*/
public String[] getExcludeProtocols()
{
return _excludeProtocols.toArray(new String[_excludeProtocols.size()]);
}
/* ------------------------------------------------------------ */
/**
* @param Protocols
* The array of protocol names to exclude from
* {@link SSLEngine#setEnabledProtocols(String[])}
*/
public void setExcludeProtocols(String... protocols)
{
checkNotStarted();
_excludeProtocols.clear();
_excludeProtocols.addAll(Arrays.asList(protocols));
}
/* ------------------------------------------------------------ */
/**
* @param protocol Protocol names to add to {@link SSLEngine#setEnabledProtocols(String[])}
*/
public void addExcludeProtocols(String... protocol)
{
checkNotStarted();
_excludeProtocols.addAll(Arrays.asList(protocol));
}
/* ------------------------------------------------------------ */
/**
* @return The array of protocol names to include in
* {@link SSLEngine#setEnabledProtocols(String[])}
*/
public String[] getIncludeProtocols()
{
return _includeProtocols.toArray(new String[_includeProtocols.size()]);
}
/* ------------------------------------------------------------ */
/**
* @param Protocols
* The array of protocol names to include in
* {@link SSLEngine#setEnabledProtocols(String[])}
*/
public void setIncludeProtocols(String... protocols)
{
checkNotStarted();
_includeProtocols = new HashSet<String>(Arrays.asList(protocols));
}
/* ------------------------------------------------------------ */
/**
* @return The array of cipher suite names to exclude from
@ -239,11 +358,21 @@ public class SslContextFactory extends AbstractLifeCycle
* The array of cipher suite names to exclude from
* {@link SSLEngine#setEnabledCipherSuites(String[])}
*/
public void setExcludeCipherSuites(String[] cipherSuites)
public void setExcludeCipherSuites(String... cipherSuites)
{
checkStarted();
_excludeCipherSuites = new HashSet<String>(Arrays.asList(cipherSuites));
checkNotStarted();
_excludeCipherSuites.clear();
_excludeCipherSuites.addAll(Arrays.asList(cipherSuites));
}
/* ------------------------------------------------------------ */
/**
* @param cipher Cipher names to add to {@link SSLEngine#setEnabledCipherSuites(String[])}
*/
public void addExcludeCipherSuites(String... cipher)
{
checkNotStarted();
_excludeCipherSuites.addAll(Arrays.asList(cipher));
}
/* ------------------------------------------------------------ */
@ -262,9 +391,9 @@ public class SslContextFactory extends AbstractLifeCycle
* The array of cipher suite names to include in
* {@link SSLEngine#setEnabledCipherSuites(String[])}
*/
public void setIncludeCipherSuites(String[] cipherSuites)
public void setIncludeCipherSuites(String... cipherSuites)
{
checkStarted();
checkNotStarted();
_includeCipherSuites = new HashSet<String>(Arrays.asList(cipherSuites));
}
@ -285,7 +414,7 @@ public class SslContextFactory extends AbstractLifeCycle
*/
public void setKeyStore(String keyStorePath)
{
checkStarted();
checkNotStarted();
_keyStorePath = keyStorePath;
}
@ -306,7 +435,7 @@ public class SslContextFactory extends AbstractLifeCycle
*/
public void setKeyStoreProvider(String keyStoreProvider)
{
checkStarted();
checkNotStarted();
_keyStoreProvider = keyStoreProvider;
}
@ -327,7 +456,7 @@ public class SslContextFactory extends AbstractLifeCycle
*/
public void setKeyStoreType(String keyStoreType)
{
checkStarted();
checkNotStarted();
_keyStoreType = keyStoreType;
}
@ -341,7 +470,7 @@ public class SslContextFactory extends AbstractLifeCycle
@Deprecated
public InputStream getKeyStoreInputStream()
{
checkConfig();
checkKeyStore();
return _keyStoreInputStream;
}
@ -355,7 +484,7 @@ public class SslContextFactory extends AbstractLifeCycle
@Deprecated
public void setKeyStoreInputStream(InputStream keyStoreInputStream)
{
checkStarted();
checkNotStarted();
_keyStoreInputStream = keyStoreInputStream;
}
@ -376,7 +505,7 @@ public class SslContextFactory extends AbstractLifeCycle
*/
public void setCertAlias(String certAlias)
{
checkStarted();
checkNotStarted();
_certAlias = certAlias;
}
@ -397,7 +526,7 @@ public class SslContextFactory extends AbstractLifeCycle
*/
public void setTrustStore(String trustStorePath)
{
checkStarted();
checkNotStarted();
_trustStorePath = trustStorePath;
}
@ -418,7 +547,7 @@ public class SslContextFactory extends AbstractLifeCycle
*/
public void setTrustStoreProvider(String trustStoreProvider)
{
checkStarted();
checkNotStarted();
_trustStoreProvider = trustStoreProvider;
}
@ -439,7 +568,7 @@ public class SslContextFactory extends AbstractLifeCycle
*/
public void setTrustStoreType(String trustStoreType)
{
checkStarted();
checkNotStarted();
_trustStoreType = trustStoreType;
}
@ -453,7 +582,7 @@ public class SslContextFactory extends AbstractLifeCycle
@Deprecated
public InputStream getTrustStoreInputStream()
{
checkConfig();
checkKeyStore();
return _trustStoreInputStream;
}
@ -467,7 +596,7 @@ public class SslContextFactory extends AbstractLifeCycle
@Deprecated
public void setTrustStoreInputStream(InputStream trustStoreInputStream)
{
checkStarted();
checkNotStarted();
_trustStoreInputStream = trustStoreInputStream;
}
@ -490,7 +619,7 @@ public class SslContextFactory extends AbstractLifeCycle
*/
public void setNeedClientAuth(boolean needClientAuth)
{
checkStarted();
checkNotStarted();
_needClientAuth = needClientAuth;
}
@ -513,7 +642,7 @@ public class SslContextFactory extends AbstractLifeCycle
*/
public void setWantClientAuth(boolean wantClientAuth)
{
checkStarted();
checkNotStarted();
_wantClientAuth = wantClientAuth;
}
@ -545,7 +674,7 @@ public class SslContextFactory extends AbstractLifeCycle
*/
public void setValidateCerts(boolean validateCerts)
{
checkStarted();
checkNotStarted();
_validateCerts = validateCerts;
}
@ -566,7 +695,7 @@ public class SslContextFactory extends AbstractLifeCycle
*/
public void setValidatePeerCerts(boolean validatePeerCerts)
{
checkStarted();
checkNotStarted();
_validatePeerCerts = validatePeerCerts;
}
@ -593,7 +722,7 @@ public class SslContextFactory extends AbstractLifeCycle
*/
public void setAllowRenegotiate(boolean allowRenegotiate)
{
checkStarted();
checkNotStarted();
_allowRenegotiate = allowRenegotiate;
}
@ -605,7 +734,7 @@ public class SslContextFactory extends AbstractLifeCycle
*/
public void setKeyStorePassword(String password)
{
checkStarted();
checkNotStarted();
_keyStorePassword = Password.getPassword(PASSWORD_PROPERTY,password,null);
}
@ -617,7 +746,7 @@ public class SslContextFactory extends AbstractLifeCycle
*/
public void setKeyManagerPassword(String password)
{
checkStarted();
checkNotStarted();
_keyManagerPassword = Password.getPassword(KEYPASSWORD_PROPERTY,password,null);
}
@ -629,7 +758,7 @@ public class SslContextFactory extends AbstractLifeCycle
*/
public void setTrustStorePassword(String password)
{
checkStarted();
checkNotStarted();
_trustStorePassword = Password.getPassword(PASSWORD_PROPERTY,password,null);
}
@ -652,7 +781,7 @@ public class SslContextFactory extends AbstractLifeCycle
*/
public void setProvider(String provider)
{
checkStarted();
checkNotStarted();
_sslProvider = provider;
}
@ -675,7 +804,7 @@ public class SslContextFactory extends AbstractLifeCycle
*/
public void setProtocol(String protocol)
{
checkStarted();
checkNotStarted();
_sslProtocol = protocol;
}
@ -700,7 +829,7 @@ public class SslContextFactory extends AbstractLifeCycle
*/
public void setSecureRandomAlgorithm(String algorithm)
{
checkStarted();
checkNotStarted();
_secureRandomAlgorithm = algorithm;
}
@ -721,7 +850,7 @@ public class SslContextFactory extends AbstractLifeCycle
*/
public void setSslKeyManagerFactoryAlgorithm(String algorithm)
{
checkStarted();
checkNotStarted();
_keyManagerFactoryAlgorithm = algorithm;
}
@ -742,7 +871,7 @@ public class SslContextFactory extends AbstractLifeCycle
*/
public void setTrustManagerFactoryAlgorithm(String algorithm)
{
checkStarted();
checkNotStarted();
_trustManagerFactoryAlgorithm = algorithm;
}
@ -763,7 +892,7 @@ public class SslContextFactory extends AbstractLifeCycle
*/
public void setCrlPath(String crlPath)
{
checkStarted();
checkNotStarted();
_crlPath = crlPath;
}
@ -786,7 +915,7 @@ public class SslContextFactory extends AbstractLifeCycle
*/
public void setMaxCertPathLength(int maxCertPathLength)
{
checkStarted();
checkNotStarted();
_maxCertPathLength = maxCertPathLength;
}
@ -797,6 +926,8 @@ public class SslContextFactory extends AbstractLifeCycle
*/
public SSLContext getSslContext()
{
if (!isStarted())
throw new IllegalStateException(getState());
return _context;
}
@ -807,60 +938,11 @@ public class SslContextFactory extends AbstractLifeCycle
*/
public void setSslContext(SSLContext sslContext)
{
checkStarted();
checkNotStarted();
_context = sslContext;
}
/* ------------------------------------------------------------ */
/**
* @throws Exception
*/
protected void createSSLContext() throws Exception
{
// verify that keystore and truststore
// parameters are set up correctly
checkConfig();
KeyStore keyStore = loadKeyStore();
KeyStore trustStore = loadTrustStore();
Collection<? extends CRL> crls = loadCRL(_crlPath);
if (_validateCerts && keyStore != null)
{
if (_certAlias == null)
{
List<String> aliases = Collections.list(keyStore.aliases());
_certAlias = aliases.size() == 1 ? aliases.get(0) : null;
}
Certificate cert = _certAlias == null?null:keyStore.getCertificate(_certAlias);
if (cert == null)
{
throw new Exception("No certificate found in the keystore" + (_certAlias==null ? "":" for alias " + _certAlias));
}
CertificateValidator validator = new CertificateValidator(trustStore, crls);
validator.setMaxCertPathLength(_maxCertPathLength);
validator.setEnableCRLDP(_enableCRLDP);
validator.setEnableOCSP(_enableOCSP);
validator.setOcspResponderURL(_ocspResponderURL);
validator.validate(keyStore, cert);
}
KeyManager[] keyManagers = getKeyManagers(keyStore);
TrustManager[] trustManagers = getTrustManagers(trustStore,crls);
SecureRandom secureRandom = (_secureRandomAlgorithm == null)?null:SecureRandom.getInstance(_secureRandomAlgorithm);
_context = (_sslProvider == null)?SSLContext.getInstance(_sslProtocol):SSLContext.getInstance(_sslProtocol,_sslProvider);
_context.init(keyManagers,trustManagers,secureRandom);
SSLSessionContext sslSessionContext = _context.getServerSessionContext();
sslSessionContext.setSessionCacheSize(_sslSessionCacheSize);
sslSessionContext.setSessionTimeout(_sslSessionTimeout);
}
/* ------------------------------------------------------------ */
/**
* Override this method to provide alternate way to load a keystore.
@ -1014,33 +1096,27 @@ public class SslContextFactory extends AbstractLifeCycle
/* ------------------------------------------------------------ */
/**
* Check configuration. Ensures that if keystore has been
* Check KetyStore Configuration. Ensures that if keystore has been
* configured but there's no truststore, that keystore is
* used as truststore.
* @return true SslContextFactory configuration can be used in server connector.
* @throws IllegalStateException if SslContextFactory configuration can't be used.
*/
public boolean checkConfig()
public void checkKeyStore()
{
boolean check = true;
if (_keyStore == null && _keyStoreInputStream == null && _keyStorePath == null)
throw new IllegalStateException("SSL doesn't have a valid keystore");
// if the keystore has been configured but there is no
// truststore configured, use the keystore as the truststore
if (_trustStore == null && _trustStoreInputStream == null && _trustStorePath == null)
{
// configuration doesn't have a valid keystore
check = false;
}
else
{
// if the keystore has been configured but there is no
// truststore configured, use the keystore as the truststore
if (_trustStore == null && _trustStoreInputStream == null && _trustStorePath == null)
{
_trustStore = _keyStore;
_trustStorePath = _keyStorePath;
_trustStoreInputStream = _keyStoreInputStream;
_trustStoreType = _keyStoreType;
_trustStoreProvider = _keyStoreProvider;
_trustStorePassword = _keyStorePassword;
_trustManagerFactoryAlgorithm = _keyManagerFactoryAlgorithm;
}
_trustStore = _keyStore;
_trustStorePath = _keyStorePath;
_trustStoreInputStream = _keyStoreInputStream;
_trustStoreType = _keyStoreType;
_trustStoreProvider = _keyStoreProvider;
_trustStorePassword = _keyStorePassword;
_trustManagerFactoryAlgorithm = _keyManagerFactoryAlgorithm;
}
// It's the same stream we cannot read it twice, so read it once in memory
@ -1057,11 +1133,9 @@ public class SslContextFactory extends AbstractLifeCycle
}
catch (Exception ex)
{
throw new RuntimeException(ex);
throw new IllegalStateException(ex);
}
}
return check;
}
/* ------------------------------------------------------------ */
@ -1073,57 +1147,68 @@ public class SslContextFactory extends AbstractLifeCycle
* @param supportedCipherSuites Array of supported cipher suites
* @return Array of cipher suites to enable
*/
public String[] selectCipherSuites(String[] enabledCipherSuites, String[] supportedCipherSuites)
public String[] selectProtocols(String[] enabledProtocols, String[] supportedProtocols)
{
Set<String> selectedCipherSuites = null;
if (enabledCipherSuites != null)
Set<String> selected_protocols = new HashSet<String>();
// Set the starting protocols - either from the included or enabled list
if (_includeProtocols!=null)
{
selectedCipherSuites = new HashSet<String>(Arrays.asList(enabledCipherSuites));
// Use only the supported included protocols
for (String protocol : supportedProtocols)
if (_includeProtocols.contains(protocol))
selected_protocols.add(protocol);
}
else
selected_protocols.addAll(Arrays.asList(enabledProtocols));
// Remove any excluded protocols
if (_excludeProtocols != null)
selected_protocols.removeAll(_excludeProtocols);
return selected_protocols.toArray(new String[selected_protocols.size()]);
}
/* ------------------------------------------------------------ */
/**
* Select cipher suites to be used by the connector
* based on configured inclusion and exclusion lists
* as well as enabled and supported cipher suite lists.
* @param enabledCipherSuites Array of enabled cipher suites
* @param supportedCipherSuites Array of supported cipher suites
* @return Array of cipher suites to enable
*/
public String[] selectCipherSuites(String[] enabledCipherSuites, String[] supportedCipherSuites)
{
Set<String> selected_ciphers = new HashSet<String>();
// Set the starting ciphers - either from the included or enabled list
if (_includeCipherSuites!=null)
{
selectedCipherSuites = new HashSet<String>();
// Use only the supported included ciphers
for (String cipherSuite : supportedCipherSuites)
if (_includeCipherSuites.contains(cipherSuite))
selected_ciphers.add(cipherSuite);
}
if ((supportedCipherSuites != null && supportedCipherSuites.length > 0) &&
(_includeCipherSuites != null && _includeCipherSuites.size() > 0))
{
Set<String> supportedCSList = new HashSet<String>(Arrays.asList(supportedCipherSuites));
for (String cipherName : _includeCipherSuites)
{
if ((!selectedCipherSuites.contains(cipherName)) &&
supportedCSList.contains(cipherName))
{
selectedCipherSuites.add(cipherName);
}
}
}
if (_excludeCipherSuites != null && _excludeCipherSuites.size() > 0)
{
for (String cipherName : _excludeCipherSuites)
{
if (selectedCipherSuites.contains(cipherName))
{
selectedCipherSuites.remove(cipherName);
}
}
}
return selectedCipherSuites.toArray(new String[selectedCipherSuites.size()]);
else
selected_ciphers.addAll(Arrays.asList(enabledCipherSuites));
// Remove any excluded ciphers
if (_excludeCipherSuites != null)
selected_ciphers.removeAll(_excludeCipherSuites);
return selected_ciphers.toArray(new String[selected_ciphers.size()]);
}
/* ------------------------------------------------------------ */
/**
* Check if the lifecycle has been started and throw runtime exception
*/
protected void checkStarted()
protected void checkNotStarted()
{
if (isStarted())
{
throw new IllegalStateException("Cannot modify configuration after SslContextFactory was started");
}
throw new IllegalStateException("Cannot modify configuration when "+getState());
}
/* ------------------------------------------------------------ */
@ -1141,7 +1226,7 @@ public class SslContextFactory extends AbstractLifeCycle
*/
public void setEnableCRLDP(boolean enableCRLDP)
{
checkStarted();
checkNotStarted();
_enableCRLDP = enableCRLDP;
}
@ -1161,7 +1246,7 @@ public class SslContextFactory extends AbstractLifeCycle
*/
public void setEnableOCSP(boolean enableOCSP)
{
checkStarted();
checkNotStarted();
_enableOCSP = enableOCSP;
}
@ -1181,7 +1266,7 @@ public class SslContextFactory extends AbstractLifeCycle
*/
public void setOcspResponderURL(String ocspResponderURL)
{
checkStarted();
checkNotStarted();
_ocspResponderURL = ocspResponderURL;
}
@ -1192,7 +1277,7 @@ public class SslContextFactory extends AbstractLifeCycle
*/
public void setKeyStore(KeyStore keyStore)
{
checkStarted();
checkNotStarted();
_keyStore = keyStore;
}
@ -1203,7 +1288,7 @@ public class SslContextFactory extends AbstractLifeCycle
*/
public void setTrustStore(KeyStore trustStore)
{
checkStarted();
checkNotStarted();
_trustStore = trustStore;
}
@ -1214,7 +1299,7 @@ public class SslContextFactory extends AbstractLifeCycle
*/
public void setKeyStoreResource(Resource resource)
{
checkStarted();
checkNotStarted();
try
{
@ -1233,7 +1318,7 @@ public class SslContextFactory extends AbstractLifeCycle
*/
public void setTrustStore(Resource resource)
{
checkStarted();
checkNotStarted();
try
{
@ -1299,4 +1384,83 @@ public class SslContextFactory extends AbstractLifeCycle
{
_sslSessionTimeout = sslSessionTimeout;
}
/* ------------------------------------------------------------ */
public SSLServerSocket newSslServerSocket(String host,int port,int backlog) throws IOException
{
SSLServerSocketFactory factory = _context.getServerSocketFactory();
SSLServerSocket socket =
(SSLServerSocket) (host==null ?
factory.createServerSocket(port,backlog):
factory.createServerSocket(port,backlog,InetAddress.getByName(host)));
if (getWantClientAuth())
socket.setWantClientAuth(getWantClientAuth());
if (getNeedClientAuth())
socket.setNeedClientAuth(getNeedClientAuth());
socket.setEnabledCipherSuites(selectCipherSuites(
socket.getEnabledCipherSuites(),
socket.getSupportedCipherSuites()));
socket.setEnabledProtocols(selectProtocols(socket.getEnabledProtocols(),socket.getSupportedProtocols()));
return socket;
}
/* ------------------------------------------------------------ */
public SSLSocket newSslSocket() throws IOException
{
SSLSocketFactory factory = _context.getSocketFactory();
SSLSocket socket = (SSLSocket)factory.createSocket();
if (getWantClientAuth())
socket.setWantClientAuth(getWantClientAuth());
if (getNeedClientAuth())
socket.setNeedClientAuth(getNeedClientAuth());
socket.setEnabledCipherSuites(selectCipherSuites(
socket.getEnabledCipherSuites(),
socket.getSupportedCipherSuites()));
socket.setEnabledProtocols(selectProtocols(socket.getEnabledProtocols(),socket.getSupportedProtocols()));
return socket;
}
/* ------------------------------------------------------------ */
public SSLEngine newSslEngine(String host,int port)
{
SSLEngine sslEngine=isSessionCachingEnabled()
?_context.createSSLEngine(host, port)
:_context.createSSLEngine();
customize(sslEngine);
return sslEngine;
}
/* ------------------------------------------------------------ */
public SSLEngine newSslEngine()
{
SSLEngine sslEngine=_context.createSSLEngine();
customize(sslEngine);
return sslEngine;
}
/* ------------------------------------------------------------ */
public void customize(SSLEngine sslEngine)
{
if (getWantClientAuth())
sslEngine.setWantClientAuth(getWantClientAuth());
if (getNeedClientAuth())
sslEngine.setNeedClientAuth(getNeedClientAuth());
sslEngine.setEnabledCipherSuites(selectCipherSuites(
sslEngine.getEnabledCipherSuites(),
sslEngine.getSupportedCipherSuites()));
sslEngine.setEnabledProtocols(selectProtocols(sslEngine.getEnabledProtocols(),sslEngine.getSupportedProtocols()));
}
}

View File

@ -109,9 +109,12 @@ public class ChannelEndPoint implements EndPoint
if (_channel.isOpen() && _channel instanceof SocketChannel)
{
Socket socket= ((SocketChannel)_channel).socket();
if (!socket.isClosed()&&!socket.isInputShutdown())
if (!socket.isClosed())
{
socket.shutdownInput();
if(socket.isOutputShutdown())
socket.close();
else if (!socket.isInputShutdown())
socket.shutdownInput();
}
}
}
@ -124,9 +127,12 @@ public class ChannelEndPoint implements EndPoint
if (_channel.isOpen() && _channel instanceof SocketChannel)
{
Socket socket= ((SocketChannel)_channel).socket();
if (!socket.isClosed()&&!socket.isOutputShutdown())
if (!socket.isClosed())
{
socket.shutdownOutput();
if (socket.isInputShutdown())
socket.close();
else if (!socket.isOutputShutdown())
socket.shutdownOutput();
}
}
}
@ -160,8 +166,8 @@ public class ChannelEndPoint implements EndPoint
{
final NIOBuffer nbuf = (NIOBuffer)buf;
final ByteBuffer bbuf=nbuf.getByteBuffer();
//noinspection SynchronizationOnLocalVariableOrMethodParameter
//noinspection SynchronizationOnLocalVariableOrMethodParameter
try
{
synchronized(bbuf)
@ -178,13 +184,17 @@ public class ChannelEndPoint implements EndPoint
}
}
if (len<0 && isOpen() && !isInputShutdown())
if (len<0 && isOpen())
{
shutdownInput();
if (!isInputShutdown())
shutdownInput();
else if (isOutputShutdown())
_channel.close();
}
}
catch (IOException x)
{
LOG.debug(x);
try
{
close();
@ -196,7 +206,6 @@ public class ChannelEndPoint implements EndPoint
if (len>0)
throw x;
LOG.ignore(x);
len=-1;
}
}

View File

@ -34,7 +34,7 @@ import org.eclipse.jetty.util.log.Logger;
*/
public class SelectChannelEndPoint extends ChannelEndPoint implements AsyncEndPoint, ConnectedEndPoint
{
public static final Logger __log=Log.getLogger("org.eclipse.jetty.io.nio");
public static final Logger LOG=Log.getLogger("org.eclipse.jetty.io.nio");
private final SelectorManager.SelectSet _selectSet;
private final SelectorManager _manager;
@ -54,7 +54,7 @@ public class SelectChannelEndPoint extends ChannelEndPoint implements AsyncEndPo
private boolean _writeBlocked;
private boolean _open;
private volatile long _idleTimestamp;
/* ------------------------------------------------------------ */
public SelectChannelEndPoint(SocketChannel channel, SelectSet selectSet, SelectionKey key, int maxIdleTime)
throws IOException
@ -90,6 +90,7 @@ public class SelectChannelEndPoint extends ChannelEndPoint implements AsyncEndPo
scheduleIdle();
}
/* ------------------------------------------------------------ */
public SelectionKey getSelectionKey()
{
@ -205,7 +206,7 @@ public class SelectChannelEndPoint extends ChannelEndPoint implements AsyncEndPo
if(!dispatched)
{
_dispatched = false;
__log.warn("Dispatched Failed! "+this+" to "+_manager);
LOG.warn("Dispatched Failed! "+this+" to "+_manager);
updateKey();
}
}
@ -250,7 +251,7 @@ public class SelectChannelEndPoint extends ChannelEndPoint implements AsyncEndPo
public void checkIdleTimestamp(long now)
{
long idleTimestamp=_idleTimestamp;
if (idleTimestamp!=0 && _maxIdleTime>0 && now>(idleTimestamp+_maxIdleTime))
if (!getChannel().isOpen() || idleTimestamp!=0 && _maxIdleTime>0 && now>(idleTimestamp+_maxIdleTime))
idleExpired();
}
@ -260,6 +261,15 @@ public class SelectChannelEndPoint extends ChannelEndPoint implements AsyncEndPo
_connection.idleExpired();
}
/* ------------------------------------------------------------ */
/**
* @return True if the endpoint has produced/consumed bytes itself (non application data).
*/
public boolean isProgressing()
{
return false;
}
/* ------------------------------------------------------------ */
/*
*/
@ -340,7 +350,7 @@ public class SelectChannelEndPoint extends ChannelEndPoint implements AsyncEndPo
}
catch (InterruptedException e)
{
__log.warn(e);
LOG.warn(e);
}
finally
{
@ -385,7 +395,7 @@ public class SelectChannelEndPoint extends ChannelEndPoint implements AsyncEndPo
}
catch (InterruptedException e)
{
__log.warn(e);
LOG.warn(e);
}
finally
{
@ -398,7 +408,7 @@ public class SelectChannelEndPoint extends ChannelEndPoint implements AsyncEndPo
catch(Throwable e)
{
// TODO remove this if it finds nothing
__log.warn(e);
LOG.warn(e);
if (e instanceof RuntimeException)
throw (RuntimeException)e;
if (e instanceof Error)
@ -414,10 +424,20 @@ public class SelectChannelEndPoint extends ChannelEndPoint implements AsyncEndPo
}
return true;
}
/* ------------------------------------------------------------ */
/* short cut for busyselectChannelServerTest */
public void clearWritable()
{
_writable=false;
}
/* ------------------------------------------------------------ */
public void scheduleWrite()
{
if (_writable==true)
LOG.debug("Required scheduleWrite {}",this);
_writable=false;
updateKey();
}
@ -445,7 +465,7 @@ public class SelectChannelEndPoint extends ChannelEndPoint implements AsyncEndPo
catch(Exception e)
{
_key=null;
__log.ignore(e);
LOG.ignore(e);
}
}
@ -483,7 +503,7 @@ public class SelectChannelEndPoint extends ChannelEndPoint implements AsyncEndPo
}
catch (Exception e)
{
__log.ignore(e);
LOG.ignore(e);
if (_key!=null && _key.isValid())
{
_key.cancel();
@ -520,9 +540,9 @@ public class SelectChannelEndPoint extends ChannelEndPoint implements AsyncEndPo
cancelIdle();
if (_open)
{
_open=false;
_selectSet.destroyEndPoint(this);
}
_open=false;
_key = null;
}
}
@ -545,7 +565,7 @@ public class SelectChannelEndPoint extends ChannelEndPoint implements AsyncEndPo
final Connection next = _connection.handle();
if (next!=_connection)
{
__log.debug("{} replaced {}",next,_connection);
LOG.debug("{} replaced {}",next,_connection);
_connection=next;
continue;
}
@ -554,26 +574,26 @@ public class SelectChannelEndPoint extends ChannelEndPoint implements AsyncEndPo
}
catch (ClosedChannelException e)
{
__log.ignore(e);
LOG.ignore(e);
}
catch (EofException e)
{
__log.debug("EOF", e);
try{close();}
catch(IOException e2){__log.ignore(e2);}
LOG.debug("EOF", e);
try{getChannel().close();}
catch(IOException e2){LOG.ignore(e2);}
}
catch (IOException e)
{
__log.warn(e.toString());
__log.debug(e);
try{close();}
catch(IOException e2){__log.ignore(e2);}
LOG.warn(e.toString());
LOG.debug(e);
try{getChannel().close();}
catch(IOException e2){LOG.ignore(e2);}
}
catch (Throwable e)
{
__log.warn("handle failed", e);
try{close();}
catch(IOException e2){__log.ignore(e2);}
LOG.warn("handle failed", e);
try{getChannel().close();}
catch(IOException e2){LOG.ignore(e2);}
}
dispatched=!undispatch();
}
@ -585,7 +605,7 @@ public class SelectChannelEndPoint extends ChannelEndPoint implements AsyncEndPo
dispatched=!undispatch();
while (dispatched)
{
__log.warn("SCEP.run() finally DISPATCHED");
LOG.warn("SCEP.run() finally DISPATCHED");
dispatched=!undispatch();
}
}
@ -605,7 +625,7 @@ public class SelectChannelEndPoint extends ChannelEndPoint implements AsyncEndPo
}
catch (IOException e)
{
__log.ignore(e);
LOG.ignore(e);
}
finally
{
@ -620,7 +640,7 @@ public class SelectChannelEndPoint extends ChannelEndPoint implements AsyncEndPo
synchronized(this)
{
return "SCEP@" + hashCode() + _channel+
"[d=" + _dispatched + ",io=" + _interestOps+
"[o="+isOpen()+" d=" + _dispatched + ",io=" + _interestOps+
",w=" + _writable + ",rb=" + _readBlocked + ",wb=" + _writeBlocked + "]";
}
}

View File

@ -4,11 +4,11 @@
// All rights reserved. This program and the accompanying materials
// are made available under the terms of the Eclipse Public License v1.0
// and Apache License v2.0 which accompanies this distribution.
// The Eclipse Public License is available at
// The Eclipse Public License is available at
// http://www.eclipse.org/legal/epl-v10.html
// The Apache License v2.0 is available at
// http://www.opensource.org/licenses/apache2.0.php
// You may elect to redistribute this code under either of these licenses.
// You may elect to redistribute this code under either of these licenses.
// ========================================================================
package org.eclipse.jetty.io.nio;
@ -30,7 +30,6 @@ import java.util.concurrent.ConcurrentMap;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;
import org.eclipse.jetty.io.ConnectedEndPoint;
import org.eclipse.jetty.io.Connection;
import org.eclipse.jetty.io.EndPoint;
@ -49,21 +48,16 @@ import org.eclipse.jetty.util.thread.Timeout.Task;
* The Selector Manager manages and number of SelectSets to allow
* NIO scheduling to scale to large numbers of connections.
* <p>
* This class works around a number of know JVM bugs. For details
* see http://wiki.eclipse.org/Jetty/Feature/JVM_NIO_Bug
*/
public abstract class SelectorManager extends AbstractLifeCycle implements Dumpable
{
public static final Logger LOG=Log.getLogger("org.eclipse.jetty.io.nio");
// TODO Tune these by approx system speed.
private static final int __JVMBUG_THRESHHOLD=Integer.getInteger("org.eclipse.jetty.io.nio.JVMBUG_THRESHHOLD",0).intValue();
private static final int __MONITOR_PERIOD=Integer.getInteger("org.eclipse.jetty.io.nio.MONITOR_PERIOD",1000).intValue();
private static final int __MAX_SELECTS=Integer.getInteger("org.eclipse.jetty.io.nio.MAX_SELECTS",25000).intValue();
private static final int __BUSY_PAUSE=Integer.getInteger("org.eclipse.jetty.io.nio.BUSY_PAUSE",50).intValue();
private static final int __BUSY_KEY=Integer.getInteger("org.eclipse.jetty.io.nio.BUSY_KEY",-1).intValue();
private static final int __IDLE_TICK=Integer.getInteger("org.eclipse.jetty.io.nio.IDLE_TICK",400).intValue();
private int _maxIdleTime;
private int _lowResourcesMaxIdleTime;
private long _lowResourcesConnections;
@ -72,7 +66,7 @@ public abstract class SelectorManager extends AbstractLifeCycle implements Dumpa
private volatile int _set;
private boolean _deferringInterestedOps0=true;
private int _selectorPriorityDelta=0;
/* ------------------------------------------------------------ */
/**
* @param maxIdleTime The maximum period in milli seconds that a connection may be idle before it is closed.
@ -82,18 +76,18 @@ public abstract class SelectorManager extends AbstractLifeCycle implements Dumpa
{
_maxIdleTime=(int)maxIdleTime;
}
/* ------------------------------------------------------------ */
/**
* @param selectSets number of select sets to create
*/
public void setSelectSets(int selectSets)
{
long lrc = _lowResourcesConnections * _selectSets;
long lrc = _lowResourcesConnections * _selectSets;
_selectSets=selectSets;
_lowResourcesConnections=lrc/_selectSets;
}
/* ------------------------------------------------------------ */
/**
* @return the max idle time
@ -102,7 +96,7 @@ public abstract class SelectorManager extends AbstractLifeCycle implements Dumpa
{
return _maxIdleTime;
}
/* ------------------------------------------------------------ */
/**
* @return the number of select sets in use
@ -114,14 +108,14 @@ public abstract class SelectorManager extends AbstractLifeCycle implements Dumpa
/* ------------------------------------------------------------ */
/**
* @param i
* @param i
* @return The select set
*/
public SelectSet getSelectSet(int i)
{
return _selectSet[i];
}
/* ------------------------------------------------------------ */
/** Register a channel
* @param channel
@ -132,8 +126,8 @@ public abstract class SelectorManager extends AbstractLifeCycle implements Dumpa
// The ++ increment here is not atomic, but it does not matter.
// so long as the value changes sometimes, then connections will
// be distributed over the available sets.
int s=_set++;
int s=_set++;
s=s%_selectSets;
SelectSet[] sets=_selectSet;
if (sets!=null)
@ -144,7 +138,7 @@ public abstract class SelectorManager extends AbstractLifeCycle implements Dumpa
}
}
/* ------------------------------------------------------------ */
/** Register a channel
* @param channel
@ -154,8 +148,8 @@ public abstract class SelectorManager extends AbstractLifeCycle implements Dumpa
// The ++ increment here is not atomic, but it does not matter.
// so long as the value changes sometimes, then connections will
// be distributed over the available sets.
int s=_set++;
int s=_set++;
s=s%_selectSets;
SelectSet[] sets=_selectSet;
if (sets!=null)
@ -165,14 +159,14 @@ public abstract class SelectorManager extends AbstractLifeCycle implements Dumpa
set.wakeup();
}
}
/* ------------------------------------------------------------ */
/** Register a {@link ServerSocketChannel}
* @param acceptChannel
*/
public void register(ServerSocketChannel acceptChannel)
{
int s=_set++;
int s=_set++;
s=s%_selectSets;
SelectSet set=_selectSet[s];
set.addChange(acceptChannel);
@ -196,8 +190,8 @@ public abstract class SelectorManager extends AbstractLifeCycle implements Dumpa
{
_selectorPriorityDelta=delta;
}
/* ------------------------------------------------------------ */
/**
* @return the lowResourcesConnections
@ -237,7 +231,7 @@ public abstract class SelectorManager extends AbstractLifeCycle implements Dumpa
{
_lowResourcesMaxIdleTime=(int)lowResourcesMaxIdleTime;
}
/* ------------------------------------------------------------------------------- */
public abstract boolean dispatch(Runnable task);
@ -254,7 +248,7 @@ public abstract class SelectorManager extends AbstractLifeCycle implements Dumpa
_selectSet[i]= new SelectSet(i);
super.doStart();
// start a thread to Select
for (int i=0;i<getSelectSets();i++)
{
@ -271,7 +265,7 @@ public abstract class SelectorManager extends AbstractLifeCycle implements Dumpa
if (sets==null)
return;
SelectSet set=sets[id];
Thread.currentThread().setName(name+" Selector"+id);
if (getSelectorPriorityDelta()!=0)
Thread.currentThread().setPriority(Thread.currentThread().getPriority()+getSelectorPriorityDelta());
@ -362,7 +356,7 @@ public abstract class SelectorManager extends AbstractLifeCycle implements Dumpa
LOG.warn(ex+","+channel+","+attachment);
LOG.debug(ex);
}
/* ------------------------------------------------------------ */
public String dump()
{
@ -375,8 +369,8 @@ public abstract class SelectorManager extends AbstractLifeCycle implements Dumpa
out.append(String.valueOf(this)).append("\n");
AggregateLifeCycle.dump(out,indent,TypeUtil.asList(_selectSet));
}
/* ------------------------------------------------------------------------------- */
/* ------------------------------------------------------------------------------- */
/* ------------------------------------------------------------------------------- */
@ -384,27 +378,19 @@ public abstract class SelectorManager extends AbstractLifeCycle implements Dumpa
{
private final int _setID;
private final Timeout _timeout;
private final ConcurrentLinkedQueue<Object> _changes = new ConcurrentLinkedQueue<Object>();
private volatile Selector _selector;
private volatile Thread _selecting;
private int _jvmBug;
private int _selects;
private long _monitorStart;
private int _busySelects;
private long _monitorNext;
private boolean _pausing;
private SelectionKey _busyKey;
private int _busyKeyCount;
private long _log;
private int _paused;
private int _jvmFix0;
private int _jvmFix1;
private int _jvmFix2;
private boolean _paused;
private volatile long _idleTick;
private ConcurrentMap<SelectChannelEndPoint,Object> _endPoints = new ConcurrentHashMap<SelectChannelEndPoint, Object>();
/* ------------------------------------------------------------ */
SelectSet(int acceptorID) throws Exception
{
@ -416,11 +402,9 @@ public abstract class SelectorManager extends AbstractLifeCycle implements Dumpa
// create a selector;
_selector = Selector.open();
_monitorStart=System.currentTimeMillis();
_monitorNext=_monitorStart+__MONITOR_PERIOD;
_log=_monitorStart+60000;
_monitorNext=System.currentTimeMillis()+__MONITOR_PERIOD;
}
/* ------------------------------------------------------------ */
public void addChange(Object change)
{
@ -429,7 +413,7 @@ public abstract class SelectorManager extends AbstractLifeCycle implements Dumpa
/* ------------------------------------------------------------ */
public void addChange(SelectableChannel channel, Object att)
{
{
if (att==null)
addChange(channel);
else if (att instanceof EndPoint)
@ -437,11 +421,11 @@ public abstract class SelectorManager extends AbstractLifeCycle implements Dumpa
else
addChange(new ChannelAndAttachment(channel,att));
}
/* ------------------------------------------------------------ */
/**
* Select and dispatch tasks found from changes and the selector.
*
*
* @throws IOException
*/
public void doSelect() throws IOException
@ -450,6 +434,9 @@ public abstract class SelectorManager extends AbstractLifeCycle implements Dumpa
{
_selecting=Thread.currentThread();
final Selector selector=_selector;
// Stopped concurrently ?
if (selector == null)
return;
// Make any key changes required
Object change;
@ -458,7 +445,7 @@ public abstract class SelectorManager extends AbstractLifeCycle implements Dumpa
{
Channel ch=null;
SelectionKey key=null;
try
{
if (change instanceof EndPoint)
@ -475,7 +462,7 @@ public abstract class SelectorManager extends AbstractLifeCycle implements Dumpa
final SelectableChannel channel=asc._channel;
ch=channel;
final Object att = asc._attachment;
if ((channel instanceof SocketChannel) && ((SocketChannel)channel).isConnected())
{
key = channel.register(selector,SelectionKey.OP_READ,att);
@ -517,7 +504,7 @@ public abstract class SelectorManager extends AbstractLifeCycle implements Dumpa
{
if (e instanceof ThreadDeath)
throw (ThreadDeath)e;
if (isRunning())
LOG.warn(e);
else
@ -525,7 +512,8 @@ public abstract class SelectorManager extends AbstractLifeCycle implements Dumpa
try
{
ch.close();
if (ch!=null)
ch.close();
}
catch(IOException e2)
{
@ -537,10 +525,9 @@ public abstract class SelectorManager extends AbstractLifeCycle implements Dumpa
// Do and instant select to see if any connections can be handled.
int selected=selector.selectNow();
_selects++;
long now=System.currentTimeMillis();
// if no immediate things to do
if (selected==0 && selector.selectedKeys().isEmpty())
{
@ -562,7 +549,7 @@ public abstract class SelectorManager extends AbstractLifeCycle implements Dumpa
_timeout.setNow(now);
long to_next_timeout=_timeout.getTimeToNext();
long wait = _changes.size()==0?__IDLE_TICK:0L;
long wait = _changes.size()==0?__IDLE_TICK:0L;
if (wait > 0 && to_next_timeout >= 0 && wait > to_next_timeout)
wait = to_next_timeout;
@ -571,24 +558,48 @@ public abstract class SelectorManager extends AbstractLifeCycle implements Dumpa
{
long before=now;
selected=selector.select(wait);
_selects++;
now = System.currentTimeMillis();
_timeout.setNow(now);
if (__JVMBUG_THRESHHOLD>0)
checkJvmBugs(before, now, wait, selected);
// If we are monitoring for busy selector
// and this select did not wait more than 1ms
if (__MONITOR_PERIOD>0 && now-before <=1)
{
// count this as a busy select and if there have been too many this monitor cycle
if (++_busySelects>__MAX_SELECTS)
{
// Start injecting pauses
_pausing=true;
// if this is the first pause
if (!_paused)
{
// Log and dump some status
_paused=true;
LOG.warn("Selector {} is too busy, pausing!",this);
final SelectSet set = this;
SelectorManager.this.dispatch(
new Runnable(){
public void run()
{
System.err.println(set+":\n"+set.dump());
}
});
}
}
}
}
}
// have we been destroyed while sleeping
if (_selector==null || !selector.isOpen())
return;
// Look for things to do
for (SelectionKey key: selector.selectedKeys())
{
{
SocketChannel channel=null;
try
{
if (!key.isValid())
@ -641,7 +652,7 @@ public abstract class SelectorManager extends AbstractLifeCycle implements Dumpa
SelectChannelEndPoint endpoint = createEndPoint(channel,key);
key.attach(endpoint);
if (key.isReadable())
endpoint.schedule();
endpoint.schedule();
}
key = null;
}
@ -665,15 +676,15 @@ public abstract class SelectorManager extends AbstractLifeCycle implements Dumpa
{
LOG.debug(e2);
}
if (key != null && !(key.channel() instanceof ServerSocketChannel) && key.isValid())
key.cancel();
}
}
// Everything always handled
selector.selectedKeys().clear();
now=System.currentTimeMillis();
_timeout.setNow(now);
Task task = _timeout.expired();
@ -688,11 +699,11 @@ public abstract class SelectorManager extends AbstractLifeCycle implements Dumpa
if (now-_idleTick>__IDLE_TICK)
{
_idleTick=now;
final long idle_now=((_lowResourcesConnections>0 && selector.keys().size()>_lowResourcesConnections))
?(now+_maxIdleTime-_lowResourcesMaxIdleTime)
:now;
dispatch(new Runnable()
{
public void run()
@ -703,6 +714,16 @@ public abstract class SelectorManager extends AbstractLifeCycle implements Dumpa
}
}
});
}
// Reset busy select monitor counts
if (__MONITOR_PERIOD>0 && now>_monitorNext)
{
_busySelects=0;
_pausing=false;
_monitorNext=now+__MONITOR_PERIOD;
}
}
catch (ClosedSelectorException e)
@ -721,130 +742,10 @@ public abstract class SelectorManager extends AbstractLifeCycle implements Dumpa
_selecting=null;
}
}
/* ------------------------------------------------------------ */
private void checkJvmBugs(long before, long now, long wait, int selected)
throws IOException
{
Selector selector = _selector;
if (selector==null)
return;
// Look for JVM bugs over a monitor period.
// http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=6403933
// http://bugs.sun.com/view_bug.do?bug_id=6693490
if (now>_monitorNext)
{
_selects=(int)(_selects*__MONITOR_PERIOD/(now-_monitorStart));
_pausing=_selects>__MAX_SELECTS;
if (_pausing)
_paused++;
_selects=0;
_jvmBug=0;
_monitorStart=now;
_monitorNext=now+__MONITOR_PERIOD;
}
if (now>_log)
{
if (_paused>0)
LOG.debug(this+" Busy selector - injecting delay "+_paused+" times");
if (_jvmFix2>0)
LOG.debug(this+" JVM BUG(s) - injecting delay"+_jvmFix2+" times");
if (_jvmFix1>0)
LOG.debug(this+" JVM BUG(s) - recreating selector "+_jvmFix1+" times, cancelled keys "+_jvmFix0+" times");
else if(LOG.isDebugEnabled() && _jvmFix0>0)
LOG.debug(this+" JVM BUG(s) - cancelled keys "+_jvmFix0+" times");
_paused=0;
_jvmFix2=0;
_jvmFix1=0;
_jvmFix0=0;
_log=now+60000;
}
// If we see signature of possible JVM bug, increment count.
if (selected==0 && wait>10 && (now-before)<(wait/2))
{
// Increment bug count and try a work around
_jvmBug++;
if (_jvmBug>(__JVMBUG_THRESHHOLD))
{
try
{
if (_jvmBug==__JVMBUG_THRESHHOLD+1)
_jvmFix2++;
Thread.sleep(__BUSY_PAUSE); // pause to avoid busy loop
}
catch(InterruptedException e)
{
LOG.ignore(e);
}
}
else if (_jvmBug==__JVMBUG_THRESHHOLD)
{
renewSelector();
}
else if (_jvmBug%32==31) // heuristic attempt to cancel key 31,63,95,... loops
{
// Cancel keys with 0 interested ops
int cancelled=0;
for (SelectionKey k: selector.keys())
{
if (k.isValid()&&k.interestOps()==0)
{
k.cancel();
cancelled++;
}
}
if (cancelled>0)
_jvmFix0++;
return;
}
}
else if (__BUSY_KEY>0 && selected==1 && _selects>__MAX_SELECTS)
{
// Look for busy key
SelectionKey busy = selector.selectedKeys().iterator().next();
if (busy==_busyKey)
{
if (++_busyKeyCount>__BUSY_KEY && !(busy.channel() instanceof ServerSocketChannel))
{
final SelectChannelEndPoint endpoint = (SelectChannelEndPoint)busy.attachment();
LOG.warn("Busy Key "+busy.channel()+" "+endpoint);
busy.cancel();
if (endpoint!=null)
{
dispatch(new Runnable()
{
public void run()
{
try
{
endpoint.close();
}
catch (IOException e)
{
LOG.ignore(e);
}
}
});
}
}
}
else
_busyKeyCount=0;
_busyKey=busy;
}
}
/* ------------------------------------------------------------ */
private void renewSelector()
private void renewSelector()
{
try
{
@ -876,7 +777,7 @@ public abstract class SelectorManager extends AbstractLifeCycle implements Dumpa
throw new RuntimeException("recreating selector",e);
}
}
/* ------------------------------------------------------------ */
public SelectorManager getManager()
{
@ -891,9 +792,9 @@ public abstract class SelectorManager extends AbstractLifeCycle implements Dumpa
/* ------------------------------------------------------------ */
/**
* @param task The task to timeout. If it implements Runnable, then
* @param task The task to timeout. If it implements Runnable, then
* expired will be called from a dispatched thread.
*
*
* @param timeoutMs
*/
public void scheduleTimeout(Timeout.Task task, long timeoutMs)
@ -902,7 +803,7 @@ public abstract class SelectorManager extends AbstractLifeCycle implements Dumpa
throw new IllegalArgumentException("!Runnable");
_timeout.schedule(task, timeoutMs);
}
/* ------------------------------------------------------------ */
public void cancelTimeout(Timeout.Task task)
{
@ -927,23 +828,24 @@ public abstract class SelectorManager extends AbstractLifeCycle implements Dumpa
renewSelector();
}
});
renewSelector();
}
}
/* ------------------------------------------------------------ */
private SelectChannelEndPoint createEndPoint(SocketChannel channel, SelectionKey sKey) throws IOException
{
SelectChannelEndPoint endp = newEndPoint(channel,this,sKey);
endPointOpened(endp);
endPointOpened(endp);
_endPoints.put(endp,this);
return endp;
}
/* ------------------------------------------------------------ */
public void destroyEndPoint(SelectChannelEndPoint endp)
{
LOG.debug("destroyEndPoint {}",endp);
_endPoints.remove(endp);
endPointClosed(endp);
}
@ -953,11 +855,11 @@ public abstract class SelectorManager extends AbstractLifeCycle implements Dumpa
{
return _selector;
}
/* ------------------------------------------------------------ */
void stop() throws Exception
{
// Spin for a while waiting for selector to complete
// Spin for a while waiting for selector to complete
// to avoid unneccessary closed channel exceptions
try
{
@ -994,8 +896,8 @@ public abstract class SelectorManager extends AbstractLifeCycle implements Dumpa
}
}
}
_timeout.cancelAll();
try
{
@ -1006,7 +908,7 @@ public abstract class SelectorManager extends AbstractLifeCycle implements Dumpa
catch (IOException e)
{
LOG.ignore(e);
}
}
_selector=null;
}
}
@ -1021,9 +923,9 @@ public abstract class SelectorManager extends AbstractLifeCycle implements Dumpa
public void dump(Appendable out, String indent) throws IOException
{
out.append(String.valueOf(this)).append(" id=").append(String.valueOf(_setID)).append("\n");
Thread selecting = _selecting;
Object where = "not selecting";
StackTraceElement[] trace =selecting==null?null:selecting.getStackTrace();
if (trace!=null)
@ -1037,28 +939,32 @@ public abstract class SelectorManager extends AbstractLifeCycle implements Dumpa
}
Selector selector=_selector;
final ArrayList<Object> dump = new ArrayList<Object>(selector.keys().size()*2);
dump.add(where);
final CountDownLatch latch = new CountDownLatch(1);
addChange(new Runnable(){
public void run()
if (selector!=null)
{
final ArrayList<Object> dump = new ArrayList<Object>(selector.keys().size()*2);
dump.add(where);
final CountDownLatch latch = new CountDownLatch(1);
addChange(new ChangeTask()
{
dumpKeyState(dump);
latch.countDown();
public void run()
{
dumpKeyState(dump);
latch.countDown();
}
});
try
{
latch.await(5,TimeUnit.SECONDS);
}
});
try
{
latch.await(5,TimeUnit.SECONDS);
catch(InterruptedException e)
{
LOG.ignore(e);
}
AggregateLifeCycle.dump(out,indent,dump);
}
catch(InterruptedException e)
{
LOG.ignore(e);
}
AggregateLifeCycle.dump(out,indent,dump);
}
/* ------------------------------------------------------------ */
@ -1081,7 +987,7 @@ public abstract class SelectorManager extends AbstractLifeCycle implements Dumpa
{
final SelectableChannel _channel;
final Object _attachment;
public ChannelAndAttachment(SelectableChannel channel, Object attachment)
{
super();
@ -1101,12 +1007,12 @@ public abstract class SelectorManager extends AbstractLifeCycle implements Dumpa
{
_deferringInterestedOps0 = deferringInterestedOps0;
}
/* ------------------------------------------------------------ */
/* ------------------------------------------------------------ */
/* ------------------------------------------------------------ */
private interface ChangeTask extends Runnable
{}
}

View File

@ -0,0 +1,69 @@
// ========================================================================
// Copyright (c) 2011 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.jndi;
import java.util.Iterator;
import javax.naming.Binding;
import javax.naming.NamingEnumeration;
import javax.naming.NamingException;
/** BindingEnumeration
* <p>Implementation of NamingEnumeration
*
* <p><h4>Notes</h4>
* <p>Used to return results of Context.listBindings();
*
* <p><h4>Usage</h4>
*
*/
public class BindingEnumeration implements NamingEnumeration<Binding>
{
Iterator<Binding> _delegate;
public BindingEnumeration (Iterator<Binding> e)
{
_delegate = e;
}
public void close()
throws NamingException
{
}
public boolean hasMore ()
throws NamingException
{
return _delegate.hasNext();
}
public Binding next()
throws NamingException
{
Binding b = (Binding)_delegate.next();
return new Binding (b.getName(), b.getClassName(), b.getObject(), true);
}
public boolean hasMoreElements()
{
return _delegate.hasNext();
}
public Binding nextElement()
{
Binding b = (Binding)_delegate.next();
return new Binding (b.getName(), b.getClassName(), b.getObject(),true);
}
}

View File

@ -0,0 +1,69 @@
// ========================================================================
// Copyright (c) 2011 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.jndi;
import java.util.Iterator;
import javax.naming.Binding;
import javax.naming.NameClassPair;
import javax.naming.NamingEnumeration;
import javax.naming.NamingException;
/** NameEnumeration
* <p>Implementation of NamingEnumeration interface.
*
* <p><h4>Notes</h4>
* <p>Used for returning results of Context.list();
*
* <p><h4>Usage</h4>
*
*/
public class NameEnumeration implements NamingEnumeration<NameClassPair>
{
Iterator<Binding> _delegate;
public NameEnumeration (Iterator<Binding> e)
{
_delegate = e;
}
public void close()
throws NamingException
{
}
public boolean hasMore ()
throws NamingException
{
return _delegate.hasNext();
}
public NameClassPair next()
throws NamingException
{
Binding b = _delegate.next();
return new NameClassPair(b.getName(),b.getClassName(),true);
}
public boolean hasMoreElements()
{
return _delegate.hasNext();
}
public NameClassPair nextElement()
{
Binding b = _delegate.next();
return new NameClassPair(b.getName(),b.getClassName(),true);
}
}

View File

@ -20,7 +20,6 @@ import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.Hashtable;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
@ -31,7 +30,6 @@ import javax.naming.InitialContext;
import javax.naming.LinkRef;
import javax.naming.Name;
import javax.naming.NameAlreadyBoundException;
import javax.naming.NameClassPair;
import javax.naming.NameNotFoundException;
import javax.naming.NameParser;
import javax.naming.NamingEnumeration;
@ -53,17 +51,8 @@ import org.eclipse.jetty.util.log.Logger;
* <p><h4>Notes</h4>
* <p>All Names are expected to be Compound, not Composite.
*
* <p><h4>Usage</h4>
* <pre>
*
*/
/*
* </pre>
*
* @see
*
*
* @version 1.0
*/
public class NamingContext implements Context, Cloneable, Dumpable
{
private final static Logger __log=NamingUtil.__log;
@ -101,123 +90,6 @@ public class NamingContext implements Context, Cloneable, Dumpable
void unbind(NamingContext ctx, Binding binding);
}
/*------------------------------------------------*/
/** NameEnumeration
* <p>Implementation of NamingEnumeration interface.
*
* <p><h4>Notes</h4>
* <p>Used for returning results of Context.list();
*
* <p><h4>Usage</h4>
* <pre>
*/
/*
* </pre>
*
* @see
*
*/
public class NameEnumeration implements NamingEnumeration<NameClassPair>
{
Iterator<Binding> _delegate;
public NameEnumeration (Iterator<Binding> e)
{
_delegate = e;
}
public void close()
throws NamingException
{
}
public boolean hasMore ()
throws NamingException
{
return _delegate.hasNext();
}
public NameClassPair next()
throws NamingException
{
Binding b = _delegate.next();
return new NameClassPair(b.getName(),b.getClassName(),true);
}
public boolean hasMoreElements()
{
return _delegate.hasNext();
}
public NameClassPair nextElement()
{
Binding b = _delegate.next();
return new NameClassPair(b.getName(),b.getClassName(),true);
}
}
/*------------------------------------------------*/
/** BindingEnumeration
* <p>Implementation of NamingEnumeration
*
* <p><h4>Notes</h4>
* <p>Used to return results of Context.listBindings();
*
* <p><h4>Usage</h4>
* <pre>
*/
/*
* </pre>
*
* @see
*
*/
public class BindingEnumeration implements NamingEnumeration<Binding>
{
Iterator<Binding> _delegate;
public BindingEnumeration (Iterator<Binding> e)
{
_delegate = e;
}
public void close()
throws NamingException
{
}
public boolean hasMore ()
throws NamingException
{
return _delegate.hasNext();
}
public Binding next()
throws NamingException
{
Binding b = (Binding)_delegate.next();
return new Binding (b.getName(), b.getClassName(), b.getObject(), true);
}
public boolean hasMoreElements()
{
return _delegate.hasNext();
}
public Binding nextElement()
{
Binding b = (Binding)_delegate.next();
return new Binding (b.getName(), b.getClassName(), b.getObject(),true);
}
}
/*------------------------------------------------*/
/**
* Constructor
@ -240,26 +112,6 @@ public class NamingContext implements Context, Cloneable, Dumpable
}
/*------------------------------------------------*/
/**
* Creates a new <code>NamingContext</code> instance.
*
* @param env a <code>Hashtable</code> value
*/
public NamingContext (Hashtable<String,Object> env)
{
if (env != null)
_env.putAll(env);
}
/*------------------------------------------------*/
/**
* Constructor
*
*/
public NamingContext ()
{
}
/*------------------------------------------------*/
@ -312,8 +164,24 @@ public class NamingContext implements Context, Cloneable, Dumpable
_parser = parser;
}
public void setEnv (Hashtable<String,Object> env)
{
_env.clear();
_env.putAll(env);
}
public Map<String,Binding> getBindings ()
{
return _bindings;
}
public void setBindings(Map<String,Binding> bindings)
{
_bindings = bindings;
}
/*------------------------------------------------*/
/**
* Bind a name to an object
@ -435,8 +303,6 @@ public class NamingContext implements Context, Cloneable, Dumpable
ne.setRemainingName(name);
throw ne;
}
Name cname = toCanonicalName (name);
@ -521,7 +387,7 @@ public class NamingContext implements Context, Cloneable, Dumpable
/*------------------------------------------------*/
/**
* Not supported
*
*
* @param name name of subcontext to remove
* @exception NamingException if an error occurs
@ -536,7 +402,7 @@ public class NamingContext implements Context, Cloneable, Dumpable
/*------------------------------------------------*/
/**
* Not supported
*
*
* @param name name of subcontext to remove
* @exception NamingException if an error occurs
@ -1128,7 +994,6 @@ public class NamingContext implements Context, Cloneable, Dumpable
ctx = binding.getObject();
if (ctx instanceof Reference)
{
//deference the object
@ -1154,8 +1019,7 @@ public class NamingContext implements Context, Cloneable, Dumpable
}
else
throw new NotContextException ("Object bound at "+firstComponent +" is not a Context");
}
}
}
/*------------------------------------------------*/
@ -1182,11 +1046,11 @@ public class NamingContext implements Context, Cloneable, Dumpable
* @param newName a <code>Name</code> value
* @exception NamingException if an error occurs
*/ public void rename(String oldName,
String newName)
throws NamingException
{
throw new OperationNotSupportedException();
}
String newName)
throws NamingException
{
throw new OperationNotSupportedException();
}
@ -1247,9 +1111,7 @@ public class NamingContext implements Context, Cloneable, Dumpable
*/
public void close ()
throws NamingException
{
{
}
@ -1362,7 +1224,7 @@ public class NamingContext implements Context, Cloneable, Dumpable
* @param name a <code>Name</code> value
* @param obj an <code>Object</code> value
*/
protected void addBinding (Name name, Object obj) throws NameAlreadyBoundException
public void addBinding (Name name, Object obj) throws NameAlreadyBoundException
{
String key = name.toString();
Binding binding=new Binding (key, obj);
@ -1394,7 +1256,7 @@ public class NamingContext implements Context, Cloneable, Dumpable
* @param name a <code>Name</code> value
* @return a <code>Binding</code> value
*/
protected Binding getBinding (Name name)
public Binding getBinding (Name name)
{
return (Binding) _bindings.get(name.toString());
}
@ -1407,13 +1269,13 @@ public class NamingContext implements Context, Cloneable, Dumpable
* @param name as a String
* @return null or the Binding
*/
protected Binding getBinding (String name)
public Binding getBinding (String name)
{
return (Binding) _bindings.get(name);
}
/*------------------------------------------------*/
protected void removeBinding (Name name)
public void removeBinding (Name name)
{
String key = name.toString();
if (__log.isDebugEnabled())
@ -1455,7 +1317,7 @@ public class NamingContext implements Context, Cloneable, Dumpable
}
/* ------------------------------------------------------------ */
private boolean isLocked()
public boolean isLocked()
{
if ((_env.get(LOCK_PROPERTY) == null) && (_env.get(UNLOCK_PROPERTY) == null))
return false;

View File

@ -67,8 +67,7 @@ public class javaRootURLContext implements Context
try
{
__javaNameParser = new javaNameParser();
__nameRoot = new NamingContext();
__nameRoot.setNameParser(__javaNameParser);
__nameRoot = new NamingContext(null,null,null,__javaNameParser);
StringRefAddr parserAddr = new StringRefAddr("parser", __javaNameParser.getClass().getName());

View File

@ -12,11 +12,19 @@
// ========================================================================
package org.eclipse.jetty.jndi.java;
import java.util.Hashtable;
import javax.naming.Context;
import javax.naming.InitialContext;
import javax.naming.Name;
import javax.naming.NameNotFoundException;
import javax.naming.NameParser;
import javax.naming.NamingException;
import javax.naming.RefAddr;
import javax.naming.Reference;
import javax.naming.Referenceable;
import javax.naming.StringRefAddr;
import javax.naming.spi.ObjectFactory;
import org.eclipse.jetty.jndi.NamingUtil;
import org.junit.After;
@ -31,13 +39,152 @@ import static org.junit.Assert.fail;
*/
public class TestLocalJNDI
{
public static class FruitFactory implements ObjectFactory
{
public FruitFactory()
{
}
public Object getObjectInstance(Object obj, Name name, Context ctx, Hashtable env) throws Exception
{
if (!env.containsKey("flavour"))
throw new Exception ("No flavour!");
if (obj instanceof Reference)
{
Reference ref = (Reference)obj;
if (ref.getClassName().equals(Fruit.class.getName()))
{
RefAddr addr = ref.get("fruit");
if (addr != null)
{
return new Fruit((String)addr.getContent());
}
}
}
return null;
}
}
public static class Fruit implements Referenceable
{
String fruit;
public Fruit(String f)
{
fruit = f;
}
public Reference getReference() throws NamingException
{
return new Reference(
Fruit.class.getName(),
new StringRefAddr("fruit", fruit),
FruitFactory.class.getName(),
null); // Factory location
}
public String toString()
{
return fruit;
}
}
@After
public void tearDown() throws Exception
{
InitialContext ic = new InitialContext();
ic.destroySubcontext("a");
}
@Test
public void testLocalReferenceable() throws Exception
{
Hashtable<String,String> env1 = new Hashtable<String,String>();
env1.put("flavour", "orange");
InitialContext ic1 = new InitialContext(env1);
ic1.bind("valencia", new Fruit("orange"));
Object o = ic1.lookup("valencia");
Hashtable<String,String> env2 = new Hashtable<String,String>();
InitialContext ic2 = new InitialContext(env2);
try
{
o = ic2.lookup("valencia");
fail("Constructed object from reference without correct environment");
}
catch (Exception e)
{
assertEquals("No flavour!", e.getMessage());
}
}
@Test
public void testLocalEnvironment() throws Exception
{
Hashtable<String,String> env1 = new Hashtable<String,String>();
env1.put("make", "holden");
env1.put("model", "commodore");
Object car1 = new Object();
InitialContext ic = new InitialContext(env1);
ic.bind("car1", car1);
assertNotNull(ic.lookup("car1"));
assertEquals(car1, ic.lookup("car1"));
Context carz = ic.createSubcontext("carz");
assertNotNull(carz);
Hashtable ht = carz.getEnvironment();
assertNotNull(ht);
assertEquals("holden", ht.get("make"));
assertEquals("commodore", ht.get("model"));
Hashtable<String,String> env2 = new Hashtable<String,String>();
env2.put("flavour", "strawberry");
InitialContext ic2 = new InitialContext(env2);
assertEquals(car1, ic2.lookup("car1"));
Context c = (Context)ic2.lookup("carz");
assertNotNull(c);
ht = c.getEnvironment();
assertEquals("holden", ht.get("make"));
assertEquals("commodore", ht.get("model"));
Context icecreamz = ic2.createSubcontext("icecreamz");
ht = icecreamz.getEnvironment();
assertNotNull(ht);
assertEquals("strawberry", ht.get("flavour"));
Context hatchbackz = ic2.createSubcontext("carz/hatchbackz");
assertNotNull(hatchbackz);
ht = hatchbackz.getEnvironment();
assertNotNull(ht);
assertEquals("holden", ht.get("make"));
assertEquals("commodore", ht.get("model"));
assertEquals(null, ht.get("flavour"));
c = (Context)ic.lookup("carz/hatchbackz");
assertNotNull(c);
assertEquals(hatchbackz, c);
}
@Test
public void testLocal () throws Exception
{

View File

@ -84,7 +84,8 @@ public class NestedConnection extends HttpConnection
{
getServer().handle(this);
completeResponse();
_generator.flushBuffer();
while (!_generator.isComplete() && _endp.isOpen())
_generator.flushBuffer();
_endp.flush();
}
finally

View File

@ -43,7 +43,7 @@ public class NestedGenerator extends AbstractGenerator
public void addContent(Buffer content, boolean last) throws IOException
{
// LOG.debug("addContent {} {}",content.length(),last);
LOG.debug("addContent {} {}",content.length(),last);
if (_noContent)
{
content.clear();
@ -70,7 +70,6 @@ public class NestedGenerator extends AbstractGenerator
// Handle any unfinished business?
if (_content != null && _content.length() > 0)
{
flushBuffer();
if (_content != null && _content.length() > 0)
throw new IllegalStateException("FULL");
@ -86,20 +85,22 @@ public class NestedGenerator extends AbstractGenerator
content.clear();
_content = null;
}
else
else if (!last || _buffer!=null)
{
// Yes - so we better check we have a buffer
initContent();
initBuffer();
// Copy _content to buffer;
int len = 0;
len = _buffer.put(_content);
// make sure there is space for a trailing null
// make sure there is space for a trailing null (???)
if (len > 0 && _buffer.space() == 0)
{
len--;
_buffer.setPutIndex(_buffer.putIndex() - 1);
}
LOG.debug("copied {} to buffer",len);
_content.skip(len);
@ -139,7 +140,7 @@ public class NestedGenerator extends AbstractGenerator
return false;
// we better check we have a buffer
initContent();
initBuffer();
// Copy _content to buffer;
@ -149,7 +150,7 @@ public class NestedGenerator extends AbstractGenerator
}
/* ------------------------------------------------------------ */
private void initContent() throws IOException
private void initBuffer() throws IOException
{
if (_buffer == null)
{
@ -176,7 +177,7 @@ public class NestedGenerator extends AbstractGenerator
@Override
public int prepareUncheckedAddContent() throws IOException
{
initContent();
initBuffer();
return _buffer.space();
}
@ -229,6 +230,26 @@ public class NestedGenerator extends AbstractGenerator
_state = STATE_CONTENT;
}
/* ------------------------------------------------------------ */
/**
* Complete the message.
*
* @throws IOException
*/
@Override
public void complete() throws IOException
{
if (_state == STATE_END)
return;
super.complete();
if (_state < STATE_FLUSHING)
_state = STATE_FLUSHING;
flushBuffer();
}
/* ------------------------------------------------------------ */
@Override
public long flushBuffer() throws IOException
@ -236,23 +257,44 @@ public class NestedGenerator extends AbstractGenerator
if (_state == STATE_HEADER)
throw new IllegalStateException("State==HEADER");
if (_content != null && _content.length() < _buffer.space() && _state != STATE_FLUSHING)
{
initContent();
_buffer.put(_content);
_content.clear();
_content = null;
}
int len = 0;
if (_buffer==null)
return 0;
{
if (_content!=null && _content.length()>0)
{
// flush content directly
len = _endp.flush(_content);
if (len>0)
_content.skip(len);
}
}
else
{
if (_buffer.length()==0 && _content!=null && _content.length()>0)
{
// Copy content to buffer
_content.skip(_buffer.put(_content));
}
int size=_buffer.length();
len =_endp.flush(_buffer);
LOG.debug("flushBuffer {} of {}",len,size);
if (len>0)
_buffer.skip(len);
}
int size=_buffer.length();
int len = _buffer==null?0:_endp.flush(_buffer);
LOG.debug("flushBuffer {} of {}",len,size);
if (len>0)
_buffer.skip(len);
if (_content!=null && _content.length()==0)
_content=null;
if (_buffer!=null && _buffer.length()==0 && _content==null)
{
_buffers.returnBuffer(_buffer);
_buffer=null;
}
if (_state==STATE_FLUSHING && _buffer==null && _content==null)
_state=STATE_END;
return len;
}

View File

@ -428,7 +428,6 @@ public class MongoSessionManager extends NoSqlSessionManager
return o;
}
bout.reset();
out.reset();
out.writeUnshared(value);
out.flush();

View File

@ -0,0 +1,48 @@
// ========================================================================
// Copyright (c) 2010-2011 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.osgi.servletbridge;
import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.eclipse.equinox.servletbridge.BridgeServlet;
/**
* Override the BridgeServlet to report on whether equinox is actually started or not
* in case it is started asynchroneously.
*
* @author hmalphettes
*/
public class BridgeServletExtended extends BridgeServlet {
@Override
protected void service(HttpServletRequest req, HttpServletResponse resp)
throws ServletException, IOException {
if (FrameworkLauncherExtended.ASYNCH_START_IN_PROGRESS != null
&& req.getMethod().equals("GET")) {
if (FrameworkLauncherExtended.ASYNCH_START_IN_PROGRESS) {
resp.getWriter().append("Equinox is currently starting...\n");
return;
} else if (FrameworkLauncherExtended.ASYNCH_START_FAILURE != null) {
resp.getWriter().append("Equinox failed to start:\n");
FrameworkLauncherExtended.ASYNCH_START_FAILURE.printStackTrace(resp.getWriter());
return;
}
}
super.service(req, resp);
}
}

View File

@ -13,146 +13,114 @@
package org.eclipse.jetty.plus.jaas.spi;
import java.io.File;
import java.io.FileInputStream;
import java.security.Principal;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Properties;
import java.util.StringTokenizer;
import java.util.Set;
import javax.security.auth.Subject;
import javax.security.auth.callback.CallbackHandler;
import org.eclipse.jetty.http.security.Credential;
import org.eclipse.jetty.security.PropertyUserStore;
import org.eclipse.jetty.server.UserIdentity;
import org.eclipse.jetty.util.log.Log;
import org.eclipse.jetty.util.log.Logger;
/**
* PropertyFileLoginModule
*
*
*
*
*/
public class PropertyFileLoginModule extends AbstractLoginModule
{
public static final String DEFAULT_FILENAME = "realm.properties";
private static final Logger LOG = Log.getLogger(PropertyFileLoginModule.class);
public static final String DEFAULT_FILENAME = "realm.properties";
public static final Map<String, Map<String, UserInfo>> fileMap = new HashMap<String, Map<String, UserInfo>>();
private String propertyFileName;
private static Map<String, PropertyUserStore> _propertyUserStores = new HashMap<String, PropertyUserStore>();
/**
private int _refreshInterval = 0;
private String _filename = DEFAULT_FILENAME;
/**
* Read contents of the configured property file.
*
* @see javax.security.auth.spi.LoginModule#initialize(javax.security.auth.Subject, javax.security.auth.callback.CallbackHandler, java.util.Map, java.util.Map)
* @see javax.security.auth.spi.LoginModule#initialize(javax.security.auth.Subject, javax.security.auth.callback.CallbackHandler, java.util.Map,
* java.util.Map)
* @param subject
* @param callbackHandler
* @param sharedState
* @param options
*/
public void initialize(Subject subject, CallbackHandler callbackHandler,
Map<String,?> sharedState, Map<String,?> options)
public void initialize(Subject subject, CallbackHandler callbackHandler, Map<String, ?> sharedState, Map<String, ?> options)
{
super.initialize(subject, callbackHandler, sharedState, options);
loadProperties((String)options.get("file"));
super.initialize(subject,callbackHandler,sharedState,options);
setupPropertyUserStore(options);
}
public void loadProperties (String filename)
{
File propsFile;
if (filename == null)
{
propsFile = new File(System.getProperty("user.dir"), DEFAULT_FILENAME);
//look for a file called realm.properties in the current directory
//if that fails, look for a file called realm.properties in $jetty.home/etc
if (!propsFile.exists())
propsFile = new File(System.getProperty("jetty.home"), DEFAULT_FILENAME);
}
else
{
propsFile = new File(filename);
}
//give up, can't find a property file to load
if (!propsFile.exists())
{
LOG.warn("No property file found");
throw new IllegalStateException ("No property file specified in login module configuration file");
}
try
{
this.propertyFileName = propsFile.getCanonicalPath();
if (fileMap.get(propertyFileName) != null)
{
if (LOG.isDebugEnabled()) {LOG.debug("Properties file "+propertyFileName+" already in cache, skipping load");}
return;
}
Map<String, UserInfo> userInfoMap = new HashMap<String, UserInfo>();
Properties props = new Properties();
props.load(new FileInputStream(propsFile));
Iterator<Map.Entry<Object,Object>> iter = props.entrySet().iterator();
while(iter.hasNext())
{
Map.Entry<Object,Object> entry = iter.next();
String username=entry.getKey().toString().trim();
String credentials=entry.getValue().toString().trim();
String roles=null;
int c=credentials.indexOf(',');
if (c>0)
{
roles=credentials.substring(c+1).trim();
credentials=credentials.substring(0,c).trim();
}
if (username!=null && username.length()>0 &&
credentials!=null && credentials.length()>0)
{
ArrayList<String> roleList = new ArrayList<String>();
if(roles!=null && roles.length()>0)
{
StringTokenizer tok = new StringTokenizer(roles,", ");
while (tok.hasMoreTokens())
roleList.add(tok.nextToken());
}
userInfoMap.put(username, (new UserInfo(username, Credential.getCredential(credentials.toString()), roleList)));
}
}
fileMap.put(propertyFileName, userInfoMap);
}
catch (Exception e)
private void setupPropertyUserStore(Map<String, ?> options)
{
if (_propertyUserStores.get(_filename) == null)
{
LOG.warn("Error loading properties from file", e);
throw new RuntimeException(e);
parseConfig(options);
PropertyUserStore _propertyUserStore = new PropertyUserStore();
_propertyUserStore.setConfig(_filename);
_propertyUserStore.setRefreshInterval(_refreshInterval);
LOG.debug("setupPropertyUserStore: Starting new PropertyUserStore. PropertiesFile: " + _filename + " refreshInterval: " + _refreshInterval);
try
{
_propertyUserStore.start();
}
catch (Exception e)
{
LOG.warn("Exception while starting propertyUserStore: ",e);
}
_propertyUserStores.put(_filename,_propertyUserStore);
}
}
/**
* Don't implement this as we want to pre-fetch all of the
* users.
* @param username
private void parseConfig(Map<String, ?> options)
{
_filename = (String)options.get("file") != null?(String)options.get("file"):DEFAULT_FILENAME;
String refreshIntervalString = (String)options.get("refreshInterval");
_refreshInterval = refreshIntervalString == null?_refreshInterval:Integer.parseInt(refreshIntervalString);
}
/**
* Don't implement this as we want to pre-fetch all of the users.
*
* @param userName
* @throws Exception
*/
public UserInfo getUserInfo (String username) throws Exception
public UserInfo getUserInfo(String userName) throws Exception
{
Map<?, ?> userInfoMap = (Map<?, ?>)fileMap.get(propertyFileName);
if (userInfoMap == null)
PropertyUserStore propertyUserStore = _propertyUserStores.get(_filename);
if (propertyUserStore == null)
throw new IllegalStateException("PropertyUserStore should never be null here!");
UserIdentity userIdentity = propertyUserStore.getUserIdentity(userName);
if(userIdentity==null)
return null;
return (UserInfo)userInfoMap.get(username);
Set<Principal> principals = userIdentity.getSubject().getPrincipals();
List<String> roles = new ArrayList<String>();
for ( Principal principal : principals )
{
roles.add( principal.getName() );
}
Credential credential = (Credential)userIdentity.getSubject().getPrivateCredentials().iterator().next();
LOG.debug("Found: " + userName + " in PropertyUserStore");
return new UserInfo(userName, credential, roles);
}
}
}

View File

@ -74,10 +74,11 @@
<artifactId>jetty-server</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>${servlet.spec.groupId}</groupId>
<artifactId>${servlet.spec.artifactId}</artifactId>
</dependency>
<dependency>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-client</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>org.eclipse.jetty</groupId>
<artifactId>test-jetty-servlet</artifactId>

View File

@ -0,0 +1,487 @@
package org.eclipse.jetty.rewrite.handler;
//========================================================================
//Copyright (c) 2006-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.
//========================================================================
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.MalformedURLException;
import java.util.Enumeration;
import java.util.HashSet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.eclipse.jetty.client.HttpClient;
import org.eclipse.jetty.client.HttpExchange;
import org.eclipse.jetty.http.HttpHeaderValues;
import org.eclipse.jetty.http.HttpHeaders;
import org.eclipse.jetty.http.HttpURI;
import org.eclipse.jetty.http.PathMap;
import org.eclipse.jetty.io.Buffer;
import org.eclipse.jetty.io.EofException;
import org.eclipse.jetty.util.log.Log;
import org.eclipse.jetty.util.log.Logger;
import org.eclipse.jetty.util.thread.QueuedThreadPool;
/**
* This rule allows the user to configure a particular rewrite rule that will proxy out
* to a configured location. This rule uses the jetty http client.
*
* Rule rule = new ProxyRule();
* rule.setPattern("/foo/*");
* rule.setProxyTo("http://url.com");
*
* see api for other configuration options which influence the configuration of the jetty
* client instance
*
*/
public class ProxyRule extends PatternRule
{
private static final Logger _log = Log.getLogger(ProxyRule.class);
private HttpClient _client;
private String _hostHeader;
private String _proxyTo;
private int _connectorType = 2;
private String _maxThreads;
private String _maxConnections;
private String _timeout;
private String _idleTimeout;
private String _requestHeaderSize;
private String _requestBufferSize;
private String _responseHeaderSize;
private String _responseBufferSize;
private HashSet<String> _DontProxyHeaders = new HashSet<String>();
{
_DontProxyHeaders.add("proxy-connection");
_DontProxyHeaders.add("connection");
_DontProxyHeaders.add("keep-alive");
_DontProxyHeaders.add("transfer-encoding");
_DontProxyHeaders.add("te");
_DontProxyHeaders.add("trailer");
_DontProxyHeaders.add("proxy-authorization");
_DontProxyHeaders.add("proxy-authenticate");
_DontProxyHeaders.add("upgrade");
}
/* ------------------------------------------------------------ */
public ProxyRule()
{
_handling = true;
_terminating = true;
}
/* ------------------------------------------------------------ */
private void initializeClient() throws Exception
{
_client = new HttpClient();
_client.setConnectorType(_connectorType);
if ( _maxThreads != null )
{
_client.setThreadPool(new QueuedThreadPool(Integer.parseInt(_maxThreads)));
}
else
{
_client.setThreadPool(new QueuedThreadPool());
}
if ( _maxConnections != null )
{
_client.setMaxConnectionsPerAddress(Integer.parseInt(_maxConnections));
}
if ( _timeout != null )
{
_client.setTimeout(Long.parseLong(_timeout));
}
if ( _idleTimeout != null )
{
_client.setIdleTimeout(Long.parseLong(_idleTimeout));
}
if ( _requestBufferSize != null )
{
_client.setRequestBufferSize(Integer.parseInt(_requestBufferSize));
}
if ( _requestHeaderSize != null )
{
_client.setRequestHeaderSize(Integer.parseInt(_requestHeaderSize));
}
if ( _responseBufferSize != null )
{
_client.setResponseBufferSize(Integer.parseInt(_responseBufferSize));
}
if ( _responseHeaderSize != null )
{
_client.setResponseHeaderSize(Integer.parseInt(_responseHeaderSize));
}
_client.start();
}
/* ------------------------------------------------------------ */
private HttpURI proxyHttpURI(String uri) throws MalformedURLException
{
return new HttpURI(_proxyTo + uri);
}
/* ------------------------------------------------------------ */
@Override
protected String apply(String target, HttpServletRequest request, final HttpServletResponse response) throws IOException
{
synchronized (this)
{
if (_client == null)
{
try
{
initializeClient();
}
catch (Exception e)
{
throw new IOException("Unable to proxy: " + e.getMessage());
}
}
}
final int debug = _log.isDebugEnabled()?request.hashCode():0;
final InputStream in = request.getInputStream();
final OutputStream out = response.getOutputStream();
HttpURI url = createUrl(request,debug);
if (url == null)
{
response.sendError(HttpServletResponse.SC_FORBIDDEN);
return target;
}
HttpExchange exchange = new HttpExchange()
{
@Override
protected void onRequestCommitted() throws IOException
{
}
@Override
protected void onRequestComplete() throws IOException
{
}
@Override
protected void onResponseComplete() throws IOException
{
if (debug != 0)
_log.debug(debug + " complete");
}
@Override
protected void onResponseContent(Buffer content) throws IOException
{
if (debug != 0)
_log.debug(debug + " content" + content.length());
content.writeTo(out);
}
@Override
protected void onResponseHeaderComplete() throws IOException
{
}
@SuppressWarnings("deprecation")
@Override
protected void onResponseStatus(Buffer version, int status, Buffer reason) throws IOException
{
if (debug != 0)
_log.debug(debug + " " + version + " " + status + " " + reason);
if (reason != null && reason.length() > 0)
response.setStatus(status,reason.toString());
else
response.setStatus(status);
}
@Override
protected void onResponseHeader(Buffer name, Buffer value) throws IOException
{
String s = name.toString().toLowerCase();
if (!_DontProxyHeaders.contains(s) || (HttpHeaders.CONNECTION_BUFFER.equals(name) && HttpHeaderValues.CLOSE_BUFFER.equals(value)))
{
if (debug != 0)
_log.debug(debug + " " + name + ": " + value);
response.addHeader(name.toString(),value.toString());
}
else if (debug != 0)
_log.debug(debug + " " + name + "! " + value);
}
@Override
protected void onConnectionFailed(Throwable ex)
{
_log.warn(ex.toString());
_log.debug(ex);
if (!response.isCommitted())
{
response.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
}
}
@Override
protected void onException(Throwable ex)
{
if (ex instanceof EofException)
{
_log.ignore(ex);
return;
}
_log.warn(ex.toString());
_log.debug(ex);
if (!response.isCommitted())
{
response.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
}
}
@Override
protected void onExpire()
{
if (!response.isCommitted())
{
response.setStatus(HttpServletResponse.SC_GATEWAY_TIMEOUT);
}
}
};
exchange.setMethod(request.getMethod());
exchange.setURL(url.toString());
exchange.setVersion(request.getProtocol());
if (debug != 0)
{
_log.debug(debug + " " + request.getMethod() + " " + url + " " + request.getProtocol());
}
boolean hasContent = createHeaders(request,debug,exchange);
if (hasContent)
{
exchange.setRequestContentSource(in);
}
/*
* we need to set the timeout on the exchange to take into account the timeout of the HttpClient and the HttpExchange
*/
long ctimeout = (_client.getTimeout() > exchange.getTimeout())?_client.getTimeout():exchange.getTimeout();
exchange.setTimeout(ctimeout);
_client.send(exchange);
try
{
exchange.waitForDone();
}
catch (InterruptedException e)
{
_log.info("Exception while waiting for response on proxied request", e);
}
return target;
}
/* ------------------------------------------------------------ */
private HttpURI createUrl(HttpServletRequest request, final int debug) throws MalformedURLException
{
String uri = request.getRequestURI();
if (request.getQueryString() != null)
{
uri += "?" + request.getQueryString();
}
uri = PathMap.pathInfo(_pattern,uri);
if(uri==null)
{
uri = "/";
}
HttpURI url = proxyHttpURI(uri);
if (debug != 0)
{
_log.debug(debug + " proxy " + uri + "-->" + url);
}
return url;
}
/* ------------------------------------------------------------ */
private boolean createHeaders(final HttpServletRequest request, final int debug, HttpExchange exchange)
{
// check connection header
String connectionHdr = request.getHeader("Connection");
if (connectionHdr != null)
{
connectionHdr = connectionHdr.toLowerCase();
if (connectionHdr.indexOf("keep-alive") < 0 && connectionHdr.indexOf("close") < 0)
{
connectionHdr = null;
}
}
// force host
if (_hostHeader != null)
{
exchange.setRequestHeader("Host",_hostHeader);
}
// copy headers
boolean xForwardedFor = false;
boolean hasContent = false;
long contentLength = -1;
Enumeration<?> enm = request.getHeaderNames();
while (enm.hasMoreElements())
{
// TODO could be better than this!
String hdr = (String)enm.nextElement();
String lhdr = hdr.toLowerCase();
if (_DontProxyHeaders.contains(lhdr))
continue;
if (connectionHdr != null && connectionHdr.indexOf(lhdr) >= 0)
continue;
if (_hostHeader != null && "host".equals(lhdr))
continue;
if ("content-type".equals(lhdr))
hasContent = true;
else if ("content-length".equals(lhdr))
{
contentLength = request.getContentLength();
exchange.setRequestHeader(HttpHeaders.CONTENT_LENGTH,Long.toString(contentLength));
if (contentLength > 0)
hasContent = true;
}
else if ("x-forwarded-for".equals(lhdr))
xForwardedFor = true;
Enumeration<?> vals = request.getHeaders(hdr);
while (vals.hasMoreElements())
{
String val = (String)vals.nextElement();
if (val != null)
{
if (debug != 0)
_log.debug(debug + " " + hdr + ": " + val);
exchange.setRequestHeader(hdr,val);
}
}
}
// Proxy headers
exchange.setRequestHeader("Via","1.1 (jetty)");
if (!xForwardedFor)
{
exchange.addRequestHeader("X-Forwarded-For",request.getRemoteAddr());
exchange.addRequestHeader("X-Forwarded-Proto",request.getScheme());
exchange.addRequestHeader("X-Forwarded-Host",request.getServerName());
exchange.addRequestHeader("X-Forwarded-Server",request.getLocalName());
}
return hasContent;
}
/* ------------------------------------------------------------ */
public void setProxyTo(String proxyTo)
{
this._proxyTo = proxyTo;
}
/* ------------------------------------------------------------ */
public void setMaxThreads(String maxThreads)
{
this._maxThreads = maxThreads;
}
/* ------------------------------------------------------------ */
public void setMaxConnections(String maxConnections)
{
_maxConnections = maxConnections;
}
/* ------------------------------------------------------------ */
public void setTimeout(String timeout)
{
_timeout = timeout;
}
/* ------------------------------------------------------------ */
public void setIdleTimeout(String idleTimeout)
{
_idleTimeout = idleTimeout;
}
/* ------------------------------------------------------------ */
public void setRequestHeaderSize(String requestHeaderSize)
{
_requestHeaderSize = requestHeaderSize;
}
/* ------------------------------------------------------------ */
public void setRequestBufferSize(String requestBufferSize)
{
_requestBufferSize = requestBufferSize;
}
/* ------------------------------------------------------------ */
public void setResponseHeaderSize(String responseHeaderSize)
{
_responseHeaderSize = responseHeaderSize;
}
/* ------------------------------------------------------------ */
public void setResponseBufferSize(String responseBufferSize)
{
_responseBufferSize = responseBufferSize;
}
/* ------------------------------------------------------------ */
public void addDontProxyHeaders(String dontProxyHeader)
{
_DontProxyHeaders.add(dontProxyHeader);
}
/* ------------------------------------------------------------ */
/**
* CONNECTOR_SOCKET = 0;
* CONNECTOR_SELECT_CHANNEL = 2; (default)
*
* @param connectorType
*/
public void setConnectorType( int connectorType )
{
_connectorType = connectorType;
}
}

View File

@ -5,11 +5,11 @@
// All rights reserved. This program and the accompanying materials
// are made available under the terms of the Eclipse Public License v1.0
// and Apache License v2.0 which accompanies this distribution.
// The Eclipse Public License is available at
// The Eclipse Public License is available at
// http://www.eclipse.org/legal/epl-v10.html
// The Apache License v2.0 is available at
// http://www.opensource.org/licenses/apache2.0.php
// You may elect to redistribute this code under either of these licenses.
// You may elect to redistribute this code under either of these licenses.
// ========================================================================
package org.eclipse.jetty.rewrite.handler;
@ -19,25 +19,24 @@ import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.eclipse.jetty.http.PathMap;
import org.eclipse.jetty.server.Request;
import org.eclipse.jetty.server.handler.HandlerWrapper;
/* ------------------------------------------------------------ */
/**
*<p> Rewrite handler is responsible for managing the rules. Its capabilities
* is not only limited for URL rewrites such as RewritePatternRule or RewriteRegexRule.
* There is also handling for cookies, headers, redirection, setting status or error codes
* whenever the rule finds a match.
*
* <p> The rules can be matched by the either: pattern matching of PathMap
* (eg {@link PatternRule}), regular expressions (eg {@link RegexRule}) or certain conditions set
* is not only limited for URL rewrites such as RewritePatternRule or RewriteRegexRule.
* There is also handling for cookies, headers, redirection, setting status or error codes
* whenever the rule finds a match.
*
* <p> The rules can be matched by the either: pattern matching of PathMap
* (eg {@link PatternRule}), regular expressions (eg {@link RegexRule}) or certain conditions set
* (eg {@link MsieSslRule} - the requests must be in SSL mode).
*
* <p> The rules can be grouped into rule containers (class {@link RuleContainer}), and will only
*
* <p> The rules can be grouped into rule containers (class {@link RuleContainer}), and will only
* be applied if the request matches the conditions for their container
* (e.g., by virtual host name)
*
*
* <p>The list of predefined rules is:
* <ul>
* <li> {@link CookiePatternRule} - adds a new cookie in response. </li>
@ -46,28 +45,36 @@ import org.eclipse.jetty.server.handler.HandlerWrapper;
* <li> {@link ResponsePatternRule} - sets the status/error codes. </li>
* <li> {@link RewritePatternRule} - rewrites the requested URI. </li>
* <li> {@link RewriteRegexRule} - rewrites the requested URI using regular expression for pattern matching. </li>
* <li> {@link ProxyRule} - proxies the requested URI to the host defined in proxyTo. </li>
* <li> {@link MsieSslRule} - disables the keep alive on SSL for IE5 and IE6. </li>
* <li> {@link LegacyRule} - the old version of rewrite. </li>
* <li> {@link ForwardedSchemeHeaderRule} - set the scheme according to the headers present. </li>
* <li> {@link VirtualHostRuleContainer} - checks whether the request matches one of a set of virtual host names.</li>
* </ul>
*
*
*
* Here is a typical jetty.xml configuration would be: <pre>
*
*
* &lt;Set name="handler"&gt;
* &lt;New id="Handlers" class="org.eclipse.jetty.rewrite.handler.RewriteHandler"&gt;
* &lt;Set name="rules"&gt;
* &lt;Array type="org.eclipse.jetty.rewrite.handler.Rule"&gt;
*
* &lt;Item&gt;
* &lt;Item&gt;
* &lt;New id="rewrite" class="org.eclipse.jetty.rewrite.handler.RewritePatternRule"&gt;
* &lt;Set name="pattern"&gt;/*&lt;/Set&gt;
* &lt;Set name="replacement"&gt;/test&lt;/Set&gt;
* &lt;/New&gt;
* &lt;/Item&gt;
*
* &lt;Item&gt;
* &lt;Item&gt;
* &lt;New id="rewrite" class="org.eclipse.jetty.rewrite.handler.ProxyRule"&gt;
* &lt;Set name="pattern"&gt;/*&lt;/Set&gt;
* &lt;Set name="proxyTo"&gt;http://webtide.com:8080&lt;/Set&gt;
* &lt;/New&gt;
* &lt;/Item&gt;
*
* &lt;Item&gt;
* &lt;New id="response" class="org.eclipse.jetty.rewrite.handler.ResponsePatternRule"&gt;
* &lt;Set name="pattern"&gt;/session/&lt;/Set&gt;
* &lt;Set name="code"&gt;400&lt;/Set&gt;
@ -75,7 +82,7 @@ import org.eclipse.jetty.server.handler.HandlerWrapper;
* &lt;/New&gt;
* &lt;/Item&gt;
*
* &lt;Item&gt;
* &lt;Item&gt;
* &lt;New id="header" class="org.eclipse.jetty.rewrite.handler.HeaderPatternRule"&gt;
* &lt;Set name="pattern"&gt;*.jsp&lt;/Set&gt;
* &lt;Set name="name"&gt;server&lt;/Set&gt;
@ -83,7 +90,7 @@ import org.eclipse.jetty.server.handler.HandlerWrapper;
* &lt;/New&gt;
* &lt;/Item&gt;
*
* &lt;Item&gt;
* &lt;Item&gt;
* &lt;New id="header" class="org.eclipse.jetty.rewrite.handler.HeaderPatternRule"&gt;
* &lt;Set name="pattern"&gt;*.jsp&lt;/Set&gt;
* &lt;Set name="name"&gt;title&lt;/Set&gt;
@ -91,28 +98,28 @@ import org.eclipse.jetty.server.handler.HandlerWrapper;
* &lt;/New&gt;
* &lt;/Item&gt;
*
* &lt;Item&gt;
* &lt;Item&gt;
* &lt;New id="redirect" class="org.eclipse.jetty.rewrite.handler.RedirectPatternRule"&gt;
* &lt;Set name="pattern"&gt;/test/dispatch&lt;/Set&gt;
* &lt;Set name="location"&gt;http://jetty.eclipse.org&lt;/Set&gt;
* &lt;/New&gt;
* &lt;/Item&gt;
*
* &lt;Item&gt;
* &lt;Item&gt;
* &lt;New id="regexRewrite" class="org.eclipse.jetty.rewrite.handler.RewriteRegexRule"&gt;
* &lt;Set name="regex"&gt;/test-jaas/$&lt;/Set&gt;
* &lt;Set name="replacement"&gt;/demo&lt;/Set&gt;
* &lt;/New&gt;
* &lt;/Item&gt;
*
* &lt;Item&gt;
*
* &lt;Item&gt;
* &lt;New id="forwardedHttps" class="org.eclipse.jetty.rewrite.handler.ForwardedSchemeHeaderRule"&gt;
* &lt;Set name="header"&gt;X-Forwarded-Scheme&lt;/Set&gt;
* &lt;Set name="headerValue"&gt;https&lt;/Set&gt;
* &lt;Set name="scheme"&gt;https&lt;/Set&gt;
* &lt;/New&gt;
* &lt;/Item&gt;
*
*
* &lt;Item&gt;
* &lt;New id="virtualHost" class="org.eclipse.jetty.rewrite.handler.VirtualHostRuleContainer"&gt;
*
@ -134,10 +141,10 @@ import org.eclipse.jetty.server.handler.HandlerWrapper;
* &lt;/New&gt;
* &lt;/Arg&gt;
* &lt;/Call&gt;
*
*
* &lt;/New&gt;
* &lt;/ Item&gt;
*
*
* &lt;/Array&gt;
* &lt;/Set&gt;
*
@ -162,13 +169,13 @@ import org.eclipse.jetty.server.handler.HandlerWrapper;
* &lt;/New&gt;
* &lt;/Set&gt;
* </pre>
*
*
*/
public class RewriteHandler extends HandlerWrapper
{
private RuleContainer _rules;
/* ------------------------------------------------------------ */
public RewriteHandler()
{
@ -179,7 +186,7 @@ public class RewriteHandler extends HandlerWrapper
/**
* To enable configuration from jetty.xml on rewriteRequestURI, rewritePathInfo and
* originalPathAttribute
*
*
* @param legacyRule old style rewrite rule
*/
@Deprecated
@ -201,7 +208,7 @@ public class RewriteHandler extends HandlerWrapper
/* ------------------------------------------------------------ */
/**
* Assigns the rules to process.
* @param rules an array of {@link Rule}.
* @param rules an array of {@link Rule}.
*/
public void setRules(Rule[] rules)
{
@ -297,13 +304,13 @@ public class RewriteHandler extends HandlerWrapper
public void handle(String target, Request baseRequest, HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException
{
if (isStarted())
{
{
String returned = _rules.matchAndApply(target, request, response);
target = (returned == null) ? target : returned;
if (!baseRequest.isHandled())
super.handle(target, baseRequest, request, response);
}
}
}

View File

@ -0,0 +1,132 @@
package org.eclipse.jetty.rewrite.handler;
//========================================================================
//Copyright (c) 2006-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.
//========================================================================
import static org.junit.Assert.assertEquals;
import java.io.IOException;
import java.net.URLEncoder;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.eclipse.jetty.client.ContentExchange;
import org.eclipse.jetty.client.HttpClient;
import org.eclipse.jetty.client.HttpExchange;
import org.eclipse.jetty.http.HttpMethods;
import org.eclipse.jetty.server.Connector;
import org.eclipse.jetty.server.Request;
import org.eclipse.jetty.server.Server;
import org.eclipse.jetty.server.handler.AbstractHandler;
import org.eclipse.jetty.server.nio.SelectChannelConnector;
import org.junit.AfterClass;
import org.junit.BeforeClass;
import org.junit.Test;
public class ProxyRuleTest
{
private static ProxyRule _rule;
private static RewriteHandler _handler;
private static Server _proxyServer = new Server();
private static Connector _proxyServerConnector = new SelectChannelConnector();
private static Server _targetServer = new Server();
private static Connector _targetServerConnector = new SelectChannelConnector();
private static HttpClient _httpClient = new HttpClient();
@BeforeClass
public static void setupOnce() throws Exception
{
_targetServer.addConnector(_targetServerConnector);
_targetServer.setHandler(new AbstractHandler()
{
public void handle(String target, Request baseRequest, HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException
{
baseRequest.setHandled(true);
String responseString = "uri: " + request.getRequestURI() + " some content";
response.getOutputStream().write(responseString.getBytes());
response.setStatus(201);
}
});
_targetServer.start();
_rule = new ProxyRule();
_rule.setPattern("/foo/*");
_rule.setProxyTo("http://localhost:" + _targetServerConnector.getLocalPort());
_handler = new RewriteHandler();
_handler.setRewriteRequestURI(true);
_handler.setRules(new Rule[] { _rule });
_proxyServer.addConnector(_proxyServerConnector);
_proxyServer.setHandler(_handler);
_proxyServer.start();
_httpClient.start();
}
@AfterClass
public static void destroy() throws Exception
{
_httpClient.stop();
_proxyServer.stop();
_targetServer.stop();
_rule = null;
}
@Test
public void testProxy() throws Exception
{
ContentExchange exchange = new ContentExchange(true);
exchange.setMethod(HttpMethods.GET);
String body = "BODY";
String url = "http://localhost:" + _proxyServerConnector.getLocalPort() + "/foo?body=" + URLEncoder.encode(body,"UTF-8");
exchange.setURL(url);
_httpClient.send(exchange);
assertEquals(HttpExchange.STATUS_COMPLETED,exchange.waitForDone());
assertEquals("uri: / some content",exchange.getResponseContent());
assertEquals(201,exchange.getResponseStatus());
}
@Test
public void testProxyWithDeeperPath() throws Exception
{
ContentExchange exchange = new ContentExchange(true);
exchange.setMethod(HttpMethods.GET);
String body = "BODY";
String url = "http://localhost:" + _proxyServerConnector.getLocalPort() + "/foo/bar/foobar?body=" + URLEncoder.encode(body,"UTF-8");
exchange.setURL(url);
_httpClient.send(exchange);
assertEquals(HttpExchange.STATUS_COMPLETED,exchange.waitForDone());
assertEquals("uri: /bar/foobar some content",exchange.getResponseContent());
assertEquals(201,exchange.getResponseStatus());
}
@Test
public void testProxyNoMatch() throws Exception
{
ContentExchange exchange = new ContentExchange(true);
exchange.setMethod(HttpMethods.GET);
String body = "BODY";
String url = "http://localhost:" + _proxyServerConnector.getLocalPort() + "/foobar?body=" + URLEncoder.encode(body,"UTF-8");
exchange.setURL(url);
_httpClient.send(exchange);
assertEquals(HttpExchange.STATUS_COMPLETED,exchange.waitForDone());
assertEquals(404,exchange.getResponseStatus());
}
}

View File

@ -17,6 +17,9 @@ import java.security.Principal;
import javax.security.auth.Subject;
import org.eclipse.jetty.http.security.Credential;
import org.eclipse.jetty.security.MappedLoginService.KnownUser;
import org.eclipse.jetty.security.MappedLoginService.RolePrincipal;
import org.eclipse.jetty.server.UserIdentity;

View File

@ -13,21 +13,12 @@
package org.eclipse.jetty.security;
import java.io.File;
import java.io.FilenameFilter;
import java.io.IOException;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Properties;
import java.util.Set;
import org.eclipse.jetty.http.security.Credential;
import org.eclipse.jetty.security.PropertyUserStore.UserListener;
import org.eclipse.jetty.server.UserIdentity;
import org.eclipse.jetty.util.Scanner;
import org.eclipse.jetty.util.Scanner.BulkListener;
import org.eclipse.jetty.util.log.Log;
import org.eclipse.jetty.util.log.Logger;
import org.eclipse.jetty.util.resource.Resource;
@ -36,27 +27,24 @@ import org.eclipse.jetty.util.resource.Resource;
/**
* Properties User Realm.
*
* An implementation of UserRealm that stores users and roles in-memory in
* HashMaps.
* An implementation of UserRealm that stores users and roles in-memory in HashMaps.
* <P>
* Typically these maps are populated by calling the load() method or passing a
* properties resource to the constructor. The format of the properties file is:
* Typically these maps are populated by calling the load() method or passing a properties resource to the constructor. The format of the properties file is:
*
* <PRE>
* username: password [,rolename ...]
* </PRE>
*
* Passwords may be clear text, obfuscated or checksummed. The class
* com.eclipse.Util.Password should be used to generate obfuscated passwords or
* password checksums.
* Passwords may be clear text, obfuscated or checksummed. The class com.eclipse.Util.Password should be used to generate obfuscated passwords or password
* checksums.
*
* If DIGEST Authentication is used, the password must be in a recoverable
* format, either plain text or OBF:.
* If DIGEST Authentication is used, the password must be in a recoverable format, either plain text or OBF:.
*/
public class HashLoginService extends MappedLoginService
public class HashLoginService extends MappedLoginService implements UserListener
{
private static final Logger LOG = Log.getLogger(HashLoginService.class);
private PropertyUserStore _propertyUserStore;
private String _config;
private Resource _configResource;
private Scanner _scanner;
@ -72,14 +60,14 @@ public class HashLoginService extends MappedLoginService
{
setName(name);
}
/* ------------------------------------------------------------ */
public HashLoginService(String name, String config)
{
setName(name);
setConfig(config);
}
/* ------------------------------------------------------------ */
public String getConfig()
{
@ -89,7 +77,7 @@ public class HashLoginService extends MappedLoginService
/* ------------------------------------------------------------ */
public void getConfig(String config)
{
_config=config;
_config = config;
}
/* ------------------------------------------------------------ */
@ -100,11 +88,10 @@ public class HashLoginService extends MappedLoginService
/* ------------------------------------------------------------ */
/**
* Load realm users from properties file. The property file maps usernames
* to password specs followed by an optional comma separated list of role
* names.
* Load realm users from properties file. The property file maps usernames to password specs followed by an optional comma separated list of role names.
*
* @param config Filename or url of user properties file.
* @param config
* Filename or url of user properties file.
*/
public void setConfig(String config)
{
@ -129,52 +116,14 @@ public class HashLoginService extends MappedLoginService
{
return null;
}
/* ------------------------------------------------------------ */
@Override
public void loadUsers() throws IOException
{
if (_config==null)
return;
_configResource = Resource.newResource(_config);
if (LOG.isDebugEnabled()) LOG.debug("Load " + this + " from " + _config);
Properties properties = new Properties();
properties.load(_configResource.getInputStream());
Set<String> known = new HashSet<String>();
for (Map.Entry<Object, Object> entry : properties.entrySet())
{
String username = ((String) entry.getKey()).trim();
String credentials = ((String) entry.getValue()).trim();
String roles = null;
int c = credentials.indexOf(',');
if (c > 0)
{
roles = credentials.substring(c + 1).trim();
credentials = credentials.substring(0, c).trim();
}
if (username != null && username.length() > 0 && credentials != null && credentials.length() > 0)
{
String[] roleArray = IdentityService.NO_ROLES;
if (roles != null && roles.length() > 0)
roleArray = roles.split(",");
known.add(username);
putUser(username,Credential.getCredential(credentials),roleArray);
}
}
Iterator<String> users = _users.keySet().iterator();
while(users.hasNext())
{
String user=users.next();
if (!known.contains(user))
users.remove();
}
// TODO: Consider refactoring MappedLoginService to not have to override with unused methods
}
/* ------------------------------------------------------------ */
/**
* @see org.eclipse.jetty.util.component.AbstractLifeCycle#doStart()
@ -183,54 +132,17 @@ public class HashLoginService extends MappedLoginService
{
super.doStart();
if (getRefreshInterval() > 0)
if (_propertyUserStore == null)
{
_scanner = new Scanner();
_scanner.setScanInterval(getRefreshInterval());
List<File> dirList = new ArrayList<File>(1);
dirList.add(_configResource.getFile());
_scanner.setScanDirs(dirList);
_scanner.setFilenameFilter(new FilenameFilter()
if(LOG.isDebugEnabled())
{
public boolean accept(File dir, String name)
{
File f = new File(dir, name);
try
{
if (f.compareTo(_configResource.getFile()) == 0) return true;
}
catch (IOException e)
{
return false;
}
return false;
}
});
_scanner.addListener(new BulkListener()
{
public void filesChanged(List<String> filenames) throws Exception
{
if (filenames == null) return;
if (filenames.isEmpty()) return;
if (filenames.size() == 1)
{
Resource r = Resource.newResource(filenames.get(0));
if (r.getFile().equals(_configResource.getFile()))
loadUsers();
}
}
public String toString()
{
return "HashLoginService$Scanner";
}
});
_scanner.setReportExistingFilesOnStartup(false);
_scanner.setRecursive(false);
_scanner.start();
LOG.debug("doStart: Starting new PropertyUserStore. PropertiesFile: " + _config + " refreshInterval: " + _refreshInterval);
}
_propertyUserStore = new PropertyUserStore();
_propertyUserStore.setRefreshInterval(_refreshInterval);
_propertyUserStore.setConfig(_config);
_propertyUserStore.registerUserListener(this);
_propertyUserStore.start();
}
}
@ -241,9 +153,24 @@ public class HashLoginService extends MappedLoginService
protected void doStop() throws Exception
{
super.doStop();
if (_scanner != null) _scanner.stop();
if (_scanner != null)
_scanner.stop();
_scanner = null;
}
/* ------------------------------------------------------------ */
public void update(String userName, Credential credential, String[] roleArray)
{
if (LOG.isDebugEnabled())
LOG.debug("update: " + userName + " Roles: " + roleArray.length);
putUser(userName,credential,roleArray);
}
/* ------------------------------------------------------------ */
public void remove(String userName)
{
if (LOG.isDebugEnabled())
LOG.debug("remove: " + userName);
removeUser(userName);
}
}

View File

@ -14,9 +14,9 @@
package org.eclipse.jetty.security;
import java.security.Principal;
import javax.security.auth.Subject;
import org.eclipse.jetty.http.security.Credential;
import org.eclipse.jetty.server.Request;
import org.eclipse.jetty.server.UserIdentity;

View File

@ -3,7 +3,9 @@ package org.eclipse.jetty.security;
import java.io.File;
import java.io.FilenameFilter;
import java.io.IOException;
import java.security.Principal;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
@ -11,7 +13,12 @@ import java.util.Map;
import java.util.Properties;
import java.util.Set;
import javax.security.auth.Subject;
import org.eclipse.jetty.http.security.Credential;
import org.eclipse.jetty.security.MappedLoginService.KnownUser;
import org.eclipse.jetty.security.MappedLoginService.RolePrincipal;
import org.eclipse.jetty.server.UserIdentity;
import org.eclipse.jetty.util.Scanner;
import org.eclipse.jetty.util.Scanner.BulkListener;
import org.eclipse.jetty.util.component.AbstractLifeCycle;
@ -42,8 +49,10 @@ public class PropertyUserStore extends AbstractLifeCycle
private Scanner _scanner;
private int _refreshInterval = 0;// default is not to reload
private IdentityService _identityService = new DefaultIdentityService();
private boolean _firstLoad = true; // true if first load, false from that point on
private final List<String> _knownUsers = new ArrayList<String>();
private final Map<String, UserIdentity> _knownUserIdentities = new HashMap<String, UserIdentity>();
private List<UserListener> _listeners;
/* ------------------------------------------------------------ */
@ -57,6 +66,12 @@ public class PropertyUserStore extends AbstractLifeCycle
{
_config = config;
}
/* ------------------------------------------------------------ */
public UserIdentity getUserIdentity(String userName)
{
return _knownUserIdentities.get(userName);
}
/* ------------------------------------------------------------ */
/**
@ -119,9 +134,29 @@ public class PropertyUserStore extends AbstractLifeCycle
{
String[] roleArray = IdentityService.NO_ROLES;
if (roles != null && roles.length() > 0)
{
roleArray = roles.split(",");
}
known.add(username);
notifyUpdate(username,Credential.getCredential(credentials),roleArray);
Credential credential = Credential.getCredential(credentials);
Principal userPrincipal = new KnownUser(username,credential);
Subject subject = new Subject();
subject.getPrincipals().add(userPrincipal);
subject.getPrivateCredentials().add(credential);
if (roles != null)
{
for (String role : roleArray)
{
subject.getPrincipals().add(new RolePrincipal(role));
}
}
subject.setReadOnly();
_knownUserIdentities.put(username,_identityService.newUserIdentity(subject,userPrincipal,roleArray));
notifyUpdate(username,credential,roleArray);
}
}
@ -138,6 +173,7 @@ public class PropertyUserStore extends AbstractLifeCycle
String user = users.next();
if (!known.contains(user))
{
_knownUserIdentities.remove(user);
notifyRemove(user);
}
}
@ -201,15 +237,17 @@ public class PropertyUserStore extends AbstractLifeCycle
_scanner.addListener(new BulkListener()
{
public void filesChanged(List filenames) throws Exception
public void filesChanged(List<String> filenames) throws Exception
{
if (filenames == null)
return;
if (filenames.isEmpty())
return;
if (filenames.size() == 1 && filenames.get(0).equals(getConfigResource().getFile().getAbsolutePath()))
if (filenames.size() == 1)
{
loadUsers();
Resource r = Resource.newResource(filenames.get(0));
if (r.getFile().equals(_configResource.getFile()))
loadUsers();
}
}

View File

@ -65,20 +65,28 @@ public class BasicAuthenticator extends LoginAuthenticator
return _deferred;
if (credentials != null)
{
credentials = credentials.substring(credentials.indexOf(' ')+1);
credentials = B64Code.decode(credentials,StringUtil.__ISO_8859_1);
int i = credentials.indexOf(':');
if (i>0)
{
int space=credentials.indexOf(' ');
if (space>0)
{
String username = credentials.substring(0,i);
String password = credentials.substring(i+1);
UserIdentity user = _loginService.login(username,password);
if (user!=null)
String method=credentials.substring(0,space);
if ("basic".equalsIgnoreCase(method))
{
renewSessionOnAuthentication(request,response);
return new UserAuthentication(getAuthMethod(),user);
credentials = credentials.substring(space+1);
credentials = B64Code.decode(credentials,StringUtil.__ISO_8859_1);
int i = credentials.indexOf(':');
if (i>0)
{
String username = credentials.substring(0,i);
String password = credentials.substring(i+1);
UserIdentity user = _loginService.login(username,password);
if (user!=null)
{
renewSessionOnAuthentication(request,response);
return new UserAuthentication(getAuthMethod(),user);
}
}
}
}
}

View File

@ -15,6 +15,12 @@ package org.eclipse.jetty.security.authentication;
import java.io.IOException;
import java.security.MessageDigest;
import java.security.SecureRandom;
import java.util.Queue;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentLinkedQueue;
import java.util.concurrent.ConcurrentMap;
import java.util.concurrent.atomic.AtomicInteger;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
@ -42,17 +48,29 @@ import org.eclipse.jetty.util.log.Logger;
/**
* @version $Rev: 4793 $ $Date: 2009-03-19 00:00:01 +0100 (Thu, 19 Mar 2009) $
*
* The nonce max age can be set with the {@link SecurityHandler#setInitParameter(String, String)}
* The nonce max age in ms can be set with the {@link SecurityHandler#setInitParameter(String, String)}
* using the name "maxNonceAge"
*/
public class DigestAuthenticator extends LoginAuthenticator
{
private static final Logger LOG = Log.getLogger(DigestAuthenticator.class);
SecureRandom _random = new SecureRandom();
private long _maxNonceAgeMs = 60*1000;
private ConcurrentMap<String, Nonce> _nonceCount = new ConcurrentHashMap<String, Nonce>();
private Queue<Nonce> _nonceQueue = new ConcurrentLinkedQueue<Nonce>();
private static class Nonce
{
final String _nonce;
final long _ts;
AtomicInteger _nc=new AtomicInteger();
public Nonce(String nonce, long ts)
{
_nonce=nonce;
_ts=ts;
}
}
protected long _maxNonceAge = 0;
protected long _nonceSecret = this.hashCode() ^ System.currentTimeMillis();
protected boolean _useStale = false;
/* ------------------------------------------------------------ */
public DigestAuthenticator()
{
super();
@ -69,19 +87,22 @@ public class DigestAuthenticator extends LoginAuthenticator
String mna=configuration.getInitParameter("maxNonceAge");
if (mna!=null)
_maxNonceAge=Long.valueOf(mna);
_maxNonceAgeMs=Long.valueOf(mna);
}
/* ------------------------------------------------------------ */
public String getAuthMethod()
{
return Constraint.__DIGEST_AUTH;
}
/* ------------------------------------------------------------ */
public boolean secureResponse(ServletRequest req, ServletResponse res, boolean mandatory, User validatedUser) throws ServerAuthException
{
return true;
}
/* ------------------------------------------------------------ */
public Authentication validateRequest(ServletRequest req, ServletResponse res, boolean mandatory) throws ServerAuthException
{
if (!mandatory)
@ -144,7 +165,7 @@ public class DigestAuthenticator extends LoginAuthenticator
}
}
int n = checkNonce(digest.nonce, (Request)request);
int n = checkNonce(digest,(Request)request);
if (n > 0)
{
@ -170,8 +191,8 @@ public class DigestAuthenticator extends LoginAuthenticator
+ domain
+ "\", nonce=\""
+ newNonce((Request)request)
+ "\", algorithm=MD5, qop=\"auth\""
+ (_useStale ? (" stale=" + stale) : ""));
+ "\", algorithm=MD5, qop=\"auth\","
+ " stale=" + stale);
response.sendError(HttpServletResponse.SC_UNAUTHORIZED);
return Authentication.SEND_CONTINUE;
@ -186,87 +207,59 @@ public class DigestAuthenticator extends LoginAuthenticator
}
/* ------------------------------------------------------------ */
public String newNonce(Request request)
{
long ts=request.getTimeStamp();
long sk = _nonceSecret;
byte[] nounce = new byte[24];
for (int i = 0; i < 8; i++)
Nonce nonce;
do
{
nounce[i] = (byte) (ts & 0xff);
ts = ts >> 8;
nounce[8 + i] = (byte) (sk & 0xff);
sk = sk >> 8;
}
byte[] nounce = new byte[24];
_random.nextBytes(nounce);
byte[] hash = null;
try
{
MessageDigest md = MessageDigest.getInstance("MD5");
md.reset();
md.update(nounce, 0, 16);
hash = md.digest();
nonce = new Nonce(new String(B64Code.encode(nounce)),request.getTimeStamp());
}
catch (Exception e)
{
LOG.warn(e);
}
for (int i = 0; i < hash.length; i++)
{
nounce[8 + i] = hash[i];
if (i == 23) break;
}
return new String(B64Code.encode(nounce));
while (_nonceCount.putIfAbsent(nonce._nonce,nonce)!=null);
_nonceQueue.add(nonce);
return nonce._nonce;
}
/**
* @param nonce nonce to check
* @param nstring nonce to check
* @param request
* @return -1 for a bad nonce, 0 for a stale none, 1 for a good nonce
*/
/* ------------------------------------------------------------ */
private int checkNonce(String nonce, Request request)
private int checkNonce(Digest digest, Request request)
{
// firstly let's expire old nonces
long expired = request.getTimeStamp()-_maxNonceAgeMs;
Nonce nonce=_nonceQueue.peek();
while (nonce!=null && nonce._ts<expired)
{
_nonceQueue.remove();
_nonceCount.remove(nonce._nonce);
nonce=_nonceQueue.peek();
}
try
{
byte[] n = B64Code.decode(nonce.toCharArray());
if (n.length != 24) return -1;
long ts = 0;
long sk = _nonceSecret;
byte[] n2 = new byte[16];
System.arraycopy(n, 0, n2, 0, 8);
for (int i = 0; i < 8; i++)
{
n2[8 + i] = (byte) (sk & 0xff);
sk = sk >> 8;
ts = (ts << 8) + (0xff & (long) n[7 - i]);
}
long age = request.getTimeStamp() - ts;
if (LOG.isDebugEnabled()) LOG.debug("age=" + age);
byte[] hash = null;
try
{
MessageDigest md = MessageDigest.getInstance("MD5");
md.reset();
md.update(n2, 0, 16);
hash = md.digest();
}
catch (Exception e)
{
LOG.warn(e);
}
for (int i = 0; i < 16; i++)
if (n[i + 8] != hash[i]) return -1;
if (_maxNonceAge > 0 && (age < 0 || age > _maxNonceAge)) return 0; // stale
nonce = _nonceCount.get(digest.nonce);
if (nonce==null)
return 0;
long count = Long.parseLong(digest.nc,16);
if (count>Integer.MAX_VALUE)
return 0;
int old=nonce._nc.get();
while (!nonce._nc.compareAndSet(old,(int)count))
old=nonce._nc.get();
if (count<=old)
return -1;
return 1;
}
catch (Exception e)
@ -276,18 +269,21 @@ public class DigestAuthenticator extends LoginAuthenticator
return -1;
}
/* ------------------------------------------------------------ */
/* ------------------------------------------------------------ */
/* ------------------------------------------------------------ */
private static class Digest extends Credential
{
private static final long serialVersionUID = -2484639019549527724L;
String method = null;
String username = null;
String realm = null;
String nonce = null;
String nc = null;
String cnonce = null;
String qop = null;
String uri = null;
String response = null;
final String method;
String username = "";
String realm = "";
String nonce = "";
String nc = "";
String cnonce = "";
String qop = "";
String uri = "";
String response = "";
/* ------------------------------------------------------------ */
Digest(String m)

View File

@ -201,13 +201,13 @@ public class ConstraintTest
assertTrue(response.indexOf("WWW-Authenticate: basic realm=\"TestRealm\"") > 0);
response = _connector.getResponses("GET /ctx/auth/info HTTP/1.0\r\n" +
"Authorization: " + B64Code.encode("user:wrong") + "\r\n" +
"Authorization: Basic " + B64Code.encode("user:wrong") + "\r\n" +
"\r\n");
assertTrue(response.startsWith("HTTP/1.1 401 Unauthorized"));
assertTrue(response.indexOf("WWW-Authenticate: basic realm=\"TestRealm\"") > 0);
response = _connector.getResponses("GET /ctx/auth/info HTTP/1.0\r\n" +
"Authorization: " + B64Code.encode("user:password") + "\r\n" +
"Authorization: Basic " + B64Code.encode("user:password") + "\r\n" +
"\r\n");
assertTrue(response.startsWith("HTTP/1.1 200 OK"));
@ -218,20 +218,20 @@ public class ConstraintTest
assertTrue(response.indexOf("WWW-Authenticate: basic realm=\"TestRealm\"") > 0);
response = _connector.getResponses("GET /ctx/admin/info HTTP/1.0\r\n" +
"Authorization: " + B64Code.encode("admin:wrong") + "\r\n" +
"Authorization: Basic " + B64Code.encode("admin:wrong") + "\r\n" +
"\r\n");
assertTrue(response.startsWith("HTTP/1.1 401 Unauthorized"));
assertTrue(response.indexOf("WWW-Authenticate: basic realm=\"TestRealm\"") > 0);
response = _connector.getResponses("GET /ctx/admin/info HTTP/1.0\r\n" +
"Authorization: " + B64Code.encode("user:password") + "\r\n" +
"Authorization: Basic " + B64Code.encode("user:password") + "\r\n" +
"\r\n");
assertTrue(response.startsWith("HTTP/1.1 403 "));
assertTrue(response.indexOf("!role") > 0);
response = _connector.getResponses("GET /ctx/admin/info HTTP/1.0\r\n" +
"Authorization: " + B64Code.encode("admin:password") + "\r\n" +
"Authorization: Basic " + B64Code.encode("admin:password") + "\r\n" +
"\r\n");
assertTrue(response.startsWith("HTTP/1.1 200 OK"));
@ -490,18 +490,18 @@ public class ConstraintTest
assertTrue(response.indexOf("WWW-Authenticate: basic realm=\"TestRealm\"") > 0);
response = _connector.getResponses("GET /ctx/auth/info HTTP/1.0\r\n" +
"Authorization: " + B64Code.encode("user:wrong") + "\r\n" +
"Authorization: Basic " + B64Code.encode("user:wrong") + "\r\n" +
"\r\n");
assertTrue(response.startsWith("HTTP/1.1 401 Unauthorized"));
assertTrue(response.indexOf("WWW-Authenticate: basic realm=\"TestRealm\"") > 0);
response = _connector.getResponses("GET /ctx/auth/info HTTP/1.0\r\n" +
"Authorization: " + B64Code.encode("user:password") + "\r\n" +
"Authorization: Basic " + B64Code.encode("user:password") + "\r\n" +
"\r\n");
assertTrue(response.startsWith("HTTP/1.1 403"));
response = _connector.getResponses("GET /ctx/auth/info HTTP/1.0\r\n" +
"Authorization: " + B64Code.encode("user2:password") + "\r\n" +
"Authorization: Basic " + B64Code.encode("user2:password") + "\r\n" +
"\r\n");
assertTrue(response.startsWith("HTTP/1.1 200 OK"));
@ -512,20 +512,20 @@ public class ConstraintTest
assertTrue(response.indexOf("WWW-Authenticate: basic realm=\"TestRealm\"") > 0);
response = _connector.getResponses("GET /ctx/admin/info HTTP/1.0\r\n" +
"Authorization: " + B64Code.encode("admin:wrong") + "\r\n" +
"Authorization: Basic " + B64Code.encode("admin:wrong") + "\r\n" +
"\r\n");
assertTrue(response.startsWith("HTTP/1.1 401 Unauthorized"));
assertTrue(response.indexOf("WWW-Authenticate: basic realm=\"TestRealm\"") > 0);
response = _connector.getResponses("GET /ctx/admin/info HTTP/1.0\r\n" +
"Authorization: " + B64Code.encode("user:password") + "\r\n" +
"Authorization: Basic " + B64Code.encode("user:password") + "\r\n" +
"\r\n");
assertTrue(response.startsWith("HTTP/1.1 403 "));
assertTrue(response.indexOf("!role") > 0);
response = _connector.getResponses("GET /ctx/admin/info HTTP/1.0\r\n" +
"Authorization: " + B64Code.encode("admin:password") + "\r\n" +
"Authorization: Basic " + B64Code.encode("admin:password") + "\r\n" +
"\r\n");
assertTrue(response.startsWith("HTTP/1.1 200 OK"));
@ -776,7 +776,7 @@ public class ConstraintTest
assertTrue(response.startsWith("HTTP/1.1 200 OK"));
response = _connector.getResponses("GET /ctx/auth/info HTTP/1.0\r\n" +
"Authorization: " + B64Code.encode("user2:password") + "\r\n" +
"Authorization: Basic " + B64Code.encode("user2:password") + "\r\n" +
"\r\n");
assertTrue(response.startsWith("HTTP/1.1 500 "));
@ -789,7 +789,7 @@ public class ConstraintTest
_server.start();
response = _connector.getResponses("GET /ctx/auth/info HTTP/1.0\r\n" +
"Authorization: " + B64Code.encode("user2:password") + "\r\n" +
"Authorization: Basic " + B64Code.encode("user2:password") + "\r\n" +
"\r\n");
assertTrue(response.startsWith("HTTP/1.1 200 OK"));
}
@ -809,13 +809,13 @@ public class ConstraintTest
assertTrue(response.indexOf("user=null") > 0);
response = _connector.getResponses("GET /ctx/noauth/info HTTP/1.0\r\n"+
"Authorization: " + B64Code.encode("admin:wrong") + "\r\n" +
"Authorization: Basic " + B64Code.encode("admin:wrong") + "\r\n" +
"\r\n");
assertTrue(response.startsWith("HTTP/1.1 200 OK"));
assertTrue(response.indexOf("user=null") > 0);
response = _connector.getResponses("GET /ctx/noauth/info HTTP/1.0\r\n"+
"Authorization: " + B64Code.encode("admin:password") + "\r\n" +
"Authorization: Basic " + B64Code.encode("admin:password") + "\r\n" +
"\r\n");
assertTrue(response.startsWith("HTTP/1.1 200 OK"));
assertTrue(response.indexOf("user=admin") > 0);

View File

@ -78,6 +78,9 @@ public class PropertyUserStoreTest
store.start();
Assert.assertNotNull("Failed to retrieve UserIdentity directly from PropertyUserStore", store.getUserIdentity("tom"));
Assert.assertNotNull("Failed to retrieve UserIdentity directly from PropertyUserStore", store.getUserIdentity("dick"));
Assert.assertNotNull("Failed to retrieve UserIdentity directly from PropertyUserStore", store.getUserIdentity("harry"));
Assert.assertEquals(3,userCount.get());
}
@ -117,7 +120,11 @@ public class PropertyUserStoreTest
long start = System.currentTimeMillis();
while (userCount.get() < 4 && (System.currentTimeMillis() - start) < 10000)
{
Thread.sleep(10);
}
Assert.assertNotNull("Failed to retrieve UserIdentity from PropertyUserStore directly", store.getUserIdentity("skip"));
Assert.assertEquals(4,userCount.get());
Assert.assertTrue(users.contains("skip"));

View File

@ -112,5 +112,11 @@
<version>${project.version}</version>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.mockito</groupId>
<artifactId>mockito-core</artifactId>
<version>1.8.5</version>
<scope>test</scope>
</dependency>
</dependencies>
</project>

View File

@ -7,12 +7,18 @@ import org.eclipse.jetty.http.HttpStatus;
import org.eclipse.jetty.io.AsyncEndPoint;
import org.eclipse.jetty.io.Connection;
import org.eclipse.jetty.io.EndPoint;
import org.eclipse.jetty.io.nio.ChannelEndPoint;
import org.eclipse.jetty.io.nio.SelectChannelEndPoint;
import org.eclipse.jetty.util.log.Log;
import org.eclipse.jetty.util.log.Logger;
public class AsyncHttpConnection extends HttpConnection
{
private final static int NO_PROGRESS_INFO = Integer.getInteger("org.mortbay.jetty.NO_PROGRESS_INFO",100);
private final static int NO_PROGRESS_CLOSE = Integer.getInteger("org.mortbay.jetty.NO_PROGRESS_CLOSE",200);
private static final Logger LOG = Log.getLogger(AsyncHttpConnection.class);
private int _total_no_progress;
public AsyncHttpConnection(Connector connector, EndPoint endpoint, Server server)
{
@ -21,22 +27,23 @@ public class AsyncHttpConnection extends HttpConnection
public Connection handle() throws IOException
{
LOG.debug("handle {}",this);
Connection connection = this;
boolean some_progress=false;
boolean progress=true;
// Loop while more in buffer
try
{
setCurrentConnection(this);
boolean progress=true;
boolean more_in_buffer =false;
while (_endp.isOpen() && (more_in_buffer || progress))
while (_endp.isOpen() && (more_in_buffer || progress) && connection==this)
{
progress=false;
try
{
LOG.debug("async request",_request);
// Handle resumed request
if (_request._async.isAsync() && !_request._async.isComplete())
@ -88,7 +95,7 @@ public class AsyncHttpConnection extends HttpConnection
{
_parser.reset();
_generator.reset(true);
return switched;
connection=switched;
}
}
@ -98,7 +105,6 @@ public class AsyncHttpConnection extends HttpConnection
reset(false);
more_in_buffer = _parser.isMoreInBuffer() || _endp.isBufferingInput();
}
// else Are we suspended?
else if (_request.isAsyncStarted())
{
@ -108,6 +114,8 @@ public class AsyncHttpConnection extends HttpConnection
}
else
more_in_buffer = _parser.isMoreInBuffer() || _endp.isBufferingInput();
some_progress|=progress|((SelectChannelEndPoint)_endp).isProgressing();
}
}
}
@ -117,10 +125,36 @@ public class AsyncHttpConnection extends HttpConnection
_parser.returnBuffers();
// Are we write blocked
if (_generator.isCommitted() && !_generator.isComplete())
if (_generator.isCommitted() && !_generator.isComplete() && _endp.isOpen())
((AsyncEndPoint)_endp).scheduleWrite();
else
_generator.returnBuffers();
if (!some_progress)
{
_total_no_progress++;
if (NO_PROGRESS_INFO>0 && _total_no_progress%NO_PROGRESS_INFO==0 && (NO_PROGRESS_CLOSE<=0 || _total_no_progress< NO_PROGRESS_CLOSE))
{
LOG.info("EndPoint making no progress: "+_total_no_progress+" "+_endp);
LOG.setDebugEnabled(true);
Log.getLogger("org.eclipse.jetty.io.nio").getLogger("ssl").setDebugEnabled(true);
Log.getLogger(ChannelEndPoint.class).setDebugEnabled(true);
}
if (NO_PROGRESS_CLOSE>0 && _total_no_progress>NO_PROGRESS_CLOSE)
{
LOG.warn("Closing EndPoint making no progress: "+_total_no_progress+" "+_endp);
_endp.close();
if (_endp instanceof SelectChannelEndPoint)
{
System.err.println(((SelectChannelEndPoint)_endp).getSelectManager().dump());
}
}
}
LOG.debug("unhandle {}",this);
}
return connection;
}

View File

@ -76,9 +76,8 @@ public class BlockingHttpConnection extends HttpConnection
LOG.debug(e);
}
_generator.sendError(e.getStatus(), e.getReason(), null, true);
_parser.reset();
_endp.close();
_endp.shutdownOutput();
}
finally
{

View File

@ -205,6 +205,7 @@ public class Dispatcher implements RequestDispatcher
if (!(response instanceof HttpServletResponse))
response = new ServletResponseHttpWrapper(response);
final boolean old_handled=baseRequest.isHandled();
final String old_uri=baseRequest.getRequestURI();
final String old_context_path=baseRequest.getContextPath();
final String old_servlet_path=baseRequest.getServletPath();
@ -216,6 +217,7 @@ public class Dispatcher implements RequestDispatcher
try
{
baseRequest.setHandled(false);
baseRequest.setDispatcherType(dispatch);
if (_named!=null)
@ -262,6 +264,8 @@ public class Dispatcher implements RequestDispatcher
baseRequest.setRequestURI(_uri);
baseRequest.setContextPath(_contextHandler.getContextPath());
baseRequest.setServletPath(null);
baseRequest.setPathInfo(_uri);
baseRequest.setAttributes(attr);
_contextHandler.handle(_path,baseRequest, (HttpServletRequest)request, (HttpServletResponse)response);
@ -286,6 +290,7 @@ public class Dispatcher implements RequestDispatcher
}
finally
{
baseRequest.setHandled(old_handled);
baseRequest.setRequestURI(old_uri);
baseRequest.setContextPath(old_context_path);
baseRequest.setServletPath(old_servlet_path);

View File

@ -327,7 +327,7 @@ public abstract class HttpConnection extends AbstractConnection
}
if (_in == null)
_in = new HttpInput(((HttpParser)_parser),_connector.getMaxIdleTime());
_in = new HttpInput(HttpConnection.this);
return _in;
}
@ -677,6 +677,16 @@ public abstract class HttpConnection extends AbstractConnection
return _expect102Processing;
}
/* ------------------------------------------------------------ */
public int getMaxIdleTime()
{
if (_connector.isLowResources() && _endp.getMaxIdleTime()==_connector.getMaxIdleTime())
return _connector.getLowResourceMaxIdleTime();
if (_endp.getMaxIdleTime()>0)
return _endp.getMaxIdleTime();
return _connector.getMaxIdleTime();
}
/* ------------------------------------------------------------ */
/* ------------------------------------------------------------ */
/* ------------------------------------------------------------ */
@ -966,8 +976,7 @@ public abstract class HttpConnection extends AbstractConnection
{
Output()
{
super((AbstractGenerator)HttpConnection.this._generator,
_connector.isLowResources()?_connector.getLowResourceMaxIdleTime():_connector.getMaxIdleTime());
super(HttpConnection.this);
}
/* ------------------------------------------------------------ */

View File

@ -22,14 +22,14 @@ import org.eclipse.jetty.io.Buffer;
public class HttpInput extends ServletInputStream
{
protected final HttpConnection _connection;
protected final HttpParser _parser;
protected final long _maxIdleTime;
/* ------------------------------------------------------------ */
public HttpInput(HttpParser parser, long maxIdleTime)
public HttpInput(HttpConnection connection)
{
_parser=parser;
_maxIdleTime=maxIdleTime;
_connection=connection;
_parser=(HttpParser)connection.getParser();
}
/* ------------------------------------------------------------ */
@ -40,7 +40,7 @@ public class HttpInput extends ServletInputStream
public int read() throws IOException
{
int c=-1;
Buffer content=_parser.blockForContent(_maxIdleTime);
Buffer content=_parser.blockForContent(_connection.getMaxIdleTime());
if (content!=null)
c= 0xff & content.get();
return c;
@ -54,7 +54,7 @@ public class HttpInput extends ServletInputStream
public int read(byte[] b, int off, int len) throws IOException
{
int l=-1;
Buffer content=_parser.blockForContent(_maxIdleTime);
Buffer content=_parser.blockForContent(_connection.getMaxIdleTime());
if (content!=null)
l= content.get(b, off, len);
return l;

View File

@ -36,9 +36,8 @@ import org.eclipse.jetty.util.ByteArrayOutputStream2;
*/
public class HttpOutput extends ServletOutputStream
{
protected final HttpConnection _connection;
protected final AbstractGenerator _generator;
protected final long _maxIdleTime;
protected final ByteArrayBuffer _buf = new ByteArrayBuffer(AbstractGenerator.NO_BYTES);
private boolean _closed;
// These are held here for reuse by Writer
@ -46,15 +45,20 @@ public class HttpOutput extends ServletOutputStream
Writer _converter;
char[] _chars;
ByteArrayOutputStream2 _bytes;
/* ------------------------------------------------------------ */
public HttpOutput(AbstractGenerator generator, long maxIdleTime)
public HttpOutput(HttpConnection connection)
{
_generator=generator;
_maxIdleTime=maxIdleTime;
_connection=connection;
_generator=(AbstractGenerator)connection.getGenerator();
}
/* ------------------------------------------------------------ */
public int getMaxIdleTime()
{
return _connection.getMaxIdleTime();
}
/* ------------------------------------------------------------ */
public boolean isWritten()
{
@ -87,7 +91,7 @@ public class HttpOutput extends ServletOutputStream
@Override
public void flush() throws IOException
{
_generator.flush(_maxIdleTime);
_generator.flush(getMaxIdleTime());
}
/* ------------------------------------------------------------ */
@ -122,7 +126,7 @@ public class HttpOutput extends ServletOutputStream
// Block until we can add _content.
while (_generator.isBufferFull())
{
_generator.blockForOutput(_maxIdleTime);
_generator.blockForOutput(getMaxIdleTime());
if (_closed)
throw new IOException("Closed");
if (!_generator.isOpen())
@ -152,7 +156,7 @@ public class HttpOutput extends ServletOutputStream
// Block until we can add _content.
while (_generator.isBufferFull())
{
_generator.blockForOutput(_maxIdleTime);
_generator.blockForOutput(getMaxIdleTime());
if (_closed)
throw new IOException("Closed");
if (!_generator.isOpen())
@ -175,7 +179,7 @@ public class HttpOutput extends ServletOutputStream
// Block until our buffer is free
while (buffer.length() > 0 && _generator.isOpen())
{
_generator.blockForOutput(_maxIdleTime);
_generator.blockForOutput(getMaxIdleTime());
}
}

View File

@ -23,9 +23,12 @@ import org.eclipse.jetty.io.ByteArrayBuffer;
import org.eclipse.jetty.io.ByteArrayEndPoint;
import org.eclipse.jetty.io.Connection;
import org.eclipse.jetty.util.StringUtil;
import org.eclipse.jetty.util.log.Log;
import org.eclipse.jetty.util.log.Logger;
public class LocalConnector extends AbstractConnector
{
private static final Logger LOG = Log.getLogger(LocalConnector.class);
private final BlockingQueue<Request> _requests = new LinkedBlockingQueue<Request>();
public LocalConnector()
@ -135,8 +138,14 @@ public class LocalConnector extends AbstractConnector
}
}
}
catch (IOException x)
{
LOG.debug(x);
leaveOpen = false;
}
catch (Exception x)
{
LOG.warn(x);
leaveOpen = false;
}
finally

View File

@ -202,79 +202,36 @@ public class Request implements HttpServletRequest
/* ------------------------------------------------------------ */
/**
* Extract Paramters from query string and/or form _content.
* Extract Parameters from query string and/or form _content.
*/
public void extractParameters()
{
if (_baseParameters == null)
_baseParameters = new MultiMap(16);
if (_paramsExtracted)
{
if (_parameters==null)
_parameters=_baseParameters;
return;
}
_paramsExtracted = true;
// Handle query string
if (_uri!=null && _uri.hasQuery())
try
{
if (_queryEncoding==null)
_uri.decodeQueryTo(_baseParameters);
else
// Handle query string
if (_uri!=null && _uri.hasQuery())
{
try
{
_uri.decodeQueryTo(_baseParameters,_queryEncoding);
}
catch (UnsupportedEncodingException e)
{
if (LOG.isDebugEnabled())
LOG.warn(e);
else
LOG.warn(e.toString());
}
}
}
// handle any _content.
String encoding = getCharacterEncoding();
String content_type = getContentType();
if (content_type != null && content_type.length() > 0)
{
content_type = HttpFields.valueParameters(content_type, null);
if (MimeTypes.FORM_ENCODED.equalsIgnoreCase(content_type) && _inputState==__NONE &&
(HttpMethods.POST.equals(getMethod()) || HttpMethods.PUT.equals(getMethod())))
{
int content_length = getContentLength();
if (content_length != 0)
if (_queryEncoding==null)
_uri.decodeQueryTo(_baseParameters);
else
{
try
{
int maxFormContentSize=-1;
if (_context!=null)
maxFormContentSize=_context.getContextHandler().getMaxFormContentSize();
else
{
Integer size = (Integer)_connection.getConnector().getServer().getAttribute("org.eclipse.jetty.server.Request.maxFormContentSize");
if (size!=null)
maxFormContentSize =size.intValue();
}
if (content_length>maxFormContentSize && maxFormContentSize > 0)
{
throw new IllegalStateException("Form too large"+content_length+">"+maxFormContentSize);
}
InputStream in = getInputStream();
// Add form params to query params
UrlEncoded.decodeTo(in, _baseParameters, encoding,content_length<0?maxFormContentSize:-1);
_uri.decodeQueryTo(_baseParameters,_queryEncoding);
}
catch (IOException e)
catch (UnsupportedEncodingException e)
{
if (LOG.isDebugEnabled())
LOG.warn(e);
@ -283,23 +240,75 @@ public class Request implements HttpServletRequest
}
}
}
}
if (_parameters==null)
_parameters=_baseParameters;
else if (_parameters!=_baseParameters)
{
// Merge parameters (needed if parameters extracted after a forward).
Iterator iter = _baseParameters.entrySet().iterator();
while (iter.hasNext())
// handle any _content.
String encoding = getCharacterEncoding();
String content_type = getContentType();
if (content_type != null && content_type.length() > 0)
{
Map.Entry entry = (Map.Entry)iter.next();
String name=(String)entry.getKey();
Object values=entry.getValue();
for (int i=0;i<LazyList.size(values);i++)
_parameters.add(name, LazyList.get(values, i));
content_type = HttpFields.valueParameters(content_type, null);
if (MimeTypes.FORM_ENCODED.equalsIgnoreCase(content_type) && _inputState==__NONE &&
(HttpMethods.POST.equals(getMethod()) || HttpMethods.PUT.equals(getMethod())))
{
int content_length = getContentLength();
if (content_length != 0)
{
try
{
int maxFormContentSize=-1;
if (_context!=null)
maxFormContentSize=_context.getContextHandler().getMaxFormContentSize();
else
{
Integer size = (Integer)_connection.getConnector().getServer().getAttribute("org.eclipse.jetty.server.Request.maxFormContentSize");
if (size!=null)
maxFormContentSize =size.intValue();
}
if (content_length>maxFormContentSize && maxFormContentSize > 0)
{
throw new IllegalStateException("Form too large"+content_length+">"+maxFormContentSize);
}
InputStream in = getInputStream();
// Add form params to query params
UrlEncoded.decodeTo(in, _baseParameters, encoding,content_length<0?maxFormContentSize:-1);
}
catch (IOException e)
{
if (LOG.isDebugEnabled())
LOG.warn(e);
else
LOG.warn(e.toString());
}
}
}
}
}
if (_parameters==null)
_parameters=_baseParameters;
else if (_parameters!=_baseParameters)
{
// Merge parameters (needed if parameters extracted after a forward).
Iterator iter = _baseParameters.entrySet().iterator();
while (iter.hasNext())
{
Map.Entry entry = (Map.Entry)iter.next();
String name=(String)entry.getKey();
Object values=entry.getValue();
for (int i=0;i<LazyList.size(values);i++)
_parameters.add(name, LazyList.get(values, i));
}
}
}
finally
{
//ensure params always set (even if empty) after extraction
if (_parameters==null)
_parameters=_baseParameters;
}
}
/* ------------------------------------------------------------ */

View File

@ -431,7 +431,7 @@ public class Response implements HttpServletResponse
if (!canonical.equals(path))
{
buf = _connection.getRequest().getRootURL();
buf.append(canonical);
buf.append(URIUtil.encodePath(canonical));
if (uri.getQuery()!=null)
{
buf.append('?');

View File

@ -17,6 +17,7 @@ import java.io.IOException;
import java.net.InetAddress;
import java.net.ServerSocket;
import java.net.Socket;
import java.net.SocketException;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Set;
@ -251,6 +252,12 @@ public class SocketConnector extends AbstractConnector
try{close();}
catch(IOException e2){LOG.ignore(e2);}
}
catch (SocketException e)
{
LOG.debug("EOF", e);
try{close();}
catch(IOException e2){LOG.ignore(e2);}
}
catch (HttpException e)
{
LOG.debug("BAD", e);

View File

@ -833,7 +833,7 @@ public class ContextHandler extends ScopedHandler implements Attributes, Server.
String old_path_info = null;
ClassLoader old_classloader = null;
Thread current_thread = null;
String pathInfo = null;
String pathInfo = target;
DispatcherType dispatch = baseRequest.getDispatcherType();

View File

@ -159,7 +159,7 @@ public class GzipHandler extends HandlerWrapper
*
* @return the buffer size
*/
public int setBufferSize()
public int getBufferSize()
{
return _bufferSize;
}

View File

@ -29,6 +29,7 @@ import org.eclipse.jetty.http.MimeTypes;
import org.eclipse.jetty.io.Buffer;
import org.eclipse.jetty.io.ByteArrayBuffer;
import org.eclipse.jetty.io.WriterOutputStream;
import org.eclipse.jetty.server.Dispatcher;
import org.eclipse.jetty.server.HttpConnection;
import org.eclipse.jetty.server.Request;
import org.eclipse.jetty.server.Response;
@ -45,7 +46,7 @@ import org.eclipse.jetty.util.resource.Resource;
*
* This handle will serve static content and handle If-Modified-Since headers.
* No caching is done.
* Requests that cannot be handled are let pass (Eg no 404's)
* Requests for resources that do not exist are let pass (Eg no 404's).
*
*
* @org.apache.xbean.XBean
@ -205,7 +206,7 @@ public class ResourceHandler extends AbstractHandler
{
try
{
_defaultStylesheet = Resource.newResource(this.getClass().getResource("/jetty-default.css"));
_defaultStylesheet = Resource.newResource(this.getClass().getResource("/jetty-dir.css"));
}
catch(IOException e)
{
@ -292,10 +293,29 @@ public class ResourceHandler extends AbstractHandler
/* ------------------------------------------------------------ */
protected Resource getResource(HttpServletRequest request) throws MalformedURLException
{
String path_info=request.getPathInfo();
if (path_info==null)
return null;
return getResource(path_info);
String servletPath;
String pathInfo;
Boolean included = request.getAttribute(Dispatcher.INCLUDE_REQUEST_URI) != null;
if (included != null && included.booleanValue())
{
servletPath = (String)request.getAttribute(Dispatcher.INCLUDE_SERVLET_PATH);
pathInfo = (String)request.getAttribute(Dispatcher.INCLUDE_PATH_INFO);
if (servletPath == null && pathInfo == null)
{
servletPath = request.getServletPath();
pathInfo = request.getPathInfo();
}
}
else
{
included = Boolean.FALSE;
servletPath = request.getServletPath();
pathInfo = request.getPathInfo();
}
String pathInContext=URIUtil.addPaths(servletPath,pathInfo);
return getResource(pathInContext);
}
@ -326,7 +346,7 @@ public class ResourceHandler extends AbstractHandler
/* ------------------------------------------------------------ */
/*
* @see org.eclipse.jetty.server.server.Handler#handle(javax.servlet.http.HttpServletRequest, javax.servlet.http.HttpServletResponse, int)
* @see org.eclipse.jetty.server.Handler#handle(javax.servlet.http.HttpServletRequest, javax.servlet.http.HttpServletResponse, int)
*/
public void handle(String target, Request baseRequest, HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException
{
@ -334,17 +354,21 @@ public class ResourceHandler extends AbstractHandler
return;
boolean skipContentBody = false;
if(!HttpMethods.GET.equals(request.getMethod()))
{
if(!HttpMethods.HEAD.equals(request.getMethod()))
{
return;
}
skipContentBody = true;
}
Resource resource = getResource(request);
if (resource==null || !resource.exists())
{
if (target.endsWith("/jetty-stylesheet.css"))
if (target.endsWith("/jetty-dir.css"))
{
response.setContentType("text/css");
resource = getStylesheet();
@ -359,7 +383,7 @@ public class ResourceHandler extends AbstractHandler
return;
}
// We are going to server something
// We are going to serve something
baseRequest.setHandled(true);
if (resource.isDirectory())

View File

@ -0,0 +1,136 @@
// ========================================================================
// Copyright (c) 2009-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.handler;
import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.eclipse.jetty.server.Request;
import org.eclipse.jetty.server.Server;
import org.eclipse.jetty.util.log.Log;
import org.eclipse.jetty.util.log.Logger;
/* ------------------------------------------------------------ */
/**
* A handler that shuts the server down on a valid request. Used to do "soft" restarts from Java. If _exitJvm ist set to true a hard System.exit() call is being
* made.
*
* This handler is a contribution from Johannes Brodwall: https://bugs.eclipse.org/bugs/show_bug.cgi?id=357687
*
* Usage:
*
* <pre>
* Server server = new Server(8080);
* HandlerList handlers = new HandlerList();
* handlers.setHandlers(new Handler[]
* { someOtherHandler, new ShutdownHandler(server,&quot;secret password&quot;) });
* server.setHandler(handlers);
* server.start();
* </pre>
*/
public class ShutdownHandler extends AbstractHandler
{
private static final Logger LOG = Log.getLogger(ShutdownHandler.class);
private final String _shutdownToken;
private final Server _server;
private boolean _exitJvm = false;
/**
* Creates a listener that lets the server be shut down remotely (but only from localhost).
*
* @param server
* the Jetty instance that should be shut down
* @param shutdownToken
* a secret password to avoid unauthorized shutdown attempts
*/
public ShutdownHandler(Server server, String shutdownToken)
{
this._server = server;
this._shutdownToken = shutdownToken;
}
public void handle(String target, Request baseRequest, HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException
{
if (!target.equals("/shutdown"))
{
return;
}
if (!request.getMethod().equals("POST"))
{
response.sendError(HttpServletResponse.SC_BAD_REQUEST);
return;
}
if (!hasCorrectSecurityToken(request))
{
LOG.warn("Unauthorized shutdown attempt from " + getRemoteAddr(request));
response.sendError(HttpServletResponse.SC_UNAUTHORIZED);
return;
}
if (!requestFromLocalhost(request))
{
LOG.warn("Unauthorized shutdown attempt from " + getRemoteAddr(request));
response.sendError(HttpServletResponse.SC_UNAUTHORIZED);
return;
}
LOG.info("Shutting down by request from " + getRemoteAddr(request));
try
{
shutdownServer();
}
catch (Exception e)
{
throw new RuntimeException("Shutting down server",e);
}
}
private boolean requestFromLocalhost(HttpServletRequest request)
{
return "127.0.0.1".equals(getRemoteAddr(request));
}
protected String getRemoteAddr(HttpServletRequest request)
{
return request.getRemoteAddr();
}
private boolean hasCorrectSecurityToken(HttpServletRequest request)
{
return _shutdownToken.equals(request.getParameter("token"));
}
private void shutdownServer() throws Exception
{
_server.stop();
if (_exitJvm)
{
System.exit(0);
}
}
public void setExitJvm(boolean exitJvm)
{
this._exitJvm = exitJvm;
}
}

View File

@ -133,6 +133,12 @@ public class SelectChannelConnector extends AbstractNIOConnector
super.persist(endpoint);
}
/* ------------------------------------------------------------ */
public SelectorManager getSelectorManager()
{
return _manager;
}
/* ------------------------------------------------------------ */
public Object getConnection()
{

View File

@ -14,7 +14,9 @@
package org.eclipse.jetty.server.session;
import java.lang.ref.WeakReference;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
@ -46,6 +48,34 @@ public class HashSessionIdManager extends AbstractSessionIdManager
super(random);
}
/* ------------------------------------------------------------ */
/**
* @return Collection of String session IDs
*/
public Collection<String> getSessions()
{
return Collections.unmodifiableCollection(_sessions.keySet());
}
/* ------------------------------------------------------------ */
/**
* @return Collection of Sessions for the passed session ID
*/
public Collection<HttpSession> getSession(String id)
{
ArrayList<HttpSession> sessions = new ArrayList<HttpSession>();
Set<WeakReference<HttpSession>> refs =_sessions.get(id);
if (refs!=null)
{
for (WeakReference<HttpSession> ref: refs)
{
HttpSession session = ref.get();
if (session!=null)
sessions.add(session);
}
}
return sessions;
}
/* ------------------------------------------------------------ */
/** Get the session ID with any worker ID.
*

View File

@ -18,6 +18,7 @@ import java.io.InputStream;
import java.sql.Blob;
import java.sql.Connection;
import java.sql.DatabaseMetaData;
import java.sql.Driver;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
@ -56,6 +57,7 @@ public class JDBCSessionIdManager extends AbstractSessionIdManager
protected final HashSet<String> _sessionIds = new HashSet<String>();
protected Server _server;
protected Driver _driver;
protected String _driverClassName;
protected String _connectionUrl;
protected DataSource _datasource;
@ -184,6 +186,19 @@ public class JDBCSessionIdManager extends AbstractSessionIdManager
_connectionUrl=connectionUrl;
}
/**
* Configure jdbc connection information via a jdbc Driver
*
* @param driverClass
* @param connectionUrl
*/
public void setDriverInfo (Driver driverClass, String connectionUrl)
{
_driver=driverClass;
_connectionUrl=connectionUrl;
}
public String getDriverClassName()
{
return _driverClassName;
@ -461,7 +476,11 @@ public class JDBCSessionIdManager extends AbstractSessionIdManager
InitialContext ic = new InitialContext();
_datasource = (DataSource)ic.lookup(_jndiName);
}
else if (_driverClassName!=null && _connectionUrl!=null)
else if ( _driver != null && _connectionUrl != null )
{
DriverManager.registerDriver(_driver);
}
else if (_driverClassName != null && _connectionUrl != null)
{
Class.forName(_driverClassName);
}

View File

@ -16,6 +16,8 @@ package org.eclipse.jetty.server.ssl;
import java.io.IOException;
import java.nio.channels.SelectionKey;
import java.nio.channels.SocketChannel;
import java.util.Arrays;
import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLEngine;
import javax.net.ssl.SSLSession;
@ -36,7 +38,6 @@ import org.eclipse.jetty.io.nio.SslSelectChannelEndPoint;
import org.eclipse.jetty.server.HttpConnection;
import org.eclipse.jetty.server.Request;
import org.eclipse.jetty.server.nio.SelectChannelConnector;
import org.eclipse.jetty.util.log.Log;
/* ------------------------------------------------------------ */
/**
@ -97,7 +98,7 @@ public class SslSelectChannelConnector extends SelectChannelConnector implements
SslSelectChannelEndPoint sslHttpChannelEndpoint=(SslSelectChannelEndPoint)endpoint;
SSLEngine sslEngine=sslHttpChannelEndpoint.getSSLEngine();
SSLSession sslSession=sslEngine.getSession();
SslCertificates.customize(sslSession,endpoint,request);
}
@ -565,33 +566,19 @@ public class SslSelectChannelConnector extends SelectChannelConnector implements
protected SSLEngine createSSLEngine(SocketChannel channel) throws IOException
{
SSLEngine engine;
if (channel != null && _sslContextFactory.isSessionCachingEnabled())
if (channel != null)
{
String peerHost = channel.socket().getInetAddress().getHostAddress();
int peerPort = channel.socket().getPort();
engine = _sslContextFactory.getSslContext().createSSLEngine(peerHost, peerPort);
engine = _sslContextFactory.newSslEngine(peerHost, peerPort);
}
else
{
engine = _sslContextFactory.getSslContext().createSSLEngine();
engine = _sslContextFactory.newSslEngine();
}
customizeEngine(engine);
return engine;
}
/* ------------------------------------------------------------ */
private void customizeEngine(SSLEngine engine)
{
engine.setUseClientMode(false);
if (_sslContextFactory.getWantClientAuth())
engine.setWantClientAuth(_sslContextFactory.getWantClientAuth());
if (_sslContextFactory.getNeedClientAuth())
engine.setNeedClientAuth(_sslContextFactory.getNeedClientAuth());
engine.setEnabledCipherSuites(
_sslContextFactory.selectCipherSuites(engine.getEnabledCipherSuites(),
engine.getSupportedCipherSuites()));
return engine;
}
/* ------------------------------------------------------------ */
@ -601,22 +588,13 @@ public class SslSelectChannelConnector extends SelectChannelConnector implements
@Override
protected void doStart() throws Exception
{
if (!_sslContextFactory.checkConfig())
{
throw new IllegalStateException("SSL context is not configured correctly.");
}
_sslContextFactory.checkKeyStore();
_sslContextFactory.start();
SSLEngine sslEngine = _sslContextFactory.getSslContext().createSSLEngine();
SSLEngine sslEngine = _sslContextFactory.newSslEngine();
sslEngine.setUseClientMode(false);
sslEngine.setWantClientAuth(_sslContextFactory.getWantClientAuth());
sslEngine.setNeedClientAuth(_sslContextFactory.getNeedClientAuth());
sslEngine.setEnabledCipherSuites(_sslContextFactory.selectCipherSuites(
sslEngine.getEnabledCipherSuites(),
sslEngine.getSupportedCipherSuites()));
SSLSession sslSession = sslEngine.getSession();

View File

@ -30,6 +30,7 @@ import javax.net.ssl.SSLSocket;
import org.eclipse.jetty.http.HttpSchemes;
import org.eclipse.jetty.http.ssl.SslContextFactory;
import org.eclipse.jetty.io.EndPoint;
import org.eclipse.jetty.io.RuntimeIOException;
import org.eclipse.jetty.io.bio.SocketEndPoint;
import org.eclipse.jetty.server.Request;
import org.eclipse.jetty.server.bio.SocketConnector;
@ -67,6 +68,7 @@ public class SslSocketConnector extends SocketConnector implements SslConnector
this(new SslContextFactory(SslContextFactory.DEFAULT_KEYSTORE_PATH));
}
/* ------------------------------------------------------------ */
public SslSocketConnector(SslContextFactory sslContextFactory)
{
_sslContextFactory = sslContextFactory;
@ -329,6 +331,22 @@ public class SslSocketConnector extends SocketConnector implements SslConnector
return integralPort == 0 || integralPort == request.getServerPort();
}
/* ------------------------------------------------------------ */
@Override
public void open() throws IOException
{
_sslContextFactory.checkKeyStore();
try
{
_sslContextFactory.start();
}
catch(Exception e)
{
throw new RuntimeIOException(e);
}
super.open();
}
/* ------------------------------------------------------------ */
/**
* {@inheritDoc}
@ -336,11 +354,7 @@ public class SslSocketConnector extends SocketConnector implements SslConnector
@Override
protected void doStart() throws Exception
{
if (!_sslContextFactory.checkConfig())
{
throw new IllegalStateException("SSL context is not configured correctly.");
}
_sslContextFactory.checkKeyStore();
_sslContextFactory.start();
super.doStart();
@ -372,22 +386,7 @@ public class SslSocketConnector extends SocketConnector implements SslConnector
@Override
protected ServerSocket newServerSocket(String host, int port,int backlog) throws IOException
{
SSLServerSocketFactory factory = _sslContextFactory.getSslContext().getServerSocketFactory();
SSLServerSocket socket =
(SSLServerSocket) (host==null ?
factory.createServerSocket(port,backlog):
factory.createServerSocket(port,backlog,InetAddress.getByName(host)));
if (_sslContextFactory.getWantClientAuth())
socket.setWantClientAuth(_sslContextFactory.getWantClientAuth());
if (_sslContextFactory.getNeedClientAuth())
socket.setNeedClientAuth(_sslContextFactory.getNeedClientAuth());
socket.setEnabledCipherSuites(_sslContextFactory.selectCipherSuites(
socket.getEnabledCipherSuites(),
socket.getSupportedCipherSuites()));
return socket;
return _sslContextFactory.newSslServerSocket(host,port,backlog);
}
/* ------------------------------------------------------------ */

View File

@ -52,7 +52,10 @@ public class BusySelectChannelServerTest extends HttpServerTestBase
{
int x=write++&0xff;
if (x<8)
{
clearWritable();
return 0;
}
if (x<32)
return flush(header);
return super.flush(header,buffer,trailer);
@ -67,7 +70,10 @@ public class BusySelectChannelServerTest extends HttpServerTestBase
{
int x=write++&0xff;
if (x<8)
{
clearWritable();
return 0;
}
if (x<32)
{
View v = new View(buffer);
@ -75,6 +81,7 @@ public class BusySelectChannelServerTest extends HttpServerTestBase
int l=super.flush(v);
if (l>0)
buffer.skip(l);
clearWritable();
return l;
}
return super.flush(buffer);

View File

@ -45,6 +45,7 @@ public abstract class ConnectorTimeoutTest extends HttpServerTestFixture
@Test
public void testMaxIdleWithRequest10() throws Exception
{
System.err.println("testMaxIdleWithRequest10");
configureServer(new HelloWorldHandler());
Socket client=newSocket(HOST,_connector.getLocalPort());
client.setSoTimeout(10000);
@ -76,6 +77,7 @@ public abstract class ConnectorTimeoutTest extends HttpServerTestFixture
@Test
public void testMaxIdleWithRequest11() throws Exception
{
System.err.println("testMaxIdleWithRequest11");
configureServer(new EchoHandler());
Socket client=newSocket(HOST,_connector.getLocalPort());
client.setSoTimeout(10000);
@ -110,6 +112,7 @@ public abstract class ConnectorTimeoutTest extends HttpServerTestFixture
@Test
public void testMaxIdleNoRequest() throws Exception
{
System.err.println("testMaxIdleNoRequest");
configureServer(new EchoHandler());
Socket client=newSocket(HOST,_connector.getLocalPort());
client.setSoTimeout(10000);
@ -138,6 +141,7 @@ public abstract class ConnectorTimeoutTest extends HttpServerTestFixture
@Test
public void testMaxIdleWithSlowRequest() throws Exception
{
System.err.println("testMaxIdleWithSlowRequest");
configureServer(new EchoHandler());
Socket client=newSocket(HOST,_connector.getLocalPort());
client.setSoTimeout(10000);
@ -178,6 +182,7 @@ public abstract class ConnectorTimeoutTest extends HttpServerTestFixture
@Test
public void testMaxIdleWithSlowResponse() throws Exception
{
System.err.println("testMaxIdleWithSlowResponse");
configureServer(new SlowResponseHandler());
Socket client=newSocket(HOST,_connector.getLocalPort());
client.setSoTimeout(10000);
@ -207,6 +212,7 @@ public abstract class ConnectorTimeoutTest extends HttpServerTestFixture
@Test
public void testMaxIdleWithWait() throws Exception
{
System.err.println("testMaxIdleWithWait");
configureServer(new WaitHandler());
Socket client=newSocket(HOST,_connector.getLocalPort());
client.setSoTimeout(10000);

View File

@ -425,7 +425,7 @@ public abstract class HttpServerTestBase extends HttpServerTestFixture
while(len>=0)
{
Thread.sleep(500);
Thread.sleep(100);
len=is.read(buf);
if (len>0)
total+=len;
@ -447,6 +447,7 @@ public abstract class HttpServerTestBase extends HttpServerTestFixture
long start=System.currentTimeMillis();
Socket client=newSocket(HOST,_connector.getLocalPort());
int total=0;
try
{
OutputStream os=client.getOutputStream();
@ -461,7 +462,6 @@ public abstract class HttpServerTestBase extends HttpServerTestFixture
).getBytes());
os.flush();
int total=0;
int len=0;
byte[] buf=new byte[1024*32];
@ -480,6 +480,7 @@ public abstract class HttpServerTestBase extends HttpServerTestFixture
}
finally
{
System.err.println("Got "+total+" of "+(512*1024));
client.close();
}
}
@ -490,17 +491,17 @@ public abstract class HttpServerTestBase extends HttpServerTestFixture
configureServer(new BigBlockHandler());
Socket client=newSocket(HOST,_connector.getLocalPort());
client.setSoTimeout(10000);
client.setSoTimeout(20000);
try
{
OutputStream os=client.getOutputStream();
BufferedReader in = new BufferedReader(new InputStreamReader(client.getInputStream()));
os.write((
"GET / HTTP/1.1\r\n"+
"GET /r1 HTTP/1.1\r\n"+
"host: "+HOST+":"+_connector.getLocalPort()+"\r\n"+
"\r\n"+
"GET / HTTP/1.1\r\n"+
"GET /r2 HTTP/1.1\r\n"+
"host: "+HOST+":"+_connector.getLocalPort()+"\r\n"+
"connection: close\r\n"+
"\r\n"
@ -583,6 +584,7 @@ public abstract class HttpServerTestBase extends HttpServerTestFixture
}
}
// Handler that sends big blocks of data in each of 10 writes, and then sends the time it took for each big block.
protected static class BigBlockHandler extends AbstractHandler
{
public void handle(String target, Request baseRequest, HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException
@ -598,10 +600,12 @@ public abstract class HttpServerTestBase extends HttpServerTestFixture
long[] times=new long[10];
for (int i=0;i<times.length;i++)
{
// System.err.println("\nBLOCK "+request.getRequestURI()+" "+i);
long start=System.currentTimeMillis();
out.write(buf);
long end=System.currentTimeMillis();
times[i]=end-start;
// System.err.println("Block "+request.getRequestURI()+" "+i+" "+times[i]);
}
out.println();
for (long t : times)

View File

@ -12,6 +12,7 @@ import org.eclipse.jetty.io.Buffer;
import org.eclipse.jetty.io.Buffers;
import org.eclipse.jetty.io.ByteArrayBuffer;
import org.eclipse.jetty.io.ByteArrayEndPoint;
import org.eclipse.jetty.io.Connection;
import org.eclipse.jetty.io.SimpleBuffers;
import org.eclipse.jetty.util.StringUtil;
import org.eclipse.jetty.util.TypeUtil;
@ -75,7 +76,17 @@ public class HttpWriterTest
};
HttpOutput httpOut = new HttpOutput(generator,60000);
HttpConnection connection = new HttpConnection(null,endp,new Server(),null,generator,null)
{
@Override
public Connection handle() throws IOException
{
return null;
}
};
endp.setMaxIdleTime(60000);
HttpOutput httpOut = new HttpOutput(connection);
_writer = new HttpWriter(httpOut);
}
@ -158,7 +169,17 @@ public class HttpWriterTest
hb.setResponse(200,"OK");
HttpOutput output = new HttpOutput(hb,10000);
HttpConnection connection = new HttpConnection(null,endp,new Server(),null,hb,null)
{
@Override
public Connection handle() throws IOException
{
return null;
}
};
endp.setMaxIdleTime(10000);
hb.setSendServerVersion(false);
HttpOutput output = new HttpOutput(connection);
HttpWriter writer = new HttpWriter(output);
writer.setCharacterEncoding(StringUtil.__UTF8);

View File

@ -24,12 +24,16 @@ import java.io.InputStream;
import java.io.Reader;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Enumeration;
import java.util.Map;
import javax.servlet.ServletException;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import junit.framework.Assert;
import org.eclipse.jetty.server.handler.AbstractHandler;
import org.eclipse.jetty.util.IO;
import org.eclipse.jetty.util.StringUtil;
@ -68,7 +72,50 @@ public class RequestTest
_server.stop();
_server.join();
}
@Test
public void testParamExtraction() throws Exception
{
_handler._checker = new RequestTester()
{
public boolean check(HttpServletRequest request,HttpServletResponse response)
{
Map map = null;
try
{
//do the parse
request.getParameterMap();
Assert.fail("Expected parsing failure");
return false;
}
catch (Exception e)
{
//catch the error and check the param map is not null
map = request.getParameterMap();
assertFalse(map == null);
assertTrue(map.isEmpty());
Enumeration names = request.getParameterNames();
assertFalse(names.hasMoreElements());
}
return true;
}
};
//Send a request with query string with illegal hex code to cause
//an exception parsing the params
String request="GET /?param=%ZZaaa HTTP/1.1\r\n"+
"Host: whatever\r\n"+
"Content-Type: text/html;charset=utf8\n"+
"\n";
String response = _connector.getResponses(request);
}
@Test
public void testContentTypeEncoding() throws Exception
{

View File

@ -383,31 +383,45 @@ public class ResponseTest
public void testSendRedirect()
throws Exception
{
ByteArrayEndPoint out=new ByteArrayEndPoint(new byte[]{},4096);
HttpConnection connection=new TestHttpConnection(connector,out, connector.getServer());
Response response = new Response(connection);
Request request = connection.getRequest();
request.setServerName("myhost");
request.setServerPort(8888);
request.setUri(new HttpURI("/path/info;param;jsessionid=12345?query=0&more=1#target"));
request.setContextPath("/path");
request.setRequestedSessionId("12345");
request.setRequestedSessionIdFromCookie(false);
AbstractSessionManager manager=new HashSessionManager();
manager.setSessionIdManager(new HashSessionIdManager());
request.setSessionManager(manager);
request.setSession(new TestSession(manager,"12345"));
manager.setCheckingRemoteSessionIdEncoding(false);
String[][] tests={
{"/other/location?name=value","http://myhost:8888/other/location;jsessionid=12345?name=value"},
{"/other/location","http://myhost:8888/other/location"},
{"/other/l%20cation","http://myhost:8888/other/l%20cation"},
{"location","http://myhost:8888/path/location"},
{"./location","http://myhost:8888/path/location"},
{"../location","http://myhost:8888/location"},
{"/other/l%20cation","http://myhost:8888/other/l%20cation"},
{"l%20cation","http://myhost:8888/path/l%20cation"},
{"./l%20cation","http://myhost:8888/path/l%20cation"},
{"../l%20cation","http://myhost:8888/l%20cation"},
};
for (int i=1;i<tests.length;i++)
{
ByteArrayEndPoint out=new ByteArrayEndPoint(new byte[]{},4096);
HttpConnection connection=new TestHttpConnection(connector,out, connector.getServer());
Response response = new Response(connection);
Request request = connection.getRequest();
request.setServerName("myhost");
request.setServerPort(8888);
request.setUri(new HttpURI("/path/info;param;jsessionid=12345?query=0&more=1#target"));
request.setContextPath("/path");
request.setRequestedSessionId("12345");
request.setRequestedSessionIdFromCookie(i>0);
AbstractSessionManager manager=new HashSessionManager();
manager.setSessionIdManager(new HashSessionIdManager());
request.setSessionManager(manager);
request.setSession(new TestSession(manager,"12345"));
manager.setCheckingRemoteSessionIdEncoding(false);
response.sendRedirect("/other/location");
String location = out.getOut().toString();
int l=location.indexOf("Location: ");
int e=location.indexOf('\n',l);
location=location.substring(l+10,e).trim();
assertEquals("http://myhost:8888/other/location;jsessionid=12345",location);
response.sendRedirect(tests[i][0]);
String location = out.getOut().toString();
int l=location.indexOf("Location: ");
int e=location.indexOf('\n',l);
location=location.substring(l+10,e).trim();
assertEquals(tests[i][0],tests[i][1],location);
}
}
@Test

View File

@ -91,7 +91,7 @@ public class StressTest
_server.setThreadPool(_threads);
_connector = new SelectChannelConnector();
_connector.setAcceptors(Math.max(1, Runtime.getRuntime().availableProcessors() / 2));
_connector.setAcceptors(1);
_connector.setAcceptQueueSize(5000);
_connector.setMaxIdleTime(30000);
_server.addConnector(_connector);
@ -123,7 +123,7 @@ public class StressTest
// TODO needs to be further investigated
assumeTrue(!OS.IS_OSX || Stress.isEnabled());
doThreads(10,100,false);
doThreads(10,10,false);
if (Stress.isEnabled())
{
Thread.sleep(1000);
@ -139,7 +139,7 @@ public class StressTest
// TODO needs to be further investigated
assumeTrue(!OS.IS_OSX || Stress.isEnabled());
doThreads(20,100,true);
doThreads(20,10,true);
if (Stress.isEnabled())
{
Thread.sleep(1000);

View File

@ -0,0 +1,76 @@
package org.eclipse.jetty.server.handler;
//========================================================================
//Copyright (c) 1999-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.
//========================================================================
import java.net.URI;
import org.eclipse.jetty.server.Connector;
import org.eclipse.jetty.server.Server;
import org.eclipse.jetty.server.bio.SocketConnector;
import org.eclipse.jetty.toolchain.test.MavenTestingUtils;
import org.eclipse.jetty.toolchain.test.SimpleRequest;
import org.junit.AfterClass;
import org.junit.BeforeClass;
import org.junit.Test;
import junit.framework.Assert;
import junit.framework.TestCase;
/**
* Resource Handler test
*
* TODO: increase the testing going on here
*/
public class ResourceHandlerTest extends TestCase
{
private static Server _server;
private static Connector _connector;
private static ContextHandler _contextHandler;
private static ResourceHandler _resourceHandler;
@BeforeClass
public void setUp() throws Exception
{
_server = new Server();
_connector = new SocketConnector();
_server.setConnectors(new Connector[] { _connector });
_resourceHandler = new ResourceHandler();
_contextHandler = new ContextHandler("/resource");
_contextHandler.setHandler(_resourceHandler);
_server.setHandler(_contextHandler);
_server.start();
}
/* ------------------------------------------------------------ */
@AfterClass
public void tearDown() throws Exception
{
_server.stop();
}
@Test
public void testSimpleResourceHandler() throws Exception
{
_resourceHandler.setResourceBase(MavenTestingUtils.getTestResourceDir("simple").getAbsolutePath());
SimpleRequest sr = new SimpleRequest(new URI("http://localhost:" + _connector.getLocalPort()));
Assert.assertEquals("simple text", sr.getString("/resource/simple.txt"));
Assert.assertNotNull("missing jetty.css" , sr.getString("/resource/jetty-dir.css"));
}
}

View File

@ -0,0 +1,80 @@
package org.eclipse.jetty.server.handler;
//========================================================================
//Copyright (c) 2009-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.
//========================================================================
import static org.junit.Assert.assertEquals;
import static org.mockito.Mockito.when;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.eclipse.jetty.server.Server;
import org.junit.Before;
import org.junit.Test;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
public class ShutdownHandlerTest
{
@Mock private HttpServletRequest request;
@Mock private HttpServletResponse response;
private Server server = new Server(0);
private String shutdownToken = "asdlnsldgnklns";
// class under test
private ShutdownHandler shutdownHandler;
@Before
public void startServer() throws Exception
{
MockitoAnnotations.initMocks(this);
server.start();
shutdownHandler = new ShutdownHandler(server,shutdownToken);
}
@Test
public void shutdownServerWithCorrectTokenAndIPTest() throws Exception
{
setDefaultExpectations();
shutdownHandler.handle("/shutdown",null,request,response);
assertEquals("Server should be stopped","STOPPED",server.getState());
}
@Test
public void wrongTokenTest() throws Exception
{
setDefaultExpectations();
when(request.getParameter("token")).thenReturn("anothertoken");
shutdownHandler.handle("/shutdown",null,request,response);
assertEquals("Server should be running","STARTED",server.getState());
}
@Test
public void shutdownRequestNotFromLocalhostTest() throws Exception
{
setDefaultExpectations();
when(request.getRemoteAddr()).thenReturn("192.168.3.3");
shutdownHandler.handle("/shutdown",null,request,response);
assertEquals("Server should be running","STARTED",server.getState());
}
private void setDefaultExpectations()
{
when(request.getMethod()).thenReturn("POST");
when(request.getParameter("token")).thenReturn(shutdownToken);
when(request.getRemoteAddr()).thenReturn("127.0.0.1");
}
}

View File

@ -0,0 +1,181 @@
//========================================================================
//Copyright 2004-2008 Mort Bay Consulting Pty. Ltd.
//------------------------------------------------------------------------
//Licensed under the Apache License, Version 2.0 (the "License");
//you may not use this file except in compliance with the License.
//You may obtain a copy of the License at
//http://www.apache.org/licenses/LICENSE-2.0
//Unless required by applicable law or agreed to in writing, software
//distributed under the License is distributed on an "AS IS" BASIS,
//WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
//See the License for the specific language governing permissions and
//limitations under the License.
//========================================================================
// JettyTest.java --
//
// Junit test that shows the Jetty SSL bug.
//
package org.eclipse.jetty.server.ssl;
import java.io.BufferedReader;
import java.io.File;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.net.Socket;
import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;
import javax.net.ssl.SSLContext;
import javax.net.ssl.TrustManager;
import javax.net.ssl.X509TrustManager;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import junit.framework.TestCase;
import org.eclipse.jetty.io.nio.SslSelectChannelEndPoint;
import org.eclipse.jetty.server.Connector;
import org.eclipse.jetty.server.Request;
import org.eclipse.jetty.server.Server;
import org.eclipse.jetty.server.handler.AbstractHandler;
/**
* HttpServer Tester.
*/
public class SSLCloseTest extends TestCase
{
private static SslSelectChannelEndPoint __endp;
private static class CredulousTM implements TrustManager, X509TrustManager
{
public X509Certificate[] getAcceptedIssuers()
{
return null;
}
public void checkClientTrusted(X509Certificate[] arg0, String arg1) throws CertificateException
{
return;
}
public void checkServerTrusted(X509Certificate[] arg0, String arg1) throws CertificateException
{
return;
}
}
private static final TrustManager[] s_dummyTrustManagers=new TrustManager[] { new CredulousTM() };
// ~ Methods
// ----------------------------------------------------------------
/**
* Feed the server the entire request at once.
*
* @throws Exception
*/
public void testClose() throws Exception
{
Server server=new Server();
SslSelectChannelConnector connector=new SslSelectChannelConnector();
String keystore = System.getProperty("user.dir")+File.separator+"src"+File.separator+"test"+File.separator+"resources"+File.separator+"keystore";
connector.setPort(0);
connector.setKeystore(keystore);
connector.setPassword("storepwd");
connector.setKeyPassword("keypwd");
server.setConnectors(new Connector[]
{ connector });
server.setHandler(new WriteHandler());
server.start();
SSLContext ctx=SSLContext.getInstance("SSLv3");
ctx.init(null,s_dummyTrustManagers,new java.security.SecureRandom());
int port=connector.getLocalPort();
// System.err.println("write:"+i);
Socket socket=ctx.getSocketFactory().createSocket("localhost",port);
OutputStream os=socket.getOutputStream();
os.write("GET /test HTTP/1.1\r\nHost:test\r\nConnection:close\r\n\r\n".getBytes());
os.flush();
BufferedReader in =new BufferedReader(new InputStreamReader(socket.getInputStream()));
String line;
while ((line=in.readLine())!=null)
{
System.err.println(line);
if (line.trim().length()==0)
break;
}
Thread.sleep(2000);
System.err.println(__endp);
while ((line=in.readLine())!=null)
System.err.println(line);
}
private static class WriteHandler extends AbstractHandler
{
public void handle(String target, Request baseRequest, HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException
{
try
{
baseRequest.setHandled(true);
response.setStatus(200);
response.setHeader("test","value");
__endp=(SslSelectChannelEndPoint)baseRequest.getConnection().getEndPoint();
OutputStream out=response.getOutputStream();
String data = "Now is the time for all good men to come to the aid of the party.\n";
data+="How now brown cow.\n";
data+="The quick brown fox jumped over the lazy dog.\n";
// data=data+data+data+data+data+data+data+data+data+data+data+data+data;
// data=data+data+data+data+data+data+data+data+data+data+data+data+data;
data=data+data+data+data;
byte[] bytes=data.getBytes("UTF-8");
for (int i=0;i<2;i++)
{
System.err.println("Write "+i+" "+bytes.length);
out.write(bytes);
}
}
catch(RuntimeException e)
{
e.printStackTrace();
throw e;
}
catch(IOException e)
{
e.printStackTrace();
throw e;
}
catch(Error e)
{
e.printStackTrace();
throw e;
}
catch(Throwable e)
{
e.printStackTrace();
throw new ServletException(e);
}
}
}
}

View File

@ -133,7 +133,7 @@ public class SSLEngineTest
@Test
public void testBigResponse() throws Exception
{
SSLContext ctx=SSLContext.getInstance("SSLv3");
SSLContext ctx=SSLContext.getInstance("TLS");
ctx.init(null,s_dummyTrustManagers,new java.security.SecureRandom());
int port=connector.getLocalPort();
@ -367,4 +367,5 @@ public class SSLEngineTest
response.flushBuffer();
}
}
}

View File

@ -23,6 +23,7 @@ import javax.net.ssl.TrustManagerFactory;
import org.eclipse.jetty.http.ssl.SslContextFactory;
import org.eclipse.jetty.server.HttpServerTestBase;
import org.junit.BeforeClass;
import org.junit.Test;
/**
* HttpServer Tester.
@ -60,14 +61,14 @@ public class SslSelectChannelServerTest extends HttpServerTestBase
keystore.load(new FileInputStream(connector.getKeystore()), "storepwd".toCharArray());
TrustManagerFactory trustManagerFactory = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
trustManagerFactory.init(keystore);
__sslContext = SSLContext.getInstance("SSL");
__sslContext = SSLContext.getInstance("TLS");
__sslContext.init(null, trustManagerFactory.getTrustManagers(), null);
try
{
HttpsURLConnection.setDefaultHostnameVerifier(__hostnameverifier);
SSLContext sc = SSLContext.getInstance("SSL");
SSLContext sc = SSLContext.getInstance("TLS");
sc.init(null, __trustAllCerts, new java.security.SecureRandom());
HttpsURLConnection.setDefaultSSLSocketFactory(sc.getSocketFactory());
}
@ -79,5 +80,20 @@ public class SslSelectChannelServerTest extends HttpServerTestBase
}
@Test
@Override
public void testBlockingWhileWritingResponseContent() throws Exception
{
super.testBlockingWhileWritingResponseContent();
}
@Test
@Override
public void testBigBlocks() throws Exception
{
super.testBigBlocks();
}
}

View File

@ -23,6 +23,7 @@ import javax.net.ssl.TrustManagerFactory;
import org.eclipse.jetty.http.ssl.SslContextFactory;
import org.eclipse.jetty.server.ConnectorTimeoutTest;
import org.junit.BeforeClass;
import org.junit.Test;
public class SslSelectChannelTimeoutTest extends ConnectorTimeoutTest
{
@ -57,4 +58,12 @@ public class SslSelectChannelTimeoutTest extends ConnectorTimeoutTest
}
@Test
public void testNoProgress() throws Exception
{
testMaxIdleNoRequest();
super.testMaxIdleWithSlowRequest();
}
}

View File

@ -15,8 +15,10 @@ package org.eclipse.jetty.server.ssl;
import java.io.FileInputStream;
import java.net.Socket;
import java.security.KeyStore;
import java.util.Arrays;
import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLSocket;
import javax.net.ssl.TrustManagerFactory;
import org.eclipse.jetty.http.ssl.SslContextFactory;
@ -37,7 +39,9 @@ public class SslSocketServerTest extends HttpServerTestBase
@Override
protected Socket newSocket(String host, int port) throws Exception
{
return __sslContext.getSocketFactory().createSocket(host,port);
SSLSocket socket = (SSLSocket)__sslContext.getSocketFactory().createSocket(host,port);
socket.setEnabledProtocols(new String[] {"TLSv1"});
return socket;
}
@ -59,7 +63,7 @@ public class SslSocketServerTest extends HttpServerTestBase
keystore.load(new FileInputStream(connector.getKeystore()), "storepwd".toCharArray());
TrustManagerFactory trustManagerFactory = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
trustManagerFactory.init(keystore);
__sslContext = SSLContext.getInstance("SSL");
__sslContext = SSLContext.getInstance("TLSv1");
__sslContext.init(null, trustManagerFactory.getTrustManagers(), null);

View File

@ -18,6 +18,7 @@ import java.net.Socket;
import java.security.KeyStore;
import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLSocket;
import javax.net.ssl.TrustManagerFactory;
import org.eclipse.jetty.http.ssl.SslContextFactory;
@ -26,12 +27,14 @@ import org.junit.BeforeClass;
public class SslSocketTimeoutTest extends ConnectorTimeoutTest
{
static SSLContext _sslContext;
static SSLContext __sslContext;
@Override
protected Socket newSocket(String host, int port) throws Exception
{
return _sslContext.getSocketFactory().createSocket(host,port);
SSLSocket socket = (SSLSocket)__sslContext.getSocketFactory().createSocket(host,port);
socket.setEnabledProtocols(new String[] {"TLSv1"});
return socket;
}
@BeforeClass
@ -53,8 +56,8 @@ public class SslSocketTimeoutTest extends ConnectorTimeoutTest
keystore.load(new FileInputStream(connector.getKeystore()), "storepwd".toCharArray());
TrustManagerFactory trustManagerFactory = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
trustManagerFactory.init(keystore);
_sslContext = SSLContext.getInstance("SSL");
_sslContext.init(null, trustManagerFactory.getTrustManagers(), null);
__sslContext = SSLContext.getInstance("TLSv1");
__sslContext.init(null, trustManagerFactory.getTrustManagers(), null);
}

View File

@ -159,17 +159,6 @@ public class SslTruncationAttackTest
Assert.assertTrue("endpoint not closed", endPointClosed.get());
}
/**
* This test is currently failing because we are looping on SslSCEP.unwrap()
* to fill the buffer, so there is a case where we loop once, read some data
* loop again and read -1, but we can't close the connection yet as we have
* to notify the application (not sure that this is necessary... must assume
* the data is truncated, so it's not that safe to pass it to the application).
* This case needs to be revisited, and it also requires a review of the
* Connection:close case, especially on the client side.
* @throws Exception if the test fails
*/
@Ignore
@Test
public void testTruncationAttackBeforeReading() throws Exception
{
@ -234,8 +223,8 @@ public class SslTruncationAttackTest
// Sleep for a while to detect eventual spin looping
TimeUnit.SECONDS.sleep(1);
Assert.assertTrue("endpoint closed", endPointClosed.get());
Assert.assertEquals("handle() invocations", 1, handleCount.get());
Assert.assertTrue("endpoint not closed", endPointClosed.get());
}

View File

@ -0,0 +1 @@
simple text

View File

@ -482,7 +482,6 @@ public class ServletHandler extends ScopedHandler
res = ((ServletResponseHttpWrapper)res).getResponse();
// Do the filter/handling thang
baseRequest.setHandled(true);
if (chain!=null)
chain.doFilter(req, res);
else
@ -591,6 +590,10 @@ public class ServletHandler extends ScopedHandler
else
LOG.debug("Response already committed for handling ",e);
}
finally
{
baseRequest.setHandled(true);
}
}
/* ------------------------------------------------------------ */

View File

@ -14,27 +14,47 @@
package org.eclipse.jetty.servlet;
import java.io.IOException;
import java.io.PrintWriter;
import java.net.HttpRetryException;
import java.util.Arrays;
import java.util.Collections;
import java.util.EnumSet;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import javax.servlet.DispatcherType;
import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.GenericServlet;
import javax.servlet.RequestDispatcher;
import javax.servlet.Servlet;
import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.ServletOutputStream;
import javax.servlet.ServletRequest;
import javax.servlet.ServletRequestWrapper;
import javax.servlet.ServletResponse;
import javax.servlet.ServletResponseWrapper;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletRequestWrapper;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpServletResponseWrapper;
import junit.framework.Assert;
import org.eclipse.jetty.server.Dispatcher;
import org.eclipse.jetty.server.LocalConnector;
import org.eclipse.jetty.server.Server;
import org.eclipse.jetty.server.handler.ContextHandler;
import org.eclipse.jetty.server.handler.ContextHandlerCollection;
import org.eclipse.jetty.server.handler.ResourceHandler;
import org.eclipse.jetty.toolchain.test.MavenTestingUtils;
import org.junit.After;
import org.junit.Before;
import org.junit.Ignore;
import org.junit.Test;
import static org.junit.Assert.assertEquals;
@ -44,17 +64,27 @@ public class DispatcherTest
{
private Server _server;
private LocalConnector _connector;
private ServletContextHandler _context;
private ContextHandlerCollection _contextCollection;
private ServletContextHandler _contextHandler;
private ResourceHandler _resourceHandler;
@Before
public void init() throws Exception
{
_server = new Server();
_server.setSendServerVersion(false);
_connector = new LocalConnector();
_context = new ServletContextHandler();
_context.setContextPath("/context");
_server.setHandler(_context);
_contextCollection = new ContextHandlerCollection();
_contextHandler = new ServletContextHandler();
_contextHandler.setContextPath("/context");
_contextCollection.addHandler(_contextHandler);
_resourceHandler = new ResourceHandler();
_resourceHandler.setResourceBase(MavenTestingUtils.getTestResourceDir("dispatchResourceTest").getAbsolutePath());
ContextHandler resourceContextHandler = new ContextHandler("/resource");
resourceContextHandler.setHandler(_resourceHandler);
_contextCollection.addHandler(resourceContextHandler);
_server.setHandler(_contextCollection);
_server.addConnector( _connector );
_server.start();
@ -70,8 +100,8 @@ public class DispatcherTest
@Test
public void testForward() throws Exception
{
_context.addServlet(ForwardServlet.class, "/ForwardServlet/*");
_context.addServlet(AssertForwardServlet.class, "/AssertForwardServlet/*");
_contextHandler.addServlet(ForwardServlet.class, "/ForwardServlet/*");
_contextHandler.addServlet(AssertForwardServlet.class, "/AssertForwardServlet/*");
String expected=
"HTTP/1.1 200 OK\r\n"+
@ -87,8 +117,8 @@ public class DispatcherTest
@Test
public void testInclude() throws Exception
{
_context.addServlet(IncludeServlet.class, "/IncludeServlet/*");
_context.addServlet(AssertIncludeServlet.class, "/AssertIncludeServlet/*");
_contextHandler.addServlet(IncludeServlet.class, "/IncludeServlet/*");
_contextHandler.addServlet(AssertIncludeServlet.class, "/AssertIncludeServlet/*");
String expected=
"HTTP/1.1 200 OK\r\n"+
@ -103,9 +133,9 @@ public class DispatcherTest
@Test
public void testForwardThenInclude() throws Exception
{
_context.addServlet(ForwardServlet.class, "/ForwardServlet/*");
_context.addServlet(IncludeServlet.class, "/IncludeServlet/*");
_context.addServlet(AssertForwardIncludeServlet.class, "/AssertForwardIncludeServlet/*");
_contextHandler.addServlet(ForwardServlet.class, "/ForwardServlet/*");
_contextHandler.addServlet(IncludeServlet.class, "/IncludeServlet/*");
_contextHandler.addServlet(AssertForwardIncludeServlet.class, "/AssertForwardIncludeServlet/*");
String expected=
"HTTP/1.1 200 OK\r\n"+
@ -120,9 +150,9 @@ public class DispatcherTest
@Test
public void testIncludeThenForward() throws Exception
{
_context.addServlet(IncludeServlet.class, "/IncludeServlet/*");
_context.addServlet(ForwardServlet.class, "/ForwardServlet/*");
_context.addServlet(AssertIncludeForwardServlet.class, "/AssertIncludeForwardServlet/*");
_contextHandler.addServlet(IncludeServlet.class, "/IncludeServlet/*");
_contextHandler.addServlet(ForwardServlet.class, "/ForwardServlet/*");
_contextHandler.addServlet(AssertIncludeForwardServlet.class, "/AssertIncludeForwardServlet/*");
String expected=
@ -140,8 +170,8 @@ public class DispatcherTest
@Test
public void testServletForward() throws Exception
{
_context.addServlet(DispatchServletServlet.class, "/dispatch/*");
_context.addServlet(RogerThatServlet.class, "/roger/*");
_contextHandler.addServlet(DispatchServletServlet.class, "/dispatch/*");
_contextHandler.addServlet(RogerThatServlet.class, "/roger/*");
String expected=
"HTTP/1.1 200 OK\r\n"+
@ -157,8 +187,8 @@ public class DispatcherTest
@Test
public void testServletInclude() throws Exception
{
_context.addServlet(DispatchServletServlet.class, "/dispatch/*");
_context.addServlet(RogerThatServlet.class, "/roger/*");
_contextHandler.addServlet(DispatchServletServlet.class, "/dispatch/*");
_contextHandler.addServlet(RogerThatServlet.class, "/roger/*");
String expected=
"HTTP/1.1 200 OK\r\n"+
@ -171,6 +201,80 @@ public class DispatcherTest
assertEquals(expected, responses);
}
@Test
public void testWorkingResourceHandler() throws Exception
{
String responses = _connector.getResponses("GET /resource/content.txt HTTP/1.0\n" + "Host: localhost\n\n");
assertTrue(responses.contains("content goes here")); // from inside the context.txt file
}
@Test
public void testIncludeToResourceHandler() throws Exception
{
_contextHandler.addServlet(DispatchToResourceServlet.class, "/resourceServlet/*");
String responses = _connector.getResponses("GET /context/resourceServlet/content.txt?do=include HTTP/1.0\n" + "Host: localhost\n\n");
// from inside the context.txt file
Assert.assertNotNull(responses);
assertTrue(responses.contains("content goes here"));
}
@Test
public void testForwardToResourceHandler() throws Exception
{
_contextHandler.addServlet(DispatchToResourceServlet.class, "/resourceServlet/*");
String responses = _connector.getResponses("GET /context/resourceServlet/content.txt?do=forward HTTP/1.0\n" + "Host: localhost\n\n");
// from inside the context.txt file
assertTrue(responses.contains("content goes here"));
}
@Test
public void testWrappedIncludeToResourceHandler() throws Exception
{
_contextHandler.addServlet(DispatchToResourceServlet.class, "/resourceServlet/*");
String responses = _connector.getResponses("GET /context/resourceServlet/content.txt?do=include&wrapped=true HTTP/1.0\n" + "Host: localhost\n\n");
// from inside the context.txt file
assertTrue(responses.contains("content goes here"));
}
@Test
public void testWrappedForwardToResourceHandler() throws Exception
{
_contextHandler.addServlet(DispatchToResourceServlet.class, "/resourceServlet/*");
String responses = _connector.getResponses("GET /context/resourceServlet/content.txt?do=forward&wrapped=true HTTP/1.0\n" + "Host: localhost\n\n");
// from inside the context.txt file
assertTrue(responses.contains("content goes here"));
}
@Test
public void testForwardFilterToRogerServlet() throws Exception
{
_contextHandler.addServlet(RogerThatServlet.class, "/*");
_contextHandler.addServlet(ReserveEchoServlet.class,"/recho/*");
_contextHandler.addServlet(EchoServlet.class, "/echo/*");
_contextHandler.addFilter(ForwardFilter.class, "/*", EnumSet.of(DispatcherType.REQUEST));
String rogerResponse = _connector.getResponses("GET /context/ HTTP/1.0\n" + "Host: localhost\n\n");
String echoResponse = _connector.getResponses("GET /context/foo?echo=echoText HTTP/1.0\n" + "Host: localhost\n\n");
String rechoResponse = _connector.getResponses("GET /context/?echo=echoText HTTP/1.0\n" + "Host: localhost\n\n");
assertTrue(rogerResponse.contains("Roger That!"));
assertTrue(echoResponse.contains("echoText"));
assertTrue(rechoResponse.contains("txeTohce"));
}
public static class ForwardServlet extends HttpServlet implements Servlet
{
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException
@ -187,6 +291,59 @@ public class DispatcherTest
}
}
/*
* Forward filter works with roger, echo and reverse echo servlets to test various
* forwarding bits using filters.
*
* when there is an echo parameter and the path info is / it forwards to the reverse echo
* anything else in the pathInfo and it sends straight to the echo servlet...otherwise its
* all roger servlet
*/
public static class ForwardFilter implements Filter
{
ServletContext servletContext;
public void init(FilterConfig filterConfig) throws ServletException
{
servletContext = filterConfig.getServletContext().getContext("/context");
}
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException
{
if ( servletContext == null || !(request instanceof HttpServletRequest) || !(response instanceof HttpServletResponse))
{
chain.doFilter(request,response);
return;
}
HttpServletRequest req = (HttpServletRequest)request;
HttpServletResponse resp = (HttpServletResponse)response;
if ( req.getParameter("echo") != null && "/".equals(req.getPathInfo()))
{
RequestDispatcher dispatcher = servletContext.getRequestDispatcher("/recho");
dispatcher.forward(request,response);
}
else if ( req.getParameter("echo") != null )
{
RequestDispatcher dispatcher = servletContext.getRequestDispatcher("/echo");
dispatcher.forward(request,response);
}
else
{
chain.doFilter(request,response);
return;
}
}
public void destroy()
{
}
}
public static class DispatchServletServlet extends HttpServlet implements Servlet
{
@Override
@ -230,6 +387,84 @@ public class DispatcherTest
}
}
public static class EchoServlet extends GenericServlet
{
@Override
public void service(ServletRequest req, ServletResponse res) throws ServletException, IOException
{
String echoText = req.getParameter("echo");
if ( echoText == null )
{
throw new ServletException("echo is a required parameter");
}
else
{
res.getWriter().print(echoText);
}
}
}
public static class ReserveEchoServlet extends GenericServlet
{
@Override
public void service(ServletRequest req, ServletResponse res) throws ServletException, IOException
{
String echoText = req.getParameter("echo");
if ( echoText == null )
{
throw new ServletException("echo is a required parameter");
}
else
{
res.getWriter().print(new StringBuffer(echoText).reverse().toString());
}
}
}
public static class DispatchToResourceServlet extends HttpServlet implements Servlet
{
@Override
public void service(HttpServletRequest req, HttpServletResponse res) throws ServletException, IOException
{
ServletContext targetContext = getServletConfig().getServletContext().getContext("/resource");
RequestDispatcher dispatcher = targetContext.getRequestDispatcher(req.getPathInfo());
if ( "true".equals(req.getParameter("wrapped")))
{
if (req.getParameter("do").equals("forward"))
{
dispatcher.forward(new HttpServletRequestWrapper(req),new HttpServletResponseWrapper(res));
}
else if (req.getParameter("do").equals("include"))
{
dispatcher.include(new HttpServletRequestWrapper(req),new HttpServletResponseWrapper(res));
}
else
{
throw new ServletException("type of forward or include is required");
}
}
else
{
if (req.getParameter("do").equals("forward"))
{
dispatcher.forward(req,res);
}
else if (req.getParameter("do").equals("include"))
{
dispatcher.include(req,res);
}
else
{
throw new ServletException("type of forward or include is required");
}
}
}
}
public static class AssertForwardServlet extends HttpServlet implements Servlet
{
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException

View File

@ -0,0 +1 @@
content goes here

View File

@ -0,0 +1 @@
text

Some files were not shown because too many files have changed in this diff Show More