Skip to main content
summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJesse McConnell2012-07-13 14:06:26 +0000
committerJesse McConnell2012-07-13 14:06:26 +0000
commiteedd4bfeefcdfad2f311820346ffca81fca30450 (patch)
tree926f07cf53054712bb5e994e901303433c98454c
parentf7f0a5b22b1f22a495eb01e99fa84a5508dad3e2 (diff)
parent5222459aa77b7fb3701859d3a35469c1cc205898 (diff)
downloadorg.eclipse.jetty.project-eedd4bfeefcdfad2f311820346ffca81fca30450.tar.gz
org.eclipse.jetty.project-eedd4bfeefcdfad2f311820346ffca81fca30450.tar.xz
org.eclipse.jetty.project-eedd4bfeefcdfad2f311820346ffca81fca30450.zip
Merge branch 'jetty-8' into release-8
-rw-r--r--README.txt13
-rw-r--r--example-jetty-embedded/src/main/java/org/eclipse/jetty/embedded/FileServerXml.java12
-rw-r--r--jetty-annotations/src/main/java/org/eclipse/jetty/annotations/MultiPartConfigAnnotationHandler.java2
-rw-r--r--jetty-annotations/src/main/java/org/eclipse/jetty/annotations/RunAsAnnotationHandler.java2
-rw-r--r--jetty-annotations/src/main/java/org/eclipse/jetty/annotations/ServletContainerInitializerListener.java4
-rw-r--r--jetty-annotations/src/main/java/org/eclipse/jetty/annotations/ServletSecurityAnnotationHandler.java2
-rw-r--r--jetty-annotations/src/main/java/org/eclipse/jetty/annotations/WebServletAnnotation.java68
-rw-r--r--jetty-annotations/src/test/java/org/eclipse/jetty/annotations/Multi.java12
-rw-r--r--jetty-annotations/src/test/java/org/eclipse/jetty/annotations/resources/TestResourceAnnotations.java12
-rw-r--r--jetty-client/src/test/java/org/eclipse/jetty/client/CachedHeadersIsolationTest.java12
-rw-r--r--jetty-client/src/test/java/org/eclipse/jetty/client/Curl.java12
-rw-r--r--jetty-client/src/test/java/org/eclipse/jetty/client/ExpirationWithLimitedConnectionsTest.java191
-rw-r--r--jetty-client/src/test/java/org/eclipse/jetty/client/HttpAsserts.java12
-rw-r--r--jetty-client/src/test/java/org/eclipse/jetty/client/HttpDestinationQueueTest.java12
-rw-r--r--jetty-client/src/test/java/org/eclipse/jetty/client/ProxyFakeTunnelTest.java12
-rw-r--r--jetty-client/src/test/java/org/eclipse/jetty/client/ProxyTunnellingTest.java19
-rw-r--r--jetty-client/src/test/java/org/eclipse/jetty/client/Siege.java12
-rw-r--r--jetty-client/src/test/java/org/eclipse/jetty/client/SluggishServerTest.java12
-rw-r--r--jetty-client/src/test/java/org/eclipse/jetty/client/SslBytesClientTest.java12
-rw-r--r--jetty-client/src/test/java/org/eclipse/jetty/client/SslBytesServerTest.java12
-rw-r--r--jetty-client/src/test/java/org/eclipse/jetty/client/SslBytesTest.java12
-rw-r--r--jetty-client/src/test/java/org/eclipse/jetty/client/SslSelectChannelValidationTest.java12
-rw-r--r--jetty-client/src/test/java/org/eclipse/jetty/client/SslSocketValidationTest.java12
-rw-r--r--jetty-client/src/test/java/org/eclipse/jetty/client/SslValidationTestBase.java12
-rw-r--r--jetty-client/src/test/java/org/eclipse/jetty/client/TimeoutTest.java12
-rw-r--r--jetty-client/src/test/java/org/eclipse/jetty/client/UnexpectedDataTest.java25
-rw-r--r--jetty-client/src/test/java/org/eclipse/jetty/client/helperClasses/AsyncSslServerAndClientCreator.java12
-rw-r--r--jetty-client/src/test/java/org/eclipse/jetty/client/helperClasses/ExternalKeyStoreAsyncSslServerAndClientCreator.java12
-rw-r--r--jetty-client/src/test/java/org/eclipse/jetty/client/helperClasses/GenericServerHandler.java12
-rw-r--r--jetty-client/src/test/java/org/eclipse/jetty/client/helperClasses/HttpServerAndClientCreator.java12
-rw-r--r--jetty-client/src/test/java/org/eclipse/jetty/client/helperClasses/ServerAndClientCreator.java12
-rw-r--r--jetty-client/src/test/java/org/eclipse/jetty/client/helperClasses/SslServerAndClientCreator.java12
-rw-r--r--jetty-continuation/src/main/java/org/eclipse/jetty/continuation/ContinuationFilter.java12
-rw-r--r--jetty-continuation/src/main/java/org/eclipse/jetty/continuation/ContinuationListener.java13
-rw-r--r--jetty-continuation/src/main/java/org/eclipse/jetty/continuation/Jetty6Continuation.java12
-rw-r--r--jetty-continuation/src/main/java/org/eclipse/jetty/continuation/Servlet3Continuation.java12
-rw-r--r--jetty-deploy/src/main/java/org/eclipse/jetty/deploy/jmx/DeploymentManagerMBean.java12
-rw-r--r--jetty-deploy/src/main/java/org/eclipse/jetty/deploy/providers/ContextProvider.java12
-rw-r--r--jetty-deploy/src/main/java/org/eclipse/jetty/deploy/providers/WebAppProvider.java12
-rw-r--r--jetty-deploy/src/test/java/org/eclipse/jetty/deploy/DeploymentManagerTest.java12
-rw-r--r--jetty-deploy/src/test/java/org/eclipse/jetty/deploy/graph/GraphTest.java12
-rw-r--r--jetty-deploy/src/test/java/org/eclipse/jetty/deploy/providers/WebAppProviderTest.java12
-rw-r--r--jetty-http-spi/src/test/java/org/eclipse/jetty/http/spi/TestSPIServer.java12
-rw-r--r--jetty-http/src/main/java/org/eclipse/jetty/http/gzip/AbstractCompressedStream.java3
-rw-r--r--jetty-http/src/main/java/org/eclipse/jetty/http/ssl/SslContextFactory.java12
-rw-r--r--jetty-http/src/test/java/org/eclipse/jetty/http/MimeTypesTest.java12
-rw-r--r--jetty-io/src/main/java/org/eclipse/jetty/io/AbstractBuffers.java12
-rw-r--r--jetty-io/src/main/java/org/eclipse/jetty/io/AbstractConnection.java12
-rw-r--r--jetty-io/src/main/java/org/eclipse/jetty/io/BuffersFactory.java12
-rw-r--r--jetty-io/src/main/java/org/eclipse/jetty/io/ConnectedEndPoint.java12
-rw-r--r--jetty-io/src/main/java/org/eclipse/jetty/io/PooledBuffers.java12
-rw-r--r--jetty-io/src/main/java/org/eclipse/jetty/io/nio/SelectChannelEndPoint.java14
-rw-r--r--jetty-io/src/test/java/org/eclipse/jetty/io/EndPointTest.java12
-rw-r--r--jetty-io/src/test/java/org/eclipse/jetty/io/bio/SocketEndPointTest.java12
-rw-r--r--jetty-io/src/test/java/org/eclipse/jetty/io/nio/ChannelEndPointTest.java12
-rw-r--r--jetty-io/src/test/java/org/eclipse/jetty/io/nio/SelectChannelEndPointSslTest.java12
-rw-r--r--jetty-io/src/test/java/org/eclipse/jetty/io/nio/SelectChannelEndPointTest.java12
-rw-r--r--jetty-jndi/src/main/java/org/eclipse/jetty/jndi/DataSourceCloser.java12
-rw-r--r--jetty-monitor/src/main/config/etc/jetty-monitor.xml6
-rw-r--r--jetty-nosql/src/main/java/org/eclipse/jetty/nosql/mongodb/jmx/MongoSessionManagerMBean.java12
-rw-r--r--jetty-npn/pom.xml2
-rw-r--r--jetty-npn/src/main/java/org/eclipse/jetty/npn/NextProtoNego.java57
-rw-r--r--jetty-plus/src/main/java/org/eclipse/jetty/plus/jaas/spi/LdapLoginModule.java1
-rw-r--r--jetty-policy/src/main/java/org/eclipse/jetty/policy/PolicyMonitor.java12
-rw-r--r--jetty-policy/src/test/java/org/eclipse/jetty/policy/PolicyMonitorTest.java12
-rw-r--r--jetty-security/src/main/java/org/eclipse/jetty/security/DefaultAuthenticatorFactory.java2
-rw-r--r--jetty-security/src/main/java/org/eclipse/jetty/security/PropertyUserStore.java12
-rw-r--r--jetty-security/src/main/java/org/eclipse/jetty/security/SpnegoUserPrincipal.java12
-rw-r--r--jetty-security/src/main/java/org/eclipse/jetty/security/authentication/SpnegoAuthenticator.java18
-rw-r--r--jetty-security/src/test/java/org/eclipse/jetty/security/PropertyUserStoreTest.java12
-rw-r--r--jetty-server/src/main/java/org/eclipse/jetty/server/CookieCutter.java1
-rw-r--r--jetty-server/src/main/java/org/eclipse/jetty/server/Server.java16
-rw-r--r--jetty-server/src/main/java/org/eclipse/jetty/server/ServletResponseHttpWrapper.java12
-rw-r--r--jetty-server/src/main/java/org/eclipse/jetty/server/handler/ConnectHandler.java51
-rw-r--r--jetty-server/src/main/java/org/eclipse/jetty/server/handler/ContextHandler.java48
-rw-r--r--jetty-server/src/main/java/org/eclipse/jetty/server/handler/DebugHandler.java19
-rw-r--r--jetty-server/src/main/java/org/eclipse/jetty/server/handler/ProxyHandler.java12
-rw-r--r--jetty-server/src/main/java/org/eclipse/jetty/server/handler/ScopedHandler.java12
-rw-r--r--jetty-server/src/main/java/org/eclipse/jetty/server/session/AbstractSession.java13
-rw-r--r--jetty-server/src/main/java/org/eclipse/jetty/server/session/HashedSession.java12
-rw-r--r--jetty-server/src/main/java/org/eclipse/jetty/server/ssl/SslCertificates.java12
-rw-r--r--jetty-server/src/main/java/org/eclipse/jetty/server/ssl/SslConnector.java12
-rw-r--r--jetty-server/src/test/java/org/eclipse/jetty/server/HttpServerTestBase.java7
-rw-r--r--jetty-server/src/test/java/org/eclipse/jetty/server/HttpServerTestFixture.java12
-rw-r--r--jetty-server/src/test/java/org/eclipse/jetty/server/HttpWriterTest.java12
-rw-r--r--jetty-server/src/test/java/org/eclipse/jetty/server/SelectChannelAsyncContextTest.java12
-rw-r--r--jetty-server/src/test/java/org/eclipse/jetty/server/SlowClientWithPipelinedRequestTest.java12
-rw-r--r--jetty-server/src/test/java/org/eclipse/jetty/server/SuspendHandler.java12
-rw-r--r--jetty-server/src/test/java/org/eclipse/jetty/server/handler/AbstractConnectHandlerTest.java12
-rw-r--r--jetty-server/src/test/java/org/eclipse/jetty/server/handler/ConnectHandlerSSLTest.java12
-rw-r--r--jetty-server/src/test/java/org/eclipse/jetty/server/handler/ConnectHandlerTest.java78
-rw-r--r--jetty-server/src/test/java/org/eclipse/jetty/server/handler/ContextHandlerTest.java29
-rw-r--r--jetty-server/src/test/java/org/eclipse/jetty/server/handler/ScopedHandlerTest.java12
-rw-r--r--jetty-server/src/test/java/org/eclipse/jetty/server/session/SessionHandlerTest.java12
-rw-r--r--jetty-server/src/test/java/org/eclipse/jetty/server/ssl/SSLCloseTest.java19
-rw-r--r--jetty-server/src/test/java/org/eclipse/jetty/server/ssl/SSLSelectChannelConnectorLoadTest.java12
-rw-r--r--jetty-server/src/test/java/org/eclipse/jetty/server/ssl/SslRenegotiateTest.java12
-rw-r--r--jetty-servlet/src/main/java/org/eclipse/jetty/servlet/DefaultServlet.java3
-rw-r--r--jetty-servlet/src/main/java/org/eclipse/jetty/servlet/Holder.java2
-rw-r--r--jetty-servlet/src/main/java/org/eclipse/jetty/servlet/ServletContextHandler.java148
-rw-r--r--jetty-servlet/src/main/java/org/eclipse/jetty/servlet/ServletHandler.java44
-rw-r--r--jetty-servlet/src/main/java/org/eclipse/jetty/servlet/ServletHolder.java90
-rw-r--r--jetty-servlet/src/main/java/org/eclipse/jetty/servlet/ServletMapping.java21
-rw-r--r--jetty-servlet/src/test/java/org/eclipse/jetty/servlet/AsyncContextDispatchWithQueryStrings.java12
-rw-r--r--jetty-servlet/src/test/java/org/eclipse/jetty/servlet/AsyncContextTest.java12
-rw-r--r--jetty-servlet/src/test/java/org/eclipse/jetty/servlet/DefaultServletTest.java12
-rw-r--r--jetty-servlet/src/test/java/org/eclipse/jetty/servlet/DispatcherTest.java38
-rw-r--r--jetty-servlet/src/test/java/org/eclipse/jetty/servlet/ServletContextHandlerTest.java12
-rw-r--r--jetty-servlets/src/main/java/org/eclipse/jetty/servlets/BalancerServlet.java417
-rw-r--r--jetty-servlets/src/main/java/org/eclipse/jetty/servlets/CrossOriginFilter.java37
-rw-r--r--jetty-servlets/src/main/java/org/eclipse/jetty/servlets/GzipFilter.java4
-rw-r--r--jetty-servlets/src/main/java/org/eclipse/jetty/servlets/ProxyServlet.java29
-rw-r--r--jetty-servlets/src/test/java/org/eclipse/jetty/servlets/AbstractBalancerServletTest.java157
-rw-r--r--jetty-servlets/src/test/java/org/eclipse/jetty/servlets/AbstractDoSFilterTest.java12
-rw-r--r--jetty-servlets/src/test/java/org/eclipse/jetty/servlets/BalancerServletTest.java129
-rw-r--r--jetty-servlets/src/test/java/org/eclipse/jetty/servlets/CrossOriginFilterTest.java58
-rw-r--r--jetty-servlets/src/test/java/org/eclipse/jetty/servlets/DoSFilterTest.java23
-rw-r--r--jetty-servlets/src/test/java/org/eclipse/jetty/servlets/GzipFilterContentLengthTest.java12
-rw-r--r--jetty-servlets/src/test/java/org/eclipse/jetty/servlets/GzipFilterDefaultNoRecompressTest.java12
-rw-r--r--jetty-servlets/src/test/java/org/eclipse/jetty/servlets/GzipFilterDefaultTest.java12
-rw-r--r--jetty-servlets/src/test/java/org/eclipse/jetty/servlets/GzipWithPipeliningTest.java12
-rw-r--r--jetty-servlets/src/test/java/org/eclipse/jetty/servlets/PipelineHelper.java12
-rw-r--r--jetty-servlets/src/test/java/org/eclipse/jetty/servlets/ProxyServletTest.java12
-rw-r--r--jetty-servlets/src/test/java/org/eclipse/jetty/servlets/gzip/GzipTester.java12
-rw-r--r--jetty-servlets/src/test/java/org/eclipse/jetty/servlets/gzip/Hex.java12
-rw-r--r--jetty-servlets/src/test/java/org/eclipse/jetty/servlets/gzip/NoOpOutputStream.java12
-rw-r--r--jetty-servlets/src/test/java/org/eclipse/jetty/servlets/gzip/TestDirContentServlet.java12
-rw-r--r--jetty-servlets/src/test/java/org/eclipse/jetty/servlets/gzip/TestMinGzipSizeServlet.java12
-rw-r--r--jetty-servlets/src/test/java/org/eclipse/jetty/servlets/gzip/TestServletLengthStreamTypeWrite.java12
-rw-r--r--jetty-servlets/src/test/java/org/eclipse/jetty/servlets/gzip/TestServletLengthTypeStreamWrite.java12
-rw-r--r--jetty-servlets/src/test/java/org/eclipse/jetty/servlets/gzip/TestServletStreamLengthTypeWrite.java12
-rw-r--r--jetty-servlets/src/test/java/org/eclipse/jetty/servlets/gzip/TestServletStreamTypeLengthWrite.java12
-rw-r--r--jetty-servlets/src/test/java/org/eclipse/jetty/servlets/gzip/TestServletTypeLengthStreamWrite.java12
-rw-r--r--jetty-servlets/src/test/java/org/eclipse/jetty/servlets/gzip/TestServletTypeStreamLengthWrite.java12
-rw-r--r--jetty-servlets/src/test/java/org/eclipse/jetty/servlets/gzip/TestStaticMimeTypeServlet.java12
-rw-r--r--jetty-spdy/pom.xml2
-rw-r--r--jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/ByteBufferPool.java27
-rw-r--r--jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/CompressionDictionary.java27
-rw-r--r--jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/CompressionFactory.java27
-rw-r--r--jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/Controller.java27
-rw-r--r--jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/FlowControlStrategy.java86
-rw-r--r--jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/ISession.java27
-rw-r--r--jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/IStream.java52
-rw-r--r--jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/IdleListener.java28
-rw-r--r--jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/Promise.java33
-rw-r--r--jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/PushSynInfo.java12
-rw-r--r--jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/SPDYv3FlowControlStrategy.java84
-rw-r--r--jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/SessionException.java28
-rw-r--r--jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/StandardByteBufferPool.java27
-rw-r--r--jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/StandardCompressionFactory.java27
-rw-r--r--jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/StandardSession.java382
-rw-r--r--jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/StandardStream.java187
-rw-r--r--jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/StreamException.java27
-rw-r--r--jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/api/ByteBufferDataInfo.java33
-rw-r--r--jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/api/BytesDataInfo.java54
-rw-r--r--jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/api/DataInfo.java27
-rw-r--r--jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/api/GoAwayInfo.java27
-rw-r--r--jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/api/Handler.java36
-rw-r--r--jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/api/Headers.java48
-rw-r--r--jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/api/HeadersInfo.java27
-rw-r--r--jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/api/PingInfo.java27
-rw-r--r--jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/api/ReplyInfo.java27
-rw-r--r--jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/api/RstInfo.java27
-rw-r--r--jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/api/SPDY.java27
-rw-r--r--jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/api/SPDYException.java27
-rw-r--r--jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/api/Session.java63
-rw-r--r--jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/api/SessionFrameListener.java27
-rw-r--r--jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/api/SessionStatus.java27
-rw-r--r--jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/api/Settings.java27
-rw-r--r--jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/api/SettingsInfo.java27
-rw-r--r--jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/api/Stream.java27
-rw-r--r--jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/api/StreamFrameListener.java27
-rw-r--r--jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/api/StreamStatus.java27
-rw-r--r--jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/api/StringDataInfo.java34
-rw-r--r--jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/api/SynInfo.java27
-rw-r--r--jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/api/server/ServerSessionFrameListener.java27
-rw-r--r--jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/frames/ControlFrame.java27
-rw-r--r--jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/frames/ControlFrameType.java30
-rw-r--r--jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/frames/CredentialFrame.java46
-rw-r--r--jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/frames/DataFrame.java27
-rw-r--r--jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/frames/GoAwayFrame.java27
-rw-r--r--jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/frames/HeadersFrame.java27
-rw-r--r--jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/frames/NoOpFrame.java27
-rw-r--r--jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/frames/PingFrame.java27
-rw-r--r--jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/frames/RstStreamFrame.java27
-rw-r--r--jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/frames/SettingsFrame.java27
-rw-r--r--jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/frames/SynReplyFrame.java27
-rw-r--r--jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/frames/SynStreamFrame.java36
-rw-r--r--jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/frames/WindowUpdateFrame.java27
-rw-r--r--jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/generator/ControlFrameGenerator.java27
-rw-r--r--jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/generator/CredentialGenerator.java80
-rw-r--r--jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/generator/DataFrameGenerator.java28
-rw-r--r--jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/generator/Generator.java28
-rw-r--r--jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/generator/GoAwayGenerator.java27
-rw-r--r--jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/generator/HeadersBlockGenerator.java29
-rw-r--r--jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/generator/HeadersGenerator.java32
-rw-r--r--jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/generator/NoOpGenerator.java27
-rw-r--r--jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/generator/PingGenerator.java27
-rw-r--r--jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/generator/RstStreamGenerator.java27
-rw-r--r--jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/generator/SettingsGenerator.java27
-rw-r--r--jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/generator/SynReplyGenerator.java27
-rw-r--r--jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/generator/SynStreamGenerator.java29
-rw-r--r--jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/generator/WindowUpdateGenerator.java27
-rw-r--r--jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/parser/ControlFrameBodyParser.java27
-rw-r--r--jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/parser/ControlFrameParser.java28
-rw-r--r--jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/parser/CredentialBodyParser.java269
-rw-r--r--jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/parser/DataFrameParser.java27
-rw-r--r--jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/parser/GoAwayBodyParser.java39
-rw-r--r--jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/parser/HeadersBlockParser.java27
-rw-r--r--jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/parser/HeadersBodyParser.java75
-rw-r--r--jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/parser/NoOpBodyParser.java27
-rw-r--r--jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/parser/Parser.java27
-rw-r--r--jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/parser/PingBodyParser.java27
-rw-r--r--jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/parser/RstStreamBodyParser.java27
-rw-r--r--jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/parser/SettingsBodyParser.java28
-rw-r--r--jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/parser/SynReplyBodyParser.java27
-rw-r--r--jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/parser/SynStreamBodyParser.java34
-rw-r--r--jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/parser/UnknownControlFrameBodyParser.java27
-rw-r--r--jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/parser/WindowUpdateBodyParser.java27
-rw-r--r--jetty-spdy/spdy-core/src/test/java/org/eclipse/jetty/spdy/AsyncTimeoutTest.java35
-rw-r--r--jetty-spdy/spdy-core/src/test/java/org/eclipse/jetty/spdy/StandardSessionTest.java178
-rw-r--r--jetty-spdy/spdy-core/src/test/java/org/eclipse/jetty/spdy/StandardStreamTest.java105
-rw-r--r--jetty-spdy/spdy-core/src/test/java/org/eclipse/jetty/spdy/api/ClientUsageTest.java35
-rw-r--r--jetty-spdy/spdy-core/src/test/java/org/eclipse/jetty/spdy/api/ServerUsageTest.java27
-rw-r--r--jetty-spdy/spdy-core/src/test/java/org/eclipse/jetty/spdy/frames/CredentialGenerateParseTest.java99
-rw-r--r--jetty-spdy/spdy-core/src/test/java/org/eclipse/jetty/spdy/frames/DataGenerateParseTest.java27
-rw-r--r--jetty-spdy/spdy-core/src/test/java/org/eclipse/jetty/spdy/frames/GoAwayGenerateParseTest.java27
-rw-r--r--jetty-spdy/spdy-core/src/test/java/org/eclipse/jetty/spdy/frames/HeadersGenerateParseTest.java121
-rw-r--r--jetty-spdy/spdy-core/src/test/java/org/eclipse/jetty/spdy/frames/NoOpGenerateParseTest.java27
-rw-r--r--jetty-spdy/spdy-core/src/test/java/org/eclipse/jetty/spdy/frames/PingGenerateParseTest.java27
-rw-r--r--jetty-spdy/spdy-core/src/test/java/org/eclipse/jetty/spdy/frames/RstStreamGenerateParseTest.java27
-rw-r--r--jetty-spdy/spdy-core/src/test/java/org/eclipse/jetty/spdy/frames/SettingsGenerateParseTest.java27
-rw-r--r--jetty-spdy/spdy-core/src/test/java/org/eclipse/jetty/spdy/frames/SynReplyGenerateParseTest.java27
-rw-r--r--jetty-spdy/spdy-core/src/test/java/org/eclipse/jetty/spdy/frames/SynStreamGenerateParseTest.java35
-rw-r--r--jetty-spdy/spdy-core/src/test/java/org/eclipse/jetty/spdy/frames/TestSPDYParserListener.java27
-rw-r--r--jetty-spdy/spdy-core/src/test/java/org/eclipse/jetty/spdy/frames/WindowUpdateGenerateParseTest.java27
-rw-r--r--jetty-spdy/spdy-core/src/test/java/org/eclipse/jetty/spdy/parser/LiveChromiumRequestParserTest.java27
-rw-r--r--jetty-spdy/spdy-core/src/test/java/org/eclipse/jetty/spdy/parser/ParseVersusCacheBenchmarkTest.java27
-rw-r--r--jetty-spdy/spdy-core/src/test/java/org/eclipse/jetty/spdy/parser/UnknownControlFrameTest.java15
-rw-r--r--jetty-spdy/spdy-core/src/test/resources/keystore.jksbin0 -> 2206 bytes
-rw-r--r--jetty-spdy/spdy-core/src/test/resources/truststore.jksbin0 -> 916 bytes
-rw-r--r--jetty-spdy/spdy-jetty-http-webapp/pom.xml43
-rw-r--r--jetty-spdy/spdy-jetty-http-webapp/src/main/config/etc/jetty-spdy-proxy.xml98
-rw-r--r--jetty-spdy/spdy-jetty-http-webapp/src/main/config/etc/jetty-spdy.xml54
-rw-r--r--jetty-spdy/spdy-jetty-http/pom.xml11
-rw-r--r--jetty-spdy/spdy-jetty-http/src/main/java/org/eclipse/jetty/spdy/http/AbstractHTTPSPDYServerConnector.java61
-rw-r--r--jetty-spdy/spdy-jetty-http/src/main/java/org/eclipse/jetty/spdy/http/HTTPSPDYHeader.java73
-rw-r--r--jetty-spdy/spdy-jetty-http/src/main/java/org/eclipse/jetty/spdy/http/HTTPSPDYServerConnector.java105
-rw-r--r--jetty-spdy/spdy-jetty-http/src/main/java/org/eclipse/jetty/spdy/http/PushStrategy.java28
-rw-r--r--jetty-spdy/spdy-jetty-http/src/main/java/org/eclipse/jetty/spdy/http/ReferrerPushStrategy.java262
-rw-r--r--jetty-spdy/spdy-jetty-http/src/main/java/org/eclipse/jetty/spdy/http/ServerHTTPAsyncConnectionFactory.java39
-rw-r--r--jetty-spdy/spdy-jetty-http/src/main/java/org/eclipse/jetty/spdy/http/ServerHTTPSPDYAsyncConnection.java230
-rw-r--r--jetty-spdy/spdy-jetty-http/src/main/java/org/eclipse/jetty/spdy/http/ServerHTTPSPDYAsyncConnectionFactory.java34
-rw-r--r--jetty-spdy/spdy-jetty-http/src/main/java/org/eclipse/jetty/spdy/proxy/HTTPSPDYProxyConnector.java39
-rw-r--r--jetty-spdy/spdy-jetty-http/src/main/java/org/eclipse/jetty/spdy/proxy/ProxyEngine.java94
-rw-r--r--jetty-spdy/spdy-jetty-http/src/main/java/org/eclipse/jetty/spdy/proxy/ProxyEngineSelector.java166
-rw-r--r--jetty-spdy/spdy-jetty-http/src/main/java/org/eclipse/jetty/spdy/proxy/ProxyHTTPAsyncConnectionFactory.java41
-rw-r--r--jetty-spdy/spdy-jetty-http/src/main/java/org/eclipse/jetty/spdy/proxy/ProxyHTTPSPDYAsyncConnection.java337
-rw-r--r--jetty-spdy/spdy-jetty-http/src/main/java/org/eclipse/jetty/spdy/proxy/SPDYProxyEngine.java514
-rw-r--r--jetty-spdy/spdy-jetty-http/src/test/java/org/eclipse/jetty/spdy/http/AbstractHTTPSPDYTest.java61
-rw-r--r--jetty-spdy/spdy-jetty-http/src/test/java/org/eclipse/jetty/spdy/http/ConcurrentStreamsTest.java44
-rw-r--r--jetty-spdy/spdy-jetty-http/src/test/java/org/eclipse/jetty/spdy/http/ProtocolNegotiationTest.java55
-rw-r--r--jetty-spdy/spdy-jetty-http/src/test/java/org/eclipse/jetty/spdy/http/PushStrategyBenchmarkTest.java395
-rw-r--r--jetty-spdy/spdy-jetty-http/src/test/java/org/eclipse/jetty/spdy/http/ReferrerPushStrategyTest.java471
-rw-r--r--jetty-spdy/spdy-jetty-http/src/test/java/org/eclipse/jetty/spdy/http/ReferrerPushStrategyUnitTest.java119
-rw-r--r--jetty-spdy/spdy-jetty-http/src/test/java/org/eclipse/jetty/spdy/http/ReferrerPushStrategyV2Test.java797
-rw-r--r--jetty-spdy/spdy-jetty-http/src/test/java/org/eclipse/jetty/spdy/http/ReferrerPushStrategyV3Test.java26
-rw-r--r--jetty-spdy/spdy-jetty-http/src/test/java/org/eclipse/jetty/spdy/http/SSLExternalServerTest.java94
-rw-r--r--jetty-spdy/spdy-jetty-http/src/test/java/org/eclipse/jetty/spdy/http/ServerHTTPSPDYv2Test.java (renamed from jetty-spdy/spdy-jetty-http/src/test/java/org/eclipse/jetty/spdy/http/ServerHTTPSPDYTest.java)421
-rw-r--r--jetty-spdy/spdy-jetty-http/src/test/java/org/eclipse/jetty/spdy/http/ServerHTTPSPDYv3Test.java26
-rw-r--r--jetty-spdy/spdy-jetty-http/src/test/java/org/eclipse/jetty/spdy/proxy/ProxyHTTPSPDYv2Test.java764
-rw-r--r--jetty-spdy/spdy-jetty/src/main/java/org/eclipse/jetty/spdy/AsyncConnectionFactory.java28
-rw-r--r--jetty-spdy/spdy-jetty/src/main/java/org/eclipse/jetty/spdy/EmptyAsyncConnection.java28
-rw-r--r--jetty-spdy/spdy-jetty/src/main/java/org/eclipse/jetty/spdy/EmptyAsyncEndPoint.java28
-rw-r--r--jetty-spdy/spdy-jetty/src/main/java/org/eclipse/jetty/spdy/FlowControlStrategyFactory.java37
-rw-r--r--jetty-spdy/spdy-jetty/src/main/java/org/eclipse/jetty/spdy/SPDYAsyncConnection.java37
-rw-r--r--jetty-spdy/spdy-jetty/src/main/java/org/eclipse/jetty/spdy/SPDYClient.java110
-rw-r--r--jetty-spdy/spdy-jetty/src/main/java/org/eclipse/jetty/spdy/SPDYServerConnector.java129
-rw-r--r--jetty-spdy/spdy-jetty/src/main/java/org/eclipse/jetty/spdy/ServerSPDYAsyncConnectionFactory.java46
-rw-r--r--jetty-spdy/spdy-jetty/src/test/java/org/eclipse/jetty/spdy/AbstractTest.java43
-rw-r--r--jetty-spdy/spdy-jetty/src/test/java/org/eclipse/jetty/spdy/ClosedStreamTest.java42
-rw-r--r--jetty-spdy/spdy-jetty/src/test/java/org/eclipse/jetty/spdy/FlowControlTest.java165
-rw-r--r--jetty-spdy/spdy-jetty/src/test/java/org/eclipse/jetty/spdy/GoAwayTest.java31
-rw-r--r--jetty-spdy/spdy-jetty/src/test/java/org/eclipse/jetty/spdy/HeadersTest.java28
-rw-r--r--jetty-spdy/spdy-jetty/src/test/java/org/eclipse/jetty/spdy/IdleTimeoutTest.java44
-rw-r--r--jetty-spdy/spdy-jetty/src/test/java/org/eclipse/jetty/spdy/PingTest.java28
-rw-r--r--jetty-spdy/spdy-jetty/src/test/java/org/eclipse/jetty/spdy/ProtocolViolationsTest.java13
-rw-r--r--jetty-spdy/spdy-jetty/src/test/java/org/eclipse/jetty/spdy/PushStreamTest.java231
-rw-r--r--jetty-spdy/spdy-jetty/src/test/java/org/eclipse/jetty/spdy/ResetStreamTest.java29
-rw-r--r--jetty-spdy/spdy-jetty/src/test/java/org/eclipse/jetty/spdy/SPDYClientFactoryTest.java28
-rw-r--r--jetty-spdy/spdy-jetty/src/test/java/org/eclipse/jetty/spdy/SPDYServerConnectorTest.java28
-rw-r--r--jetty-spdy/spdy-jetty/src/test/java/org/eclipse/jetty/spdy/SSLEngineLeakTest.java13
-rw-r--r--jetty-spdy/spdy-jetty/src/test/java/org/eclipse/jetty/spdy/SSLSynReplyTest.java28
-rw-r--r--jetty-spdy/spdy-jetty/src/test/java/org/eclipse/jetty/spdy/SettingsTest.java28
-rw-r--r--jetty-spdy/spdy-jetty/src/test/java/org/eclipse/jetty/spdy/SynDataReplyDataLoadTest.java28
-rw-r--r--jetty-spdy/spdy-jetty/src/test/java/org/eclipse/jetty/spdy/SynReplyTest.java27
-rw-r--r--jetty-spdy/spdy-jetty/src/test/java/org/eclipse/jetty/spdy/UnsupportedVersionTest.java15
-rw-r--r--jetty-start/src/main/java/org/eclipse/jetty/start/CommandLineBuilder.java12
-rw-r--r--jetty-start/src/main/java/org/eclipse/jetty/start/Main.java37
-rw-r--r--jetty-start/src/main/java/org/eclipse/jetty/start/Monitor.java14
-rw-r--r--jetty-start/src/test/java/org/eclipse/jetty/start/CommandLineBuilderTest.java12
-rw-r--r--jetty-util/src/main/java/org/eclipse/jetty/util/Atomics.java68
-rw-r--r--jetty-util/src/main/java/org/eclipse/jetty/util/ConcurrentHashSet.java12
-rw-r--r--jetty-util/src/main/java/org/eclipse/jetty/util/Loader.java43
-rw-r--r--jetty-util/src/main/java/org/eclipse/jetty/util/MultiPartInputStream.java10
-rw-r--r--jetty-util/src/main/java/org/eclipse/jetty/util/PatternMatcher.java12
-rw-r--r--jetty-util/src/main/java/org/eclipse/jetty/util/RunningStats.java0
-rw-r--r--jetty-util/src/main/java/org/eclipse/jetty/util/SimpleStats.java0
-rw-r--r--jetty-util/src/main/java/org/eclipse/jetty/util/URIUtil.java39
-rw-r--r--jetty-util/src/main/java/org/eclipse/jetty/util/component/AggregateLifeCycle.java16
-rw-r--r--jetty-util/src/main/java/org/eclipse/jetty/util/component/Destroyable.java12
-rw-r--r--jetty-util/src/main/java/org/eclipse/jetty/util/component/Dumpable.java12
-rw-r--r--jetty-util/src/main/java/org/eclipse/jetty/util/component/FileDestroyable.java12
-rw-r--r--jetty-util/src/main/java/org/eclipse/jetty/util/log/AbstractLogger.java12
-rw-r--r--jetty-util/src/main/java/org/eclipse/jetty/util/security/Constraint.java5
-rw-r--r--jetty-util/src/main/java/org/eclipse/jetty/util/statistic/CounterStatistic.java37
-rw-r--r--jetty-util/src/main/java/org/eclipse/jetty/util/statistic/SampleStatistic.java30
-rw-r--r--jetty-util/src/main/java/org/eclipse/jetty/util/thread/ShutdownThread.java7
-rw-r--r--jetty-util/src/test/java/org/eclipse/jetty/util/MultiExceptionTest.java12
-rw-r--r--jetty-util/src/test/java/org/eclipse/jetty/util/MultiMapTest.java12
-rw-r--r--jetty-util/src/test/java/org/eclipse/jetty/util/MultiPartInputStreamTest.java91
-rw-r--r--jetty-util/src/test/java/org/eclipse/jetty/util/ScannerTest.java12
-rw-r--r--jetty-util/src/test/java/org/eclipse/jetty/util/URITest.java4
-rw-r--r--jetty-util/src/test/java/org/eclipse/jetty/util/component/AggregateLifeCycleTest.java12
-rw-r--r--jetty-util/src/test/java/org/eclipse/jetty/util/log/Blue.java12
-rw-r--r--jetty-util/src/test/java/org/eclipse/jetty/util/log/CapturingJULHandler.java12
-rw-r--r--jetty-util/src/test/java/org/eclipse/jetty/util/log/Green.java12
-rw-r--r--jetty-util/src/test/java/org/eclipse/jetty/util/log/JavaUtilLogTest.java12
-rw-r--r--jetty-util/src/test/java/org/eclipse/jetty/util/log/NamedLogTest.java12
-rw-r--r--jetty-util/src/test/java/org/eclipse/jetty/util/log/Red.java12
-rw-r--r--jetty-util/src/test/java/org/eclipse/jetty/util/log/Slf4jHelper.java12
-rw-r--r--jetty-util/src/test/java/org/eclipse/jetty/util/log/StdErrCapture.java12
-rw-r--r--jetty-util/src/test/java/org/eclipse/jetty/util/ssl/SslContextFactoryTest.java12
-rw-r--r--jetty-util/src/test/java/org/eclipse/jetty/util/statistic/SampleStatisticTest.java12
-rw-r--r--jetty-webapp/src/main/java/org/eclipse/jetty/webapp/AbstractConfiguration.java12
-rw-r--r--jetty-webapp/src/main/java/org/eclipse/jetty/webapp/CloneConfiguration.java12
-rw-r--r--jetty-webapp/src/main/java/org/eclipse/jetty/webapp/MetaDataComplete.java12
-rw-r--r--jetty-webapp/src/main/java/org/eclipse/jetty/webapp/Origin.java12
-rw-r--r--jetty-webapp/src/main/java/org/eclipse/jetty/webapp/StandardDescriptorProcessor.java92
-rw-r--r--jetty-webapp/src/main/java/org/eclipse/jetty/webapp/WebAppContext.java21
-rw-r--r--jetty-webapp/src/main/java/org/eclipse/jetty/webapp/WebInfConfiguration.java12
-rw-r--r--jetty-webapp/src/test/java/org/acme/webapp/ClassInJarA.java12
-rw-r--r--jetty-webapp/src/test/java/org/eclipse/jetty/webapp/WebAppClassLoaderTest.java12
-rw-r--r--jetty-webapp/src/test/java/org/eclipse/jetty/webapp/WebAppContextTest.java11
-rw-r--r--jetty-websocket/src/main/java/org/eclipse/jetty/websocket/WebSocketHandler.java3
-rw-r--r--jetty-websocket/src/test/java/org/eclipse/jetty/websocket/WebSocketServletRFCTest.java12
-rw-r--r--jetty-xml/src/main/java/org/eclipse/jetty/xml/XmlConfiguration.java279
-rw-r--r--jetty-xml/src/test/java/org/eclipse/jetty/xml/ConstructorArgTestClass.java77
-rw-r--r--jetty-xml/src/test/java/org/eclipse/jetty/xml/TestConfiguration.java63
-rw-r--r--jetty-xml/src/test/java/org/eclipse/jetty/xml/XmlConfigurationTest.java181
-rw-r--r--pom.xml1
-rw-r--r--test-continuation-jetty6/src/test/java/org/eclipse/jetty/continuation/TestProxyServer.java12
-rw-r--r--test-jetty-nested/src/main/java/org/eclipse/jetty/nested/NestedJettyServlet.java12
-rw-r--r--test-jetty-nested/src/main/java/org/eclipse/jetty/nested/TestServlet.java12
-rw-r--r--test-jetty-servlet/src/main/java/Jetty400Repro.java13
-rw-r--r--test-jetty-webapp/src/main/java/com/acme/Counter.java19
-rw-r--r--test-jetty-webapp/src/main/java/com/acme/Date2Tag.java19
-rw-r--r--test-jetty-webapp/src/main/java/com/acme/DateTag.java19
-rw-r--r--test-jetty-webapp/src/main/java/com/acme/WebSocketChatServlet.java12
-rw-r--r--test-jetty-webapp/src/test/java/org/eclipse/jetty/DispatchServletTest.java26
-rw-r--r--tests/test-integration/src/test/java/org/eclipse/jetty/test/DigestPostTest.java12
-rw-r--r--tests/test-sessions/test-hash-sessions/src/test/java/org/eclipse/jetty/server/session/HashTestServer.java25
-rw-r--r--tests/test-sessions/test-hash-sessions/src/test/java/org/eclipse/jetty/server/session/RemoveSessionTest.java12
-rw-r--r--tests/test-sessions/test-hash-sessions/src/test/java/org/eclipse/jetty/server/session/SessionInvalidateAndCreateTest.java12
-rw-r--r--tests/test-sessions/test-sessions-common/src/main/java/org/eclipse/jetty/server/session/AbstractRemoveSessionTest.java12
-rw-r--r--tests/test-sessions/test-sessions-common/src/main/java/org/eclipse/jetty/server/session/AbstractSessionMigrationTest.java4
366 files changed, 11974 insertions, 3908 deletions
diff --git a/README.txt b/README.txt
index 3412f8ff16..412eb3a442 100644
--- a/README.txt
+++ b/README.txt
@@ -3,8 +3,8 @@ This is a source checkout of the Jetty webserver.
To build, use:
- mvn install
-
+ mvn clean install
+
The jetty distribution will be built in
jetty-distribution/target/distribution
@@ -12,8 +12,11 @@ The jetty distribution will be built in
The first build may take a long time as Maven downloads all the
dependencies.
-The tests do a lot of stress testing, and on some machines it is
+The tests do a lot of stress testing, and on some machines it is
necessary to set the file descriptor limit to greater than 2048
-for the tests to all pass successfully.
+for the tests to all pass successfully.
+
+Bypass tests by building with -Dmaven.test.skip=true but note
+that this will not produce some test jars that are leveraged
+in other places in the build.
-Bypass tests by building with -Dmaven.test.skip=true but note that this will not produce some test jars that are leveraged in other places in the build.
diff --git a/example-jetty-embedded/src/main/java/org/eclipse/jetty/embedded/FileServerXml.java b/example-jetty-embedded/src/main/java/org/eclipse/jetty/embedded/FileServerXml.java
index 428a1dbbf6..4c2429e68d 100644
--- a/example-jetty-embedded/src/main/java/org/eclipse/jetty/embedded/FileServerXml.java
+++ b/example-jetty-embedded/src/main/java/org/eclipse/jetty/embedded/FileServerXml.java
@@ -1,4 +1,16 @@
package org.eclipse.jetty.embedded;
+//========================================================================
+//Copyright (c) 2006-2012 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 org.eclipse.jetty.server.Server;
import org.eclipse.jetty.util.resource.Resource;
diff --git a/jetty-annotations/src/main/java/org/eclipse/jetty/annotations/MultiPartConfigAnnotationHandler.java b/jetty-annotations/src/main/java/org/eclipse/jetty/annotations/MultiPartConfigAnnotationHandler.java
index 7a02031352..4042ccaec0 100644
--- a/jetty-annotations/src/main/java/org/eclipse/jetty/annotations/MultiPartConfigAnnotationHandler.java
+++ b/jetty-annotations/src/main/java/org/eclipse/jetty/annotations/MultiPartConfigAnnotationHandler.java
@@ -79,7 +79,7 @@ public class MultiPartConfigAnnotationHandler extends AbstractIntrospectableAnno
{
for (ServletHolder h : holders)
{
- if (h.getClassName().equals(clazz.getName()))
+ if (h.getClassName() != null && h.getClassName().equals(clazz.getName()))
{
holder = h;
}
diff --git a/jetty-annotations/src/main/java/org/eclipse/jetty/annotations/RunAsAnnotationHandler.java b/jetty-annotations/src/main/java/org/eclipse/jetty/annotations/RunAsAnnotationHandler.java
index 1e4e25d42d..02cae551d0 100644
--- a/jetty-annotations/src/main/java/org/eclipse/jetty/annotations/RunAsAnnotationHandler.java
+++ b/jetty-annotations/src/main/java/org/eclipse/jetty/annotations/RunAsAnnotationHandler.java
@@ -102,7 +102,7 @@ public class RunAsAnnotationHandler extends AbstractIntrospectableAnnotationHand
{
for (ServletHolder h : holders)
{
- if (h.getClassName().equals(clazz.getName()))
+ if (h.getClassName() != null && h.getClassName().equals(clazz.getName()))
{
holder = h;
}
diff --git a/jetty-annotations/src/main/java/org/eclipse/jetty/annotations/ServletContainerInitializerListener.java b/jetty-annotations/src/main/java/org/eclipse/jetty/annotations/ServletContainerInitializerListener.java
index e3cac47aaa..7e0529026a 100644
--- a/jetty-annotations/src/main/java/org/eclipse/jetty/annotations/ServletContainerInitializerListener.java
+++ b/jetty-annotations/src/main/java/org/eclipse/jetty/annotations/ServletContainerInitializerListener.java
@@ -105,9 +105,9 @@ public class ServletContainerInitializerListener implements ServletContextListen
}
}
- //TODO Email from Jan Luehe 18 August: after all ServletContainerInitializers have been
+ //Email from Jan Luehe 18 August: after all ServletContainerInitializers have been
//called, need to check to see if there are any ServletRegistrations remaining
- //that are "preliminary" and fail the deployment if so.
+ //that are "preliminary" and fail the deployment if so. Implemented in ServletHolder.doStart().
}
}
diff --git a/jetty-annotations/src/main/java/org/eclipse/jetty/annotations/ServletSecurityAnnotationHandler.java b/jetty-annotations/src/main/java/org/eclipse/jetty/annotations/ServletSecurityAnnotationHandler.java
index a439f0df9b..83be6bf93c 100644
--- a/jetty-annotations/src/main/java/org/eclipse/jetty/annotations/ServletSecurityAnnotationHandler.java
+++ b/jetty-annotations/src/main/java/org/eclipse/jetty/annotations/ServletSecurityAnnotationHandler.java
@@ -245,7 +245,7 @@ public class ServletSecurityAnnotationHandler extends AbstractIntrospectableAnno
{
//Check the name of the servlet that this mapping applies to, and then find the ServletHolder for it to find it's class
ServletHolder holder = _context.getServletHandler().getServlet(mapping.getServletName());
- if (holder.getClassName().equals(className))
+ if (holder.getClassName() != null && holder.getClassName().equals(className))
results.add(mapping);
}
return results;
diff --git a/jetty-annotations/src/main/java/org/eclipse/jetty/annotations/WebServletAnnotation.java b/jetty-annotations/src/main/java/org/eclipse/jetty/annotations/WebServletAnnotation.java
index b3cd7acd4d..8cdc0840cb 100644
--- a/jetty-annotations/src/main/java/org/eclipse/jetty/annotations/WebServletAnnotation.java
+++ b/jetty-annotations/src/main/java/org/eclipse/jetty/annotations/WebServletAnnotation.java
@@ -92,7 +92,7 @@ public class WebServletAnnotation extends DiscoveredAnnotation
MetaData metaData = _context.getMetaData();
- //Find out if a <servlet> of this type already exists with this name
+ //Find out if a <servlet> already exists with this name
ServletHolder[] holders = _context.getServletHandler().getServlets();
boolean isNew = true;
ServletHolder holder = null;
@@ -100,7 +100,7 @@ public class WebServletAnnotation extends DiscoveredAnnotation
{
for (ServletHolder h : holders)
{
- if (h.getClassName().equals(clazz.getName()) && h.getName() != null && servletName.equals(h.getName()))
+ if (h.getName() != null && servletName.equals(h.getName()))
{
holder = h;
isNew = false;
@@ -142,11 +142,19 @@ public class WebServletAnnotation extends DiscoveredAnnotation
}
else
{
+ //set the class according to the servlet that is annotated, if it wasn't already
+ //NOTE: this may be considered as "completing" an incomplete servlet registration, and it is
+ //not clear from servlet 3.0 spec whether this is intended, or if only a ServletContext.addServlet() call
+ //can complete it, see http://java.net/jira/browse/SERVLET_SPEC-42
+ if (holder.getClassName() == null)
+ holder.setClassName(clazz.getName());
+ if (holder.getHeldClass() == null)
+ holder.setHeldClass(clazz);
+
//check if the existing servlet has each init-param from the annotation
//if not, add it
for (WebInitParam ip:annotation.initParams())
{
- //if (holder.getInitParameter(ip.name()) == null)
if (metaData.getOrigin(servletName+".servlet.init-param"+ip.name())==Origin.NotSet)
{
holder.setInitParameter(ip.name(), ip.value());
@@ -154,17 +162,53 @@ public class WebServletAnnotation extends DiscoveredAnnotation
}
}
- //check the url-patterns, if there annotation has a new one, add it
- ServletMapping[] mappings = _context.getServletHandler().getServletMappings();
-
+ //check the url-patterns
//ServletSpec 3.0 p81 If a servlet already has url mappings from a
- //descriptor the annotation is ignored
- if (mappings == null && metaData.getOriginDescriptor(servletName+".servlet.mappings") != null)
+ //webxml or fragment descriptor the annotation is ignored. However, we want to be able to
+ //replace mappings that were given in webdefault.xml
+ boolean mappingsExist = false;
+ boolean anyNonDefaults = false;
+ ServletMapping[] allMappings = _context.getServletHandler().getServletMappings();
+ if (allMappings != null)
+ {
+ for (ServletMapping m:allMappings)
+ {
+ if (m.getServletName() != null && servletName.equals(m.getServletName()))
+ {
+ mappingsExist = true;
+ if (!m.isDefault())
+ {
+ anyNonDefaults = true;
+ break;
+ }
+ }
+ }
+ }
+
+ if (anyNonDefaults)
+ return; //if any mappings already set by a descriptor that is not webdefault.xml, we're done
+
+ boolean clash = false;
+ if (mappingsExist)
+ {
+ for (String p:urlPatternList)
+ {
+ ServletMapping m = _context.getServletHandler().getServletMapping(p);
+ if (m != null && !m.isDefault())
+ {
+ //trying to override a servlet-mapping that was added not by webdefault.xml
+ clash = true;
+ break;
+ }
+ }
+ }
+
+ if (!mappingsExist || !clash)
{
- ServletMapping mapping = new ServletMapping();
- mapping.setServletName(servletName);
- mapping.setPathSpecs(LazyList.toStringArray(urlPatternList));
- _context.getServletHandler().addServletMapping(mapping);
+ ServletMapping m = new ServletMapping();
+ m.setServletName(servletName);
+ m.setPathSpecs(LazyList.toStringArray(urlPatternList));
+ _context.getServletHandler().addServletMapping(m);
}
}
}
diff --git a/jetty-annotations/src/test/java/org/eclipse/jetty/annotations/Multi.java b/jetty-annotations/src/test/java/org/eclipse/jetty/annotations/Multi.java
index 36cbe8e24d..790d2702cd 100644
--- a/jetty-annotations/src/test/java/org/eclipse/jetty/annotations/Multi.java
+++ b/jetty-annotations/src/test/java/org/eclipse/jetty/annotations/Multi.java
@@ -1,4 +1,16 @@
package org.eclipse.jetty.annotations;
+//========================================================================
+//Copyright (c) 2006-2012 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.lang.annotation.ElementType;
import java.lang.annotation.Retention;
diff --git a/jetty-annotations/src/test/java/org/eclipse/jetty/annotations/resources/TestResourceAnnotations.java b/jetty-annotations/src/test/java/org/eclipse/jetty/annotations/resources/TestResourceAnnotations.java
index 451e899b95..66ebc5a20f 100644
--- a/jetty-annotations/src/test/java/org/eclipse/jetty/annotations/resources/TestResourceAnnotations.java
+++ b/jetty-annotations/src/test/java/org/eclipse/jetty/annotations/resources/TestResourceAnnotations.java
@@ -1,4 +1,16 @@
package org.eclipse.jetty.annotations.resources;
+//========================================================================
+//Copyright (c) 2006-2012 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.lang.reflect.Field;
import java.util.List;
diff --git a/jetty-client/src/test/java/org/eclipse/jetty/client/CachedHeadersIsolationTest.java b/jetty-client/src/test/java/org/eclipse/jetty/client/CachedHeadersIsolationTest.java
index 8a59980838..0cfdecb680 100644
--- a/jetty-client/src/test/java/org/eclipse/jetty/client/CachedHeadersIsolationTest.java
+++ b/jetty-client/src/test/java/org/eclipse/jetty/client/CachedHeadersIsolationTest.java
@@ -1,4 +1,16 @@
package org.eclipse.jetty.client;
+//========================================================================
+//Copyright (c) 2006-2012 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;
diff --git a/jetty-client/src/test/java/org/eclipse/jetty/client/Curl.java b/jetty-client/src/test/java/org/eclipse/jetty/client/Curl.java
index 6c4d510270..5f44036c08 100644
--- a/jetty-client/src/test/java/org/eclipse/jetty/client/Curl.java
+++ b/jetty-client/src/test/java/org/eclipse/jetty/client/Curl.java
@@ -1,4 +1,16 @@
package org.eclipse.jetty.client;
+//========================================================================
+//Copyright 2011-2012 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.util.concurrent.CountDownLatch;
diff --git a/jetty-client/src/test/java/org/eclipse/jetty/client/ExpirationWithLimitedConnectionsTest.java b/jetty-client/src/test/java/org/eclipse/jetty/client/ExpirationWithLimitedConnectionsTest.java
new file mode 100644
index 0000000000..3db4a5e72b
--- /dev/null
+++ b/jetty-client/src/test/java/org/eclipse/jetty/client/ExpirationWithLimitedConnectionsTest.java
@@ -0,0 +1,191 @@
+// ========================================================================
+// Copyright 2012-2012 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;
+
+import java.io.BufferedReader;
+import java.io.IOException;
+import java.io.InputStreamReader;
+import java.io.OutputStream;
+import java.net.ServerSocket;
+import java.net.Socket;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.concurrent.CopyOnWriteArrayList;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Executors;
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.atomic.AtomicBoolean;
+import java.util.concurrent.atomic.AtomicLong;
+
+import org.eclipse.jetty.util.log.Log;
+import org.eclipse.jetty.util.log.Logger;
+import org.junit.Assert;
+import org.junit.Test;
+
+public class ExpirationWithLimitedConnectionsTest
+{
+ @Test
+ public void testExpirationWithMaxConnectionPerAddressReached() throws Exception
+ {
+ final Logger logger = Log.getLogger("org.eclipse.jetty.client");
+ logger.setDebugEnabled(true);
+
+ HttpClient client = new HttpClient();
+ int maxConnectionsPerAddress = 10;
+ client.setMaxConnectionsPerAddress(maxConnectionsPerAddress);
+ long timeout = 1000;
+ client.setTimeout(timeout);
+ client.start();
+
+ final List<Socket> sockets = new CopyOnWriteArrayList<Socket>();
+ final List<Exception> failures = new CopyOnWriteArrayList<Exception>();
+ final AtomicLong processingDelay = new AtomicLong(200);
+
+ final ExecutorService threadPool = Executors.newCachedThreadPool();
+ final ServerSocket server = new ServerSocket(0);
+ threadPool.submit(new Runnable()
+ {
+ public void run()
+ {
+ while (true)
+ {
+ try
+ {
+ final Socket socket = server.accept();
+ sockets.add(socket);
+ logger.debug("CONNECTION {}", socket.getRemoteSocketAddress());
+ threadPool.submit(new Runnable()
+ {
+ public void run()
+ {
+ while (true)
+ {
+ try
+ {
+ BufferedReader reader = new BufferedReader(new InputStreamReader(socket.getInputStream(), "UTF-8"));
+ String firstLine = reader.readLine();
+ String line = firstLine;
+ while (line != null)
+ {
+ if (line.length() == 0)
+ break;
+ line = reader.readLine();
+ }
+
+ if (line == null)
+ break;
+
+ long sleep = processingDelay.get();
+ logger.debug("{} {} {} ms", firstLine, socket.getRemoteSocketAddress(), sleep);
+ TimeUnit.MILLISECONDS.sleep(sleep);
+
+ String response = "" +
+ "HTTP/1.1 200 OK\r\n" +
+ "Content-Length: 0\r\n" +
+ "\r\n";
+ OutputStream output = socket.getOutputStream();
+ output.write(response.getBytes("UTF-8"));
+ output.flush();
+ }
+ catch (Exception x)
+ {
+ failures.add(x);
+ break;
+ }
+ }
+ }
+ });
+ }
+ catch (Exception x)
+ {
+ failures.add(x);
+ break;
+ }
+ }
+ }
+ });
+
+ List<ContentExchange> exchanges = new ArrayList<ContentExchange>();
+
+ final AtomicBoolean firstExpired = new AtomicBoolean();
+ int count = 0;
+ int maxAdditionalRequest = 100;
+ int additionalRequests = 0;
+ while (true)
+ {
+ TimeUnit.MILLISECONDS.sleep(1); // Just avoid being too fast
+ ContentExchange exchange = new ContentExchange(true)
+ {
+ @Override
+ protected void onResponseComplete() throws IOException
+ {
+ logger.debug("{} {} OK", getMethod(), getRequestURI());
+ }
+
+ @Override
+ protected void onExpire()
+ {
+ logger.debug("{} {} EXPIRED {}", getMethod(), getRequestURI(), this);
+ firstExpired.compareAndSet(false, true);
+ }
+ };
+ exchanges.add(exchange);
+ Address address = new Address("localhost", server.getLocalPort());
+ exchange.setAddress(address);
+ exchange.setMethod("GET");
+ exchange.setRequestURI("/" + count);
+ exchange.setVersion("HTTP/1.1");
+ exchange.setRequestHeader("Host", address.toString());
+ logger.debug("{} {} SENT", exchange.getMethod(), exchange.getRequestURI());
+ client.send(exchange);
+ ++count;
+
+ if (processingDelay.get() > 0)
+ {
+ if (client.getDestination(address, false).getConnections() == maxConnectionsPerAddress)
+ {
+ if (firstExpired.get())
+ {
+ ++additionalRequests;
+ if (additionalRequests == maxAdditionalRequest)
+ processingDelay.set(0);
+ }
+ }
+ }
+ else
+ {
+ ++additionalRequests;
+ if (additionalRequests == 2 * maxAdditionalRequest)
+ break;
+ }
+ }
+
+ for (ContentExchange exchange : exchanges)
+ {
+ int status = exchange.waitForDone();
+ Assert.assertTrue(status == HttpExchange.STATUS_COMPLETED || status == HttpExchange.STATUS_EXPIRED);
+ }
+
+ client.stop();
+
+ Assert.assertTrue(failures.isEmpty());
+
+ for (Socket socket : sockets)
+ socket.close();
+ server.close();
+
+ threadPool.shutdown();
+ threadPool.awaitTermination(5, TimeUnit.SECONDS);
+ }
+}
diff --git a/jetty-client/src/test/java/org/eclipse/jetty/client/HttpAsserts.java b/jetty-client/src/test/java/org/eclipse/jetty/client/HttpAsserts.java
index e041005757..bd1e9d3741 100644
--- a/jetty-client/src/test/java/org/eclipse/jetty/client/HttpAsserts.java
+++ b/jetty-client/src/test/java/org/eclipse/jetty/client/HttpAsserts.java
@@ -1,4 +1,16 @@
package org.eclipse.jetty.client;
+//========================================================================
+//Copyright 2011-2012 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.util.Collections;
import java.util.List;
diff --git a/jetty-client/src/test/java/org/eclipse/jetty/client/HttpDestinationQueueTest.java b/jetty-client/src/test/java/org/eclipse/jetty/client/HttpDestinationQueueTest.java
index 4f3b970a62..d292a8961b 100644
--- a/jetty-client/src/test/java/org/eclipse/jetty/client/HttpDestinationQueueTest.java
+++ b/jetty-client/src/test/java/org/eclipse/jetty/client/HttpDestinationQueueTest.java
@@ -1,4 +1,16 @@
package org.eclipse.jetty.client;
+//========================================================================
+//Copyright 2011-2012 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.ServerSocket;
import java.net.Socket;
diff --git a/jetty-client/src/test/java/org/eclipse/jetty/client/ProxyFakeTunnelTest.java b/jetty-client/src/test/java/org/eclipse/jetty/client/ProxyFakeTunnelTest.java
index 1d09edc80a..6071f5ef1a 100644
--- a/jetty-client/src/test/java/org/eclipse/jetty/client/ProxyFakeTunnelTest.java
+++ b/jetty-client/src/test/java/org/eclipse/jetty/client/ProxyFakeTunnelTest.java
@@ -1,4 +1,16 @@
package org.eclipse.jetty.client;
+//========================================================================
+//Copyright 2011-2012 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;
diff --git a/jetty-client/src/test/java/org/eclipse/jetty/client/ProxyTunnellingTest.java b/jetty-client/src/test/java/org/eclipse/jetty/client/ProxyTunnellingTest.java
index 89a55f510e..b85fb5041e 100644
--- a/jetty-client/src/test/java/org/eclipse/jetty/client/ProxyTunnellingTest.java
+++ b/jetty-client/src/test/java/org/eclipse/jetty/client/ProxyTunnellingTest.java
@@ -1,7 +1,18 @@
package org.eclipse.jetty.client;
-
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertTrue;
+//========================================================================
+//Copyright 2011-2012 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.*;
import java.io.IOException;
import java.net.URLEncoder;
@@ -229,7 +240,7 @@ public class ProxyTunnellingTest
exchange.setURL("https://localhost:" + serverPort + "/echo?body=" + URLEncoder.encode(body, "UTF-8"));
httpClient.send(exchange);
- assertTrue(latch.await(serverConnectTimeout * 2, TimeUnit.MILLISECONDS));
+ assertTrue("Server connect exception should have occurred", latch.await(serverConnectTimeout * 2, TimeUnit.MILLISECONDS));
}
finally
{
diff --git a/jetty-client/src/test/java/org/eclipse/jetty/client/Siege.java b/jetty-client/src/test/java/org/eclipse/jetty/client/Siege.java
index bc476c27fc..00c24dc3df 100644
--- a/jetty-client/src/test/java/org/eclipse/jetty/client/Siege.java
+++ b/jetty-client/src/test/java/org/eclipse/jetty/client/Siege.java
@@ -1,4 +1,16 @@
package org.eclipse.jetty.client;
+//========================================================================
+//Copyright 2011-2012 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.util.ArrayList;
diff --git a/jetty-client/src/test/java/org/eclipse/jetty/client/SluggishServerTest.java b/jetty-client/src/test/java/org/eclipse/jetty/client/SluggishServerTest.java
index 65252038b7..edc358ad5f 100644
--- a/jetty-client/src/test/java/org/eclipse/jetty/client/SluggishServerTest.java
+++ b/jetty-client/src/test/java/org/eclipse/jetty/client/SluggishServerTest.java
@@ -1,4 +1,16 @@
package org.eclipse.jetty.client;
+//========================================================================
+//Copyright 2011-2012 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;
diff --git a/jetty-client/src/test/java/org/eclipse/jetty/client/SslBytesClientTest.java b/jetty-client/src/test/java/org/eclipse/jetty/client/SslBytesClientTest.java
index a2f041b7d0..7c2e57cccd 100644
--- a/jetty-client/src/test/java/org/eclipse/jetty/client/SslBytesClientTest.java
+++ b/jetty-client/src/test/java/org/eclipse/jetty/client/SslBytesClientTest.java
@@ -1,4 +1,16 @@
package org.eclipse.jetty.client;
+//========================================================================
+//Copyright 2011-2012 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.BufferedReader;
import java.io.File;
diff --git a/jetty-client/src/test/java/org/eclipse/jetty/client/SslBytesServerTest.java b/jetty-client/src/test/java/org/eclipse/jetty/client/SslBytesServerTest.java
index be41f47bb9..fc046614b8 100644
--- a/jetty-client/src/test/java/org/eclipse/jetty/client/SslBytesServerTest.java
+++ b/jetty-client/src/test/java/org/eclipse/jetty/client/SslBytesServerTest.java
@@ -1,4 +1,16 @@
package org.eclipse.jetty.client;
+//========================================================================
+//Copyright 2011-2012 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.hamcrest.Matchers.*;
diff --git a/jetty-client/src/test/java/org/eclipse/jetty/client/SslBytesTest.java b/jetty-client/src/test/java/org/eclipse/jetty/client/SslBytesTest.java
index 9b13bc30e0..db3762fd7c 100644
--- a/jetty-client/src/test/java/org/eclipse/jetty/client/SslBytesTest.java
+++ b/jetty-client/src/test/java/org/eclipse/jetty/client/SslBytesTest.java
@@ -1,4 +1,16 @@
package org.eclipse.jetty.client;
+//========================================================================
+//Copyright 2011-2012 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.EOFException;
import java.io.IOException;
diff --git a/jetty-client/src/test/java/org/eclipse/jetty/client/SslSelectChannelValidationTest.java b/jetty-client/src/test/java/org/eclipse/jetty/client/SslSelectChannelValidationTest.java
index ffba50d058..a6bfd2fa7b 100644
--- a/jetty-client/src/test/java/org/eclipse/jetty/client/SslSelectChannelValidationTest.java
+++ b/jetty-client/src/test/java/org/eclipse/jetty/client/SslSelectChannelValidationTest.java
@@ -1,4 +1,16 @@
package org.eclipse.jetty.client;
+//========================================================================
+//Copyright 2011-2012 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 org.eclipse.jetty.server.ssl.SslSelectChannelConnector;
diff --git a/jetty-client/src/test/java/org/eclipse/jetty/client/SslSocketValidationTest.java b/jetty-client/src/test/java/org/eclipse/jetty/client/SslSocketValidationTest.java
index eef2f2914d..8238018793 100644
--- a/jetty-client/src/test/java/org/eclipse/jetty/client/SslSocketValidationTest.java
+++ b/jetty-client/src/test/java/org/eclipse/jetty/client/SslSocketValidationTest.java
@@ -1,4 +1,16 @@
package org.eclipse.jetty.client;
+//========================================================================
+//Copyright 2011-2012 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 org.eclipse.jetty.server.ssl.SslSocketConnector;
diff --git a/jetty-client/src/test/java/org/eclipse/jetty/client/SslValidationTestBase.java b/jetty-client/src/test/java/org/eclipse/jetty/client/SslValidationTestBase.java
index 50a733c492..2ed12f4390 100644
--- a/jetty-client/src/test/java/org/eclipse/jetty/client/SslValidationTestBase.java
+++ b/jetty-client/src/test/java/org/eclipse/jetty/client/SslValidationTestBase.java
@@ -1,4 +1,16 @@
package org.eclipse.jetty.client;
+//========================================================================
+//Copyright 2011-2012 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.InputStream;
import java.lang.reflect.Constructor;
diff --git a/jetty-client/src/test/java/org/eclipse/jetty/client/TimeoutTest.java b/jetty-client/src/test/java/org/eclipse/jetty/client/TimeoutTest.java
index 4aefca5514..2c90a80266 100644
--- a/jetty-client/src/test/java/org/eclipse/jetty/client/TimeoutTest.java
+++ b/jetty-client/src/test/java/org/eclipse/jetty/client/TimeoutTest.java
@@ -1,4 +1,16 @@
package org.eclipse.jetty.client;
+//========================================================================
+//Copyright 2011-2012 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.hamcrest.Matchers.*;
diff --git a/jetty-client/src/test/java/org/eclipse/jetty/client/UnexpectedDataTest.java b/jetty-client/src/test/java/org/eclipse/jetty/client/UnexpectedDataTest.java
index 74dd69d43d..5812ff8e04 100644
--- a/jetty-client/src/test/java/org/eclipse/jetty/client/UnexpectedDataTest.java
+++ b/jetty-client/src/test/java/org/eclipse/jetty/client/UnexpectedDataTest.java
@@ -1,16 +1,15 @@
-// ========================================================================
-// Copyright 2006-2007 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.
-// ========================================================================
+//========================================================================
+//Copyright 2011-2012 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;
diff --git a/jetty-client/src/test/java/org/eclipse/jetty/client/helperClasses/AsyncSslServerAndClientCreator.java b/jetty-client/src/test/java/org/eclipse/jetty/client/helperClasses/AsyncSslServerAndClientCreator.java
index b9627e47db..c5424b83c4 100644
--- a/jetty-client/src/test/java/org/eclipse/jetty/client/helperClasses/AsyncSslServerAndClientCreator.java
+++ b/jetty-client/src/test/java/org/eclipse/jetty/client/helperClasses/AsyncSslServerAndClientCreator.java
@@ -1,4 +1,16 @@
package org.eclipse.jetty.client.helperClasses;
+//========================================================================
+//Copyright 2011-2012 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 org.eclipse.jetty.client.HttpClient;
import org.eclipse.jetty.toolchain.test.MavenTestingUtils;
diff --git a/jetty-client/src/test/java/org/eclipse/jetty/client/helperClasses/ExternalKeyStoreAsyncSslServerAndClientCreator.java b/jetty-client/src/test/java/org/eclipse/jetty/client/helperClasses/ExternalKeyStoreAsyncSslServerAndClientCreator.java
index 584f4b1a64..c8442bc1e8 100644
--- a/jetty-client/src/test/java/org/eclipse/jetty/client/helperClasses/ExternalKeyStoreAsyncSslServerAndClientCreator.java
+++ b/jetty-client/src/test/java/org/eclipse/jetty/client/helperClasses/ExternalKeyStoreAsyncSslServerAndClientCreator.java
@@ -1,4 +1,16 @@
package org.eclipse.jetty.client.helperClasses;
+//========================================================================
+//Copyright 2011-2012 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.FileInputStream;
diff --git a/jetty-client/src/test/java/org/eclipse/jetty/client/helperClasses/GenericServerHandler.java b/jetty-client/src/test/java/org/eclipse/jetty/client/helperClasses/GenericServerHandler.java
index cc9ac05545..4694bfff13 100644
--- a/jetty-client/src/test/java/org/eclipse/jetty/client/helperClasses/GenericServerHandler.java
+++ b/jetty-client/src/test/java/org/eclipse/jetty/client/helperClasses/GenericServerHandler.java
@@ -1,4 +1,16 @@
package org.eclipse.jetty.client.helperClasses;
+//========================================================================
+//Copyright 2011-2012 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.ByteArrayOutputStream;
import java.io.IOException;
diff --git a/jetty-client/src/test/java/org/eclipse/jetty/client/helperClasses/HttpServerAndClientCreator.java b/jetty-client/src/test/java/org/eclipse/jetty/client/helperClasses/HttpServerAndClientCreator.java
index d9a2f1d3ee..6f18ac85b3 100644
--- a/jetty-client/src/test/java/org/eclipse/jetty/client/helperClasses/HttpServerAndClientCreator.java
+++ b/jetty-client/src/test/java/org/eclipse/jetty/client/helperClasses/HttpServerAndClientCreator.java
@@ -1,4 +1,16 @@
package org.eclipse.jetty.client.helperClasses;
+//========================================================================
+//Copyright 2011-2012 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 org.eclipse.jetty.client.HttpClient;
import org.eclipse.jetty.server.Connector;
diff --git a/jetty-client/src/test/java/org/eclipse/jetty/client/helperClasses/ServerAndClientCreator.java b/jetty-client/src/test/java/org/eclipse/jetty/client/helperClasses/ServerAndClientCreator.java
index 015006f680..98c063968c 100644
--- a/jetty-client/src/test/java/org/eclipse/jetty/client/helperClasses/ServerAndClientCreator.java
+++ b/jetty-client/src/test/java/org/eclipse/jetty/client/helperClasses/ServerAndClientCreator.java
@@ -1,4 +1,16 @@
package org.eclipse.jetty.client.helperClasses;
+//========================================================================
+//Copyright 2011-2012 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 org.eclipse.jetty.client.HttpClient;
import org.eclipse.jetty.server.Server;
diff --git a/jetty-client/src/test/java/org/eclipse/jetty/client/helperClasses/SslServerAndClientCreator.java b/jetty-client/src/test/java/org/eclipse/jetty/client/helperClasses/SslServerAndClientCreator.java
index d0e0ad0a11..f1c30f030d 100644
--- a/jetty-client/src/test/java/org/eclipse/jetty/client/helperClasses/SslServerAndClientCreator.java
+++ b/jetty-client/src/test/java/org/eclipse/jetty/client/helperClasses/SslServerAndClientCreator.java
@@ -1,4 +1,16 @@
package org.eclipse.jetty.client.helperClasses;
+//========================================================================
+//Copyright 2011-2012 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 org.eclipse.jetty.client.HttpClient;
diff --git a/jetty-continuation/src/main/java/org/eclipse/jetty/continuation/ContinuationFilter.java b/jetty-continuation/src/main/java/org/eclipse/jetty/continuation/ContinuationFilter.java
index e5bd75144a..c10ae1292c 100644
--- a/jetty-continuation/src/main/java/org/eclipse/jetty/continuation/ContinuationFilter.java
+++ b/jetty-continuation/src/main/java/org/eclipse/jetty/continuation/ContinuationFilter.java
@@ -1,4 +1,16 @@
package org.eclipse.jetty.continuation;
+//========================================================================
+//Copyright 2011-2012 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;
diff --git a/jetty-continuation/src/main/java/org/eclipse/jetty/continuation/ContinuationListener.java b/jetty-continuation/src/main/java/org/eclipse/jetty/continuation/ContinuationListener.java
index 54581a8f5b..a3f3ee1ceb 100644
--- a/jetty-continuation/src/main/java/org/eclipse/jetty/continuation/ContinuationListener.java
+++ b/jetty-continuation/src/main/java/org/eclipse/jetty/continuation/ContinuationListener.java
@@ -1,5 +1,16 @@
-
package org.eclipse.jetty.continuation;
+//========================================================================
+//Copyright 2011-2012 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.util.EventListener;
diff --git a/jetty-continuation/src/main/java/org/eclipse/jetty/continuation/Jetty6Continuation.java b/jetty-continuation/src/main/java/org/eclipse/jetty/continuation/Jetty6Continuation.java
index 142b675ec2..db43a22f7b 100644
--- a/jetty-continuation/src/main/java/org/eclipse/jetty/continuation/Jetty6Continuation.java
+++ b/jetty-continuation/src/main/java/org/eclipse/jetty/continuation/Jetty6Continuation.java
@@ -1,4 +1,16 @@
package org.eclipse.jetty.continuation;
+//========================================================================
+//Copyright 2011-2012 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.util.ArrayList;
import java.util.List;
diff --git a/jetty-continuation/src/main/java/org/eclipse/jetty/continuation/Servlet3Continuation.java b/jetty-continuation/src/main/java/org/eclipse/jetty/continuation/Servlet3Continuation.java
index 26323372c4..5e509b007f 100644
--- a/jetty-continuation/src/main/java/org/eclipse/jetty/continuation/Servlet3Continuation.java
+++ b/jetty-continuation/src/main/java/org/eclipse/jetty/continuation/Servlet3Continuation.java
@@ -1,4 +1,16 @@
package org.eclipse.jetty.continuation;
+//========================================================================
+//Copyright 2011-2012 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.util.ArrayList;
diff --git a/jetty-deploy/src/main/java/org/eclipse/jetty/deploy/jmx/DeploymentManagerMBean.java b/jetty-deploy/src/main/java/org/eclipse/jetty/deploy/jmx/DeploymentManagerMBean.java
index 3bd5362494..447fb7bd7d 100644
--- a/jetty-deploy/src/main/java/org/eclipse/jetty/deploy/jmx/DeploymentManagerMBean.java
+++ b/jetty-deploy/src/main/java/org/eclipse/jetty/deploy/jmx/DeploymentManagerMBean.java
@@ -1,4 +1,16 @@
package org.eclipse.jetty.deploy.jmx;
+//========================================================================
+//Copyright 2011-2012 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.util.ArrayList;
import java.util.Collection;
diff --git a/jetty-deploy/src/main/java/org/eclipse/jetty/deploy/providers/ContextProvider.java b/jetty-deploy/src/main/java/org/eclipse/jetty/deploy/providers/ContextProvider.java
index 323f836bf9..2685b82fdc 100644
--- a/jetty-deploy/src/main/java/org/eclipse/jetty/deploy/providers/ContextProvider.java
+++ b/jetty-deploy/src/main/java/org/eclipse/jetty/deploy/providers/ContextProvider.java
@@ -1,4 +1,16 @@
package org.eclipse.jetty.deploy.providers;
+//========================================================================
+//Copyright 2009-2012 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.File;
import java.io.FilenameFilter;
diff --git a/jetty-deploy/src/main/java/org/eclipse/jetty/deploy/providers/WebAppProvider.java b/jetty-deploy/src/main/java/org/eclipse/jetty/deploy/providers/WebAppProvider.java
index c924b455a9..557edc0de9 100644
--- a/jetty-deploy/src/main/java/org/eclipse/jetty/deploy/providers/WebAppProvider.java
+++ b/jetty-deploy/src/main/java/org/eclipse/jetty/deploy/providers/WebAppProvider.java
@@ -1,4 +1,16 @@
package org.eclipse.jetty.deploy.providers;
+//========================================================================
+//Copyright 2009-2012 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.File;
import java.io.FilenameFilter;
diff --git a/jetty-deploy/src/test/java/org/eclipse/jetty/deploy/DeploymentManagerTest.java b/jetty-deploy/src/test/java/org/eclipse/jetty/deploy/DeploymentManagerTest.java
index 99d619444f..b29dc8fc69 100644
--- a/jetty-deploy/src/test/java/org/eclipse/jetty/deploy/DeploymentManagerTest.java
+++ b/jetty-deploy/src/test/java/org/eclipse/jetty/deploy/DeploymentManagerTest.java
@@ -1,4 +1,16 @@
package org.eclipse.jetty.deploy;
+//========================================================================
+//Copyright 2011-2012 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.util.Collection;
import java.util.Set;
diff --git a/jetty-deploy/src/test/java/org/eclipse/jetty/deploy/graph/GraphTest.java b/jetty-deploy/src/test/java/org/eclipse/jetty/deploy/graph/GraphTest.java
index cc284e1f4d..c067569a73 100644
--- a/jetty-deploy/src/test/java/org/eclipse/jetty/deploy/graph/GraphTest.java
+++ b/jetty-deploy/src/test/java/org/eclipse/jetty/deploy/graph/GraphTest.java
@@ -1,4 +1,16 @@
package org.eclipse.jetty.deploy.graph;
+//========================================================================
+//Copyright 2011-2012 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 junit.framework.Assert;
diff --git a/jetty-deploy/src/test/java/org/eclipse/jetty/deploy/providers/WebAppProviderTest.java b/jetty-deploy/src/test/java/org/eclipse/jetty/deploy/providers/WebAppProviderTest.java
index 8e6357bd43..0685d88909 100644
--- a/jetty-deploy/src/test/java/org/eclipse/jetty/deploy/providers/WebAppProviderTest.java
+++ b/jetty-deploy/src/test/java/org/eclipse/jetty/deploy/providers/WebAppProviderTest.java
@@ -1,4 +1,16 @@
package org.eclipse.jetty.deploy.providers;
+//========================================================================
+//Copyright 2011-2012 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.File;
import java.util.Arrays;
diff --git a/jetty-http-spi/src/test/java/org/eclipse/jetty/http/spi/TestSPIServer.java b/jetty-http-spi/src/test/java/org/eclipse/jetty/http/spi/TestSPIServer.java
index 20ad8e97be..f0d2327510 100644
--- a/jetty-http-spi/src/test/java/org/eclipse/jetty/http/spi/TestSPIServer.java
+++ b/jetty-http-spi/src/test/java/org/eclipse/jetty/http/spi/TestSPIServer.java
@@ -1,4 +1,16 @@
package org.eclipse.jetty.http.spi;
+//========================================================================
+//Copyright 2011-2012 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.OutputStream;
diff --git a/jetty-http/src/main/java/org/eclipse/jetty/http/gzip/AbstractCompressedStream.java b/jetty-http/src/main/java/org/eclipse/jetty/http/gzip/AbstractCompressedStream.java
index 39aaa99516..2b136cec6a 100644
--- a/jetty-http/src/main/java/org/eclipse/jetty/http/gzip/AbstractCompressedStream.java
+++ b/jetty-http/src/main/java/org/eclipse/jetty/http/gzip/AbstractCompressedStream.java
@@ -234,8 +234,7 @@ public abstract class AbstractCompressedStream extends ServletOutputStream
if (_response.isCommitted())
throw new IllegalStateException();
- setHeader("Content-Encoding", _encoding);
-
+ setHeader("Content-Encoding", _encoding);
if (_response.containsHeader("Content-Encoding"))
{
_out=_compressedOutputStream=createStream();
diff --git a/jetty-http/src/main/java/org/eclipse/jetty/http/ssl/SslContextFactory.java b/jetty-http/src/main/java/org/eclipse/jetty/http/ssl/SslContextFactory.java
index 7a5d156f0e..fc1ab558af 100644
--- a/jetty-http/src/main/java/org/eclipse/jetty/http/ssl/SslContextFactory.java
+++ b/jetty-http/src/main/java/org/eclipse/jetty/http/ssl/SslContextFactory.java
@@ -1,4 +1,16 @@
package org.eclipse.jetty.http.ssl;
+//========================================================================
+//Copyright 2011-2012 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.
+//========================================================================
/* ------------------------------------------------------------ */
diff --git a/jetty-http/src/test/java/org/eclipse/jetty/http/MimeTypesTest.java b/jetty-http/src/test/java/org/eclipse/jetty/http/MimeTypesTest.java
index e3ea297379..f95e6b0f10 100644
--- a/jetty-http/src/test/java/org/eclipse/jetty/http/MimeTypesTest.java
+++ b/jetty-http/src/test/java/org/eclipse/jetty/http/MimeTypesTest.java
@@ -1,4 +1,16 @@
package org.eclipse.jetty.http;
+//========================================================================
+//Copyright 2011-2012 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 org.eclipse.jetty.io.Buffer;
import org.junit.Assert;
diff --git a/jetty-io/src/main/java/org/eclipse/jetty/io/AbstractBuffers.java b/jetty-io/src/main/java/org/eclipse/jetty/io/AbstractBuffers.java
index b94710af5c..9bc63cd1de 100644
--- a/jetty-io/src/main/java/org/eclipse/jetty/io/AbstractBuffers.java
+++ b/jetty-io/src/main/java/org/eclipse/jetty/io/AbstractBuffers.java
@@ -1,4 +1,16 @@
package org.eclipse.jetty.io;
+//========================================================================
+//Copyright (c) 2006-2012 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 org.eclipse.jetty.io.nio.DirectNIOBuffer;
import org.eclipse.jetty.io.nio.IndirectNIOBuffer;
diff --git a/jetty-io/src/main/java/org/eclipse/jetty/io/AbstractConnection.java b/jetty-io/src/main/java/org/eclipse/jetty/io/AbstractConnection.java
index ef80cccb2f..e3da77460e 100644
--- a/jetty-io/src/main/java/org/eclipse/jetty/io/AbstractConnection.java
+++ b/jetty-io/src/main/java/org/eclipse/jetty/io/AbstractConnection.java
@@ -1,4 +1,16 @@
package org.eclipse.jetty.io;
+//========================================================================
+//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;
diff --git a/jetty-io/src/main/java/org/eclipse/jetty/io/BuffersFactory.java b/jetty-io/src/main/java/org/eclipse/jetty/io/BuffersFactory.java
index 693976a3d8..db23f96232 100644
--- a/jetty-io/src/main/java/org/eclipse/jetty/io/BuffersFactory.java
+++ b/jetty-io/src/main/java/org/eclipse/jetty/io/BuffersFactory.java
@@ -1,4 +1,16 @@
package org.eclipse.jetty.io;
+//========================================================================
+//Copyright 2011-2012 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.
+//========================================================================
public class BuffersFactory
{
diff --git a/jetty-io/src/main/java/org/eclipse/jetty/io/ConnectedEndPoint.java b/jetty-io/src/main/java/org/eclipse/jetty/io/ConnectedEndPoint.java
index a7e66dd284..ea550ce409 100644
--- a/jetty-io/src/main/java/org/eclipse/jetty/io/ConnectedEndPoint.java
+++ b/jetty-io/src/main/java/org/eclipse/jetty/io/ConnectedEndPoint.java
@@ -1,4 +1,16 @@
package org.eclipse.jetty.io;
+//========================================================================
+//Copyright 2011-2012 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.
+//========================================================================
public interface ConnectedEndPoint extends EndPoint
{
diff --git a/jetty-io/src/main/java/org/eclipse/jetty/io/PooledBuffers.java b/jetty-io/src/main/java/org/eclipse/jetty/io/PooledBuffers.java
index 194eb9bf71..f8356bab81 100644
--- a/jetty-io/src/main/java/org/eclipse/jetty/io/PooledBuffers.java
+++ b/jetty-io/src/main/java/org/eclipse/jetty/io/PooledBuffers.java
@@ -1,4 +1,16 @@
package org.eclipse.jetty.io;
+//========================================================================
+//Copyright 2011-2012 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.util.Queue;
import java.util.concurrent.ConcurrentLinkedQueue;
diff --git a/jetty-io/src/main/java/org/eclipse/jetty/io/nio/SelectChannelEndPoint.java b/jetty-io/src/main/java/org/eclipse/jetty/io/nio/SelectChannelEndPoint.java
index a8db4ec100..3ba70b035b 100644
--- a/jetty-io/src/main/java/org/eclipse/jetty/io/nio/SelectChannelEndPoint.java
+++ b/jetty-io/src/main/java/org/eclipse/jetty/io/nio/SelectChannelEndPoint.java
@@ -333,9 +333,10 @@ public class SelectChannelEndPoint extends ChannelEndPoint implements AsyncEndPo
if (l==0 && ( header!=null && header.hasContent() || buffer!=null && buffer.hasContent() || trailer!=null && trailer.hasContent()))
{
synchronized (this)
- {
- if (_dispatched)
- _writable=false;
+ {
+ _writable=false;
+ if (!_dispatched)
+ updateKey();
}
}
else if (l>0)
@@ -358,9 +359,10 @@ public class SelectChannelEndPoint extends ChannelEndPoint implements AsyncEndPo
if (l==0 && buffer!=null && buffer.hasContent())
{
synchronized (this)
- {
- if (_dispatched)
- _writable=false;
+ {
+ _writable=false;
+ if (!_dispatched)
+ updateKey();
}
}
else if (l>0)
diff --git a/jetty-io/src/test/java/org/eclipse/jetty/io/EndPointTest.java b/jetty-io/src/test/java/org/eclipse/jetty/io/EndPointTest.java
index 51be3cd751..62183eb186 100644
--- a/jetty-io/src/test/java/org/eclipse/jetty/io/EndPointTest.java
+++ b/jetty-io/src/test/java/org/eclipse/jetty/io/EndPointTest.java
@@ -1,4 +1,16 @@
package org.eclipse.jetty.io;
+//========================================================================
+//Copyright 2011-2012 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.junit.Assert.assertFalse;
diff --git a/jetty-io/src/test/java/org/eclipse/jetty/io/bio/SocketEndPointTest.java b/jetty-io/src/test/java/org/eclipse/jetty/io/bio/SocketEndPointTest.java
index 277c6c7ccb..c412b42736 100644
--- a/jetty-io/src/test/java/org/eclipse/jetty/io/bio/SocketEndPointTest.java
+++ b/jetty-io/src/test/java/org/eclipse/jetty/io/bio/SocketEndPointTest.java
@@ -1,4 +1,16 @@
package org.eclipse.jetty.io.bio;
+//========================================================================
+//Copyright 2011-2012 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.ServerSocket;
import java.net.Socket;
diff --git a/jetty-io/src/test/java/org/eclipse/jetty/io/nio/ChannelEndPointTest.java b/jetty-io/src/test/java/org/eclipse/jetty/io/nio/ChannelEndPointTest.java
index 1d8d5b2c7e..2803722a0d 100644
--- a/jetty-io/src/test/java/org/eclipse/jetty/io/nio/ChannelEndPointTest.java
+++ b/jetty-io/src/test/java/org/eclipse/jetty/io/nio/ChannelEndPointTest.java
@@ -1,4 +1,16 @@
package org.eclipse.jetty.io.nio;
+//========================================================================
+//Copyright 2011-2012 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.nio.channels.ServerSocketChannel;
import java.nio.channels.SocketChannel;
diff --git a/jetty-io/src/test/java/org/eclipse/jetty/io/nio/SelectChannelEndPointSslTest.java b/jetty-io/src/test/java/org/eclipse/jetty/io/nio/SelectChannelEndPointSslTest.java
index fbf3eae1ac..e279f5cfa3 100644
--- a/jetty-io/src/test/java/org/eclipse/jetty/io/nio/SelectChannelEndPointSslTest.java
+++ b/jetty-io/src/test/java/org/eclipse/jetty/io/nio/SelectChannelEndPointSslTest.java
@@ -1,4 +1,16 @@
package org.eclipse.jetty.io.nio;
+//========================================================================
+//Copyright 2011-2012 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.File;
import java.io.IOException;
diff --git a/jetty-io/src/test/java/org/eclipse/jetty/io/nio/SelectChannelEndPointTest.java b/jetty-io/src/test/java/org/eclipse/jetty/io/nio/SelectChannelEndPointTest.java
index 47e5f7daf5..5399f7fe41 100644
--- a/jetty-io/src/test/java/org/eclipse/jetty/io/nio/SelectChannelEndPointTest.java
+++ b/jetty-io/src/test/java/org/eclipse/jetty/io/nio/SelectChannelEndPointTest.java
@@ -1,4 +1,16 @@
package org.eclipse.jetty.io.nio;
+//========================================================================
+//Copyright 2011-2012 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.hamcrest.Matchers.greaterThanOrEqualTo;
import static org.hamcrest.Matchers.greaterThan;
diff --git a/jetty-jndi/src/main/java/org/eclipse/jetty/jndi/DataSourceCloser.java b/jetty-jndi/src/main/java/org/eclipse/jetty/jndi/DataSourceCloser.java
index 352b745fcc..e0a46e9848 100644
--- a/jetty-jndi/src/main/java/org/eclipse/jetty/jndi/DataSourceCloser.java
+++ b/jetty-jndi/src/main/java/org/eclipse/jetty/jndi/DataSourceCloser.java
@@ -1,4 +1,16 @@
package org.eclipse.jetty.jndi;
+//========================================================================
+//Copyright 2011-2012 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.lang.reflect.Method;
import java.sql.Statement;
diff --git a/jetty-monitor/src/main/config/etc/jetty-monitor.xml b/jetty-monitor/src/main/config/etc/jetty-monitor.xml
index 6a866dda28..dc97f88a49 100644
--- a/jetty-monitor/src/main/config/etc/jetty-monitor.xml
+++ b/jetty-monitor/src/main/config/etc/jetty-monitor.xml
@@ -8,14 +8,14 @@
<New class="org.eclipse.jetty.monitor.ThreadMonitor">
<Set name="scanInterval">2000</Set>
<Set name="busyThreshold">90</Set>
- <Set name="stackDepth">3</Set>
+ <Set name="stackDepth">5</Set>
<Set name="trailLength">2</Set>
<!-- To enable logging CPU utilization for threads above specified threshold, -->
<!-- uncomment the following lines, changing log interval (in milliseconds) -->
<!-- and log threshold (in percent) as desired. -->
<!--
- <Set name="logInterval">10000</Arg>
- <Set name="logThreshold">1</Arg>
+ <Set name="logInterval">10000</Set>
+ <Set name="logThreshold">65</Set>
-->
<!-- To enable detail dump of the server whenever a thread is detected as spinning, -->
diff --git a/jetty-nosql/src/main/java/org/eclipse/jetty/nosql/mongodb/jmx/MongoSessionManagerMBean.java b/jetty-nosql/src/main/java/org/eclipse/jetty/nosql/mongodb/jmx/MongoSessionManagerMBean.java
index bb41ac918b..646fad620c 100644
--- a/jetty-nosql/src/main/java/org/eclipse/jetty/nosql/mongodb/jmx/MongoSessionManagerMBean.java
+++ b/jetty-nosql/src/main/java/org/eclipse/jetty/nosql/mongodb/jmx/MongoSessionManagerMBean.java
@@ -1,4 +1,16 @@
package org.eclipse.jetty.nosql.mongodb.jmx;
+//========================================================================
+//Copyright 2011-2012 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 org.eclipse.jetty.nosql.mongodb.MongoSessionManager;
import org.eclipse.jetty.server.handler.AbstractHandlerContainer;
diff --git a/jetty-npn/pom.xml b/jetty-npn/pom.xml
index 063dffda7a..f7bd5872e8 100644
--- a/jetty-npn/pom.xml
+++ b/jetty-npn/pom.xml
@@ -9,7 +9,7 @@
<modelVersion>4.0.0</modelVersion>
<groupId>org.eclipse.jetty.npn</groupId>
<artifactId>npn-api</artifactId>
- <version>1.0.1-SNAPSHOT</version>
+ <version>1.1.1-SNAPSHOT</version>
<name>Jetty :: Next Protocol Negotiation :: API</name>
<scm>
diff --git a/jetty-npn/src/main/java/org/eclipse/jetty/npn/NextProtoNego.java b/jetty-npn/src/main/java/org/eclipse/jetty/npn/NextProtoNego.java
index 3db7950ef8..c6ff784c77 100644
--- a/jetty-npn/src/main/java/org/eclipse/jetty/npn/NextProtoNego.java
+++ b/jetty-npn/src/main/java/org/eclipse/jetty/npn/NextProtoNego.java
@@ -1,18 +1,16 @@
-/*
- * Copyright (c) 2012 the original author or authors.
- *
- * 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.
- */
+//========================================================================
+//Copyright 2011-2012 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.npn;
@@ -87,7 +85,8 @@ import javax.net.ssl.SSLSocket;
* </pre>
* <p>There is no need to unregister {@link SSLSocket} or {@link SSLEngine} instances, as they
* are kept in a {@link WeakHashMap} and will be garbage collected when the application does not
- * hard reference them anymore.</p>
+ * hard reference them anymore. However, methods to explicitly unregister {@link SSLSocket} or
+ * {@link SSLEngine} instances are provided.</p>
* <p>In order to help application development, you can set the {@link NextProtoNego#debug} field
* to {@code true} to have debug code printed to {@link System#err}.</p>
*/
@@ -109,6 +108,7 @@ public class NextProtoNego
*
* @param socket the socket to register with the provider
* @param provider the provider to register with the socket
+ * @see #remove(SSLSocket)
*/
public static void put(SSLSocket socket, Provider provider)
{
@@ -125,10 +125,23 @@ public class NextProtoNego
}
/**
+ * <p>Unregisters the given SSLSocket.</p>
+ *
+ * @param socket the socket to unregister
+ * @return the provider registered with the socket
+ * @see #put(SSLSocket, Provider)
+ */
+ public static Provider remove(SSLSocket socket)
+ {
+ return objects.remove(socket);
+ }
+
+ /**
* <p>Registers a SSLEngine with a provider.</p>
*
* @param engine the engine to register with the provider
* @param provider the provider to register with the engine
+ * @see #remove(SSLEngine)
*/
public static void put(SSLEngine engine, Provider provider)
{
@@ -146,6 +159,18 @@ public class NextProtoNego
}
/**
+ * <p>Unregisters the given SSLEngine.</p>
+ *
+ * @param engine the engine to unregister
+ * @return the provider registered with the engine
+ * @see #put(SSLEngine, Provider)
+ */
+ public static Provider remove(SSLEngine engine)
+ {
+ return objects.remove(engine);
+ }
+
+ /**
* <p>Base, empty, interface for providers.</p>
*/
public interface Provider
diff --git a/jetty-plus/src/main/java/org/eclipse/jetty/plus/jaas/spi/LdapLoginModule.java b/jetty-plus/src/main/java/org/eclipse/jetty/plus/jaas/spi/LdapLoginModule.java
index 5f7401724a..a939937e66 100644
--- a/jetty-plus/src/main/java/org/eclipse/jetty/plus/jaas/spi/LdapLoginModule.java
+++ b/jetty-plus/src/main/java/org/eclipse/jetty/plus/jaas/spi/LdapLoginModule.java
@@ -327,6 +327,7 @@ public class LdapLoginModule extends AbstractLoginModule
SearchControls ctls = new SearchControls();
ctls.setDerefLinkFlag(true);
ctls.setSearchScope(SearchControls.SUBTREE_SCOPE);
+ ctls.setReturningAttributes(new String[]{_roleNameAttribute});
String filter = "(&(objectClass={0})({1}={2}))";
Object[] filterArguments = {_roleObjectClass, _roleMemberAttribute, userDn};
diff --git a/jetty-policy/src/main/java/org/eclipse/jetty/policy/PolicyMonitor.java b/jetty-policy/src/main/java/org/eclipse/jetty/policy/PolicyMonitor.java
index 64a1755fec..092ce5e045 100644
--- a/jetty-policy/src/main/java/org/eclipse/jetty/policy/PolicyMonitor.java
+++ b/jetty-policy/src/main/java/org/eclipse/jetty/policy/PolicyMonitor.java
@@ -1,4 +1,16 @@
package org.eclipse.jetty.policy;
+//========================================================================
+//Copyright 2011-2012 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.File;
import java.io.FileInputStream;
diff --git a/jetty-policy/src/test/java/org/eclipse/jetty/policy/PolicyMonitorTest.java b/jetty-policy/src/test/java/org/eclipse/jetty/policy/PolicyMonitorTest.java
index 0600853428..4831513048 100644
--- a/jetty-policy/src/test/java/org/eclipse/jetty/policy/PolicyMonitorTest.java
+++ b/jetty-policy/src/test/java/org/eclipse/jetty/policy/PolicyMonitorTest.java
@@ -1,4 +1,16 @@
package org.eclipse.jetty.policy;
+//========================================================================
+//Copyright 2011-2012 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.File;
import java.util.HashMap;
diff --git a/jetty-security/src/main/java/org/eclipse/jetty/security/DefaultAuthenticatorFactory.java b/jetty-security/src/main/java/org/eclipse/jetty/security/DefaultAuthenticatorFactory.java
index 6c243a3a87..4dee1d083b 100644
--- a/jetty-security/src/main/java/org/eclipse/jetty/security/DefaultAuthenticatorFactory.java
+++ b/jetty-security/src/main/java/org/eclipse/jetty/security/DefaultAuthenticatorFactory.java
@@ -62,6 +62,8 @@ public class DefaultAuthenticatorFactory implements Authenticator.Factory
authenticator=new FormAuthenticator();
else if ( Constraint.__SPNEGO_AUTH.equalsIgnoreCase(auth) )
authenticator = new SpnegoAuthenticator();
+ else if ( Constraint.__NEGOTIATE_AUTH.equalsIgnoreCase(auth) ) // see Bug #377076
+ authenticator = new SpnegoAuthenticator(Constraint.__NEGOTIATE_AUTH);
if (Constraint.__CERT_AUTH.equalsIgnoreCase(auth)||Constraint.__CERT_AUTH2.equalsIgnoreCase(auth))
authenticator=new ClientCertAuthenticator();
diff --git a/jetty-security/src/main/java/org/eclipse/jetty/security/PropertyUserStore.java b/jetty-security/src/main/java/org/eclipse/jetty/security/PropertyUserStore.java
index d3921bcab0..1c95cc1a23 100644
--- a/jetty-security/src/main/java/org/eclipse/jetty/security/PropertyUserStore.java
+++ b/jetty-security/src/main/java/org/eclipse/jetty/security/PropertyUserStore.java
@@ -1,4 +1,16 @@
package org.eclipse.jetty.security;
+//========================================================================
+//Copyright 2011-2012 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.File;
import java.io.FilenameFilter;
diff --git a/jetty-security/src/main/java/org/eclipse/jetty/security/SpnegoUserPrincipal.java b/jetty-security/src/main/java/org/eclipse/jetty/security/SpnegoUserPrincipal.java
index a30f60996f..26de9c2c20 100644
--- a/jetty-security/src/main/java/org/eclipse/jetty/security/SpnegoUserPrincipal.java
+++ b/jetty-security/src/main/java/org/eclipse/jetty/security/SpnegoUserPrincipal.java
@@ -1,4 +1,16 @@
package org.eclipse.jetty.security;
+//========================================================================
+//Copyright 2011-2012 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.security.Principal;
diff --git a/jetty-security/src/main/java/org/eclipse/jetty/security/authentication/SpnegoAuthenticator.java b/jetty-security/src/main/java/org/eclipse/jetty/security/authentication/SpnegoAuthenticator.java
index 9df7448468..412d3fd30c 100644
--- a/jetty-security/src/main/java/org/eclipse/jetty/security/authentication/SpnegoAuthenticator.java
+++ b/jetty-security/src/main/java/org/eclipse/jetty/security/authentication/SpnegoAuthenticator.java
@@ -36,9 +36,25 @@ public class SpnegoAuthenticator extends LoginAuthenticator
{
private static final Logger LOG = Log.getLogger(SpnegoAuthenticator.class);
+ private String _authMethod = Constraint.__SPNEGO_AUTH;
+
+ public SpnegoAuthenticator()
+ {
+
+ }
+
+ /**
+ * Allow for a custom authMethod value to be set for instances where SPENGO may not be appropriate
+ * @param authMethod
+ */
+ public SpnegoAuthenticator( String authMethod )
+ {
+ _authMethod = authMethod;
+ }
+
public String getAuthMethod()
{
- return Constraint.__SPNEGO_AUTH;
+ return _authMethod;
}
public Authentication validateRequest(ServletRequest request, ServletResponse response, boolean mandatory) throws ServerAuthException
diff --git a/jetty-security/src/test/java/org/eclipse/jetty/security/PropertyUserStoreTest.java b/jetty-security/src/test/java/org/eclipse/jetty/security/PropertyUserStoreTest.java
index 2e24c178c4..3e70b3efbb 100644
--- a/jetty-security/src/test/java/org/eclipse/jetty/security/PropertyUserStoreTest.java
+++ b/jetty-security/src/test/java/org/eclipse/jetty/security/PropertyUserStoreTest.java
@@ -1,4 +1,16 @@
package org.eclipse.jetty.security;
+//========================================================================
+//Copyright 2011-2012 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.BufferedWriter;
import java.io.File;
diff --git a/jetty-server/src/main/java/org/eclipse/jetty/server/CookieCutter.java b/jetty-server/src/main/java/org/eclipse/jetty/server/CookieCutter.java
index 67ca6db289..8beb127508 100644
--- a/jetty-server/src/main/java/org/eclipse/jetty/server/CookieCutter.java
+++ b/jetty-server/src/main/java/org/eclipse/jetty/server/CookieCutter.java
@@ -312,7 +312,6 @@ public class CookieCutter
}
catch (Exception e)
{
- LOG.warn(e.toString());
LOG.debug(e);
}
diff --git a/jetty-server/src/main/java/org/eclipse/jetty/server/Server.java b/jetty-server/src/main/java/org/eclipse/jetty/server/Server.java
index 5c9c2076ef..f477da9c17 100644
--- a/jetty-server/src/main/java/org/eclipse/jetty/server/Server.java
+++ b/jetty-server/src/main/java/org/eclipse/jetty/server/Server.java
@@ -137,11 +137,21 @@ public class Server extends HandlerWrapper implements Attributes
/* ------------------------------------------------------------ */
public void setStopAtShutdown(boolean stop)
{
- _stopAtShutdown=stop;
+ //if we now want to stop
if (stop)
- ShutdownThread.register(this);
+ {
+ //and we weren't stopping before
+ if (!_stopAtShutdown)
+ {
+ //only register to stop if we're already started (otherwise we'll do it in doStart())
+ if (isStarted())
+ ShutdownThread.register(this);
+ }
+ }
else
ShutdownThread.deregister(this);
+
+ _stopAtShutdown=stop;
}
/* ------------------------------------------------------------ */
@@ -344,7 +354,7 @@ public class Server extends HandlerWrapper implements Attributes
{
LOG.debug("REQUEST "+target+" on "+connection);
handle(target, request, request, response);
- LOG.debug("RESPONSE "+target+" "+connection.getResponse().getStatus());
+ LOG.debug("RESPONSE "+target+" "+connection.getResponse().getStatus()+" handled="+request.isHandled());
}
else
handle(target, request, request, response);
diff --git a/jetty-server/src/main/java/org/eclipse/jetty/server/ServletResponseHttpWrapper.java b/jetty-server/src/main/java/org/eclipse/jetty/server/ServletResponseHttpWrapper.java
index 12595c594a..fc710143f5 100644
--- a/jetty-server/src/main/java/org/eclipse/jetty/server/ServletResponseHttpWrapper.java
+++ b/jetty-server/src/main/java/org/eclipse/jetty/server/ServletResponseHttpWrapper.java
@@ -1,4 +1,16 @@
package org.eclipse.jetty.server;
+//========================================================================
+//Copyright 2011-2012 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.util.Collection;
diff --git a/jetty-server/src/main/java/org/eclipse/jetty/server/handler/ConnectHandler.java b/jetty-server/src/main/java/org/eclipse/jetty/server/handler/ConnectHandler.java
index cef2c5cc97..cc79dc2aa7 100644
--- a/jetty-server/src/main/java/org/eclipse/jetty/server/handler/ConnectHandler.java
+++ b/jetty-server/src/main/java/org/eclipse/jetty/server/handler/ConnectHandler.java
@@ -1,7 +1,21 @@
package org.eclipse.jetty.server.handler;
+//========================================================================
+//Copyright 2011-2012 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.net.InetSocketAddress;
+import java.net.SocketException;
+import java.net.SocketTimeoutException;
import java.nio.channels.ClosedChannelException;
import java.nio.channels.SelectionKey;
import java.nio.channels.SocketChannel;
@@ -223,7 +237,33 @@ public class ConnectHandler extends HandlerWrapper
return;
}
- SocketChannel channel = connectToServer(request, host, port);
+ SocketChannel channel;
+
+ try
+ {
+ channel = connectToServer(request,host,port);
+ }
+ catch (SocketException se)
+ {
+ LOG.info("ConnectHandler: SocketException " + se.getMessage());
+ response.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
+ baseRequest.setHandled(true);
+ return;
+ }
+ catch (SocketTimeoutException ste)
+ {
+ LOG.info("ConnectHandler: SocketTimeoutException" + ste.getMessage());
+ response.setStatus(HttpServletResponse.SC_GATEWAY_TIMEOUT);
+ baseRequest.setHandled(true);
+ return;
+ }
+ catch (IOException ioe)
+ {
+ LOG.info("ConnectHandler: IOException" + ioe.getMessage());
+ response.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
+ baseRequest.setHandled(true);
+ return;
+ }
// Transfer unread data from old connection to new connection
// We need to copy the data to avoid races:
@@ -304,9 +344,10 @@ public class ConnectHandler extends HandlerWrapper
return new ProxyToServerConnection(context, buffer);
}
+ // may return null
private SocketChannel connectToServer(HttpServletRequest request, String host, int port) throws IOException
{
- SocketChannel channel = connect(request, host, port);
+ SocketChannel channel = connect(request, host, port);
channel.configureBlocking(false);
return channel;
}
@@ -323,6 +364,12 @@ public class ConnectHandler extends HandlerWrapper
protected SocketChannel connect(HttpServletRequest request, String host, int port) throws IOException
{
SocketChannel channel = SocketChannel.open();
+
+ if (channel == null)
+ {
+ throw new IOException("unable to connect to " + host + ":" + port);
+ }
+
try
{
// Connect to remote server
diff --git a/jetty-server/src/main/java/org/eclipse/jetty/server/handler/ContextHandler.java b/jetty-server/src/main/java/org/eclipse/jetty/server/handler/ContextHandler.java
index 812ef3013a..6b1e9cfebb 100644
--- a/jetty-server/src/main/java/org/eclipse/jetty/server/handler/ContextHandler.java
+++ b/jetty-server/src/main/java/org/eclipse/jetty/server/handler/ContextHandler.java
@@ -68,6 +68,7 @@ import org.eclipse.jetty.util.Attributes;
import org.eclipse.jetty.util.AttributesMap;
import org.eclipse.jetty.util.LazyList;
import org.eclipse.jetty.util.Loader;
+import org.eclipse.jetty.util.StringUtil;
import org.eclipse.jetty.util.TypeUtil;
import org.eclipse.jetty.util.URIUtil;
import org.eclipse.jetty.util.component.AggregateLifeCycle;
@@ -143,6 +144,7 @@ public class ContextHandler extends ScopedHandler implements Attributes, Server.
private Object _requestListeners;
private Object _requestAttributeListeners;
private Map<String, Object> _managedAttributes;
+ private String[] _protectedTargets;
private boolean _shutdown = false;
private boolean _available = true;
@@ -1131,13 +1133,49 @@ public class ContextHandler extends ScopedHandler implements Attributes, Server.
/* ------------------------------------------------------------ */
/**
* Check the target. Called by {@link #handle(String, Request, HttpServletRequest, HttpServletResponse)} when a target within a context is determined. If
- * the target is protected, 404 is returned. The default implementation always returns false.
+ * the target is protected, 404 is returned.
*/
/* ------------------------------------------------------------ */
- protected boolean isProtectedTarget(String target)
+ public boolean isProtectedTarget(String target)
{
- return false;
+ if (target == null || _protectedTargets == null)
+ return false;
+
+ while (target.startsWith("//"))
+ target=URIUtil.compactPath(target);
+
+ boolean isProtected = false;
+ int i=0;
+ while (!isProtected && i<_protectedTargets.length)
+ {
+ isProtected = StringUtil.startsWithIgnoreCase(target, _protectedTargets[i++]);
+ }
+ return isProtected;
}
+
+
+ public void setProtectedTargets (String[] targets)
+ {
+ if (targets == null)
+ {
+ _protectedTargets = null;
+ return;
+ }
+
+ _protectedTargets = new String[targets.length];
+ System.arraycopy(targets, 0, _protectedTargets, 0, targets.length);
+ }
+
+ public String[] getProtectedTargets ()
+ {
+ if (_protectedTargets == null)
+ return null;
+
+ String[] tmp = new String[_protectedTargets.length];
+ System.arraycopy(_protectedTargets, 0, tmp, 0, _protectedTargets.length);
+ return tmp;
+ }
+
/* ------------------------------------------------------------ */
/*
@@ -1793,8 +1831,8 @@ public class ContextHandler extends ScopedHandler implements Attributes, Server.
query = uriInContext.substring(q + 1);
uriInContext = uriInContext.substring(0,q);
}
- if ((q = uriInContext.indexOf(';')) > 0)
- uriInContext = uriInContext.substring(0,q);
+ // if ((q = uriInContext.indexOf(';')) > 0)
+ // uriInContext = uriInContext.substring(0,q);
String pathInContext = URIUtil.canonicalPath(URIUtil.decodePath(uriInContext));
String uri = URIUtil.addPaths(getContextPath(),uriInContext);
diff --git a/jetty-server/src/main/java/org/eclipse/jetty/server/handler/DebugHandler.java b/jetty-server/src/main/java/org/eclipse/jetty/server/handler/DebugHandler.java
index d224474e3a..dd463edb78 100644
--- a/jetty-server/src/main/java/org/eclipse/jetty/server/handler/DebugHandler.java
+++ b/jetty-server/src/main/java/org/eclipse/jetty/server/handler/DebugHandler.java
@@ -1,15 +1,14 @@
//========================================================================
-//Copyright 2009 Mort Bay Consulting Pty. Ltd.
+//Copyright 2011-2012 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.
+//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;
diff --git a/jetty-server/src/main/java/org/eclipse/jetty/server/handler/ProxyHandler.java b/jetty-server/src/main/java/org/eclipse/jetty/server/handler/ProxyHandler.java
index 96b4dfd854..bf8c556b88 100644
--- a/jetty-server/src/main/java/org/eclipse/jetty/server/handler/ProxyHandler.java
+++ b/jetty-server/src/main/java/org/eclipse/jetty/server/handler/ProxyHandler.java
@@ -1,4 +1,16 @@
package org.eclipse.jetty.server.handler;
+//========================================================================
+//Copyright 2011-2012 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 org.eclipse.jetty.server.Handler;
diff --git a/jetty-server/src/main/java/org/eclipse/jetty/server/handler/ScopedHandler.java b/jetty-server/src/main/java/org/eclipse/jetty/server/handler/ScopedHandler.java
index d4ff318c7a..674c780d7e 100644
--- a/jetty-server/src/main/java/org/eclipse/jetty/server/handler/ScopedHandler.java
+++ b/jetty-server/src/main/java/org/eclipse/jetty/server/handler/ScopedHandler.java
@@ -1,4 +1,16 @@
package org.eclipse.jetty.server.handler;
+//========================================================================
+//Copyright 2011-2012 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;
diff --git a/jetty-server/src/main/java/org/eclipse/jetty/server/session/AbstractSession.java b/jetty-server/src/main/java/org/eclipse/jetty/server/session/AbstractSession.java
index 690c917393..c22dbf8247 100644
--- a/jetty-server/src/main/java/org/eclipse/jetty/server/session/AbstractSession.java
+++ b/jetty-server/src/main/java/org/eclipse/jetty/server/session/AbstractSession.java
@@ -1,4 +1,16 @@
package org.eclipse.jetty.server.session;
+//========================================================================
+//Copyright 2011-2012 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.util.ArrayList;
import java.util.Collections;
@@ -77,6 +89,7 @@ public abstract class AbstractSession implements AbstractSessionManager.SessionI
_accessed=accessed;
_lastAccessed=accessed;
_requests=1;
+ _maxIdleMs=_manager._dftMaxIdleSecs>0?_manager._dftMaxIdleSecs*1000L:-1;
if (LOG.isDebugEnabled())
LOG.debug("new session "+_nodeId+" "+_clusterId);
}
diff --git a/jetty-server/src/main/java/org/eclipse/jetty/server/session/HashedSession.java b/jetty-server/src/main/java/org/eclipse/jetty/server/session/HashedSession.java
index 5db2550a13..20ead43892 100644
--- a/jetty-server/src/main/java/org/eclipse/jetty/server/session/HashedSession.java
+++ b/jetty-server/src/main/java/org/eclipse/jetty/server/session/HashedSession.java
@@ -1,4 +1,16 @@
package org.eclipse.jetty.server.session;
+//========================================================================
+//Copyright 2011-2012 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.DataOutputStream;
import java.io.File;
diff --git a/jetty-server/src/main/java/org/eclipse/jetty/server/ssl/SslCertificates.java b/jetty-server/src/main/java/org/eclipse/jetty/server/ssl/SslCertificates.java
index 7fcd9f8d11..f0e047b8d1 100644
--- a/jetty-server/src/main/java/org/eclipse/jetty/server/ssl/SslCertificates.java
+++ b/jetty-server/src/main/java/org/eclipse/jetty/server/ssl/SslCertificates.java
@@ -1,4 +1,16 @@
package org.eclipse.jetty.server.ssl;
+//========================================================================
+//Copyright 2011-2012 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.ByteArrayInputStream;
import java.io.IOException;
diff --git a/jetty-server/src/main/java/org/eclipse/jetty/server/ssl/SslConnector.java b/jetty-server/src/main/java/org/eclipse/jetty/server/ssl/SslConnector.java
index fb04d57d61..ae45de39fe 100644
--- a/jetty-server/src/main/java/org/eclipse/jetty/server/ssl/SslConnector.java
+++ b/jetty-server/src/main/java/org/eclipse/jetty/server/ssl/SslConnector.java
@@ -1,4 +1,16 @@
package org.eclipse.jetty.server.ssl;
+//========================================================================
+//Copyright 2011-2012 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.File;
import java.security.SecureRandom;
diff --git a/jetty-server/src/test/java/org/eclipse/jetty/server/HttpServerTestBase.java b/jetty-server/src/test/java/org/eclipse/jetty/server/HttpServerTestBase.java
index 49d6cf0cad..614204e9b1 100644
--- a/jetty-server/src/test/java/org/eclipse/jetty/server/HttpServerTestBase.java
+++ b/jetty-server/src/test/java/org/eclipse/jetty/server/HttpServerTestBase.java
@@ -21,9 +21,11 @@ import java.io.InputStreamReader;
import java.io.LineNumberReader;
import java.io.OutputStream;
import java.net.Socket;
+import java.net.SocketException;
import java.net.URL;
import java.util.Arrays;
import java.util.Random;
+import java.util.concurrent.BrokenBarrierException;
import java.util.concurrent.Exchanger;
import javax.servlet.ServletException;
import javax.servlet.ServletOutputStream;
@@ -131,6 +133,11 @@ public abstract class HttpServerTestBase extends HttpServerTestFixture
Assert.assertThat(response, Matchers.containsString("HTTP/1.1 413 "));
}
+ catch(SocketException e)
+ {
+ // TODO looks like a close is overtaking the 413 in SSL
+ System.err.println("Investigate this "+e);
+ }
finally
{
client.close();
diff --git a/jetty-server/src/test/java/org/eclipse/jetty/server/HttpServerTestFixture.java b/jetty-server/src/test/java/org/eclipse/jetty/server/HttpServerTestFixture.java
index 607c271abe..0fa1972d51 100644
--- a/jetty-server/src/test/java/org/eclipse/jetty/server/HttpServerTestFixture.java
+++ b/jetty-server/src/test/java/org/eclipse/jetty/server/HttpServerTestFixture.java
@@ -1,4 +1,16 @@
package org.eclipse.jetty.server;
+//========================================================================
+//Copyright 2011-2012 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.BufferedReader;
import java.io.IOException;
diff --git a/jetty-server/src/test/java/org/eclipse/jetty/server/HttpWriterTest.java b/jetty-server/src/test/java/org/eclipse/jetty/server/HttpWriterTest.java
index 3d21c41375..6edd05115f 100644
--- a/jetty-server/src/test/java/org/eclipse/jetty/server/HttpWriterTest.java
+++ b/jetty-server/src/test/java/org/eclipse/jetty/server/HttpWriterTest.java
@@ -1,4 +1,16 @@
package org.eclipse.jetty.server;
+//========================================================================
+//Copyright 2011-2012 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.junit.Assert.assertTrue;
diff --git a/jetty-server/src/test/java/org/eclipse/jetty/server/SelectChannelAsyncContextTest.java b/jetty-server/src/test/java/org/eclipse/jetty/server/SelectChannelAsyncContextTest.java
index 3bd3cf3920..6e13a24622 100644
--- a/jetty-server/src/test/java/org/eclipse/jetty/server/SelectChannelAsyncContextTest.java
+++ b/jetty-server/src/test/java/org/eclipse/jetty/server/SelectChannelAsyncContextTest.java
@@ -1,4 +1,16 @@
package org.eclipse.jetty.server;
+//========================================================================
+//Copyright 2011-2012 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.net.Socket;
diff --git a/jetty-server/src/test/java/org/eclipse/jetty/server/SlowClientWithPipelinedRequestTest.java b/jetty-server/src/test/java/org/eclipse/jetty/server/SlowClientWithPipelinedRequestTest.java
index 833e5ff97b..db9782dbb1 100644
--- a/jetty-server/src/test/java/org/eclipse/jetty/server/SlowClientWithPipelinedRequestTest.java
+++ b/jetty-server/src/test/java/org/eclipse/jetty/server/SlowClientWithPipelinedRequestTest.java
@@ -1,4 +1,16 @@
package org.eclipse.jetty.server;
+//========================================================================
+//Copyright 2011-2012 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;
diff --git a/jetty-server/src/test/java/org/eclipse/jetty/server/SuspendHandler.java b/jetty-server/src/test/java/org/eclipse/jetty/server/SuspendHandler.java
index 4cde042e98..553886aef2 100644
--- a/jetty-server/src/test/java/org/eclipse/jetty/server/SuspendHandler.java
+++ b/jetty-server/src/test/java/org/eclipse/jetty/server/SuspendHandler.java
@@ -1,4 +1,16 @@
package org.eclipse.jetty.server;
+//========================================================================
+//Copyright 2011-2012 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;
diff --git a/jetty-server/src/test/java/org/eclipse/jetty/server/handler/AbstractConnectHandlerTest.java b/jetty-server/src/test/java/org/eclipse/jetty/server/handler/AbstractConnectHandlerTest.java
index eb07c09aad..aa78cd69fc 100644
--- a/jetty-server/src/test/java/org/eclipse/jetty/server/handler/AbstractConnectHandlerTest.java
+++ b/jetty-server/src/test/java/org/eclipse/jetty/server/handler/AbstractConnectHandlerTest.java
@@ -1,4 +1,16 @@
package org.eclipse.jetty.server.handler;
+//========================================================================
+//Copyright 2011-2012 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.BufferedReader;
import java.io.EOFException;
diff --git a/jetty-server/src/test/java/org/eclipse/jetty/server/handler/ConnectHandlerSSLTest.java b/jetty-server/src/test/java/org/eclipse/jetty/server/handler/ConnectHandlerSSLTest.java
index 25284911ca..2af503aee6 100644
--- a/jetty-server/src/test/java/org/eclipse/jetty/server/handler/ConnectHandlerSSLTest.java
+++ b/jetty-server/src/test/java/org/eclipse/jetty/server/handler/ConnectHandlerSSLTest.java
@@ -1,4 +1,16 @@
package org.eclipse.jetty.server.handler;
+//========================================================================
+//Copyright 2011-2012 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.BufferedReader;
import java.io.ByteArrayOutputStream;
diff --git a/jetty-server/src/test/java/org/eclipse/jetty/server/handler/ConnectHandlerTest.java b/jetty-server/src/test/java/org/eclipse/jetty/server/handler/ConnectHandlerTest.java
index da1f5c5707..8a5ac5b5d2 100644
--- a/jetty-server/src/test/java/org/eclipse/jetty/server/handler/ConnectHandlerTest.java
+++ b/jetty-server/src/test/java/org/eclipse/jetty/server/handler/ConnectHandlerTest.java
@@ -1,4 +1,19 @@
package org.eclipse.jetty.server.handler;
+//========================================================================
+//Copyright 2011-2012 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.*;
+import static org.junit.Assume.*;
import java.io.BufferedReader;
import java.io.ByteArrayOutputStream;
@@ -6,9 +21,12 @@ import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
+import java.net.InetAddress;
import java.net.Socket;
+import java.net.UnknownHostException;
import java.nio.channels.SocketChannel;
import java.util.concurrent.ConcurrentMap;
+
import javax.servlet.ServletException;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletRequest;
@@ -19,13 +37,10 @@ import org.eclipse.jetty.io.EndPoint;
import org.eclipse.jetty.server.Request;
import org.eclipse.jetty.server.nio.SelectChannelConnector;
import org.eclipse.jetty.toolchain.test.OS;
-import org.eclipse.jetty.util.log.Log;
+import org.junit.Assert;
import org.junit.BeforeClass;
import org.junit.Test;
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assume.assumeTrue;
-
/**
* @version $Revision$ $Date$
*/
@@ -104,6 +119,53 @@ public class ConnectHandlerTest extends AbstractConnectHandlerTest
}
}
+
+ @Test
+ public void testCONNECTBadHostPort() throws Exception
+ {
+ String invalidHostname = "AMAZEBALLS_BADHOST.webtide.com";
+
+ try
+ {
+ InetAddress addr = InetAddress.getByName(invalidHostname);
+ StringBuilder err = new StringBuilder();
+ err.append("DNS Hijacking detected: ");
+ err.append(invalidHostname).append(" should have not returned a valid IP address [");
+ err.append(addr.getHostAddress()).append("]. ");
+ err.append("Fix your DNS provider to have this test pass.");
+ err.append("\nFor more info see https://en.wikipedia.org/wiki/DNS_hijacking");
+ Assert.assertNull(err.toString(), addr);
+ }
+ catch (UnknownHostException e)
+ {
+ // expected path
+ }
+
+ String hostPort = String.format("%s:%d",invalidHostname,serverConnector.getLocalPort());
+ String request = "" +
+ "CONNECT " + hostPort + " HTTP/1.1\r\n" +
+ "Host: " + hostPort + "\r\n" +
+ "\r\n";
+ Socket socket = newSocket();
+ socket.setSoTimeout(30000);
+ try
+ {
+ OutputStream output = socket.getOutputStream();
+ BufferedReader input = new BufferedReader(new InputStreamReader(socket.getInputStream()));
+
+ output.write(request.getBytes("UTF-8"));
+ output.flush();
+
+ // Expect 500 OK from the CONNECT request
+ Response response = readResponse(input);
+ assertEquals("Response Code", "500", response.getCode());
+ }
+ finally
+ {
+ socket.close();
+ }
+ }
+
@Test
public void testCONNECT10AndGET() throws Exception
{
@@ -355,6 +417,14 @@ public class ConnectHandlerTest extends AbstractConnectHandlerTest
@Test
public void testCONNECTAndPOSTWithBigBody() throws Exception
{
+ // fails under windows and occasionally on mac due to OOME
+ boolean stress = Boolean.getBoolean( "STRESS" );
+
+ if (!stress)
+ {
+ return;
+ }
+
// Log.getLogger(ConnectHandler.class).setDebugEnabled(true);
String hostPort = "localhost:" + serverConnector.getLocalPort();
String request = "" +
diff --git a/jetty-server/src/test/java/org/eclipse/jetty/server/handler/ContextHandlerTest.java b/jetty-server/src/test/java/org/eclipse/jetty/server/handler/ContextHandlerTest.java
index 0ca3fba82f..183dc57ee2 100644
--- a/jetty-server/src/test/java/org/eclipse/jetty/server/handler/ContextHandlerTest.java
+++ b/jetty-server/src/test/java/org/eclipse/jetty/server/handler/ContextHandlerTest.java
@@ -1,5 +1,4 @@
// ========================================================================
-// $Id$
// Copyright (c) 2006-2009 Mort Bay Consulting Pty. Ltd.
// ------------------------------------------------------------------------
// All rights reserved. This program and the accompanying materials
@@ -292,6 +291,34 @@ public class ContextHandlerTest
assertEquals("333",handler.getServletContext().getAttribute("ccc"));
assertEquals(null,handler.getServletContext().getAttribute("ddd"));
}
+
+ @Test
+ public void testProtected() throws Exception
+ {
+ ContextHandler handler = new ContextHandler();
+ String[] protectedTargets = {"/foo-inf", "/bar-inf"};
+ handler.setProtectedTargets(protectedTargets);
+
+ assertTrue(handler.isProtectedTarget("/foo-inf/x/y/z"));
+ assertFalse(handler.isProtectedTarget("/foo/x/y/z"));
+ assertTrue(handler.isProtectedTarget("/foo-inf?x=y&z=1"));
+
+ protectedTargets = new String[4];
+ System.arraycopy(handler.getProtectedTargets(), 0, protectedTargets, 0, 2);
+ protectedTargets[2] = "/abc";
+ protectedTargets[3] = "/def";
+ handler.setProtectedTargets(protectedTargets);
+
+ assertTrue(handler.isProtectedTarget("/foo-inf/x/y/z"));
+ assertFalse(handler.isProtectedTarget("/foo/x/y/z"));
+ assertTrue(handler.isProtectedTarget("/foo-inf?x=y&z=1"));
+ assertTrue(handler.isProtectedTarget("/abc/124"));
+ assertTrue(handler.isProtectedTarget("//def"));
+
+ assertTrue(handler.isProtectedTarget("/ABC/7777"));
+ }
+
+
private void checkResourcePathsForExampleWebApp(String root) throws IOException
{
diff --git a/jetty-server/src/test/java/org/eclipse/jetty/server/handler/ScopedHandlerTest.java b/jetty-server/src/test/java/org/eclipse/jetty/server/handler/ScopedHandlerTest.java
index 0fa811db0b..b74e9fc9e4 100644
--- a/jetty-server/src/test/java/org/eclipse/jetty/server/handler/ScopedHandlerTest.java
+++ b/jetty-server/src/test/java/org/eclipse/jetty/server/handler/ScopedHandlerTest.java
@@ -1,4 +1,16 @@
package org.eclipse.jetty.server.handler;
+//========================================================================
+//Copyright 2011-2012 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;
diff --git a/jetty-server/src/test/java/org/eclipse/jetty/server/session/SessionHandlerTest.java b/jetty-server/src/test/java/org/eclipse/jetty/server/session/SessionHandlerTest.java
index c413a1a7be..f5728f4d69 100644
--- a/jetty-server/src/test/java/org/eclipse/jetty/server/session/SessionHandlerTest.java
+++ b/jetty-server/src/test/java/org/eclipse/jetty/server/session/SessionHandlerTest.java
@@ -1,4 +1,16 @@
package org.eclipse.jetty.server.session;
+//========================================================================
+//Copyright 2011-2012 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.junit.Assert.assertFalse;
diff --git a/jetty-server/src/test/java/org/eclipse/jetty/server/ssl/SSLCloseTest.java b/jetty-server/src/test/java/org/eclipse/jetty/server/ssl/SSLCloseTest.java
index eb92715497..321122e0a6 100644
--- a/jetty-server/src/test/java/org/eclipse/jetty/server/ssl/SSLCloseTest.java
+++ b/jetty-server/src/test/java/org/eclipse/jetty/server/ssl/SSLCloseTest.java
@@ -1,15 +1,14 @@
//========================================================================
-//Copyright 2004-2008 Mort Bay Consulting Pty. Ltd.
+//Copyright 2011-2012 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.
+//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.
//========================================================================
// JettyTest.java --
diff --git a/jetty-server/src/test/java/org/eclipse/jetty/server/ssl/SSLSelectChannelConnectorLoadTest.java b/jetty-server/src/test/java/org/eclipse/jetty/server/ssl/SSLSelectChannelConnectorLoadTest.java
index 79ef7d32f2..67efa21884 100644
--- a/jetty-server/src/test/java/org/eclipse/jetty/server/ssl/SSLSelectChannelConnectorLoadTest.java
+++ b/jetty-server/src/test/java/org/eclipse/jetty/server/ssl/SSLSelectChannelConnectorLoadTest.java
@@ -1,4 +1,16 @@
package org.eclipse.jetty.server.ssl;
+//========================================================================
+//Copyright 2011-2012 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.BufferedReader;
import java.io.FileInputStream;
diff --git a/jetty-server/src/test/java/org/eclipse/jetty/server/ssl/SslRenegotiateTest.java b/jetty-server/src/test/java/org/eclipse/jetty/server/ssl/SslRenegotiateTest.java
index a38967f164..65864527f8 100644
--- a/jetty-server/src/test/java/org/eclipse/jetty/server/ssl/SslRenegotiateTest.java
+++ b/jetty-server/src/test/java/org/eclipse/jetty/server/ssl/SslRenegotiateTest.java
@@ -1,4 +1,16 @@
package org.eclipse.jetty.server.ssl;
+//========================================================================
+//Copyright 2011-2012 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.assertFalse;
import static org.junit.Assert.assertTrue;
diff --git a/jetty-servlet/src/main/java/org/eclipse/jetty/servlet/DefaultServlet.java b/jetty-servlet/src/main/java/org/eclipse/jetty/servlet/DefaultServlet.java
index 2ee07da5d1..3164387975 100644
--- a/jetty-servlet/src/main/java/org/eclipse/jetty/servlet/DefaultServlet.java
+++ b/jetty-servlet/src/main/java/org/eclipse/jetty/servlet/DefaultServlet.java
@@ -421,6 +421,9 @@ public class DefaultServlet extends HttpServlet implements ResourceFactory
boolean gzip=false;
if (!included.booleanValue() && _gzip && reqRanges==null && !endsWithSlash )
{
+ // Tell caches that response may vary by accept-encoding
+ response.setHeader(HttpHeaders.VARY,HttpHeaders.ACCEPT_ENCODING);
+ // Should we vary this response according to accept-encoding?
String accept=request.getHeader(HttpHeaders.ACCEPT_ENCODING);
if (accept!=null && accept.indexOf("gzip")>=0)
gzip=true;
diff --git a/jetty-servlet/src/main/java/org/eclipse/jetty/servlet/Holder.java b/jetty-servlet/src/main/java/org/eclipse/jetty/servlet/Holder.java
index c1fe3526a7..eea5ac42fe 100644
--- a/jetty-servlet/src/main/java/org/eclipse/jetty/servlet/Holder.java
+++ b/jetty-servlet/src/main/java/org/eclipse/jetty/servlet/Holder.java
@@ -82,7 +82,7 @@ public class Holder<T> extends AbstractLifeCycle implements Dumpable
{
//if no class already loaded and no classname, make servlet permanently unavailable
if (_class==null && (_className==null || _className.equals("")))
- throw new UnavailableException("No class for Servlet or Filter", -1);
+ throw new UnavailableException("No class for Servlet or Filter for "+_name, -1);
//try to load class
if (_class==null)
diff --git a/jetty-servlet/src/main/java/org/eclipse/jetty/servlet/ServletContextHandler.java b/jetty-servlet/src/main/java/org/eclipse/jetty/servlet/ServletContextHandler.java
index cc5fd070c2..91cefb05ee 100644
--- a/jetty-servlet/src/main/java/org/eclipse/jetty/servlet/ServletContextHandler.java
+++ b/jetty-servlet/src/main/java/org/eclipse/jetty/servlet/ServletContextHandler.java
@@ -815,11 +815,24 @@ public class ServletContextHandler extends ContextHandler
throw new UnsupportedOperationException();
final ServletHandler handler = ServletContextHandler.this.getServletHandler();
- final FilterHolder holder= handler.newFilterHolder(Holder.Source.JAVAX_API);
- holder.setName(filterName);
- holder.setHeldClass(filterClass);
- handler.addFilter(holder);
- return holder.getRegistration();
+ FilterHolder holder = handler.getFilter(filterName);
+ if (holder == null)
+ {
+ //new filter
+ holder = handler.newFilterHolder(Holder.Source.JAVAX_API);
+ holder.setName(filterName);
+ holder.setHeldClass(filterClass);
+ handler.addFilter(holder);
+ return holder.getRegistration();
+ }
+ if (holder.getClassName()==null && holder.getHeldClass()==null)
+ {
+ //preliminary filter registration completion
+ holder.setHeldClass(filterClass);
+ return holder.getRegistration();
+ }
+ else
+ return null; //existing filter
}
/* ------------------------------------------------------------ */
@@ -836,11 +849,24 @@ public class ServletContextHandler extends ContextHandler
throw new UnsupportedOperationException();
final ServletHandler handler = ServletContextHandler.this.getServletHandler();
- final FilterHolder holder= handler.newFilterHolder(Holder.Source.JAVAX_API);
- holder.setName(filterName);
- holder.setClassName(className);
- handler.addFilter(holder);
- return holder.getRegistration();
+ FilterHolder holder = handler.getFilter(filterName);
+ if (holder == null)
+ {
+ //new filter
+ holder = handler.newFilterHolder(Holder.Source.JAVAX_API);
+ holder.setName(filterName);
+ holder.setClassName(className);
+ handler.addFilter(holder);
+ return holder.getRegistration();
+ }
+ if (holder.getClassName()==null && holder.getHeldClass()==null)
+ {
+ //preliminary filter registration completion
+ holder.setClassName(className);
+ return holder.getRegistration();
+ }
+ else
+ return null; //existing filter
}
@@ -858,11 +884,25 @@ public class ServletContextHandler extends ContextHandler
throw new UnsupportedOperationException();
final ServletHandler handler = ServletContextHandler.this.getServletHandler();
- final FilterHolder holder= handler.newFilterHolder(Holder.Source.JAVAX_API);
- holder.setName(filterName);
- holder.setFilter(filter);
- handler.addFilter(holder);
- return holder.getRegistration();
+ FilterHolder holder = handler.getFilter(filterName);
+ if (holder == null)
+ {
+ //new filter
+ holder = handler.newFilterHolder(Holder.Source.JAVAX_API);
+ holder.setName(filterName);
+ holder.setFilter(filter);
+ handler.addFilter(holder);
+ return holder.getRegistration();
+ }
+
+ if (holder.getClassName()==null && holder.getHeldClass()==null)
+ {
+ //preliminary filter registration completion
+ holder.setFilter(filter);
+ return holder.getRegistration();
+ }
+ else
+ return null; //existing filter
}
/* ------------------------------------------------------------ */
@@ -877,13 +917,27 @@ public class ServletContextHandler extends ContextHandler
if (!_enabled)
throw new UnsupportedOperationException();
-
+
final ServletHandler handler = ServletContextHandler.this.getServletHandler();
- final ServletHolder holder= handler.newServletHolder(Holder.Source.JAVAX_API);
- holder.setName(servletName);
- holder.setHeldClass(servletClass);
- handler.addServlet(holder);
- return dynamicHolderAdded(holder);
+ ServletHolder holder = handler.getServlet(servletName);
+ if (holder == null)
+ {
+ //new servlet
+ holder = handler.newServletHolder(Holder.Source.JAVAX_API);
+ holder.setName(servletName);
+ holder.setHeldClass(servletClass);
+ handler.addServlet(holder);
+ return dynamicHolderAdded(holder);
+ }
+
+ //complete a partial registration
+ if (holder.getClassName()==null && holder.getHeldClass()==null)
+ {
+ holder.setHeldClass(servletClass);
+ return holder.getRegistration();
+ }
+ else
+ return null; //existing completed registration for servlet name
}
/* ------------------------------------------------------------ */
@@ -899,12 +953,27 @@ public class ServletContextHandler extends ContextHandler
if (!_enabled)
throw new UnsupportedOperationException();
- final ServletHandler handler = ServletContextHandler.this.getServletHandler();
- final ServletHolder holder= handler.newServletHolder(Holder.Source.JAVAX_API);
- holder.setName(servletName);
- holder.setClassName(className);
- handler.addServlet(holder);
- return dynamicHolderAdded(holder);
+
+ final ServletHandler handler = ServletContextHandler.this.getServletHandler();
+ ServletHolder holder = handler.getServlet(servletName);
+ if (holder == null)
+ {
+ //new servlet
+ holder = handler.newServletHolder(Holder.Source.JAVAX_API);
+ holder.setName(servletName);
+ holder.setClassName(className);
+ handler.addServlet(holder);
+ return dynamicHolderAdded(holder);
+ }
+
+ //complete a partial registration
+ if (holder.getClassName()==null && holder.getHeldClass()==null)
+ {
+ holder.setClassName(className);
+ return holder.getRegistration();
+ }
+ else
+ return null; //existing completed registration for servlet name
}
/* ------------------------------------------------------------ */
@@ -919,13 +988,28 @@ public class ServletContextHandler extends ContextHandler
if (!_enabled)
throw new UnsupportedOperationException();
+
+ //TODO handle partial registrations
final ServletHandler handler = ServletContextHandler.this.getServletHandler();
- final ServletHolder holder= handler.newServletHolder(Holder.Source.JAVAX_API);
- holder.setName(servletName);
- holder.setServlet(servlet);
- handler.addServlet(holder);
- return dynamicHolderAdded(holder);
+ ServletHolder holder = handler.getServlet(servletName);
+ if (holder == null)
+ {
+ holder = handler.newServletHolder(Holder.Source.JAVAX_API);
+ holder.setName(servletName);
+ holder.setServlet(servlet);
+ handler.addServlet(holder);
+ return dynamicHolderAdded(holder);
+ }
+
+ //complete a partial registration
+ if (holder.getClassName()==null && holder.getHeldClass()==null)
+ {
+ holder.setServlet(servlet);
+ return holder.getRegistration();
+ }
+ else
+ return null; //existing completed registration for servlet name
}
/* ------------------------------------------------------------ */
diff --git a/jetty-servlet/src/main/java/org/eclipse/jetty/servlet/ServletHandler.java b/jetty-servlet/src/main/java/org/eclipse/jetty/servlet/ServletHandler.java
index 708099437c..8084896bb0 100644
--- a/jetty-servlet/src/main/java/org/eclipse/jetty/servlet/ServletHandler.java
+++ b/jetty-servlet/src/main/java/org/eclipse/jetty/servlet/ServletHandler.java
@@ -259,44 +259,7 @@ public class ServletHandler extends ScopedHandler
return null;
return _servletPathMap.getMatch(pathInContext);
}
-
- /* ------------------------------------------------------------ */
- /**
- * @param uriInContext uri to get dispatcher for
- * @return A {@link RequestDispatcher dispatcher} wrapping the resource at <code>uriInContext</code>,
- * or <code>null</code> if the specified uri cannot be dispatched to.
- */
- public RequestDispatcher getRequestDispatcher(String uriInContext)
- {
- if (uriInContext == null || _contextHandler==null)
- return null;
-
- if (!uriInContext.startsWith("/"))
- return null;
-
- try
- {
- String query=null;
- int q;
- if ((q=uriInContext.indexOf('?'))>0)
- {
- query=uriInContext.substring(q+1);
- uriInContext=uriInContext.substring(0,q);
- }
- if ((q=uriInContext.indexOf(';'))>0)
- uriInContext=uriInContext.substring(0,q);
-
- String pathInContext=URIUtil.canonicalPath(URIUtil.decodePath(uriInContext));
- String uri=URIUtil.addPaths(_contextHandler.getContextPath(), uriInContext);
- return new Dispatcher(_contextHandler, uri, pathInContext, query);
- }
- catch(Exception e)
- {
- LOG.ignore(e);
- }
- return null;
- }
-
+
/* ------------------------------------------------------------ */
public ServletContext getServletContext()
{
@@ -318,6 +281,7 @@ public class ServletHandler extends ScopedHandler
*/
public ServletMapping getServletMapping(String pattern)
{
+ ServletMapping theMapping = null;
if (_servletMappings!=null)
{
for (ServletMapping m:_servletMappings)
@@ -328,12 +292,12 @@ public class ServletHandler extends ScopedHandler
for (String path:paths)
{
if (pattern.equals(path))
- return m;
+ theMapping = m;
}
}
}
}
- return null;
+ return theMapping;
}
/* ------------------------------------------------------------ */
diff --git a/jetty-servlet/src/main/java/org/eclipse/jetty/servlet/ServletHolder.java b/jetty-servlet/src/main/java/org/eclipse/jetty/servlet/ServletHolder.java
index e34b1d40a4..6d20a1d94e 100644
--- a/jetty-servlet/src/main/java/org/eclipse/jetty/servlet/ServletHolder.java
+++ b/jetty-servlet/src/main/java/org/eclipse/jetty/servlet/ServletHolder.java
@@ -41,6 +41,8 @@ import org.eclipse.jetty.security.IdentityService;
import org.eclipse.jetty.security.RunAsToken;
import org.eclipse.jetty.server.Request;
import org.eclipse.jetty.server.UserIdentity;
+import org.eclipse.jetty.server.handler.ContextHandler;
+import org.eclipse.jetty.util.Loader;
import org.eclipse.jetty.util.log.Log;
import org.eclipse.jetty.util.log.Logger;
@@ -285,16 +287,28 @@ public class ServletHolder extends Holder<Servlet> implements UserIdentity.Scope
_unavailable=0;
if (!_enabled)
return;
-
+ //check servlet has a class (ie is not a preliminary registration). If preliminary, fail startup.
try
{
super.doStart();
+ }
+ catch (UnavailableException ue)
+ {
+ makeUnavailable(ue);
+ throw ue;
+ }
+
+ try
+ {
checkServletType();
}
catch (UnavailableException ue)
{
makeUnavailable(ue);
+ if (!_servletHandler.isStartWithUnavailable())
+ throw ue; //servlet is not an instance of javax.servlet.Servlet
}
+
_identityService = _servletHandler.getIdentityService();
if (_identityService!=null && _runAsRole!=null)
@@ -488,6 +502,12 @@ public class ServletHolder extends Holder<Servlet> implements UserIdentity.Scope
{
old_run_as=_identityService.setRunAs(_identityService.getSystemUserIdentity(),_runAsToken);
}
+
+ // Handle configuring servlets that implement org.apache.jasper.servlet.JspServlet
+ if (isJspServlet())
+ {
+ initJspServlet();
+ }
_servlet.init(_config);
}
@@ -523,6 +543,31 @@ public class ServletHolder extends Holder<Servlet> implements UserIdentity.Scope
/* ------------------------------------------------------------ */
/**
+ * @throws Exception
+ */
+ protected void initJspServlet () throws Exception
+ {
+ ContextHandler ch = ((ContextHandler.Context)getServletHandler().getServletContext()).getContextHandler();
+
+ /* Set the webapp's classpath for Jasper */
+ ch.setAttribute("org.apache.catalina.jsp_classpath", ch.getClassPath());
+
+ /* Set the system classpath for Jasper */
+ setInitParameter("com.sun.appserv.jsp.classpath", Loader.getClassPath(ch.getClassLoader().getParent()));
+
+ /* Set up other classpath attribute */
+ if ("?".equals(getInitParameter("classpath")))
+ {
+ String classpath = ch.getClassPath();
+ LOG.debug("classpath=" + classpath);
+ if (classpath != null)
+ setInitParameter("classpath", classpath);
+ }
+ }
+
+
+ /* ------------------------------------------------------------ */
+ /**
* @see org.eclipse.jetty.server.UserIdentity.Scope#getContextPath()
*/
public String getContextPath()
@@ -616,6 +661,34 @@ public class ServletHolder extends Holder<Servlet> implements UserIdentity.Scope
request.setAttribute("javax.servlet.error.servlet_name",getName());
}
}
+
+
+ /* ------------------------------------------------------------ */
+ private boolean isJspServlet ()
+ {
+ if (_servlet == null)
+ return false;
+
+ Class c = _servlet.getClass();
+
+ boolean result = false;
+ while (c != null && !result)
+ {
+ result = isJspServlet(c.getName());
+ c = c.getSuperclass();
+ }
+
+ return result;
+ }
+
+
+ /* ------------------------------------------------------------ */
+ private boolean isJspServlet (String classname)
+ {
+ if (classname == null)
+ return false;
+ return ("org.apache.jasper.servlet.JspServlet".equals(classname));
+ }
/* ------------------------------------------------------------ */
@@ -644,17 +717,24 @@ public class ServletHolder extends Holder<Servlet> implements UserIdentity.Scope
Set<String> clash=null;
for (String pattern : urlPatterns)
{
- if (_servletHandler.getServletMapping(pattern)!=null)
+ ServletMapping mapping = _servletHandler.getServletMapping(pattern);
+ if (mapping!=null)
{
- if (clash==null)
- clash=new HashSet<String>();
- clash.add(pattern);
+ //if the servlet mapping was from a default descriptor, then allow it to be overridden
+ if (!mapping.isDefault())
+ {
+ if (clash==null)
+ clash=new HashSet<String>();
+ clash.add(pattern);
+ }
}
}
+ //if there were any clashes amongst the urls, return them
if (clash!=null)
return clash;
+ //otherwise apply all of them
ServletMapping mapping = new ServletMapping();
mapping.setServletName(ServletHolder.this.getName());
mapping.setPathSpecs(urlPatterns);
diff --git a/jetty-servlet/src/main/java/org/eclipse/jetty/servlet/ServletMapping.java b/jetty-servlet/src/main/java/org/eclipse/jetty/servlet/ServletMapping.java
index e8e133d541..27af5fa400 100644
--- a/jetty-servlet/src/main/java/org/eclipse/jetty/servlet/ServletMapping.java
+++ b/jetty-servlet/src/main/java/org/eclipse/jetty/servlet/ServletMapping.java
@@ -21,6 +21,8 @@ public class ServletMapping
{
private String[] _pathSpecs;
private String _servletName;
+ private boolean _default;
+
/* ------------------------------------------------------------ */
public ServletMapping()
@@ -72,6 +74,25 @@ public class ServletMapping
_servletName = servletName;
}
+
+ /* ------------------------------------------------------------ */
+ /**
+ * @return
+ */
+ public boolean isDefault()
+ {
+ return _default;
+ }
+
+
+ /* ------------------------------------------------------------ */
+ /**
+ * @param default1
+ */
+ public void setDefault(boolean fromDefault)
+ {
+ _default = fromDefault;
+ }
/* ------------------------------------------------------------ */
public String toString()
diff --git a/jetty-servlet/src/test/java/org/eclipse/jetty/servlet/AsyncContextDispatchWithQueryStrings.java b/jetty-servlet/src/test/java/org/eclipse/jetty/servlet/AsyncContextDispatchWithQueryStrings.java
index 27497fa085..27d1a5502f 100644
--- a/jetty-servlet/src/test/java/org/eclipse/jetty/servlet/AsyncContextDispatchWithQueryStrings.java
+++ b/jetty-servlet/src/test/java/org/eclipse/jetty/servlet/AsyncContextDispatchWithQueryStrings.java
@@ -1,4 +1,16 @@
package org.eclipse.jetty.servlet;
+//========================================================================
+//Copyright 2011-2012 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.junit.Assert.assertTrue;
diff --git a/jetty-servlet/src/test/java/org/eclipse/jetty/servlet/AsyncContextTest.java b/jetty-servlet/src/test/java/org/eclipse/jetty/servlet/AsyncContextTest.java
index 925c409493..3da4254bf1 100644
--- a/jetty-servlet/src/test/java/org/eclipse/jetty/servlet/AsyncContextTest.java
+++ b/jetty-servlet/src/test/java/org/eclipse/jetty/servlet/AsyncContextTest.java
@@ -1,4 +1,16 @@
package org.eclipse.jetty.servlet;
+//========================================================================
+//Copyright 2011-2012 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.hamcrest.Matchers.equalTo;
import static org.junit.Assert.assertEquals;
diff --git a/jetty-servlet/src/test/java/org/eclipse/jetty/servlet/DefaultServletTest.java b/jetty-servlet/src/test/java/org/eclipse/jetty/servlet/DefaultServletTest.java
index 3164aaab4e..96a9a73733 100644
--- a/jetty-servlet/src/test/java/org/eclipse/jetty/servlet/DefaultServletTest.java
+++ b/jetty-servlet/src/test/java/org/eclipse/jetty/servlet/DefaultServletTest.java
@@ -1,4 +1,16 @@
package org.eclipse.jetty.servlet;
+//========================================================================
+//Copyright 2011-2012 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.assertTrue;
diff --git a/jetty-servlet/src/test/java/org/eclipse/jetty/servlet/DispatcherTest.java b/jetty-servlet/src/test/java/org/eclipse/jetty/servlet/DispatcherTest.java
index 9925340ee6..9d1f9e5b98 100644
--- a/jetty-servlet/src/test/java/org/eclipse/jetty/servlet/DispatcherTest.java
+++ b/jetty-servlet/src/test/java/org/eclipse/jetty/servlet/DispatcherTest.java
@@ -108,6 +108,27 @@ public class DispatcherTest
assertEquals(expected, responses);
}
+
+ @Test
+ public void testForwardWithParam() throws Exception
+ {
+ _contextHandler.addServlet(ForwardServlet.class, "/ForwardServlet/*");
+ _contextHandler.addServlet(EchoURIServlet.class, "/EchoURI/*");
+
+ String expected=
+ "HTTP/1.1 200 OK\r\n"+
+ "Content-Type: text/plain\r\n"+
+ "Content-Length: 54\r\n"+
+ "\r\n"+
+ "/context\r\n"+
+ "/EchoURI\r\n"+
+ "/x x\r\n"+
+ "/context/EchoURI/x%20x;a=1\r\n";
+
+ String responses = _connector.getResponses("GET /context/ForwardServlet;ignore=true?do=req.echo&uri=EchoURI%2Fx%2520x%3Ba=1%3Fb=2 HTTP/1.1\n" + "Host: localhost\n\n");
+
+ assertEquals(expected, responses);
+ }
@Test
public void testInclude() throws Exception
@@ -282,6 +303,10 @@ public class DispatcherTest
dispatcher = getServletContext().getRequestDispatcher("/AssertIncludeForwardServlet/assertpath?do=end");
else if(request.getParameter("do").equals("assertforward"))
dispatcher = getServletContext().getRequestDispatcher("/AssertForwardServlet?do=end&do=the");
+ else if(request.getParameter("do").equals("ctx.echo"))
+ dispatcher = getServletContext().getRequestDispatcher(request.getParameter("uri"));
+ else if(request.getParameter("do").equals("req.echo"))
+ dispatcher = request.getRequestDispatcher(request.getParameter("uri"));
dispatcher.forward(request, response);
}
}
@@ -465,6 +490,19 @@ public class DispatcherTest
}
}
+ public static class EchoURIServlet extends HttpServlet implements Servlet
+ {
+ protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException
+ {
+ response.setContentType("text/plain");
+ response.setStatus(HttpServletResponse.SC_OK);
+ response.getOutputStream().println(request.getContextPath());
+ response.getOutputStream().println(request.getServletPath());
+ response.getOutputStream().println(request.getPathInfo());
+ response.getOutputStream().println(request.getRequestURI());
+ }
+ }
+
public static class AssertForwardServlet extends HttpServlet implements Servlet
{
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException
diff --git a/jetty-servlet/src/test/java/org/eclipse/jetty/servlet/ServletContextHandlerTest.java b/jetty-servlet/src/test/java/org/eclipse/jetty/servlet/ServletContextHandlerTest.java
index 522643605f..820c5805a0 100644
--- a/jetty-servlet/src/test/java/org/eclipse/jetty/servlet/ServletContextHandlerTest.java
+++ b/jetty-servlet/src/test/java/org/eclipse/jetty/servlet/ServletContextHandlerTest.java
@@ -1,4 +1,16 @@
package org.eclipse.jetty.servlet;
+//========================================================================
+//Copyright 2011-2012 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;
diff --git a/jetty-servlets/src/main/java/org/eclipse/jetty/servlets/BalancerServlet.java b/jetty-servlets/src/main/java/org/eclipse/jetty/servlets/BalancerServlet.java
new file mode 100644
index 0000000000..f7ef7db009
--- /dev/null
+++ b/jetty-servlets/src/main/java/org/eclipse/jetty/servlets/BalancerServlet.java
@@ -0,0 +1,417 @@
+// ========================================================================
+// Copyright (c) 2012 Intalio, Inc.
+// ------------------------------------------------------------------------
+// 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.servlets;
+
+import java.net.MalformedURLException;
+import java.net.URI;
+import java.net.URISyntaxException;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Set;
+import java.util.concurrent.atomic.AtomicInteger;
+
+import javax.servlet.ServletConfig;
+import javax.servlet.ServletException;
+import javax.servlet.UnavailableException;
+import javax.servlet.http.Cookie;
+import javax.servlet.http.HttpServletRequest;
+
+import org.eclipse.jetty.http.HttpURI;
+import org.eclipse.jetty.server.Request;
+
+/**
+ * 6
+ */
+public class BalancerServlet extends ProxyServlet
+{
+
+ private static final class BalancerMember
+ {
+
+ private String _name;
+
+ private String _proxyTo;
+
+ private HttpURI _backendURI;
+
+ public BalancerMember(String name, String proxyTo)
+ {
+ super();
+ _name = name;
+ _proxyTo = proxyTo;
+ _backendURI = new HttpURI(_proxyTo);
+ }
+
+ public String getProxyTo()
+ {
+ return _proxyTo;
+ }
+
+ public HttpURI getBackendURI()
+ {
+ return _backendURI;
+ }
+
+ @Override
+ public String toString()
+ {
+ return "BalancerMember [_name=" + _name + ", _proxyTo=" + _proxyTo + "]";
+ }
+
+ @Override
+ public int hashCode()
+ {
+ final int prime = 31;
+ int result = 1;
+ result = prime * result + ((_name == null)?0:_name.hashCode());
+ return result;
+ }
+
+ @Override
+ public boolean equals(Object obj)
+ {
+ if (this == obj)
+ return true;
+ if (obj == null)
+ return false;
+ if (getClass() != obj.getClass())
+ return false;
+ BalancerMember other = (BalancerMember)obj;
+ if (_name == null)
+ {
+ if (other._name != null)
+ return false;
+ }
+ else if (!_name.equals(other._name))
+ return false;
+ return true;
+ }
+
+ }
+
+ private static final class RoundRobinIterator implements Iterator<BalancerMember>
+ {
+
+ private BalancerMember[] _balancerMembers;
+
+ private AtomicInteger _index;
+
+ public RoundRobinIterator(Collection<BalancerMember> balancerMembers)
+ {
+ _balancerMembers = (BalancerMember[])balancerMembers.toArray(new BalancerMember[balancerMembers.size()]);
+ _index = new AtomicInteger(-1);
+ }
+
+ public boolean hasNext()
+ {
+ return true;
+ }
+
+ public BalancerMember next()
+ {
+ BalancerMember balancerMember = null;
+ while (balancerMember == null)
+ {
+ int currentIndex = _index.get();
+ int nextIndex = (currentIndex + 1) % _balancerMembers.length;
+ if (_index.compareAndSet(currentIndex,nextIndex))
+ {
+ balancerMember = _balancerMembers[nextIndex];
+ }
+ }
+ return balancerMember;
+ }
+
+ public void remove()
+ {
+ throw new UnsupportedOperationException();
+ }
+
+ }
+
+ private static final String BALANCER_MEMBER_PREFIX = "BalancerMember.";
+
+ private static final List<String> FORBIDDEN_CONFIG_PARAMETERS;
+ static
+ {
+ List<String> params = new LinkedList<String>();
+ params.add("HostHeader");
+ params.add("whiteList");
+ params.add("blackList");
+ FORBIDDEN_CONFIG_PARAMETERS = Collections.unmodifiableList(params);
+ }
+
+ private static final List<String> REVERSE_PROXY_HEADERS;
+ static
+ {
+ List<String> params = new LinkedList<String>();
+ params.add("Location");
+ params.add("Content-Location");
+ params.add("URI");
+ REVERSE_PROXY_HEADERS = Collections.unmodifiableList(params);
+ }
+
+ private static final String JSESSIONID = "jsessionid";
+
+ private static final String JSESSIONID_URL_PREFIX = JSESSIONID + "=";
+
+ private boolean _stickySessions;
+
+ private Set<BalancerMember> _balancerMembers = new HashSet<BalancerMember>();
+
+ private boolean _proxyPassReverse;
+
+ private RoundRobinIterator _roundRobinIterator;
+
+ @Override
+ public void init(ServletConfig config) throws ServletException
+ {
+ validateConfig(config);
+ super.init(config);
+ initStickySessions(config);
+ initBalancers(config);
+ initProxyPassReverse(config);
+ postInit();
+ }
+
+ private void validateConfig(ServletConfig config) throws ServletException
+ {
+ @SuppressWarnings("unchecked")
+ List<String> initParameterNames = Collections.list(config.getInitParameterNames());
+ for (String initParameterName : initParameterNames)
+ {
+ if (FORBIDDEN_CONFIG_PARAMETERS.contains(initParameterName))
+ {
+ throw new UnavailableException(initParameterName + " not supported in " + getClass().getName());
+ }
+ }
+ }
+
+ private void initStickySessions(ServletConfig config) throws ServletException
+ {
+ _stickySessions = "true".equalsIgnoreCase(config.getInitParameter("StickySessions"));
+ }
+
+ private void initBalancers(ServletConfig config) throws ServletException
+ {
+ Set<String> balancerNames = getBalancerNames(config);
+ for (String balancerName : balancerNames)
+ {
+ String memberProxyToParam = BALANCER_MEMBER_PREFIX + balancerName + ".ProxyTo";
+ String proxyTo = config.getInitParameter(memberProxyToParam);
+ if (proxyTo == null || proxyTo.trim().length() == 0)
+ {
+ throw new UnavailableException(memberProxyToParam + " parameter is empty.");
+ }
+ _balancerMembers.add(new BalancerMember(balancerName,proxyTo));
+ }
+ }
+
+ private void initProxyPassReverse(ServletConfig config)
+ {
+ _proxyPassReverse = "true".equalsIgnoreCase(config.getInitParameter("ProxyPassReverse"));
+ }
+
+ private void postInit()
+ {
+ _roundRobinIterator = new RoundRobinIterator(_balancerMembers);
+ }
+
+ private Set<String> getBalancerNames(ServletConfig config) throws ServletException
+ {
+ Set<String> names = new HashSet<String>();
+ @SuppressWarnings("unchecked")
+ List<String> initParameterNames = Collections.list(config.getInitParameterNames());
+ for (String initParameterName : initParameterNames)
+ {
+ if (!initParameterName.startsWith(BALANCER_MEMBER_PREFIX))
+ {
+ continue;
+ }
+ int endOfNameIndex = initParameterName.lastIndexOf(".");
+ if (endOfNameIndex <= BALANCER_MEMBER_PREFIX.length())
+ {
+ throw new UnavailableException(initParameterName + " parameter does not provide a balancer member name");
+ }
+ names.add(initParameterName.substring(BALANCER_MEMBER_PREFIX.length(),endOfNameIndex));
+ }
+ return names;
+ }
+
+ @Override
+ protected HttpURI proxyHttpURI(HttpServletRequest request, String uri) throws MalformedURLException
+ {
+ BalancerMember balancerMember = selectBalancerMember(request);
+ try
+ {
+ URI dstUri = new URI(balancerMember.getProxyTo() + "/" + uri).normalize();
+ return new HttpURI(dstUri.toString());
+ }
+ catch (URISyntaxException e)
+ {
+ throw new MalformedURLException(e.getMessage());
+ }
+ }
+
+ private BalancerMember selectBalancerMember(HttpServletRequest request)
+ {
+ BalancerMember balancerMember = null;
+ if (_stickySessions)
+ {
+ String name = getBalancerMemberNameFromSessionId(request);
+ if (name != null)
+ {
+ balancerMember = findBalancerMemberByName(name);
+ if (balancerMember != null)
+ {
+ return balancerMember;
+ }
+ }
+ }
+ return _roundRobinIterator.next();
+ }
+
+ private BalancerMember findBalancerMemberByName(String name)
+ {
+ BalancerMember example = new BalancerMember(name,"");
+ for (BalancerMember balancerMember : _balancerMembers)
+ {
+ if (balancerMember.equals(example))
+ {
+ return balancerMember;
+ }
+ }
+ return null;
+ }
+
+ private String getBalancerMemberNameFromSessionId(HttpServletRequest request)
+ {
+ String name = getBalancerMemberNameFromSessionCookie(request);
+ if (name == null)
+ {
+ name = getBalancerMemberNameFromURL(request);
+ }
+ return name;
+ }
+
+ private String getBalancerMemberNameFromSessionCookie(HttpServletRequest request)
+ {
+ Cookie[] cookies = request.getCookies();
+ String name = null;
+ for (Cookie cookie : cookies)
+ {
+ if (JSESSIONID.equalsIgnoreCase(cookie.getName()))
+ {
+ name = extractBalancerMemberNameFromSessionId(cookie.getValue());
+ break;
+ }
+ }
+ return name;
+ }
+
+ private String getBalancerMemberNameFromURL(HttpServletRequest request)
+ {
+ String name = null;
+ String requestURI = request.getRequestURI();
+ int idx = requestURI.lastIndexOf(";");
+ if (idx != -1)
+ {
+ String requestURISuffix = requestURI.substring(idx);
+ if (requestURISuffix.startsWith(JSESSIONID_URL_PREFIX))
+ {
+ name = extractBalancerMemberNameFromSessionId(requestURISuffix.substring(JSESSIONID_URL_PREFIX.length()));
+ }
+ }
+ return name;
+ }
+
+ private String extractBalancerMemberNameFromSessionId(String sessionId)
+ {
+ String name = null;
+ int idx = sessionId.lastIndexOf(".");
+ if (idx != -1)
+ {
+ String sessionIdSuffix = sessionId.substring(idx + 1);
+ name = (sessionIdSuffix.length() > 0)?sessionIdSuffix:null;
+ }
+ return name;
+ }
+
+ @Override
+ protected String filterResponseHeaderValue(String headerName, String headerValue, HttpServletRequest request)
+ {
+ if (_proxyPassReverse && REVERSE_PROXY_HEADERS.contains(headerName))
+ {
+ HttpURI locationURI = new HttpURI(headerValue);
+ if (isAbsoluteLocation(locationURI) && isBackendLocation(locationURI))
+ {
+ Request jettyRequest = (Request)request;
+ URI reverseUri;
+ try
+ {
+ reverseUri = new URI(jettyRequest.getRootURL().append(locationURI.getCompletePath()).toString()).normalize();
+ return reverseUri.toURL().toString();
+ }
+ catch (Exception e)
+ {
+ _log.warn("Not filtering header response",e);
+ return headerValue;
+ }
+ }
+ }
+ return headerValue;
+ }
+
+ private boolean isBackendLocation(HttpURI locationURI)
+ {
+ for (BalancerMember balancerMember : _balancerMembers)
+ {
+ HttpURI backendURI = balancerMember.getBackendURI();
+ if (backendURI.getHost().equals(locationURI.getHost()) && backendURI.getScheme().equals(locationURI.getScheme())
+ && backendURI.getPort() == locationURI.getPort())
+ {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ private boolean isAbsoluteLocation(HttpURI locationURI)
+ {
+ return locationURI.getHost() != null;
+ }
+
+ @Override
+ public String getHostHeader()
+ {
+ throw new UnsupportedOperationException("HostHeader not supported in " + getClass().getName());
+ }
+
+ @Override
+ public void setHostHeader(String hostHeader)
+ {
+ throw new UnsupportedOperationException("HostHeader not supported in " + getClass().getName());
+ }
+
+ @Override
+ public boolean validateDestination(String host, String path)
+ {
+ return true;
+ }
+
+} \ No newline at end of file
diff --git a/jetty-servlets/src/main/java/org/eclipse/jetty/servlets/CrossOriginFilter.java b/jetty-servlets/src/main/java/org/eclipse/jetty/servlets/CrossOriginFilter.java
index bb57608c4b..6561166a18 100644
--- a/jetty-servlets/src/main/java/org/eclipse/jetty/servlets/CrossOriginFilter.java
+++ b/jetty-servlets/src/main/java/org/eclipse/jetty/servlets/CrossOriginFilter.java
@@ -54,15 +54,18 @@ import org.eclipse.jetty.util.log.Logger;
* and any 3 letter top-level domain (.com, .net, .org, etc.).</li>
* <li><b>allowedMethods</b>, a comma separated list of HTTP methods that
* are allowed to be used when accessing the resources. Default value is
- * <b>GET,POST</b></li>
+ * <b>GET,POST,HEAD</b></li>
* <li><b>allowedHeaders</b>, a comma separated list of HTTP headers that
* are allowed to be specified when accessing the resources. Default value
- * is <b>X-Requested-With</b></li>
+ * is <b>X-Requested-With,Content-Type,Accept,Origin</b></li>
* <li><b>preflightMaxAge</b>, the number of seconds that preflight requests
* can be cached by the client. Default value is <b>1800</b> seconds, or 30
* minutes</li>
* <li><b>allowCredentials</b>, a boolean indicating if the resource allows
* requests with credentials. Default value is <b>false</b></li>
+ * <li><b>exposeHeaders</b>, a comma separated list of HTTP headers that
+ * are allowed to be exposed on the client. Default value is the
+ * <b>empty list</b></li>
* </ul></p>
* <p>A typical configuration could be:
* <pre>
@@ -79,8 +82,6 @@ import org.eclipse.jetty.util.log.Logger;
* ...
* &lt;/web-app&gt;
* </pre></p>
- *
- * @version $Revision$ $Date$
*/
public class CrossOriginFilter implements Filter
{
@@ -96,12 +97,15 @@ public class CrossOriginFilter implements Filter
public static final String ACCESS_CONTROL_ALLOW_HEADERS_HEADER = "Access-Control-Allow-Headers";
public static final String ACCESS_CONTROL_MAX_AGE_HEADER = "Access-Control-Max-Age";
public static final String ACCESS_CONTROL_ALLOW_CREDENTIALS_HEADER = "Access-Control-Allow-Credentials";
+ public static final String ACCESS_CONTROL_EXPOSE_HEADERS_HEADER = "Access-Control-Expose-Headers";
// Implementation constants
public static final String ALLOWED_ORIGINS_PARAM = "allowedOrigins";
public static final String ALLOWED_METHODS_PARAM = "allowedMethods";
public static final String ALLOWED_HEADERS_PARAM = "allowedHeaders";
public static final String PREFLIGHT_MAX_AGE_PARAM = "preflightMaxAge";
public static final String ALLOW_CREDENTIALS_PARAM = "allowCredentials";
+ public static final String EXPOSED_HEADERS_PARAM = "exposedHeaders";
+ public static final String FORWARD_PREFLIGHT_PARAM = "forwardPreflight";
private static final String ANY_ORIGIN = "*";
private static final List<String> SIMPLE_HTTP_METHODS = Arrays.asList("GET", "POST", "HEAD");
@@ -109,8 +113,10 @@ public class CrossOriginFilter implements Filter
private List<String> allowedOrigins = new ArrayList<String>();
private List<String> allowedMethods = new ArrayList<String>();
private List<String> allowedHeaders = new ArrayList<String>();
- private int preflightMaxAge = 0;
+ private List<String> exposedHeaders = new ArrayList<String>();
+ private int preflightMaxAge;
private boolean allowCredentials;
+ private boolean forwardPreflight;
public void init(FilterConfig config) throws ServletException
{
@@ -163,6 +169,16 @@ public class CrossOriginFilter implements Filter
allowedCredentialsConfig = "true";
allowCredentials = Boolean.parseBoolean(allowedCredentialsConfig);
+ String exposedHeadersConfig = config.getInitParameter(EXPOSED_HEADERS_PARAM);
+ if (exposedHeadersConfig == null)
+ exposedHeadersConfig = "";
+ exposedHeaders.addAll(Arrays.asList(exposedHeadersConfig.split(",")));
+
+ String forwardPreflightConfig = config.getInitParameter(FORWARD_PREFLIGHT_PARAM);
+ if (forwardPreflightConfig == null)
+ forwardPreflightConfig = "true";
+ forwardPreflight = Boolean.parseBoolean(forwardPreflightConfig);
+
if (LOG.isDebugEnabled())
{
LOG.debug("Cross-origin filter configuration: " +
@@ -170,7 +186,10 @@ public class CrossOriginFilter implements Filter
ALLOWED_METHODS_PARAM + " = " + allowedMethodsConfig + ", " +
ALLOWED_HEADERS_PARAM + " = " + allowedHeadersConfig + ", " +
PREFLIGHT_MAX_AGE_PARAM + " = " + preflightMaxAgeConfig + ", " +
- ALLOW_CREDENTIALS_PARAM + " = " + allowedCredentialsConfig);
+ ALLOW_CREDENTIALS_PARAM + " = " + allowedCredentialsConfig + "," +
+ EXPOSED_HEADERS_PARAM + " = " + exposedHeadersConfig + "," +
+ FORWARD_PREFLIGHT_PARAM + " = " + forwardPreflightConfig
+ );
}
}
@@ -196,6 +215,10 @@ public class CrossOriginFilter implements Filter
{
LOG.debug("Cross-origin request to {} is a preflight cross-origin request", request.getRequestURI());
handlePreflightResponse(request, response, origin);
+ if (forwardPreflight)
+ LOG.debug("Preflight cross-origin request to {} forwarded to application", request.getRequestURI());
+ else
+ return;
}
else
{
@@ -305,6 +328,8 @@ public class CrossOriginFilter implements Filter
response.setHeader(ACCESS_CONTROL_ALLOW_ORIGIN_HEADER, origin);
if (allowCredentials)
response.setHeader(ACCESS_CONTROL_ALLOW_CREDENTIALS_HEADER, "true");
+ if (!exposedHeaders.isEmpty())
+ response.setHeader(ACCESS_CONTROL_EXPOSE_HEADERS_HEADER, commify(exposedHeaders));
}
private void handlePreflightResponse(HttpServletRequest request, HttpServletResponse response, String origin)
diff --git a/jetty-servlets/src/main/java/org/eclipse/jetty/servlets/GzipFilter.java b/jetty-servlets/src/main/java/org/eclipse/jetty/servlets/GzipFilter.java
index 8b9a9c76d3..2837be9c97 100644
--- a/jetty-servlets/src/main/java/org/eclipse/jetty/servlets/GzipFilter.java
+++ b/jetty-servlets/src/main/java/org/eclipse/jetty/servlets/GzipFilter.java
@@ -201,7 +201,11 @@ public class GzipFilter extends UserAgentFilter
{
HttpServletRequest request=(HttpServletRequest)req;
HttpServletResponse response=(HttpServletResponse)res;
+
+ // Inform caches that responses may vary according to Accept-Encoding
+ response.setHeader("Vary","Accept-Encoding");
+ // Should we vary this response according to Accept-Encoding
String compressionType = selectCompression(request.getHeader("accept-encoding"));
if (compressionType!=null && !response.containsHeader("Content-Encoding") && !HttpMethods.HEAD.equalsIgnoreCase(request.getMethod()))
{
diff --git a/jetty-servlets/src/main/java/org/eclipse/jetty/servlets/ProxyServlet.java b/jetty-servlets/src/main/java/org/eclipse/jetty/servlets/ProxyServlet.java
index 7fa971838a..6687903a6a 100644
--- a/jetty-servlets/src/main/java/org/eclipse/jetty/servlets/ProxyServlet.java
+++ b/jetty-servlets/src/main/java/org/eclipse/jetty/servlets/ProxyServlet.java
@@ -483,13 +483,20 @@ public class ProxyServlet implements Servlet
@Override
protected void onResponseHeader(Buffer name, Buffer value) throws IOException
{
- String s = name.toString().toLowerCase();
+ String nameString = name.toString();
+ String s = nameString.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());
+ String filteredHeaderValue = filterResponseHeaderValue(nameString,value.toString(),request);
+ if (filteredHeaderValue != null && filteredHeaderValue.trim().length() > 0)
+ {
+ if (debug != 0)
+ _log.debug(debug + " " + name + ": (filtered): " + filteredHeaderValue);
+ response.addHeader(nameString,filteredHeaderValue);
+ }
}
else if (debug != 0)
_log.debug(debug + " " + name + "! " + value);
@@ -786,8 +793,22 @@ public class ProxyServlet implements Servlet
}
/**
+ * Extension point for remote server response header filtering. The default implementation returns the header value as is. If null is returned, this header
+ * won't be forwarded back to the client.
+ *
+ * @param headerName
+ * @param headerValue
+ * @param request
+ * @return filteredHeaderValue
+ */
+ protected String filterResponseHeaderValue(String headerName, String headerValue, HttpServletRequest request)
+ {
+ return headerValue;
+ }
+
+ /**
* Transparent Proxy.
- *
+ *
* This convenience extension to ProxyServlet configures the servlet as a transparent proxy. The servlet is configured with init parameters:
* <ul>
* <li>ProxyTo - a URI like http://host:80/context to which the request is proxied.
@@ -795,7 +816,7 @@ public class ProxyServlet implements Servlet
* </ul>
* For example, if a request was received at /foo/bar and the ProxyTo was http://host:80/context and the Prefix was /foo, then the request would be proxied
* to http://host:80/context/bar
- *
+ *
*/
public static class Transparent extends ProxyServlet
{
diff --git a/jetty-servlets/src/test/java/org/eclipse/jetty/servlets/AbstractBalancerServletTest.java b/jetty-servlets/src/test/java/org/eclipse/jetty/servlets/AbstractBalancerServletTest.java
new file mode 100644
index 0000000000..e798396adc
--- /dev/null
+++ b/jetty-servlets/src/test/java/org/eclipse/jetty/servlets/AbstractBalancerServletTest.java
@@ -0,0 +1,157 @@
+package org.eclipse.jetty.servlets;
+
+//========================================================================
+//Copyright (c) 2012 Intalio, Inc.
+//------------------------------------------------------------------------
+//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 javax.servlet.http.HttpServlet;
+
+import org.eclipse.jetty.client.ContentExchange;
+import org.eclipse.jetty.client.HttpClient;
+import org.eclipse.jetty.http.HttpCookie;
+import org.eclipse.jetty.http.HttpMethods;
+import org.eclipse.jetty.io.Buffer;
+import org.eclipse.jetty.server.Server;
+import org.eclipse.jetty.server.nio.SelectChannelConnector;
+import org.eclipse.jetty.server.session.HashSessionIdManager;
+import org.eclipse.jetty.servlet.ServletContextHandler;
+import org.eclipse.jetty.servlet.ServletHolder;
+import org.junit.After;
+import org.junit.Before;
+
+
+public abstract class AbstractBalancerServletTest
+{
+
+ private boolean _stickySessions;
+
+ private Server _node1;
+
+ private Server _node2;
+
+ private Server _balancerServer;
+
+ private HttpClient _httpClient;
+
+ @Before
+ public void setUp() throws Exception
+ {
+ _httpClient = new HttpClient();
+ _httpClient.registerListener("org.eclipse.jetty.client.RedirectListener");
+ _httpClient.start();
+ }
+
+ @After
+ public void tearDown() throws Exception
+ {
+ stopServer(_node1);
+ stopServer(_node2);
+ stopServer(_balancerServer);
+ _httpClient.stop();
+ }
+
+ private void stopServer(Server server)
+ {
+ try
+ {
+ server.stop();
+ }
+ catch (Exception e)
+ {
+ // Do nothing
+ }
+ }
+
+ protected void setStickySessions(boolean stickySessions)
+ {
+ _stickySessions = stickySessions;
+ }
+
+ protected void startBalancer(Class<? extends HttpServlet> httpServletClass) throws Exception
+ {
+ _node1 = createServer(new ServletHolder(httpServletClass.newInstance()),"/pipo","/molo/*");
+ setSessionIdManager(_node1,"node1");
+ _node1.start();
+
+ _node2 = createServer(new ServletHolder(httpServletClass.newInstance()),"/pipo","/molo/*");
+ setSessionIdManager(_node2,"node2");
+ _node2.start();
+
+ BalancerServlet balancerServlet = new BalancerServlet();
+ ServletHolder balancerServletHolder = new ServletHolder(balancerServlet);
+ balancerServletHolder.setInitParameter("StickySessions",String.valueOf(_stickySessions));
+ balancerServletHolder.setInitParameter("ProxyPassReverse","true");
+ balancerServletHolder.setInitParameter("BalancerMember." + "node1" + ".ProxyTo","http://localhost:" + getServerPort(_node1));
+ balancerServletHolder.setInitParameter("BalancerMember." + "node2" + ".ProxyTo","http://localhost:" + getServerPort(_node2));
+
+ _balancerServer = createServer(balancerServletHolder,"/pipo","/molo/*");
+ _balancerServer.start();
+ }
+
+ private Server createServer(ServletHolder servletHolder, String appContext, String servletUrlPattern)
+ {
+ Server server = new Server();
+ SelectChannelConnector httpConnector = new SelectChannelConnector();
+ server.addConnector(httpConnector);
+
+ ServletContextHandler context = new ServletContextHandler(ServletContextHandler.SESSIONS);
+ context.setContextPath(appContext);
+ server.setHandler(context);
+
+ context.addServlet(servletHolder,servletUrlPattern);
+
+ return server;
+ }
+
+ private void setSessionIdManager(Server node, String nodeName)
+ {
+ HashSessionIdManager sessionIdManager = new HashSessionIdManager();
+ sessionIdManager.setWorkerName(nodeName);
+ node.setSessionIdManager(sessionIdManager);
+ }
+
+ private int getServerPort(Server node)
+ {
+ return node.getConnectors()[0].getLocalPort();
+ }
+
+ protected byte[] sendRequestToBalancer(String requestUri) throws IOException, InterruptedException
+ {
+ ContentExchange exchange = new ContentExchange()
+ {
+ @Override
+ protected void onResponseHeader(Buffer name, Buffer value) throws IOException
+ {
+ // Cookie persistence
+ if (name.toString().equals("Set-Cookie"))
+ {
+ String cookieVal = value.toString();
+ if (cookieVal.startsWith("JSESSIONID="))
+ {
+ String jsessionid = cookieVal.split(";")[0].substring("JSESSIONID=".length());
+ _httpClient.getDestination(getAddress(),false).addCookie(new HttpCookie("JSESSIONID",jsessionid));
+ }
+ }
+ }
+ };
+ exchange.setURL("http://localhost:" + getServerPort(_balancerServer) + "/pipo/molo/" + requestUri);
+ exchange.setMethod(HttpMethods.GET);
+
+ _httpClient.send(exchange);
+ exchange.waitForDone();
+
+ return exchange.getResponseContentBytes();
+ }
+
+}
diff --git a/jetty-servlets/src/test/java/org/eclipse/jetty/servlets/AbstractDoSFilterTest.java b/jetty-servlets/src/test/java/org/eclipse/jetty/servlets/AbstractDoSFilterTest.java
index c2b09772b7..5d09cf114d 100644
--- a/jetty-servlets/src/test/java/org/eclipse/jetty/servlets/AbstractDoSFilterTest.java
+++ b/jetty-servlets/src/test/java/org/eclipse/jetty/servlets/AbstractDoSFilterTest.java
@@ -1,4 +1,16 @@
package org.eclipse.jetty.servlets;
+//========================================================================
+//Copyright 2011-2012 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.junit.Assert.assertTrue;
diff --git a/jetty-servlets/src/test/java/org/eclipse/jetty/servlets/BalancerServletTest.java b/jetty-servlets/src/test/java/org/eclipse/jetty/servlets/BalancerServletTest.java
new file mode 100644
index 0000000000..9513895fc6
--- /dev/null
+++ b/jetty-servlets/src/test/java/org/eclipse/jetty/servlets/BalancerServletTest.java
@@ -0,0 +1,129 @@
+package org.eclipse.jetty.servlets;
+//========================================================================
+//Copyright (c) 2012 Intalio, Inc.
+//------------------------------------------------------------------------
+//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.*;
+
+import java.io.BufferedReader;
+import java.io.ByteArrayInputStream;
+import java.io.IOException;
+import java.io.InputStreamReader;
+
+import javax.servlet.ServletException;
+import javax.servlet.http.HttpServlet;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import org.junit.Test;
+
+/**
+ *
+ */
+public class BalancerServletTest extends AbstractBalancerServletTest
+{
+
+ @Test
+ public void testRoundRobinBalancer() throws Exception
+ {
+ setStickySessions(false);
+ startBalancer(CounterServlet.class);
+
+ for (int i = 0; i < 10; i++)
+ {
+ byte[] responseBytes = sendRequestToBalancer("/");
+ String returnedCounter = readFirstLine(responseBytes);
+ // RR : response should increment every other request
+ String expectedCounter = String.valueOf(i / 2);
+ assertEquals(expectedCounter,returnedCounter);
+ }
+ }
+
+ @Test
+ public void testStickySessionsBalancer() throws Exception
+ {
+ setStickySessions(true);
+ startBalancer(CounterServlet.class);
+
+ for (int i = 0; i < 10; i++)
+ {
+ byte[] responseBytes = sendRequestToBalancer("/");
+ String returnedCounter = readFirstLine(responseBytes);
+ // RR : response should increment on each request
+ String expectedCounter = String.valueOf(i);
+ assertEquals(expectedCounter,returnedCounter);
+ }
+ }
+
+ @Test
+ public void testProxyPassReverse() throws Exception
+ {
+ setStickySessions(false);
+ startBalancer(RelocationServlet.class);
+
+ byte[] responseBytes = sendRequestToBalancer("index.html");
+ String msg = readFirstLine(responseBytes);
+ assertEquals("success",msg);
+ }
+
+ private String readFirstLine(byte[] responseBytes) throws IOException
+ {
+ BufferedReader reader = new BufferedReader(new InputStreamReader(new ByteArrayInputStream(responseBytes)));
+ return reader.readLine();
+ }
+
+ @SuppressWarnings("serial")
+ public static final class CounterServlet extends HttpServlet
+ {
+
+ private int counter;
+
+ @Override
+ public void init() throws ServletException
+ {
+ counter = 0;
+ }
+
+ @Override
+ protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException
+ {
+ // Force session creation
+ req.getSession();
+ resp.setContentType("text/plain");
+ resp.getWriter().println(counter++);
+ }
+ }
+
+ @SuppressWarnings("serial")
+ public static final class RelocationServlet extends HttpServlet
+ {
+ @Override
+ protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException
+ {
+ if (req.getRequestURI().endsWith("/index.html"))
+ {
+ resp.sendRedirect("http://localhost:" + req.getLocalPort() + req.getContextPath() + req.getServletPath() + "/other.html?secret=pipo%20molo");
+ return;
+ }
+ resp.setContentType("text/plain");
+ if ("pipo molo".equals(req.getParameter("secret")))
+ {
+ resp.getWriter().println("success");
+ }
+ else
+ {
+ resp.getWriter().println("failure");
+ }
+ }
+ }
+
+}
diff --git a/jetty-servlets/src/test/java/org/eclipse/jetty/servlets/CrossOriginFilterTest.java b/jetty-servlets/src/test/java/org/eclipse/jetty/servlets/CrossOriginFilterTest.java
index ff78a629ff..c250165550 100644
--- a/jetty-servlets/src/test/java/org/eclipse/jetty/servlets/CrossOriginFilterTest.java
+++ b/jetty-servlets/src/test/java/org/eclipse/jetty/servlets/CrossOriginFilterTest.java
@@ -1,3 +1,16 @@
+// ========================================================================
+// Copyright 2011-2012 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.servlets;
import java.io.IOException;
@@ -374,6 +387,51 @@ public class CrossOriginFilterTest
Assert.assertTrue(latch.await(1, TimeUnit.SECONDS));
}
+ @Test
+ public void testSimpleRequestWithExposedHeaders() throws Exception
+ {
+ FilterHolder filterHolder = new FilterHolder(new CrossOriginFilter());
+ filterHolder.setInitParameter("exposedHeaders", "Content-Length");
+ tester.getContext().addFilter(filterHolder, "/*", EnumSet.of(DispatcherType.REQUEST));
+
+ CountDownLatch latch = new CountDownLatch(1);
+ tester.getContext().addServlet(new ServletHolder(new ResourceServlet(latch)), "/*");
+
+ String request = "" +
+ "GET / HTTP/1.1\r\n" +
+ "Host: localhost\r\n" +
+ "Origin: http://localhost\r\n" +
+ "\r\n";
+ String response = tester.getResponses(request);
+ Assert.assertTrue(response.contains("HTTP/1.1 200"));
+ Assert.assertTrue(response.contains(CrossOriginFilter.ACCESS_CONTROL_EXPOSE_HEADERS_HEADER));
+ Assert.assertTrue(latch.await(1, TimeUnit.SECONDS));
+ }
+
+ @Test
+ public void testForwardPreflightRequest() throws Exception
+ {
+ FilterHolder filterHolder = new FilterHolder(new CrossOriginFilter());
+ filterHolder.setInitParameter(CrossOriginFilter.ALLOWED_METHODS_PARAM, "PUT");
+ filterHolder.setInitParameter(CrossOriginFilter.FORWARD_PREFLIGHT_PARAM, "false");
+ tester.getContext().addFilter(filterHolder, "/*", FilterMapping.DEFAULT);
+
+ CountDownLatch latch = new CountDownLatch(1);
+ tester.getContext().addServlet(new ServletHolder(new ResourceServlet(latch)), "/*");
+
+ // Preflight request
+ String request = "" +
+ "OPTIONS / HTTP/1.1\r\n" +
+ "Host: localhost\r\n" +
+ CrossOriginFilter.ACCESS_CONTROL_REQUEST_METHOD_HEADER + ": PUT\r\n" +
+ "Origin: http://localhost\r\n" +
+ "\r\n";
+ String response = tester.getResponses(request);
+ Assert.assertTrue(response.contains("HTTP/1.1 200"));
+ Assert.assertTrue(response.contains(CrossOriginFilter.ACCESS_CONTROL_ALLOW_METHODS_HEADER));
+ Assert.assertFalse(latch.await(1, TimeUnit.SECONDS));
+ }
+
public static class ResourceServlet extends HttpServlet
{
private static final long serialVersionUID = 1L;
diff --git a/jetty-servlets/src/test/java/org/eclipse/jetty/servlets/DoSFilterTest.java b/jetty-servlets/src/test/java/org/eclipse/jetty/servlets/DoSFilterTest.java
index 6f89e0f0eb..eee5518c3a 100644
--- a/jetty-servlets/src/test/java/org/eclipse/jetty/servlets/DoSFilterTest.java
+++ b/jetty-servlets/src/test/java/org/eclipse/jetty/servlets/DoSFilterTest.java
@@ -1,15 +1,14 @@
-// ========================================================================
-// Copyright 2009 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.
+//========================================================================
+//Copyright 2011-2012 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.servlets;
diff --git a/jetty-servlets/src/test/java/org/eclipse/jetty/servlets/GzipFilterContentLengthTest.java b/jetty-servlets/src/test/java/org/eclipse/jetty/servlets/GzipFilterContentLengthTest.java
index c752591bc2..60307270b4 100644
--- a/jetty-servlets/src/test/java/org/eclipse/jetty/servlets/GzipFilterContentLengthTest.java
+++ b/jetty-servlets/src/test/java/org/eclipse/jetty/servlets/GzipFilterContentLengthTest.java
@@ -1,4 +1,16 @@
package org.eclipse.jetty.servlets;
+//========================================================================
+//Copyright 2011-2012 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.File;
import java.util.Arrays;
diff --git a/jetty-servlets/src/test/java/org/eclipse/jetty/servlets/GzipFilterDefaultNoRecompressTest.java b/jetty-servlets/src/test/java/org/eclipse/jetty/servlets/GzipFilterDefaultNoRecompressTest.java
index a890b96b62..8920bf08b6 100644
--- a/jetty-servlets/src/test/java/org/eclipse/jetty/servlets/GzipFilterDefaultNoRecompressTest.java
+++ b/jetty-servlets/src/test/java/org/eclipse/jetty/servlets/GzipFilterDefaultNoRecompressTest.java
@@ -1,4 +1,16 @@
package org.eclipse.jetty.servlets;
+//========================================================================
+//Copyright 2011-2012 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.File;
import java.io.IOException;
diff --git a/jetty-servlets/src/test/java/org/eclipse/jetty/servlets/GzipFilterDefaultTest.java b/jetty-servlets/src/test/java/org/eclipse/jetty/servlets/GzipFilterDefaultTest.java
index 8fd8a0336f..38496601c6 100644
--- a/jetty-servlets/src/test/java/org/eclipse/jetty/servlets/GzipFilterDefaultTest.java
+++ b/jetty-servlets/src/test/java/org/eclipse/jetty/servlets/GzipFilterDefaultTest.java
@@ -1,4 +1,16 @@
package org.eclipse.jetty.servlets;
+//========================================================================
+//Copyright 2011-2012 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.util.Arrays;
diff --git a/jetty-servlets/src/test/java/org/eclipse/jetty/servlets/GzipWithPipeliningTest.java b/jetty-servlets/src/test/java/org/eclipse/jetty/servlets/GzipWithPipeliningTest.java
index 631864af8d..7a1242eb48 100644
--- a/jetty-servlets/src/test/java/org/eclipse/jetty/servlets/GzipWithPipeliningTest.java
+++ b/jetty-servlets/src/test/java/org/eclipse/jetty/servlets/GzipWithPipeliningTest.java
@@ -1,4 +1,16 @@
package org.eclipse.jetty.servlets;
+//========================================================================
+//Copyright 2011-2012 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.hamcrest.Matchers.containsString;
import static org.hamcrest.Matchers.greaterThan;
diff --git a/jetty-servlets/src/test/java/org/eclipse/jetty/servlets/PipelineHelper.java b/jetty-servlets/src/test/java/org/eclipse/jetty/servlets/PipelineHelper.java
index ad58c1bad6..3ea4641cf9 100644
--- a/jetty-servlets/src/test/java/org/eclipse/jetty/servlets/PipelineHelper.java
+++ b/jetty-servlets/src/test/java/org/eclipse/jetty/servlets/PipelineHelper.java
@@ -1,4 +1,16 @@
package org.eclipse.jetty.servlets;
+//========================================================================
+//Copyright 2011-2012 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;
diff --git a/jetty-servlets/src/test/java/org/eclipse/jetty/servlets/ProxyServletTest.java b/jetty-servlets/src/test/java/org/eclipse/jetty/servlets/ProxyServletTest.java
index 80e1fe396f..04f06623fb 100644
--- a/jetty-servlets/src/test/java/org/eclipse/jetty/servlets/ProxyServletTest.java
+++ b/jetty-servlets/src/test/java/org/eclipse/jetty/servlets/ProxyServletTest.java
@@ -1,4 +1,16 @@
package org.eclipse.jetty.servlets;
+//========================================================================
+//Copyright 2011-2012 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.File;
import java.io.FileInputStream;
diff --git a/jetty-servlets/src/test/java/org/eclipse/jetty/servlets/gzip/GzipTester.java b/jetty-servlets/src/test/java/org/eclipse/jetty/servlets/gzip/GzipTester.java
index aadaa20fa8..7b096319d9 100644
--- a/jetty-servlets/src/test/java/org/eclipse/jetty/servlets/gzip/GzipTester.java
+++ b/jetty-servlets/src/test/java/org/eclipse/jetty/servlets/gzip/GzipTester.java
@@ -1,4 +1,16 @@
package org.eclipse.jetty.servlets.gzip;
+//========================================================================
+//Copyright 2011-2012 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.hamcrest.Matchers.containsString;
import static org.hamcrest.Matchers.equalTo;
diff --git a/jetty-servlets/src/test/java/org/eclipse/jetty/servlets/gzip/Hex.java b/jetty-servlets/src/test/java/org/eclipse/jetty/servlets/gzip/Hex.java
index ee17583c92..3d1608f7a9 100644
--- a/jetty-servlets/src/test/java/org/eclipse/jetty/servlets/gzip/Hex.java
+++ b/jetty-servlets/src/test/java/org/eclipse/jetty/servlets/gzip/Hex.java
@@ -1,4 +1,16 @@
package org.eclipse.jetty.servlets.gzip;
+//========================================================================
+//Copyright 2011-2012 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.
+//========================================================================
public final class Hex
{
diff --git a/jetty-servlets/src/test/java/org/eclipse/jetty/servlets/gzip/NoOpOutputStream.java b/jetty-servlets/src/test/java/org/eclipse/jetty/servlets/gzip/NoOpOutputStream.java
index 0a3c857a0a..bb457d7682 100644
--- a/jetty-servlets/src/test/java/org/eclipse/jetty/servlets/gzip/NoOpOutputStream.java
+++ b/jetty-servlets/src/test/java/org/eclipse/jetty/servlets/gzip/NoOpOutputStream.java
@@ -1,4 +1,16 @@
package org.eclipse.jetty.servlets.gzip;
+//========================================================================
+//Copyright 2011-2012 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.OutputStream;
diff --git a/jetty-servlets/src/test/java/org/eclipse/jetty/servlets/gzip/TestDirContentServlet.java b/jetty-servlets/src/test/java/org/eclipse/jetty/servlets/gzip/TestDirContentServlet.java
index 440528b332..4b95545e99 100644
--- a/jetty-servlets/src/test/java/org/eclipse/jetty/servlets/gzip/TestDirContentServlet.java
+++ b/jetty-servlets/src/test/java/org/eclipse/jetty/servlets/gzip/TestDirContentServlet.java
@@ -1,4 +1,16 @@
package org.eclipse.jetty.servlets.gzip;
+//========================================================================
+//Copyright 2011-2012 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.ByteArrayOutputStream;
import java.io.File;
diff --git a/jetty-servlets/src/test/java/org/eclipse/jetty/servlets/gzip/TestMinGzipSizeServlet.java b/jetty-servlets/src/test/java/org/eclipse/jetty/servlets/gzip/TestMinGzipSizeServlet.java
index 3a3c9897f6..7b071cf2e0 100644
--- a/jetty-servlets/src/test/java/org/eclipse/jetty/servlets/gzip/TestMinGzipSizeServlet.java
+++ b/jetty-servlets/src/test/java/org/eclipse/jetty/servlets/gzip/TestMinGzipSizeServlet.java
@@ -1,4 +1,16 @@
package org.eclipse.jetty.servlets.gzip;
+//========================================================================
+//Copyright 2011-2012 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;
diff --git a/jetty-servlets/src/test/java/org/eclipse/jetty/servlets/gzip/TestServletLengthStreamTypeWrite.java b/jetty-servlets/src/test/java/org/eclipse/jetty/servlets/gzip/TestServletLengthStreamTypeWrite.java
index 5c5cd4810b..01873fedcc 100644
--- a/jetty-servlets/src/test/java/org/eclipse/jetty/servlets/gzip/TestServletLengthStreamTypeWrite.java
+++ b/jetty-servlets/src/test/java/org/eclipse/jetty/servlets/gzip/TestServletLengthStreamTypeWrite.java
@@ -1,4 +1,16 @@
package org.eclipse.jetty.servlets.gzip;
+//========================================================================
+//Copyright 2011-2012 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;
diff --git a/jetty-servlets/src/test/java/org/eclipse/jetty/servlets/gzip/TestServletLengthTypeStreamWrite.java b/jetty-servlets/src/test/java/org/eclipse/jetty/servlets/gzip/TestServletLengthTypeStreamWrite.java
index 4cf6a4acaf..aa7b090889 100644
--- a/jetty-servlets/src/test/java/org/eclipse/jetty/servlets/gzip/TestServletLengthTypeStreamWrite.java
+++ b/jetty-servlets/src/test/java/org/eclipse/jetty/servlets/gzip/TestServletLengthTypeStreamWrite.java
@@ -1,4 +1,16 @@
package org.eclipse.jetty.servlets.gzip;
+//========================================================================
+//Copyright 2011-2012 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;
diff --git a/jetty-servlets/src/test/java/org/eclipse/jetty/servlets/gzip/TestServletStreamLengthTypeWrite.java b/jetty-servlets/src/test/java/org/eclipse/jetty/servlets/gzip/TestServletStreamLengthTypeWrite.java
index f10d5305ce..271f143217 100644
--- a/jetty-servlets/src/test/java/org/eclipse/jetty/servlets/gzip/TestServletStreamLengthTypeWrite.java
+++ b/jetty-servlets/src/test/java/org/eclipse/jetty/servlets/gzip/TestServletStreamLengthTypeWrite.java
@@ -1,4 +1,16 @@
package org.eclipse.jetty.servlets.gzip;
+//========================================================================
+//Copyright 2011-2012 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;
diff --git a/jetty-servlets/src/test/java/org/eclipse/jetty/servlets/gzip/TestServletStreamTypeLengthWrite.java b/jetty-servlets/src/test/java/org/eclipse/jetty/servlets/gzip/TestServletStreamTypeLengthWrite.java
index efd5bcdc12..9c85cc139a 100644
--- a/jetty-servlets/src/test/java/org/eclipse/jetty/servlets/gzip/TestServletStreamTypeLengthWrite.java
+++ b/jetty-servlets/src/test/java/org/eclipse/jetty/servlets/gzip/TestServletStreamTypeLengthWrite.java
@@ -1,4 +1,16 @@
package org.eclipse.jetty.servlets.gzip;
+//========================================================================
+//Copyright 2011-2012 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;
diff --git a/jetty-servlets/src/test/java/org/eclipse/jetty/servlets/gzip/TestServletTypeLengthStreamWrite.java b/jetty-servlets/src/test/java/org/eclipse/jetty/servlets/gzip/TestServletTypeLengthStreamWrite.java
index 7551d4d4a6..9185cd3e03 100644
--- a/jetty-servlets/src/test/java/org/eclipse/jetty/servlets/gzip/TestServletTypeLengthStreamWrite.java
+++ b/jetty-servlets/src/test/java/org/eclipse/jetty/servlets/gzip/TestServletTypeLengthStreamWrite.java
@@ -1,4 +1,16 @@
package org.eclipse.jetty.servlets.gzip;
+//========================================================================
+//Copyright 2011-2012 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;
diff --git a/jetty-servlets/src/test/java/org/eclipse/jetty/servlets/gzip/TestServletTypeStreamLengthWrite.java b/jetty-servlets/src/test/java/org/eclipse/jetty/servlets/gzip/TestServletTypeStreamLengthWrite.java
index 9efc34d43e..87f04c204d 100644
--- a/jetty-servlets/src/test/java/org/eclipse/jetty/servlets/gzip/TestServletTypeStreamLengthWrite.java
+++ b/jetty-servlets/src/test/java/org/eclipse/jetty/servlets/gzip/TestServletTypeStreamLengthWrite.java
@@ -1,4 +1,16 @@
package org.eclipse.jetty.servlets.gzip;
+//========================================================================
+//Copyright 2011-2012 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;
diff --git a/jetty-servlets/src/test/java/org/eclipse/jetty/servlets/gzip/TestStaticMimeTypeServlet.java b/jetty-servlets/src/test/java/org/eclipse/jetty/servlets/gzip/TestStaticMimeTypeServlet.java
index 298fc0aa9b..fd85fc3b73 100644
--- a/jetty-servlets/src/test/java/org/eclipse/jetty/servlets/gzip/TestStaticMimeTypeServlet.java
+++ b/jetty-servlets/src/test/java/org/eclipse/jetty/servlets/gzip/TestStaticMimeTypeServlet.java
@@ -1,4 +1,16 @@
package org.eclipse.jetty.servlets.gzip;
+//========================================================================
+//Copyright 2011-2012 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;
diff --git a/jetty-spdy/pom.xml b/jetty-spdy/pom.xml
index 7517551c11..d03be44993 100644
--- a/jetty-spdy/pom.xml
+++ b/jetty-spdy/pom.xml
@@ -13,7 +13,7 @@
<name>Jetty :: SPDY :: Parent</name>
<properties>
- <npn.version>1.0.0.v20120402</npn.version>
+ <npn.version>1.1.0.v20120525</npn.version>
</properties>
<modules>
diff --git a/jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/ByteBufferPool.java b/jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/ByteBufferPool.java
index 68eac61ac0..e2964cc0f0 100644
--- a/jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/ByteBufferPool.java
+++ b/jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/ByteBufferPool.java
@@ -1,18 +1,15 @@
-/*
- * Copyright (c) 2012 the original author or authors.
- *
- * 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.
- */
+//========================================================================
+//Copyright 2012 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.spdy;
diff --git a/jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/CompressionDictionary.java b/jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/CompressionDictionary.java
index 0aa024d30f..8b8b83a134 100644
--- a/jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/CompressionDictionary.java
+++ b/jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/CompressionDictionary.java
@@ -1,18 +1,15 @@
-/*
- * Copyright (c) 2012 the original author or authors.
- *
- * 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.
- */
+//========================================================================
+//Copyright 2011-2012 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.spdy;
diff --git a/jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/CompressionFactory.java b/jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/CompressionFactory.java
index f81a5b3f49..620c24ac10 100644
--- a/jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/CompressionFactory.java
+++ b/jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/CompressionFactory.java
@@ -1,18 +1,15 @@
-/*
- * Copyright (c) 2012 the original author or authors.
- *
- * 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.
- */
+//========================================================================
+//Copyright 2011-2012 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.spdy;
diff --git a/jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/Controller.java b/jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/Controller.java
index 998efd5774..75e26ef934 100644
--- a/jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/Controller.java
+++ b/jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/Controller.java
@@ -1,18 +1,15 @@
-/*
- * Copyright (c) 2012 the original author or authors.
- *
- * 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.
- */
+//========================================================================
+//Copyright 2011-2012 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.spdy;
diff --git a/jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/FlowControlStrategy.java b/jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/FlowControlStrategy.java
new file mode 100644
index 0000000000..c08bc42121
--- /dev/null
+++ b/jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/FlowControlStrategy.java
@@ -0,0 +1,86 @@
+//========================================================================
+//Copyright 2011-2012 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.spdy;
+
+import org.eclipse.jetty.spdy.api.DataInfo;
+
+// TODO: add methods that tell how much written and whether we're TCP congested ?
+public interface FlowControlStrategy
+{
+ public int getWindowSize(ISession session);
+
+ public void setWindowSize(ISession session, int windowSize);
+
+ public void onNewStream(ISession session, IStream stream);
+
+ public void onWindowUpdate(ISession session, IStream stream, int delta);
+
+ public void updateWindow(ISession session, IStream stream, int delta);
+
+ public void onDataReceived(ISession session, IStream stream, DataInfo dataInfo);
+
+ public void onDataConsumed(ISession session, IStream stream, DataInfo dataInfo, int delta);
+
+ public static class None implements FlowControlStrategy
+ {
+ private volatile int windowSize;
+
+ public None()
+ {
+ this(65536);
+ }
+
+ public None(int windowSize)
+ {
+ this.windowSize = windowSize;
+ }
+
+ @Override
+ public int getWindowSize(ISession session)
+ {
+ return windowSize;
+ }
+
+ @Override
+ public void setWindowSize(ISession session, int windowSize)
+ {
+ this.windowSize = windowSize;
+ }
+
+ @Override
+ public void onNewStream(ISession session, IStream stream)
+ {
+ stream.updateWindowSize(windowSize);
+ }
+
+ @Override
+ public void onWindowUpdate(ISession session, IStream stream, int delta)
+ {
+ }
+
+ @Override
+ public void updateWindow(ISession session, IStream stream, int delta)
+ {
+ }
+
+ @Override
+ public void onDataReceived(ISession session, IStream stream, DataInfo dataInfo)
+ {
+ }
+
+ @Override
+ public void onDataConsumed(ISession session, IStream stream, DataInfo dataInfo, int delta)
+ {
+ }
+ }
+}
diff --git a/jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/ISession.java b/jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/ISession.java
index c69af21838..41bbfd7da8 100644
--- a/jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/ISession.java
+++ b/jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/ISession.java
@@ -1,18 +1,15 @@
-/*
- * Copyright (c) 2012 the original author or authors.
- *
- * 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.
- */
+//========================================================================
+//Copyright 2011-2012 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.spdy;
diff --git a/jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/IStream.java b/jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/IStream.java
index 07934c16e1..ad75f406a7 100644
--- a/jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/IStream.java
+++ b/jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/IStream.java
@@ -1,29 +1,24 @@
-/*
- * Copyright (c) 2012 the original author or authors.
- *
- * 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.
- */
+//========================================================================
+//Copyright 2011-2012 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.spdy;
-import java.nio.ByteBuffer;
-
+import org.eclipse.jetty.spdy.api.DataInfo;
import org.eclipse.jetty.spdy.api.SessionFrameListener;
import org.eclipse.jetty.spdy.api.Stream;
import org.eclipse.jetty.spdy.api.StreamFrameListener;
import org.eclipse.jetty.spdy.api.SynInfo;
import org.eclipse.jetty.spdy.frames.ControlFrame;
-import org.eclipse.jetty.spdy.frames.DataFrame;
/**
* <p>The internal interface that represents a stream.</p>
@@ -77,37 +72,36 @@ public interface IStream extends Stream
* for example by updating the stream's state or by calling listeners.</p>
*
* @param frame the control frame to process
- * @see #process(DataFrame, ByteBuffer)
+ * @see #process(DataInfo)
*/
public void process(ControlFrame frame);
/**
- * <p>Processes the given data frame along with the given byte buffer,
+ * <p>Processes the given {@code dataInfo},
* for example by updating the stream's state or by calling listeners.</p>
*
- * @param frame the data frame to process
- * @param data the byte buffer to process
+ * @param dataInfo the DataInfo to process
* @see #process(ControlFrame)
*/
- public void process(DataFrame frame, ByteBuffer data);
-
+ public void process(DataInfo dataInfo);
+
/**
* <p>Associate the given {@link IStream} to this {@link IStream}.</p>
- *
+ *
* @param stream the stream to associate with this stream
*/
public void associate(IStream stream);
-
+
/**
* <p>remove the given associated {@link IStream} from this stream</p>
- *
+ *
* @param stream the stream to be removed
*/
public void disassociate(IStream stream);
-
+
/**
* <p>Overrides Stream.getAssociatedStream() to return an instance of IStream instead of Stream
- *
+ *
* @see Stream#getAssociatedStream()
*/
@Override
diff --git a/jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/IdleListener.java b/jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/IdleListener.java
index 8ca26add0d..42e4449679 100644
--- a/jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/IdleListener.java
+++ b/jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/IdleListener.java
@@ -1,19 +1,15 @@
-/*
- * Copyright (c) 2012 the original author or authors.
- *
- * 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.
- */
-
+///========================================================================
+//Copyright 2011-2012 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.spdy;
public interface IdleListener
diff --git a/jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/Promise.java b/jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/Promise.java
index d44da62dee..b08cde8c49 100644
--- a/jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/Promise.java
+++ b/jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/Promise.java
@@ -1,21 +1,19 @@
-/*
- * Copyright (c) 2012 the original author or authors.
- *
- * 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.
- */
+//========================================================================
+//Copyright 2011-2012 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.spdy;
+import java.util.concurrent.CancellationException;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.Future;
@@ -44,7 +42,8 @@ public class Promise<T> implements Handler<T>, Future<T>
latch.countDown();
}
- public void failed(Throwable x)
+ @Override
+ public void failed(T context, Throwable x)
{
this.failure = x;
latch.countDown();
@@ -88,6 +87,8 @@ public class Promise<T> implements Handler<T>, Future<T>
private T result() throws ExecutionException
{
+ if (isCancelled())
+ throw new CancellationException();
Throwable failure = this.failure;
if (failure != null)
throw new ExecutionException(failure);
diff --git a/jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/PushSynInfo.java b/jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/PushSynInfo.java
index a460d54d7d..8befef43ed 100644
--- a/jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/PushSynInfo.java
+++ b/jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/PushSynInfo.java
@@ -1,4 +1,16 @@
package org.eclipse.jetty.spdy;
+//========================================================================
+//Copyright 2011-2012 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 org.eclipse.jetty.spdy.api.SynInfo;
diff --git a/jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/SPDYv3FlowControlStrategy.java b/jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/SPDYv3FlowControlStrategy.java
new file mode 100644
index 0000000000..8eb4b0ebdf
--- /dev/null
+++ b/jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/SPDYv3FlowControlStrategy.java
@@ -0,0 +1,84 @@
+//========================================================================
+//Copyright 2011-2012 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.spdy;
+
+import java.util.concurrent.TimeUnit;
+
+import org.eclipse.jetty.spdy.api.DataInfo;
+import org.eclipse.jetty.spdy.api.Stream;
+import org.eclipse.jetty.spdy.frames.WindowUpdateFrame;
+
+public class SPDYv3FlowControlStrategy implements FlowControlStrategy
+{
+ private volatile int windowSize;
+
+ @Override
+ public int getWindowSize(ISession session)
+ {
+ return windowSize;
+ }
+
+ @Override
+ public void setWindowSize(ISession session, int windowSize)
+ {
+ int prevWindowSize = this.windowSize;
+ this.windowSize = windowSize;
+ for (Stream stream : session.getStreams())
+ ((IStream)stream).updateWindowSize(windowSize - prevWindowSize);
+ }
+
+ @Override
+ public void onNewStream(ISession session, IStream stream)
+ {
+ stream.updateWindowSize(windowSize);
+ }
+
+ @Override
+ public void onWindowUpdate(ISession session, IStream stream, int delta)
+ {
+ if (stream != null)
+ stream.updateWindowSize(delta);
+ }
+
+ @Override
+ public void updateWindow(ISession session, IStream stream, int delta)
+ {
+ stream.updateWindowSize(delta);
+ }
+
+ @Override
+ public void onDataReceived(ISession session, IStream stream, DataInfo dataInfo)
+ {
+ // Do nothing
+ }
+
+ @Override
+ public void onDataConsumed(ISession session, IStream stream, DataInfo dataInfo, int delta)
+ {
+ // This is the algorithm for flow control.
+ // This method may be called multiple times with delta=1, but we only send a window
+ // update when the whole dataInfo has been consumed.
+ // Other policies may be to send window updates when consumed() is greater than
+ // a certain threshold, etc. but for now the policy is not pluggable for simplicity.
+ // Note that the frequency of window updates depends on the read buffer, that
+ // should not be too smaller than the window size to avoid frequent window updates.
+ // Therefore, a pluggable policy should be able to modify the read buffer capacity.
+ int length = dataInfo.length();
+ if (dataInfo.consumed() == length && !stream.isClosed() && length > 0)
+ {
+ WindowUpdateFrame windowUpdateFrame = new WindowUpdateFrame(session.getVersion(), stream.getId(), length);
+ session.control(stream, windowUpdateFrame, 0, TimeUnit.MILLISECONDS, null, null);
+ }
+ }
+}
diff --git a/jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/SessionException.java b/jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/SessionException.java
index 3e0c1950e5..65f375412d 100644
--- a/jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/SessionException.java
+++ b/jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/SessionException.java
@@ -1,18 +1,15 @@
-/*
- * Copyright (c) 2012 the original author or authors.
- *
- * 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.
- */
+//========================================================================
+//Copyright 2011-2012 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.spdy;
@@ -20,7 +17,6 @@ import org.eclipse.jetty.spdy.api.SessionStatus;
public class SessionException extends RuntimeException
{
-
private final SessionStatus sessionStatus;
public SessionException(SessionStatus sessionStatus)
diff --git a/jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/StandardByteBufferPool.java b/jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/StandardByteBufferPool.java
index 3ecc001da7..60b6190bf2 100644
--- a/jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/StandardByteBufferPool.java
+++ b/jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/StandardByteBufferPool.java
@@ -1,18 +1,15 @@
-/*
- * Copyright (c) 2012 the original author or authors.
- *
- * 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.
- */
+//========================================================================
+//Copyright 2011-2012 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.spdy;
diff --git a/jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/StandardCompressionFactory.java b/jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/StandardCompressionFactory.java
index f0a7eebbdf..1e7e6e084d 100644
--- a/jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/StandardCompressionFactory.java
+++ b/jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/StandardCompressionFactory.java
@@ -1,18 +1,15 @@
-/*
- * Copyright (c) 2012 the original author or authors.
- *
- * 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.
- */
+//========================================================================
+//Copyright 2011-2012 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.spdy;
diff --git a/jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/StandardSession.java b/jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/StandardSession.java
index b77e9eb6af..d5524e2f61 100644
--- a/jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/StandardSession.java
+++ b/jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/StandardSession.java
@@ -1,26 +1,27 @@
-/*
- * Copyright (c) 2012 the original author or authors.
- *
- * 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.
- */
+//========================================================================
+//Copyright 2011-2012 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.spdy;
+import java.io.IOException;
import java.nio.ByteBuffer;
import java.nio.channels.InterruptedByTimeoutException;
+import java.util.ArrayList;
+import java.util.Collections;
import java.util.HashSet;
import java.util.LinkedList;
import java.util.List;
+import java.util.Map;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
@@ -33,6 +34,7 @@ import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.atomic.AtomicInteger;
+import org.eclipse.jetty.spdy.api.ByteBufferDataInfo;
import org.eclipse.jetty.spdy.api.DataInfo;
import org.eclipse.jetty.spdy.api.GoAwayInfo;
import org.eclipse.jetty.spdy.api.Handler;
@@ -50,6 +52,7 @@ import org.eclipse.jetty.spdy.api.StreamStatus;
import org.eclipse.jetty.spdy.api.SynInfo;
import org.eclipse.jetty.spdy.frames.ControlFrame;
import org.eclipse.jetty.spdy.frames.ControlFrameType;
+import org.eclipse.jetty.spdy.frames.CredentialFrame;
import org.eclipse.jetty.spdy.frames.DataFrame;
import org.eclipse.jetty.spdy.frames.GoAwayFrame;
import org.eclipse.jetty.spdy.frames.HeadersFrame;
@@ -61,10 +64,13 @@ import org.eclipse.jetty.spdy.frames.SynStreamFrame;
import org.eclipse.jetty.spdy.frames.WindowUpdateFrame;
import org.eclipse.jetty.spdy.generator.Generator;
import org.eclipse.jetty.spdy.parser.Parser;
+import org.eclipse.jetty.util.Atomics;
+import org.eclipse.jetty.util.component.AggregateLifeCycle;
+import org.eclipse.jetty.util.component.Dumpable;
import org.eclipse.jetty.util.log.Log;
import org.eclipse.jetty.util.log.Logger;
-public class StandardSession implements ISession, Parser.Listener, Handler<StandardSession.FrameBytes>
+public class StandardSession implements ISession, Parser.Listener, Handler<StandardSession.FrameBytes>, Dumpable
{
private static final Logger logger = Log.getLogger(Session.class);
private static final ThreadLocal<Integer> handlerInvocations = new ThreadLocal<Integer>()
@@ -76,6 +82,7 @@ public class StandardSession implements ISession, Parser.Listener, Handler<Stand
}
};
+ private final Map<String, Object> attributes = new ConcurrentHashMap<>();
private final List<Listener> listeners = new CopyOnWriteArrayList<>();
private final ConcurrentMap<Integer, IStream> streams = new ConcurrentHashMap<>();
private final LinkedList<FrameBytes> queue = new LinkedList<>();
@@ -92,11 +99,13 @@ public class StandardSession implements ISession, Parser.Listener, Handler<Stand
private final AtomicBoolean goAwaySent = new AtomicBoolean();
private final AtomicBoolean goAwayReceived = new AtomicBoolean();
private final AtomicInteger lastStreamId = new AtomicInteger();
+ private final FlowControlStrategy flowControlStrategy;
private boolean flushing;
- private volatile int windowSize = 65536;
+ private Throwable failure;
public StandardSession(short version, ByteBufferPool bufferPool, Executor threadPool, ScheduledExecutorService scheduler,
- Controller<FrameBytes> controller, IdleListener idleListener, int initialStreamId, SessionFrameListener listener, Generator generator)
+ Controller<FrameBytes> controller, IdleListener idleListener, int initialStreamId, SessionFrameListener listener,
+ Generator generator, FlowControlStrategy flowControlStrategy)
{
this.version = version;
this.bufferPool = bufferPool;
@@ -108,6 +117,7 @@ public class StandardSession implements ISession, Parser.Listener, Handler<Stand
this.pingIds = new AtomicInteger(initialStreamId);
this.listener = listener;
this.generator = generator;
+ this.flowControlStrategy = flowControlStrategy;
}
@Override
@@ -152,7 +162,8 @@ public class StandardSession implements ISession, Parser.Listener, Handler<Stand
synchronized (this)
{
int streamId = streamIds.getAndAdd(2);
- SynStreamFrame synStream = new SynStreamFrame(version, synInfo.getFlags(), streamId, associatedStreamId, synInfo.getPriority(), synInfo.getHeaders());
+ // TODO: for SPDYv3 we need to support the "slot" argument
+ SynStreamFrame synStream = new SynStreamFrame(version, synInfo.getFlags(), streamId, associatedStreamId, synInfo.getPriority(), (short)0, synInfo.getHeaders());
IStream stream = createStream(synStream, listener, true);
generateAndEnqueueControlFrame(stream, synStream, timeout, unit, handler, stream);
}
@@ -201,7 +212,7 @@ public class StandardSession implements ISession, Parser.Listener, Handler<Stand
public void settings(SettingsInfo settingsInfo, long timeout, TimeUnit unit, Handler<Void> handler)
{
SettingsFrame frame = new SettingsFrame(version,settingsInfo.getFlags(),settingsInfo.getSettings());
- control(null,frame,timeout,unit,handler,null);
+ control(null, frame, timeout, unit, handler, null);
}
@Override
@@ -237,7 +248,7 @@ public class StandardSession implements ISession, Parser.Listener, Handler<Stand
@Override
public void goAway(long timeout, TimeUnit unit, Handler<Void> handler)
{
- goAway(SessionStatus.OK,timeout,unit,handler);
+ goAway(SessionStatus.OK, timeout, unit, handler);
}
private void goAway(SessionStatus sessionStatus, long timeout, TimeUnit unit, Handler<Void> handler)
@@ -263,16 +274,40 @@ public class StandardSession implements ISession, Parser.Listener, Handler<Stand
}
@Override
+ public IStream getStream(int streamId)
+ {
+ return streams.get(streamId);
+ }
+
+ @Override
+ public Object getAttribute(String key)
+ {
+ return attributes.get(key);
+ }
+
+ @Override
+ public void setAttribute(String key, Object value)
+ {
+ attributes.put(key, value);
+ }
+
+ @Override
+ public Object removeAttribute(String key)
+ {
+ return attributes.remove(key);
+ }
+
+ @Override
public void onControlFrame(ControlFrame frame)
{
- notifyIdle(idleListener,false);
+ notifyIdle(idleListener, false);
try
{
- logger.debug("Processing {}",frame);
+ logger.debug("Processing {}", frame);
if (goAwaySent.get())
{
- logger.debug("Skipped processing of {}",frame);
+ logger.debug("Skipped processing of {}", frame);
return;
}
@@ -323,6 +358,11 @@ public class StandardSession implements ISession, Parser.Listener, Handler<Stand
onWindowUpdate((WindowUpdateFrame)frame);
break;
}
+ case CREDENTIAL:
+ {
+ onCredential((CredentialFrame)frame);
+ break;
+ }
default:
{
throw new IllegalStateException();
@@ -331,7 +371,7 @@ public class StandardSession implements ISession, Parser.Listener, Handler<Stand
}
finally
{
- notifyIdle(idleListener,true);
+ notifyIdle(idleListener, true);
}
}
@@ -341,11 +381,11 @@ public class StandardSession implements ISession, Parser.Listener, Handler<Stand
notifyIdle(idleListener, false);
try
{
- logger.debug("Processing {}, {} data bytes",frame,data.remaining());
+ logger.debug("Processing {}, {} data bytes", frame, data.remaining());
if (goAwaySent.get())
{
- logger.debug("Skipped processing of {}",frame);
+ logger.debug("Skipped processing of {}", frame);
return;
}
@@ -353,18 +393,18 @@ public class StandardSession implements ISession, Parser.Listener, Handler<Stand
IStream stream = streams.get(streamId);
if (stream == null)
{
- RstInfo rstInfo = new RstInfo(streamId,StreamStatus.INVALID_STREAM);
- logger.debug("Unknown stream {}",rstInfo);
+ RstInfo rstInfo = new RstInfo(streamId, StreamStatus.INVALID_STREAM);
+ logger.debug("Unknown stream {}", rstInfo);
rst(rstInfo);
}
else
{
- processData(stream,frame,data);
+ processData(stream, frame, data);
}
}
finally
{
- notifyIdle(idleListener,true);
+ notifyIdle(idleListener, true);
}
}
@@ -374,10 +414,19 @@ public class StandardSession implements ISession, Parser.Listener, Handler<Stand
listener.onIdle(idle);
}
- private void processData(IStream stream, DataFrame frame, ByteBuffer data)
+ private void processData(final IStream stream, DataFrame frame, ByteBuffer data)
{
- stream.process(frame,data);
- updateLastStreamId(stream);
+ ByteBufferDataInfo dataInfo = new ByteBufferDataInfo(data, frame.isClose(), frame.isCompress())
+ {
+ @Override
+ public void consume(int delta)
+ {
+ super.consume(delta);
+ flowControlStrategy.onDataConsumed(StandardSession.this, stream, this, delta);
+ }
+ };
+ flowControlStrategy.onDataReceived(this, stream, dataInfo);
+ stream.process(dataInfo);
if (stream.isClosed())
removeStream(stream);
}
@@ -407,6 +456,8 @@ public class StandardSession implements ISession, Parser.Listener, Handler<Stand
private void processSyn(SessionFrameListener listener, IStream stream, SynStreamFrame frame)
{
stream.process(frame);
+ // Update the last stream id before calling the application (which may send a GO_AWAY)
+ updateLastStreamId(stream);
SynInfo synInfo = new SynInfo(frame.getHeaders(),frame.isClose(),frame.getPriority());
StreamFrameListener streamListener = notifyOnSyn(listener,stream,synInfo);
stream.setStreamFrameListener(streamListener);
@@ -452,7 +503,9 @@ public class StandardSession implements ISession, Parser.Listener, Handler<Stand
private IStream newStream(SynStreamFrame frame)
{
IStream associatedStream = streams.get(frame.getAssociatedStreamId());
- return new StandardStream(frame, this, windowSize, associatedStream);
+ IStream stream = new StandardStream(frame.getStreamId(), frame.getPriority(), this, associatedStream);
+ flowControlStrategy.onNewStream(this, stream);
+ return stream;
}
private void notifyStreamCreated(IStream stream)
@@ -467,7 +520,12 @@ public class StandardSession implements ISession, Parser.Listener, Handler<Stand
}
catch (Exception x)
{
- logger.info("Exception while notifying listener " + listener,x);
+ logger.info("Exception while notifying listener " + listener, x);
+ }
+ catch (Error x)
+ {
+ logger.info("Exception while notifying listener " + listener, x);
+ throw x;
}
}
}
@@ -498,7 +556,12 @@ public class StandardSession implements ISession, Parser.Listener, Handler<Stand
}
catch (Exception x)
{
- logger.info("Exception while notifying listener " + listener,x);
+ logger.info("Exception while notifying listener " + listener, x);
+ }
+ catch (Error x)
+ {
+ logger.info("Exception while notifying listener " + listener, x);
+ throw x;
}
}
}
@@ -547,15 +610,12 @@ public class StandardSession implements ISession, Parser.Listener, Handler<Stand
Settings.Setting windowSizeSetting = frame.getSettings().get(Settings.ID.INITIAL_WINDOW_SIZE);
if (windowSizeSetting != null)
{
- int prevWindowSize = windowSize;
- windowSize = windowSizeSetting.value();
- for (IStream stream : streams.values())
- stream.updateWindowSize(windowSize - prevWindowSize);
- logger.debug("Updated window size to {}",windowSize);
+ int windowSize = windowSizeSetting.value();
+ setWindowSize(windowSize);
+ logger.debug("Updated session window size to {}", windowSize);
}
-
- SettingsInfo settingsInfo = new SettingsInfo(frame.getSettings(),frame.isClearPersisted());
- notifyOnSettings(listener,settingsInfo);
+ SettingsInfo settingsInfo = new SettingsInfo(frame.getSettings(), frame.isClearPersisted());
+ notifyOnSettings(listener, settingsInfo);
flush();
}
@@ -615,8 +675,14 @@ public class StandardSession implements ISession, Parser.Listener, Handler<Stand
{
int streamId = frame.getStreamId();
IStream stream = streams.get(streamId);
- if (stream != null)
- stream.process(frame);
+ flowControlStrategy.onWindowUpdate(this, stream, frame.getWindowDelta());
+ flush();
+ }
+
+ private void onCredential(CredentialFrame frame)
+ {
+ logger.warn("{} frame not yet supported", ControlFrameType.CREDENTIAL);
+ flush();
}
protected void close()
@@ -638,7 +704,12 @@ public class StandardSession implements ISession, Parser.Listener, Handler<Stand
}
catch (Exception xx)
{
- logger.info("Exception while notifying listener " + listener,xx);
+ logger.info("Exception while notifying listener " + listener, xx);
+ }
+ catch (Error xx)
+ {
+ logger.info("Exception while notifying listener " + listener, xx);
+ throw xx;
}
}
@@ -646,17 +717,21 @@ public class StandardSession implements ISession, Parser.Listener, Handler<Stand
{
try
{
- if (listener != null)
- {
- logger.debug("Invoking callback with {} on listener {}",synInfo,listener);
- return listener.onSyn(stream,synInfo);
- }
+ if (listener == null)
+ return null;
+ logger.debug("Invoking callback with {} on listener {}",synInfo,listener);
+ return listener.onSyn(stream,synInfo);
}
catch (Exception x)
{
logger.info("Exception while notifying listener " + listener,x);
+ return null;
+ }
+ catch (Error x)
+ {
+ logger.info("Exception while notifying listener " + listener, x);
+ throw x;
}
- return null;
}
private void notifyOnRst(SessionFrameListener listener, RstInfo rstInfo)
@@ -671,7 +746,12 @@ public class StandardSession implements ISession, Parser.Listener, Handler<Stand
}
catch (Exception x)
{
- logger.info("Exception while notifying listener " + listener,x);
+ logger.info("Exception while notifying listener " + listener, x);
+ }
+ catch (Error x)
+ {
+ logger.info("Exception while notifying listener " + listener, x);
+ throw x;
}
}
@@ -687,7 +767,12 @@ public class StandardSession implements ISession, Parser.Listener, Handler<Stand
}
catch (Exception x)
{
- logger.info("Exception while notifying listener " + listener,x);
+ logger.info("Exception while notifying listener " + listener, x);
+ }
+ catch (Error x)
+ {
+ logger.info("Exception while notifying listener " + listener, x);
+ throw x;
}
}
@@ -703,7 +788,12 @@ public class StandardSession implements ISession, Parser.Listener, Handler<Stand
}
catch (Exception x)
{
- logger.info("Exception while notifying listener " + listener,x);
+ logger.info("Exception while notifying listener " + listener, x);
+ }
+ catch (Error x)
+ {
+ logger.info("Exception while notifying listener " + listener, x);
+ throw x;
}
}
@@ -719,7 +809,12 @@ public class StandardSession implements ISession, Parser.Listener, Handler<Stand
}
catch (Exception x)
{
- logger.info("Exception while notifying listener " + listener,x);
+ logger.info("Exception while notifying listener " + listener, x);
+ }
+ catch (Error x)
+ {
+ logger.info("Exception while notifying listener " + listener, x);
+ throw x;
}
}
@@ -734,23 +829,16 @@ public class StandardSession implements ISession, Parser.Listener, Handler<Stand
{
try
{
- if (stream != null)
- {
- updateLastStreamId(stream);
- if (stream.isClosed())
- removeStream(stream);
- }
-
// Synchronization is necessary, since we may have concurrent replies
// and those needs to be generated and enqueued atomically in order
// to maintain a correct compression context
synchronized (this)
{
ByteBuffer buffer = generator.control(frame);
- logger.debug("Queuing {} on {}",frame,stream);
- ControlFrameBytes<C> frameBytes = new ControlFrameBytes<>(stream,handler,context,frame,buffer);
+ logger.debug("Queuing {} on {}", frame, stream);
+ ControlFrameBytes<C> frameBytes = new ControlFrameBytes<>(stream, handler, context, frame, buffer);
if (timeout > 0)
- frameBytes.task = scheduler.schedule(frameBytes,timeout,unit);
+ frameBytes.task = scheduler.schedule(frameBytes, timeout, unit);
// Special handling for PING frames, they must be sent as soon as possible
if (ControlFrameType.PING == frame.getType())
@@ -759,26 +847,17 @@ public class StandardSession implements ISession, Parser.Listener, Handler<Stand
append(frameBytes);
}
}
- catch (Throwable x)
+ catch (Exception x)
{
- notifyHandlerFailed(handler, x);
+ notifyHandlerFailed(handler, context, x);
}
}
private void updateLastStreamId(IStream stream)
{
int streamId = stream.getId();
- if (stream.isClosed() && streamId % 2 != streamIds.get() % 2)
- {
- // Non-blocking atomic update
- int oldValue = lastStreamId.get();
- while (streamId > oldValue)
- {
- if (lastStreamId.compareAndSet(oldValue,streamId))
- break;
- oldValue = lastStreamId.get();
- }
- }
+ if (streamId % 2 != streamIds.get() % 2)
+ Atomics.updateMax(lastStreamId, streamId);
}
@Override
@@ -787,9 +866,7 @@ public class StandardSession implements ISession, Parser.Listener, Handler<Stand
logger.debug("Queuing {} on {}",dataInfo,stream);
DataFrameBytes<C> frameBytes = new DataFrameBytes<>(stream,handler,context,dataInfo);
if (timeout > 0)
- {
frameBytes.task = scheduler.schedule(frameBytes,timeout,unit);
- }
append(frameBytes);
flush();
}
@@ -822,9 +899,11 @@ public class StandardSession implements ISession, Parser.Listener, Handler<Stand
if (buffer != null)
{
queue.remove(i);
- // TODO: stream.isUniDirectional() check here is only needed for pushStreams which send a syn with close=true --> find a better solution
- if (stream != null && !streams.containsValue(stream) && !stream.isUnidirectional())
+ if (stream != null && stream.isReset())
+ {
frameBytes.fail(new StreamException(stream.getId(),StreamStatus.INVALID_STREAM));
+ return;
+ }
break;
}
@@ -847,34 +926,50 @@ public class StandardSession implements ISession, Parser.Listener, Handler<Stand
private void append(FrameBytes frameBytes)
{
+ Throwable failure;
synchronized (queue)
{
- int index = queue.size();
- while (index > 0)
+ failure = this.failure;
+ if (failure == null)
{
- FrameBytes element = queue.get(index - 1);
- if (element.compareTo(frameBytes) >= 0)
- break;
- --index;
+ int index = queue.size();
+ while (index > 0)
+ {
+ FrameBytes element = queue.get(index - 1);
+ if (element.compareTo(frameBytes) >= 0)
+ break;
+ --index;
+ }
+ queue.add(index,frameBytes);
}
- queue.add(index,frameBytes);
}
+
+ if (failure != null)
+ frameBytes.fail(new SPDYException(failure));
}
private void prepend(FrameBytes frameBytes)
{
+ Throwable failure;
synchronized (queue)
{
- int index = 0;
- while (index < queue.size())
+ failure = this.failure;
+ if (failure == null)
{
- FrameBytes element = queue.get(index);
- if (element.compareTo(frameBytes) <= 0)
- break;
- ++index;
+ int index = 0;
+ while (index < queue.size())
+ {
+ FrameBytes element = queue.get(index);
+ if (element.compareTo(frameBytes) <= 0)
+ break;
+ ++index;
+ }
+ queue.add(index,frameBytes);
}
- queue.add(index,frameBytes);
}
+
+ if (failure != null)
+ frameBytes.fail(new SPDYException(failure));
}
@Override
@@ -889,9 +984,23 @@ public class StandardSession implements ISession, Parser.Listener, Handler<Stand
}
@Override
- public void failed(Throwable x)
+ public void failed(FrameBytes frameBytes, Throwable x)
{
- throw new SPDYException(x);
+ List<FrameBytes> frameBytesToFail = new ArrayList<>();
+ frameBytesToFail.add(frameBytes);
+
+ synchronized (queue)
+ {
+ failure = x;
+ String logMessage = String.format("Failed write of %s, failing all %d frame(s) in queue",frameBytes,queue.size());
+ logger.debug(logMessage,x);
+ frameBytesToFail.addAll(queue);
+ queue.clear();
+ flushing = false;
+ }
+
+ for (FrameBytes fb : frameBytesToFail)
+ fb.fail(x);
}
protected void write(ByteBuffer buffer, Handler<FrameBytes> handler, FrameBytes frameBytes)
@@ -947,23 +1056,64 @@ public class StandardSession implements ISession, Parser.Listener, Handler<Stand
}
catch (Exception x)
{
- logger.info("Exception while notifying handler " + handler,x);
+ logger.info("Exception while notifying handler " + handler, x);
+ }
+ catch (Error x)
+ {
+ logger.info("Exception while notifying handler " + handler, x);
+ throw x;
}
}
- private <C> void notifyHandlerFailed(Handler<C> handler, Throwable x)
+ private <C> void notifyHandlerFailed(Handler<C> handler, C context, Throwable x)
{
try
{
if (handler != null)
- handler.failed(x);
+ handler.failed(context, x);
}
catch (Exception xx)
{
- logger.info("Exception while notifying handler " + handler,xx);
+ logger.info("Exception while notifying handler " + handler, xx);
}
+ catch (Error xx)
+ {
+ logger.info("Exception while notifying handler " + handler, xx);
+ throw xx;
+ }
+ }
+
+ public int getWindowSize()
+ {
+ return flowControlStrategy.getWindowSize(this);
+ }
+
+ public void setWindowSize(int initialWindowSize)
+ {
+ flowControlStrategy.setWindowSize(this, initialWindowSize);
+ }
+
+ public String toString()
+ {
+ return String.format("%s@%x{v%d,queuSize=%d,windowSize=%d,streams=%d}", getClass().getSimpleName(), hashCode(), version, queue.size(), getWindowSize(), streams.size());
+ }
+
+
+ @Override
+ public String dump()
+ {
+ return AggregateLifeCycle.dump(this);
+ }
+
+ @Override
+ public void dump(Appendable out, String indent) throws IOException
+ {
+ AggregateLifeCycle.dumpObject(out,this);
+ AggregateLifeCycle.dump(out,indent,Collections.singletonList(controller),streams.values());
}
+
+
public interface FrameBytes extends Comparable<FrameBytes>
{
public IStream getStream();
@@ -998,8 +1148,16 @@ public class StandardSession implements ISession, Parser.Listener, Handler<Stand
@Override
public int compareTo(FrameBytes that)
{
- // If this.stream.priority > that.stream.priority => -1 (this.stream has less priority than that.stream)
- return that.getStream().getPriority() - getStream().getPriority();
+ // FrameBytes may have or not have a related stream (for example, PING do not have a related stream)
+ // FrameBytes without related streams have higher priority
+ IStream thisStream = getStream();
+ IStream thatStream = that.getStream();
+ if (thisStream == null)
+ return thatStream == null ? 0 : -1;
+ if (thatStream == null)
+ return 1;
+ // If this.stream.priority > that.stream.priority => this.stream has less priority than that.stream
+ return thatStream.getPriority() - thisStream.getPriority();
}
@Override
@@ -1013,7 +1171,8 @@ public class StandardSession implements ISession, Parser.Listener, Handler<Stand
public void fail(Throwable x)
{
cancelTask();
- notifyHandlerFailed(handler,x);
+ notifyHandlerFailed(handler,context,x);
+ StandardSession.this.flush();
}
private void cancelTask()
@@ -1062,6 +1221,9 @@ public class StandardSession implements ISession, Parser.Listener, Handler<Stand
// Recipients will know the last good stream id and act accordingly.
close();
}
+ IStream stream = getStream();
+ if (stream != null && stream.isClosed())
+ removeStream(stream);
}
@Override
@@ -1112,14 +1274,14 @@ public class StandardSession implements ISession, Parser.Listener, Handler<Stand
{
bufferPool.release(buffer);
IStream stream = getStream();
- stream.updateWindowSize(-size);
-
+ flowControlStrategy.updateWindow(StandardSession.this, stream, -size);
if (dataInfo.available() > 0)
{
// We have written a frame out of this DataInfo, but there is more to write.
// We need to keep the correct ordering of frames, to avoid that another
// DataInfo for the same stream is written before this one is finished.
prepend(this);
+ flush();
}
else
{
diff --git a/jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/StandardStream.java b/jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/StandardStream.java
index 4de901c74e..360a639591 100644
--- a/jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/StandardStream.java
+++ b/jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/StandardStream.java
@@ -1,22 +1,18 @@
-/*
- * Copyright (c) 2012 the original author or authors.
- *
- * 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.
- */
+//========================================================================
+//Copyright 2011-2012 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.spdy;
-import java.nio.ByteBuffer;
import java.util.Collections;
import java.util.Map;
import java.util.Set;
@@ -25,23 +21,18 @@ import java.util.concurrent.Future;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicInteger;
-import org.eclipse.jetty.spdy.api.ByteBufferDataInfo;
import org.eclipse.jetty.spdy.api.DataInfo;
import org.eclipse.jetty.spdy.api.Handler;
import org.eclipse.jetty.spdy.api.HeadersInfo;
import org.eclipse.jetty.spdy.api.ReplyInfo;
import org.eclipse.jetty.spdy.api.RstInfo;
-import org.eclipse.jetty.spdy.api.Session;
import org.eclipse.jetty.spdy.api.Stream;
import org.eclipse.jetty.spdy.api.StreamFrameListener;
import org.eclipse.jetty.spdy.api.StreamStatus;
import org.eclipse.jetty.spdy.api.SynInfo;
import org.eclipse.jetty.spdy.frames.ControlFrame;
-import org.eclipse.jetty.spdy.frames.DataFrame;
import org.eclipse.jetty.spdy.frames.HeadersFrame;
import org.eclipse.jetty.spdy.frames.SynReplyFrame;
-import org.eclipse.jetty.spdy.frames.SynStreamFrame;
-import org.eclipse.jetty.spdy.frames.WindowUpdateFrame;
import org.eclipse.jetty.util.log.Log;
import org.eclipse.jetty.util.log.Logger;
@@ -49,28 +40,29 @@ public class StandardStream implements IStream
{
private static final Logger logger = Log.getLogger(Stream.class);
private final Map<String, Object> attributes = new ConcurrentHashMap<>();
- private final IStream associatedStream;
- private final SynStreamFrame frame;
+ private final int id;
+ private final byte priority;
private final ISession session;
- private final AtomicInteger windowSize;
+ private final IStream associatedStream;
+ private final AtomicInteger windowSize = new AtomicInteger();
private final Set<Stream> pushedStreams = Collections.newSetFromMap(new ConcurrentHashMap<Stream, Boolean>());
private volatile StreamFrameListener listener;
private volatile OpenState openState = OpenState.SYN_SENT;
private volatile CloseState closeState = CloseState.OPENED;
private volatile boolean reset = false;
- public StandardStream(SynStreamFrame frame, ISession session, int windowSize, IStream associatedStream)
+ public StandardStream(int id, byte priority, ISession session, IStream associatedStream)
{
- this.frame = frame;
+ this.id = id;
+ this.priority = priority;
this.session = session;
- this.windowSize = new AtomicInteger(windowSize);
this.associatedStream = associatedStream;
}
@Override
public int getId()
{
- return frame.getStreamId();
+ return id;
}
@Override
@@ -100,7 +92,7 @@ public class StandardStream implements IStream
@Override
public byte getPriority()
{
- return frame.getPriority();
+ return priority;
}
@Override
@@ -113,11 +105,11 @@ public class StandardStream implements IStream
public void updateWindowSize(int delta)
{
int size = windowSize.addAndGet(delta);
- logger.debug("Updated window size by {}, new window size {}",delta,size);
+ logger.debug("Updated window size {} -> {} for {}", size - delta, size, this);
}
@Override
- public Session getSession()
+ public ISession getSession()
{
return session;
}
@@ -146,6 +138,11 @@ public class StandardStream implements IStream
this.listener = listener;
}
+ public StreamFrameListener getStreamFrameListener()
+ {
+ return listener;
+ }
+
@Override
public void updateCloseState(boolean close, boolean local)
{
@@ -155,7 +152,7 @@ public class StandardStream implements IStream
{
case OPENED:
{
- closeState = local?CloseState.LOCALLY_CLOSED:CloseState.REMOTELY_CLOSED;
+ closeState = local ? CloseState.LOCALLY_CLOSED : CloseState.REMOTELY_CLOSED;
break;
}
case LOCALLY_CLOSED:
@@ -196,25 +193,19 @@ public class StandardStream implements IStream
{
openState = OpenState.REPLY_RECV;
SynReplyFrame synReply = (SynReplyFrame)frame;
- updateCloseState(synReply.isClose(),false);
- ReplyInfo replyInfo = new ReplyInfo(synReply.getHeaders(),synReply.isClose());
+ updateCloseState(synReply.isClose(), false);
+ ReplyInfo replyInfo = new ReplyInfo(synReply.getHeaders(), synReply.isClose());
notifyOnReply(replyInfo);
break;
}
case HEADERS:
{
HeadersFrame headers = (HeadersFrame)frame;
- updateCloseState(headers.isClose(),false);
- HeadersInfo headersInfo = new HeadersInfo(headers.getHeaders(),headers.isClose(),headers.isResetCompression());
+ updateCloseState(headers.isClose(), false);
+ HeadersInfo headersInfo = new HeadersInfo(headers.getHeaders(), headers.isClose(), headers.isResetCompression());
notifyOnHeaders(headersInfo);
break;
}
- case WINDOW_UPDATE:
- {
- WindowUpdateFrame windowUpdate = (WindowUpdateFrame)frame;
- updateWindowSize(windowUpdate.getWindowDelta());
- break;
- }
case RST_STREAM:
{
reset = true;
@@ -229,57 +220,28 @@ public class StandardStream implements IStream
}
@Override
- public void process(DataFrame frame, ByteBuffer data)
+ public void process(DataInfo dataInfo)
{
// TODO: in v3 we need to send a rst instead of just ignoring
// ignore data frame if this stream is remotelyClosed already
- if (isHalfClosed() && !isLocallyClosed())
+ if (isRemotelyClosed())
{
- logger.debug("Ignoring received dataFrame as this stream is remotely closed: " + frame);
+ logger.debug("Stream is remotely closed, ignoring {}", dataInfo);
return;
}
if (!canReceive())
{
- logger.debug("Can't receive. Sending rst: " + frame);
- session.rst(new RstInfo(getId(),StreamStatus.PROTOCOL_ERROR));
+ logger.debug("Protocol error receiving {}, resetting" + dataInfo);
+ session.rst(new RstInfo(getId(), StreamStatus.PROTOCOL_ERROR));
return;
}
- updateCloseState(frame.isClose(),false);
-
- ByteBufferDataInfo dataInfo = new ByteBufferDataInfo(data,frame.isClose(),frame.isCompress())
- {
- @Override
- public void consume(int delta)
- {
- super.consume(delta);
-
- // This is the algorithm for flow control.
- // This method may be called multiple times with delta=1, but we only send a window
- // update when the whole dataInfo has been consumed.
- // Other policies may be to send window updates when consumed() is greater than
- // a certain threshold, etc. but for now the policy is not pluggable for simplicity.
- // Note that the frequency of window updates depends on the read buffer, that
- // should not be too smaller than the window size to avoid frequent window updates.
- // Therefore, a pluggable policy should be able to modify the read buffer capacity.
- if (consumed() == length() && !isClosed())
- windowUpdate(length());
- }
- };
+ updateCloseState(dataInfo.isClose(), false);
notifyOnData(dataInfo);
session.flush();
}
- private void windowUpdate(int delta)
- {
- if (delta > 0)
- {
- WindowUpdateFrame windowUpdateFrame = new WindowUpdateFrame(session.getVersion(),getId(),delta);
- session.control(this,windowUpdateFrame,0,TimeUnit.MILLISECONDS,null,null);
- }
- }
-
private void notifyOnReply(ReplyInfo replyInfo)
{
final StreamFrameListener listener = this.listener;
@@ -287,13 +249,18 @@ public class StandardStream implements IStream
{
if (listener != null)
{
- logger.debug("Invoking reply callback with {} on listener {}",replyInfo,listener);
- listener.onReply(this,replyInfo);
+ logger.debug("Invoking reply callback with {} on listener {}", replyInfo, listener);
+ listener.onReply(this, replyInfo);
}
}
catch (Exception x)
{
- logger.info("Exception while notifying listener " + listener,x);
+ logger.info("Exception while notifying listener " + listener, x);
+ }
+ catch (Error x)
+ {
+ logger.info("Exception while notifying listener " + listener, x);
+ throw x;
}
}
@@ -304,13 +271,18 @@ public class StandardStream implements IStream
{
if (listener != null)
{
- logger.debug("Invoking headers callback with {} on listener {}",frame,listener);
- listener.onHeaders(this,headersInfo);
+ logger.debug("Invoking headers callback with {} on listener {}", headersInfo, listener);
+ listener.onHeaders(this, headersInfo);
}
}
catch (Exception x)
{
- logger.info("Exception while notifying listener " + listener,x);
+ logger.info("Exception while notifying listener " + listener, x);
+ }
+ catch (Error x)
+ {
+ logger.info("Exception while notifying listener " + listener, x);
+ throw x;
}
}
@@ -321,14 +293,19 @@ public class StandardStream implements IStream
{
if (listener != null)
{
- logger.debug("Invoking data callback with {} on listener {}",dataInfo,listener);
- listener.onData(this,dataInfo);
- logger.debug("Invoked data callback with {} on listener {}",dataInfo,listener);
+ logger.debug("Invoking data callback with {} on listener {}", dataInfo, listener);
+ listener.onData(this, dataInfo);
+ logger.debug("Invoked data callback with {} on listener {}", dataInfo, listener);
}
}
catch (Exception x)
{
- logger.info("Exception while notifying listener " + listener,x);
+ logger.info("Exception while notifying listener " + listener, x);
+ }
+ catch (Error x)
+ {
+ logger.info("Exception while notifying listener " + listener, x);
+ throw x;
}
}
@@ -345,11 +322,11 @@ public class StandardStream implements IStream
{
if (isClosed() || isReset())
{
- handler.failed(new StreamException(getId(),StreamStatus.STREAM_ALREADY_CLOSED));
+ handler.failed(this, new StreamException(getId(), StreamStatus.STREAM_ALREADY_CLOSED));
return;
}
- PushSynInfo pushSynInfo = new PushSynInfo(getId(),synInfo);
- session.syn(pushSynInfo,null,timeout,unit,handler);
+ PushSynInfo pushSynInfo = new PushSynInfo(getId(), synInfo);
+ session.syn(pushSynInfo, null, timeout, unit, handler);
}
@Override
@@ -366,9 +343,9 @@ public class StandardStream implements IStream
if (isUnidirectional())
throw new IllegalStateException("Protocol violation: cannot send SYN_REPLY frames in unidirectional streams");
openState = OpenState.REPLY_SENT;
- updateCloseState(replyInfo.isClose(),true);
- SynReplyFrame frame = new SynReplyFrame(session.getVersion(),replyInfo.getFlags(),getId(),replyInfo.getHeaders());
- session.control(this,frame,timeout,unit,handler,null);
+ updateCloseState(replyInfo.isClose(), true);
+ SynReplyFrame frame = new SynReplyFrame(session.getVersion(), replyInfo.getFlags(), getId(), replyInfo.getHeaders());
+ session.control(this, frame, timeout, unit, handler, null);
}
@Override
@@ -384,18 +361,18 @@ public class StandardStream implements IStream
{
if (!canSend())
{
- session.rst(new RstInfo(getId(),StreamStatus.PROTOCOL_ERROR));
+ session.rst(new RstInfo(getId(), StreamStatus.PROTOCOL_ERROR));
throw new IllegalStateException("Protocol violation: cannot send a DATA frame before a SYN_REPLY frame");
}
if (isLocallyClosed())
{
- session.rst(new RstInfo(getId(),StreamStatus.PROTOCOL_ERROR));
+ session.rst(new RstInfo(getId(), StreamStatus.PROTOCOL_ERROR));
throw new IllegalStateException("Protocol violation: cannot send a DATA frame on a closed stream");
}
// Cannot update the close state here, because the data that we send may
// be flow controlled, so we need the stream to update the window size.
- session.data(this,dataInfo,timeout,unit,handler,null);
+ session.data(this, dataInfo, timeout, unit, handler, null);
}
@Override
@@ -411,18 +388,18 @@ public class StandardStream implements IStream
{
if (!canSend())
{
- session.rst(new RstInfo(getId(),StreamStatus.PROTOCOL_ERROR));
+ session.rst(new RstInfo(getId(), StreamStatus.PROTOCOL_ERROR));
throw new IllegalStateException("Protocol violation: cannot send a HEADERS frame before a SYN_REPLY frame");
}
if (isLocallyClosed())
{
- session.rst(new RstInfo(getId(),StreamStatus.PROTOCOL_ERROR));
+ session.rst(new RstInfo(getId(), StreamStatus.PROTOCOL_ERROR));
throw new IllegalStateException("Protocol violation: cannot send a HEADERS frame on a closed stream");
}
- updateCloseState(headersInfo.isClose(),true);
- HeadersFrame frame = new HeadersFrame(session.getVersion(),headersInfo.getFlags(),getId(),headersInfo.getHeaders());
- session.control(this,frame,timeout,unit,handler,null);
+ updateCloseState(headersInfo.isClose(), true);
+ HeadersFrame frame = new HeadersFrame(session.getVersion(), headersInfo.getFlags(), getId(), headersInfo.getHeaders());
+ session.control(this, frame, timeout, unit, handler, null);
}
@Override
@@ -456,10 +433,16 @@ public class StandardStream implements IStream
return closeState == CloseState.LOCALLY_CLOSED || closeState == CloseState.CLOSED;
}
+ private boolean isRemotelyClosed()
+ {
+ CloseState closeState = this.closeState;
+ return closeState == CloseState.REMOTELY_CLOSED || closeState == CloseState.CLOSED;
+ }
+
@Override
public String toString()
{
- return String.format("stream=%d v%d %s",getId(),session.getVersion(),closeState);
+ return String.format("stream=%d v%d windowSize=%db reset=%s %s %s", getId(), session.getVersion(), getWindowSize(), isReset(), openState, closeState);
}
private boolean canSend()
diff --git a/jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/StreamException.java b/jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/StreamException.java
index 5b4bd7f456..4a0a954918 100644
--- a/jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/StreamException.java
+++ b/jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/StreamException.java
@@ -1,18 +1,15 @@
-/*
- * Copyright (c) 2012 the original author or authors.
- *
- * 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.
- */
+//========================================================================
+//Copyright 2011-2012 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.spdy;
diff --git a/jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/api/ByteBufferDataInfo.java b/jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/api/ByteBufferDataInfo.java
index 678ff516e3..3b856f6619 100644
--- a/jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/api/ByteBufferDataInfo.java
+++ b/jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/api/ByteBufferDataInfo.java
@@ -1,18 +1,15 @@
-/*
- * Copyright (c) 2012 the original author or authors.
- *
- * 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.
- */
+//========================================================================
+//Copyright 2011-2012 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.spdy.api;
@@ -68,4 +65,10 @@ public class ByteBufferDataInfo extends DataInfo
}
return space;
}
+
+ @Override
+ protected ByteBuffer allocate(int size)
+ {
+ return buffer.isDirect() ? ByteBuffer.allocateDirect(size) : super.allocate(size);
+ }
}
diff --git a/jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/api/BytesDataInfo.java b/jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/api/BytesDataInfo.java
index f2150846ca..9d2123b066 100644
--- a/jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/api/BytesDataInfo.java
+++ b/jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/api/BytesDataInfo.java
@@ -1,18 +1,15 @@
-/*
- * Copyright (c) 2012 the original author or authors.
- *
- * 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.
- */
+//========================================================================
+//Copyright 2011-2012 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.spdy.api;
@@ -23,39 +20,44 @@ import java.nio.ByteBuffer;
*/
public class BytesDataInfo extends DataInfo
{
- private byte[] bytes;
- private int offset;
+ private final byte[] bytes;
+ private final int offset;
+ private final int length;
+ private int index;
public BytesDataInfo(byte[] bytes, boolean close)
{
- this(bytes, close, false);
+ this(bytes, 0, bytes.length, close);
}
- public BytesDataInfo(byte[] bytes, boolean close, boolean compress)
+ public BytesDataInfo(byte[] bytes, int offset, int length, boolean close)
{
- super(close, compress);
+ super(close, false);
this.bytes = bytes;
+ this.offset = offset;
+ this.length = length;
+ this.index = offset;
}
@Override
public int length()
{
- return bytes.length;
+ return length;
}
@Override
public int available()
{
- return length() - offset;
+ return length - index + offset;
}
@Override
public int readInto(ByteBuffer output)
{
int space = output.remaining();
- int length = Math.min(available(), space);
- output.put(bytes, offset, length);
- offset += length;
- return length;
+ int chunk = Math.min(available(), space);
+ output.put(bytes, index, chunk);
+ index += chunk;
+ return chunk;
}
}
diff --git a/jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/api/DataInfo.java b/jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/api/DataInfo.java
index 40364017f5..8253e40fc8 100644
--- a/jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/api/DataInfo.java
+++ b/jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/api/DataInfo.java
@@ -1,18 +1,15 @@
-/*
- * Copyright (c) 2012 the original author or authors.
- *
- * 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.
- */
+//========================================================================
+//Copyright 2011-2012 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.spdy.api;
diff --git a/jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/api/GoAwayInfo.java b/jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/api/GoAwayInfo.java
index 4ebc7262fc..1e16e34534 100644
--- a/jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/api/GoAwayInfo.java
+++ b/jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/api/GoAwayInfo.java
@@ -1,18 +1,15 @@
-/*
- * Copyright (c) 2012 the original author or authors.
- *
- * 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.
- */
+//========================================================================
+//Copyright 2011-2012 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.spdy.api;
diff --git a/jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/api/Handler.java b/jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/api/Handler.java
index 479d33fe09..b69467e368 100644
--- a/jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/api/Handler.java
+++ b/jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/api/Handler.java
@@ -1,18 +1,15 @@
-/*
- * Copyright (c) 2012 the original author or authors.
- *
- * 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.
- */
+//========================================================================
+//Copyright 2011-2012 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.spdy.api;
@@ -28,16 +25,16 @@ public interface Handler<C>
* <p>Callback invoked when the operation completes.</p>
*
* @param context the context
- * @see #failed(Throwable)
+ * @see #failed(Object, Throwable)
*/
public abstract void completed(C context);
/**
* <p>Callback invoked when the operation fails.</p>
- *
+ * @param context the context
* @param x the reason for the operation failure
*/
- public void failed(Throwable x);
+ public void failed(C context, Throwable x);
/**
* <p>Empty implementation of {@link Handler}</p>
@@ -52,9 +49,8 @@ public interface Handler<C>
}
@Override
- public void failed(Throwable x)
+ public void failed(C context, Throwable x)
{
- throw new SPDYException(x);
}
}
}
diff --git a/jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/api/Headers.java b/jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/api/Headers.java
index 3161500604..261a94f730 100644
--- a/jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/api/Headers.java
+++ b/jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/api/Headers.java
@@ -1,18 +1,15 @@
-/*
- * Copyright (c) 2012 the original author or authors.
- *
- * 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.
- */
+//========================================================================
+//Copyright 2011-2012 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.spdy.api;
@@ -219,13 +216,15 @@ public class Headers implements Iterable<Headers.Header>
if (obj == null || getClass() != obj.getClass())
return false;
Header that = (Header)obj;
- return name.equals(that.name) && Arrays.equals(values, that.values);
+ // Header names must be lowercase, thus we lowercase them before transmission, but keep them as is
+ // internally. That's why we've to compare them case insensitive.
+ return name.equalsIgnoreCase(that.name) && Arrays.equals(values, that.values);
}
@Override
public int hashCode()
{
- int result = name.hashCode();
+ int result = name.toLowerCase().hashCode();
result = 31 * result + Arrays.hashCode(values);
return result;
}
@@ -269,6 +268,21 @@ public class Headers implements Iterable<Headers.Header>
}
/**
+ * @return the values as a comma separated list
+ */
+ public String valuesAsString()
+ {
+ StringBuilder result = new StringBuilder();
+ for (int i = 0; i < values.length; ++i)
+ {
+ if (i > 0)
+ result.append(", ");
+ result.append(values[i]);
+ }
+ return result.toString();
+ }
+
+ /**
* @return whether the header has multiple values
*/
public boolean hasMultipleValues()
diff --git a/jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/api/HeadersInfo.java b/jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/api/HeadersInfo.java
index 62ae07f609..97a6a7e59c 100644
--- a/jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/api/HeadersInfo.java
+++ b/jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/api/HeadersInfo.java
@@ -1,18 +1,15 @@
-/*
- * Copyright (c) 2012 the original author or authors.
- *
- * 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.
- */
+//========================================================================
+//Copyright 2011-2012 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.spdy.api;
diff --git a/jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/api/PingInfo.java b/jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/api/PingInfo.java
index bbcd9a87d0..28bc7a7c99 100644
--- a/jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/api/PingInfo.java
+++ b/jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/api/PingInfo.java
@@ -1,18 +1,15 @@
-/*
- * Copyright (c) 2012 the original author or authors.
- *
- * 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.
- */
+//========================================================================
+//Copyright 2011-2012 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.spdy.api;
diff --git a/jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/api/ReplyInfo.java b/jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/api/ReplyInfo.java
index 9ce0ef6eb5..9e511436e6 100644
--- a/jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/api/ReplyInfo.java
+++ b/jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/api/ReplyInfo.java
@@ -1,18 +1,15 @@
-/*
- * Copyright (c) 2012 the original author or authors.
- *
- * 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.
- */
+//========================================================================
+//Copyright 2011-2012 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.spdy.api;
diff --git a/jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/api/RstInfo.java b/jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/api/RstInfo.java
index f1f5ee482a..101fd71396 100644
--- a/jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/api/RstInfo.java
+++ b/jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/api/RstInfo.java
@@ -1,18 +1,15 @@
-/*
- * Copyright (c) 2012 the original author or authors.
- *
- * 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.
- */
+//========================================================================
+//Copyright 2011-2012 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.spdy.api;
diff --git a/jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/api/SPDY.java b/jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/api/SPDY.java
index 8ec2d8d668..31d7620ad5 100644
--- a/jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/api/SPDY.java
+++ b/jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/api/SPDY.java
@@ -1,18 +1,15 @@
-/*
- * Copyright (c) 2012 the original author or authors.
- *
- * 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.
- */
+//========================================================================
+//Copyright 2011-2012 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.spdy.api;
diff --git a/jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/api/SPDYException.java b/jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/api/SPDYException.java
index a0585f7ad7..af21428e87 100644
--- a/jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/api/SPDYException.java
+++ b/jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/api/SPDYException.java
@@ -1,18 +1,15 @@
-/*
- * Copyright (c) 2012 the original author or authors.
- *
- * 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.
- */
+//========================================================================
+//Copyright 2011-2012 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.spdy.api;
diff --git a/jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/api/Session.java b/jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/api/Session.java
index 5e2e5e281d..bbe17fc729 100644
--- a/jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/api/Session.java
+++ b/jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/api/Session.java
@@ -1,18 +1,15 @@
-/*
- * Copyright (c) 2012 the original author or authors.
- *
- * 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.
- */
+//========================================================================
+//Copyright 2011-2012 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.spdy.api;
@@ -75,7 +72,7 @@ public interface Session
* @see #syn(SynInfo, StreamFrameListener, long, TimeUnit, Handler)
*/
public Future<Stream> syn(SynInfo synInfo, StreamFrameListener listener);
-
+
/**
* <p>Sends asynchronously a SYN_FRAME to create a new {@link Stream SPDY stream}.</p>
* <p>Callers may pass a non-null completion handler to be notified of when the
@@ -90,7 +87,7 @@ public interface Session
*/
public void syn(SynInfo synInfo, StreamFrameListener listener, long timeout, TimeUnit unit, Handler<Stream> handler);
-
+
/**
* <p>Sends asynchronously a RST_STREAM to abort a stream.</p>
* <p>Callers may use the returned future to wait for the reset to be sent.</p>
@@ -180,11 +177,41 @@ public interface Session
public void goAway(long timeout, TimeUnit unit, Handler<Void> handler);
/**
- * @return the streams currently active in this session
+ * @return a snapshot of the streams currently active in this session
+ * @see #getStream(int)
*/
public Set<Stream> getStreams();
/**
+ * @param streamId the id of the stream to retrieve
+ * @return the stream with the given stream id
+ * @see #getStreams()
+ */
+ public Stream getStream(int streamId);
+
+ /**
+ * @param key the attribute key
+ * @return an arbitrary object associated with the given key to this session
+ * @see #setAttribute(String, Object)
+ */
+ public Object getAttribute(String key);
+
+ /**
+ * @param key the attribute key
+ * @param value an arbitrary object to associate with the given key to this session
+ * @see #getAttribute(String)
+ * @see #removeAttribute(String)
+ */
+ public void setAttribute(String key, Object value);
+
+ /**
+ * @param key the attribute key
+ * @return the arbitrary object associated with the given key to this session
+ * @see #setAttribute(String, Object)
+ */
+ public Object removeAttribute(String key);
+
+ /**
* <p>Super interface for listeners with callbacks that are invoked on specific session events.</p>
*/
public interface Listener extends EventListener
diff --git a/jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/api/SessionFrameListener.java b/jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/api/SessionFrameListener.java
index 467919c29c..7e507e3fd8 100644
--- a/jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/api/SessionFrameListener.java
+++ b/jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/api/SessionFrameListener.java
@@ -1,18 +1,15 @@
-/*
- * Copyright (c) 2012 the original author or authors.
- *
- * 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.
- */
+//========================================================================
+//Copyright 2011-2012 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.spdy.api;
diff --git a/jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/api/SessionStatus.java b/jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/api/SessionStatus.java
index c9c40d137f..56e9355ef1 100644
--- a/jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/api/SessionStatus.java
+++ b/jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/api/SessionStatus.java
@@ -1,18 +1,15 @@
-/*
- * Copyright (c) 2012 the original author or authors.
- *
- * 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.
- */
+//========================================================================
+//Copyright 2011-2012 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.spdy.api;
diff --git a/jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/api/Settings.java b/jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/api/Settings.java
index 6db03e814c..6ed59a00db 100644
--- a/jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/api/Settings.java
+++ b/jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/api/Settings.java
@@ -1,18 +1,15 @@
-/*
- * Copyright (c) 2012 the original author or authors.
- *
- * 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.
- */
+//========================================================================
+//Copyright 2011-2012 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.spdy.api;
diff --git a/jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/api/SettingsInfo.java b/jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/api/SettingsInfo.java
index 3823382d3d..d622189797 100644
--- a/jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/api/SettingsInfo.java
+++ b/jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/api/SettingsInfo.java
@@ -1,18 +1,15 @@
-/*
- * Copyright (c) 2012 the original author or authors.
- *
- * 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.
- */
+//========================================================================
+//Copyright 2011-2012 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.spdy.api;
diff --git a/jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/api/Stream.java b/jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/api/Stream.java
index c7f6e3537d..092c7a3549 100644
--- a/jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/api/Stream.java
+++ b/jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/api/Stream.java
@@ -1,18 +1,15 @@
-/*
- * Copyright (c) 2012 the original author or authors.
- *
- * 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.
- */
+//========================================================================
+//Copyright 2011-2012 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.spdy.api;
diff --git a/jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/api/StreamFrameListener.java b/jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/api/StreamFrameListener.java
index a279f38a01..23b5b16943 100644
--- a/jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/api/StreamFrameListener.java
+++ b/jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/api/StreamFrameListener.java
@@ -1,18 +1,15 @@
-/*
- * Copyright (c) 2012 the original author or authors.
- *
- * 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.
- */
+//========================================================================
+//Copyright 2011-2012 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.spdy.api;
diff --git a/jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/api/StreamStatus.java b/jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/api/StreamStatus.java
index c9908c8a14..b3e48e0b48 100644
--- a/jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/api/StreamStatus.java
+++ b/jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/api/StreamStatus.java
@@ -1,18 +1,15 @@
-/*
- * Copyright (c) 2012 the original author or authors.
- *
- * 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.
- */
+//========================================================================
+//Copyright 2011-2012 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.spdy.api;
diff --git a/jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/api/StringDataInfo.java b/jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/api/StringDataInfo.java
index 41e9e62330..164c6fb430 100644
--- a/jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/api/StringDataInfo.java
+++ b/jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/api/StringDataInfo.java
@@ -1,18 +1,15 @@
-/*
- * Copyright (c) 2012 the original author or authors.
- *
- * 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.
- */
+//========================================================================
+//Copyright 2011-2012 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.spdy.api;
@@ -25,11 +22,6 @@ public class StringDataInfo extends BytesDataInfo
{
public StringDataInfo(String string, boolean close)
{
- this(string, close, false);
- }
-
- public StringDataInfo(String string, boolean close, boolean compress)
- {
- super(string.getBytes(Charset.forName("UTF-8")), close, compress);
+ super(string.getBytes(Charset.forName("UTF-8")), close);
}
}
diff --git a/jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/api/SynInfo.java b/jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/api/SynInfo.java
index c51a0016dd..3f8eb605df 100644
--- a/jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/api/SynInfo.java
+++ b/jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/api/SynInfo.java
@@ -1,18 +1,15 @@
-/*
- * Copyright (c) 2012 the original author or authors.
- *
- * 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.
- */
+//========================================================================
+//Copyright 2011-2012 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.spdy.api;
diff --git a/jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/api/server/ServerSessionFrameListener.java b/jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/api/server/ServerSessionFrameListener.java
index 7941550569..7b330a9cea 100644
--- a/jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/api/server/ServerSessionFrameListener.java
+++ b/jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/api/server/ServerSessionFrameListener.java
@@ -1,18 +1,15 @@
-/*
- * Copyright (c) 2012 the original author or authors.
- *
- * 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.
- */
+//========================================================================
+//Copyright 2011-2012 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.spdy.api.server;
diff --git a/jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/frames/ControlFrame.java b/jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/frames/ControlFrame.java
index afd554c67e..a9c7b0a5af 100644
--- a/jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/frames/ControlFrame.java
+++ b/jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/frames/ControlFrame.java
@@ -1,18 +1,15 @@
-/*
- * Copyright (c) 2012 the original author or authors.
- *
- * 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.
- */
+//========================================================================
+//Copyright 2011-2012 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.spdy.frames;
diff --git a/jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/frames/ControlFrameType.java b/jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/frames/ControlFrameType.java
index bf638d3bf5..1fb28346d6 100644
--- a/jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/frames/ControlFrameType.java
+++ b/jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/frames/ControlFrameType.java
@@ -1,18 +1,15 @@
-/*
- * Copyright (c) 2012 the original author or authors.
- *
- * 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.
- */
+//========================================================================
+//Copyright 2011-2012 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.spdy.frames;
@@ -29,7 +26,8 @@ public enum ControlFrameType
PING((short)6),
GO_AWAY((short)7),
HEADERS((short)8),
- WINDOW_UPDATE((short)9);
+ WINDOW_UPDATE((short)9),
+ CREDENTIAL((short)10);
public static ControlFrameType from(short code)
{
diff --git a/jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/frames/CredentialFrame.java b/jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/frames/CredentialFrame.java
new file mode 100644
index 0000000000..5bd882fb96
--- /dev/null
+++ b/jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/frames/CredentialFrame.java
@@ -0,0 +1,46 @@
+//========================================================================
+//Copyright 2011-2012 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.spdy.frames;
+
+import java.security.cert.Certificate;
+
+public class CredentialFrame extends ControlFrame
+{
+ private final short slot;
+ private final byte[] proof;
+ private final Certificate[] certificateChain;
+
+ public CredentialFrame(short version, short slot, byte[] proof, Certificate[] certificateChain)
+ {
+ super(version, ControlFrameType.CREDENTIAL, (byte)0);
+ this.slot = slot;
+ this.proof = proof;
+ this.certificateChain = certificateChain;
+ }
+
+ public short getSlot()
+ {
+ return slot;
+ }
+
+ public byte[] getProof()
+ {
+ return proof;
+ }
+
+ public Certificate[] getCertificateChain()
+ {
+ return certificateChain;
+ }
+}
diff --git a/jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/frames/DataFrame.java b/jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/frames/DataFrame.java
index 3ce17eeb9f..e261bf8f5e 100644
--- a/jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/frames/DataFrame.java
+++ b/jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/frames/DataFrame.java
@@ -1,18 +1,15 @@
-/*
- * Copyright (c) 2012 the original author or authors.
- *
- * 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.
- */
+//========================================================================
+//Copyright 2011-2012 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.spdy.frames;
diff --git a/jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/frames/GoAwayFrame.java b/jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/frames/GoAwayFrame.java
index bda5755522..15f04f1a4d 100644
--- a/jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/frames/GoAwayFrame.java
+++ b/jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/frames/GoAwayFrame.java
@@ -1,18 +1,15 @@
-/*
- * Copyright (c) 2012 the original author or authors.
- *
- * 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.
- */
+//========================================================================
+//Copyright 2011-2012 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.spdy.frames;
diff --git a/jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/frames/HeadersFrame.java b/jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/frames/HeadersFrame.java
index e0545b6870..ea88513075 100644
--- a/jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/frames/HeadersFrame.java
+++ b/jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/frames/HeadersFrame.java
@@ -1,18 +1,15 @@
-/*
- * Copyright (c) 2012 the original author or authors.
- *
- * 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.
- */
+//========================================================================
+//Copyright 2011-2012 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.spdy.frames;
diff --git a/jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/frames/NoOpFrame.java b/jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/frames/NoOpFrame.java
index bf9eac00f3..e4cffcc3f7 100644
--- a/jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/frames/NoOpFrame.java
+++ b/jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/frames/NoOpFrame.java
@@ -1,18 +1,15 @@
-/*
- * Copyright (c) 2012 the original author or authors.
- *
- * 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.
- */
+//========================================================================
+//Copyright 2011-2012 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.spdy.frames;
diff --git a/jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/frames/PingFrame.java b/jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/frames/PingFrame.java
index aa1ac543d2..3989a09ccc 100644
--- a/jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/frames/PingFrame.java
+++ b/jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/frames/PingFrame.java
@@ -1,18 +1,15 @@
-/*
- * Copyright (c) 2012 the original author or authors.
- *
- * 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.
- */
+//========================================================================
+//Copyright 2011-2012 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.spdy.frames;
diff --git a/jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/frames/RstStreamFrame.java b/jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/frames/RstStreamFrame.java
index 334b8166ac..0877da45d5 100644
--- a/jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/frames/RstStreamFrame.java
+++ b/jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/frames/RstStreamFrame.java
@@ -1,18 +1,15 @@
-/*
- * Copyright (c) 2012 the original author or authors.
- *
- * 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.
- */
+//========================================================================
+//Copyright 2011-2012 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.spdy.frames;
diff --git a/jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/frames/SettingsFrame.java b/jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/frames/SettingsFrame.java
index afddb371fa..8b676cde73 100644
--- a/jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/frames/SettingsFrame.java
+++ b/jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/frames/SettingsFrame.java
@@ -1,18 +1,15 @@
-/*
- * Copyright (c) 2012 the original author or authors.
- *
- * 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.
- */
+//========================================================================
+//Copyright 2011-2012 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.spdy.frames;
diff --git a/jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/frames/SynReplyFrame.java b/jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/frames/SynReplyFrame.java
index 9108168638..82888b14bf 100644
--- a/jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/frames/SynReplyFrame.java
+++ b/jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/frames/SynReplyFrame.java
@@ -1,18 +1,15 @@
-/*
- * Copyright (c) 2012 the original author or authors.
- *
- * 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.
- */
+//========================================================================
+//Copyright 2011-2012 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.spdy.frames;
diff --git a/jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/frames/SynStreamFrame.java b/jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/frames/SynStreamFrame.java
index 1b4089541c..c5aa8d3bc5 100644
--- a/jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/frames/SynStreamFrame.java
+++ b/jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/frames/SynStreamFrame.java
@@ -1,18 +1,15 @@
-/*
- * Copyright (c) 2012 the original author or authors.
- *
- * 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.
- */
+//========================================================================
+//Copyright 2011-2012 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.spdy.frames;
@@ -25,14 +22,16 @@ public class SynStreamFrame extends ControlFrame
private final int streamId;
private final int associatedStreamId;
private final byte priority;
+ private final short slot;
private final Headers headers;
- public SynStreamFrame(short version, byte flags, int streamId, int associatedStreamId, byte priority, Headers headers)
+ public SynStreamFrame(short version, byte flags, int streamId, int associatedStreamId, byte priority, short slot, Headers headers)
{
super(version, ControlFrameType.SYN_STREAM, flags);
this.streamId = streamId;
this.associatedStreamId = associatedStreamId;
this.priority = priority;
+ this.slot = slot;
this.headers = headers;
}
@@ -51,6 +50,11 @@ public class SynStreamFrame extends ControlFrame
return priority;
}
+ public short getSlot()
+ {
+ return slot;
+ }
+
public Headers getHeaders()
{
return headers;
diff --git a/jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/frames/WindowUpdateFrame.java b/jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/frames/WindowUpdateFrame.java
index 22a4129e76..8ed37d4784 100644
--- a/jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/frames/WindowUpdateFrame.java
+++ b/jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/frames/WindowUpdateFrame.java
@@ -1,18 +1,15 @@
-/*
- * Copyright (c) 2012 the original author or authors.
- *
- * 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.
- */
+//========================================================================
+//Copyright 2011-2012 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.spdy.frames;
diff --git a/jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/generator/ControlFrameGenerator.java b/jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/generator/ControlFrameGenerator.java
index c872beddb6..ff7302cfc7 100644
--- a/jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/generator/ControlFrameGenerator.java
+++ b/jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/generator/ControlFrameGenerator.java
@@ -1,18 +1,15 @@
-/*
- * Copyright (c) 2012 the original author or authors.
- *
- * 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.
- */
+//========================================================================
+//Copyright 2011-2012 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.spdy.generator;
diff --git a/jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/generator/CredentialGenerator.java b/jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/generator/CredentialGenerator.java
new file mode 100644
index 0000000000..f2064fb68f
--- /dev/null
+++ b/jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/generator/CredentialGenerator.java
@@ -0,0 +1,80 @@
+//========================================================================
+//Copyright 2011-2012 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.spdy.generator;
+
+import java.nio.ByteBuffer;
+import java.security.cert.Certificate;
+import java.security.cert.CertificateEncodingException;
+import java.util.ArrayList;
+import java.util.List;
+
+import org.eclipse.jetty.spdy.ByteBufferPool;
+import org.eclipse.jetty.spdy.SessionException;
+import org.eclipse.jetty.spdy.api.SessionStatus;
+import org.eclipse.jetty.spdy.frames.ControlFrame;
+import org.eclipse.jetty.spdy.frames.CredentialFrame;
+
+public class CredentialGenerator extends ControlFrameGenerator
+{
+ public CredentialGenerator(ByteBufferPool bufferPool)
+ {
+ super(bufferPool);
+ }
+
+ @Override
+ public ByteBuffer generate(ControlFrame frame)
+ {
+ CredentialFrame credential = (CredentialFrame)frame;
+
+ byte[] proof = credential.getProof();
+
+ List<byte[]> certificates = serializeCertificates(credential.getCertificateChain());
+ int certificatesLength = 0;
+ for (byte[] certificate : certificates)
+ certificatesLength += certificate.length;
+
+ int frameBodyLength = 2 + 4 + proof.length + certificates.size() * 4 + certificatesLength;
+
+ int totalLength = ControlFrame.HEADER_LENGTH + frameBodyLength;
+ ByteBuffer buffer = getByteBufferPool().acquire(totalLength, true);
+ generateControlFrameHeader(credential, frameBodyLength, buffer);
+
+ buffer.putShort(credential.getSlot());
+ buffer.putInt(proof.length);
+ buffer.put(proof);
+ for (byte[] certificate : certificates)
+ {
+ buffer.putInt(certificate.length);
+ buffer.put(certificate);
+ }
+
+ buffer.flip();
+ return buffer;
+ }
+
+ private List<byte[]> serializeCertificates(Certificate[] certificates)
+ {
+ try
+ {
+ List<byte[]> result = new ArrayList<>(certificates.length);
+ for (Certificate certificate : certificates)
+ result.add(certificate.getEncoded());
+ return result;
+ }
+ catch (CertificateEncodingException x)
+ {
+ throw new SessionException(SessionStatus.PROTOCOL_ERROR, x);
+ }
+ }
+}
diff --git a/jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/generator/DataFrameGenerator.java b/jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/generator/DataFrameGenerator.java
index 075cbc081f..aed8fbc758 100644
--- a/jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/generator/DataFrameGenerator.java
+++ b/jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/generator/DataFrameGenerator.java
@@ -1,19 +1,15 @@
-/*
- * Copyright (c) 2012 the original author or authors.
- *
- * 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.
- */
-
+//========================================================================
+//Copyright 2011-2012 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.spdy.generator;
import java.nio.ByteBuffer;
diff --git a/jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/generator/Generator.java b/jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/generator/Generator.java
index 70462c6ddd..cccbf15586 100644
--- a/jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/generator/Generator.java
+++ b/jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/generator/Generator.java
@@ -1,18 +1,15 @@
-/*
- * Copyright (c) 2012 the original author or authors.
- *
- * 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.
- */
+//========================================================================
+//Copyright 2011-2012 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.spdy.generator;
@@ -42,6 +39,7 @@ public class Generator
generators.put(ControlFrameType.GO_AWAY, new GoAwayGenerator(bufferPool));
generators.put(ControlFrameType.HEADERS, new HeadersGenerator(bufferPool, headersBlockGenerator));
generators.put(ControlFrameType.WINDOW_UPDATE, new WindowUpdateGenerator(bufferPool));
+ generators.put(ControlFrameType.CREDENTIAL, new CredentialGenerator(bufferPool));
dataFrameGenerator = new DataFrameGenerator(bufferPool);
}
diff --git a/jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/generator/GoAwayGenerator.java b/jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/generator/GoAwayGenerator.java
index 80c824f860..dced42a64e 100644
--- a/jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/generator/GoAwayGenerator.java
+++ b/jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/generator/GoAwayGenerator.java
@@ -1,18 +1,15 @@
-/*
- * Copyright (c) 2012 the original author or authors.
- *
- * 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.
- */
+//========================================================================
+//Copyright 2011-2012 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.spdy.generator;
diff --git a/jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/generator/HeadersBlockGenerator.java b/jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/generator/HeadersBlockGenerator.java
index 93a2dd6210..6290841b79 100644
--- a/jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/generator/HeadersBlockGenerator.java
+++ b/jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/generator/HeadersBlockGenerator.java
@@ -1,18 +1,15 @@
-/*
- * Copyright (c) 2012 the original author or authors.
- *
- * 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.
- */
+//========================================================================
+//Copyright 2011-2012 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.spdy.generator;
@@ -43,7 +40,7 @@ public class HeadersBlockGenerator
writeCount(version, buffer, headers.size());
for (Headers.Header header : headers)
{
- String name = header.name();
+ String name = header.name().toLowerCase();
byte[] nameBytes = name.getBytes(iso1);
writeNameLength(version, buffer, nameBytes.length);
buffer.write(nameBytes, 0, nameBytes.length);
diff --git a/jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/generator/HeadersGenerator.java b/jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/generator/HeadersGenerator.java
index e979330ff7..6f520d91ea 100644
--- a/jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/generator/HeadersGenerator.java
+++ b/jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/generator/HeadersGenerator.java
@@ -1,18 +1,15 @@
-/*
- * Copyright (c) 2012 the original author or authors.
- *
- * 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.
- */
+//========================================================================
+//Copyright 2011-2012 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.spdy.generator;
@@ -20,6 +17,7 @@ import java.nio.ByteBuffer;
import org.eclipse.jetty.spdy.ByteBufferPool;
import org.eclipse.jetty.spdy.SessionException;
+import org.eclipse.jetty.spdy.api.SPDY;
import org.eclipse.jetty.spdy.api.SessionStatus;
import org.eclipse.jetty.spdy.frames.ControlFrame;
import org.eclipse.jetty.spdy.frames.HeadersFrame;
@@ -43,6 +41,8 @@ public class HeadersGenerator extends ControlFrameGenerator
ByteBuffer headersBuffer = headersBlockGenerator.generate(version, headers.getHeaders());
int frameBodyLength = 4;
+ if (frame.getVersion() == SPDY.V2)
+ frameBodyLength += 2;
int frameLength = frameBodyLength + headersBuffer.remaining();
if (frameLength > 0xFF_FF_FF)
@@ -58,6 +58,8 @@ public class HeadersGenerator extends ControlFrameGenerator
generateControlFrameHeader(headers, frameLength, buffer);
buffer.putInt(headers.getStreamId() & 0x7F_FF_FF_FF);
+ if (frame.getVersion() == SPDY.V2)
+ buffer.putShort((short)0);
buffer.put(headersBuffer);
diff --git a/jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/generator/NoOpGenerator.java b/jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/generator/NoOpGenerator.java
index 5678df329c..86a2feb5c0 100644
--- a/jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/generator/NoOpGenerator.java
+++ b/jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/generator/NoOpGenerator.java
@@ -1,18 +1,15 @@
-/*
- * Copyright (c) 2012 the original author or authors.
- *
- * 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.
- */
+//========================================================================
+//Copyright 2011-2012 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.spdy.generator;
diff --git a/jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/generator/PingGenerator.java b/jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/generator/PingGenerator.java
index ae2a3e4ebc..0ead892baa 100644
--- a/jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/generator/PingGenerator.java
+++ b/jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/generator/PingGenerator.java
@@ -1,18 +1,15 @@
-/*
- * Copyright (c) 2012 the original author or authors.
- *
- * 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.
- */
+//========================================================================
+//Copyright 2011-2012 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.spdy.generator;
diff --git a/jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/generator/RstStreamGenerator.java b/jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/generator/RstStreamGenerator.java
index d7d1a21af6..63a014250e 100644
--- a/jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/generator/RstStreamGenerator.java
+++ b/jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/generator/RstStreamGenerator.java
@@ -1,18 +1,15 @@
-/*
- * Copyright (c) 2012 the original author or authors.
- *
- * 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.
- */
+//========================================================================
+//Copyright 2011-2012 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.spdy.generator;
diff --git a/jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/generator/SettingsGenerator.java b/jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/generator/SettingsGenerator.java
index c61846ebd8..6004afa905 100644
--- a/jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/generator/SettingsGenerator.java
+++ b/jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/generator/SettingsGenerator.java
@@ -1,18 +1,15 @@
-/*
- * Copyright (c) 2012 the original author or authors.
- *
- * 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.
- */
+//========================================================================
+//Copyright 2011-2012 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.spdy.generator;
diff --git a/jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/generator/SynReplyGenerator.java b/jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/generator/SynReplyGenerator.java
index 4820086da2..fc8f382700 100644
--- a/jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/generator/SynReplyGenerator.java
+++ b/jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/generator/SynReplyGenerator.java
@@ -1,18 +1,15 @@
-/*
- * Copyright (c) 2012 the original author or authors.
- *
- * 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.
- */
+//========================================================================
+//Copyright 2011-2012 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.spdy.generator;
diff --git a/jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/generator/SynStreamGenerator.java b/jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/generator/SynStreamGenerator.java
index cf432e1496..ff6ace8699 100644
--- a/jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/generator/SynStreamGenerator.java
+++ b/jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/generator/SynStreamGenerator.java
@@ -1,18 +1,15 @@
-/*
- * Copyright (c) 2012 the original author or authors.
- *
- * 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.
- */
+//========================================================================
+//Copyright 2011-2012 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.spdy.generator;
@@ -64,6 +61,7 @@ public class SynStreamGenerator extends ControlFrameGenerator
buffer.putInt(streamId & 0x7F_FF_FF_FF);
buffer.putInt(synStream.getAssociatedStreamId() & 0x7F_FF_FF_FF);
writePriority(streamId, version, synStream.getPriority(), buffer);
+ buffer.put((byte)synStream.getSlot());
buffer.put(headersBuffer);
@@ -85,6 +83,5 @@ public class SynStreamGenerator extends ControlFrameGenerator
throw new StreamException(streamId, StreamStatus.UNSUPPORTED_VERSION);
}
buffer.put(priority);
- buffer.put((byte)0);
}
}
diff --git a/jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/generator/WindowUpdateGenerator.java b/jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/generator/WindowUpdateGenerator.java
index 329d058489..38092803cf 100644
--- a/jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/generator/WindowUpdateGenerator.java
+++ b/jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/generator/WindowUpdateGenerator.java
@@ -1,18 +1,15 @@
-/*
- * Copyright (c) 2012 the original author or authors.
- *
- * 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.
- */
+//========================================================================
+//Copyright 2011-2012 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.spdy.generator;
diff --git a/jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/parser/ControlFrameBodyParser.java b/jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/parser/ControlFrameBodyParser.java
index a9499a8ad4..f820b599c8 100644
--- a/jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/parser/ControlFrameBodyParser.java
+++ b/jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/parser/ControlFrameBodyParser.java
@@ -1,18 +1,15 @@
-/*
- * Copyright (c) 2012 the original author or authors.
- *
- * 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.
- */
+//========================================================================
+//Copyright 2011-2012 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.spdy.parser;
diff --git a/jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/parser/ControlFrameParser.java b/jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/parser/ControlFrameParser.java
index af8b78f654..73c0189866 100644
--- a/jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/parser/ControlFrameParser.java
+++ b/jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/parser/ControlFrameParser.java
@@ -1,18 +1,15 @@
-/*
- * Copyright (c) 2012 the original author or authors.
- *
- * 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.
- */
+//========================================================================
+//Copyright 2011-2012 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.spdy.parser;
@@ -46,6 +43,7 @@ public abstract class ControlFrameParser
parsers.put(ControlFrameType.GO_AWAY, new GoAwayBodyParser(this));
parsers.put(ControlFrameType.HEADERS, new HeadersBodyParser(decompressor, this));
parsers.put(ControlFrameType.WINDOW_UPDATE, new WindowUpdateBodyParser(this));
+ parsers.put(ControlFrameType.CREDENTIAL, new CredentialBodyParser(this));
}
public short getVersion()
diff --git a/jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/parser/CredentialBodyParser.java b/jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/parser/CredentialBodyParser.java
new file mode 100644
index 0000000000..0dbb3d6b8e
--- /dev/null
+++ b/jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/parser/CredentialBodyParser.java
@@ -0,0 +1,269 @@
+//========================================================================
+//Copyright 2011-2012 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.spdy.parser;
+
+import java.io.ByteArrayInputStream;
+import java.nio.ByteBuffer;
+import java.security.cert.Certificate;
+import java.security.cert.CertificateException;
+import java.security.cert.CertificateFactory;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+
+import org.eclipse.jetty.spdy.SessionException;
+import org.eclipse.jetty.spdy.api.SessionStatus;
+import org.eclipse.jetty.spdy.frames.ControlFrameType;
+import org.eclipse.jetty.spdy.frames.CredentialFrame;
+
+public class CredentialBodyParser extends ControlFrameBodyParser
+{
+ private final List<Certificate> certificates = new ArrayList<>();
+ private final ControlFrameParser controlFrameParser;
+ private State state = State.SLOT;
+ private int totalLength;
+ private int cursor;
+ private short slot;
+ private int proofLength;
+ private byte[] proof;
+ private int certificateLength;
+ private byte[] certificate;
+
+ public CredentialBodyParser(ControlFrameParser controlFrameParser)
+ {
+ this.controlFrameParser = controlFrameParser;
+ }
+
+ @Override
+ public boolean parse(ByteBuffer buffer)
+ {
+ while (buffer.hasRemaining())
+ {
+ switch (state)
+ {
+ case SLOT:
+ {
+ if (buffer.remaining() >= 2)
+ {
+ slot = buffer.getShort();
+ checkSlotValid();
+ state = State.PROOF_LENGTH;
+ }
+ else
+ {
+ state = State.SLOT_BYTES;
+ cursor = 2;
+ }
+ break;
+ }
+ case SLOT_BYTES:
+ {
+ byte currByte = buffer.get();
+ --cursor;
+ slot += (currByte & 0xFF) << 8 * cursor;
+ if (cursor == 0)
+ {
+ checkSlotValid();
+ state = State.PROOF_LENGTH;
+ }
+ break;
+ }
+ case PROOF_LENGTH:
+ {
+ if (buffer.remaining() >= 4)
+ {
+ proofLength = buffer.getInt() & 0x7F_FF_FF_FF;
+ state = State.PROOF;
+ }
+ else
+ {
+ state = State.PROOF_LENGTH_BYTES;
+ cursor = 4;
+ }
+ break;
+ }
+ case PROOF_LENGTH_BYTES:
+ {
+ byte currByte = buffer.get();
+ --cursor;
+ proofLength += (currByte & 0xFF) << 8 * cursor;
+ if (cursor == 0)
+ {
+ proofLength &= 0x7F_FF_FF_FF;
+ state = State.PROOF;
+ }
+ break;
+ }
+ case PROOF:
+ {
+ totalLength = controlFrameParser.getLength() - 2 - 4 - proofLength;
+ proof = new byte[proofLength];
+ if (buffer.remaining() >= proofLength)
+ {
+ buffer.get(proof);
+ state = State.CERTIFICATE_LENGTH;
+ if (totalLength == 0)
+ {
+ onCredential();
+ return true;
+ }
+ }
+ else
+ {
+ state = State.PROOF_BYTES;
+ cursor = proofLength;
+ }
+ break;
+ }
+ case PROOF_BYTES:
+ {
+ proof[proofLength - cursor] = buffer.get();
+ --cursor;
+ if (cursor == 0)
+ {
+ state = State.CERTIFICATE_LENGTH;
+ if (totalLength == 0)
+ {
+ onCredential();
+ return true;
+ }
+ }
+ break;
+ }
+ case CERTIFICATE_LENGTH:
+ {
+ if (buffer.remaining() >= 4)
+ {
+ certificateLength = buffer.getInt() & 0x7F_FF_FF_FF;
+ state = State.CERTIFICATE;
+ }
+ else
+ {
+ state = State.CERTIFICATE_LENGTH_BYTES;
+ cursor = 4;
+ }
+ break;
+ }
+ case CERTIFICATE_LENGTH_BYTES:
+ {
+ byte currByte = buffer.get();
+ --cursor;
+ certificateLength += (currByte & 0xFF) << 8 * cursor;
+ if (cursor == 0)
+ {
+ certificateLength &= 0x7F_FF_FF_FF;
+ state = State.CERTIFICATE;
+ }
+ break;
+ }
+ case CERTIFICATE:
+ {
+ totalLength -= 4 + certificateLength;
+ certificate = new byte[certificateLength];
+ if (buffer.remaining() >= certificateLength)
+ {
+ buffer.get(certificate);
+ if (onCertificate())
+ return true;
+ }
+ else
+ {
+ state = State.CERTIFICATE_BYTES;
+ cursor = certificateLength;
+ }
+ break;
+ }
+ case CERTIFICATE_BYTES:
+ {
+ certificate[certificateLength - cursor] = buffer.get();
+ --cursor;
+ if (cursor == 0)
+ {
+ if (onCertificate())
+ return true;
+ }
+ break;
+ }
+ default:
+ {
+ throw new IllegalStateException();
+ }
+ }
+ }
+ return false;
+ }
+
+ private void checkSlotValid()
+ {
+ if (slot <= 0)
+ throw new SessionException(SessionStatus.PROTOCOL_ERROR,
+ "Invalid slot " + slot + " for " + ControlFrameType.CREDENTIAL + " frame");
+ }
+
+ private boolean onCertificate()
+ {
+ certificates.add(deserializeCertificate(certificate));
+ if (totalLength == 0)
+ {
+ onCredential();
+ return true;
+ }
+ else
+ {
+ certificateLength = 0;
+ state = State.CERTIFICATE_LENGTH;
+ }
+ return false;
+ }
+
+ private Certificate deserializeCertificate(byte[] bytes)
+ {
+ try
+ {
+ CertificateFactory certificateFactory = CertificateFactory.getInstance("X.509");
+ return certificateFactory.generateCertificate(new ByteArrayInputStream(bytes));
+ }
+ catch (CertificateException x)
+ {
+ throw new SessionException(SessionStatus.PROTOCOL_ERROR, x);
+ }
+ }
+
+ private void onCredential()
+ {
+ CredentialFrame frame = new CredentialFrame(controlFrameParser.getVersion(), slot,
+ Arrays.copyOf(proof, proof.length), certificates.toArray(new Certificate[certificates.size()]));
+ controlFrameParser.onControlFrame(frame);
+ reset();
+ }
+
+ private void reset()
+ {
+ state = State.SLOT;
+ totalLength = 0;
+ cursor = 0;
+ slot = 0;
+ proofLength = 0;
+ proof = null;
+ certificateLength = 0;
+ certificate = null;
+ certificates.clear();
+ }
+
+ public enum State
+ {
+ SLOT, SLOT_BYTES, PROOF_LENGTH, PROOF_LENGTH_BYTES, PROOF, PROOF_BYTES,
+ CERTIFICATE_LENGTH, CERTIFICATE_LENGTH_BYTES, CERTIFICATE, CERTIFICATE_BYTES
+ }
+}
diff --git a/jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/parser/DataFrameParser.java b/jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/parser/DataFrameParser.java
index 74ea686837..1926ab7352 100644
--- a/jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/parser/DataFrameParser.java
+++ b/jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/parser/DataFrameParser.java
@@ -1,18 +1,15 @@
-/*
- * Copyright (c) 2012 the original author or authors.
- *
- * 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.
- */
+//========================================================================
+//Copyright 2011-2012 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.spdy.parser;
diff --git a/jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/parser/GoAwayBodyParser.java b/jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/parser/GoAwayBodyParser.java
index 753ad804d4..cb9fd37d93 100644
--- a/jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/parser/GoAwayBodyParser.java
+++ b/jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/parser/GoAwayBodyParser.java
@@ -1,18 +1,15 @@
-/*
- * Copyright (c) 2012 the original author or authors.
- *
- * 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.
- */
+//========================================================================
+//Copyright 2011-2012 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.spdy.parser;
@@ -24,7 +21,7 @@ import org.eclipse.jetty.spdy.frames.GoAwayFrame;
public class GoAwayBodyParser extends ControlFrameBodyParser
{
private final ControlFrameParser controlFrameParser;
- private State state = State.LAST_STREAM_ID;
+ private State state = State.LAST_GOOD_STREAM_ID;
private int cursor;
private int lastStreamId;
private int statusCode;
@@ -41,7 +38,7 @@ public class GoAwayBodyParser extends ControlFrameBodyParser
{
switch (state)
{
- case LAST_STREAM_ID:
+ case LAST_GOOD_STREAM_ID:
{
if (buffer.remaining() >= 4)
{
@@ -66,12 +63,12 @@ public class GoAwayBodyParser extends ControlFrameBodyParser
}
else
{
- state = State.LAST_STREAM_ID_BYTES;
+ state = State.LAST_GOOD_STREAM_ID_BYTES;
cursor = 4;
}
break;
}
- case LAST_STREAM_ID_BYTES:
+ case LAST_GOOD_STREAM_ID_BYTES:
{
byte currByte = buffer.get();
--cursor;
@@ -144,7 +141,7 @@ public class GoAwayBodyParser extends ControlFrameBodyParser
private void reset()
{
- state = State.LAST_STREAM_ID;
+ state = State.LAST_GOOD_STREAM_ID;
cursor = 0;
lastStreamId = 0;
statusCode = 0;
@@ -152,6 +149,6 @@ public class GoAwayBodyParser extends ControlFrameBodyParser
private enum State
{
- LAST_STREAM_ID, LAST_STREAM_ID_BYTES, STATUS_CODE, STATUS_CODE_BYTES
+ LAST_GOOD_STREAM_ID, LAST_GOOD_STREAM_ID_BYTES, STATUS_CODE, STATUS_CODE_BYTES
}
}
diff --git a/jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/parser/HeadersBlockParser.java b/jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/parser/HeadersBlockParser.java
index 2b4b70bafb..60725f821e 100644
--- a/jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/parser/HeadersBlockParser.java
+++ b/jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/parser/HeadersBlockParser.java
@@ -1,18 +1,15 @@
-/*
- * Copyright (c) 2012 the original author or authors.
- *
- * 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.
- */
+//========================================================================
+//Copyright 2011-2012 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.spdy.parser;
diff --git a/jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/parser/HeadersBodyParser.java b/jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/parser/HeadersBodyParser.java
index 98bbc7ca25..a91a19c5c3 100644
--- a/jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/parser/HeadersBodyParser.java
+++ b/jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/parser/HeadersBodyParser.java
@@ -1,18 +1,15 @@
-/*
- * Copyright (c) 2012 the original author or authors.
- *
- * 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.
- */
+//========================================================================
+//Copyright 2011-2012 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.spdy.parser;
@@ -21,6 +18,7 @@ import java.nio.ByteBuffer;
import org.eclipse.jetty.spdy.CompressionFactory;
import org.eclipse.jetty.spdy.api.Headers;
import org.eclipse.jetty.spdy.api.HeadersInfo;
+import org.eclipse.jetty.spdy.api.SPDY;
import org.eclipse.jetty.spdy.frames.ControlFrameType;
import org.eclipse.jetty.spdy.frames.HeadersFrame;
@@ -51,7 +49,7 @@ public class HeadersBodyParser extends ControlFrameBodyParser
if (buffer.remaining() >= 4)
{
streamId = buffer.getInt() & 0x7F_FF_FF_FF;
- state = State.HEADERS;
+ state = State.ADDITIONAL;
}
else
{
@@ -68,14 +66,55 @@ public class HeadersBodyParser extends ControlFrameBodyParser
if (cursor == 0)
{
streamId &= 0x7F_FF_FF_FF;
- state = State.HEADERS;
+ state = State.ADDITIONAL;
+ }
+ break;
+ }
+ case ADDITIONAL:
+ {
+ switch (controlFrameParser.getVersion())
+ {
+ case SPDY.V2:
+ {
+ if (buffer.remaining() >= 2)
+ {
+ buffer.getShort();
+ state = State.HEADERS;
+ }
+ else
+ {
+ state = State.ADDITIONAL_BYTES;
+ cursor = 2;
+ }
+ break;
+ }
+ case SPDY.V3:
+ {
+ state = State.HEADERS;
+ break;
+ }
+ default:
+ {
+ throw new IllegalStateException();
+ }
}
break;
}
+ case ADDITIONAL_BYTES:
+ {
+ assert controlFrameParser.getVersion() == SPDY.V2;
+ buffer.get();
+ --cursor;
+ if (cursor == 0)
+ state = State.HEADERS;
+ break;
+ }
case HEADERS:
{
short version = controlFrameParser.getVersion();
int length = controlFrameParser.getLength() - 4;
+ if (version == SPDY.V2)
+ length -= 2;
if (headersBlockParser.parse(streamId, version, length, buffer))
{
byte flags = controlFrameParser.getFlags();
@@ -109,7 +148,7 @@ public class HeadersBodyParser extends ControlFrameBodyParser
private enum State
{
- STREAM_ID, STREAM_ID_BYTES, HEADERS
+ STREAM_ID, STREAM_ID_BYTES, ADDITIONAL, ADDITIONAL_BYTES, HEADERS
}
private class HeadersHeadersBlockParser extends HeadersBlockParser
diff --git a/jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/parser/NoOpBodyParser.java b/jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/parser/NoOpBodyParser.java
index ac14c798b5..f0efe09dd4 100644
--- a/jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/parser/NoOpBodyParser.java
+++ b/jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/parser/NoOpBodyParser.java
@@ -1,18 +1,15 @@
-/*
- * Copyright (c) 2012 the original author or authors.
- *
- * 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.
- */
+//========================================================================
+//Copyright 2011-2012 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.spdy.parser;
diff --git a/jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/parser/Parser.java b/jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/parser/Parser.java
index 8cc42e1814..df897603b5 100644
--- a/jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/parser/Parser.java
+++ b/jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/parser/Parser.java
@@ -1,18 +1,15 @@
-/*
- * Copyright (c) 2012 the original author or authors.
- *
- * 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.
- */
+//========================================================================
+//Copyright 2011-2012 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.spdy.parser;
diff --git a/jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/parser/PingBodyParser.java b/jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/parser/PingBodyParser.java
index 3f078f6e64..0e8ed61334 100644
--- a/jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/parser/PingBodyParser.java
+++ b/jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/parser/PingBodyParser.java
@@ -1,18 +1,15 @@
-/*
- * Copyright (c) 2012 the original author or authors.
- *
- * 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.
- */
+//========================================================================
+//Copyright 2011-2012 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.spdy.parser;
diff --git a/jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/parser/RstStreamBodyParser.java b/jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/parser/RstStreamBodyParser.java
index 81c9b3ccf8..e05aea4906 100644
--- a/jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/parser/RstStreamBodyParser.java
+++ b/jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/parser/RstStreamBodyParser.java
@@ -1,18 +1,15 @@
-/*
- * Copyright (c) 2012 the original author or authors.
- *
- * 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.
- */
+//========================================================================
+//Copyright 2011-2012 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.spdy.parser;
diff --git a/jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/parser/SettingsBodyParser.java b/jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/parser/SettingsBodyParser.java
index d76382ad0e..e4fc7c76ce 100644
--- a/jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/parser/SettingsBodyParser.java
+++ b/jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/parser/SettingsBodyParser.java
@@ -1,19 +1,15 @@
-/*
- * Copyright (c) 2012 the original author or authors.
- *
- * 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.
- */
-
+//========================================================================
+//Copyright 2011-2012 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.spdy.parser;
import java.nio.ByteBuffer;
diff --git a/jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/parser/SynReplyBodyParser.java b/jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/parser/SynReplyBodyParser.java
index ec58478f29..4c93210d3f 100644
--- a/jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/parser/SynReplyBodyParser.java
+++ b/jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/parser/SynReplyBodyParser.java
@@ -1,18 +1,15 @@
-/*
- * Copyright (c) 2012 the original author or authors.
- *
- * 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.
- */
+//========================================================================
+//Copyright 2011-2012 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.spdy.parser;
diff --git a/jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/parser/SynStreamBodyParser.java b/jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/parser/SynStreamBodyParser.java
index 14673b9e7d..ba54e739f9 100644
--- a/jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/parser/SynStreamBodyParser.java
+++ b/jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/parser/SynStreamBodyParser.java
@@ -1,18 +1,15 @@
-/*
- * Copyright (c) 2012 the original author or authors.
- *
- * 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.
- */
+//========================================================================
+//Copyright 2011-2012 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.spdy.parser;
@@ -38,6 +35,7 @@ public class SynStreamBodyParser extends ControlFrameBodyParser
private int streamId;
private int associatedStreamId;
private byte priority;
+ private short slot;
public SynStreamBodyParser(CompressionFactory.Decompressor decompressor, ControlFrameParser controlFrameParser)
{
@@ -118,7 +116,9 @@ public class SynStreamBodyParser extends ControlFrameBodyParser
}
else
{
- // Unused byte after priority, skip it
+ slot = (short)(currByte & 0xFF);
+ if (slot < 0)
+ throw new StreamException(streamId, StreamStatus.INVALID_CREDENTIALS);
cursor = 0;
state = State.HEADERS;
}
@@ -134,7 +134,7 @@ public class SynStreamBodyParser extends ControlFrameBodyParser
if (flags > (SynInfo.FLAG_CLOSE | PushSynInfo.FLAG_UNIDIRECTIONAL))
throw new IllegalArgumentException("Invalid flag " + flags + " for frame " + ControlFrameType.SYN_STREAM);
- SynStreamFrame frame = new SynStreamFrame(version, flags, streamId, associatedStreamId, priority, new Headers(headers, true));
+ SynStreamFrame frame = new SynStreamFrame(version, flags, streamId, associatedStreamId, priority, slot, new Headers(headers, true));
controlFrameParser.onControlFrame(frame);
reset();
diff --git a/jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/parser/UnknownControlFrameBodyParser.java b/jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/parser/UnknownControlFrameBodyParser.java
index ea5890ff6f..0de0d37eeb 100644
--- a/jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/parser/UnknownControlFrameBodyParser.java
+++ b/jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/parser/UnknownControlFrameBodyParser.java
@@ -1,18 +1,15 @@
-/*
- * Copyright (c) 2012 the original author or authors.
- *
- * 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.
- */
+//========================================================================
+//Copyright 2011-2012 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.spdy.parser;
diff --git a/jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/parser/WindowUpdateBodyParser.java b/jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/parser/WindowUpdateBodyParser.java
index 697b885308..9010a346bc 100644
--- a/jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/parser/WindowUpdateBodyParser.java
+++ b/jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/parser/WindowUpdateBodyParser.java
@@ -1,18 +1,15 @@
-/*
- * Copyright (c) 2012 the original author or authors.
- *
- * 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.
- */
+//========================================================================
+//Copyright 2011-2012 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.spdy.parser;
diff --git a/jetty-spdy/spdy-core/src/test/java/org/eclipse/jetty/spdy/AsyncTimeoutTest.java b/jetty-spdy/spdy-core/src/test/java/org/eclipse/jetty/spdy/AsyncTimeoutTest.java
index 85cea3452d..16af7c7a51 100644
--- a/jetty-spdy/spdy-core/src/test/java/org/eclipse/jetty/spdy/AsyncTimeoutTest.java
+++ b/jetty-spdy/spdy-core/src/test/java/org/eclipse/jetty/spdy/AsyncTimeoutTest.java
@@ -1,18 +1,15 @@
-/*
- * Copyright (c) 2012 the original author or authors.
- *
- * 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.
- */
+//========================================================================
+//Copyright 2011-2012 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.spdy;
@@ -46,7 +43,7 @@ public class AsyncTimeoutTest
Executor threadPool = Executors.newCachedThreadPool();
ScheduledExecutorService scheduler = Executors.newSingleThreadScheduledExecutor();
Generator generator = new Generator(new StandardByteBufferPool(), new StandardCompressionFactory.StandardCompressor());
- Session session = new StandardSession(SPDY.V2, bufferPool, threadPool, scheduler, new TestController(), null, 1, null, generator)
+ Session session = new StandardSession(SPDY.V2, bufferPool, threadPool, scheduler, new TestController(), null, 1, null, generator, new FlowControlStrategy.None())
{
@Override
public void flush()
@@ -72,7 +69,7 @@ public class AsyncTimeoutTest
}
@Override
- public void failed(Throwable x)
+ public void failed(Stream stream, Throwable x)
{
failedLatch.countDown();
}
@@ -91,7 +88,7 @@ public class AsyncTimeoutTest
Executor threadPool = Executors.newCachedThreadPool();
ScheduledExecutorService scheduler = Executors.newSingleThreadScheduledExecutor();
Generator generator = new Generator(new StandardByteBufferPool(), new StandardCompressionFactory.StandardCompressor());
- Session session = new StandardSession(SPDY.V2, bufferPool, threadPool, scheduler, new TestController(), null, 1, null, generator)
+ Session session = new StandardSession(SPDY.V2, bufferPool, threadPool, scheduler, new TestController(), null, 1, null, generator, new FlowControlStrategy.None())
{
@Override
protected void write(ByteBuffer buffer, Handler<FrameBytes> handler, FrameBytes frameBytes)
@@ -120,7 +117,7 @@ public class AsyncTimeoutTest
}
@Override
- public void failed(Throwable x)
+ public void failed(Void context, Throwable x)
{
failedLatch.countDown();
}
diff --git a/jetty-spdy/spdy-core/src/test/java/org/eclipse/jetty/spdy/StandardSessionTest.java b/jetty-spdy/spdy-core/src/test/java/org/eclipse/jetty/spdy/StandardSessionTest.java
index c999c34c59..6406f623ae 100644
--- a/jetty-spdy/spdy-core/src/test/java/org/eclipse/jetty/spdy/StandardSessionTest.java
+++ b/jetty-spdy/spdy-core/src/test/java/org/eclipse/jetty/spdy/StandardSessionTest.java
@@ -1,31 +1,20 @@
-/*
- * Copyright (c) 2012 the original author or authors.
- *
- * 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.
- */
+//========================================================================
+//Copyright 2011-2012 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.spdy;
-import static org.hamcrest.Matchers.greaterThan;
-import static org.hamcrest.Matchers.is;
-import static org.hamcrest.Matchers.not;
-import static org.junit.Assert.assertThat;
-import static org.mockito.Matchers.any;
-import static org.mockito.Matchers.anyInt;
-import static org.mockito.Mockito.never;
-import static org.mockito.Mockito.verify;
-
import java.nio.ByteBuffer;
+import java.nio.channels.ClosedChannelException;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.Executor;
@@ -34,6 +23,8 @@ import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;
+import org.eclipse.jetty.spdy.StandardSession.FrameBytes;
+import org.eclipse.jetty.spdy.api.ByteBufferDataInfo;
import org.eclipse.jetty.spdy.api.DataInfo;
import org.eclipse.jetty.spdy.api.Handler;
import org.eclipse.jetty.spdy.api.Headers;
@@ -55,13 +46,25 @@ import org.junit.Ignore;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
+import org.mockito.invocation.InvocationOnMock;
import org.mockito.runners.MockitoJUnitRunner;
+import org.mockito.stubbing.Answer;
+
+import static org.hamcrest.Matchers.greaterThan;
+import static org.hamcrest.Matchers.is;
+import static org.hamcrest.Matchers.not;
+import static org.junit.Assert.assertThat;
+import static org.mockito.Mockito.any;
+import static org.mockito.Mockito.times;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
@RunWith(MockitoJUnitRunner.class)
public class StandardSessionTest
{
@Mock
- private ISession sessionMock;
+ private Controller<FrameBytes> controller;
+
private ByteBufferPool bufferPool;
private Executor threadPool;
private StandardSession session;
@@ -76,13 +79,36 @@ public class StandardSessionTest
threadPool = Executors.newCachedThreadPool();
scheduler = Executors.newSingleThreadScheduledExecutor();
generator = new Generator(new StandardByteBufferPool(),new StandardCompressionFactory.StandardCompressor());
- session = new StandardSession(SPDY.V2,bufferPool,threadPool,scheduler,new TestController(),null,1,null,generator);
+ session = new StandardSession(SPDY.V2,bufferPool,threadPool,scheduler,controller,null,1,null,generator,new FlowControlStrategy.None());
headers = new Headers();
}
+ @SuppressWarnings("unchecked")
+ private void setControllerWriteExpectationToFail(final boolean fail)
+ {
+ when(controller.write(any(ByteBuffer.class),any(Handler.class),any(StandardSession.FrameBytes.class))).thenAnswer(new Answer<Integer>()
+ {
+ public Integer answer(InvocationOnMock invocation)
+ {
+ Object[] args = invocation.getArguments();
+
+ Handler<StandardSession.FrameBytes> handler = (Handler<FrameBytes>)args[1];
+ FrameBytes context = (FrameBytes)args[2];
+
+ if (fail)
+ handler.failed(context,new ClosedChannelException());
+ else
+ handler.completed(context);
+ return 0;
+ }
+ });
+ }
+
@Test
public void testStreamIsRemovedFromSessionWhenReset() throws InterruptedException, ExecutionException, TimeoutException
{
+ setControllerWriteExpectationToFail(false);
+
IStream stream = createStream();
assertThatStreamIsInSession(stream);
assertThat("stream is not reset",stream.isReset(),is(false));
@@ -94,6 +120,8 @@ public class StandardSessionTest
@Test
public void testStreamIsAddedAndRemovedFromSession() throws InterruptedException, ExecutionException, TimeoutException
{
+ setControllerWriteExpectationToFail(false);
+
IStream stream = createStream();
assertThatStreamIsInSession(stream);
stream.updateCloseState(true,true);
@@ -105,6 +133,8 @@ public class StandardSessionTest
@Test
public void testStreamIsRemovedWhenHeadersWithCloseFlagAreSent() throws InterruptedException, ExecutionException, TimeoutException
{
+ setControllerWriteExpectationToFail(false);
+
IStream stream = createStream();
assertThatStreamIsInSession(stream);
stream.updateCloseState(true,false);
@@ -116,6 +146,8 @@ public class StandardSessionTest
@Test
public void testStreamIsUnidirectional() throws InterruptedException, ExecutionException, TimeoutException
{
+ setControllerWriteExpectationToFail(false);
+
IStream stream = createStream();
assertThat("stream is not unidirectional",stream.isUnidirectional(),not(true));
Stream pushStream = createPushStream(stream);
@@ -125,6 +157,8 @@ public class StandardSessionTest
@Test
public void testPushStreamCreation() throws InterruptedException, ExecutionException, TimeoutException
{
+ setControllerWriteExpectationToFail(false);
+
Stream stream = createStream();
IStream pushStream = createPushStream(stream);
assertThat("Push stream must be associated to the first stream created",pushStream.getAssociatedStream().getId(),is(stream.getId()));
@@ -134,6 +168,8 @@ public class StandardSessionTest
@Test
public void testPushStreamIsNotClosedWhenAssociatedStreamIsClosed() throws InterruptedException, ExecutionException, TimeoutException
{
+ setControllerWriteExpectationToFail(false);
+
IStream stream = createStream();
Stream pushStream = createPushStream(stream);
assertThatStreamIsNotHalfClosed(stream);
@@ -155,6 +191,8 @@ public class StandardSessionTest
@Test
public void testCreatePushStreamOnClosedStream() throws InterruptedException, ExecutionException, TimeoutException
{
+ setControllerWriteExpectationToFail(false);
+
IStream stream = createStream();
stream.updateCloseState(true,true);
assertThatStreamIsHalfClosed(stream);
@@ -167,15 +205,10 @@ public class StandardSessionTest
{
final CountDownLatch failedLatch = new CountDownLatch(1);
SynInfo synInfo = new SynInfo(headers,false,stream.getPriority());
- stream.syn(synInfo,5,TimeUnit.SECONDS,new Handler<Stream>()
+ stream.syn(synInfo,5,TimeUnit.SECONDS,new Handler.Adapter<Stream>()
{
@Override
- public void completed(Stream context)
- {
- }
-
- @Override
- public void failed(Throwable x)
+ public void failed(Stream stream, Throwable x)
{
failedLatch.countDown();
}
@@ -186,6 +219,8 @@ public class StandardSessionTest
@Test
public void testPushStreamIsAddedAndRemovedFromParentAndSessionWhenClosed() throws InterruptedException, ExecutionException, TimeoutException
{
+ setControllerWriteExpectationToFail(false);
+
IStream stream = createStream();
IStream pushStream = createPushStream(stream);
assertThatPushStreamIsHalfClosed(pushStream);
@@ -200,6 +235,8 @@ public class StandardSessionTest
@Test
public void testPushStreamIsRemovedWhenReset() throws InterruptedException, ExecutionException, TimeoutException
{
+ setControllerWriteExpectationToFail(false);
+
IStream stream = createStream();
IStream pushStream = (IStream)stream.syn(new SynInfo(false)).get();
assertThatPushStreamIsInSession(pushStream);
@@ -212,6 +249,8 @@ public class StandardSessionTest
@Test
public void testPushStreamWithSynInfoClosedTrue() throws InterruptedException, ExecutionException, TimeoutException
{
+ setControllerWriteExpectationToFail(false);
+
IStream stream = createStream();
SynInfo synInfo = new SynInfo(headers,true,stream.getPriority());
IStream pushStream = (IStream)stream.syn(synInfo).get(5,TimeUnit.SECONDS);
@@ -225,6 +264,8 @@ public class StandardSessionTest
public void testPushStreamSendHeadersWithCloseFlagIsRemovedFromSessionAndDisassociateFromParent() throws InterruptedException, ExecutionException,
TimeoutException
{
+ setControllerWriteExpectationToFail(false);
+
IStream stream = createStream();
SynInfo synInfo = new SynInfo(headers,false,stream.getPriority());
IStream pushStream = (IStream)stream.syn(synInfo).get(5,TimeUnit.SECONDS);
@@ -240,6 +281,8 @@ public class StandardSessionTest
@Test
public void testCreatedAndClosedListenersAreCalledForNewStream() throws InterruptedException, ExecutionException, TimeoutException
{
+ setControllerWriteExpectationToFail(false);
+
final CountDownLatch createdListenerCalledLatch = new CountDownLatch(1);
final CountDownLatch closedListenerCalledLatch = new CountDownLatch(1);
session.addListener(new TestStreamListener(createdListenerCalledLatch,closedListenerCalledLatch));
@@ -253,6 +296,8 @@ public class StandardSessionTest
@Test
public void testListenerIsCalledForResetStream() throws InterruptedException, ExecutionException, TimeoutException
{
+ setControllerWriteExpectationToFail(false);
+
final CountDownLatch closedListenerCalledLatch = new CountDownLatch(1);
session.addListener(new TestStreamListener(null,closedListenerCalledLatch));
IStream stream = createStream();
@@ -263,6 +308,8 @@ public class StandardSessionTest
@Test
public void testCreatedAndClosedListenersAreCalledForNewPushStream() throws InterruptedException, ExecutionException, TimeoutException
{
+ setControllerWriteExpectationToFail(false);
+
final CountDownLatch createdListenerCalledLatch = new CountDownLatch(2);
final CountDownLatch closedListenerCalledLatch = new CountDownLatch(1);
session.addListener(new TestStreamListener(createdListenerCalledLatch,closedListenerCalledLatch));
@@ -277,6 +324,8 @@ public class StandardSessionTest
@Test
public void testListenerIsCalledForResetPushStream() throws InterruptedException, ExecutionException, TimeoutException
{
+ setControllerWriteExpectationToFail(false);
+
final CountDownLatch closedListenerCalledLatch = new CountDownLatch(1);
session.addListener(new TestStreamListener(null,closedListenerCalledLatch));
IStream stream = createStream();
@@ -313,31 +362,23 @@ public class StandardSessionTest
}
}
- @SuppressWarnings("unchecked")
- @Test(expected = IllegalStateException.class)
- public void testSendDataOnHalfClosedStream() throws InterruptedException, ExecutionException, TimeoutException
- {
- SynStreamFrame synStreamFrame = new SynStreamFrame(SPDY.V2,SynInfo.FLAG_CLOSE,1,0,(byte)0,null);
- IStream stream = new StandardStream(synStreamFrame,sessionMock,8184,null);
- stream.updateCloseState(synStreamFrame.isClose(),true);
- assertThat("stream is half closed",stream.isHalfClosed(),is(true));
- stream.data(new StringDataInfo("data on half closed stream",true));
- verify(sessionMock,never()).data(any(IStream.class),any(DataInfo.class),anyInt(),any(TimeUnit.class),any(Handler.class),any(void.class));
- }
-
@Test
@Ignore("In V3 we need to rst the stream if we receive data on a remotely half closed stream.")
public void receiveDataOnRemotelyHalfClosedStreamResetsStreamInV3() throws InterruptedException, ExecutionException
{
+ setControllerWriteExpectationToFail(false);
+
IStream stream = (IStream)session.syn(new SynInfo(false),new StreamFrameListener.Adapter()).get();
stream.updateCloseState(true,false);
assertThat("stream is half closed from remote side",stream.isHalfClosed(),is(true));
- stream.process(new DataFrame(stream.getId(),(byte)0,256),ByteBuffer.allocate(256));
+ stream.process(new ByteBufferDataInfo(ByteBuffer.allocate(256), true));
}
@Test
public void testReceiveDataOnRemotelyClosedStreamIsIgnored() throws InterruptedException, ExecutionException, TimeoutException
{
+ setControllerWriteExpectationToFail(false);
+
final CountDownLatch onDataCalledLatch = new CountDownLatch(1);
Stream stream = session.syn(new SynInfo(false),new StreamFrameListener.Adapter()
{
@@ -353,10 +394,38 @@ public class StandardSessionTest
assertThat("onData is never called",onDataCalledLatch.await(1,TimeUnit.SECONDS),not(true));
}
+ @SuppressWarnings("unchecked")
+ @Test
+ public void testControllerWriteFailsInEndPointFlush() throws InterruptedException
+ {
+ setControllerWriteExpectationToFail(true);
+
+ final CountDownLatch failedCalledLatch = new CountDownLatch(2);
+ SynStreamFrame synStreamFrame = new SynStreamFrame(SPDY.V2, SynInfo.FLAG_CLOSE, 1, 0, (byte)0, (short)0, null);
+ IStream stream = new StandardStream(synStreamFrame.getStreamId(), synStreamFrame.getPriority(), session, null);
+ stream.updateWindowSize(8192);
+ Handler.Adapter<Void> handler = new Handler.Adapter<Void>()
+ {
+ @Override
+ public void failed(Void context, Throwable x)
+ {
+ failedCalledLatch.countDown();
+ }
+ };
+
+ // first data frame should fail on controller.write()
+ stream.data(new StringDataInfo("data", false), 5, TimeUnit.SECONDS, handler);
+ // second data frame should fail without controller.writer() as the connection is expected to be broken after first controller.write() call failed.
+ stream.data(new StringDataInfo("data", false), 5, TimeUnit.SECONDS, handler);
+
+ verify(controller, times(1)).write(any(ByteBuffer.class), any(Handler.class), any(FrameBytes.class));
+ assertThat("Handler.failed has been called twice", failedCalledLatch.await(5, TimeUnit.SECONDS), is(true));
+ }
+
private IStream createStream() throws InterruptedException, ExecutionException, TimeoutException
{
SynInfo synInfo = new SynInfo(headers,false,(byte)0);
- return (IStream)session.syn(synInfo,new StreamFrameListener.Adapter()).get(5,TimeUnit.SECONDS);
+ return (IStream)session.syn(synInfo,new StreamFrameListener.Adapter()).get(50,TimeUnit.SECONDS);
}
private IStream createPushStream(Stream stream) throws InterruptedException, ExecutionException, TimeoutException
@@ -365,21 +434,6 @@ public class StandardSessionTest
return (IStream)stream.syn(synInfo).get(5,TimeUnit.SECONDS);
}
- private static class TestController implements Controller<StandardSession.FrameBytes>
- {
- @Override
- public int write(ByteBuffer buffer, Handler<StandardSession.FrameBytes> handler, StandardSession.FrameBytes context)
- {
- handler.completed(context);
- return buffer.remaining();
- }
-
- @Override
- public void close(boolean onlyOutput)
- {
- }
- }
-
private void assertThatStreamIsClosed(IStream stream)
{
assertThat("stream is closed",stream.isClosed(),is(true));
diff --git a/jetty-spdy/spdy-core/src/test/java/org/eclipse/jetty/spdy/StandardStreamTest.java b/jetty-spdy/spdy-core/src/test/java/org/eclipse/jetty/spdy/StandardStreamTest.java
index 68a6a9576c..f75c723739 100644
--- a/jetty-spdy/spdy-core/src/test/java/org/eclipse/jetty/spdy/StandardStreamTest.java
+++ b/jetty-spdy/spdy-core/src/test/java/org/eclipse/jetty/spdy/StandardStreamTest.java
@@ -1,36 +1,31 @@
-// ========================================================================
-// 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.
-// ========================================================================
-
+//========================================================================
+//Copyright 2011-2012 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.spdy;
-import static org.hamcrest.Matchers.equalTo;
-import static org.hamcrest.Matchers.is;
-import static org.junit.Assert.assertThat;
-import static org.mockito.Matchers.any;
-import static org.mockito.Matchers.anyLong;
-import static org.mockito.Matchers.argThat;
-import static org.mockito.Mockito.verify;
-import static org.mockito.Mockito.when;
-
import java.util.HashSet;
import java.util.Set;
import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.ExecutionException;
import java.util.concurrent.TimeUnit;
+import java.util.concurrent.TimeoutException;
+import org.eclipse.jetty.spdy.api.DataInfo;
import org.eclipse.jetty.spdy.api.Handler;
+import org.eclipse.jetty.spdy.api.SPDY;
import org.eclipse.jetty.spdy.api.Stream;
import org.eclipse.jetty.spdy.api.StreamFrameListener;
+import org.eclipse.jetty.spdy.api.StringDataInfo;
import org.eclipse.jetty.spdy.api.SynInfo;
import org.eclipse.jetty.spdy.frames.SynStreamFrame;
import org.junit.Test;
@@ -39,16 +34,25 @@ import org.mockito.ArgumentMatcher;
import org.mockito.Mock;
import org.mockito.runners.MockitoJUnitRunner;
+import static org.hamcrest.Matchers.equalTo;
+import static org.hamcrest.Matchers.is;
+import static org.junit.Assert.assertThat;
+import static org.mockito.Matchers.any;
+import static org.mockito.Matchers.anyInt;
+import static org.mockito.Matchers.anyLong;
+import static org.mockito.Matchers.argThat;
+import static org.mockito.Mockito.never;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
-/* ------------------------------------------------------------ */
-/**
- */
@RunWith(MockitoJUnitRunner.class)
public class StandardStreamTest
{
- @Mock private ISession session;
- @Mock private SynStreamFrame synStreamFrame;
-
+ @Mock
+ private ISession session;
+ @Mock
+ private SynStreamFrame synStreamFrame;
+
/**
* Test method for {@link org.eclipse.jetty.spdy.StandardStream#syn(org.eclipse.jetty.spdy.api.SynInfo)}.
*/
@@ -56,34 +60,38 @@ public class StandardStreamTest
@Test
public void testSyn()
{
- Stream stream = new StandardStream(synStreamFrame,session,0,null);
+ Stream stream = new StandardStream(synStreamFrame.getStreamId(), synStreamFrame.getPriority(), session, null);
Set<Stream> streams = new HashSet<>();
streams.add(stream);
when(synStreamFrame.isClose()).thenReturn(false);
SynInfo synInfo = new SynInfo(false);
when(session.getStreams()).thenReturn(streams);
stream.syn(synInfo);
- verify(session).syn(argThat(new PushSynInfoMatcher(stream.getId(),synInfo)),any(StreamFrameListener.class),anyLong(),any(TimeUnit.class),any(Handler.class));
+ verify(session).syn(argThat(new PushSynInfoMatcher(stream.getId(), synInfo)), any(StreamFrameListener.class), anyLong(), any(TimeUnit.class), any(Handler.class));
}
-
- private class PushSynInfoMatcher extends ArgumentMatcher<PushSynInfo>{
+
+ private class PushSynInfoMatcher extends ArgumentMatcher<PushSynInfo>
+ {
int associatedStreamId;
SynInfo synInfo;
-
+
public PushSynInfoMatcher(int associatedStreamId, SynInfo synInfo)
{
this.associatedStreamId = associatedStreamId;
this.synInfo = synInfo;
}
+
@Override
public boolean matches(Object argument)
{
PushSynInfo pushSynInfo = (PushSynInfo)argument;
- if(pushSynInfo.getAssociatedStreamId() != associatedStreamId){
+ if (pushSynInfo.getAssociatedStreamId() != associatedStreamId)
+ {
System.out.println("streamIds do not match!");
return false;
}
- if(pushSynInfo.isClose() != synInfo.isClose()){
+ if (pushSynInfo.isClose() != synInfo.isClose())
+ {
System.out.println("isClose doesn't match");
return false;
}
@@ -92,16 +100,17 @@ public class StandardStreamTest
}
@Test
- public void testSynOnClosedStream(){
- IStream stream = new StandardStream(synStreamFrame,session,0,null);
- stream.updateCloseState(true,true);
- stream.updateCloseState(true,false);
- assertThat("stream expected to be closed",stream.isClosed(),is(true));
+ public void testSynOnClosedStream()
+ {
+ IStream stream = new StandardStream(synStreamFrame.getStreamId(), synStreamFrame.getPriority(), session, null);
+ stream.updateCloseState(true, true);
+ stream.updateCloseState(true, false);
+ assertThat("stream expected to be closed", stream.isClosed(), is(true));
final CountDownLatch failedLatch = new CountDownLatch(1);
- stream.syn(new SynInfo(false),1,TimeUnit.SECONDS,new Handler.Adapter<Stream>()
+ stream.syn(new SynInfo(false), 1, TimeUnit.SECONDS, new Handler.Adapter<Stream>()
{
@Override
- public void failed(Throwable x)
+ public void failed(Stream stream, Throwable x)
{
failedLatch.countDown();
}
@@ -109,4 +118,16 @@ public class StandardStreamTest
assertThat("PushStream creation failed", failedLatch.getCount(), equalTo(0L));
}
+ @SuppressWarnings("unchecked")
+ @Test(expected = IllegalStateException.class)
+ public void testSendDataOnHalfClosedStream() throws InterruptedException, ExecutionException, TimeoutException
+ {
+ SynStreamFrame synStreamFrame = new SynStreamFrame(SPDY.V2, SynInfo.FLAG_CLOSE, 1, 0, (byte)0, (short)0, null);
+ IStream stream = new StandardStream(synStreamFrame.getStreamId(), synStreamFrame.getPriority(), session, null);
+ stream.updateWindowSize(8192);
+ stream.updateCloseState(synStreamFrame.isClose(), true);
+ assertThat("stream is half closed", stream.isHalfClosed(), is(true));
+ stream.data(new StringDataInfo("data on half closed stream", true));
+ verify(session, never()).data(any(IStream.class), any(DataInfo.class), anyInt(), any(TimeUnit.class), any(Handler.class), any(void.class));
+ }
}
diff --git a/jetty-spdy/spdy-core/src/test/java/org/eclipse/jetty/spdy/api/ClientUsageTest.java b/jetty-spdy/spdy-core/src/test/java/org/eclipse/jetty/spdy/api/ClientUsageTest.java
index b1c40d54da..9de7f49175 100644
--- a/jetty-spdy/spdy-core/src/test/java/org/eclipse/jetty/spdy/api/ClientUsageTest.java
+++ b/jetty-spdy/spdy-core/src/test/java/org/eclipse/jetty/spdy/api/ClientUsageTest.java
@@ -1,18 +1,15 @@
-/*
- * Copyright (c) 2012 the original author or authors.
- *
- * 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.
- */
+//========================================================================
+//Copyright 2011-2012 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.spdy.api;
@@ -29,7 +26,7 @@ public class ClientUsageTest
@Test
public void testClientRequestResponseNoBody() throws Exception
{
- Session session = new StandardSession(SPDY.V2, null, null, null, null, null, 1, null, null);
+ Session session = new StandardSession(SPDY.V2, null, null, null, null, null, 1, null, null, null);
session.syn(new SynInfo(true), new StreamFrameListener.Adapter()
{
@@ -48,7 +45,7 @@ public class ClientUsageTest
@Test
public void testClientRequestWithBodyResponseNoBody() throws Exception
{
- Session session = new StandardSession(SPDY.V2, null, null, null, null, null, 1, null, null);
+ Session session = new StandardSession(SPDY.V2, null, null, null, null, null, 1, null, null, null);
Stream stream = session.syn(new SynInfo(false), new StreamFrameListener.Adapter()
{
@@ -69,7 +66,7 @@ public class ClientUsageTest
@Test
public void testAsyncClientRequestWithBodyResponseNoBody() throws Exception
{
- Session session = new StandardSession(SPDY.V2, null, null, null, null, null, 1, null, null);
+ Session session = new StandardSession(SPDY.V2, null, null, null, null, null, 1, null, null, null);
final String context = "context";
session.syn(new SynInfo(false), new StreamFrameListener.Adapter()
@@ -104,7 +101,7 @@ public class ClientUsageTest
@Test
public void testAsyncClientRequestWithBodyAndResponseWithBody() throws Exception
{
- Session session = new StandardSession(SPDY.V2, null, null, null, null, null, 1, null, null);
+ Session session = new StandardSession(SPDY.V2, null, null, null, null, null, 1, null, null, null);
session.syn(new SynInfo(false), new StreamFrameListener.Adapter()
{
diff --git a/jetty-spdy/spdy-core/src/test/java/org/eclipse/jetty/spdy/api/ServerUsageTest.java b/jetty-spdy/spdy-core/src/test/java/org/eclipse/jetty/spdy/api/ServerUsageTest.java
index a8bff06d67..b1a326fc17 100644
--- a/jetty-spdy/spdy-core/src/test/java/org/eclipse/jetty/spdy/api/ServerUsageTest.java
+++ b/jetty-spdy/spdy-core/src/test/java/org/eclipse/jetty/spdy/api/ServerUsageTest.java
@@ -1,18 +1,15 @@
-/*
- * Copyright (c) 2012 the original author or authors.
- *
- * 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.
- */
+//========================================================================
+//Copyright 2011-2012 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.spdy.api;
diff --git a/jetty-spdy/spdy-core/src/test/java/org/eclipse/jetty/spdy/frames/CredentialGenerateParseTest.java b/jetty-spdy/spdy-core/src/test/java/org/eclipse/jetty/spdy/frames/CredentialGenerateParseTest.java
new file mode 100644
index 0000000000..e7db2c8c7a
--- /dev/null
+++ b/jetty-spdy/spdy-core/src/test/java/org/eclipse/jetty/spdy/frames/CredentialGenerateParseTest.java
@@ -0,0 +1,99 @@
+//========================================================================
+//Copyright 2011-2012 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.spdy.frames;
+
+import java.io.InputStream;
+import java.nio.ByteBuffer;
+import java.security.KeyStore;
+import java.security.cert.Certificate;
+
+import org.eclipse.jetty.spdy.StandardByteBufferPool;
+import org.eclipse.jetty.spdy.StandardCompressionFactory;
+import org.eclipse.jetty.spdy.api.SPDY;
+import org.eclipse.jetty.spdy.generator.Generator;
+import org.eclipse.jetty.spdy.parser.Parser;
+import org.eclipse.jetty.util.resource.Resource;
+import org.junit.Assert;
+import org.junit.Test;
+
+public class CredentialGenerateParseTest
+{
+ @Test
+ public void testGenerateParse() throws Exception
+ {
+ short slot = 1;
+ byte[] proof = new byte[]{0, 1, 2};
+ Certificate[] temp = loadCertificates();
+ Certificate[] certificates = new Certificate[temp.length * 2];
+ System.arraycopy(temp, 0, certificates, 0, temp.length);
+ System.arraycopy(temp, 0, certificates, temp.length, temp.length);
+ CredentialFrame frame1 = new CredentialFrame(SPDY.V3, slot, proof, certificates);
+ Generator generator = new Generator(new StandardByteBufferPool(), new StandardCompressionFactory().newCompressor());
+ ByteBuffer buffer = generator.control(frame1);
+
+ Assert.assertNotNull(buffer);
+
+ TestSPDYParserListener listener = new TestSPDYParserListener();
+ Parser parser = new Parser(new StandardCompressionFactory().newDecompressor());
+ parser.addListener(listener);
+ parser.parse(buffer);
+ ControlFrame frame2 = listener.getControlFrame();
+
+ Assert.assertNotNull(frame2);
+ Assert.assertEquals(ControlFrameType.CREDENTIAL, frame2.getType());
+ CredentialFrame credential = (CredentialFrame)frame2;
+ Assert.assertEquals(SPDY.V3, credential.getVersion());
+ Assert.assertEquals(0, credential.getFlags());
+ Assert.assertEquals(slot, credential.getSlot());
+ Assert.assertArrayEquals(proof, credential.getProof());
+ Assert.assertArrayEquals(certificates, credential.getCertificateChain());
+ }
+
+ @Test
+ public void testGenerateParseOneByteAtATime() throws Exception
+ {
+ short slot = 1;
+ byte[] proof = new byte[]{0, 1, 2};
+ Certificate[] certificates = loadCertificates();
+ CredentialFrame frame1 = new CredentialFrame(SPDY.V3, slot, proof, certificates);
+ Generator generator = new Generator(new StandardByteBufferPool(), new StandardCompressionFactory().newCompressor());
+ ByteBuffer buffer = generator.control(frame1);
+
+ Assert.assertNotNull(buffer);
+
+ TestSPDYParserListener listener = new TestSPDYParserListener();
+ Parser parser = new Parser(new StandardCompressionFactory().newDecompressor());
+ parser.addListener(listener);
+ while (buffer.hasRemaining())
+ parser.parse(ByteBuffer.wrap(new byte[]{buffer.get()}));
+ ControlFrame frame2 = listener.getControlFrame();
+
+ Assert.assertNotNull(frame2);
+ Assert.assertEquals(ControlFrameType.CREDENTIAL, frame2.getType());
+ CredentialFrame credential = (CredentialFrame)frame2;
+ Assert.assertEquals(SPDY.V3, credential.getVersion());
+ Assert.assertEquals(0, credential.getFlags());
+ Assert.assertEquals(slot, credential.getSlot());
+ Assert.assertArrayEquals(proof, credential.getProof());
+ Assert.assertArrayEquals(certificates, credential.getCertificateChain());
+ }
+
+ private Certificate[] loadCertificates() throws Exception
+ {
+ KeyStore keyStore = KeyStore.getInstance("JKS");
+ InputStream keyStoreStream = Resource.newResource("src/test/resources/keystore.jks").getInputStream();
+ keyStore.load(keyStoreStream, "storepwd".toCharArray());
+ return keyStore.getCertificateChain("mykey");
+ }
+}
diff --git a/jetty-spdy/spdy-core/src/test/java/org/eclipse/jetty/spdy/frames/DataGenerateParseTest.java b/jetty-spdy/spdy-core/src/test/java/org/eclipse/jetty/spdy/frames/DataGenerateParseTest.java
index ea83e10dd9..6f53b64c09 100644
--- a/jetty-spdy/spdy-core/src/test/java/org/eclipse/jetty/spdy/frames/DataGenerateParseTest.java
+++ b/jetty-spdy/spdy-core/src/test/java/org/eclipse/jetty/spdy/frames/DataGenerateParseTest.java
@@ -1,18 +1,15 @@
-/*
- * Copyright (c) 2012 the original author or authors.
- *
- * 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.
- */
+//========================================================================
+//Copyright 2011-2012 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.spdy.frames;
diff --git a/jetty-spdy/spdy-core/src/test/java/org/eclipse/jetty/spdy/frames/GoAwayGenerateParseTest.java b/jetty-spdy/spdy-core/src/test/java/org/eclipse/jetty/spdy/frames/GoAwayGenerateParseTest.java
index c32df12ba0..c3ae26d436 100644
--- a/jetty-spdy/spdy-core/src/test/java/org/eclipse/jetty/spdy/frames/GoAwayGenerateParseTest.java
+++ b/jetty-spdy/spdy-core/src/test/java/org/eclipse/jetty/spdy/frames/GoAwayGenerateParseTest.java
@@ -1,18 +1,15 @@
-/*
- * Copyright (c) 2012 the original author or authors.
- *
- * 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.
- */
+//========================================================================
+//Copyright 2011-2012 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.spdy.frames;
diff --git a/jetty-spdy/spdy-core/src/test/java/org/eclipse/jetty/spdy/frames/HeadersGenerateParseTest.java b/jetty-spdy/spdy-core/src/test/java/org/eclipse/jetty/spdy/frames/HeadersGenerateParseTest.java
index 99bd4b37ed..fd5a36de3d 100644
--- a/jetty-spdy/spdy-core/src/test/java/org/eclipse/jetty/spdy/frames/HeadersGenerateParseTest.java
+++ b/jetty-spdy/spdy-core/src/test/java/org/eclipse/jetty/spdy/frames/HeadersGenerateParseTest.java
@@ -1,18 +1,15 @@
-/*
- * Copyright (c) 2012 the original author or authors.
- *
- * 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.
- */
+//========================================================================
+//Copyright 2011-2012 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.spdy.frames;
@@ -25,65 +22,77 @@ import org.eclipse.jetty.spdy.api.HeadersInfo;
import org.eclipse.jetty.spdy.api.SPDY;
import org.eclipse.jetty.spdy.generator.Generator;
import org.eclipse.jetty.spdy.parser.Parser;
-import org.junit.Assert;
+import org.junit.Before;
import org.junit.Test;
+import static org.hamcrest.CoreMatchers.is;
+import static org.hamcrest.CoreMatchers.notNullValue;
+import static org.junit.Assert.assertThat;
+
public class HeadersGenerateParseTest
{
- @Test
- public void testGenerateParse() throws Exception
+
+ private Headers headers = new Headers();
+ private int streamId = 13;
+ private byte flags = HeadersInfo.FLAG_RESET_COMPRESSION;
+ private final TestSPDYParserListener listener = new TestSPDYParserListener();
+ private final Parser parser = new Parser(new StandardCompressionFactory().newDecompressor());
+ private ByteBuffer buffer;
+
+ @Before
+ public void setUp()
{
- byte flags = HeadersInfo.FLAG_RESET_COMPRESSION;
- int streamId = 13;
- Headers headers = new Headers();
+ parser.addListener(listener);
headers.put("a", "b");
+ buffer = createHeadersFrameBuffer(headers);
+ }
+
+ private ByteBuffer createHeadersFrameBuffer(Headers headers)
+ {
HeadersFrame frame1 = new HeadersFrame(SPDY.V2, flags, streamId, headers);
Generator generator = new Generator(new StandardByteBufferPool(), new StandardCompressionFactory().newCompressor());
ByteBuffer buffer = generator.control(frame1);
+ assertThat("Buffer is not null", buffer, notNullValue());
+ return buffer;
+ }
- Assert.assertNotNull(buffer);
-
- TestSPDYParserListener listener = new TestSPDYParserListener();
- Parser parser = new Parser(new StandardCompressionFactory().newDecompressor());
- parser.addListener(listener);
+ @Test
+ public void testGenerateParse() throws Exception
+ {
parser.parse(buffer);
- ControlFrame frame2 = listener.getControlFrame();
-
- Assert.assertNotNull(frame2);
- Assert.assertEquals(ControlFrameType.HEADERS, frame2.getType());
- HeadersFrame headersFrame = (HeadersFrame)frame2;
- Assert.assertEquals(SPDY.V2, headersFrame.getVersion());
- Assert.assertEquals(streamId, headersFrame.getStreamId());
- Assert.assertEquals(flags, headersFrame.getFlags());
- Assert.assertEquals(headers, headersFrame.getHeaders());
+ assertExpectationsAreMet(headers);
}
@Test
public void testGenerateParseOneByteAtATime() throws Exception
{
- byte flags = HeadersInfo.FLAG_RESET_COMPRESSION;
- int streamId = 13;
- Headers headers = new Headers();
- headers.put("a", "b");
- HeadersFrame frame1 = new HeadersFrame(SPDY.V2, flags, streamId, headers);
- Generator generator = new Generator(new StandardByteBufferPool(), new StandardCompressionFactory().newCompressor());
- ByteBuffer buffer = generator.control(frame1);
-
- Assert.assertNotNull(buffer);
-
- TestSPDYParserListener listener = new TestSPDYParserListener();
- Parser parser = new Parser(new StandardCompressionFactory().newDecompressor());
- parser.addListener(listener);
while (buffer.hasRemaining())
parser.parse(ByteBuffer.wrap(new byte[]{buffer.get()}));
- ControlFrame frame2 = listener.getControlFrame();
- Assert.assertNotNull(frame2);
- Assert.assertEquals(ControlFrameType.HEADERS, frame2.getType());
- HeadersFrame headersFrame = (HeadersFrame)frame2;
- Assert.assertEquals(SPDY.V2, headersFrame.getVersion());
- Assert.assertEquals(streamId, headersFrame.getStreamId());
- Assert.assertEquals(flags, headersFrame.getFlags());
- Assert.assertEquals(headers, headersFrame.getHeaders());
+ assertExpectationsAreMet(headers);
+ }
+
+ @Test
+ public void testHeadersAreTranslatedToLowerCase()
+ {
+ Headers headers = new Headers();
+ headers.put("Via","localhost");
+ parser.parse(createHeadersFrameBuffer(headers));
+ HeadersFrame parsedHeadersFrame = assertExpectationsAreMet(headers);
+ Headers.Header viaHeader = parsedHeadersFrame.getHeaders().get("via");
+ assertThat("Via Header name is lowercase", viaHeader.name(), is("via"));
+ }
+
+ private HeadersFrame assertExpectationsAreMet(Headers headers)
+ {
+ ControlFrame parsedControlFrame = listener.getControlFrame();
+ assertThat("listener received controlFrame", parsedControlFrame, notNullValue());
+ assertThat("ControlFrame type is HEADERS", ControlFrameType.HEADERS, is(parsedControlFrame.getType()));
+ HeadersFrame headersFrame = (HeadersFrame)parsedControlFrame;
+ assertThat("Version matches", SPDY.V2, is(headersFrame.getVersion()));
+ assertThat("StreamId matches", streamId, is(headersFrame.getStreamId()));
+ assertThat("flags match", flags, is(headersFrame.getFlags()));
+ assertThat("headers match", headers, is(headersFrame.getHeaders()));
+ return headersFrame;
}
}
diff --git a/jetty-spdy/spdy-core/src/test/java/org/eclipse/jetty/spdy/frames/NoOpGenerateParseTest.java b/jetty-spdy/spdy-core/src/test/java/org/eclipse/jetty/spdy/frames/NoOpGenerateParseTest.java
index 50afa5f4b6..9c248be4ed 100644
--- a/jetty-spdy/spdy-core/src/test/java/org/eclipse/jetty/spdy/frames/NoOpGenerateParseTest.java
+++ b/jetty-spdy/spdy-core/src/test/java/org/eclipse/jetty/spdy/frames/NoOpGenerateParseTest.java
@@ -1,18 +1,15 @@
-/*
- * Copyright (c) 2012 the original author or authors.
- *
- * 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.
- */
+//========================================================================
+//Copyright 2011-2012 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.spdy.frames;
diff --git a/jetty-spdy/spdy-core/src/test/java/org/eclipse/jetty/spdy/frames/PingGenerateParseTest.java b/jetty-spdy/spdy-core/src/test/java/org/eclipse/jetty/spdy/frames/PingGenerateParseTest.java
index 231406a6a9..1bd87f8601 100644
--- a/jetty-spdy/spdy-core/src/test/java/org/eclipse/jetty/spdy/frames/PingGenerateParseTest.java
+++ b/jetty-spdy/spdy-core/src/test/java/org/eclipse/jetty/spdy/frames/PingGenerateParseTest.java
@@ -1,18 +1,15 @@
-/*
- * Copyright (c) 2012 the original author or authors.
- *
- * 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.
- */
+//========================================================================
+//Copyright 2011-2012 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.spdy.frames;
diff --git a/jetty-spdy/spdy-core/src/test/java/org/eclipse/jetty/spdy/frames/RstStreamGenerateParseTest.java b/jetty-spdy/spdy-core/src/test/java/org/eclipse/jetty/spdy/frames/RstStreamGenerateParseTest.java
index 378a3faf91..df70d3695d 100644
--- a/jetty-spdy/spdy-core/src/test/java/org/eclipse/jetty/spdy/frames/RstStreamGenerateParseTest.java
+++ b/jetty-spdy/spdy-core/src/test/java/org/eclipse/jetty/spdy/frames/RstStreamGenerateParseTest.java
@@ -1,18 +1,15 @@
-/*
- * Copyright (c) 2012 the original author or authors.
- *
- * 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.
- */
+//========================================================================
+//Copyright 2011-2012 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.spdy.frames;
diff --git a/jetty-spdy/spdy-core/src/test/java/org/eclipse/jetty/spdy/frames/SettingsGenerateParseTest.java b/jetty-spdy/spdy-core/src/test/java/org/eclipse/jetty/spdy/frames/SettingsGenerateParseTest.java
index 3fc531b93a..88b640d63c 100644
--- a/jetty-spdy/spdy-core/src/test/java/org/eclipse/jetty/spdy/frames/SettingsGenerateParseTest.java
+++ b/jetty-spdy/spdy-core/src/test/java/org/eclipse/jetty/spdy/frames/SettingsGenerateParseTest.java
@@ -1,18 +1,15 @@
-/*
- * Copyright (c) 2012 the original author or authors.
- *
- * 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.
- */
+//========================================================================
+//Copyright 2011-2012 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.spdy.frames;
diff --git a/jetty-spdy/spdy-core/src/test/java/org/eclipse/jetty/spdy/frames/SynReplyGenerateParseTest.java b/jetty-spdy/spdy-core/src/test/java/org/eclipse/jetty/spdy/frames/SynReplyGenerateParseTest.java
index ed51e82675..6da3189c54 100644
--- a/jetty-spdy/spdy-core/src/test/java/org/eclipse/jetty/spdy/frames/SynReplyGenerateParseTest.java
+++ b/jetty-spdy/spdy-core/src/test/java/org/eclipse/jetty/spdy/frames/SynReplyGenerateParseTest.java
@@ -1,18 +1,15 @@
-/*
- * Copyright (c) 2012 the original author or authors.
- *
- * 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.
- */
+//========================================================================
+//Copyright 2011-2012 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.spdy.frames;
diff --git a/jetty-spdy/spdy-core/src/test/java/org/eclipse/jetty/spdy/frames/SynStreamGenerateParseTest.java b/jetty-spdy/spdy-core/src/test/java/org/eclipse/jetty/spdy/frames/SynStreamGenerateParseTest.java
index 2fac2bbe9f..5cf4b223c1 100644
--- a/jetty-spdy/spdy-core/src/test/java/org/eclipse/jetty/spdy/frames/SynStreamGenerateParseTest.java
+++ b/jetty-spdy/spdy-core/src/test/java/org/eclipse/jetty/spdy/frames/SynStreamGenerateParseTest.java
@@ -1,18 +1,15 @@
-/*
- * Copyright (c) 2012 the original author or authors.
- *
- * 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.
- */
+//========================================================================
+//Copyright 2011-2012 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.spdy.frames;
@@ -37,10 +34,11 @@ public class SynStreamGenerateParseTest
int streamId = 13;
int associatedStreamId = 11;
byte priority = 3;
+ short slot = 5;
Headers headers = new Headers();
headers.put("a", "b");
headers.put("c", "d");
- SynStreamFrame frame1 = new SynStreamFrame(SPDY.V2, flags, streamId, associatedStreamId, priority, headers);
+ SynStreamFrame frame1 = new SynStreamFrame(SPDY.V2, flags, streamId, associatedStreamId, priority, slot, headers);
Generator generator = new Generator(new StandardByteBufferPool(), new StandardCompressionFactory().newCompressor());
ByteBuffer buffer = generator.control(frame1);
@@ -60,6 +58,7 @@ public class SynStreamGenerateParseTest
Assert.assertEquals(associatedStreamId, synStream.getAssociatedStreamId());
Assert.assertEquals(flags, synStream.getFlags());
Assert.assertEquals(priority, synStream.getPriority());
+ Assert.assertEquals(slot, synStream.getSlot());
Assert.assertEquals(headers, synStream.getHeaders());
}
@@ -70,10 +69,11 @@ public class SynStreamGenerateParseTest
int streamId = 13;
int associatedStreamId = 11;
byte priority = 3;
+ short slot = 5;
Headers headers = new Headers();
headers.put("a", "b");
headers.put("c", "d");
- SynStreamFrame frame1 = new SynStreamFrame(SPDY.V2, flags, streamId, associatedStreamId, priority, headers);
+ SynStreamFrame frame1 = new SynStreamFrame(SPDY.V2, flags, streamId, associatedStreamId, priority, slot, headers);
Generator generator = new Generator(new StandardByteBufferPool(), new StandardCompressionFactory().newCompressor());
ByteBuffer buffer = generator.control(frame1);
@@ -94,6 +94,7 @@ public class SynStreamGenerateParseTest
Assert.assertEquals(associatedStreamId, synStream.getAssociatedStreamId());
Assert.assertEquals(flags, synStream.getFlags());
Assert.assertEquals(priority, synStream.getPriority());
+ Assert.assertEquals(slot, synStream.getSlot());
Assert.assertEquals(headers, synStream.getHeaders());
}
}
diff --git a/jetty-spdy/spdy-core/src/test/java/org/eclipse/jetty/spdy/frames/TestSPDYParserListener.java b/jetty-spdy/spdy-core/src/test/java/org/eclipse/jetty/spdy/frames/TestSPDYParserListener.java
index 4642ca5d3b..14e0cf35c8 100644
--- a/jetty-spdy/spdy-core/src/test/java/org/eclipse/jetty/spdy/frames/TestSPDYParserListener.java
+++ b/jetty-spdy/spdy-core/src/test/java/org/eclipse/jetty/spdy/frames/TestSPDYParserListener.java
@@ -1,18 +1,15 @@
-/*
- * Copyright (c) 2012 the original author or authors.
- *
- * 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.
- */
+//========================================================================
+//Copyright 2011-2012 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.spdy.frames;
diff --git a/jetty-spdy/spdy-core/src/test/java/org/eclipse/jetty/spdy/frames/WindowUpdateGenerateParseTest.java b/jetty-spdy/spdy-core/src/test/java/org/eclipse/jetty/spdy/frames/WindowUpdateGenerateParseTest.java
index 8f7dbee211..41bdf676ac 100644
--- a/jetty-spdy/spdy-core/src/test/java/org/eclipse/jetty/spdy/frames/WindowUpdateGenerateParseTest.java
+++ b/jetty-spdy/spdy-core/src/test/java/org/eclipse/jetty/spdy/frames/WindowUpdateGenerateParseTest.java
@@ -1,18 +1,15 @@
-/*
- * Copyright (c) 2012 the original author or authors.
- *
- * 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.
- */
+//========================================================================
+//Copyright 2011-2012 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.spdy.frames;
diff --git a/jetty-spdy/spdy-core/src/test/java/org/eclipse/jetty/spdy/parser/LiveChromiumRequestParserTest.java b/jetty-spdy/spdy-core/src/test/java/org/eclipse/jetty/spdy/parser/LiveChromiumRequestParserTest.java
index 56b65f0b6f..46b7897f7a 100644
--- a/jetty-spdy/spdy-core/src/test/java/org/eclipse/jetty/spdy/parser/LiveChromiumRequestParserTest.java
+++ b/jetty-spdy/spdy-core/src/test/java/org/eclipse/jetty/spdy/parser/LiveChromiumRequestParserTest.java
@@ -1,18 +1,15 @@
-/*
- * Copyright (c) 2012 the original author or authors.
- *
- * 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.
- */
+//========================================================================
+//Copyright 2011-2012 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.spdy.parser;
diff --git a/jetty-spdy/spdy-core/src/test/java/org/eclipse/jetty/spdy/parser/ParseVersusCacheBenchmarkTest.java b/jetty-spdy/spdy-core/src/test/java/org/eclipse/jetty/spdy/parser/ParseVersusCacheBenchmarkTest.java
index abaac53a2c..cc92e0c629 100644
--- a/jetty-spdy/spdy-core/src/test/java/org/eclipse/jetty/spdy/parser/ParseVersusCacheBenchmarkTest.java
+++ b/jetty-spdy/spdy-core/src/test/java/org/eclipse/jetty/spdy/parser/ParseVersusCacheBenchmarkTest.java
@@ -1,18 +1,15 @@
-/*
- * Copyright (c) 2012 the original author or authors.
- *
- * 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.
- */
+//========================================================================
+//Copyright 2011-2012 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.spdy.parser;
diff --git a/jetty-spdy/spdy-core/src/test/java/org/eclipse/jetty/spdy/parser/UnknownControlFrameTest.java b/jetty-spdy/spdy-core/src/test/java/org/eclipse/jetty/spdy/parser/UnknownControlFrameTest.java
index 750f407d4b..12c470c40c 100644
--- a/jetty-spdy/spdy-core/src/test/java/org/eclipse/jetty/spdy/parser/UnknownControlFrameTest.java
+++ b/jetty-spdy/spdy-core/src/test/java/org/eclipse/jetty/spdy/parser/UnknownControlFrameTest.java
@@ -1,3 +1,16 @@
+//========================================================================
+//Copyright 2011-2012 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.spdy.parser;
import java.nio.ByteBuffer;
@@ -23,7 +36,7 @@ public class UnknownControlFrameTest
@Test
public void testUnknownControlFrame() throws Exception
{
- SynStreamFrame frame = new SynStreamFrame(SPDY.V2, SynInfo.FLAG_CLOSE, 1, 0, (byte)0, new Headers());
+ SynStreamFrame frame = new SynStreamFrame(SPDY.V2, SynInfo.FLAG_CLOSE, 1, 0, (byte)0, (short)0, new Headers());
Generator generator = new Generator(new StandardByteBufferPool(), new StandardCompressionFactory.StandardCompressor());
ByteBuffer buffer = generator.control(frame);
// Change the frame type to unknown
diff --git a/jetty-spdy/spdy-core/src/test/resources/keystore.jks b/jetty-spdy/spdy-core/src/test/resources/keystore.jks
new file mode 100644
index 0000000000..428ba54776
--- /dev/null
+++ b/jetty-spdy/spdy-core/src/test/resources/keystore.jks
Binary files differ
diff --git a/jetty-spdy/spdy-core/src/test/resources/truststore.jks b/jetty-spdy/spdy-core/src/test/resources/truststore.jks
new file mode 100644
index 0000000000..839cb8c351
--- /dev/null
+++ b/jetty-spdy/spdy-core/src/test/resources/truststore.jks
Binary files differ
diff --git a/jetty-spdy/spdy-jetty-http-webapp/pom.xml b/jetty-spdy/spdy-jetty-http-webapp/pom.xml
index 7aa8e91525..150217e98c 100644
--- a/jetty-spdy/spdy-jetty-http-webapp/pom.xml
+++ b/jetty-spdy/spdy-jetty-http-webapp/pom.xml
@@ -39,7 +39,7 @@
<stopKey>quit</stopKey>
<jvmArgs>
-Dlog4j.configuration=file://${basedir}/src/main/resources/log4j.properties
- -Xbootclasspath/p:${settings.localRepository}/org/mortbay/jetty/npn/npn-boot/${project.version}/npn-boot-${project.version}.jar
+ -Xbootclasspath/p:${settings.localRepository}/org/mortbay/jetty/npn/npn-boot/${npn.version}/npn-boot-${npn.version}.jar
</jvmArgs>
<jettyXml>${basedir}/src/main/config/etc/jetty-spdy.xml</jettyXml>
<contextPath>/</contextPath>
@@ -60,4 +60,45 @@
-->
</plugins>
</build>
+
+<!--
+ <profiles>
+ <profile>
+ <id>proxy</id>
+ <build>
+ <plugins>
+ <plugin>
+ <groupId>org.mortbay.jetty</groupId>
+ <artifactId>jetty-maven-plugin</artifactId>
+ <version>${project.version}</version>
+ <configuration>
+ <stopPort>8888</stopPort>
+ <stopKey>quit</stopKey>
+ <jvmArgs>
+ -Dlog4j.configuration=file://${basedir}/src/main/resources/log4j.properties
+ -Xbootclasspath/p:${settings.localRepository}/org/mortbay/jetty/npn/npn-boot/${npn.version}/npn-boot-${npn.version}.jar
+ -Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=n,address=5005
+ </jvmArgs>
+ <jettyXml>${basedir}/src/main/config/etc/jetty-spdy-proxy.xml</jettyXml>
+ <contextPath>/</contextPath>
+ </configuration>
+ <dependencies>
+ <dependency>
+ <groupId>org.eclipse.jetty.spdy</groupId>
+ <artifactId>spdy-jetty-http</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.slf4j</groupId>
+ <artifactId>slf4j-log4j12</artifactId>
+ <version>${slf4j-version}</version>
+ </dependency>
+ </dependencies>
+ </plugin>
+ </plugins>
+ </build>
+ </profile>
+ </profiles>
+-->
+
</project>
diff --git a/jetty-spdy/spdy-jetty-http-webapp/src/main/config/etc/jetty-spdy-proxy.xml b/jetty-spdy/spdy-jetty-http-webapp/src/main/config/etc/jetty-spdy-proxy.xml
new file mode 100644
index 0000000000..9c637ec41f
--- /dev/null
+++ b/jetty-spdy/spdy-jetty-http-webapp/src/main/config/etc/jetty-spdy-proxy.xml
@@ -0,0 +1,98 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE Configure PUBLIC "-//Jetty//Configure//EN" "http://www.eclipse.org/jetty/configure.dtd">
+
+<Configure id="Server" class="org.eclipse.jetty.server.Server">
+
+ <New id="sslContextFactory" class="org.eclipse.jetty.util.ssl.SslContextFactory">
+ <Set name="keyStorePath">src/main/resources/keystore.jks</Set>
+ <Set name="keyStorePassword">storepwd</Set>
+ <Set name="trustStore">src/main/resources/truststore.jks</Set>
+ <Set name="trustStorePassword">storepwd</Set>
+ <Set name="protocol">TLSv1</Set>
+ </New>
+
+ <!--
+ <Set class="org.eclipse.jetty.npn.NextProtoNego" name="debug" type="boolean">true</Set>
+ -->
+
+ <!--
+ This is the upstream server connector. It speaks non-SSL SPDY/2(HTTP) on port 9090.
+ -->
+ <Call name="addConnector">
+ <Arg>
+ <New class="org.eclipse.jetty.spdy.http.HTTPSPDYServerConnector">
+ <Set name="Port">9090</Set>
+ <Set name="defaultAsyncConnectionFactory">
+ <Call name="getAsyncConnectionFactory">
+ <Arg>spdy/2</Arg>
+ </Call>
+ </Set>
+ </New>
+ </Arg>
+ </Call>
+
+ <!--
+ This ProxyEngine translates the incoming SPDY/x(HTTP) request to SPDY/2(HTTP)
+ -->
+ <New id="spdyProxyEngine" class="org.eclipse.jetty.spdy.proxy.SPDYProxyEngine">
+ <Arg>
+ <New class="org.eclipse.jetty.spdy.SPDYClient$Factory">
+ <Call name="start"/>
+ </New>
+ </Arg>
+ </New>
+
+ <!--
+ The ProxyEngineSelector receives SPDY/x(HTTP) requests from proxy connectors below
+ and is configured to process requests for host "localhost".
+ Such requests are converted from SPDY/x(HTTP) to SPDY/2(HTTP) by the configured ProxyEngine
+ and forwarded to 127.0.0.1:9090, where they are served by the upstream server above.
+ -->
+ <New id="proxyEngineSelector" class="org.eclipse.jetty.spdy.proxy.ProxyEngineSelector">
+ <Call name="putProxyEngine">
+ <Arg>spdy/2</Arg>
+ <Arg><Ref id="spdyProxyEngine" /></Arg>
+ </Call>
+ <Set name="proxyServerInfos">
+ <Map>
+ <Entry>
+ <Item>localhost</Item>
+ <Item>
+ <New class="org.eclipse.jetty.spdy.proxy.ProxyEngineSelector$ProxyServerInfo">
+ <Arg type="String">spdy/2</Arg>
+ <Arg>127.0.0.1</Arg>
+ <Arg type="int">9090</Arg>
+ </New>
+ </Item>
+ </Entry>
+ </Map>
+ </Set>
+ </New>
+
+ <!--
+ These are the reverse proxy connectors accepting requests from clients.
+ They accept non-SSL (on port 8080) and SSL (on port 8443) HTTP,
+ SPDY/2(HTTP) and SPDY/3(HTTP).
+ Non-SPDY HTTP requests are converted to SPDY internally and passed to the
+ ProxyEngine above.
+ -->
+ <Call name="addConnector">
+ <Arg>
+ <New class="org.eclipse.jetty.spdy.proxy.HTTPSPDYProxyConnector">
+ <Arg><Ref id="proxyEngineSelector" /></Arg>
+ <Set name="Port">8080</Set>
+ </New>
+ </Arg>
+ </Call>
+ <Call name="addConnector">
+ <Arg>
+ <New class="org.eclipse.jetty.spdy.proxy.HTTPSPDYProxyConnector">
+ <Arg><Ref id="proxyEngineSelector" /></Arg>
+ <Arg><Ref id="sslContextFactory" /></Arg>
+ <Set name="Port">8443</Set>
+ </New>
+ </Arg>
+ </Call>
+
+
+</Configure>
diff --git a/jetty-spdy/spdy-jetty-http-webapp/src/main/config/etc/jetty-spdy.xml b/jetty-spdy/spdy-jetty-http-webapp/src/main/config/etc/jetty-spdy.xml
index 95c9c2b9c2..0d847bcbd4 100644
--- a/jetty-spdy/spdy-jetty-http-webapp/src/main/config/etc/jetty-spdy.xml
+++ b/jetty-spdy/spdy-jetty-http-webapp/src/main/config/etc/jetty-spdy.xml
@@ -11,9 +11,45 @@
<Set name="protocol">TLSv1</Set>
</New>
+ <!-- Uncomment to create a ReferrerPushStrategy that can be added to the Connectors -->
+
+ <!--
+ <New id="pushStrategy" class="org.eclipse.jetty.spdy.http.ReferrerPushStrategy">
+ <Arg type="List">
+ <Array type="String">
+ <Item>.*\.css</Item>
+ <Item>.*\.js</Item>
+ <Item>.*\.png</Item>
+ <Item>.*\.jpg</Item>
+ <Item>.*\.gif</Item>
+ </Array>
+ </Arg>
+ </New>
+ -->
+
+ <!--<Set class="org.eclipse.jetty.npn.NextProtoNego" name="debug" type="boolean">true</Set>-->
+
<Call name="addConnector">
<Arg>
<New class="org.eclipse.jetty.spdy.http.HTTPSPDYServerConnector">
+ <!-- uncomment to enable to apply ReferrerPushStrategy for spdy/3
+ if you want to support it in both spdy/2 and spdy/3, just replace the
+ value in the first map entry.
+ -->
+ <!--
+ <Arg name="pushStrategies">
+ <Map>
+ <Entry>
+ <Item type="short">2</Item>
+ <Item><New class="org.eclipse.jetty.spdy.http.PushStrategy$None" /></Item>
+ </Entry>
+ <Entry>
+ <Item type="short">3</Item>
+ <Item><Ref id="pushStrategy" /></Item>
+ </Entry>
+ </Map>
+ </Arg>
+ -->
<Set name="Port">8080</Set>
</New>
</Arg>
@@ -24,6 +60,24 @@
<Arg>
<Ref id="sslContextFactory" />
</Arg>
+ <!-- uncomment to enable to apply ReferrerPushStrategy for spdy/3
+ if you want to support it in both spdy/2 and spdy/3, just replace the
+ value in the first map entry.
+ -->
+ <!--
+ <Arg name="pushStrategies">
+ <Map>
+ <Entry>
+ <Item type="short">2</Item>
+ <Item><New class="org.eclipse.jetty.spdy.http.PushStrategy$None" /></Item>
+ </Entry>
+ <Entry>
+ <Item type="short">3</Item>
+ <Item><Ref id="pushStrategy" /></Item>
+ </Entry>
+ </Map>
+ </Arg>
+ -->
<Set name="Port">8443</Set>
</New>
</Arg>
diff --git a/jetty-spdy/spdy-jetty-http/pom.xml b/jetty-spdy/spdy-jetty-http/pom.xml
index e89e209843..dfaf1b1f93 100644
--- a/jetty-spdy/spdy-jetty-http/pom.xml
+++ b/jetty-spdy/spdy-jetty-http/pom.xml
@@ -61,11 +61,22 @@
<scope>test</scope>
</dependency>
<dependency>
+ <groupId>org.eclipse.jetty</groupId>
+ <artifactId>jetty-client</artifactId>
+ <version>${project.version}</version>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-log4j12</artifactId>
<version>${slf4j-version}</version>
<scope>test</scope>
</dependency>
+ <dependency>
+ <groupId>org.mockito</groupId>
+ <artifactId>mockito-core</artifactId>
+ <scope>test</scope>
+ </dependency>
</dependencies>
</project>
diff --git a/jetty-spdy/spdy-jetty-http/src/main/java/org/eclipse/jetty/spdy/http/AbstractHTTPSPDYServerConnector.java b/jetty-spdy/spdy-jetty-http/src/main/java/org/eclipse/jetty/spdy/http/AbstractHTTPSPDYServerConnector.java
new file mode 100644
index 0000000000..543f78323c
--- /dev/null
+++ b/jetty-spdy/spdy-jetty-http/src/main/java/org/eclipse/jetty/spdy/http/AbstractHTTPSPDYServerConnector.java
@@ -0,0 +1,61 @@
+//========================================================================
+//Copyright 2011-2012 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.spdy.http;
+
+import java.io.IOException;
+
+import org.eclipse.jetty.http.HttpSchemes;
+import org.eclipse.jetty.io.EndPoint;
+import org.eclipse.jetty.server.Request;
+import org.eclipse.jetty.spdy.SPDYServerConnector;
+import org.eclipse.jetty.spdy.api.server.ServerSessionFrameListener;
+import org.eclipse.jetty.util.ssl.SslContextFactory;
+
+public class AbstractHTTPSPDYServerConnector extends SPDYServerConnector
+{
+ public AbstractHTTPSPDYServerConnector(ServerSessionFrameListener listener, SslContextFactory sslContextFactory)
+ {
+ super(listener, sslContextFactory);
+ }
+
+ @Override
+ public void customize(EndPoint endPoint, Request request) throws IOException
+ {
+ super.customize(endPoint, request);
+ if (getSslContextFactory() != null)
+ request.setScheme(HttpSchemes.HTTPS);
+ }
+
+ @Override
+ public boolean isConfidential(Request request)
+ {
+ if (getSslContextFactory() != null)
+ {
+ int confidentialPort = getConfidentialPort();
+ return confidentialPort == 0 || confidentialPort == request.getServerPort();
+ }
+ return super.isConfidential(request);
+ }
+
+ @Override
+ public boolean isIntegral(Request request)
+ {
+ if (getSslContextFactory() != null)
+ {
+ int integralPort = getIntegralPort();
+ return integralPort == 0 || integralPort == request.getServerPort();
+ }
+ return super.isIntegral(request);
+ }
+}
diff --git a/jetty-spdy/spdy-jetty-http/src/main/java/org/eclipse/jetty/spdy/http/HTTPSPDYHeader.java b/jetty-spdy/spdy-jetty-http/src/main/java/org/eclipse/jetty/spdy/http/HTTPSPDYHeader.java
new file mode 100644
index 0000000000..7149aa5ae0
--- /dev/null
+++ b/jetty-spdy/spdy-jetty-http/src/main/java/org/eclipse/jetty/spdy/http/HTTPSPDYHeader.java
@@ -0,0 +1,73 @@
+//========================================================================
+//Copyright 2011-2012 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.spdy.http;
+
+import java.util.HashMap;
+import java.util.Map;
+
+import org.eclipse.jetty.spdy.api.SPDY;
+
+public enum HTTPSPDYHeader
+{
+ METHOD("method", ":method"),
+ URI("url", ":path"),
+ VERSION("version", ":version"),
+ SCHEME("scheme", ":scheme"),
+ HOST("host", ":host"),
+ STATUS("status", ":status");
+
+ public static HTTPSPDYHeader from(short version, String name)
+ {
+ switch (version)
+ {
+ case SPDY.V2:
+ return Names.v2Names.get(name);
+ case SPDY.V3:
+ return Names.v3Names.get(name);
+ default:
+ throw new IllegalStateException();
+ }
+ }
+
+ private final String v2Name;
+ private final String v3Name;
+
+ private HTTPSPDYHeader(String v2Name, String v3Name)
+ {
+ this.v2Name = v2Name;
+ Names.v2Names.put(v2Name, this);
+ this.v3Name = v3Name;
+ Names.v3Names.put(v3Name, this);
+ }
+
+ public String name(short version)
+ {
+ switch (version)
+ {
+ case SPDY.V2:
+ return v2Name;
+ case SPDY.V3:
+ return v3Name;
+ default:
+ throw new IllegalStateException();
+ }
+ }
+
+ private static class Names
+ {
+ private static final Map<String, HTTPSPDYHeader> v2Names = new HashMap<>();
+ private static final Map<String, HTTPSPDYHeader> v3Names = new HashMap<>();
+ }
+}
diff --git a/jetty-spdy/spdy-jetty-http/src/main/java/org/eclipse/jetty/spdy/http/HTTPSPDYServerConnector.java b/jetty-spdy/spdy-jetty-http/src/main/java/org/eclipse/jetty/spdy/http/HTTPSPDYServerConnector.java
index 63544a0356..8b76589cb3 100644
--- a/jetty-spdy/spdy-jetty-http/src/main/java/org/eclipse/jetty/spdy/http/HTTPSPDYServerConnector.java
+++ b/jetty-spdy/spdy-jetty-http/src/main/java/org/eclipse/jetty/spdy/http/HTTPSPDYServerConnector.java
@@ -1,91 +1,64 @@
-/*
- * Copyright (c) 2012 the original author or authors.
- *
- * 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.
- */
+//========================================================================
+//Copyright 2011-2012 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.spdy.http;
-import java.io.IOException;
+import java.util.Collections;
+import java.util.Map;
-import org.eclipse.jetty.http.HttpSchemes;
-import org.eclipse.jetty.io.EndPoint;
-import org.eclipse.jetty.server.Request;
-import org.eclipse.jetty.spdy.AsyncConnectionFactory;
-import org.eclipse.jetty.spdy.SPDYServerConnector;
import org.eclipse.jetty.spdy.api.SPDY;
import org.eclipse.jetty.util.ssl.SslContextFactory;
-public class HTTPSPDYServerConnector extends SPDYServerConnector
+public class HTTPSPDYServerConnector extends AbstractHTTPSPDYServerConnector
{
- private final AsyncConnectionFactory defaultConnectionFactory;
- private final PushStrategy pushStrategy = new PushStrategy.None();
-
public HTTPSPDYServerConnector()
{
- this(null);
+ this(null, Collections.<Short, PushStrategy>emptyMap());
}
- public HTTPSPDYServerConnector(SslContextFactory sslContextFactory)
+ public HTTPSPDYServerConnector(Map<Short, PushStrategy> pushStrategies)
{
- super(null, sslContextFactory);
- // Override the default connection factory for non-SSL connections
- defaultConnectionFactory = new ServerHTTPAsyncConnectionFactory(this);
+ this(null, pushStrategies);
}
- @Override
- protected void doStart() throws Exception
- {
- super.doStart();
- // Override the "spdy/2" protocol by handling HTTP over SPDY
- putAsyncConnectionFactory("spdy/2", new ServerHTTPSPDYAsyncConnectionFactory(SPDY.V2, getByteBufferPool(), getExecutor(), getScheduler(), this, pushStrategy));
- // Add the "http/1.1" protocol for browsers that do not support NPN
- putAsyncConnectionFactory("http/1.1", new ServerHTTPAsyncConnectionFactory(this));
- }
-
- @Override
- protected AsyncConnectionFactory getDefaultAsyncConnectionFactory()
+ public HTTPSPDYServerConnector(SslContextFactory sslContextFactory)
{
- return defaultConnectionFactory;
+ this(sslContextFactory, Collections.<Short, PushStrategy>emptyMap());
}
- @Override
- public void customize(EndPoint endPoint, Request request) throws IOException
+ public HTTPSPDYServerConnector(SslContextFactory sslContextFactory, Map<Short, PushStrategy> pushStrategies)
{
- super.customize(endPoint, request);
- if (getSslContextFactory() != null)
- request.setScheme(HttpSchemes.HTTPS);
+ // We pass a null ServerSessionFrameListener because for
+ // HTTP over SPDY we need one that references the endPoint
+ super(null, sslContextFactory);
+ clearAsyncConnectionFactories();
+ // The "spdy/3" protocol handles HTTP over SPDY
+ putAsyncConnectionFactory("spdy/3", new ServerHTTPSPDYAsyncConnectionFactory(SPDY.V3, getByteBufferPool(), getExecutor(), getScheduler(), this, getPushStrategy(SPDY.V3,pushStrategies)));
+ // The "spdy/2" protocol handles HTTP over SPDY
+ putAsyncConnectionFactory("spdy/2", new ServerHTTPSPDYAsyncConnectionFactory(SPDY.V2, getByteBufferPool(), getExecutor(), getScheduler(), this, getPushStrategy(SPDY.V2,pushStrategies)));
+ // The "http/1.1" protocol handles browsers that support NPN but not SPDY
+ putAsyncConnectionFactory("http/1.1", new ServerHTTPAsyncConnectionFactory(this));
+ // The default connection factory handles plain HTTP on non-SSL or non-NPN connections
+ setDefaultAsyncConnectionFactory(getAsyncConnectionFactory("http/1.1"));
}
- @Override
- public boolean isConfidential(Request request)
+ private PushStrategy getPushStrategy(short version, Map<Short, PushStrategy> pushStrategies)
{
- if (getSslContextFactory() != null)
- {
- int confidentialPort = getConfidentialPort();
- return confidentialPort == 0 || confidentialPort == request.getServerPort();
- }
- return super.isConfidential(request);
+ PushStrategy pushStrategy = pushStrategies.get(version);
+ if(pushStrategy == null)
+ pushStrategy = new PushStrategy.None();
+ return pushStrategy;
}
- @Override
- public boolean isIntegral(Request request)
- {
- if (getSslContextFactory() != null)
- {
- int integralPort = getIntegralPort();
- return integralPort == 0 || integralPort == request.getServerPort();
- }
- return super.isIntegral(request);
- }
}
diff --git a/jetty-spdy/spdy-jetty-http/src/main/java/org/eclipse/jetty/spdy/http/PushStrategy.java b/jetty-spdy/spdy-jetty-http/src/main/java/org/eclipse/jetty/spdy/http/PushStrategy.java
index 780a5b22d1..c15fe5baac 100644
--- a/jetty-spdy/spdy-jetty-http/src/main/java/org/eclipse/jetty/spdy/http/PushStrategy.java
+++ b/jetty-spdy/spdy-jetty-http/src/main/java/org/eclipse/jetty/spdy/http/PushStrategy.java
@@ -1,18 +1,16 @@
-/*
- * Copyright (c) 2012 the original author or authors.
- *
- * 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.
- */
+//========================================================================
+//Copyright 2011-2012 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.spdy.http;
diff --git a/jetty-spdy/spdy-jetty-http/src/main/java/org/eclipse/jetty/spdy/http/ReferrerPushStrategy.java b/jetty-spdy/spdy-jetty-http/src/main/java/org/eclipse/jetty/spdy/http/ReferrerPushStrategy.java
index cf3fe06f1b..0079897726 100644
--- a/jetty-spdy/spdy-jetty-http/src/main/java/org/eclipse/jetty/spdy/http/ReferrerPushStrategy.java
+++ b/jetty-spdy/spdy-jetty-http/src/main/java/org/eclipse/jetty/spdy/http/ReferrerPushStrategy.java
@@ -1,28 +1,28 @@
-/*
- * Copyright (c) 2012 the original author or authors.
- *
- * 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.
- */
+//========================================================================
+//Copyright 2011-2012 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.spdy.http;
import java.util.Arrays;
import java.util.Collections;
-import java.util.LinkedHashSet;
+import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.atomic.AtomicLong;
import java.util.regex.Pattern;
import org.eclipse.jetty.spdy.api.Headers;
@@ -37,64 +37,99 @@ import org.eclipse.jetty.util.log.Logger;
* will have a <tt>Referer</tt> HTTP header that points to <tt>index.html</tt>, which we
* use to link the associated resource to the main resource.</p>
* <p>However, also following a hyperlink generates a HTTP request with a <tt>Referer</tt>
- * HTTP header that points to <tt>index.html</tt>; therefore main resources and associated
- * resources must be distinguishable.</p>
- * <p>This class distinguishes associated resources by their URL path suffix.
+ * HTTP header that points to <tt>index.html</tt>; therefore a proper value for {@link #getReferrerPushPeriod()}
+ * has to be set. If the referrerPushPeriod for a main resource has been passed, no more
+ * associated resources will be added for that main resource.</p>
+ * <p>This class distinguishes associated main resources by their URL path suffix and content
+ * type.
* CSS stylesheets, images and JavaScript files have recognizable URL path suffixes that
- * are classified as associated resources.</p>
- * <p>Note however, that CSS stylesheets may refer to images, and the CSS image request
- * will have the CSS stylesheet as referrer, so there is some degree of recursion that
- * needs to be handled.</p>
- *
- * TODO: this class is kind-of leaking since the resources map is always adding entries
- * TODO: although these entries will be limited by the number of application pages.
- * TODO: however, there is no ConcurrentLinkedHashMap yet in JDK (there is in Guava though)
- * TODO: so we cannot use the built-in LRU features of LinkedHashMap
- *
- * TODO: Wikipedia maps URLs like http://en.wikipedia.org/wiki/File:PNG-Gradient_hex.png
- * TODO: to text/html, so perhaps we need to improve isPushResource() by looking at the
- * TODO: response Content-Type header, and not only at the URL extension
+ * are classified as associated resources. The suffix regexs can be configured by constructor argument</p>
+ * <p>When CSS stylesheets refer to images, the CSS image request will have the CSS
+ * stylesheet as referrer. This implementation will push also the CSS image.</p>
+ * <p>The push metadata built by this implementation is limited by the number of pages
+ * of the application itself, and by the
+ * {@link #getMaxAssociatedResources() max associated resources} parameter.
+ * This parameter limits the number of associated resources per each main resource, so
+ * that if a main resource has hundreds of associated resources, only up to the number
+ * specified by this parameter will be pushed.</p>
*/
public class ReferrerPushStrategy implements PushStrategy
{
private static final Logger logger = Log.getLogger(ReferrerPushStrategy.class);
- private final ConcurrentMap<String, Set<String>> resources = new ConcurrentHashMap<>();
- private final Set<Pattern> pushRegexps = new LinkedHashSet<>();
- private final Set<Pattern> allowedPushOrigins = new LinkedHashSet<>();
+ private final ConcurrentMap<String, MainResource> mainResources = new ConcurrentHashMap<>();
+ private final Set<Pattern> pushRegexps = new HashSet<>();
+ private final Set<String> pushContentTypes = new HashSet<>();
+ private final Set<Pattern> allowedPushOrigins = new HashSet<>();
+ private volatile int maxAssociatedResources = 32;
+ private volatile int referrerPushPeriod = 5000;
public ReferrerPushStrategy()
{
- this(Arrays.asList(".*\\.css", ".*\\.js", ".*\\.png", ".*\\.jpg", ".*\\.gif"));
+ this(Arrays.asList(".*\\.css", ".*\\.js", ".*\\.png", ".*\\.jpeg", ".*\\.jpg", ".*\\.gif", ".*\\.ico"));
}
public ReferrerPushStrategy(List<String> pushRegexps)
{
- this(pushRegexps, Collections.<String>emptyList());
+ this(pushRegexps, Arrays.asList(
+ "text/css",
+ "text/javascript", "application/javascript", "application/x-javascript",
+ "image/png", "image/x-png",
+ "image/jpeg",
+ "image/gif",
+ "image/x-icon", "image/vnd.microsoft.icon"));
+ }
+
+ public ReferrerPushStrategy(List<String> pushRegexps, List<String> pushContentTypes)
+ {
+ this(pushRegexps, pushContentTypes, Collections.<String>emptyList());
}
- public ReferrerPushStrategy(List<String> pushRegexps, List<String> allowedPushOrigins)
+ public ReferrerPushStrategy(List<String> pushRegexps, List<String> pushContentTypes, List<String> allowedPushOrigins)
{
for (String pushRegexp : pushRegexps)
this.pushRegexps.add(Pattern.compile(pushRegexp));
+ this.pushContentTypes.addAll(pushContentTypes);
for (String allowedPushOrigin : allowedPushOrigins)
this.allowedPushOrigins.add(Pattern.compile(allowedPushOrigin.replace(".", "\\.").replace("*", ".*")));
}
+ public int getMaxAssociatedResources()
+ {
+ return maxAssociatedResources;
+ }
+
+ public void setMaxAssociatedResources(int maxAssociatedResources)
+ {
+ this.maxAssociatedResources = maxAssociatedResources;
+ }
+
+ public int getReferrerPushPeriod()
+ {
+ return referrerPushPeriod;
+ }
+
+ public void setReferrerPushPeriod(int referrerPushPeriod)
+ {
+ this.referrerPushPeriod = referrerPushPeriod;
+ }
+
@Override
public Set<String> apply(Stream stream, Headers requestHeaders, Headers responseHeaders)
{
- Set<String> result = Collections.emptySet();
- String scheme = requestHeaders.get("scheme").value();
- String host = requestHeaders.get("host").value();
- String origin = new StringBuilder(scheme).append("://").append(host).toString();
- String url = requestHeaders.get("url").value();
- String absoluteURL = new StringBuilder(origin).append(url).toString();
- logger.debug("Applying push strategy for {}", absoluteURL);
- if (isValidMethod(requestHeaders.get("method").value()))
+ Set<String> result = Collections.<String>emptySet();
+ short version = stream.getSession().getVersion();
+ if (!isIfModifiedSinceHeaderPresent(requestHeaders) && isValidMethod(requestHeaders.get(HTTPSPDYHeader.METHOD.name(version)).value()))
{
+ String scheme = requestHeaders.get(HTTPSPDYHeader.SCHEME.name(version)).value();
+ String host = requestHeaders.get(HTTPSPDYHeader.HOST.name(version)).value();
+ String origin = scheme + "://" + host;
+ String url = requestHeaders.get(HTTPSPDYHeader.URI.name(version)).value();
+ String absoluteURL = origin + url;
+ logger.debug("Applying push strategy for {}", absoluteURL);
if (isMainResource(url, responseHeaders))
{
- result = pushResources(absoluteURL);
+ MainResource mainResource = getOrCreateMainResource(absoluteURL);
+ result = mainResource.getResources();
}
else if (isPushResource(url, responseHeaders))
{
@@ -102,18 +137,49 @@ public class ReferrerPushStrategy implements PushStrategy
if (referrerHeader != null)
{
String referrer = referrerHeader.value();
- Set<String> pushResources = resources.get(referrer);
- if (pushResources == null || !pushResources.contains(url))
- buildMetadata(origin, url, referrer);
+ MainResource mainResource = mainResources.get(referrer);
+ if (mainResource == null)
+ mainResource = getOrCreateMainResource(referrer);
+
+ Set<String> pushResources = mainResource.getResources();
+ if (!pushResources.contains(url))
+ mainResource.addResource(url, origin, referrer);
else
- result = pushResources(absoluteURL);
+ result = getPushResources(absoluteURL);
}
}
+ logger.debug("Pushing {} resources for {}: {}", result.size(), absoluteURL, result);
}
- logger.debug("Push resources for {}: {}", absoluteURL, result);
return result;
}
+ private Set<String> getPushResources(String absoluteURL)
+ {
+ Set<String> result = Collections.emptySet();
+ if (mainResources.get(absoluteURL) != null)
+ result = mainResources.get(absoluteURL).getResources();
+ return result;
+ }
+
+ private MainResource getOrCreateMainResource(String absoluteURL)
+ {
+ MainResource mainResource = mainResources.get(absoluteURL);
+ if (mainResource == null)
+ {
+ logger.debug("Creating new main resource for {}", absoluteURL);
+ MainResource value = new MainResource(absoluteURL);
+ mainResource = mainResources.putIfAbsent(absoluteURL, value);
+ if (mainResource == null)
+ mainResource = value;
+ }
+ return mainResource;
+ }
+
+ private boolean isIfModifiedSinceHeaderPresent(Headers headers)
+ {
+ return headers.get("if-modified-since") != null;
+ }
+
private boolean isValidMethod(String method)
{
return "GET".equalsIgnoreCase(method);
@@ -129,43 +195,85 @@ public class ReferrerPushStrategy implements PushStrategy
for (Pattern pushRegexp : pushRegexps)
{
if (pushRegexp.matcher(url).matches())
- return true;
+ {
+ Headers.Header header = responseHeaders.get("content-type");
+ if (header == null)
+ return true;
+
+ String contentType = header.value().toLowerCase();
+ for (String pushContentType : pushContentTypes)
+ if (contentType.startsWith(pushContentType))
+ return true;
+ }
}
return false;
}
- private Set<String> pushResources(String absoluteURL)
+ private class MainResource
{
- Set<String> pushResources = resources.get(absoluteURL);
- if (pushResources == null)
- return Collections.emptySet();
- return Collections.unmodifiableSet(pushResources);
- }
+ private final String name;
+ private final Set<String> resources = Collections.newSetFromMap(new ConcurrentHashMap<String, Boolean>());
+ private final AtomicLong firstResourceAdded = new AtomicLong(-1);
- private void buildMetadata(String origin, String url, String referrer)
- {
- if (referrer.startsWith(origin) || isPushOriginAllowed(origin))
+ private MainResource(String name)
{
- Set<String> pushResources = resources.get(referrer);
- if (pushResources == null)
+ this.name = name;
+ }
+
+ public boolean addResource(String url, String origin, String referrer)
+ {
+ // We start the push period here and not when initializing the main resource, because a browser with a
+ // prefilled cache won't request the subresources. If the browser with warmed up cache now hits the main
+ // resource after a server restart, the push period shouldn't start until the first subresource is
+ // being requested.
+ firstResourceAdded.compareAndSet(-1, System.nanoTime());
+
+ long delay = TimeUnit.NANOSECONDS.toMillis(System.nanoTime() - firstResourceAdded.get());
+ if (!referrer.startsWith(origin) && !isPushOriginAllowed(origin))
+ {
+ logger.debug("Skipped store of push metadata {} for {}: Origin: {} doesn't match or origin not allowed",
+ url, name, origin);
+ return false;
+ }
+
+ // This check is not strictly concurrent-safe, but limiting
+ // the number of associated resources is achieved anyway
+ // although in rare cases few more resources will be stored
+ if (resources.size() >= maxAssociatedResources)
{
- pushResources = Collections.newSetFromMap(new ConcurrentHashMap<String, Boolean>());
- Set<String> existing = resources.putIfAbsent(referrer, pushResources);
- if (existing != null)
- pushResources = existing;
+ logger.debug("Skipped store of push metadata {} for {}: max associated resources ({}) reached",
+ url, name, maxAssociatedResources);
+ return false;
}
- pushResources.add(url);
- logger.debug("Built push metadata for {}: {}", referrer, pushResources);
+ if (delay > referrerPushPeriod)
+ {
+ logger.debug("Delay: {}ms longer than referrerPushPeriod: {}ms. Not adding resource: {} for: {}", delay, referrerPushPeriod, url, name);
+ return false;
+ }
+
+ logger.debug("Adding resource: {} for: {} with delay: {}ms.", url, name, delay);
+ resources.add(url);
+ return true;
}
- }
- private boolean isPushOriginAllowed(String origin)
- {
- for (Pattern allowedPushOrigin : allowedPushOrigins)
+ public Set<String> getResources()
{
- if (allowedPushOrigin.matcher(origin).matches())
- return true;
+ return Collections.unmodifiableSet(resources);
+ }
+
+ public String toString()
+ {
+ return "MainResource: " + name + " associated resources:" + resources.size();
+ }
+
+ private boolean isPushOriginAllowed(String origin)
+ {
+ for (Pattern allowedPushOrigin : allowedPushOrigins)
+ {
+ if (allowedPushOrigin.matcher(origin).matches())
+ return true;
+ }
+ return false;
}
- return false;
}
}
diff --git a/jetty-spdy/spdy-jetty-http/src/main/java/org/eclipse/jetty/spdy/http/ServerHTTPAsyncConnectionFactory.java b/jetty-spdy/spdy-jetty-http/src/main/java/org/eclipse/jetty/spdy/http/ServerHTTPAsyncConnectionFactory.java
index 3622b2fdf6..b0bae06de1 100644
--- a/jetty-spdy/spdy-jetty-http/src/main/java/org/eclipse/jetty/spdy/http/ServerHTTPAsyncConnectionFactory.java
+++ b/jetty-spdy/spdy-jetty-http/src/main/java/org/eclipse/jetty/spdy/http/ServerHTTPAsyncConnectionFactory.java
@@ -1,18 +1,16 @@
-/*
- * Copyright (c) 2012 the original author or authors.
- *
- * 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.
- */
+//========================================================================
+//Copyright 2011-2012 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.spdy.http;
@@ -21,18 +19,23 @@ import java.nio.channels.SocketChannel;
import org.eclipse.jetty.io.AsyncEndPoint;
import org.eclipse.jetty.io.nio.AsyncConnection;
import org.eclipse.jetty.server.AsyncHttpConnection;
-import org.eclipse.jetty.server.Connector;
import org.eclipse.jetty.spdy.AsyncConnectionFactory;
+import org.eclipse.jetty.spdy.SPDYServerConnector;
public class ServerHTTPAsyncConnectionFactory implements AsyncConnectionFactory
{
- private final Connector connector;
+ private final SPDYServerConnector connector;
- public ServerHTTPAsyncConnectionFactory(Connector connector)
+ public ServerHTTPAsyncConnectionFactory(SPDYServerConnector connector)
{
this.connector = connector;
}
+ public SPDYServerConnector getConnector()
+ {
+ return connector;
+ }
+
@Override
public AsyncConnection newAsyncConnection(SocketChannel channel, AsyncEndPoint endPoint, Object attachment)
{
diff --git a/jetty-spdy/spdy-jetty-http/src/main/java/org/eclipse/jetty/spdy/http/ServerHTTPSPDYAsyncConnection.java b/jetty-spdy/spdy-jetty-http/src/main/java/org/eclipse/jetty/spdy/http/ServerHTTPSPDYAsyncConnection.java
index f82b3f08e1..ecc241ea97 100644
--- a/jetty-spdy/spdy-jetty-http/src/main/java/org/eclipse/jetty/spdy/http/ServerHTTPSPDYAsyncConnection.java
+++ b/jetty-spdy/spdy-jetty-http/src/main/java/org/eclipse/jetty/spdy/http/ServerHTTPSPDYAsyncConnection.java
@@ -1,18 +1,16 @@
-/*
- * Copyright (c) 2012 the original author or authors.
- *
- * 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.
- */
+//========================================================================
+//Copyright 2011-2012 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.spdy.http;
@@ -24,8 +22,10 @@ import java.util.LinkedList;
import java.util.Queue;
import java.util.Set;
import java.util.concurrent.BlockingQueue;
+import java.util.concurrent.ExecutionException;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.TimeUnit;
+import java.util.concurrent.TimeoutException;
import org.eclipse.jetty.http.HttpException;
import org.eclipse.jetty.http.HttpFields;
@@ -47,11 +47,13 @@ import org.eclipse.jetty.server.Connector;
import org.eclipse.jetty.server.Server;
import org.eclipse.jetty.spdy.SPDYAsyncConnection;
import org.eclipse.jetty.spdy.api.ByteBufferDataInfo;
+import org.eclipse.jetty.spdy.api.BytesDataInfo;
import org.eclipse.jetty.spdy.api.DataInfo;
import org.eclipse.jetty.spdy.api.Handler;
import org.eclipse.jetty.spdy.api.Headers;
import org.eclipse.jetty.spdy.api.ReplyInfo;
import org.eclipse.jetty.spdy.api.RstInfo;
+import org.eclipse.jetty.spdy.api.SPDY;
import org.eclipse.jetty.spdy.api.Stream;
import org.eclipse.jetty.spdy.api.StreamStatus;
import org.eclipse.jetty.spdy.api.SynInfo;
@@ -66,6 +68,7 @@ public class ServerHTTPSPDYAsyncConnection extends AbstractHttpConnection implem
private final Queue<Runnable> tasks = new LinkedList<>();
private final BlockingQueue<DataInfo> dataInfos = new LinkedBlockingQueue<>();
+ private final short version;
private final SPDYAsyncConnection connection;
private final PushStrategy pushStrategy;
private final Stream stream;
@@ -75,9 +78,10 @@ public class ServerHTTPSPDYAsyncConnection extends AbstractHttpConnection implem
private volatile State state = State.INITIAL;
private boolean dispatched; // Guarded by synchronization on tasks
- public ServerHTTPSPDYAsyncConnection(Connector connector, AsyncEndPoint endPoint, Server server, SPDYAsyncConnection connection, PushStrategy pushStrategy, Stream stream)
+ public ServerHTTPSPDYAsyncConnection(Connector connector, AsyncEndPoint endPoint, Server server, short version, SPDYAsyncConnection connection, PushStrategy pushStrategy, Stream stream)
{
super(connector, endPoint, server);
+ this.version = version;
this.connection = connection;
this.pushStrategy = pushStrategy;
this.stream = stream;
@@ -159,9 +163,9 @@ public class ServerHTTPSPDYAsyncConnection extends AbstractHttpConnection implem
}
case REQUEST:
{
- Headers.Header method = headers.get("method");
- Headers.Header uri = headers.get("url");
- Headers.Header version = headers.get("version");
+ Headers.Header method = headers.get(HTTPSPDYHeader.METHOD.name(version));
+ Headers.Header uri = headers.get(HTTPSPDYHeader.URI.name(version));
+ Headers.Header version = headers.get(HTTPSPDYHeader.VERSION.name(this.version));
if (method == null || uri == null || version == null)
throw new HttpException(HttpStatus.BAD_REQUEST_400);
@@ -172,6 +176,10 @@ public class ServerHTTPSPDYAsyncConnection extends AbstractHttpConnection implem
logger.debug("HTTP > {} {} {}", m, u, v);
startRequest(new ByteArrayBuffer(m), new ByteArrayBuffer(u), new ByteArrayBuffer(v));
+ Headers.Header schemeHeader = headers.get(HTTPSPDYHeader.SCHEME.name(this.version));
+ if(schemeHeader != null)
+ _request.setScheme(schemeHeader.value());
+
updateState(State.HEADERS);
handle();
break;
@@ -181,15 +189,19 @@ public class ServerHTTPSPDYAsyncConnection extends AbstractHttpConnection implem
for (Headers.Header header : headers)
{
String name = header.name();
- switch (name)
+
+ // Skip special SPDY headers, unless it's the "host" header
+ HTTPSPDYHeader specialHeader = HTTPSPDYHeader.from(version, name);
+ if (specialHeader != null)
{
- case "method":
- case "version":
- case "url":
- {
- // Skip request line headers
+ if (specialHeader == HTTPSPDYHeader.HOST)
+ name = "host";
+ else
continue;
- }
+ }
+
+ switch (name)
+ {
case "connection":
case "keep-alive":
case "proxy-connection":
@@ -264,8 +276,8 @@ public class ServerHTTPSPDYAsyncConnection extends AbstractHttpConnection implem
else
{
Headers headers = new Headers();
- headers.put("status", String.valueOf(status));
- headers.put("version", "HTTP/1.1");
+ headers.put(HTTPSPDYHeader.STATUS.name(version), String.valueOf(status));
+ headers.put(HTTPSPDYHeader.VERSION.name(version), "HTTP/1.1");
stream.reply(new ReplyInfo(headers, true));
}
}
@@ -393,46 +405,67 @@ public class ServerHTTPSPDYAsyncConnection extends AbstractHttpConnection implem
{
if (!stream.isUnidirectional())
stream.reply(replyInfo);
- if (replyInfo.getHeaders().get("status").value().startsWith("200") && !stream.isClosed() && !isIfModifiedSinceHeaderPresent())
+ if (replyInfo.getHeaders().get(HTTPSPDYHeader.STATUS.name(version)).value().startsWith("200") &&
+ !stream.isClosed())
{
// We have a 200 OK with some content to send
- Headers.Header scheme = headers.get("scheme");
- Headers.Header host = headers.get("host");
- Headers.Header url = headers.get("url");
- Set<String> pushResources = pushStrategy.apply(stream, this.headers, replyInfo.getHeaders());
- String referrer = new StringBuilder(scheme.value()).append("://").append(host.value()).append(url.value()).toString();
- for (String pushURL : pushResources)
+ Headers.Header scheme = headers.get(HTTPSPDYHeader.SCHEME.name(version));
+ Headers.Header host = headers.get(HTTPSPDYHeader.HOST.name(version));
+ Headers.Header uri = headers.get(HTTPSPDYHeader.URI.name(version));
+ Set<String> pushResources = pushStrategy.apply(stream, headers, replyInfo.getHeaders());
+
+ for (String pushResourcePath : pushResources)
{
- final Headers pushHeaders = new Headers();
- pushHeaders.put("method", "GET");
- pushHeaders.put("url", pushURL);
- pushHeaders.put("version", "HTTP/1.1");
- pushHeaders.put(scheme);
- pushHeaders.put(host);
- pushHeaders.put("referer", referrer);
- // Remember support for gzip encoding
- pushHeaders.put(headers.get("accept-encoding"));
+ final Headers requestHeaders = createRequestHeaders(scheme, host, uri, pushResourcePath);
+ final Headers pushHeaders = createPushHeaders(scheme, host, pushResourcePath);
+
stream.syn(new SynInfo(pushHeaders, false), getMaxIdleTime(), TimeUnit.MILLISECONDS, new Handler.Adapter<Stream>()
{
@Override
public void completed(Stream pushStream)
{
- Synchronous pushConnection = new Synchronous(getConnector(), getEndPoint(), getServer(), connection, pushStrategy, pushStream);
- pushConnection.beginRequest(pushHeaders, true);
+ ServerHTTPSPDYAsyncConnection pushConnection =
+ new ServerHTTPSPDYAsyncConnection(getConnector(), getEndPoint(), getServer(), version, connection, pushStrategy, pushStream);
+ pushConnection.beginRequest(requestHeaders, true);
}
});
}
}
}
- private boolean isIfModifiedSinceHeaderPresent()
- {
- if (headers.get("if-modified-since") != null)
- return true;
- return false;
- }
-
+ private Headers createRequestHeaders(Headers.Header scheme, Headers.Header host, Headers.Header uri, String pushResourcePath)
+ {
+ final Headers requestHeaders = new Headers();
+ requestHeaders.put(HTTPSPDYHeader.METHOD.name(version), "GET");
+ requestHeaders.put(HTTPSPDYHeader.VERSION.name(version), "HTTP/1.1");
+ requestHeaders.put(scheme);
+ requestHeaders.put(host);
+ requestHeaders.put(HTTPSPDYHeader.URI.name(version), pushResourcePath);
+ String referrer = scheme.value() + "://" + host.value() + uri.value();
+ requestHeaders.put("referer", referrer);
+ // Remember support for gzip encoding
+ requestHeaders.put(headers.get("accept-encoding"));
+ requestHeaders.put("x-spdy-push", "true");
+ return requestHeaders;
+ }
+
+ private Headers createPushHeaders(Headers.Header scheme, Headers.Header host, String pushResourcePath)
+ {
+ final Headers pushHeaders = new Headers();
+ if (version == SPDY.V2)
+ pushHeaders.put(HTTPSPDYHeader.URI.name(version), scheme.value() + "://" + host.value() + pushResourcePath);
+ else
+ {
+ pushHeaders.put(HTTPSPDYHeader.URI.name(version), pushResourcePath);
+ pushHeaders.put(scheme);
+ pushHeaders.put(host);
+ }
+ pushHeaders.put(HTTPSPDYHeader.STATUS.name(version), "200");
+ pushHeaders.put(HTTPSPDYHeader.VERSION.name(version), "HTTP/1.1");
+ return pushHeaders;
+ }
+
private Buffer consumeContent(long maxIdleTime) throws IOException, InterruptedException
{
while (true)
@@ -614,11 +647,11 @@ public class ServerHTTPSPDYAsyncConnection extends AbstractHttpConnection implem
{
Headers headers = new Headers();
String version = "HTTP/1.1";
- headers.put("version", version);
+ headers.put(HTTPSPDYHeader.VERSION.name(ServerHTTPSPDYAsyncConnection.this.version), version);
StringBuilder status = new StringBuilder().append(_status);
if (_reason != null)
status.append(" ").append(_reason.toString("UTF-8"));
- headers.put("status", status.toString());
+ headers.put(HTTPSPDYHeader.STATUS.name(ServerHTTPSPDYAsyncConnection.this.version), status.toString());
logger.debug("HTTP < {} {}", version, status);
if (fields != null)
@@ -634,19 +667,14 @@ public class ServerHTTPSPDYAsyncConnection extends AbstractHttpConnection implem
}
// We have to query the HttpGenerator and its buffers to know
- // whether there is content buffered; if so, send the data frame
+ // whether there is content buffered and update the generator state
Buffer content = getContentBuffer();
reply(stream, new ReplyInfo(headers, content == null));
if (content != null)
{
- closed = allContentAdded || isAllContentWritten();
- ByteBuffer buffer = ByteBuffer.wrap(content.asArray());
- logger.debug("HTTP < {} bytes of content", buffer.remaining());
- // Send the data frame
- stream.data(new ByteBufferDataInfo(buffer, closed));
+ closed = false;
// Update HttpGenerator fields so that they remain consistent
- content.clear();
- _state = closed ? HttpGenerator.STATE_END : HttpGenerator.STATE_CONTENT;
+ _state = HttpGenerator.STATE_CONTENT;
}
else
{
@@ -660,7 +688,7 @@ public class ServerHTTPSPDYAsyncConnection extends AbstractHttpConnection implem
{
if (_buffer != null && _buffer.length() > 0)
return _buffer;
- if (_bypass && _content != null && _content.length() > 0)
+ if (_content != null && _content.length() > 0)
return _content;
return null;
}
@@ -685,22 +713,48 @@ public class ServerHTTPSPDYAsyncConnection extends AbstractHttpConnection implem
@Override
public void flush(long maxIdleTime) throws IOException
{
- while (_content != null && _content.length() > 0)
+ try
{
- _content.skip(_buffer.put(_content));
- ByteBuffer buffer = ByteBuffer.wrap(_buffer.asArray());
- logger.debug("HTTP < {} bytes of content", buffer.remaining());
- _buffer.clear();
- closed = _content.length() == 0 && _last;
- stream.data(new ByteBufferDataInfo(buffer, closed));
-
- boolean expired = !connection.getEndPoint().blockWritable(maxIdleTime);
- if (expired)
+ Buffer content = getContentBuffer();
+ while (content != null)
{
- stream.getSession().goAway();
- throw new EOFException("write timeout");
+ DataInfo dataInfo = toDataInfo(content, closed);
+ logger.debug("HTTP < {} bytes of content", dataInfo.length());
+ stream.data(dataInfo).get(maxIdleTime, TimeUnit.MILLISECONDS);
+ content.clear();
+ _bypass = false;
+ content = getContentBuffer();
}
}
+ catch (TimeoutException x)
+ {
+ stream.getSession().goAway();
+ throw new EOFException("write timeout");
+ }
+ catch (InterruptedException x)
+ {
+ throw new InterruptedIOException();
+ }
+ catch (ExecutionException x)
+ {
+ throw new IOException(x.getCause());
+ }
+ }
+
+ private DataInfo toDataInfo(Buffer buffer, boolean close)
+ {
+ if (buffer instanceof ByteArrayBuffer)
+ return new BytesDataInfo(buffer.array(), buffer.getIndex(), buffer.length(), close);
+
+ if (buffer instanceof NIOBuffer)
+ {
+ ByteBuffer byteBuffer = ((NIOBuffer)buffer).getByteBuffer();
+ byteBuffer.limit(buffer.putIndex());
+ byteBuffer.position(buffer.getIndex());
+ return new ByteBufferDataInfo(byteBuffer, close);
+ }
+
+ return new BytesDataInfo(buffer.asArray(), close);
}
@Override
@@ -727,35 +781,17 @@ public class ServerHTTPSPDYAsyncConnection extends AbstractHttpConnection implem
Buffer content = getContentBuffer();
if (content != null)
{
- ByteBuffer buffer = ByteBuffer.wrap(content.asArray());
- logger.debug("HTTP < {} bytes of content", buffer.remaining());
- // Update HttpGenerator fields so that they remain consistent
- content.clear();
+ closed = true;
_state = STATE_END;
- // Send the data frame
- stream.data(new ByteBufferDataInfo(buffer, true));
+ flush(getMaxIdleTime());
}
else if (!closed)
{
closed = true;
_state = STATE_END;
- // Send the data frame
+ // Send the last, empty, data frame
stream.data(new ByteBufferDataInfo(ZERO_BYTES, true));
}
}
}
-
- private static class Synchronous extends ServerHTTPSPDYAsyncConnection
- {
- private Synchronous(Connector connector, AsyncEndPoint endPoint, Server server, SPDYAsyncConnection connection, PushStrategy pushStrategy, Stream stream)
- {
- super(connector, endPoint, server, connection, pushStrategy, stream);
- }
-
- @Override
- protected void execute(Runnable task)
- {
- task.run();
- }
- }
}
diff --git a/jetty-spdy/spdy-jetty-http/src/main/java/org/eclipse/jetty/spdy/http/ServerHTTPSPDYAsyncConnectionFactory.java b/jetty-spdy/spdy-jetty-http/src/main/java/org/eclipse/jetty/spdy/http/ServerHTTPSPDYAsyncConnectionFactory.java
index 16db295eeb..7a5f381b3c 100644
--- a/jetty-spdy/spdy-jetty-http/src/main/java/org/eclipse/jetty/spdy/http/ServerHTTPSPDYAsyncConnectionFactory.java
+++ b/jetty-spdy/spdy-jetty-http/src/main/java/org/eclipse/jetty/spdy/http/ServerHTTPSPDYAsyncConnectionFactory.java
@@ -1,18 +1,16 @@
-/*
- * Copyright (c) 2012 the original author or authors.
- *
- * 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.
- */
+//========================================================================
+//Copyright 2011-2012 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.spdy.http;
@@ -52,7 +50,7 @@ public class ServerHTTPSPDYAsyncConnectionFactory extends ServerSPDYAsyncConnect
}
@Override
- protected ServerSessionFrameListener newServerSessionFrameListener(AsyncEndPoint endPoint, Object attachment)
+ protected ServerSessionFrameListener provideServerSessionFrameListener(AsyncEndPoint endPoint, Object attachment)
{
return new HTTPServerFrameListener(endPoint);
}
@@ -78,8 +76,8 @@ public class ServerHTTPSPDYAsyncConnectionFactory extends ServerSPDYAsyncConnect
logger.debug("Received {} on {}", synInfo, stream);
HTTPSPDYAsyncEndPoint asyncEndPoint = new HTTPSPDYAsyncEndPoint(endPoint, stream);
- ServerHTTPSPDYAsyncConnection connection = new ServerHTTPSPDYAsyncConnection(connector,
- asyncEndPoint, connector.getServer(), (SPDYAsyncConnection)endPoint.getConnection(),
+ ServerHTTPSPDYAsyncConnection connection = new ServerHTTPSPDYAsyncConnection(connector, asyncEndPoint,
+ connector.getServer(), getVersion(), (SPDYAsyncConnection)endPoint.getConnection(),
pushStrategy, stream);
asyncEndPoint.setConnection(connection);
stream.setAttribute(CONNECTION_ATTRIBUTE, connection);
diff --git a/jetty-spdy/spdy-jetty-http/src/main/java/org/eclipse/jetty/spdy/proxy/HTTPSPDYProxyConnector.java b/jetty-spdy/spdy-jetty-http/src/main/java/org/eclipse/jetty/spdy/proxy/HTTPSPDYProxyConnector.java
new file mode 100644
index 0000000000..2827af05ce
--- /dev/null
+++ b/jetty-spdy/spdy-jetty-http/src/main/java/org/eclipse/jetty/spdy/proxy/HTTPSPDYProxyConnector.java
@@ -0,0 +1,39 @@
+//========================================================================
+//Copyright 2011-2012 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.spdy.proxy;
+
+import org.eclipse.jetty.spdy.ServerSPDYAsyncConnectionFactory;
+import org.eclipse.jetty.spdy.api.SPDY;
+import org.eclipse.jetty.spdy.http.AbstractHTTPSPDYServerConnector;
+import org.eclipse.jetty.util.ssl.SslContextFactory;
+
+public class HTTPSPDYProxyConnector extends AbstractHTTPSPDYServerConnector
+{
+ public HTTPSPDYProxyConnector(ProxyEngineSelector proxyEngineSelector)
+ {
+ this(proxyEngineSelector, null);
+ }
+
+ public HTTPSPDYProxyConnector(ProxyEngineSelector proxyEngineSelector, SslContextFactory sslContextFactory)
+ {
+ super(proxyEngineSelector, sslContextFactory);
+ clearAsyncConnectionFactories();
+
+ putAsyncConnectionFactory("spdy/3", new ServerSPDYAsyncConnectionFactory(SPDY.V3, getByteBufferPool(), getExecutor(), getScheduler(), proxyEngineSelector));
+ putAsyncConnectionFactory("spdy/2", new ServerSPDYAsyncConnectionFactory(SPDY.V2, getByteBufferPool(), getExecutor(), getScheduler(), proxyEngineSelector));
+ putAsyncConnectionFactory("http/1.1", new ProxyHTTPAsyncConnectionFactory(this, SPDY.V2, proxyEngineSelector));
+ setDefaultAsyncConnectionFactory(getAsyncConnectionFactory("http/1.1"));
+ }
+}
diff --git a/jetty-spdy/spdy-jetty-http/src/main/java/org/eclipse/jetty/spdy/proxy/ProxyEngine.java b/jetty-spdy/spdy-jetty-http/src/main/java/org/eclipse/jetty/spdy/proxy/ProxyEngine.java
new file mode 100644
index 0000000000..0a172614a5
--- /dev/null
+++ b/jetty-spdy/spdy-jetty-http/src/main/java/org/eclipse/jetty/spdy/proxy/ProxyEngine.java
@@ -0,0 +1,94 @@
+//========================================================================
+//Copyright 2011-2012 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.spdy.proxy;
+
+import java.net.InetAddress;
+import java.net.UnknownHostException;
+
+import org.eclipse.jetty.spdy.api.Headers;
+import org.eclipse.jetty.spdy.api.Stream;
+import org.eclipse.jetty.spdy.api.StreamFrameListener;
+import org.eclipse.jetty.spdy.api.SynInfo;
+import org.eclipse.jetty.util.log.Log;
+import org.eclipse.jetty.util.log.Logger;
+
+/**
+ * <p>{@link ProxyEngine} is the class for SPDY proxy functionalities that receives a SPDY request and converts it to
+ * any protocol to its server side.</p>
+ * <p>This class listens for SPDY events sent by clients; subclasses are responsible for translating
+ * these SPDY client events into appropriate events to forward to the server, in the appropriate
+ * protocol that is understood by the server.</p>
+ */
+public abstract class ProxyEngine
+{
+ protected final Logger logger = Log.getLogger(getClass());
+ private final String name;
+
+ protected ProxyEngine()
+ {
+ this(name());
+ }
+
+ private static String name()
+ {
+ try
+ {
+ return InetAddress.getLocalHost().getHostName();
+ }
+ catch (UnknownHostException x)
+ {
+ return "localhost";
+ }
+ }
+
+ public abstract StreamFrameListener proxy(Stream clientStream, SynInfo clientSynInfo, ProxyEngineSelector.ProxyServerInfo proxyServerInfo);
+
+ protected ProxyEngine(String name)
+ {
+ this.name = name;
+ }
+
+ public String getName()
+ {
+ return name;
+ }
+
+ protected void addRequestProxyHeaders(Stream stream, Headers headers)
+ {
+ addViaHeader(headers);
+ String address = (String)stream.getSession().getAttribute("org.eclipse.jetty.spdy.remoteAddress");
+ if (address != null)
+ headers.add("X-Forwarded-For", address);
+ }
+
+ protected void addResponseProxyHeaders(Stream stream, Headers headers)
+ {
+ addViaHeader(headers);
+ }
+
+ private void addViaHeader(Headers headers)
+ {
+ headers.add("Via", "http/1.1 " + getName());
+ }
+
+ protected void customizeRequestHeaders(Stream stream, Headers headers)
+ {
+ }
+
+ protected void customizeResponseHeaders(Stream stream, Headers headers)
+ {
+ }
+
+}
diff --git a/jetty-spdy/spdy-jetty-http/src/main/java/org/eclipse/jetty/spdy/proxy/ProxyEngineSelector.java b/jetty-spdy/spdy-jetty-http/src/main/java/org/eclipse/jetty/spdy/proxy/ProxyEngineSelector.java
new file mode 100644
index 0000000000..ee23df4dbc
--- /dev/null
+++ b/jetty-spdy/spdy-jetty-http/src/main/java/org/eclipse/jetty/spdy/proxy/ProxyEngineSelector.java
@@ -0,0 +1,166 @@
+package org.eclipse.jetty.spdy.proxy;
+
+import java.net.InetSocketAddress;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.concurrent.ConcurrentHashMap;
+
+import org.eclipse.jetty.spdy.api.GoAwayInfo;
+import org.eclipse.jetty.spdy.api.Headers;
+import org.eclipse.jetty.spdy.api.PingInfo;
+import org.eclipse.jetty.spdy.api.RstInfo;
+import org.eclipse.jetty.spdy.api.Session;
+import org.eclipse.jetty.spdy.api.Stream;
+import org.eclipse.jetty.spdy.api.StreamFrameListener;
+import org.eclipse.jetty.spdy.api.StreamStatus;
+import org.eclipse.jetty.spdy.api.SynInfo;
+import org.eclipse.jetty.spdy.api.server.ServerSessionFrameListener;
+import org.eclipse.jetty.spdy.http.HTTPSPDYHeader;
+import org.eclipse.jetty.util.log.Log;
+import org.eclipse.jetty.util.log.Logger;
+
+/**
+ * <p>{@link ProxyEngineSelector} is the main entry point for syn stream events of a jetty SPDY proxy. It receives the
+ * syn stream frames from the clients, checks if there's an appropriate {@link ProxyServerInfo} for the given target
+ * host and forwards the syn to a {@link ProxyEngine} for the protocol defined in {@link ProxyServerInfo}.</p>
+ *
+ * <p>If no {@link ProxyServerInfo} can be found for the given target host or no {@link ProxyEngine} can be found for
+ * the given protocol, it resets the client stream.</p>
+ *
+ * <p>This class also provides configuration for the proxy rules.</p>
+ */
+public class ProxyEngineSelector extends ServerSessionFrameListener.Adapter
+{
+ protected final Logger logger = Log.getLogger(getClass());
+ private final Map<String, ProxyServerInfo> proxyInfos = new ConcurrentHashMap<>();
+ private final Map<String, ProxyEngine> proxyEngines = new ConcurrentHashMap<>();
+
+ @Override
+ public final StreamFrameListener onSyn(final Stream clientStream, SynInfo clientSynInfo)
+ {
+ logger.debug("C -> P {} on {}", clientSynInfo, clientStream);
+
+ final Session clientSession = clientStream.getSession();
+ short clientVersion = clientSession.getVersion();
+ Headers headers = new Headers(clientSynInfo.getHeaders(), false);
+
+ Headers.Header hostHeader = headers.get(HTTPSPDYHeader.HOST.name(clientVersion));
+ if (hostHeader == null)
+ {
+ rst(clientStream);
+ return null;
+ }
+
+ String host = hostHeader.value();
+ int colon = host.indexOf(':');
+ if (colon >= 0)
+ host = host.substring(0, colon);
+
+ ProxyServerInfo proxyServerInfo = getProxyServerInfo(host);
+ if (proxyServerInfo == null)
+ {
+ rst(clientStream);
+ return null;
+ }
+
+ String protocol = proxyServerInfo.getProtocol();
+ ProxyEngine proxyEngine = proxyEngines.get(protocol);
+ if (proxyEngine == null)
+ {
+ rst(clientStream);
+ return null;
+ }
+
+ return proxyEngine.proxy(clientStream, clientSynInfo, proxyServerInfo);
+ }
+
+ @Override
+ public void onPing(Session clientSession, PingInfo pingInfo)
+ {
+ // We do not know to which upstream server
+ // to send the PING so we just ignore it
+ }
+
+ @Override
+ public void onGoAway(Session session, GoAwayInfo goAwayInfo)
+ {
+ // TODO:
+ }
+
+ public Map<String, ProxyEngine> getProxyEngines()
+ {
+ return new HashMap<>(proxyEngines);
+ }
+
+ public void setProxyEngines(Map<String, ProxyEngine> proxyEngines)
+ {
+ this.proxyEngines.clear();
+ this.proxyEngines.putAll(proxyEngines);
+ }
+
+ public ProxyEngine getProxyEngine(String protocol)
+ {
+ return proxyEngines.get(protocol);
+ }
+
+ public void putProxyEngine(String protocol, ProxyEngine proxyEngine)
+ {
+ proxyEngines.put(protocol, proxyEngine);
+ }
+
+ public Map<String, ProxyServerInfo> getProxyServerInfos()
+ {
+ return new HashMap<>(proxyInfos);
+ }
+
+ protected ProxyServerInfo getProxyServerInfo(String host)
+ {
+ return proxyInfos.get(host);
+ }
+
+ public void setProxyServerInfos(Map<String, ProxyServerInfo> proxyServerInfos)
+ {
+ this.proxyInfos.clear();
+ this.proxyInfos.putAll(proxyServerInfos);
+ }
+
+ public void putProxyServerInfo(String host, ProxyServerInfo proxyServerInfo)
+ {
+ proxyInfos.put(host, proxyServerInfo);
+ }
+
+ private void rst(Stream stream)
+ {
+ RstInfo rstInfo = new RstInfo(stream.getId(), StreamStatus.REFUSED_STREAM);
+ stream.getSession().rst(rstInfo);
+ }
+
+ public static class ProxyServerInfo
+ {
+ private final String protocol;
+ private final String host;
+ private final InetSocketAddress address;
+
+ public ProxyServerInfo(String protocol, String host, int port)
+ {
+ this.protocol = protocol;
+ this.host = host;
+ this.address = new InetSocketAddress(host, port);
+ }
+
+ public String getProtocol()
+ {
+ return protocol;
+ }
+
+ public String getHost()
+ {
+ return host;
+ }
+
+ public InetSocketAddress getAddress()
+ {
+ return address;
+ }
+ }
+}
diff --git a/jetty-spdy/spdy-jetty-http/src/main/java/org/eclipse/jetty/spdy/proxy/ProxyHTTPAsyncConnectionFactory.java b/jetty-spdy/spdy-jetty-http/src/main/java/org/eclipse/jetty/spdy/proxy/ProxyHTTPAsyncConnectionFactory.java
new file mode 100644
index 0000000000..f73c7e819b
--- /dev/null
+++ b/jetty-spdy/spdy-jetty-http/src/main/java/org/eclipse/jetty/spdy/proxy/ProxyHTTPAsyncConnectionFactory.java
@@ -0,0 +1,41 @@
+//========================================================================
+//Copyright 2011-2012 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.spdy.proxy;
+
+import java.nio.channels.SocketChannel;
+
+import org.eclipse.jetty.io.AsyncEndPoint;
+import org.eclipse.jetty.io.nio.AsyncConnection;
+import org.eclipse.jetty.spdy.SPDYServerConnector;
+import org.eclipse.jetty.spdy.http.ServerHTTPAsyncConnectionFactory;
+
+public class ProxyHTTPAsyncConnectionFactory extends ServerHTTPAsyncConnectionFactory
+{
+ private final short version;
+ private final ProxyEngineSelector proxyEngineSelector;
+
+ public ProxyHTTPAsyncConnectionFactory(SPDYServerConnector connector, short version, ProxyEngineSelector proxyEngineSelector)
+ {
+ super(connector);
+ this.version = version;
+ this.proxyEngineSelector = proxyEngineSelector;
+ }
+
+ @Override
+ public AsyncConnection newAsyncConnection(SocketChannel channel, AsyncEndPoint endPoint, Object attachment)
+ {
+ return new ProxyHTTPSPDYAsyncConnection(getConnector(), endPoint, version, proxyEngineSelector);
+ }
+}
diff --git a/jetty-spdy/spdy-jetty-http/src/main/java/org/eclipse/jetty/spdy/proxy/ProxyHTTPSPDYAsyncConnection.java b/jetty-spdy/spdy-jetty-http/src/main/java/org/eclipse/jetty/spdy/proxy/ProxyHTTPSPDYAsyncConnection.java
new file mode 100644
index 0000000000..92c318479a
--- /dev/null
+++ b/jetty-spdy/spdy-jetty-http/src/main/java/org/eclipse/jetty/spdy/proxy/ProxyHTTPSPDYAsyncConnection.java
@@ -0,0 +1,337 @@
+//========================================================================
+//Copyright 2011-2012 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.spdy.proxy;
+
+import java.io.IOException;
+import java.nio.ByteBuffer;
+import java.util.concurrent.TimeUnit;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+import org.eclipse.jetty.http.HttpFields;
+import org.eclipse.jetty.http.HttpGenerator;
+import org.eclipse.jetty.io.AsyncEndPoint;
+import org.eclipse.jetty.io.Buffer;
+import org.eclipse.jetty.io.ByteArrayBuffer;
+import org.eclipse.jetty.io.EndPoint;
+import org.eclipse.jetty.io.nio.DirectNIOBuffer;
+import org.eclipse.jetty.io.nio.IndirectNIOBuffer;
+import org.eclipse.jetty.io.nio.NIOBuffer;
+import org.eclipse.jetty.server.AsyncHttpConnection;
+import org.eclipse.jetty.spdy.ISession;
+import org.eclipse.jetty.spdy.IStream;
+import org.eclipse.jetty.spdy.SPDYServerConnector;
+import org.eclipse.jetty.spdy.StandardSession;
+import org.eclipse.jetty.spdy.StandardStream;
+import org.eclipse.jetty.spdy.api.ByteBufferDataInfo;
+import org.eclipse.jetty.spdy.api.BytesDataInfo;
+import org.eclipse.jetty.spdy.api.DataInfo;
+import org.eclipse.jetty.spdy.api.GoAwayInfo;
+import org.eclipse.jetty.spdy.api.Handler;
+import org.eclipse.jetty.spdy.api.Headers;
+import org.eclipse.jetty.spdy.api.HeadersInfo;
+import org.eclipse.jetty.spdy.api.ReplyInfo;
+import org.eclipse.jetty.spdy.api.RstInfo;
+import org.eclipse.jetty.spdy.api.SessionStatus;
+import org.eclipse.jetty.spdy.api.Stream;
+import org.eclipse.jetty.spdy.api.StreamFrameListener;
+import org.eclipse.jetty.spdy.api.SynInfo;
+import org.eclipse.jetty.spdy.http.HTTPSPDYHeader;
+
+public class ProxyHTTPSPDYAsyncConnection extends AsyncHttpConnection
+{
+ private final Headers headers = new Headers();
+ private final short version;
+ private final ProxyEngineSelector proxyEngineSelector;
+ private final HttpGenerator generator;
+ private final ISession session;
+ private HTTPStream stream;
+ private Buffer content;
+
+ public ProxyHTTPSPDYAsyncConnection(SPDYServerConnector connector, EndPoint endPoint, short version, ProxyEngineSelector proxyEngineSelector)
+ {
+ super(connector, endPoint, connector.getServer());
+ this.version = version;
+ this.proxyEngineSelector = proxyEngineSelector;
+ this.generator = (HttpGenerator)_generator;
+ this.session = new HTTPSession(version, connector);
+ this.session.setAttribute("org.eclipse.jetty.spdy.remoteAddress", endPoint.getRemoteAddr());
+ }
+
+ @Override
+ public AsyncEndPoint getEndPoint()
+ {
+ return (AsyncEndPoint)super.getEndPoint();
+ }
+
+ @Override
+ protected void startRequest(Buffer method, Buffer uri, Buffer httpVersion) throws IOException
+ {
+ SPDYServerConnector connector = (SPDYServerConnector)getConnector();
+ String scheme = connector.getSslContextFactory() != null ? "https" : "http";
+ headers.put(HTTPSPDYHeader.SCHEME.name(version), scheme);
+ headers.put(HTTPSPDYHeader.METHOD.name(version), method.toString("UTF-8"));
+ headers.put(HTTPSPDYHeader.URI.name(version), uri.toString("UTF-8"));
+ headers.put(HTTPSPDYHeader.VERSION.name(version), httpVersion.toString("UTF-8"));
+ }
+
+ @Override
+ protected void parsedHeader(Buffer name, Buffer value) throws IOException
+ {
+ String headerName = name.toString("UTF-8").toLowerCase();
+ String headerValue = value.toString("UTF-8");
+ switch (headerName)
+ {
+ case "host":
+ headers.put(HTTPSPDYHeader.HOST.name(version), headerValue);
+ break;
+ default:
+ headers.put(headerName, headerValue);
+ break;
+ }
+ }
+
+ @Override
+ protected void headerComplete() throws IOException
+ {
+ }
+
+ @Override
+ protected void content(Buffer buffer) throws IOException
+ {
+ if (content == null)
+ {
+ stream = syn(false);
+ content = buffer;
+ }
+ else
+ {
+ stream.getStreamFrameListener().onData(stream, toDataInfo(buffer, false));
+ }
+ }
+
+ @Override
+ public void messageComplete(long contentLength) throws IOException
+ {
+ if (stream == null)
+ {
+ assert content == null;
+ if (headers.isEmpty())
+ proxyEngineSelector.onGoAway(session, new GoAwayInfo(0, SessionStatus.OK));
+ else
+ syn(true);
+ }
+ else
+ {
+ stream.getStreamFrameListener().onData(stream, toDataInfo(content, true));
+ }
+ headers.clear();
+ stream = null;
+ content = null;
+ }
+
+ private HTTPStream syn(boolean close)
+ {
+ HTTPStream stream = new HTTPStream(1, (byte)0, session, null);
+ StreamFrameListener streamFrameListener = proxyEngineSelector.onSyn(stream, new SynInfo(headers, close));
+ stream.setStreamFrameListener(streamFrameListener);
+ return stream;
+ }
+
+ private DataInfo toDataInfo(Buffer buffer, boolean close)
+ {
+ if (buffer instanceof ByteArrayBuffer)
+ return new BytesDataInfo(buffer.array(), buffer.getIndex(), buffer.length(), close);
+
+ if (buffer instanceof NIOBuffer)
+ {
+ ByteBuffer byteBuffer = ((NIOBuffer)buffer).getByteBuffer();
+ byteBuffer.limit(buffer.putIndex());
+ byteBuffer.position(buffer.getIndex());
+ return new ByteBufferDataInfo(byteBuffer, close);
+ }
+
+ return new BytesDataInfo(buffer.asArray(), close);
+ }
+
+ private class HTTPSession extends StandardSession
+ {
+ private HTTPSession(short version, SPDYServerConnector connector)
+ {
+ super(version, connector.getByteBufferPool(), connector.getExecutor(), connector.getScheduler(), null, null, 1, proxyEngineSelector, null, null);
+ }
+
+ @Override
+ public void rst(RstInfo rstInfo, long timeout, TimeUnit unit, Handler<Void> handler)
+ {
+ // Not much we can do in HTTP land: just close the connection
+ goAway(timeout, unit, handler);
+ }
+
+ @Override
+ public void goAway(long timeout, TimeUnit unit, Handler<Void> handler)
+ {
+ try
+ {
+ getEndPoint().close();
+ handler.completed(null);
+ }
+ catch (IOException x)
+ {
+ handler.failed(null, x);
+ }
+ }
+ }
+
+ /**
+ * <p>This stream will convert the SPDY invocations performed by the proxy into HTTP to be sent to the client.</p>
+ */
+ private class HTTPStream extends StandardStream
+ {
+ private final Pattern statusRegexp = Pattern.compile("(\\d{3})\\s*(.*)");
+
+ private HTTPStream(int id, byte priority, ISession session, IStream associatedStream)
+ {
+ super(id, priority, session, associatedStream);
+ }
+
+ @Override
+ public void syn(SynInfo synInfo, long timeout, TimeUnit unit, Handler<Stream> handler)
+ {
+ // HTTP does not support pushed streams
+ handler.completed(new HTTPPushStream(2, getPriority(), getSession(), this));
+ }
+
+ @Override
+ public void headers(HeadersInfo headersInfo, long timeout, TimeUnit unit, Handler<Void> handler)
+ {
+ // TODO
+ throw new UnsupportedOperationException("Not Yet Implemented");
+ }
+
+ @Override
+ public void reply(ReplyInfo replyInfo, long timeout, TimeUnit unit, Handler<Void> handler)
+ {
+ try
+ {
+ Headers headers = new Headers(replyInfo.getHeaders(), false);
+
+ headers.remove(HTTPSPDYHeader.SCHEME.name(version));
+
+ String status = headers.remove(HTTPSPDYHeader.STATUS.name(version)).value();
+ Matcher matcher = statusRegexp.matcher(status);
+ matcher.matches();
+ int code = Integer.parseInt(matcher.group(1));
+ String reason = matcher.group(2);
+ generator.setResponse(code, reason);
+
+ String httpVersion = headers.remove(HTTPSPDYHeader.VERSION.name(version)).value();
+ generator.setVersion(Integer.parseInt(httpVersion.replaceAll("\\D", "")));
+
+ Headers.Header host = headers.remove(HTTPSPDYHeader.HOST.name(version));
+ if (host != null)
+ headers.put("host", host.value());
+
+ HttpFields fields = new HttpFields();
+ for (Headers.Header header : headers)
+ {
+ String name = camelize(header.name());
+ fields.put(name, header.value());
+ }
+ generator.completeHeader(fields, replyInfo.isClose());
+
+ if (replyInfo.isClose())
+ complete();
+
+ handler.completed(null);
+ }
+ catch (IOException x)
+ {
+ handler.failed(null, x);
+ }
+ }
+
+ private String camelize(String name)
+ {
+ char[] chars = name.toCharArray();
+ chars[0] = Character.toUpperCase(chars[0]);
+
+ for (int i = 0; i < chars.length; ++i)
+ {
+ char c = chars[i];
+ int j = i + 1;
+ if (c == '-' && j < chars.length)
+ chars[j] = Character.toUpperCase(chars[j]);
+ }
+ return new String(chars);
+ }
+
+ @Override
+ public void data(DataInfo dataInfo, long timeout, TimeUnit unit, Handler<Void> handler)
+ {
+ try
+ {
+ // Data buffer must be copied, as the ByteBuffer is pooled
+ ByteBuffer byteBuffer = dataInfo.asByteBuffer(false);
+
+ Buffer buffer = byteBuffer.isDirect() ?
+ new DirectNIOBuffer(byteBuffer, false) :
+ new IndirectNIOBuffer(byteBuffer, false);
+
+ generator.addContent(buffer, dataInfo.isClose());
+ generator.flush(unit.toMillis(timeout));
+
+ if (dataInfo.isClose())
+ complete();
+
+ handler.completed(null);
+ }
+ catch (IOException x)
+ {
+ handler.failed(null, x);
+ }
+ }
+
+ private void complete() throws IOException
+ {
+ generator.complete();
+ // We need to call asyncDispatch() as if the HTTP request
+ // has been suspended and now we complete the response
+ getEndPoint().asyncDispatch();
+ }
+ }
+
+ private class HTTPPushStream extends StandardStream
+ {
+ private HTTPPushStream(int id, byte priority, ISession session, IStream associatedStream)
+ {
+ super(id, priority, session, associatedStream);
+ }
+
+ @Override
+ public void headers(HeadersInfo headersInfo, long timeout, TimeUnit unit, Handler<Void> handler)
+ {
+ // Ignore pushed headers
+ handler.completed(null);
+ }
+
+ @Override
+ public void data(DataInfo dataInfo, long timeout, TimeUnit unit, Handler<Void> handler)
+ {
+ // Ignore pushed data
+ handler.completed(null);
+ }
+ }
+}
diff --git a/jetty-spdy/spdy-jetty-http/src/main/java/org/eclipse/jetty/spdy/proxy/SPDYProxyEngine.java b/jetty-spdy/spdy-jetty-http/src/main/java/org/eclipse/jetty/spdy/proxy/SPDYProxyEngine.java
new file mode 100644
index 0000000000..c01af3ef0f
--- /dev/null
+++ b/jetty-spdy/spdy-jetty-http/src/main/java/org/eclipse/jetty/spdy/proxy/SPDYProxyEngine.java
@@ -0,0 +1,514 @@
+//========================================================================
+//Copyright 2011-2012 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.spdy.proxy;
+
+import java.net.InetSocketAddress;
+import java.util.LinkedList;
+import java.util.Queue;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.ConcurrentMap;
+import java.util.concurrent.TimeUnit;
+
+import org.eclipse.jetty.spdy.SPDYClient;
+import org.eclipse.jetty.spdy.api.ByteBufferDataInfo;
+import org.eclipse.jetty.spdy.api.DataInfo;
+import org.eclipse.jetty.spdy.api.GoAwayInfo;
+import org.eclipse.jetty.spdy.api.Handler;
+import org.eclipse.jetty.spdy.api.Headers;
+import org.eclipse.jetty.spdy.api.HeadersInfo;
+import org.eclipse.jetty.spdy.api.ReplyInfo;
+import org.eclipse.jetty.spdy.api.RstInfo;
+import org.eclipse.jetty.spdy.api.SPDY;
+import org.eclipse.jetty.spdy.api.Session;
+import org.eclipse.jetty.spdy.api.SessionFrameListener;
+import org.eclipse.jetty.spdy.api.Stream;
+import org.eclipse.jetty.spdy.api.StreamFrameListener;
+import org.eclipse.jetty.spdy.api.StreamStatus;
+import org.eclipse.jetty.spdy.api.SynInfo;
+import org.eclipse.jetty.spdy.http.HTTPSPDYHeader;
+
+/**
+ * <p>{@link SPDYProxyEngine} implements a SPDY to SPDY proxy, that is, converts SPDY events received by
+ * clients into SPDY events for the servers.</p>
+ */
+public class SPDYProxyEngine extends ProxyEngine implements StreamFrameListener
+{
+ private static final String STREAM_HANDLER_ATTRIBUTE = "org.eclipse.jetty.spdy.http.proxy.streamHandler";
+ private static final String CLIENT_STREAM_ATTRIBUTE = "org.eclipse.jetty.spdy.http.proxy.clientStream";
+
+ private final ConcurrentMap<String, Session> serverSessions = new ConcurrentHashMap<>();
+ private final SessionFrameListener sessionListener = new ProxySessionFrameListener();
+ private final SPDYClient.Factory factory;
+ private volatile long connectTimeout = 15000;
+ private volatile long timeout = 60000;
+
+ public SPDYProxyEngine(SPDYClient.Factory factory)
+ {
+ this.factory = factory;
+ }
+
+ public long getConnectTimeout()
+ {
+ return connectTimeout;
+ }
+
+ public void setConnectTimeout(long connectTimeout)
+ {
+ this.connectTimeout = connectTimeout;
+ }
+
+ public long getTimeout()
+ {
+ return timeout;
+ }
+
+ public void setTimeout(long timeout)
+ {
+ this.timeout = timeout;
+ }
+
+ public StreamFrameListener proxy(final Stream clientStream, SynInfo clientSynInfo, ProxyEngineSelector.ProxyServerInfo proxyServerInfo)
+ {
+ Headers headers = new Headers(clientSynInfo.getHeaders(), false);
+
+ short serverVersion = getVersion(proxyServerInfo.getProtocol());
+ InetSocketAddress address = proxyServerInfo.getAddress();
+ Session serverSession = produceSession(proxyServerInfo.getHost(), serverVersion, address);
+ if (serverSession == null)
+ {
+ rst(clientStream);
+ return null;
+ }
+
+ final Session clientSession = clientStream.getSession();
+
+ addRequestProxyHeaders(clientStream, headers);
+ customizeRequestHeaders(clientStream, headers);
+ convert(clientSession.getVersion(), serverVersion, headers);
+
+ SynInfo serverSynInfo = new SynInfo(headers, clientSynInfo.isClose());
+ StreamFrameListener listener = new ProxyStreamFrameListener(clientStream);
+ StreamHandler handler = new StreamHandler(clientStream, serverSynInfo);
+ clientStream.setAttribute(STREAM_HANDLER_ATTRIBUTE, handler);
+ serverSession.syn(serverSynInfo, listener, timeout, TimeUnit.MILLISECONDS, handler);
+ return this;
+ }
+
+ private static short getVersion(String protocol)
+ {
+ switch (protocol)
+ {
+ case "spdy/2":
+ return SPDY.V2;
+ case "spdy/3":
+ return SPDY.V3;
+ default:
+ throw new IllegalArgumentException("Procotol: " + protocol + " is not a known SPDY protocol");
+ }
+ }
+
+ @Override
+ public void onReply(Stream stream, ReplyInfo replyInfo)
+ {
+ // Servers do not receive replies
+ }
+
+ @Override
+ public void onHeaders(Stream stream, HeadersInfo headersInfo)
+ {
+ // TODO
+ throw new UnsupportedOperationException("Not Yet Implemented");
+ }
+
+ @Override
+ public void onData(Stream clientStream, final DataInfo clientDataInfo)
+ {
+ logger.debug("C -> P {} on {}", clientDataInfo, clientStream);
+
+ ByteBufferDataInfo serverDataInfo = new ByteBufferDataInfo(clientDataInfo.asByteBuffer(false), clientDataInfo.isClose())
+ {
+ @Override
+ public void consume(int delta)
+ {
+ super.consume(delta);
+ clientDataInfo.consume(delta);
+ }
+ };
+
+ StreamHandler streamHandler = (StreamHandler)clientStream.getAttribute(STREAM_HANDLER_ATTRIBUTE);
+ streamHandler.data(serverDataInfo);
+ }
+
+ private Session produceSession(String host, short version, InetSocketAddress address)
+ {
+ try
+ {
+ Session session = serverSessions.get(host);
+ if (session == null)
+ {
+ SPDYClient client = factory.newSPDYClient(version);
+ session = client.connect(address, sessionListener).get(getConnectTimeout(), TimeUnit.MILLISECONDS);
+ logger.debug("Proxy session connected to {}", address);
+ Session existing = serverSessions.putIfAbsent(host, session);
+ if (existing != null)
+ {
+ session.goAway(getTimeout(), TimeUnit.MILLISECONDS, new Handler.Adapter<Void>());
+ session = existing;
+ }
+ }
+ return session;
+ }
+ catch (Exception x)
+ {
+ logger.debug(x);
+ return null;
+ }
+ }
+
+ private void convert(short fromVersion, short toVersion, Headers headers)
+ {
+ if (fromVersion != toVersion)
+ {
+ for (HTTPSPDYHeader httpHeader : HTTPSPDYHeader.values())
+ {
+ Headers.Header header = headers.remove(httpHeader.name(fromVersion));
+ if (header != null)
+ {
+ String toName = httpHeader.name(toVersion);
+ for (String value : header.values())
+ headers.add(toName, value);
+ }
+ }
+ }
+ }
+
+ private void rst(Stream stream)
+ {
+ RstInfo rstInfo = new RstInfo(stream.getId(), StreamStatus.REFUSED_STREAM);
+ stream.getSession().rst(rstInfo, getTimeout(), TimeUnit.MILLISECONDS, new Handler.Adapter<Void>());
+ }
+
+ private class ProxyStreamFrameListener extends StreamFrameListener.Adapter
+ {
+ private final Stream clientStream;
+ private volatile ReplyInfo replyInfo;
+
+ public ProxyStreamFrameListener(Stream clientStream)
+ {
+ this.clientStream = clientStream;
+ }
+
+ @Override
+ public void onReply(final Stream stream, ReplyInfo replyInfo)
+ {
+ logger.debug("S -> P {} on {}", replyInfo, stream);
+
+ short serverVersion = stream.getSession().getVersion();
+ Headers headers = new Headers(replyInfo.getHeaders(), false);
+
+ addResponseProxyHeaders(stream, headers);
+ customizeResponseHeaders(stream, headers);
+ short clientVersion = this.clientStream.getSession().getVersion();
+ convert(serverVersion, clientVersion, headers);
+
+ this.replyInfo = new ReplyInfo(headers, replyInfo.isClose());
+ if (replyInfo.isClose())
+ reply(stream);
+ }
+
+ @Override
+ public void onHeaders(Stream stream, HeadersInfo headersInfo)
+ {
+ // TODO
+ throw new UnsupportedOperationException("Not Yet Implemented");
+ }
+
+ @Override
+ public void onData(final Stream stream, final DataInfo dataInfo)
+ {
+ logger.debug("S -> P {} on {}", dataInfo, stream);
+
+ if (replyInfo != null)
+ {
+ if (dataInfo.isClose())
+ replyInfo.getHeaders().put("content-length", String.valueOf(dataInfo.available()));
+ reply(stream);
+ }
+ data(stream, dataInfo);
+ }
+
+ private void reply(final Stream stream)
+ {
+ final ReplyInfo replyInfo = this.replyInfo;
+ this.replyInfo = null;
+ clientStream.reply(replyInfo, getTimeout(), TimeUnit.MILLISECONDS, new Handler<Void>()
+ {
+ @Override
+ public void completed(Void context)
+ {
+ logger.debug("P -> C {} from {} to {}", replyInfo, stream, clientStream);
+ }
+
+ @Override
+ public void failed(Void context, Throwable x)
+ {
+ logger.debug(x);
+ rst(clientStream);
+ }
+ });
+ }
+
+ private void data(final Stream stream, final DataInfo dataInfo)
+ {
+ clientStream.data(dataInfo, getTimeout(), TimeUnit.MILLISECONDS, new Handler<Void>()
+ {
+ @Override
+ public void completed(Void context)
+ {
+ dataInfo.consume(dataInfo.length());
+ logger.debug("P -> C {} from {} to {}", dataInfo, stream, clientStream);
+ }
+
+ @Override
+ public void failed(Void context, Throwable x)
+ {
+ logger.debug(x);
+ rst(clientStream);
+ }
+ });
+ }
+ }
+
+ /**
+ * <p>{@link StreamHandler} implements the forwarding of DATA frames from the client to the server.</p>
+ * <p>Instances of this class buffer DATA frames sent by clients and send them to the server.
+ * The buffering happens between the send of the SYN_STREAM to the server (where DATA frames may arrive
+ * from the client before the SYN_STREAM has been fully sent), and between DATA frames, if the client
+ * is a fast producer and the server a slow consumer, or if the client is a SPDY v2 client (and hence
+ * without flow control) while the server is a SPDY v3 server (and hence with flow control).</p>
+ */
+ private class StreamHandler implements Handler<Stream>
+ {
+ private final Queue<DataInfoHandler> queue = new LinkedList<>();
+ private final Stream clientStream;
+ private final SynInfo serverSynInfo;
+ private Stream serverStream;
+
+ private StreamHandler(Stream clientStream, SynInfo serverSynInfo)
+ {
+ this.clientStream = clientStream;
+ this.serverSynInfo = serverSynInfo;
+ }
+
+ @Override
+ public void completed(Stream serverStream)
+ {
+ logger.debug("P -> S {} from {} to {}", serverSynInfo, clientStream, serverStream);
+
+ serverStream.setAttribute(CLIENT_STREAM_ATTRIBUTE, clientStream);
+
+ DataInfoHandler dataInfoHandler;
+ synchronized (queue)
+ {
+ this.serverStream = serverStream;
+ dataInfoHandler = queue.peek();
+ if (dataInfoHandler != null)
+ {
+ if (dataInfoHandler.flushing)
+ {
+ logger.debug("SYN completed, flushing {}, queue size {}", dataInfoHandler.dataInfo, queue.size());
+ dataInfoHandler = null;
+ }
+ else
+ {
+ dataInfoHandler.flushing = true;
+ logger.debug("SYN completed, queue size {}", queue.size());
+ }
+ }
+ else
+ {
+ logger.debug("SYN completed, queue empty");
+ }
+ }
+ if (dataInfoHandler != null)
+ flush(serverStream, dataInfoHandler);
+ }
+
+ @Override
+ public void failed(Stream serverStream, Throwable x)
+ {
+ logger.debug(x);
+ rst(clientStream);
+ }
+
+ public void data(DataInfo dataInfo)
+ {
+ Stream serverStream;
+ DataInfoHandler dataInfoHandler = null;
+ DataInfoHandler item = new DataInfoHandler(dataInfo);
+ synchronized (queue)
+ {
+ queue.offer(item);
+ serverStream = this.serverStream;
+ if (serverStream != null)
+ {
+ dataInfoHandler = queue.peek();
+ if (dataInfoHandler.flushing)
+ {
+ logger.debug("Queued {}, flushing {}, queue size {}", dataInfo, dataInfoHandler.dataInfo, queue.size());
+ serverStream = null;
+ }
+ else
+ {
+ dataInfoHandler.flushing = true;
+ logger.debug("Queued {}, queue size {}", dataInfo, queue.size());
+ }
+ }
+ else
+ {
+ logger.debug("Queued {}, SYN incomplete, queue size {}", dataInfo, queue.size());
+ }
+ }
+ if (serverStream != null)
+ flush(serverStream, dataInfoHandler);
+ }
+
+ private void flush(Stream serverStream, DataInfoHandler dataInfoHandler)
+ {
+ logger.debug("P -> S {} on {}", dataInfoHandler.dataInfo, serverStream);
+ serverStream.data(dataInfoHandler.dataInfo, getTimeout(), TimeUnit.MILLISECONDS, dataInfoHandler);
+ }
+
+ private class DataInfoHandler implements Handler<Void>
+ {
+ private final DataInfo dataInfo;
+ private boolean flushing;
+
+ private DataInfoHandler(DataInfo dataInfo)
+ {
+ this.dataInfo = dataInfo;
+ }
+
+ @Override
+ public void completed(Void context)
+ {
+ Stream serverStream;
+ DataInfoHandler dataInfoHandler;
+ synchronized (queue)
+ {
+ serverStream = StreamHandler.this.serverStream;
+ assert serverStream != null;
+ dataInfoHandler = queue.poll();
+ assert dataInfoHandler == this;
+ dataInfoHandler = queue.peek();
+ if (dataInfoHandler != null)
+ {
+ assert !dataInfoHandler.flushing;
+ dataInfoHandler.flushing = true;
+ logger.debug("Completed {}, queue size {}", dataInfo, queue.size());
+ }
+ else
+ {
+ logger.debug("Completed {}, queue empty", dataInfo);
+ }
+ }
+ if (dataInfoHandler != null)
+ flush(serverStream, dataInfoHandler);
+ }
+
+ @Override
+ public void failed(Void context, Throwable x)
+ {
+ logger.debug(x);
+ rst(clientStream);
+ }
+ }
+ }
+
+ private class ProxySessionFrameListener extends SessionFrameListener.Adapter implements StreamFrameListener
+ {
+ @Override
+ public StreamFrameListener onSyn(Stream serverStream, SynInfo serverSynInfo)
+ {
+ logger.debug("S -> P pushed {} on {}", serverSynInfo, serverStream);
+
+ Headers headers = new Headers(serverSynInfo.getHeaders(), false);
+
+ addResponseProxyHeaders(serverStream, headers);
+ customizeResponseHeaders(serverStream, headers);
+ Stream clientStream = (Stream)serverStream.getAssociatedStream().getAttribute(CLIENT_STREAM_ATTRIBUTE);
+ convert(serverStream.getSession().getVersion(), clientStream.getSession().getVersion(), headers);
+
+ StreamHandler handler = new StreamHandler(clientStream, serverSynInfo);
+ serverStream.setAttribute(STREAM_HANDLER_ATTRIBUTE, handler);
+ clientStream.syn(new SynInfo(headers, serverSynInfo.isClose()), getTimeout(), TimeUnit.MILLISECONDS, handler);
+
+ return this;
+ }
+
+ @Override
+ public void onRst(Session serverSession, RstInfo serverRstInfo)
+ {
+ Stream serverStream = serverSession.getStream(serverRstInfo.getStreamId());
+ if (serverStream != null)
+ {
+ Stream clientStream = (Stream)serverStream.getAttribute(CLIENT_STREAM_ATTRIBUTE);
+ if (clientStream != null)
+ {
+ Session clientSession = clientStream.getSession();
+ RstInfo clientRstInfo = new RstInfo(clientStream.getId(), serverRstInfo.getStreamStatus());
+ clientSession.rst(clientRstInfo, getTimeout(), TimeUnit.MILLISECONDS, new Handler.Adapter<Void>());
+ }
+ }
+ }
+
+ @Override
+ public void onGoAway(Session serverSession, GoAwayInfo goAwayInfo)
+ {
+ serverSessions.values().remove(serverSession);
+ }
+
+ @Override
+ public void onReply(Stream stream, ReplyInfo replyInfo)
+ {
+ // Push streams never send a reply
+ }
+
+ @Override
+ public void onHeaders(Stream stream, HeadersInfo headersInfo)
+ {
+ throw new UnsupportedOperationException(); //TODO
+ }
+
+ @Override
+ public void onData(Stream serverStream, final DataInfo serverDataInfo)
+ {
+ logger.debug("S -> P pushed {} on {}", serverDataInfo, serverStream);
+
+ ByteBufferDataInfo clientDataInfo = new ByteBufferDataInfo(serverDataInfo.asByteBuffer(false), serverDataInfo.isClose())
+ {
+ @Override
+ public void consume(int delta)
+ {
+ super.consume(delta);
+ serverDataInfo.consume(delta);
+ }
+ };
+
+ StreamHandler handler = (StreamHandler)serverStream.getAttribute(STREAM_HANDLER_ATTRIBUTE);
+ handler.data(clientDataInfo);
+ }
+ }
+}
diff --git a/jetty-spdy/spdy-jetty-http/src/test/java/org/eclipse/jetty/spdy/http/AbstractHTTPSPDYTest.java b/jetty-spdy/spdy-jetty-http/src/test/java/org/eclipse/jetty/spdy/http/AbstractHTTPSPDYTest.java
index 84dd3271a5..a5c4c28043 100644
--- a/jetty-spdy/spdy-jetty-http/src/test/java/org/eclipse/jetty/spdy/http/AbstractHTTPSPDYTest.java
+++ b/jetty-spdy/spdy-jetty-http/src/test/java/org/eclipse/jetty/spdy/http/AbstractHTTPSPDYTest.java
@@ -1,18 +1,16 @@
-/*
- * Copyright (c) 2012 the original author or authors.
- *
- * 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.
- */
+//========================================================================
+//Copyright 2011-2012 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.spdy.http;
@@ -55,8 +53,13 @@ public abstract class AbstractHTTPSPDYTest
protected InetSocketAddress startHTTPServer(Handler handler) throws Exception
{
+ return startHTTPServer(SPDY.V2, handler);
+ }
+
+ protected InetSocketAddress startHTTPServer(short version, Handler handler) throws Exception
+ {
server = new Server();
- connector = newHTTPSPDYServerConnector();
+ connector = newHTTPSPDYServerConnector(version);
connector.setPort(0);
server.addConnector(connector);
server.setHandler(handler);
@@ -64,21 +67,22 @@ public abstract class AbstractHTTPSPDYTest
return new InetSocketAddress("localhost", connector.getLocalPort());
}
- protected SPDYServerConnector newHTTPSPDYServerConnector()
+ protected SPDYServerConnector newHTTPSPDYServerConnector(short version)
{
// For these tests, we need the connector to speak HTTP over SPDY even in non-SSL
- return new HTTPSPDYServerConnector()
- {
- @Override
- protected AsyncConnectionFactory getDefaultAsyncConnectionFactory()
- {
- return new ServerHTTPSPDYAsyncConnectionFactory(SPDY.V2, getByteBufferPool(), getExecutor(), getScheduler(), this, new PushStrategy.None());
- }
- };
+ SPDYServerConnector connector = new HTTPSPDYServerConnector();
+ AsyncConnectionFactory defaultFactory = new ServerHTTPSPDYAsyncConnectionFactory(version, connector.getByteBufferPool(), connector.getExecutor(), connector.getScheduler(), connector, new PushStrategy.None());
+ connector.setDefaultAsyncConnectionFactory(defaultFactory);
+ return connector;
}
protected Session startClient(InetSocketAddress socketAddress, SessionFrameListener listener) throws Exception
{
+ return startClient(SPDY.V2, socketAddress, listener);
+ }
+
+ protected Session startClient(short version, InetSocketAddress socketAddress, SessionFrameListener listener) throws Exception
+ {
if (clientFactory == null)
{
QueuedThreadPool threadPool = new QueuedThreadPool();
@@ -86,7 +90,7 @@ public abstract class AbstractHTTPSPDYTest
clientFactory = newSPDYClientFactory(threadPool);
clientFactory.start();
}
- return clientFactory.newSPDYClient(SPDY.V2).connect(socketAddress, listener).get(5, TimeUnit.SECONDS);
+ return clientFactory.newSPDYClient(version).connect(socketAddress, listener).get(5, TimeUnit.SECONDS);
}
protected SPDYClient.Factory newSPDYClientFactory(Executor threadPool)
@@ -107,4 +111,9 @@ public abstract class AbstractHTTPSPDYTest
server.join();
}
}
+
+ protected short version()
+ {
+ return SPDY.V2;
+ }
}
diff --git a/jetty-spdy/spdy-jetty-http/src/test/java/org/eclipse/jetty/spdy/http/ConcurrentStreamsTest.java b/jetty-spdy/spdy-jetty-http/src/test/java/org/eclipse/jetty/spdy/http/ConcurrentStreamsTest.java
index a26555004b..56cb5ef7c7 100644
--- a/jetty-spdy/spdy-jetty-http/src/test/java/org/eclipse/jetty/spdy/http/ConcurrentStreamsTest.java
+++ b/jetty-spdy/spdy-jetty-http/src/test/java/org/eclipse/jetty/spdy/http/ConcurrentStreamsTest.java
@@ -1,18 +1,16 @@
-/*
- * Copyright (c) 2012 the original author or authors.
- *
- * 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.
- */
+//========================================================================
+//Copyright 2011-2012 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.spdy.http;
@@ -73,10 +71,10 @@ public class ConcurrentStreamsTest extends AbstractHTTPSPDYTest
// Perform slow request. This will wait on server side until the fast request wakes it up
Headers headers = new Headers();
- headers.put("method", "GET");
- headers.put("url", "/slow");
- headers.put("version", "HTTP/1.1");
- headers.put("host", "localhost:" + connector.getLocalPort());
+ headers.put(HTTPSPDYHeader.METHOD.name(version()), "GET");
+ headers.put(HTTPSPDYHeader.URI.name(version()), "/slow");
+ headers.put(HTTPSPDYHeader.VERSION.name(version()), "HTTP/1.1");
+ headers.put(HTTPSPDYHeader.HOST.name(version()), "localhost:" + connector.getLocalPort());
final CountDownLatch slowClientLatch = new CountDownLatch(1);
session.syn(new SynInfo(headers, true), new StreamFrameListener.Adapter()
{
@@ -91,10 +89,10 @@ public class ConcurrentStreamsTest extends AbstractHTTPSPDYTest
// Perform the fast request. This will wake up the slow request
headers.clear();
- headers.put("method", "GET");
- headers.put("url", "/fast");
- headers.put("version", "HTTP/1.1");
- headers.put("host", "localhost:" + connector.getLocalPort());
+ headers.put(HTTPSPDYHeader.METHOD.name(version()), "GET");
+ headers.put(HTTPSPDYHeader.URI.name(version()), "/fast");
+ headers.put(HTTPSPDYHeader.VERSION.name(version()), "HTTP/1.1");
+ headers.put(HTTPSPDYHeader.HOST.name(version()), "localhost:" + connector.getLocalPort());
final CountDownLatch fastClientLatch = new CountDownLatch(1);
session.syn(new SynInfo(headers, true), new StreamFrameListener.Adapter()
{
diff --git a/jetty-spdy/spdy-jetty-http/src/test/java/org/eclipse/jetty/spdy/http/ProtocolNegotiationTest.java b/jetty-spdy/spdy-jetty-http/src/test/java/org/eclipse/jetty/spdy/http/ProtocolNegotiationTest.java
index e9cca9d33b..5de439b206 100644
--- a/jetty-spdy/spdy-jetty-http/src/test/java/org/eclipse/jetty/spdy/http/ProtocolNegotiationTest.java
+++ b/jetty-spdy/spdy-jetty-http/src/test/java/org/eclipse/jetty/spdy/http/ProtocolNegotiationTest.java
@@ -1,18 +1,16 @@
-/*
- * Copyright (c) 2012 the original author or authors.
- *
- * 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.
- */
+//========================================================================
+//Copyright 2011-2012 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.spdy.http;
@@ -27,7 +25,6 @@ import javax.net.ssl.SSLSocket;
import org.eclipse.jetty.npn.NextProtoNego;
import org.eclipse.jetty.server.Server;
-import org.eclipse.jetty.spdy.AsyncConnectionFactory;
import org.eclipse.jetty.spdy.SPDYServerConnector;
import org.eclipse.jetty.util.ssl.SslContextFactory;
import org.junit.Assert;
@@ -109,9 +106,8 @@ public class ProtocolNegotiationTest
public String selectProtocol(List<String> strings)
{
Assert.assertNotNull(strings);
- Assert.assertEquals(1, strings.size());
- String protocol = strings.get(0);
- Assert.assertEquals("http/1.1", protocol);
+ String protocol = "http/1.1";
+ Assert.assertTrue(strings.contains(protocol));
return protocol;
}
});
@@ -166,11 +162,11 @@ public class ProtocolNegotiationTest
public String selectProtocol(List<String> strings)
{
Assert.assertNotNull(strings);
- Assert.assertEquals(2, strings.size());
- String spdyProtocol = strings.get(0);
- Assert.assertEquals("spdy/2", spdyProtocol);
- String httpProtocol = strings.get(1);
- Assert.assertEquals("http/1.1", httpProtocol);
+ String spdyProtocol = "spdy/2";
+ Assert.assertTrue(strings.contains(spdyProtocol));
+ String httpProtocol = "http/1.1";
+ Assert.assertTrue(strings.contains(httpProtocol));
+ Assert.assertTrue(strings.indexOf(spdyProtocol) < strings.indexOf(httpProtocol));
return httpProtocol;
}
});
@@ -198,14 +194,9 @@ public class ProtocolNegotiationTest
@Test
public void testServerAdvertisingSPDYAndHTTPSpeaksDefaultProtocolWhenNPNMissing() throws Exception
{
- InetSocketAddress address = startServer(new SPDYServerConnector(null, newSslContextFactory())
- {
- @Override
- protected AsyncConnectionFactory getDefaultAsyncConnectionFactory()
- {
- return new ServerHTTPAsyncConnectionFactory(connector);
- }
- });
+ SPDYServerConnector connector = new SPDYServerConnector(null, newSslContextFactory());
+ connector.setDefaultAsyncConnectionFactory(new ServerHTTPAsyncConnectionFactory(connector));
+ InetSocketAddress address = startServer(connector);
connector.putAsyncConnectionFactory("http/1.1", new ServerHTTPAsyncConnectionFactory(connector));
SslContextFactory sslContextFactory = newSslContextFactory();
diff --git a/jetty-spdy/spdy-jetty-http/src/test/java/org/eclipse/jetty/spdy/http/PushStrategyBenchmarkTest.java b/jetty-spdy/spdy-jetty-http/src/test/java/org/eclipse/jetty/spdy/http/PushStrategyBenchmarkTest.java
new file mode 100644
index 0000000000..9486157de2
--- /dev/null
+++ b/jetty-spdy/spdy-jetty-http/src/test/java/org/eclipse/jetty/spdy/http/PushStrategyBenchmarkTest.java
@@ -0,0 +1,395 @@
+//========================================================================
+//Copyright 2011-2012 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.spdy.http;
+
+import java.io.IOException;
+import java.net.InetSocketAddress;
+import java.util.Collections;
+import java.util.Set;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.atomic.AtomicReference;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+import javax.servlet.ServletException;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import junit.framework.Assert;
+import org.eclipse.jetty.client.Address;
+import org.eclipse.jetty.client.ContentExchange;
+import org.eclipse.jetty.client.HttpClient;
+import org.eclipse.jetty.client.HttpExchange;
+import org.eclipse.jetty.server.Request;
+import org.eclipse.jetty.server.handler.AbstractHandler;
+import org.eclipse.jetty.spdy.AsyncConnectionFactory;
+import org.eclipse.jetty.spdy.api.DataInfo;
+import org.eclipse.jetty.spdy.api.Headers;
+import org.eclipse.jetty.spdy.api.SPDY;
+import org.eclipse.jetty.spdy.api.Session;
+import org.eclipse.jetty.spdy.api.SessionFrameListener;
+import org.eclipse.jetty.spdy.api.Stream;
+import org.eclipse.jetty.spdy.api.StreamFrameListener;
+import org.eclipse.jetty.spdy.api.SynInfo;
+import org.junit.Test;
+
+public class PushStrategyBenchmarkTest extends AbstractHTTPSPDYTest
+{
+ // Sample resources size from webtide.com home page
+ private final int[] htmlResources = new int[]
+ {8 * 1024};
+ private final int[] cssResources = new int[]
+ {12 * 1024, 2 * 1024};
+ private final int[] jsResources = new int[]
+ {75 * 1024, 24 * 1024, 36 * 1024};
+ private final int[] pngResources = new int[]
+ {1024, 45 * 1024, 6 * 1024, 2 * 1024, 2 * 1024, 2 * 1024, 3 * 1024, 512, 512, 19 * 1024, 512, 128, 32};
+ private final Set<String> pushedResources = Collections.newSetFromMap(new ConcurrentHashMap<String, Boolean>());
+ private final AtomicReference<CountDownLatch> latch = new AtomicReference<>();
+ private final long roundtrip = 100;
+ private final int runs = 10;
+
+ @Test
+ public void benchmarkPushStrategy() throws Exception
+ {
+ InetSocketAddress address = startHTTPServer(version(), new PushStrategyBenchmarkHandler());
+
+ // Plain HTTP
+ AsyncConnectionFactory dacf = new ServerHTTPAsyncConnectionFactory(connector);
+ connector.setDefaultAsyncConnectionFactory(dacf);
+ HttpClient httpClient = new HttpClient();
+ // Simulate browsers, that open 6 connection per origin
+ httpClient.setMaxConnectionsPerAddress(6);
+ httpClient.start();
+ benchmarkHTTP(httpClient);
+ httpClient.stop();
+
+ // First push strategy
+ PushStrategy pushStrategy = new PushStrategy.None();
+ dacf = new ServerHTTPSPDYAsyncConnectionFactory(version(), connector.getByteBufferPool(), connector.getExecutor(), connector.getScheduler(), connector, pushStrategy);
+ connector.setDefaultAsyncConnectionFactory(dacf);
+ Session session = startClient(version(), address, new ClientSessionFrameListener());
+ benchmarkSPDY(pushStrategy, session);
+ session.goAway().get(5, TimeUnit.SECONDS);
+
+ // Second push strategy
+ pushStrategy = new ReferrerPushStrategy();
+ dacf = new ServerHTTPSPDYAsyncConnectionFactory(version(), connector.getByteBufferPool(), connector.getExecutor(), connector.getScheduler(), connector, pushStrategy);
+ connector.setDefaultAsyncConnectionFactory(dacf);
+ session = startClient(version(), address, new ClientSessionFrameListener());
+ benchmarkSPDY(pushStrategy, session);
+ session.goAway().get(5, TimeUnit.SECONDS);
+ }
+
+ private void benchmarkHTTP(HttpClient httpClient) throws Exception
+ {
+ // Warm up
+ performHTTPRequests(httpClient);
+ performHTTPRequests(httpClient);
+
+ long total = 0;
+ for (int i = 0; i < runs; ++i)
+ {
+ long begin = System.nanoTime();
+ int requests = performHTTPRequests(httpClient);
+ long elapsed = TimeUnit.NANOSECONDS.toMillis(System.nanoTime() - begin);
+ total += elapsed;
+ System.err.printf("HTTP: run %d, %d request(s), roundtrip delay %d ms, elapsed = %d%n",
+ i, requests, roundtrip, elapsed);
+ }
+ System.err.printf("HTTP: roundtrip delay %d ms, average = %d%n%n",
+ roundtrip, total / runs);
+ }
+
+ private int performHTTPRequests(HttpClient httpClient) throws Exception
+ {
+ int result = 0;
+
+ for (int j = 0; j < htmlResources.length; ++j)
+ {
+ latch.set(new CountDownLatch(cssResources.length + jsResources.length + pngResources.length));
+
+ String primaryPath = "/" + j + ".html";
+ String referrer = new StringBuilder("http://localhost:").append(connector.getLocalPort()).append(primaryPath).toString();
+ ContentExchange exchange = new ContentExchange(true);
+ exchange.setMethod("GET");
+ exchange.setRequestURI(primaryPath);
+ exchange.setVersion("HTTP/1.1");
+ exchange.setAddress(new Address("localhost", connector.getLocalPort()));
+ exchange.setRequestHeader("Host", "localhost:" + connector.getLocalPort());
+ ++result;
+ httpClient.send(exchange);
+ Assert.assertEquals(HttpExchange.STATUS_COMPLETED, exchange.waitForDone());
+ Assert.assertEquals(200, exchange.getResponseStatus());
+
+ for (int i = 0; i < cssResources.length; ++i)
+ {
+ String path = "/" + i + ".css";
+ exchange = createExchangeWithReferrer(referrer, path);
+ ++result;
+ httpClient.send(exchange);
+ }
+ for (int i = 0; i < jsResources.length; ++i)
+ {
+ String path = "/" + i + ".js";
+ exchange = createExchangeWithReferrer(referrer, path);
+ ++result;
+ httpClient.send(exchange);
+ }
+ for (int i = 0; i < pngResources.length; ++i)
+ {
+ String path = "/" + i + ".png";
+ exchange = createExchangeWithReferrer(referrer, path);
+ ++result;
+ httpClient.send(exchange);
+ }
+
+ Assert.assertTrue(latch.get().await(5, TimeUnit.SECONDS));
+ }
+
+ return result;
+ }
+
+ private ContentExchange createExchangeWithReferrer(String referrer, String path)
+ {
+ ContentExchange exchange;
+ exchange = new TestExchange();
+ exchange.setMethod("GET");
+ exchange.setRequestURI(path);
+ exchange.setVersion("HTTP/1.1");
+ exchange.setAddress(new Address("localhost", connector.getLocalPort()));
+ exchange.setRequestHeader("Host", "localhost:" + connector.getLocalPort());
+ exchange.setRequestHeader("referer", referrer);
+ return exchange;
+ }
+
+
+ private void benchmarkSPDY(PushStrategy pushStrategy, Session session) throws Exception
+ {
+ // Warm up PushStrategy
+ performRequests(session);
+ performRequests(session);
+
+ long total = 0;
+ for (int i = 0; i < runs; ++i)
+ {
+ long begin = System.nanoTime();
+ int requests = performRequests(session);
+ long elapsed = TimeUnit.NANOSECONDS.toMillis(System.nanoTime() - begin);
+ total += elapsed;
+ System.err.printf("SPDY(%s): run %d, %d request(s), roundtrip delay %d ms, elapsed = %d%n",
+ pushStrategy.getClass().getSimpleName(), i, requests, roundtrip, elapsed);
+ }
+ System.err.printf("SPDY(%s): roundtrip delay %d ms, average = %d%n%n",
+ pushStrategy.getClass().getSimpleName(), roundtrip, total / runs);
+ }
+
+ private int performRequests(Session session) throws Exception
+ {
+ int result = 0;
+
+ for (int j = 0; j < htmlResources.length; ++j)
+ {
+ latch.set(new CountDownLatch(cssResources.length + jsResources.length + pngResources.length));
+ pushedResources.clear();
+
+ String primaryPath = "/" + j + ".html";
+ String referrer = new StringBuilder("http://localhost:").append(connector.getLocalPort()).append(primaryPath).toString();
+ Headers headers = new Headers();
+ headers.put(HTTPSPDYHeader.METHOD.name(version()), "GET");
+ headers.put(HTTPSPDYHeader.URI.name(version()), primaryPath);
+ headers.put(HTTPSPDYHeader.VERSION.name(version()), "HTTP/1.1");
+ headers.put(HTTPSPDYHeader.SCHEME.name(version()), "http");
+ headers.put(HTTPSPDYHeader.HOST.name(version()), "localhost:" + connector.getLocalPort());
+ // Wait for the HTML to simulate browser's behavior
+ ++result;
+ final CountDownLatch htmlLatch = new CountDownLatch(1);
+ session.syn(new SynInfo(headers, true), new StreamFrameListener.Adapter()
+ {
+ @Override
+ public void onData(Stream stream, DataInfo dataInfo)
+ {
+ dataInfo.consume(dataInfo.length());
+ if (dataInfo.isClose())
+ htmlLatch.countDown();
+ }
+ });
+ Assert.assertTrue(htmlLatch.await(5, TimeUnit.SECONDS));
+
+ for (int i = 0; i < cssResources.length; ++i)
+ {
+ String path = "/" + i + ".css";
+ if (pushedResources.contains(path))
+ continue;
+ headers = createRequestHeaders(referrer, path);
+ ++result;
+ session.syn(new SynInfo(headers, true), new DataListener());
+ }
+ for (int i = 0; i < jsResources.length; ++i)
+ {
+ String path = "/" + i + ".js";
+ if (pushedResources.contains(path))
+ continue;
+ headers = createRequestHeaders(referrer, path);
+ ++result;
+ session.syn(new SynInfo(headers, true), new DataListener());
+ }
+ for (int i = 0; i < pngResources.length; ++i)
+ {
+ String path = "/" + i + ".png";
+ if (pushedResources.contains(path))
+ continue;
+ headers = createRequestHeaders(referrer, path);
+ ++result;
+ session.syn(new SynInfo(headers, true), new DataListener());
+ }
+
+ Assert.assertTrue(latch.get().await(5, TimeUnit.SECONDS));
+ }
+
+ return result;
+ }
+
+ private Headers createRequestHeaders(String referrer, String path)
+ {
+ Headers headers;
+ headers = new Headers();
+ headers.put(HTTPSPDYHeader.METHOD.name(version()), "GET");
+ headers.put(HTTPSPDYHeader.URI.name(version()), path);
+ headers.put(HTTPSPDYHeader.VERSION.name(version()), "HTTP/1.1");
+ headers.put(HTTPSPDYHeader.SCHEME.name(version()), "http");
+ headers.put(HTTPSPDYHeader.HOST.name(version()), "localhost:" + connector.getLocalPort());
+ headers.put("referer", referrer);
+ return headers;
+ }
+
+ private void sleep(long delay) throws ServletException
+ {
+ try
+ {
+ TimeUnit.MILLISECONDS.sleep(delay);
+ }
+ catch (InterruptedException x)
+ {
+ throw new ServletException(x);
+ }
+ }
+
+ private class PushStrategyBenchmarkHandler extends AbstractHandler
+ {
+ @Override
+ public void handle(String target, Request baseRequest, HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException
+ {
+ baseRequest.setHandled(true);
+
+ // Sleep half of the roundtrip time, to simulate the delay of responses, even for pushed resources
+ sleep(roundtrip / 2);
+ // If it's not a pushed resource, sleep half of the roundtrip time, to simulate the delay of requests
+ if (request.getHeader("x-spdy-push") == null)
+ sleep(roundtrip / 2);
+
+ String suffix = target.substring(target.indexOf('.') + 1);
+ int index = Integer.parseInt(target.substring(1, target.length() - suffix.length() - 1));
+
+ int contentLength;
+ String contentType;
+ switch (suffix)
+ {
+ case "html":
+ contentLength = htmlResources[index];
+ contentType = "text/html";
+ break;
+ case "css":
+ contentLength = cssResources[index];
+ contentType = "text/css";
+ break;
+ case "js":
+ contentLength = jsResources[index];
+ contentType = "text/javascript";
+ break;
+ case "png":
+ contentLength = pngResources[index];
+ contentType = "image/png";
+ break;
+ default:
+ throw new ServletException();
+ }
+
+ response.setContentType(contentType);
+ response.setContentLength(contentLength);
+ response.getOutputStream().write(new byte[contentLength]);
+ }
+ }
+
+ private void addPushedResource(String pushedURI)
+ {
+ switch (version())
+ {
+ case SPDY.V2:
+ {
+ Matcher matcher = Pattern.compile("https?://[^:]+:\\d+(/.*)").matcher(pushedURI);
+ Assert.assertTrue(matcher.matches());
+ pushedResources.add(matcher.group(1));
+ break;
+ }
+ case SPDY.V3:
+ {
+ pushedResources.add(pushedURI);
+ break;
+ }
+ default:
+ {
+ throw new IllegalStateException();
+ }
+ }
+ }
+
+ private class ClientSessionFrameListener extends SessionFrameListener.Adapter
+ {
+ @Override
+ public StreamFrameListener onSyn(Stream stream, SynInfo synInfo)
+ {
+ String path = synInfo.getHeaders().get(HTTPSPDYHeader.URI.name(version())).value();
+ addPushedResource(path);
+ return new DataListener();
+ }
+ }
+
+ private class DataListener extends StreamFrameListener.Adapter
+ {
+ @Override
+ public void onData(Stream stream, DataInfo dataInfo)
+ {
+ dataInfo.consume(dataInfo.length());
+ if (dataInfo.isClose())
+ latch.get().countDown();
+ }
+ }
+
+ private class TestExchange extends ContentExchange
+ {
+ private TestExchange()
+ {
+ super(true);
+ }
+
+ @Override
+ protected void onResponseComplete() throws IOException
+ {
+ latch.get().countDown();
+ }
+ }
+}
diff --git a/jetty-spdy/spdy-jetty-http/src/test/java/org/eclipse/jetty/spdy/http/ReferrerPushStrategyTest.java b/jetty-spdy/spdy-jetty-http/src/test/java/org/eclipse/jetty/spdy/http/ReferrerPushStrategyTest.java
deleted file mode 100644
index f18ff00b41..0000000000
--- a/jetty-spdy/spdy-jetty-http/src/test/java/org/eclipse/jetty/spdy/http/ReferrerPushStrategyTest.java
+++ /dev/null
@@ -1,471 +0,0 @@
-package org.eclipse.jetty.spdy.http;
-
-import java.io.IOException;
-import java.io.PrintWriter;
-import java.net.InetSocketAddress;
-import java.util.concurrent.CountDownLatch;
-import java.util.concurrent.TimeUnit;
-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.handler.AbstractHandler;
-import org.eclipse.jetty.spdy.AsyncConnectionFactory;
-import org.eclipse.jetty.spdy.SPDYServerConnector;
-import org.eclipse.jetty.spdy.api.DataInfo;
-import org.eclipse.jetty.spdy.api.Headers;
-import org.eclipse.jetty.spdy.api.ReplyInfo;
-import org.eclipse.jetty.spdy.api.SPDY;
-import org.eclipse.jetty.spdy.api.Session;
-import org.eclipse.jetty.spdy.api.SessionFrameListener;
-import org.eclipse.jetty.spdy.api.Stream;
-import org.eclipse.jetty.spdy.api.StreamFrameListener;
-import org.eclipse.jetty.spdy.api.SynInfo;
-import org.junit.Assert;
-import org.junit.Test;
-
-public class ReferrerPushStrategyTest extends AbstractHTTPSPDYTest
-{
- @Override
- protected SPDYServerConnector newHTTPSPDYServerConnector()
- {
- return new HTTPSPDYServerConnector()
- {
- private final AsyncConnectionFactory defaultAsyncConnectionFactory =
- new ServerHTTPSPDYAsyncConnectionFactory(SPDY.V2, getByteBufferPool(), getExecutor(), getScheduler(), this, new ReferrerPushStrategy());
-
- @Override
- protected AsyncConnectionFactory getDefaultAsyncConnectionFactory()
- {
- return defaultAsyncConnectionFactory;
- }
- };
- }
-
- @Test
- public void testAssociatedResourceIsPushed() throws Exception
- {
- InetSocketAddress address = startHTTPServer(new AbstractHandler()
- {
- @Override
- public void handle(String target, Request baseRequest, HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException
- {
- String url = request.getRequestURI();
- PrintWriter output = response.getWriter();
- if (url.endsWith(".html"))
- output.print("<html><head/><body>HELLO</body></html>");
- else if (url.endsWith(".css"))
- output.print("body { background: #FFF; }");
- baseRequest.setHandled(true);
- }
- });
- Session session1 = startClient(address, null);
-
- final CountDownLatch mainResourceLatch = new CountDownLatch(1);
- Headers mainRequestHeaders = new Headers();
- mainRequestHeaders.put("method", "GET");
- String mainResource = "/index.html";
- mainRequestHeaders.put("url", mainResource);
- mainRequestHeaders.put("version", "HTTP/1.1");
- mainRequestHeaders.put("scheme", "http");
- mainRequestHeaders.put("host", "localhost:" + connector.getLocalPort());
- session1.syn(new SynInfo(mainRequestHeaders, true), new StreamFrameListener.Adapter()
- {
- @Override
- public void onData(Stream stream, DataInfo dataInfo)
- {
- dataInfo.consume(dataInfo.length());
- if (dataInfo.isClose())
- mainResourceLatch.countDown();
- }
- });
- Assert.assertTrue(mainResourceLatch.await(5, TimeUnit.SECONDS));
-
- final CountDownLatch associatedResourceLatch = new CountDownLatch(1);
- Headers associatedRequestHeaders = new Headers();
- associatedRequestHeaders.put("method", "GET");
- associatedRequestHeaders.put("url", "/style.css");
- associatedRequestHeaders.put("version", "HTTP/1.1");
- associatedRequestHeaders.put("scheme", "http");
- associatedRequestHeaders.put("host", "localhost:" + connector.getLocalPort());
- associatedRequestHeaders.put("referer", "http://localhost:" + connector.getLocalPort() + mainResource);
- session1.syn(new SynInfo(associatedRequestHeaders, true), new StreamFrameListener.Adapter()
- {
- @Override
- public void onData(Stream stream, DataInfo dataInfo)
- {
- dataInfo.consume(dataInfo.length());
- if (dataInfo.isClose())
- associatedResourceLatch.countDown();
- }
- });
- Assert.assertTrue(associatedResourceLatch.await(5, TimeUnit.SECONDS));
-
- // Create another client, and perform the same request for the main resource, we expect the css being pushed
-
- final CountDownLatch mainStreamLatch = new CountDownLatch(2);
- final CountDownLatch pushDataLatch = new CountDownLatch(1);
- Session session2 = startClient(address, new SessionFrameListener.Adapter()
- {
- @Override
- public StreamFrameListener onSyn(Stream stream, SynInfo synInfo)
- {
- Assert.assertTrue(stream.isUnidirectional());
- return new StreamFrameListener.Adapter()
- {
- @Override
- public void onData(Stream stream, DataInfo dataInfo)
- {
- dataInfo.consume(dataInfo.length());
- if (dataInfo.isClose())
- pushDataLatch.countDown();
- }
- };
- }
- });
- session2.syn(new SynInfo(mainRequestHeaders, true), new StreamFrameListener.Adapter()
- {
- @Override
- public void onReply(Stream stream, ReplyInfo replyInfo)
- {
- Assert.assertFalse(replyInfo.isClose());
- mainStreamLatch.countDown();
- }
-
- @Override
- public void onData(Stream stream, DataInfo dataInfo)
- {
- dataInfo.consume(dataInfo.length());
- if (dataInfo.isClose())
- mainStreamLatch.countDown();
- }
- });
-
- Assert.assertTrue(mainStreamLatch.await(5, TimeUnit.SECONDS));
- Assert.assertTrue(pushDataLatch.await(5, TimeUnit.SECONDS));
- }
-
- @Test
- public void testNestedAssociatedResourceIsPushed() throws Exception
- {
- InetSocketAddress address = startHTTPServer(new AbstractHandler()
- {
- @Override
- public void handle(String target, Request baseRequest, HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException
- {
- String url = request.getRequestURI();
- PrintWriter output = response.getWriter();
- if (url.endsWith(".html"))
- output.print("<html><head/><body>HELLO</body></html>");
- else if (url.endsWith(".css"))
- output.print("body { background: #FFF; }");
- else if (url.endsWith(".gif"))
- output.print("\u0000");
- baseRequest.setHandled(true);
- }
- });
- Session session1 = startClient(address, null);
-
- final CountDownLatch mainResourceLatch = new CountDownLatch(1);
- Headers mainRequestHeaders = new Headers();
- mainRequestHeaders.put("method", "GET");
- String mainResource = "/index.html";
- mainRequestHeaders.put("url", mainResource);
- mainRequestHeaders.put("version", "HTTP/1.1");
- mainRequestHeaders.put("scheme", "http");
- mainRequestHeaders.put("host", "localhost:" + connector.getLocalPort());
- session1.syn(new SynInfo(mainRequestHeaders, true), new StreamFrameListener.Adapter()
- {
- @Override
- public void onData(Stream stream, DataInfo dataInfo)
- {
- dataInfo.consume(dataInfo.length());
- if (dataInfo.isClose())
- mainResourceLatch.countDown();
- }
- });
- Assert.assertTrue(mainResourceLatch.await(5, TimeUnit.SECONDS));
-
- final CountDownLatch associatedResourceLatch = new CountDownLatch(1);
- Headers associatedRequestHeaders = new Headers();
- associatedRequestHeaders.put("method", "GET");
- String associatedResource = "/style.css";
- associatedRequestHeaders.put("url", associatedResource);
- associatedRequestHeaders.put("version", "HTTP/1.1");
- associatedRequestHeaders.put("scheme", "http");
- associatedRequestHeaders.put("host", "localhost:" + connector.getLocalPort());
- associatedRequestHeaders.put("referer", "http://localhost:" + connector.getLocalPort() + mainResource);
- session1.syn(new SynInfo(associatedRequestHeaders, true), new StreamFrameListener.Adapter()
- {
- @Override
- public void onData(Stream stream, DataInfo dataInfo)
- {
- dataInfo.consume(dataInfo.length());
- if (dataInfo.isClose())
- associatedResourceLatch.countDown();
- }
- });
- Assert.assertTrue(associatedResourceLatch.await(5, TimeUnit.SECONDS));
-
- final CountDownLatch nestedResourceLatch = new CountDownLatch(1);
- Headers nestedRequestHeaders = new Headers();
- nestedRequestHeaders.put("method", "GET");
- nestedRequestHeaders.put("url", "/image.gif");
- nestedRequestHeaders.put("version", "HTTP/1.1");
- nestedRequestHeaders.put("scheme", "http");
- nestedRequestHeaders.put("host", "localhost:" + connector.getLocalPort());
- nestedRequestHeaders.put("referer", "http://localhost:" + connector.getLocalPort() + associatedResource);
- session1.syn(new SynInfo(nestedRequestHeaders, true), new StreamFrameListener.Adapter()
- {
- @Override
- public void onData(Stream stream, DataInfo dataInfo)
- {
- dataInfo.consume(dataInfo.length());
- if (dataInfo.isClose())
- nestedResourceLatch.countDown();
- }
- });
- Assert.assertTrue(nestedResourceLatch.await(5, TimeUnit.SECONDS));
-
- // Create another client, and perform the same request for the main resource, we expect the css and the image being pushed
-
- final CountDownLatch mainStreamLatch = new CountDownLatch(2);
- final CountDownLatch pushDataLatch = new CountDownLatch(2);
- Session session2 = startClient(address, new SessionFrameListener.Adapter()
- {
- @Override
- public StreamFrameListener onSyn(Stream stream, SynInfo synInfo)
- {
- Assert.assertTrue(stream.isUnidirectional());
- return new StreamFrameListener.Adapter()
- {
- @Override
- public void onData(Stream stream, DataInfo dataInfo)
- {
- dataInfo.consume(dataInfo.length());
- if (dataInfo.isClose())
- pushDataLatch.countDown();
- }
- };
- }
- });
- session2.syn(new SynInfo(mainRequestHeaders, true), new StreamFrameListener.Adapter()
- {
- @Override
- public void onReply(Stream stream, ReplyInfo replyInfo)
- {
- Assert.assertFalse(replyInfo.isClose());
- mainStreamLatch.countDown();
- }
-
- @Override
- public void onData(Stream stream, DataInfo dataInfo)
- {
- dataInfo.consume(dataInfo.length());
- if (dataInfo.isClose())
- mainStreamLatch.countDown();
- }
- });
-
- Assert.assertTrue(mainStreamLatch.await(5, TimeUnit.SECONDS));
- Assert.assertTrue(pushDataLatch.await(5, TimeUnit.SECONDS));
- }
-
- @Test
- public void testMainResourceWithReferrerIsNotPushed() throws Exception
- {
- InetSocketAddress address = startHTTPServer(new AbstractHandler()
- {
- @Override
- public void handle(String target, Request baseRequest, HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException
- {
- String url = request.getRequestURI();
- PrintWriter output = response.getWriter();
- if (url.endsWith(".html"))
- output.print("<html><head/><body>HELLO</body></html>");
- baseRequest.setHandled(true);
- }
- });
- Session session1 = startClient(address, null);
-
- final CountDownLatch mainResourceLatch = new CountDownLatch(1);
- Headers mainRequestHeaders = new Headers();
- mainRequestHeaders.put("method", "GET");
- String mainResource = "/index.html";
- mainRequestHeaders.put("url", mainResource);
- mainRequestHeaders.put("version", "HTTP/1.1");
- mainRequestHeaders.put("scheme", "http");
- mainRequestHeaders.put("host", "localhost:" + connector.getLocalPort());
- session1.syn(new SynInfo(mainRequestHeaders, true), new StreamFrameListener.Adapter()
- {
- @Override
- public void onData(Stream stream, DataInfo dataInfo)
- {
- dataInfo.consume(dataInfo.length());
- if (dataInfo.isClose())
- mainResourceLatch.countDown();
- }
- });
- Assert.assertTrue(mainResourceLatch.await(5, TimeUnit.SECONDS));
-
- final CountDownLatch associatedResourceLatch = new CountDownLatch(1);
- Headers associatedRequestHeaders = new Headers();
- associatedRequestHeaders.put("method", "GET");
- associatedRequestHeaders.put("url", "/home.html");
- associatedRequestHeaders.put("version", "HTTP/1.1");
- associatedRequestHeaders.put("scheme", "http");
- associatedRequestHeaders.put("host", "localhost:" + connector.getLocalPort());
- associatedRequestHeaders.put("referer", "http://localhost:" + connector.getLocalPort() + mainResource);
- session1.syn(new SynInfo(associatedRequestHeaders, true), new StreamFrameListener.Adapter()
- {
- @Override
- public void onData(Stream stream, DataInfo dataInfo)
- {
- dataInfo.consume(dataInfo.length());
- if (dataInfo.isClose())
- associatedResourceLatch.countDown();
- }
- });
- Assert.assertTrue(associatedResourceLatch.await(5, TimeUnit.SECONDS));
-
- // Create another client, and perform the same request for the main resource, we expect nothing being pushed
-
- final CountDownLatch mainStreamLatch = new CountDownLatch(2);
- final CountDownLatch pushLatch = new CountDownLatch(1);
- Session session2 = startClient(address, new SessionFrameListener.Adapter()
- {
- @Override
- public StreamFrameListener onSyn(Stream stream, SynInfo synInfo)
- {
- pushLatch.countDown();
- return null;
- }
- });
- session2.syn(new SynInfo(mainRequestHeaders, true), new StreamFrameListener.Adapter()
- {
- @Override
- public void onReply(Stream stream, ReplyInfo replyInfo)
- {
- Assert.assertFalse(replyInfo.isClose());
- mainStreamLatch.countDown();
- }
-
- @Override
- public void onData(Stream stream, DataInfo dataInfo)
- {
- dataInfo.consume(dataInfo.length());
- if (dataInfo.isClose())
- mainStreamLatch.countDown();
- }
- });
-
- Assert.assertTrue(mainStreamLatch.await(5, TimeUnit.SECONDS));
- Assert.assertFalse(pushLatch.await(1, TimeUnit.SECONDS));
- }
-
- @Test
- public void testRequestWithIfModifiedSinceHeaderPreventsPush() throws Exception
- {
- InetSocketAddress address = startHTTPServer(new AbstractHandler()
- {
- @Override
- public void handle(String target, Request baseRequest, HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException
- {
- String url = request.getRequestURI();
- PrintWriter output = response.getWriter();
- if (url.endsWith(".html"))
- output.print("<html><head/><body>HELLO</body></html>");
- else if (url.endsWith(".css"))
- output.print("body { background: #FFF; }");
- baseRequest.setHandled(true);
- }
- });
- Session session1 = startClient(address, null);
-
- final CountDownLatch mainResourceLatch = new CountDownLatch(1);
- Headers mainRequestHeaders = new Headers();
- mainRequestHeaders.put("method", "GET");
- String mainResource = "/index.html";
- mainRequestHeaders.put("url", mainResource);
- mainRequestHeaders.put("version", "HTTP/1.1");
- mainRequestHeaders.put("scheme", "http");
- mainRequestHeaders.put("host", "localhost:" + connector.getLocalPort());
- mainRequestHeaders.put("If-Modified-Since", "Tue, 27 Mar 2012 16:36:52 GMT");
- session1.syn(new SynInfo(mainRequestHeaders, true), new StreamFrameListener.Adapter()
- {
- @Override
- public void onData(Stream stream, DataInfo dataInfo)
- {
- dataInfo.consume(dataInfo.length());
- if (dataInfo.isClose())
- mainResourceLatch.countDown();
- }
- });
- Assert.assertTrue(mainResourceLatch.await(5, TimeUnit.SECONDS));
-
- final CountDownLatch associatedResourceLatch = new CountDownLatch(1);
- Headers associatedRequestHeaders = new Headers();
- associatedRequestHeaders.put("method", "GET");
- associatedRequestHeaders.put("url", "/style.css");
- associatedRequestHeaders.put("version", "HTTP/1.1");
- associatedRequestHeaders.put("scheme", "http");
- associatedRequestHeaders.put("host", "localhost:" + connector.getLocalPort());
- associatedRequestHeaders.put("referer", "http://localhost:" + connector.getLocalPort() + mainResource);
- session1.syn(new SynInfo(associatedRequestHeaders, true), new StreamFrameListener.Adapter()
- {
- @Override
- public void onData(Stream stream, DataInfo dataInfo)
- {
- dataInfo.consume(dataInfo.length());
- if (dataInfo.isClose())
- associatedResourceLatch.countDown();
- }
- });
- Assert.assertTrue(associatedResourceLatch.await(5, TimeUnit.SECONDS));
-
- // Create another client, and perform the same request for the main resource, we expect the css NOT being pushed as the main request contains an
- // if-modified-since header
-
- final CountDownLatch mainStreamLatch = new CountDownLatch(2);
- final CountDownLatch pushDataLatch = new CountDownLatch(1);
- Session session2 = startClient(address, new SessionFrameListener.Adapter()
- {
- @Override
- public StreamFrameListener onSyn(Stream stream, SynInfo synInfo)
- {
- Assert.assertTrue(stream.isUnidirectional());
- return new StreamFrameListener.Adapter()
- {
- @Override
- public void onData(Stream stream, DataInfo dataInfo)
- {
- dataInfo.consume(dataInfo.length());
- if (dataInfo.isClose())
- pushDataLatch.countDown();
- }
- };
- }
- });
- session2.syn(new SynInfo(mainRequestHeaders, true), new StreamFrameListener.Adapter()
- {
- @Override
- public void onReply(Stream stream, ReplyInfo replyInfo)
- {
- Assert.assertFalse(replyInfo.isClose());
- mainStreamLatch.countDown();
- }
-
- @Override
- public void onData(Stream stream, DataInfo dataInfo)
- {
- dataInfo.consume(dataInfo.length());
- if (dataInfo.isClose())
- mainStreamLatch.countDown();
- }
- });
-
- Assert.assertTrue(mainStreamLatch.await(5, TimeUnit.SECONDS));
- Assert.assertFalse("We don't expect data to be pushed as the main request contained an if-modified-since header",pushDataLatch.await(1, TimeUnit.SECONDS));
- }
-}
diff --git a/jetty-spdy/spdy-jetty-http/src/test/java/org/eclipse/jetty/spdy/http/ReferrerPushStrategyUnitTest.java b/jetty-spdy/spdy-jetty-http/src/test/java/org/eclipse/jetty/spdy/http/ReferrerPushStrategyUnitTest.java
new file mode 100644
index 0000000000..0edbcf8a33
--- /dev/null
+++ b/jetty-spdy/spdy-jetty-http/src/test/java/org/eclipse/jetty/spdy/http/ReferrerPushStrategyUnitTest.java
@@ -0,0 +1,119 @@
+//========================================================================
+//Copyright 2011-2012 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.spdy.http;
+
+import java.util.Set;
+
+import org.eclipse.jetty.spdy.api.Headers;
+import org.eclipse.jetty.spdy.api.SPDY;
+import org.eclipse.jetty.spdy.api.Session;
+import org.eclipse.jetty.spdy.api.Stream;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.runners.MockitoJUnitRunner;
+
+import static org.hamcrest.CoreMatchers.is;
+import static org.junit.Assert.assertThat;
+import static org.mockito.Mockito.when;
+
+@RunWith(MockitoJUnitRunner.class)
+public class ReferrerPushStrategyUnitTest
+{
+ public static final short VERSION = SPDY.V3;
+ public static final String SCHEME = "http";
+ public static final String HOST = "localhost";
+ public static final String MAIN_URI = "/index.html";
+ public static final String METHOD = "GET";
+
+ // class under test
+ private ReferrerPushStrategy referrerPushStrategy;
+
+ @Mock
+ Stream stream;
+ @Mock
+ Session session;
+
+
+ @Before
+ public void setup()
+ {
+ referrerPushStrategy = new ReferrerPushStrategy();
+ }
+
+ @Test
+ public void testReferrerCallsAfterTimeoutAreNotAddedAsPushResources() throws InterruptedException
+ {
+ Headers requestHeaders = getBaseHeaders(VERSION);
+ int referrerCallTimeout = 1000;
+ referrerPushStrategy.setReferrerPushPeriod(referrerCallTimeout);
+ setMockExpectations();
+
+ String referrerUrl = fillPushStrategyCache(requestHeaders);
+ Set<String> pushResources;
+
+ // sleep to pretend that the user manually clicked on a linked resource instead the browser requesting subresources immediately
+ Thread.sleep(referrerCallTimeout + 1);
+
+ requestHeaders.put(HTTPSPDYHeader.URI.name(VERSION), "image2.jpg");
+ requestHeaders.put("referer", referrerUrl);
+ pushResources = referrerPushStrategy.apply(stream, requestHeaders, new Headers());
+ assertThat("pushResources is empty", pushResources.size(), is(0));
+
+ requestHeaders.put(HTTPSPDYHeader.URI.name(VERSION), MAIN_URI);
+ pushResources = referrerPushStrategy.apply(stream, requestHeaders, new Headers());
+ // as the image2.jpg request has been a link and not a subresource, we expect that pushResources.size() is still 2
+ assertThat("pushResources contains two elements image.jpg and style.css", pushResources.size(), is(2));
+ }
+
+ private Headers getBaseHeaders(short version)
+ {
+ Headers requestHeaders = new Headers();
+ requestHeaders.put(HTTPSPDYHeader.SCHEME.name(version), SCHEME);
+ requestHeaders.put(HTTPSPDYHeader.HOST.name(version), HOST);
+ requestHeaders.put(HTTPSPDYHeader.URI.name(version), MAIN_URI);
+ requestHeaders.put(HTTPSPDYHeader.METHOD.name(version), METHOD);
+ return requestHeaders;
+ }
+
+ private void setMockExpectations()
+ {
+ when(stream.getSession()).thenReturn(session);
+ when(session.getVersion()).thenReturn(VERSION);
+ }
+
+ private String fillPushStrategyCache(Headers requestHeaders)
+ {
+ Set<String> pushResources = referrerPushStrategy.apply(stream, requestHeaders, new Headers());
+ assertThat("pushResources is empty", pushResources.size(), is(0));
+
+ String origin = SCHEME + "://" + HOST;
+ String referrerUrl = origin + MAIN_URI;
+
+ requestHeaders.put(HTTPSPDYHeader.URI.name(VERSION), "image.jpg");
+ requestHeaders.put("referer", referrerUrl);
+ pushResources = referrerPushStrategy.apply(stream, requestHeaders, new Headers());
+ assertThat("pushResources is empty", pushResources.size(), is(0));
+
+ requestHeaders.put(HTTPSPDYHeader.URI.name(VERSION), "style.css");
+ pushResources = referrerPushStrategy.apply(stream, requestHeaders, new Headers());
+ assertThat("pushResources is empty", pushResources.size(), is(0));
+
+ requestHeaders.put(HTTPSPDYHeader.URI.name(VERSION), MAIN_URI);
+ pushResources = referrerPushStrategy.apply(stream, requestHeaders, new Headers());
+ assertThat("pushResources contains two elements image.jpg and style.css", pushResources.size(), is(2));
+ return referrerUrl;
+ }
+}
diff --git a/jetty-spdy/spdy-jetty-http/src/test/java/org/eclipse/jetty/spdy/http/ReferrerPushStrategyV2Test.java b/jetty-spdy/spdy-jetty-http/src/test/java/org/eclipse/jetty/spdy/http/ReferrerPushStrategyV2Test.java
new file mode 100644
index 0000000000..8bc79c3f58
--- /dev/null
+++ b/jetty-spdy/spdy-jetty-http/src/test/java/org/eclipse/jetty/spdy/http/ReferrerPushStrategyV2Test.java
@@ -0,0 +1,797 @@
+//========================================================================
+//Copyright 2011-2012 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.spdy.http;
+
+import java.io.IOException;
+import java.io.PrintWriter;
+import java.net.InetSocketAddress;
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.TimeUnit;
+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.handler.AbstractHandler;
+import org.eclipse.jetty.spdy.AsyncConnectionFactory;
+import org.eclipse.jetty.spdy.SPDYServerConnector;
+import org.eclipse.jetty.spdy.api.DataInfo;
+import org.eclipse.jetty.spdy.api.Headers;
+import org.eclipse.jetty.spdy.api.ReplyInfo;
+import org.eclipse.jetty.spdy.api.SPDY;
+import org.eclipse.jetty.spdy.api.Session;
+import org.eclipse.jetty.spdy.api.SessionFrameListener;
+import org.eclipse.jetty.spdy.api.Stream;
+import org.eclipse.jetty.spdy.api.StreamFrameListener;
+import org.eclipse.jetty.spdy.api.SynInfo;
+import org.junit.Assert;
+import org.junit.Test;
+
+public class ReferrerPushStrategyV2Test extends AbstractHTTPSPDYTest
+{
+
+ private final String mainResource = "/index.html";
+ private final String cssResource = "/style.css";
+
+ @Override
+ protected SPDYServerConnector newHTTPSPDYServerConnector(short version)
+ {
+ SPDYServerConnector connector = super.newHTTPSPDYServerConnector(version);
+ AsyncConnectionFactory defaultFactory = new ServerHTTPSPDYAsyncConnectionFactory(version, connector.getByteBufferPool(), connector.getExecutor(), connector.getScheduler(), connector, new ReferrerPushStrategy());
+ connector.setDefaultAsyncConnectionFactory(defaultFactory);
+ return connector;
+ }
+
+ @Test
+ public void testPushHeadersAreValid() throws Exception
+ {
+ InetSocketAddress address = createServer();
+
+ ReferrerPushStrategy pushStrategy = new ReferrerPushStrategy();
+ int referrerPushPeriod = 1000;
+ pushStrategy.setReferrerPushPeriod(referrerPushPeriod);
+ AsyncConnectionFactory defaultFactory = new ServerHTTPSPDYAsyncConnectionFactory(version(), connector.getByteBufferPool(), connector.getExecutor(), connector.getScheduler(), connector, pushStrategy);
+ connector.setDefaultAsyncConnectionFactory(defaultFactory);
+
+ Headers mainRequestHeaders = createHeadersWithoutReferrer(mainResource);
+ Session session1 = sendMainRequestAndCSSRequest(address, mainRequestHeaders);
+
+ // Sleep for pushPeriod This should prevent application.js from being mapped as pushResource
+ Thread.sleep(referrerPushPeriod + 1);
+
+ sendJSRequest(session1);
+
+ run2ndClientRequests(address, mainRequestHeaders, true);
+ }
+
+ @Test
+ public void testReferrerPushPeriod() throws Exception
+ {
+ InetSocketAddress address = createServer();
+
+ ReferrerPushStrategy pushStrategy = new ReferrerPushStrategy();
+ int referrerPushPeriod = 1000;
+ pushStrategy.setReferrerPushPeriod(referrerPushPeriod);
+ AsyncConnectionFactory defaultFactory = new ServerHTTPSPDYAsyncConnectionFactory(version(), connector.getByteBufferPool(), connector.getExecutor(), connector.getScheduler(), connector, pushStrategy);
+ connector.setDefaultAsyncConnectionFactory(defaultFactory);
+
+ Headers mainRequestHeaders = createHeadersWithoutReferrer(mainResource);
+ Session session1 = sendMainRequestAndCSSRequest(address, mainRequestHeaders);
+
+ // Sleep for pushPeriod This should prevent application.js from being mapped as pushResource
+ Thread.sleep(referrerPushPeriod+1);
+
+ sendJSRequest(session1);
+
+ run2ndClientRequests(address, mainRequestHeaders, false);
+ }
+
+ @Test
+ public void testMaxAssociatedResources() throws Exception
+ {
+ InetSocketAddress address = createServer();
+
+ ReferrerPushStrategy pushStrategy = new ReferrerPushStrategy();
+ pushStrategy.setMaxAssociatedResources(1);
+ AsyncConnectionFactory defaultFactory = new ServerHTTPSPDYAsyncConnectionFactory(version(), connector.getByteBufferPool(), connector.getExecutor(), connector.getScheduler(), connector, pushStrategy);
+ connector.setDefaultAsyncConnectionFactory(defaultFactory);
+
+ Headers mainRequestHeaders = createHeadersWithoutReferrer(mainResource);
+ Session session1 = sendMainRequestAndCSSRequest(address, mainRequestHeaders);
+
+ sendJSRequest(session1);
+
+ run2ndClientRequests(address, mainRequestHeaders, false);
+ }
+
+ private InetSocketAddress createServer() throws Exception
+ {
+ return startHTTPServer(version(), new AbstractHandler()
+ {
+ @Override
+ public void handle(String target, Request baseRequest, HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException
+ {
+ String url = request.getRequestURI();
+ PrintWriter output = response.getWriter();
+ if (url.endsWith(".html"))
+ output.print("<html><head/><body>HELLO</body></html>");
+ else if (url.endsWith(".css"))
+ output.print("body { background: #FFF; }");
+ else if (url.endsWith(".js"))
+ output.print("function(){}();");
+ baseRequest.setHandled(true);
+ }
+ });
+ }
+
+ private Session sendMainRequestAndCSSRequest(InetSocketAddress address, Headers mainRequestHeaders) throws Exception
+ {
+ Session session1 = startClient(version(), address, null);
+
+ final CountDownLatch mainResourceLatch = new CountDownLatch(1);
+ session1.syn(new SynInfo(mainRequestHeaders, true), new StreamFrameListener.Adapter()
+ {
+ @Override
+ public void onData(Stream stream, DataInfo dataInfo)
+ {
+ dataInfo.consume(dataInfo.length());
+ if (dataInfo.isClose())
+ mainResourceLatch.countDown();
+ }
+ });
+ Assert.assertTrue(mainResourceLatch.await(5, TimeUnit.SECONDS));
+
+ final CountDownLatch associatedResourceLatch1 = new CountDownLatch(1);
+ Headers associatedRequestHeaders1 = createHeaders(cssResource);
+ session1.syn(new SynInfo(associatedRequestHeaders1, true), new StreamFrameListener.Adapter()
+ {
+ @Override
+ public void onData(Stream stream, DataInfo dataInfo)
+ {
+ dataInfo.consume(dataInfo.length());
+ if (dataInfo.isClose())
+ associatedResourceLatch1.countDown();
+ }
+ });
+ Assert.assertTrue(associatedResourceLatch1.await(5, TimeUnit.SECONDS));
+ return session1;
+ }
+
+
+ private void sendJSRequest(Session session1) throws InterruptedException
+ {
+ final CountDownLatch associatedResourceLatch2 = new CountDownLatch(1);
+ String jsResource = "/application.js";
+ Headers associatedRequestHeaders2 = createHeaders(jsResource);
+ session1.syn(new SynInfo(associatedRequestHeaders2, true), new StreamFrameListener.Adapter()
+ {
+ @Override
+ public void onData(Stream stream, DataInfo dataInfo)
+ {
+ dataInfo.consume(dataInfo.length());
+ if (dataInfo.isClose())
+ associatedResourceLatch2.countDown();
+ }
+ });
+ Assert.assertTrue(associatedResourceLatch2.await(5, TimeUnit.SECONDS));
+ }
+
+ private void run2ndClientRequests(InetSocketAddress address, Headers mainRequestHeaders, final boolean validateHeaders) throws Exception
+ {
+ // Create another client, and perform the same request for the main resource,
+ // we expect the css being pushed, but not the js
+
+ final CountDownLatch mainStreamLatch = new CountDownLatch(2);
+ final CountDownLatch pushDataLatch = new CountDownLatch(1);
+ final CountDownLatch pushSynHeadersValid = new CountDownLatch(1);
+ Session session2 = startClient(version(), address, new SessionFrameListener.Adapter()
+ {
+ @Override
+ public StreamFrameListener onSyn(Stream stream, SynInfo synInfo)
+ {
+ if(validateHeaders)
+ validateHeaders(synInfo.getHeaders(), pushSynHeadersValid);
+
+ Assert.assertTrue(stream.isUnidirectional());
+ Assert.assertTrue(synInfo.getHeaders().get(HTTPSPDYHeader.URI.name(version())).value().endsWith(".css"));
+ return new StreamFrameListener.Adapter()
+ {
+ @Override
+ public void onData(Stream stream, DataInfo dataInfo)
+ {
+
+ dataInfo.consume(dataInfo.length());
+ if (dataInfo.isClose())
+ pushDataLatch.countDown();
+ }
+ };
+ }
+ });
+ session2.syn(new SynInfo(mainRequestHeaders, true), new StreamFrameListener.Adapter()
+ {
+ @Override
+ public void onReply(Stream stream, ReplyInfo replyInfo)
+ {
+ Assert.assertFalse(replyInfo.isClose());
+ mainStreamLatch.countDown();
+ }
+
+ @Override
+ public void onData(Stream stream, DataInfo dataInfo)
+ {
+ dataInfo.consume(dataInfo.length());
+ if (dataInfo.isClose())
+ mainStreamLatch.countDown();
+ }
+ });
+
+ Assert.assertTrue("Main request reply and/or data not received", mainStreamLatch.await(5, TimeUnit.SECONDS));
+ Assert.assertTrue("Pushed data not received", pushDataLatch.await(5, TimeUnit.SECONDS));
+ if(validateHeaders)
+ Assert.assertTrue("Push syn headers not valid", pushSynHeadersValid.await(5, TimeUnit.SECONDS));
+ }
+
+ @Test
+ public void testAssociatedResourceIsPushed() throws Exception
+ {
+ InetSocketAddress address = startHTTPServer(version(), new AbstractHandler()
+ {
+ @Override
+ public void handle(String target, Request baseRequest, HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException
+ {
+ String url = request.getRequestURI();
+ PrintWriter output = response.getWriter();
+ if (url.endsWith(".html"))
+ output.print("<html><head/><body>HELLO</body></html>");
+ else if (url.endsWith(".css"))
+ output.print("body { background: #FFF; }");
+ baseRequest.setHandled(true);
+ }
+ });
+ Session session1 = startClient(version(), address, null);
+
+ final CountDownLatch mainResourceLatch = new CountDownLatch(1);
+ Headers mainRequestHeaders = createHeadersWithoutReferrer(mainResource);
+
+ session1.syn(new SynInfo(mainRequestHeaders, true), new StreamFrameListener.Adapter()
+ {
+ @Override
+ public void onData(Stream stream, DataInfo dataInfo)
+ {
+ dataInfo.consume(dataInfo.length());
+ if (dataInfo.isClose())
+ mainResourceLatch.countDown();
+ }
+ });
+ Assert.assertTrue(mainResourceLatch.await(5, TimeUnit.SECONDS));
+
+ final CountDownLatch associatedResourceLatch = new CountDownLatch(1);
+ Headers associatedRequestHeaders = createHeaders(cssResource);
+ session1.syn(new SynInfo(associatedRequestHeaders, true), new StreamFrameListener.Adapter()
+ {
+ @Override
+ public void onData(Stream stream, DataInfo dataInfo)
+ {
+ dataInfo.consume(dataInfo.length());
+ if (dataInfo.isClose())
+ associatedResourceLatch.countDown();
+ }
+ });
+ Assert.assertTrue(associatedResourceLatch.await(5, TimeUnit.SECONDS));
+
+ // Create another client, and perform the same request for the main resource, we expect the css being pushed
+
+ final CountDownLatch mainStreamLatch = new CountDownLatch(2);
+ final CountDownLatch pushDataLatch = new CountDownLatch(1);
+ Session session2 = startClient(version(), address, new SessionFrameListener.Adapter()
+ {
+ @Override
+ public StreamFrameListener onSyn(Stream stream, SynInfo synInfo)
+ {
+ Assert.assertTrue(stream.isUnidirectional());
+ return new StreamFrameListener.Adapter()
+ {
+ @Override
+ public void onData(Stream stream, DataInfo dataInfo)
+ {
+ dataInfo.consume(dataInfo.length());
+ if (dataInfo.isClose())
+ pushDataLatch.countDown();
+ }
+ };
+ }
+ });
+ session2.syn(new SynInfo(mainRequestHeaders, true), new StreamFrameListener.Adapter()
+ {
+ @Override
+ public void onReply(Stream stream, ReplyInfo replyInfo)
+ {
+ Assert.assertFalse(replyInfo.isClose());
+ mainStreamLatch.countDown();
+ }
+
+ @Override
+ public void onData(Stream stream, DataInfo dataInfo)
+ {
+ dataInfo.consume(dataInfo.length());
+ if (dataInfo.isClose())
+ mainStreamLatch.countDown();
+ }
+ });
+
+ Assert.assertTrue(mainStreamLatch.await(5, TimeUnit.SECONDS));
+ Assert.assertTrue(pushDataLatch.await(5, TimeUnit.SECONDS));
+ }
+
+ @Test
+ public void testAssociatedResourceWithWrongContentTypeIsNotPushed() throws Exception
+ {
+ final String fakeResource = "/fake.png";
+ InetSocketAddress address = startHTTPServer(version(), new AbstractHandler()
+ {
+ @Override
+ public void handle(String target, Request baseRequest, HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException
+ {
+ String url = request.getRequestURI();
+ PrintWriter output = response.getWriter();
+ if (url.endsWith(".html"))
+ {
+ response.setContentType("text/html");
+ output.print("<html><head/><body>HELLO</body></html>");
+ }
+ else if (url.equals(fakeResource))
+ {
+ response.setContentType("text/html");
+ output.print("<html><head/><body>IMAGE</body></html>");
+ }
+ else if (url.endsWith(".css"))
+ {
+ response.setContentType("text/css");
+ output.print("body { background: #FFF; }");
+ }
+ baseRequest.setHandled(true);
+ }
+ });
+ Session session1 = startClient(version(), address, null);
+
+ final CountDownLatch mainResourceLatch = new CountDownLatch(1);
+ Headers mainRequestHeaders = createHeadersWithoutReferrer(mainResource);
+
+ session1.syn(new SynInfo(mainRequestHeaders, true), new StreamFrameListener.Adapter()
+ {
+ @Override
+ public void onData(Stream stream, DataInfo dataInfo)
+ {
+ dataInfo.consume(dataInfo.length());
+ if (dataInfo.isClose())
+ mainResourceLatch.countDown();
+ }
+ });
+ Assert.assertTrue(mainResourceLatch.await(5, TimeUnit.SECONDS));
+
+ final CountDownLatch associatedResourceLatch = new CountDownLatch(1);
+ String cssResource = "/stylesheet.css";
+ Headers associatedRequestHeaders = createHeaders(cssResource);
+ session1.syn(new SynInfo(associatedRequestHeaders, true), new StreamFrameListener.Adapter()
+ {
+ @Override
+ public void onData(Stream stream, DataInfo dataInfo)
+ {
+ dataInfo.consume(dataInfo.length());
+ if (dataInfo.isClose())
+ associatedResourceLatch.countDown();
+ }
+ });
+ Assert.assertTrue(associatedResourceLatch.await(5, TimeUnit.SECONDS));
+
+ final CountDownLatch fakeAssociatedResourceLatch = new CountDownLatch(1);
+ Headers fakeAssociatedRequestHeaders = createHeaders(fakeResource);
+ session1.syn(new SynInfo(fakeAssociatedRequestHeaders, true), new StreamFrameListener.Adapter()
+ {
+ @Override
+ public void onData(Stream stream, DataInfo dataInfo)
+ {
+ dataInfo.consume(dataInfo.length());
+ if (dataInfo.isClose())
+ fakeAssociatedResourceLatch.countDown();
+ }
+ });
+ Assert.assertTrue(fakeAssociatedResourceLatch.await(5, TimeUnit.SECONDS));
+
+ // Create another client, and perform the same request for the main resource,
+ // we expect the css being pushed but not the fake PNG
+
+ final CountDownLatch mainStreamLatch = new CountDownLatch(2);
+ final CountDownLatch pushDataLatch = new CountDownLatch(1);
+ Session session2 = startClient(version(), address, new SessionFrameListener.Adapter()
+ {
+ @Override
+ public StreamFrameListener onSyn(Stream stream, SynInfo synInfo)
+ {
+ Assert.assertTrue(stream.isUnidirectional());
+ Assert.assertTrue(synInfo.getHeaders().get(HTTPSPDYHeader.URI.name(version())).value().endsWith(".css"));
+ return new StreamFrameListener.Adapter()
+ {
+ @Override
+ public void onData(Stream stream, DataInfo dataInfo)
+ {
+ dataInfo.consume(dataInfo.length());
+ if (dataInfo.isClose())
+ pushDataLatch.countDown();
+ }
+ };
+ }
+ });
+ session2.syn(new SynInfo(mainRequestHeaders, true), new StreamFrameListener.Adapter()
+ {
+ @Override
+ public void onReply(Stream stream, ReplyInfo replyInfo)
+ {
+ Assert.assertFalse(replyInfo.isClose());
+ mainStreamLatch.countDown();
+ }
+
+ @Override
+ public void onData(Stream stream, DataInfo dataInfo)
+ {
+ dataInfo.consume(dataInfo.length());
+ if (dataInfo.isClose())
+ mainStreamLatch.countDown();
+ }
+ });
+
+ Assert.assertTrue(mainStreamLatch.await(5, TimeUnit.SECONDS));
+ Assert.assertTrue(pushDataLatch.await(5, TimeUnit.SECONDS));
+ }
+
+ @Test
+ public void testNestedAssociatedResourceIsPushed() throws Exception
+ {
+ InetSocketAddress address = startHTTPServer(version(), new AbstractHandler()
+ {
+ @Override
+ public void handle(String target, Request baseRequest, HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException
+ {
+ String url = request.getRequestURI();
+ PrintWriter output = response.getWriter();
+ if (url.endsWith(".html"))
+ output.print("<html><head/><body>HELLO</body></html>");
+ else if (url.endsWith(".css"))
+ output.print("body { background: #FFF; }");
+ else if (url.endsWith(".gif"))
+ output.print("\u0000");
+ baseRequest.setHandled(true);
+ }
+ });
+ Session session1 = startClient(version(), address, null);
+
+ final CountDownLatch mainResourceLatch = new CountDownLatch(1);
+ Headers mainRequestHeaders = createHeadersWithoutReferrer(mainResource);
+
+ session1.syn(new SynInfo(mainRequestHeaders, true), new StreamFrameListener.Adapter()
+ {
+ @Override
+ public void onData(Stream stream, DataInfo dataInfo)
+ {
+ dataInfo.consume(dataInfo.length());
+ if (dataInfo.isClose())
+ mainResourceLatch.countDown();
+ }
+ });
+ Assert.assertTrue(mainResourceLatch.await(5, TimeUnit.SECONDS));
+
+ final CountDownLatch associatedResourceLatch = new CountDownLatch(1);
+ Headers associatedRequestHeaders = createHeaders(cssResource);
+ session1.syn(new SynInfo(associatedRequestHeaders, true), new StreamFrameListener.Adapter()
+ {
+ @Override
+ public void onData(Stream stream, DataInfo dataInfo)
+ {
+ dataInfo.consume(dataInfo.length());
+ if (dataInfo.isClose())
+ associatedResourceLatch.countDown();
+ }
+ });
+ Assert.assertTrue(associatedResourceLatch.await(5, TimeUnit.SECONDS));
+
+ final CountDownLatch nestedResourceLatch = new CountDownLatch(1);
+ String imageUrl = "/image.gif";
+ Headers nestedRequestHeaders = createHeaders(imageUrl, cssResource);
+
+ session1.syn(new SynInfo(nestedRequestHeaders, true), new StreamFrameListener.Adapter()
+ {
+ @Override
+ public void onData(Stream stream, DataInfo dataInfo)
+ {
+ dataInfo.consume(dataInfo.length());
+ if (dataInfo.isClose())
+ nestedResourceLatch.countDown();
+ }
+ });
+ Assert.assertTrue(nestedResourceLatch.await(5, TimeUnit.SECONDS));
+
+ // Create another client, and perform the same request for the main resource, we expect the css and the image being pushed
+
+ final CountDownLatch mainStreamLatch = new CountDownLatch(2);
+ final CountDownLatch pushDataLatch = new CountDownLatch(2);
+ Session session2 = startClient(version(), address, new SessionFrameListener.Adapter()
+ {
+ @Override
+ public StreamFrameListener onSyn(Stream stream, SynInfo synInfo)
+ {
+ Assert.assertTrue(stream.isUnidirectional());
+ return new StreamFrameListener.Adapter()
+ {
+ @Override
+ public void onData(Stream stream, DataInfo dataInfo)
+ {
+ dataInfo.consume(dataInfo.length());
+ if (dataInfo.isClose())
+ pushDataLatch.countDown();
+ }
+ };
+ }
+ });
+ session2.syn(new SynInfo(mainRequestHeaders, true), new StreamFrameListener.Adapter()
+ {
+ @Override
+ public void onReply(Stream stream, ReplyInfo replyInfo)
+ {
+ Assert.assertFalse(replyInfo.isClose());
+ mainStreamLatch.countDown();
+ }
+
+ @Override
+ public void onData(Stream stream, DataInfo dataInfo)
+ {
+ dataInfo.consume(dataInfo.length());
+ if (dataInfo.isClose())
+ mainStreamLatch.countDown();
+ }
+ });
+
+ Assert.assertTrue(mainStreamLatch.await(5, TimeUnit.SECONDS));
+ Assert.assertTrue(pushDataLatch.await(5, TimeUnit.SECONDS));
+ }
+
+ @Test
+ public void testMainResourceWithReferrerIsNotPushed() throws Exception
+ {
+ InetSocketAddress address = startHTTPServer(version(), new AbstractHandler()
+ {
+ @Override
+ public void handle(String target, Request baseRequest, HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException
+ {
+ String url = request.getRequestURI();
+ PrintWriter output = response.getWriter();
+ if (url.endsWith(".html"))
+ output.print("<html><head/><body>HELLO</body></html>");
+ baseRequest.setHandled(true);
+ }
+ });
+ Session session1 = startClient(version(), address, null);
+
+ final CountDownLatch mainResourceLatch = new CountDownLatch(1);
+ Headers mainRequestHeaders = createHeadersWithoutReferrer(mainResource);
+
+ session1.syn(new SynInfo(mainRequestHeaders, true), new StreamFrameListener.Adapter()
+ {
+ @Override
+ public void onData(Stream stream, DataInfo dataInfo)
+ {
+ dataInfo.consume(dataInfo.length());
+ if (dataInfo.isClose())
+ mainResourceLatch.countDown();
+ }
+ });
+ Assert.assertTrue(mainResourceLatch.await(5, TimeUnit.SECONDS));
+
+ final CountDownLatch associatedResourceLatch = new CountDownLatch(1);
+ String associatedResource = "/home.html";
+ Headers associatedRequestHeaders = createHeaders(associatedResource);
+
+ session1.syn(new SynInfo(associatedRequestHeaders, true), new StreamFrameListener.Adapter()
+ {
+ @Override
+ public void onData(Stream stream, DataInfo dataInfo)
+ {
+ dataInfo.consume(dataInfo.length());
+ if (dataInfo.isClose())
+ associatedResourceLatch.countDown();
+ }
+ });
+ Assert.assertTrue(associatedResourceLatch.await(5, TimeUnit.SECONDS));
+
+ // Create another client, and perform the same request for the main resource, we expect nothing being pushed
+
+ final CountDownLatch mainStreamLatch = new CountDownLatch(2);
+ final CountDownLatch pushLatch = new CountDownLatch(1);
+ Session session2 = startClient(version(), address, new SessionFrameListener.Adapter()
+ {
+ @Override
+ public StreamFrameListener onSyn(Stream stream, SynInfo synInfo)
+ {
+ pushLatch.countDown();
+ return null;
+ }
+ });
+ session2.syn(new SynInfo(mainRequestHeaders, true), new StreamFrameListener.Adapter()
+ {
+ @Override
+ public void onReply(Stream stream, ReplyInfo replyInfo)
+ {
+ Assert.assertFalse(replyInfo.isClose());
+ mainStreamLatch.countDown();
+ }
+
+ @Override
+ public void onData(Stream stream, DataInfo dataInfo)
+ {
+ dataInfo.consume(dataInfo.length());
+ if (dataInfo.isClose())
+ mainStreamLatch.countDown();
+ }
+ });
+
+ Assert.assertTrue(mainStreamLatch.await(5, TimeUnit.SECONDS));
+ Assert.assertFalse(pushLatch.await(1, TimeUnit.SECONDS));
+ }
+
+ @Test
+ public void testRequestWithIfModifiedSinceHeaderPreventsPush() throws Exception
+ {
+ InetSocketAddress address = startHTTPServer(version(), new AbstractHandler()
+ {
+ @Override
+ public void handle(String target, Request baseRequest, HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException
+ {
+ String url = request.getRequestURI();
+ PrintWriter output = response.getWriter();
+ if (url.endsWith(".html"))
+ output.print("<html><head/><body>HELLO</body></html>");
+ else if (url.endsWith(".css"))
+ output.print("body { background: #FFF; }");
+ baseRequest.setHandled(true);
+ }
+ });
+ Session session1 = startClient(version(), address, null);
+
+ final CountDownLatch mainResourceLatch = new CountDownLatch(1);
+ Headers mainRequestHeaders = createHeaders(mainResource);
+ mainRequestHeaders.put("If-Modified-Since", "Tue, 27 Mar 2012 16:36:52 GMT");
+ session1.syn(new SynInfo(mainRequestHeaders, true), new StreamFrameListener.Adapter()
+ {
+ @Override
+ public void onData(Stream stream, DataInfo dataInfo)
+ {
+ dataInfo.consume(dataInfo.length());
+ if (dataInfo.isClose())
+ mainResourceLatch.countDown();
+ }
+ });
+ Assert.assertTrue(mainResourceLatch.await(5, TimeUnit.SECONDS));
+
+ final CountDownLatch associatedResourceLatch = new CountDownLatch(1);
+ Headers associatedRequestHeaders = createHeaders(cssResource);
+ session1.syn(new SynInfo(associatedRequestHeaders, true), new StreamFrameListener.Adapter()
+ {
+ @Override
+ public void onData(Stream stream, DataInfo dataInfo)
+ {
+ dataInfo.consume(dataInfo.length());
+ if (dataInfo.isClose())
+ associatedResourceLatch.countDown();
+ }
+ });
+ Assert.assertTrue(associatedResourceLatch.await(5, TimeUnit.SECONDS));
+
+ // Create another client, and perform the same request for the main resource, we expect the css NOT being pushed as the main request contains an
+ // if-modified-since header
+
+ final CountDownLatch mainStreamLatch = new CountDownLatch(2);
+ final CountDownLatch pushDataLatch = new CountDownLatch(1);
+ Session session2 = startClient(version(), address, new SessionFrameListener.Adapter()
+ {
+ @Override
+ public StreamFrameListener onSyn(Stream stream, SynInfo synInfo)
+ {
+ Assert.assertTrue(stream.isUnidirectional());
+ return new StreamFrameListener.Adapter()
+ {
+ @Override
+ public void onData(Stream stream, DataInfo dataInfo)
+ {
+ dataInfo.consume(dataInfo.length());
+ if (dataInfo.isClose())
+ pushDataLatch.countDown();
+ }
+ };
+ }
+ });
+ session2.syn(new SynInfo(mainRequestHeaders, true), new StreamFrameListener.Adapter()
+ {
+ @Override
+ public void onReply(Stream stream, ReplyInfo replyInfo)
+ {
+ Assert.assertFalse(replyInfo.isClose());
+ mainStreamLatch.countDown();
+ }
+
+ @Override
+ public void onData(Stream stream, DataInfo dataInfo)
+ {
+ dataInfo.consume(dataInfo.length());
+ if (dataInfo.isClose())
+ mainStreamLatch.countDown();
+ }
+ });
+
+ Assert.assertTrue(mainStreamLatch.await(5, TimeUnit.SECONDS));
+ Assert.assertFalse("We don't expect data to be pushed as the main request contained an if-modified-since header",pushDataLatch.await(1, TimeUnit.SECONDS));
+ }
+
+ private void validateHeaders(Headers headers, CountDownLatch pushSynHeadersValid)
+ {
+ if (validateHeader(headers, HTTPSPDYHeader.STATUS.name(version()), "200")
+ && validateHeader(headers, HTTPSPDYHeader.VERSION.name(version()), "HTTP/1.1")
+ && validateUriHeader(headers))
+ pushSynHeadersValid.countDown();
+ }
+
+ private boolean validateHeader(Headers headers, String name, String expectedValue)
+ {
+ Headers.Header header = headers.get(name);
+ if (header != null && expectedValue.equals(header.value()))
+ return true;
+ System.out.println(name + " not valid! " + headers);
+ return false;
+ }
+
+ private boolean validateUriHeader(Headers headers)
+ {
+ Headers.Header uriHeader = headers.get(HTTPSPDYHeader.URI.name(version()));
+ if (uriHeader != null)
+ if (version() == SPDY.V2 && uriHeader.value().startsWith("http://"))
+ return true;
+ else if (version() == SPDY.V3 && uriHeader.value().startsWith("/")
+ && headers.get(HTTPSPDYHeader.HOST.name(version())) != null && headers.get(HTTPSPDYHeader.SCHEME.name(version())) != null)
+ return true;
+ System.out.println(HTTPSPDYHeader.URI.name(version()) + " not valid!");
+ return false;
+ }
+
+ private Headers createHeaders(String resource)
+ {
+ return createHeaders(resource, mainResource);
+ }
+
+ private Headers createHeaders(String resource, String referrer)
+ {
+ Headers associatedRequestHeaders = createHeadersWithoutReferrer(resource);
+ associatedRequestHeaders.put("referer", "http://localhost:" + connector.getLocalPort() + referrer);
+ return associatedRequestHeaders;
+ }
+
+ private Headers createHeadersWithoutReferrer(String resource)
+ {
+ Headers associatedRequestHeaders = new Headers();
+ associatedRequestHeaders.put(HTTPSPDYHeader.METHOD.name(version()), "GET");
+ associatedRequestHeaders.put(HTTPSPDYHeader.URI.name(version()), resource);
+ associatedRequestHeaders.put(HTTPSPDYHeader.VERSION.name(version()), "HTTP/1.1");
+ associatedRequestHeaders.put(HTTPSPDYHeader.SCHEME.name(version()), "http");
+ associatedRequestHeaders.put(HTTPSPDYHeader.HOST.name(version()), "localhost:" + connector.getLocalPort());
+ return associatedRequestHeaders;
+ }
+}
diff --git a/jetty-spdy/spdy-jetty-http/src/test/java/org/eclipse/jetty/spdy/http/ReferrerPushStrategyV3Test.java b/jetty-spdy/spdy-jetty-http/src/test/java/org/eclipse/jetty/spdy/http/ReferrerPushStrategyV3Test.java
new file mode 100644
index 0000000000..2b637cb2cd
--- /dev/null
+++ b/jetty-spdy/spdy-jetty-http/src/test/java/org/eclipse/jetty/spdy/http/ReferrerPushStrategyV3Test.java
@@ -0,0 +1,26 @@
+//========================================================================
+//Copyright 2011-2012 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.spdy.http;
+
+import org.eclipse.jetty.spdy.api.SPDY;
+
+public class ReferrerPushStrategyV3Test extends ReferrerPushStrategyV2Test
+{
+ @Override
+ protected short version()
+ {
+ return SPDY.V3;
+ }
+}
diff --git a/jetty-spdy/spdy-jetty-http/src/test/java/org/eclipse/jetty/spdy/http/SSLExternalServerTest.java b/jetty-spdy/spdy-jetty-http/src/test/java/org/eclipse/jetty/spdy/http/SSLExternalServerTest.java
new file mode 100644
index 0000000000..42bd5be8fd
--- /dev/null
+++ b/jetty-spdy/spdy-jetty-http/src/test/java/org/eclipse/jetty/spdy/http/SSLExternalServerTest.java
@@ -0,0 +1,94 @@
+//========================================================================
+//Copyright 2011-2012 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.spdy.http;
+
+import java.io.IOException;
+import java.net.InetSocketAddress;
+import java.net.Socket;
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.Executor;
+import java.util.concurrent.TimeUnit;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+import org.eclipse.jetty.spdy.SPDYClient;
+import org.eclipse.jetty.spdy.api.Headers;
+import org.eclipse.jetty.spdy.api.ReplyInfo;
+import org.eclipse.jetty.spdy.api.SPDY;
+import org.eclipse.jetty.spdy.api.Session;
+import org.eclipse.jetty.spdy.api.Stream;
+import org.eclipse.jetty.spdy.api.StreamFrameListener;
+import org.eclipse.jetty.spdy.api.SynInfo;
+import org.eclipse.jetty.util.ssl.SslContextFactory;
+import org.junit.Assert;
+import org.junit.Assume;
+import org.junit.Test;
+
+public class SSLExternalServerTest extends AbstractHTTPSPDYTest
+{
+ @Override
+ protected SPDYClient.Factory newSPDYClientFactory(Executor threadPool)
+ {
+ SslContextFactory sslContextFactory = new SslContextFactory();
+ // Force TLSv1
+ sslContextFactory.setIncludeProtocols("TLSv1");
+ return new SPDYClient.Factory(threadPool, sslContextFactory);
+ }
+
+ @Test
+ public void testExternalServer() throws Exception
+ {
+ String host = "encrypted.google.com";
+ int port = 443;
+ InetSocketAddress address = new InetSocketAddress(host, port);
+
+ try
+ {
+ // Test whether there is connectivity to avoid fail the test when offline
+ Socket socket = new Socket();
+ socket.connect(address, 5000);
+ socket.close();
+ }
+ catch (IOException x)
+ {
+ Assume.assumeNoException(x);
+ }
+
+ final short version = SPDY.V2;
+ Session session = startClient(version, address, null);
+ Headers headers = new Headers();
+ headers.put(HTTPSPDYHeader.SCHEME.name(version), "https");
+ headers.put(HTTPSPDYHeader.HOST.name(version), host + ":" + port);
+ headers.put(HTTPSPDYHeader.METHOD.name(version), "GET");
+ headers.put(HTTPSPDYHeader.URI.name(version), "/");
+ headers.put(HTTPSPDYHeader.VERSION.name(version), "HTTP/1.1");
+ final CountDownLatch latch = new CountDownLatch(1);
+ session.syn(new SynInfo(headers, true), new StreamFrameListener.Adapter()
+ {
+ @Override
+ public void onReply(Stream stream, ReplyInfo replyInfo)
+ {
+ Headers headers = replyInfo.getHeaders();
+ Headers.Header versionHeader = headers.get(HTTPSPDYHeader.STATUS.name(version));
+ if (versionHeader != null)
+ {
+ Matcher matcher = Pattern.compile("(\\d{3}).*").matcher(versionHeader.value());
+ if (matcher.matches() && Integer.parseInt(matcher.group(1)) < 400)
+ latch.countDown();
+ }
+ }
+ });
+ Assert.assertTrue(latch.await(5, TimeUnit.SECONDS));
+ }
+}
diff --git a/jetty-spdy/spdy-jetty-http/src/test/java/org/eclipse/jetty/spdy/http/ServerHTTPSPDYTest.java b/jetty-spdy/spdy-jetty-http/src/test/java/org/eclipse/jetty/spdy/http/ServerHTTPSPDYv2Test.java
index 8b0c85e54a..5bab1f512e 100644
--- a/jetty-spdy/spdy-jetty-http/src/test/java/org/eclipse/jetty/spdy/http/ServerHTTPSPDYTest.java
+++ b/jetty-spdy/spdy-jetty-http/src/test/java/org/eclipse/jetty/spdy/http/ServerHTTPSPDYv2Test.java
@@ -1,21 +1,20 @@
-/*
- * Copyright (c) 2012 the original author or authors.
- *
- * 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.
- */
+//========================================================================
+//Copyright 2011-2012 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.spdy.http;
+import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
@@ -48,14 +47,14 @@ import org.eclipse.jetty.spdy.api.SynInfo;
import org.junit.Assert;
import org.junit.Test;
-public class ServerHTTPSPDYTest extends AbstractHTTPSPDYTest
+public class ServerHTTPSPDYv2Test extends AbstractHTTPSPDYTest
{
@Test
public void testSimpleGET() throws Exception
{
final String path = "/foo";
final CountDownLatch handlerLatch = new CountDownLatch(1);
- Session session = startClient(startHTTPServer(new AbstractHandler()
+ Session session = startClient(version(), startHTTPServer(version(), new AbstractHandler()
{
@Override
public void handle(String target, Request request, HttpServletRequest httpRequest, HttpServletResponse httpResponse)
@@ -71,11 +70,11 @@ public class ServerHTTPSPDYTest extends AbstractHTTPSPDYTest
}), null);
Headers headers = new Headers();
- headers.put("method", "GET");
- headers.put("url", path);
- headers.put("version", "HTTP/1.1");
- headers.put("scheme", "http");
- headers.put("host", "localhost:" + connector.getLocalPort());
+ headers.put(HTTPSPDYHeader.METHOD.name(version()), "GET");
+ headers.put(HTTPSPDYHeader.URI.name(version()), path);
+ headers.put(HTTPSPDYHeader.VERSION.name(version()), "HTTP/1.1");
+ headers.put(HTTPSPDYHeader.SCHEME.name(version()), "http");
+ headers.put(HTTPSPDYHeader.HOST.name(version()), "localhost:" + connector.getLocalPort());
final CountDownLatch replyLatch = new CountDownLatch(1);
session.syn(new SynInfo(headers, true), new StreamFrameListener.Adapter()
{
@@ -84,7 +83,7 @@ public class ServerHTTPSPDYTest extends AbstractHTTPSPDYTest
{
Assert.assertTrue(replyInfo.isClose());
Headers replyHeaders = replyInfo.getHeaders();
- Assert.assertTrue(replyHeaders.get("status").value().contains("200"));
+ Assert.assertTrue(replyHeaders.get(HTTPSPDYHeader.STATUS.name(version())).value().contains("200"));
replyLatch.countDown();
}
});
@@ -99,7 +98,7 @@ public class ServerHTTPSPDYTest extends AbstractHTTPSPDYTest
final String query = "p=1";
final String uri = path + "?" + query;
final CountDownLatch handlerLatch = new CountDownLatch(1);
- Session session = startClient(startHTTPServer(new AbstractHandler()
+ Session session = startClient(version(), startHTTPServer(version(), new AbstractHandler()
{
@Override
public void handle(String target, Request request, HttpServletRequest httpRequest, HttpServletResponse httpResponse)
@@ -115,11 +114,11 @@ public class ServerHTTPSPDYTest extends AbstractHTTPSPDYTest
}), null);
Headers headers = new Headers();
- headers.put("method", "GET");
- headers.put("url", uri);
- headers.put("version", "HTTP/1.1");
- headers.put("scheme", "http");
- headers.put("host", "localhost:" + connector.getLocalPort());
+ headers.put(HTTPSPDYHeader.METHOD.name(version()), "GET");
+ headers.put(HTTPSPDYHeader.URI.name(version()), uri);
+ headers.put(HTTPSPDYHeader.VERSION.name(version()), "HTTP/1.1");
+ headers.put(HTTPSPDYHeader.SCHEME.name(version()), "http");
+ headers.put(HTTPSPDYHeader.HOST.name(version()), "localhost:" + connector.getLocalPort());
final CountDownLatch replyLatch = new CountDownLatch(1);
session.syn(new SynInfo(headers, true), new StreamFrameListener.Adapter()
{
@@ -128,7 +127,7 @@ public class ServerHTTPSPDYTest extends AbstractHTTPSPDYTest
{
Assert.assertTrue(replyInfo.isClose());
Headers replyHeaders = replyInfo.getHeaders();
- Assert.assertTrue(replyHeaders.get("status").value().contains("200"));
+ Assert.assertTrue(replyHeaders.get(HTTPSPDYHeader.STATUS.name(version())).value().contains("200"));
replyLatch.countDown();
}
});
@@ -141,7 +140,7 @@ public class ServerHTTPSPDYTest extends AbstractHTTPSPDYTest
{
final String path = "/foo";
final CountDownLatch handlerLatch = new CountDownLatch(1);
- Session session = startClient(startHTTPServer(new AbstractHandler()
+ Session session = startClient(version(), startHTTPServer(version(), new AbstractHandler()
{
@Override
public void handle(String target, Request request, HttpServletRequest httpRequest, HttpServletResponse httpResponse)
@@ -156,11 +155,11 @@ public class ServerHTTPSPDYTest extends AbstractHTTPSPDYTest
}), null);
Headers headers = new Headers();
- headers.put("method", "HEAD");
- headers.put("url", path);
- headers.put("version", "HTTP/1.1");
- headers.put("scheme", "http");
- headers.put("host", "localhost:" + connector.getLocalPort());
+ headers.put(HTTPSPDYHeader.METHOD.name(version()), "HEAD");
+ headers.put(HTTPSPDYHeader.URI.name(version()), path);
+ headers.put(HTTPSPDYHeader.VERSION.name(version()), "HTTP/1.1");
+ headers.put(HTTPSPDYHeader.SCHEME.name(version()), "http");
+ headers.put(HTTPSPDYHeader.HOST.name(version()), "localhost:" + connector.getLocalPort());
final CountDownLatch replyLatch = new CountDownLatch(1);
session.syn(new SynInfo(headers, true), new StreamFrameListener.Adapter()
{
@@ -169,7 +168,7 @@ public class ServerHTTPSPDYTest extends AbstractHTTPSPDYTest
{
Assert.assertTrue(replyInfo.isClose());
Headers replyHeaders = replyInfo.getHeaders();
- Assert.assertTrue(replyHeaders.get("status").value().contains("200"));
+ Assert.assertTrue(replyHeaders.get(HTTPSPDYHeader.STATUS.name(version())).value().contains("200"));
replyLatch.countDown();
}
});
@@ -183,7 +182,7 @@ public class ServerHTTPSPDYTest extends AbstractHTTPSPDYTest
final String path = "/foo";
final String data = "a=1&b=2";
final CountDownLatch handlerLatch = new CountDownLatch(1);
- Session session = startClient(startHTTPServer(new AbstractHandler()
+ Session session = startClient(version(), startHTTPServer(version(), new AbstractHandler()
{
@Override
public void handle(String target, Request request, HttpServletRequest httpRequest, HttpServletResponse httpResponse)
@@ -206,11 +205,11 @@ public class ServerHTTPSPDYTest extends AbstractHTTPSPDYTest
}), null);
Headers headers = new Headers();
- headers.put("method", "POST");
- headers.put("url", path);
- headers.put("version", "HTTP/1.1");
- headers.put("scheme", "http");
- headers.put("host", "localhost:" + connector.getLocalPort());
+ headers.put(HTTPSPDYHeader.METHOD.name(version()), "POST");
+ headers.put(HTTPSPDYHeader.URI.name(version()), path);
+ headers.put(HTTPSPDYHeader.VERSION.name(version()), "HTTP/1.1");
+ headers.put(HTTPSPDYHeader.SCHEME.name(version()), "http");
+ headers.put(HTTPSPDYHeader.HOST.name(version()), "localhost:" + connector.getLocalPort());
headers.put("content-type", "application/x-www-form-urlencoded");
final CountDownLatch replyLatch = new CountDownLatch(1);
Stream stream = session.syn(new SynInfo(headers, false), new StreamFrameListener.Adapter()
@@ -220,7 +219,7 @@ public class ServerHTTPSPDYTest extends AbstractHTTPSPDYTest
{
Assert.assertTrue(replyInfo.isClose());
Headers replyHeaders = replyInfo.getHeaders();
- Assert.assertTrue(replyHeaders.get("status").value().contains("200"));
+ Assert.assertTrue(replyHeaders.get(HTTPSPDYHeader.STATUS.name(version())).value().contains("200"));
replyLatch.countDown();
}
}).get(5, TimeUnit.SECONDS);
@@ -237,7 +236,7 @@ public class ServerHTTPSPDYTest extends AbstractHTTPSPDYTest
final String data1 = "a=1&";
final String data2 = "b=2";
final CountDownLatch handlerLatch = new CountDownLatch(1);
- Session session = startClient(startHTTPServer(new AbstractHandler()
+ Session session = startClient(version(), startHTTPServer(version(), new AbstractHandler()
{
@Override
public void handle(String target, Request request, HttpServletRequest httpRequest, HttpServletResponse httpResponse)
@@ -252,11 +251,11 @@ public class ServerHTTPSPDYTest extends AbstractHTTPSPDYTest
}), null);
Headers headers = new Headers();
- headers.put("method", "POST");
- headers.put("url", path);
- headers.put("version", "HTTP/1.1");
- headers.put("scheme", "http");
- headers.put("host", "localhost:" + connector.getLocalPort());
+ headers.put(HTTPSPDYHeader.METHOD.name(version()), "POST");
+ headers.put(HTTPSPDYHeader.URI.name(version()), path);
+ headers.put(HTTPSPDYHeader.VERSION.name(version()), "HTTP/1.1");
+ headers.put(HTTPSPDYHeader.SCHEME.name(version()), "http");
+ headers.put(HTTPSPDYHeader.HOST.name(version()), "localhost:" + connector.getLocalPort());
headers.put("content-type", "application/x-www-form-urlencoded");
final CountDownLatch replyLatch = new CountDownLatch(1);
Stream stream = session.syn(new SynInfo(headers, false), new StreamFrameListener.Adapter()
@@ -266,7 +265,7 @@ public class ServerHTTPSPDYTest extends AbstractHTTPSPDYTest
{
Assert.assertTrue(replyInfo.isClose());
Headers replyHeaders = replyInfo.getHeaders();
- Assert.assertTrue(replyHeaders.get("status").value().contains("200"));
+ Assert.assertTrue(replyHeaders.get(HTTPSPDYHeader.STATUS.name(version())).value().contains("200"));
replyLatch.countDown();
}
}).get(5, TimeUnit.SECONDS);
@@ -286,7 +285,7 @@ public class ServerHTTPSPDYTest extends AbstractHTTPSPDYTest
final String data1 = "a=1&";
final String data2 = "b=2";
final CountDownLatch handlerLatch = new CountDownLatch(1);
- Session session = startClient(startHTTPServer(new AbstractHandler()
+ Session session = startClient(version(), startHTTPServer(version(), new AbstractHandler()
{
@Override
public void handle(String target, Request request, HttpServletRequest httpRequest, HttpServletResponse httpResponse)
@@ -301,11 +300,11 @@ public class ServerHTTPSPDYTest extends AbstractHTTPSPDYTest
}), null);
Headers headers = new Headers();
- headers.put("method", "POST");
- headers.put("url", path);
- headers.put("version", "HTTP/1.1");
- headers.put("scheme", "http");
- headers.put("host", "localhost:" + connector.getLocalPort());
+ headers.put(HTTPSPDYHeader.METHOD.name(version()), "POST");
+ headers.put(HTTPSPDYHeader.URI.name(version()), path);
+ headers.put(HTTPSPDYHeader.VERSION.name(version()), "HTTP/1.1");
+ headers.put(HTTPSPDYHeader.SCHEME.name(version()), "http");
+ headers.put(HTTPSPDYHeader.HOST.name(version()), "localhost:" + connector.getLocalPort());
headers.put("content-type", "application/x-www-form-urlencoded");
final CountDownLatch replyLatch = new CountDownLatch(1);
Stream stream = session.syn(new SynInfo(headers, false), new StreamFrameListener.Adapter()
@@ -315,7 +314,7 @@ public class ServerHTTPSPDYTest extends AbstractHTTPSPDYTest
{
Assert.assertTrue(replyInfo.isClose());
Headers replyHeaders = replyInfo.getHeaders();
- Assert.assertTrue(replyHeaders.toString(), replyHeaders.get("status").value().contains("200"));
+ Assert.assertTrue(replyHeaders.toString(), replyHeaders.get(HTTPSPDYHeader.STATUS.name(version())).value().contains("200"));
replyLatch.countDown();
}
}).get(5, TimeUnit.SECONDS);
@@ -332,7 +331,7 @@ public class ServerHTTPSPDYTest extends AbstractHTTPSPDYTest
{
final String data = "0123456789ABCDEF";
final CountDownLatch handlerLatch = new CountDownLatch(1);
- Session session = startClient(startHTTPServer(new AbstractHandler()
+ Session session = startClient(version(), startHTTPServer(version(), new AbstractHandler()
{
@Override
public void handle(String target, Request request, HttpServletRequest httpRequest, HttpServletResponse httpResponse)
@@ -347,11 +346,11 @@ public class ServerHTTPSPDYTest extends AbstractHTTPSPDYTest
}), null);
Headers headers = new Headers();
- headers.put("method", "GET");
- headers.put("url", "/foo");
- headers.put("version", "HTTP/1.1");
- headers.put("scheme", "http");
- headers.put("host", "localhost:" + connector.getLocalPort());
+ headers.put(HTTPSPDYHeader.METHOD.name(version()), "GET");
+ headers.put(HTTPSPDYHeader.URI.name(version()), "/foo");
+ headers.put(HTTPSPDYHeader.VERSION.name(version()), "HTTP/1.1");
+ headers.put(HTTPSPDYHeader.SCHEME.name(version()), "http");
+ headers.put(HTTPSPDYHeader.HOST.name(version()), "localhost:" + connector.getLocalPort());
final CountDownLatch replyLatch = new CountDownLatch(1);
final CountDownLatch dataLatch = new CountDownLatch(1);
session.syn(new SynInfo(headers, true), new StreamFrameListener.Adapter()
@@ -361,7 +360,7 @@ public class ServerHTTPSPDYTest extends AbstractHTTPSPDYTest
{
Assert.assertFalse(replyInfo.isClose());
Headers replyHeaders = replyInfo.getHeaders();
- Assert.assertTrue(replyHeaders.get("status").value().contains("200"));
+ Assert.assertTrue(replyHeaders.get(HTTPSPDYHeader.STATUS.name(version())).value().contains("200"));
replyLatch.countDown();
}
@@ -383,7 +382,7 @@ public class ServerHTTPSPDYTest extends AbstractHTTPSPDYTest
{
final char data = 'x';
final CountDownLatch handlerLatch = new CountDownLatch(1);
- Session session = startClient(startHTTPServer(new AbstractHandler()
+ Session session = startClient(version(), startHTTPServer(version(), new AbstractHandler()
{
@Override
public void handle(String target, Request request, HttpServletRequest httpRequest, HttpServletResponse httpResponse)
@@ -398,11 +397,11 @@ public class ServerHTTPSPDYTest extends AbstractHTTPSPDYTest
}), null);
Headers headers = new Headers();
- headers.put("method", "GET");
- headers.put("url", "/foo");
- headers.put("version", "HTTP/1.1");
- headers.put("scheme", "http");
- headers.put("host", "localhost:" + connector.getLocalPort());
+ headers.put(HTTPSPDYHeader.METHOD.name(version()), "GET");
+ headers.put(HTTPSPDYHeader.URI.name(version()), "/foo");
+ headers.put(HTTPSPDYHeader.VERSION.name(version()), "HTTP/1.1");
+ headers.put(HTTPSPDYHeader.SCHEME.name(version()), "http");
+ headers.put(HTTPSPDYHeader.HOST.name(version()), "localhost:" + connector.getLocalPort());
final CountDownLatch replyLatch = new CountDownLatch(1);
final CountDownLatch dataLatch = new CountDownLatch(1);
session.syn(new SynInfo(headers, true), new StreamFrameListener.Adapter()
@@ -412,7 +411,7 @@ public class ServerHTTPSPDYTest extends AbstractHTTPSPDYTest
{
Assert.assertFalse(replyInfo.isClose());
Headers replyHeaders = replyInfo.getHeaders();
- Assert.assertTrue(replyHeaders.get("status").value().contains("200"));
+ Assert.assertTrue(replyHeaders.get(HTTPSPDYHeader.STATUS.name(version())).value().contains("200"));
replyLatch.countDown();
}
@@ -437,7 +436,7 @@ public class ServerHTTPSPDYTest extends AbstractHTTPSPDYTest
final String data1 = "0123456789ABCDEF";
final String data2 = "FEDCBA9876543210";
final CountDownLatch handlerLatch = new CountDownLatch(1);
- Session session = startClient(startHTTPServer(new AbstractHandler()
+ Session session = startClient(version(), startHTTPServer(version(), new AbstractHandler()
{
@Override
public void handle(String target, Request request, HttpServletRequest httpRequest, HttpServletResponse httpResponse)
@@ -454,11 +453,11 @@ public class ServerHTTPSPDYTest extends AbstractHTTPSPDYTest
}), null);
Headers headers = new Headers();
- headers.put("method", "GET");
- headers.put("url", "/foo");
- headers.put("version", "HTTP/1.1");
- headers.put("scheme", "http");
- headers.put("host", "localhost:" + connector.getLocalPort());
+ headers.put(HTTPSPDYHeader.METHOD.name(version()), "GET");
+ headers.put(HTTPSPDYHeader.URI.name(version()), "/foo");
+ headers.put(HTTPSPDYHeader.VERSION.name(version()), "HTTP/1.1");
+ headers.put(HTTPSPDYHeader.SCHEME.name(version()), "http");
+ headers.put(HTTPSPDYHeader.HOST.name(version()), "localhost:" + connector.getLocalPort());
final CountDownLatch replyLatch = new CountDownLatch(1);
final CountDownLatch dataLatch = new CountDownLatch(2);
session.syn(new SynInfo(headers, true), new StreamFrameListener.Adapter()
@@ -472,7 +471,7 @@ public class ServerHTTPSPDYTest extends AbstractHTTPSPDYTest
Assert.assertEquals(1, replyFrames.incrementAndGet());
Assert.assertFalse(replyInfo.isClose());
Headers replyHeaders = replyInfo.getHeaders();
- Assert.assertTrue(replyHeaders.get("status").value().contains("200"));
+ Assert.assertTrue(replyHeaders.get(HTTPSPDYHeader.STATUS.name(version())).value().contains("200"));
replyLatch.countDown();
}
@@ -499,7 +498,7 @@ public class ServerHTTPSPDYTest extends AbstractHTTPSPDYTest
final byte[] data = new byte[128 * 1024];
Arrays.fill(data, (byte)'x');
final CountDownLatch handlerLatch = new CountDownLatch(1);
- Session session = startClient(startHTTPServer(new AbstractHandler()
+ Session session = startClient(version(), startHTTPServer(version(), new AbstractHandler()
{
@Override
public void handle(String target, Request request, HttpServletRequest httpRequest, HttpServletResponse httpResponse)
@@ -514,11 +513,11 @@ public class ServerHTTPSPDYTest extends AbstractHTTPSPDYTest
}), null);
Headers headers = new Headers();
- headers.put("method", "GET");
- headers.put("url", "/foo");
- headers.put("version", "HTTP/1.1");
- headers.put("scheme", "http");
- headers.put("host", "localhost:" + connector.getLocalPort());
+ headers.put(HTTPSPDYHeader.METHOD.name(version()), "GET");
+ headers.put(HTTPSPDYHeader.URI.name(version()), "/foo");
+ headers.put(HTTPSPDYHeader.VERSION.name(version()), "HTTP/1.1");
+ headers.put(HTTPSPDYHeader.SCHEME.name(version()), "http");
+ headers.put(HTTPSPDYHeader.HOST.name(version()), "localhost:" + connector.getLocalPort());
final CountDownLatch replyLatch = new CountDownLatch(1);
final CountDownLatch dataLatch = new CountDownLatch(1);
session.syn(new SynInfo(headers, true), new StreamFrameListener.Adapter()
@@ -530,7 +529,7 @@ public class ServerHTTPSPDYTest extends AbstractHTTPSPDYTest
{
Assert.assertFalse(replyInfo.isClose());
Headers replyHeaders = replyInfo.getHeaders();
- Assert.assertTrue(replyHeaders.get("status").value().contains("200"));
+ Assert.assertTrue(replyHeaders.get(HTTPSPDYHeader.STATUS.name(version())).value().contains("200"));
replyLatch.countDown();
}
@@ -556,7 +555,7 @@ public class ServerHTTPSPDYTest extends AbstractHTTPSPDYTest
final byte[] data = new byte[128 * 1024];
Arrays.fill(data, (byte)'y');
final CountDownLatch handlerLatch = new CountDownLatch(1);
- Session session = startClient(startHTTPServer(new AbstractHandler()
+ Session session = startClient(version(), startHTTPServer(version(), new AbstractHandler()
{
@Override
public void handle(String target, Request request, HttpServletRequest httpRequest, HttpServletResponse httpResponse)
@@ -572,11 +571,11 @@ public class ServerHTTPSPDYTest extends AbstractHTTPSPDYTest
}), null);
Headers headers = new Headers();
- headers.put("method", "GET");
- headers.put("url", "/foo");
- headers.put("version", "HTTP/1.1");
- headers.put("scheme", "http");
- headers.put("host", "localhost:" + connector.getLocalPort());
+ headers.put(HTTPSPDYHeader.METHOD.name(version()), "GET");
+ headers.put(HTTPSPDYHeader.URI.name(version()), "/foo");
+ headers.put(HTTPSPDYHeader.VERSION.name(version()), "HTTP/1.1");
+ headers.put(HTTPSPDYHeader.SCHEME.name(version()), "http");
+ headers.put(HTTPSPDYHeader.HOST.name(version()), "localhost:" + connector.getLocalPort());
final CountDownLatch replyLatch = new CountDownLatch(1);
final CountDownLatch dataLatch = new CountDownLatch(1);
session.syn(new SynInfo(headers, true), new StreamFrameListener.Adapter()
@@ -588,7 +587,7 @@ public class ServerHTTPSPDYTest extends AbstractHTTPSPDYTest
{
Assert.assertFalse(replyInfo.isClose());
Headers replyHeaders = replyInfo.getHeaders();
- Assert.assertTrue(replyHeaders.get("status").value().contains("200"));
+ Assert.assertTrue(replyHeaders.get(HTTPSPDYHeader.STATUS.name(version())).value().contains("200"));
replyLatch.countDown();
}
@@ -613,7 +612,7 @@ public class ServerHTTPSPDYTest extends AbstractHTTPSPDYTest
{
final String data = "0123456789ABCDEF";
final CountDownLatch handlerLatch = new CountDownLatch(1);
- Session session = startClient(startHTTPServer(new AbstractHandler()
+ Session session = startClient(version(), startHTTPServer(version(), new AbstractHandler()
{
@Override
public void handle(String target, Request request, HttpServletRequest httpRequest, HttpServletResponse httpResponse)
@@ -630,11 +629,11 @@ public class ServerHTTPSPDYTest extends AbstractHTTPSPDYTest
}), null);
Headers headers = new Headers();
- headers.put("method", "GET");
- headers.put("url", "/foo");
- headers.put("version", "HTTP/1.1");
- headers.put("scheme", "http");
- headers.put("host", "localhost:" + connector.getLocalPort());
+ headers.put(HTTPSPDYHeader.METHOD.name(version()), "GET");
+ headers.put(HTTPSPDYHeader.URI.name(version()), "/foo");
+ headers.put(HTTPSPDYHeader.VERSION.name(version()), "HTTP/1.1");
+ headers.put(HTTPSPDYHeader.SCHEME.name(version()), "http");
+ headers.put(HTTPSPDYHeader.HOST.name(version()), "localhost:" + connector.getLocalPort());
final CountDownLatch replyLatch = new CountDownLatch(1);
final CountDownLatch dataLatch = new CountDownLatch(1);
session.syn(new SynInfo(headers, true), new StreamFrameListener.Adapter()
@@ -646,7 +645,7 @@ public class ServerHTTPSPDYTest extends AbstractHTTPSPDYTest
{
Assert.assertFalse(replyInfo.isClose());
Headers replyHeaders = replyInfo.getHeaders();
- Assert.assertTrue(replyHeaders.get("status").value().contains("200"));
+ Assert.assertTrue(replyHeaders.get(HTTPSPDYHeader.STATUS.name(version())).value().contains("200"));
replyLatch.countDown();
}
@@ -674,7 +673,7 @@ public class ServerHTTPSPDYTest extends AbstractHTTPSPDYTest
final String data1 = "0123456789ABCDEF";
final String data2 = "FEDCBA9876543210";
final CountDownLatch handlerLatch = new CountDownLatch(1);
- Session session = startClient(startHTTPServer(new AbstractHandler()
+ Session session = startClient(version(), startHTTPServer(version(), new AbstractHandler()
{
@Override
public void handle(String target, Request request, HttpServletRequest httpRequest, HttpServletResponse httpResponse)
@@ -693,11 +692,11 @@ public class ServerHTTPSPDYTest extends AbstractHTTPSPDYTest
}), null);
Headers headers = new Headers();
- headers.put("method", "GET");
- headers.put("url", "/foo");
- headers.put("version", "HTTP/1.1");
- headers.put("scheme", "http");
- headers.put("host", "localhost:" + connector.getLocalPort());
+ headers.put(HTTPSPDYHeader.METHOD.name(version()), "GET");
+ headers.put(HTTPSPDYHeader.URI.name(version()), "/foo");
+ headers.put(HTTPSPDYHeader.VERSION.name(version()), "HTTP/1.1");
+ headers.put(HTTPSPDYHeader.SCHEME.name(version()), "http");
+ headers.put(HTTPSPDYHeader.HOST.name(version()), "localhost:" + connector.getLocalPort());
final CountDownLatch replyLatch = new CountDownLatch(1);
final CountDownLatch dataLatch = new CountDownLatch(1);
session.syn(new SynInfo(headers, true), new StreamFrameListener.Adapter()
@@ -709,7 +708,7 @@ public class ServerHTTPSPDYTest extends AbstractHTTPSPDYTest
{
Assert.assertFalse(replyInfo.isClose());
Headers replyHeaders = replyInfo.getHeaders();
- Assert.assertTrue(replyHeaders.get("status").value().contains("200"));
+ Assert.assertTrue(replyHeaders.get(HTTPSPDYHeader.STATUS.name(version())).value().contains("200"));
replyLatch.countDown();
}
@@ -736,7 +735,7 @@ public class ServerHTTPSPDYTest extends AbstractHTTPSPDYTest
{
final String suffix = "/redirect";
final CountDownLatch handlerLatch = new CountDownLatch(1);
- Session session = startClient(startHTTPServer(new AbstractHandler()
+ Session session = startClient(version(), startHTTPServer(version(), new AbstractHandler()
{
@Override
public void handle(String target, Request request, HttpServletRequest httpRequest, HttpServletResponse httpResponse)
@@ -751,11 +750,11 @@ public class ServerHTTPSPDYTest extends AbstractHTTPSPDYTest
}), null);
Headers headers = new Headers();
- headers.put("method", "GET");
- headers.put("url", "/foo");
- headers.put("version", "HTTP/1.1");
- headers.put("scheme", "http");
- headers.put("host", "localhost:" + connector.getLocalPort());
+ headers.put(HTTPSPDYHeader.METHOD.name(version()), "GET");
+ headers.put(HTTPSPDYHeader.URI.name(version()), "/foo");
+ headers.put(HTTPSPDYHeader.VERSION.name(version()), "HTTP/1.1");
+ headers.put(HTTPSPDYHeader.SCHEME.name(version()), "http");
+ headers.put(HTTPSPDYHeader.HOST.name(version()), "localhost:" + connector.getLocalPort());
final CountDownLatch replyLatch = new CountDownLatch(1);
session.syn(new SynInfo(headers, true), new StreamFrameListener.Adapter()
{
@@ -767,7 +766,7 @@ public class ServerHTTPSPDYTest extends AbstractHTTPSPDYTest
Assert.assertEquals(1, replies.incrementAndGet());
Assert.assertTrue(replyInfo.isClose());
Headers replyHeaders = replyInfo.getHeaders();
- Assert.assertTrue(replyHeaders.get("status").value().contains("302"));
+ Assert.assertTrue(replyHeaders.get(HTTPSPDYHeader.STATUS.name(version())).value().contains("302"));
Assert.assertTrue(replyHeaders.get("location").value().endsWith(suffix));
replyLatch.countDown();
}
@@ -780,7 +779,7 @@ public class ServerHTTPSPDYTest extends AbstractHTTPSPDYTest
public void testGETWithSendError() throws Exception
{
final CountDownLatch handlerLatch = new CountDownLatch(1);
- Session session = startClient(startHTTPServer(new AbstractHandler()
+ Session session = startClient(version(), startHTTPServer(version(), new AbstractHandler()
{
@Override
public void handle(String target, Request request, HttpServletRequest httpRequest, HttpServletResponse httpResponse)
@@ -793,11 +792,11 @@ public class ServerHTTPSPDYTest extends AbstractHTTPSPDYTest
}), null);
Headers headers = new Headers();
- headers.put("method", "GET");
- headers.put("url", "/foo");
- headers.put("version", "HTTP/1.1");
- headers.put("scheme", "http");
- headers.put("host", "localhost:" + connector.getLocalPort());
+ headers.put(HTTPSPDYHeader.METHOD.name(version()), "GET");
+ headers.put(HTTPSPDYHeader.URI.name(version()), "/foo");
+ headers.put(HTTPSPDYHeader.VERSION.name(version()), "HTTP/1.1");
+ headers.put(HTTPSPDYHeader.SCHEME.name(version()), "http");
+ headers.put(HTTPSPDYHeader.HOST.name(version()), "localhost:" + connector.getLocalPort());
final CountDownLatch replyLatch = new CountDownLatch(1);
final CountDownLatch dataLatch = new CountDownLatch(1);
session.syn(new SynInfo(headers, true), new StreamFrameListener.Adapter()
@@ -810,15 +809,15 @@ public class ServerHTTPSPDYTest extends AbstractHTTPSPDYTest
Assert.assertEquals(1, replies.incrementAndGet());
Assert.assertFalse(replyInfo.isClose());
Headers replyHeaders = replyInfo.getHeaders();
- Assert.assertTrue(replyHeaders.get("status").value().contains("404"));
+ Assert.assertTrue(replyHeaders.get(HTTPSPDYHeader.STATUS.name(version())).value().contains("404"));
replyLatch.countDown();
}
@Override
public void onData(Stream stream, DataInfo dataInfo)
{
- Assert.assertTrue(dataInfo.isClose());
- dataLatch.countDown();
+ if (dataInfo.isClose())
+ dataLatch.countDown();
}
});
Assert.assertTrue(handlerLatch.await(5, TimeUnit.SECONDS));
@@ -829,7 +828,7 @@ public class ServerHTTPSPDYTest extends AbstractHTTPSPDYTest
@Test
public void testGETWithException() throws Exception
{
- Session session = startClient(startHTTPServer(new AbstractHandler()
+ Session session = startClient(version(), startHTTPServer(version(), new AbstractHandler()
{
@Override
public void handle(String target, Request request, HttpServletRequest httpRequest, HttpServletResponse httpResponse)
@@ -840,11 +839,11 @@ public class ServerHTTPSPDYTest extends AbstractHTTPSPDYTest
}), null);
Headers headers = new Headers();
- headers.put("method", "GET");
- headers.put("url", "/foo");
- headers.put("version", "HTTP/1.1");
- headers.put("scheme", "http");
- headers.put("host", "localhost:" + connector.getLocalPort());
+ headers.put(HTTPSPDYHeader.METHOD.name(version()), "GET");
+ headers.put(HTTPSPDYHeader.URI.name(version()), "/foo");
+ headers.put(HTTPSPDYHeader.VERSION.name(version()), "HTTP/1.1");
+ headers.put(HTTPSPDYHeader.SCHEME.name(version()), "http");
+ headers.put(HTTPSPDYHeader.HOST.name(version()), "localhost:" + connector.getLocalPort());
final CountDownLatch replyLatch = new CountDownLatch(1);
session.syn(new SynInfo(headers, true), new StreamFrameListener.Adapter()
{
@@ -856,7 +855,7 @@ public class ServerHTTPSPDYTest extends AbstractHTTPSPDYTest
Assert.assertEquals(1, replies.incrementAndGet());
Assert.assertTrue(replyInfo.isClose());
Headers replyHeaders = replyInfo.getHeaders();
- Assert.assertTrue(replyHeaders.get("status").value().contains("500"));
+ Assert.assertTrue(replyHeaders.get(HTTPSPDYHeader.STATUS.name(version())).value().contains("500"));
replyLatch.countDown();
}
});
@@ -869,7 +868,7 @@ public class ServerHTTPSPDYTest extends AbstractHTTPSPDYTest
final String pangram1 = "the quick brown fox jumps over the lazy dog";
final String pangram2 = "qualche vago ione tipo zolfo, bromo, sodio";
final CountDownLatch handlerLatch = new CountDownLatch(1);
- Session session = startClient(startHTTPServer(new AbstractHandler()
+ Session session = startClient(version(), startHTTPServer(version(), new AbstractHandler()
{
@Override
public void handle(String target, Request request, HttpServletRequest httpRequest, HttpServletResponse httpResponse)
@@ -887,11 +886,11 @@ public class ServerHTTPSPDYTest extends AbstractHTTPSPDYTest
}), null);
Headers headers = new Headers();
- headers.put("method", "GET");
- headers.put("url", "/foo");
- headers.put("version", "HTTP/1.1");
- headers.put("scheme", "http");
- headers.put("host", "localhost:" + connector.getLocalPort());
+ headers.put(HTTPSPDYHeader.METHOD.name(version()), "GET");
+ headers.put(HTTPSPDYHeader.URI.name(version()), "/foo");
+ headers.put(HTTPSPDYHeader.VERSION.name(version()), "HTTP/1.1");
+ headers.put(HTTPSPDYHeader.SCHEME.name(version()), "http");
+ headers.put(HTTPSPDYHeader.HOST.name(version()), "localhost:" + connector.getLocalPort());
final CountDownLatch replyLatch = new CountDownLatch(1);
final CountDownLatch dataLatch = new CountDownLatch(2);
session.syn(new SynInfo(headers, true), new StreamFrameListener.Adapter()
@@ -905,7 +904,7 @@ public class ServerHTTPSPDYTest extends AbstractHTTPSPDYTest
Assert.assertEquals(1, replyFrames.incrementAndGet());
Assert.assertFalse(replyInfo.isClose());
Headers replyHeaders = replyInfo.getHeaders();
- Assert.assertTrue(replyHeaders.get("status").value().contains("200"));
+ Assert.assertTrue(replyHeaders.get(HTTPSPDYHeader.STATUS.name(version())).value().contains("200"));
Assert.assertTrue(replyHeaders.get("extra").value().contains("X"));
replyLatch.countDown();
}
@@ -933,11 +932,30 @@ public class ServerHTTPSPDYTest extends AbstractHTTPSPDYTest
}
@Test
- public void testGETWithMediumContentByPassed() throws Exception
+ public void testGETWithMediumContentAsInputStreamByPassed() throws Exception
+ {
+ byte[] data = new byte[2048];
+ testGETWithContentByPassed(new ByteArrayInputStream(data), data.length);
+ }
+
+ @Test
+ public void testGETWithBigContentAsInputStreamByPassed() throws Exception
+ {
+ byte[] data = new byte[128 * 1024];
+ testGETWithContentByPassed(new ByteArrayInputStream(data), data.length);
+ }
+
+ @Test
+ public void testGETWithMediumContentAsBufferByPassed() throws Exception
+ {
+ byte[] data = new byte[2048];
+ testGETWithContentByPassed(new ByteArrayBuffer(data), data.length);
+ }
+
+ private void testGETWithContentByPassed(final Object content, final int length) throws Exception
{
- final byte[] data = new byte[2048];
final CountDownLatch handlerLatch = new CountDownLatch(1);
- Session session = startClient(startHTTPServer(new AbstractHandler()
+ Session session = startClient(version(), startHTTPServer(version(), new AbstractHandler()
{
@Override
public void handle(String target, Request request, HttpServletRequest httpRequest, HttpServletResponse httpResponse)
@@ -947,23 +965,23 @@ public class ServerHTTPSPDYTest extends AbstractHTTPSPDYTest
// We use this trick that's present in Jetty code: if we add a request attribute
// called "org.eclipse.jetty.server.sendContent", then it will trigger the
// content bypass that we want to test
- request.setAttribute("org.eclipse.jetty.server.sendContent", new ByteArrayBuffer(data));
+ request.setAttribute("org.eclipse.jetty.server.sendContent", content);
handlerLatch.countDown();
}
}), null);
Headers headers = new Headers();
- headers.put("method", "GET");
- headers.put("url", "/foo");
- headers.put("version", "HTTP/1.1");
- headers.put("scheme", "http");
- headers.put("host", "localhost:" + connector.getLocalPort());
+ headers.put(HTTPSPDYHeader.METHOD.name(version()), "GET");
+ headers.put(HTTPSPDYHeader.URI.name(version()), "/foo");
+ headers.put(HTTPSPDYHeader.VERSION.name(version()), "HTTP/1.1");
+ headers.put(HTTPSPDYHeader.SCHEME.name(version()), "http");
+ headers.put(HTTPSPDYHeader.HOST.name(version()), "localhost:" + connector.getLocalPort());
final CountDownLatch replyLatch = new CountDownLatch(1);
final CountDownLatch dataLatch = new CountDownLatch(1);
session.syn(new SynInfo(headers, true), new StreamFrameListener.Adapter()
{
private final AtomicInteger replyFrames = new AtomicInteger();
- private final AtomicInteger dataFrames = new AtomicInteger();
+ private final AtomicInteger contentLength = new AtomicInteger();
@Override
public void onReply(Stream stream, ReplyInfo replyInfo)
@@ -971,17 +989,19 @@ public class ServerHTTPSPDYTest extends AbstractHTTPSPDYTest
Assert.assertEquals(1, replyFrames.incrementAndGet());
Assert.assertFalse(replyInfo.isClose());
Headers replyHeaders = replyInfo.getHeaders();
- Assert.assertTrue(replyHeaders.get("status").value().contains("200"));
+ Assert.assertTrue(replyHeaders.get(HTTPSPDYHeader.STATUS.name(version())).value().contains("200"));
replyLatch.countDown();
}
@Override
public void onData(Stream stream, DataInfo dataInfo)
{
- Assert.assertEquals(1, dataFrames.incrementAndGet());
- Assert.assertTrue(dataInfo.isClose());
- Assert.assertArrayEquals(data, dataInfo.asBytes(true));
- dataLatch.countDown();
+ contentLength.addAndGet(dataInfo.asBytes(true).length);
+ if (dataInfo.isClose())
+ {
+ Assert.assertEquals(length, contentLength.get());
+ dataLatch.countDown();
+ }
}
});
Assert.assertTrue(handlerLatch.await(5, TimeUnit.SECONDS));
@@ -990,11 +1010,66 @@ public class ServerHTTPSPDYTest extends AbstractHTTPSPDYTest
}
@Test
+ public void testGETWithMultipleMediumContentByPassed() throws Exception
+ {
+ final byte[] data = new byte[2048];
+ Session session = startClient(version(), startHTTPServer(version(), new AbstractHandler()
+ {
+ @Override
+ public void handle(String target, Request request, HttpServletRequest httpRequest, HttpServletResponse httpResponse)
+ throws IOException, ServletException
+ {
+ // The sequence of write/flush/write/write below triggers a condition where
+ // HttpGenerator._bypass is set to true on the second write(), and the
+ // third write causes an infinite spin loop on the third write().
+ request.setHandled(true);
+ OutputStream output = httpResponse.getOutputStream();
+ output.write(data);
+ output.flush();
+ output.write(data);
+ output.write(data);
+ }
+ }), null);
+
+ Headers headers = new Headers();
+ headers.put(HTTPSPDYHeader.METHOD.name(version()), "GET");
+ headers.put(HTTPSPDYHeader.URI.name(version()), "/foo");
+ headers.put(HTTPSPDYHeader.VERSION.name(version()), "HTTP/1.1");
+ headers.put(HTTPSPDYHeader.SCHEME.name(version()), "http");
+ headers.put(HTTPSPDYHeader.HOST.name(version()), "localhost:" + connector.getLocalPort());
+ final CountDownLatch replyLatch = new CountDownLatch(1);
+ final CountDownLatch dataLatch = new CountDownLatch(1);
+ final AtomicInteger contentLength = new AtomicInteger();
+ session.syn(new SynInfo(headers, true), new StreamFrameListener.Adapter()
+ {
+ @Override
+ public void onReply(Stream stream, ReplyInfo replyInfo)
+ {
+ Assert.assertFalse(replyInfo.isClose());
+ Headers replyHeaders = replyInfo.getHeaders();
+ Assert.assertTrue(replyHeaders.get(HTTPSPDYHeader.STATUS.name(version())).value().contains("200"));
+ replyLatch.countDown();
+ }
+
+ @Override
+ public void onData(Stream stream, DataInfo dataInfo)
+ {
+ dataInfo.consume(dataInfo.available());
+ contentLength.addAndGet(dataInfo.length());
+ if (dataInfo.isClose())
+ dataLatch.countDown();
+ }
+ });
+ Assert.assertTrue(dataLatch.await(5, TimeUnit.SECONDS));
+ Assert.assertEquals(3 * data.length, contentLength.get());
+ }
+
+ @Test
public void testPOSTThenSuspendRequestThenReadOneChunkThenComplete() throws Exception
{
final byte[] data = new byte[2000];
final CountDownLatch latch = new CountDownLatch(1);
- Session session = startClient(startHTTPServer(new AbstractHandler()
+ Session session = startClient(version(), startHTTPServer(version(), new AbstractHandler()
{
@Override
public void handle(String target, final Request request, HttpServletRequest httpRequest, HttpServletResponse httpResponse)
@@ -1030,11 +1105,11 @@ public class ServerHTTPSPDYTest extends AbstractHTTPSPDYTest
}), null);
Headers headers = new Headers();
- headers.put("method", "POST");
- headers.put("url", "/foo");
- headers.put("version", "HTTP/1.1");
- headers.put("scheme", "http");
- headers.put("host", "localhost:" + connector.getLocalPort());
+ headers.put(HTTPSPDYHeader.METHOD.name(version()), "POST");
+ headers.put(HTTPSPDYHeader.URI.name(version()), "/foo");
+ headers.put(HTTPSPDYHeader.VERSION.name(version()), "HTTP/1.1");
+ headers.put(HTTPSPDYHeader.SCHEME.name(version()), "http");
+ headers.put(HTTPSPDYHeader.HOST.name(version()), "localhost:" + connector.getLocalPort());
final CountDownLatch replyLatch = new CountDownLatch(1);
Stream stream = session.syn(new SynInfo(headers, false), new StreamFrameListener.Adapter()
{
@@ -1042,7 +1117,7 @@ public class ServerHTTPSPDYTest extends AbstractHTTPSPDYTest
public void onReply(Stream stream, ReplyInfo replyInfo)
{
Headers replyHeaders = replyInfo.getHeaders();
- Assert.assertTrue(replyHeaders.get("status").value().contains("200"));
+ Assert.assertTrue(replyHeaders.get(HTTPSPDYHeader.STATUS.name(version())).value().contains("200"));
replyLatch.countDown();
}
}).get(5, TimeUnit.SECONDS);
@@ -1057,7 +1132,7 @@ public class ServerHTTPSPDYTest extends AbstractHTTPSPDYTest
{
final byte[] data = new byte[2000];
final CountDownLatch latch = new CountDownLatch(1);
- Session session = startClient(startHTTPServer(new AbstractHandler()
+ Session session = startClient(version(), startHTTPServer(version(), new AbstractHandler()
{
@Override
public void handle(String target, final Request request, HttpServletRequest httpRequest, HttpServletResponse httpResponse)
@@ -1093,11 +1168,11 @@ public class ServerHTTPSPDYTest extends AbstractHTTPSPDYTest
}), null);
Headers headers = new Headers();
- headers.put("method", "POST");
- headers.put("url", "/foo");
- headers.put("version", "HTTP/1.1");
- headers.put("scheme", "http");
- headers.put("host", "localhost:" + connector.getLocalPort());
+ headers.put(HTTPSPDYHeader.METHOD.name(version()), "POST");
+ headers.put(HTTPSPDYHeader.URI.name(version()), "/foo");
+ headers.put(HTTPSPDYHeader.VERSION.name(version()), "HTTP/1.1");
+ headers.put(HTTPSPDYHeader.SCHEME.name(version()), "http");
+ headers.put(HTTPSPDYHeader.HOST.name(version()), "localhost:" + connector.getLocalPort());
final CountDownLatch replyLatch = new CountDownLatch(1);
Stream stream = session.syn(new SynInfo(headers, false), new StreamFrameListener.Adapter()
{
@@ -1105,7 +1180,7 @@ public class ServerHTTPSPDYTest extends AbstractHTTPSPDYTest
public void onReply(Stream stream, ReplyInfo replyInfo)
{
Headers replyHeaders = replyInfo.getHeaders();
- Assert.assertTrue(replyHeaders.get("status").value().contains("200"));
+ Assert.assertTrue(replyHeaders.get(HTTPSPDYHeader.STATUS.name(version())).value().contains("200"));
replyLatch.countDown();
}
}).get(5, TimeUnit.SECONDS);
@@ -1121,7 +1196,7 @@ public class ServerHTTPSPDYTest extends AbstractHTTPSPDYTest
{
final byte[] data = new byte[1000];
final CountDownLatch latch = new CountDownLatch(1);
- Session session = startClient(startHTTPServer(new AbstractHandler()
+ Session session = startClient(version(), startHTTPServer(version(), new AbstractHandler()
{
@Override
public void handle(String target, final Request request, HttpServletRequest httpRequest, HttpServletResponse httpResponse)
@@ -1166,11 +1241,11 @@ public class ServerHTTPSPDYTest extends AbstractHTTPSPDYTest
}), null);
Headers headers = new Headers();
- headers.put("method", "POST");
- headers.put("url", "/foo");
- headers.put("version", "HTTP/1.1");
- headers.put("scheme", "http");
- headers.put("host", "localhost:" + connector.getLocalPort());
+ headers.put(HTTPSPDYHeader.METHOD.name(version()), "POST");
+ headers.put(HTTPSPDYHeader.URI.name(version()), "/foo");
+ headers.put(HTTPSPDYHeader.VERSION.name(version()), "HTTP/1.1");
+ headers.put(HTTPSPDYHeader.SCHEME.name(version()), "http");
+ headers.put(HTTPSPDYHeader.HOST.name(version()), "localhost:" + connector.getLocalPort());
final CountDownLatch responseLatch = new CountDownLatch(2);
Stream stream = session.syn(new SynInfo(headers, false), new StreamFrameListener.Adapter()
{
@@ -1178,7 +1253,7 @@ public class ServerHTTPSPDYTest extends AbstractHTTPSPDYTest
public void onReply(Stream stream, ReplyInfo replyInfo)
{
Headers replyHeaders = replyInfo.getHeaders();
- Assert.assertTrue(replyHeaders.get("status").value().contains("200"));
+ Assert.assertTrue(replyHeaders.get(HTTPSPDYHeader.STATUS.name(version())).value().contains("200"));
responseLatch.countDown();
}
diff --git a/jetty-spdy/spdy-jetty-http/src/test/java/org/eclipse/jetty/spdy/http/ServerHTTPSPDYv3Test.java b/jetty-spdy/spdy-jetty-http/src/test/java/org/eclipse/jetty/spdy/http/ServerHTTPSPDYv3Test.java
new file mode 100644
index 0000000000..e6c4de2ac3
--- /dev/null
+++ b/jetty-spdy/spdy-jetty-http/src/test/java/org/eclipse/jetty/spdy/http/ServerHTTPSPDYv3Test.java
@@ -0,0 +1,26 @@
+//========================================================================
+//Copyright 2011-2012 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.spdy.http;
+
+import org.eclipse.jetty.spdy.api.SPDY;
+
+public class ServerHTTPSPDYv3Test extends ServerHTTPSPDYv2Test
+{
+ @Override
+ protected short version()
+ {
+ return SPDY.V3;
+ }
+}
diff --git a/jetty-spdy/spdy-jetty-http/src/test/java/org/eclipse/jetty/spdy/proxy/ProxyHTTPSPDYv2Test.java b/jetty-spdy/spdy-jetty-http/src/test/java/org/eclipse/jetty/spdy/proxy/ProxyHTTPSPDYv2Test.java
new file mode 100644
index 0000000000..6c2c89bc87
--- /dev/null
+++ b/jetty-spdy/spdy-jetty-http/src/test/java/org/eclipse/jetty/spdy/proxy/ProxyHTTPSPDYv2Test.java
@@ -0,0 +1,764 @@
+//========================================================================
+//Copyright 2011-2012 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.spdy.proxy;
+
+import java.io.BufferedReader;
+import java.io.ByteArrayOutputStream;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.io.OutputStream;
+import java.net.InetSocketAddress;
+import java.net.Socket;
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.TimeUnit;
+
+import org.eclipse.jetty.server.Server;
+import org.eclipse.jetty.spdy.SPDYClient;
+import org.eclipse.jetty.spdy.SPDYServerConnector;
+import org.eclipse.jetty.spdy.ServerSPDYAsyncConnectionFactory;
+import org.eclipse.jetty.spdy.api.BytesDataInfo;
+import org.eclipse.jetty.spdy.api.DataInfo;
+import org.eclipse.jetty.spdy.api.GoAwayInfo;
+import org.eclipse.jetty.spdy.api.Handler;
+import org.eclipse.jetty.spdy.api.Headers;
+import org.eclipse.jetty.spdy.api.PingInfo;
+import org.eclipse.jetty.spdy.api.ReplyInfo;
+import org.eclipse.jetty.spdy.api.RstInfo;
+import org.eclipse.jetty.spdy.api.SPDY;
+import org.eclipse.jetty.spdy.api.Session;
+import org.eclipse.jetty.spdy.api.SessionFrameListener;
+import org.eclipse.jetty.spdy.api.Stream;
+import org.eclipse.jetty.spdy.api.StreamFrameListener;
+import org.eclipse.jetty.spdy.api.StreamStatus;
+import org.eclipse.jetty.spdy.api.SynInfo;
+import org.eclipse.jetty.spdy.api.server.ServerSessionFrameListener;
+import org.eclipse.jetty.spdy.http.HTTPSPDYHeader;
+import org.junit.After;
+import org.junit.Assert;
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.rules.TestWatchman;
+import org.junit.runners.model.FrameworkMethod;
+
+public class ProxyHTTPSPDYv2Test
+{
+ @Rule
+ public final TestWatchman testName = new TestWatchman()
+ {
+ @Override
+ public void starting(FrameworkMethod method)
+ {
+ super.starting(method);
+ System.err.printf("Running %s.%s()%n",
+ method.getMethod().getDeclaringClass().getName(),
+ method.getName());
+ }
+ };
+
+ private SPDYClient.Factory factory;
+ private Server server;
+ private Server proxy;
+ private SPDYServerConnector proxyConnector;
+
+ protected short version()
+ {
+ return SPDY.V2;
+ }
+
+ protected InetSocketAddress startServer(ServerSessionFrameListener listener) throws Exception
+ {
+ server = new Server();
+ SPDYServerConnector serverConnector = new SPDYServerConnector(listener);
+ serverConnector.setDefaultAsyncConnectionFactory(new ServerSPDYAsyncConnectionFactory(version(), serverConnector.getByteBufferPool(), serverConnector.getExecutor(), serverConnector.getScheduler(), listener));
+ serverConnector.setPort(0);
+ server.addConnector(serverConnector);
+ server.start();
+ return new InetSocketAddress("localhost", serverConnector.getLocalPort());
+ }
+
+ protected InetSocketAddress startProxy(InetSocketAddress address) throws Exception
+ {
+ proxy = new Server();
+ ProxyEngineSelector proxyEngineSelector = new ProxyEngineSelector();
+ SPDYProxyEngine spdyProxyEngine = new SPDYProxyEngine(factory);
+ proxyEngineSelector.putProxyEngine("spdy/" + version(), spdyProxyEngine);
+ proxyEngineSelector.putProxyServerInfo("localhost", new ProxyEngineSelector.ProxyServerInfo("spdy/" + version(), address.getHostName(), address.getPort()));
+ proxyConnector = new HTTPSPDYProxyConnector(proxyEngineSelector);
+ proxyConnector.setPort(0);
+ proxy.addConnector(proxyConnector);
+ proxy.start();
+ return new InetSocketAddress("localhost", proxyConnector.getLocalPort());
+ }
+
+ @Before
+ public void init() throws Exception
+ {
+ factory = new SPDYClient.Factory();
+ factory.start();
+ }
+
+ @After
+ public void destroy() throws Exception
+ {
+ if (server != null)
+ {
+ server.stop();
+ server.join();
+ }
+ if (proxy != null)
+ {
+ proxy.stop();
+ proxy.join();
+ }
+ factory.stop();
+ }
+
+ @Test
+ public void testClosingClientDoesNotCloseServer() throws Exception
+ {
+ final CountDownLatch closeLatch = new CountDownLatch(1);
+ InetSocketAddress proxyAddress = startProxy(startServer(new ServerSessionFrameListener.Adapter()
+ {
+ @Override
+ public StreamFrameListener onSyn(Stream stream, SynInfo synInfo)
+ {
+ Headers responseHeaders = new Headers();
+ responseHeaders.put(HTTPSPDYHeader.VERSION.name(version()), "HTTP/1.1");
+ responseHeaders.put(HTTPSPDYHeader.STATUS.name(version()), "200 OK");
+ stream.reply(new ReplyInfo(responseHeaders, true));
+ return null;
+ }
+
+ @Override
+ public void onGoAway(Session session, GoAwayInfo goAwayInfo)
+ {
+ closeLatch.countDown();
+ }
+ }));
+
+ Socket client = new Socket();
+ client.connect(proxyAddress);
+ OutputStream output = client.getOutputStream();
+
+ String request = "" +
+ "GET / HTTP/1.1\r\n" +
+ "Host: localhost:" + proxyAddress.getPort() + "\r\n" +
+ "\r\n";
+ output.write(request.getBytes("UTF-8"));
+ output.flush();
+
+ InputStream input = client.getInputStream();
+ BufferedReader reader = new BufferedReader(new InputStreamReader(input, "UTF-8"));
+ String line = reader.readLine();
+ Assert.assertTrue(line.contains(" 200"));
+ while (line.length() > 0)
+ line = reader.readLine();
+ Assert.assertFalse(reader.ready());
+
+ client.close();
+
+ // Must not close, other clients may still be connected
+ Assert.assertFalse(closeLatch.await(1, TimeUnit.SECONDS));
+ }
+
+ @Test
+ public void testGETThenNoContentFromTwoClients() throws Exception
+ {
+ InetSocketAddress proxyAddress = startProxy(startServer(new ServerSessionFrameListener.Adapter()
+ {
+ @Override
+ public StreamFrameListener onSyn(Stream stream, SynInfo synInfo)
+ {
+ Assert.assertTrue(synInfo.isClose());
+ Headers requestHeaders = synInfo.getHeaders();
+ Assert.assertNotNull(requestHeaders.get("via"));
+
+ Headers responseHeaders = new Headers();
+ responseHeaders.put(HTTPSPDYHeader.VERSION.name(version()), "HTTP/1.1");
+ responseHeaders.put(HTTPSPDYHeader.STATUS.name(version()), "200 OK");
+ ReplyInfo replyInfo = new ReplyInfo(responseHeaders, true);
+ stream.reply(replyInfo);
+ return null;
+ }
+ }));
+
+ Socket client1 = new Socket();
+ client1.connect(proxyAddress);
+ OutputStream output1 = client1.getOutputStream();
+
+ String request = "" +
+ "GET / HTTP/1.1\r\n" +
+ "Host: localhost:" + proxyAddress.getPort() + "\r\n" +
+ "\r\n";
+ output1.write(request.getBytes("UTF-8"));
+ output1.flush();
+
+ InputStream input1 = client1.getInputStream();
+ BufferedReader reader1 = new BufferedReader(new InputStreamReader(input1, "UTF-8"));
+ String line = reader1.readLine();
+ Assert.assertTrue(line.contains(" 200"));
+ while (line.length() > 0)
+ line = reader1.readLine();
+ Assert.assertFalse(reader1.ready());
+
+ // Perform another request with another client
+ Socket client2 = new Socket();
+ client2.connect(proxyAddress);
+ OutputStream output2 = client2.getOutputStream();
+
+ output2.write(request.getBytes("UTF-8"));
+ output2.flush();
+
+ InputStream input2 = client2.getInputStream();
+ BufferedReader reader2 = new BufferedReader(new InputStreamReader(input2, "UTF-8"));
+ line = reader2.readLine();
+ Assert.assertTrue(line.contains(" 200"));
+ while (line.length() > 0)
+ line = reader2.readLine();
+ Assert.assertFalse(reader2.ready());
+
+ client1.close();
+ client2.close();
+ }
+
+ @Test
+ public void testGETThenSmallResponseContent() throws Exception
+ {
+ final byte[] data = "0123456789ABCDEF".getBytes("UTF-8");
+ InetSocketAddress proxyAddress = startProxy(startServer(new ServerSessionFrameListener.Adapter()
+ {
+ @Override
+ public StreamFrameListener onSyn(Stream stream, SynInfo synInfo)
+ {
+ Assert.assertTrue(synInfo.isClose());
+ Headers requestHeaders = synInfo.getHeaders();
+ Assert.assertNotNull(requestHeaders.get("via"));
+
+ Headers responseHeaders = new Headers();
+ responseHeaders.put(HTTPSPDYHeader.VERSION.name(version()), "HTTP/1.1");
+ responseHeaders.put(HTTPSPDYHeader.STATUS.name(version()), "200 OK");
+ ReplyInfo replyInfo = new ReplyInfo(responseHeaders, false);
+ stream.reply(replyInfo);
+ stream.data(new BytesDataInfo(data, true));
+
+ return null;
+ }
+ }));
+
+ Socket client = new Socket();
+ client.connect(proxyAddress);
+ OutputStream output = client.getOutputStream();
+
+ String request = "" +
+ "GET / HTTP/1.1\r\n" +
+ "Host: localhost:" + proxyAddress.getPort() + "\r\n" +
+ "\r\n";
+ output.write(request.getBytes("UTF-8"));
+ output.flush();
+
+ InputStream input = client.getInputStream();
+ BufferedReader reader = new BufferedReader(new InputStreamReader(input, "UTF-8"));
+ String line = reader.readLine();
+ Assert.assertTrue(line.contains(" 200"));
+ while (line.length() > 0)
+ line = reader.readLine();
+ for (byte datum : data)
+ Assert.assertEquals(datum, reader.read());
+ Assert.assertFalse(reader.ready());
+
+ // Perform another request so that we are sure we reset the states of parsers and generators
+ output.write(request.getBytes("UTF-8"));
+ output.flush();
+
+ line = reader.readLine();
+ Assert.assertTrue(line.contains(" 200"));
+ while (line.length() > 0)
+ line = reader.readLine();
+ for (byte datum : data)
+ Assert.assertEquals(datum, reader.read());
+ Assert.assertFalse(reader.ready());
+
+ client.close();
+ }
+
+ @Test
+ public void testPOSTWithSmallRequestContentThenRedirect() throws Exception
+ {
+ final byte[] data = "0123456789ABCDEF".getBytes("UTF-8");
+ InetSocketAddress proxyAddress = startProxy(startServer(new ServerSessionFrameListener.Adapter()
+ {
+ @Override
+ public StreamFrameListener onSyn(Stream stream, SynInfo synInfo)
+ {
+ return new StreamFrameListener.Adapter()
+ {
+ @Override
+ public void onData(Stream stream, DataInfo dataInfo)
+ {
+ dataInfo.consume(dataInfo.length());
+ if (dataInfo.isClose())
+ {
+ Headers headers = new Headers();
+ headers.put(HTTPSPDYHeader.VERSION.name(version()), "HTTP/1.1");
+ headers.put(HTTPSPDYHeader.STATUS.name(version()), "303 See Other");
+ stream.reply(new ReplyInfo(headers, true));
+ }
+ }
+ };
+ }
+ }));
+
+ Socket client = new Socket();
+ client.connect(proxyAddress);
+ OutputStream output = client.getOutputStream();
+
+ String request = "" +
+ "POST / HTTP/1.1\r\n" +
+ "Host: localhost:" + proxyAddress.getPort() + "\r\n" +
+ "Content-Length: " + data.length + "\r\n" +
+ "Content-Type: application/octet-stream\r\n" +
+ "\r\n";
+ output.write(request.getBytes("UTF-8"));
+ output.write(data);
+ output.flush();
+
+ InputStream input = client.getInputStream();
+ BufferedReader reader = new BufferedReader(new InputStreamReader(input, "UTF-8"));
+ String line = reader.readLine();
+ Assert.assertTrue(line.contains(" 303"));
+ while (line.length() > 0)
+ line = reader.readLine();
+ Assert.assertFalse(reader.ready());
+
+ // Perform another request so that we are sure we reset the states of parsers and generators
+ output.write(request.getBytes("UTF-8"));
+ output.write(data);
+ output.flush();
+
+ line = reader.readLine();
+ Assert.assertTrue(line.contains(" 303"));
+ while (line.length() > 0)
+ line = reader.readLine();
+ Assert.assertFalse(reader.ready());
+
+ client.close();
+ }
+
+ @Test
+ public void testPOSTWithSmallRequestContentThenSmallResponseContent() throws Exception
+ {
+ final byte[] data = "0123456789ABCDEF".getBytes("UTF-8");
+ InetSocketAddress proxyAddress = startProxy(startServer(new ServerSessionFrameListener.Adapter()
+ {
+ @Override
+ public StreamFrameListener onSyn(Stream stream, SynInfo synInfo)
+ {
+ return new StreamFrameListener.Adapter()
+ {
+ @Override
+ public void onData(Stream stream, DataInfo dataInfo)
+ {
+ dataInfo.consume(dataInfo.length());
+ if (dataInfo.isClose())
+ {
+ Headers responseHeaders = new Headers();
+ responseHeaders.put(HTTPSPDYHeader.VERSION.name(version()), "HTTP/1.1");
+ responseHeaders.put(HTTPSPDYHeader.STATUS.name(version()), "200 OK");
+ ReplyInfo replyInfo = new ReplyInfo(responseHeaders, false);
+ stream.reply(replyInfo);
+ stream.data(new BytesDataInfo(data, true));
+ }
+ }
+ };
+ }
+ }));
+
+ Socket client = new Socket();
+ client.connect(proxyAddress);
+ OutputStream output = client.getOutputStream();
+
+ String request = "" +
+ "POST / HTTP/1.1\r\n" +
+ "Host: localhost:" + proxyAddress.getPort() + "\r\n" +
+ "Content-Length: " + data.length + "\r\n" +
+ "Content-Type: application/octet-stream\r\n" +
+ "\r\n";
+ output.write(request.getBytes("UTF-8"));
+ output.write(data);
+ output.flush();
+
+ InputStream input = client.getInputStream();
+ BufferedReader reader = new BufferedReader(new InputStreamReader(input, "UTF-8"));
+ String line = reader.readLine();
+ Assert.assertTrue(line.contains(" 200"));
+ while (line.length() > 0)
+ line = reader.readLine();
+ for (byte datum : data)
+ Assert.assertEquals(datum, reader.read());
+ Assert.assertFalse(reader.ready());
+
+ // Perform another request so that we are sure we reset the states of parsers and generators
+ output.write(request.getBytes("UTF-8"));
+ output.write(data);
+ output.flush();
+
+ line = reader.readLine();
+ Assert.assertTrue(line.contains(" 200"));
+ while (line.length() > 0)
+ line = reader.readLine();
+ for (byte datum : data)
+ Assert.assertEquals(datum, reader.read());
+ Assert.assertFalse(reader.ready());
+
+ client.close();
+ }
+
+ @Test
+ public void testSYNThenREPLY() throws Exception
+ {
+ final String header = "foo";
+ InetSocketAddress proxyAddress = startProxy(startServer(new ServerSessionFrameListener.Adapter()
+ {
+ @Override
+ public StreamFrameListener onSyn(Stream stream, SynInfo synInfo)
+ {
+ Headers requestHeaders = synInfo.getHeaders();
+ Assert.assertNotNull(requestHeaders.get("via"));
+ Assert.assertNotNull(requestHeaders.get(header));
+
+ Headers responseHeaders = new Headers();
+ responseHeaders.put(header, "baz");
+ stream.reply(new ReplyInfo(responseHeaders, true));
+ return null;
+ }
+ }));
+ proxyConnector.setDefaultAsyncConnectionFactory(proxyConnector.getAsyncConnectionFactory("spdy/" + version()));
+
+ Session client = factory.newSPDYClient(version()).connect(proxyAddress, null).get(5, TimeUnit.SECONDS);
+
+ final CountDownLatch replyLatch = new CountDownLatch(1);
+ Headers headers = new Headers();
+ headers.put(HTTPSPDYHeader.HOST.name(version()), "localhost:" + proxyAddress.getPort());
+ headers.put(header, "bar");
+ client.syn(new SynInfo(headers, true), new StreamFrameListener.Adapter()
+ {
+ @Override
+ public void onReply(Stream stream, ReplyInfo replyInfo)
+ {
+ Headers headers = replyInfo.getHeaders();
+ Assert.assertNotNull(headers.get(header));
+ replyLatch.countDown();
+ }
+ });
+
+ Assert.assertTrue(replyLatch.await(5, TimeUnit.SECONDS));
+
+ client.goAway().get(5, TimeUnit.SECONDS);
+ }
+
+ @Test
+ public void testSYNThenREPLYAndDATA() throws Exception
+ {
+ final byte[] data = "0123456789ABCDEF".getBytes("UTF-8");
+ final String header = "foo";
+ InetSocketAddress proxyAddress = startProxy(startServer(new ServerSessionFrameListener.Adapter()
+ {
+ @Override
+ public StreamFrameListener onSyn(Stream stream, SynInfo synInfo)
+ {
+ Headers requestHeaders = synInfo.getHeaders();
+ Assert.assertNotNull(requestHeaders.get("via"));
+ Assert.assertNotNull(requestHeaders.get(header));
+
+ Headers responseHeaders = new Headers();
+ responseHeaders.put(header, "baz");
+ stream.reply(new ReplyInfo(responseHeaders, false));
+ stream.data(new BytesDataInfo(data, true));
+ return null;
+ }
+ }));
+ proxyConnector.setDefaultAsyncConnectionFactory(proxyConnector.getAsyncConnectionFactory("spdy/" + version()));
+
+ Session client = factory.newSPDYClient(version()).connect(proxyAddress, null).get(5, TimeUnit.SECONDS);
+
+ final CountDownLatch replyLatch = new CountDownLatch(1);
+ final CountDownLatch dataLatch = new CountDownLatch(1);
+ Headers headers = new Headers();
+ headers.put(HTTPSPDYHeader.HOST.name(version()), "localhost:" + proxyAddress.getPort());
+ headers.put(header, "bar");
+ client.syn(new SynInfo(headers, true), new StreamFrameListener.Adapter()
+ {
+ private final ByteArrayOutputStream result = new ByteArrayOutputStream();
+
+ @Override
+ public void onReply(Stream stream, ReplyInfo replyInfo)
+ {
+ Headers headers = replyInfo.getHeaders();
+ Assert.assertNotNull(headers.get(header));
+ replyLatch.countDown();
+ }
+
+ @Override
+ public void onData(Stream stream, DataInfo dataInfo)
+ {
+ result.write(dataInfo.asBytes(true), 0, dataInfo.length());
+ if (dataInfo.isClose())
+ {
+ Assert.assertArrayEquals(data, result.toByteArray());
+ dataLatch.countDown();
+ }
+ }
+ });
+
+ Assert.assertTrue(replyLatch.await(5, TimeUnit.SECONDS));
+ Assert.assertTrue(dataLatch.await(5, TimeUnit.SECONDS));
+
+ client.goAway().get(5, TimeUnit.SECONDS);
+ }
+
+ @Test
+ public void testGETThenSPDYPushIsIgnored() throws Exception
+ {
+ final byte[] data = "0123456789ABCDEF".getBytes("UTF-8");
+ InetSocketAddress proxyAddress = startProxy(startServer(new ServerSessionFrameListener.Adapter()
+ {
+ @Override
+ public StreamFrameListener onSyn(Stream stream, SynInfo synInfo)
+ {
+ Headers responseHeaders = new Headers();
+ responseHeaders.put(HTTPSPDYHeader.VERSION.name(version()), "HTTP/1.1");
+ responseHeaders.put(HTTPSPDYHeader.STATUS.name(version()), "200 OK");
+
+ Headers pushHeaders = new Headers();
+ pushHeaders.put(HTTPSPDYHeader.URI.name(version()), "/push");
+ stream.syn(new SynInfo(pushHeaders, false), 5, TimeUnit.SECONDS, new Handler.Adapter<Stream>()
+ {
+ @Override
+ public void completed(Stream pushStream)
+ {
+ pushStream.data(new BytesDataInfo(data, true));
+ }
+ });
+
+ stream.reply(new ReplyInfo(responseHeaders, true));
+ return null;
+ }
+ }));
+
+ Socket client = new Socket();
+ client.connect(proxyAddress);
+ OutputStream output = client.getOutputStream();
+
+ String request = "" +
+ "GET / HTTP/1.1\r\n" +
+ "Host: localhost:" + proxyAddress.getPort() + "\r\n" +
+ "\r\n";
+ output.write(request.getBytes("UTF-8"));
+ output.flush();
+
+ client.setSoTimeout(1000);
+ InputStream input = client.getInputStream();
+ BufferedReader reader = new BufferedReader(new InputStreamReader(input, "UTF-8"));
+ String line = reader.readLine();
+ Assert.assertTrue(line.contains(" 200"));
+ while (line.length() > 0)
+ line = reader.readLine();
+ Assert.assertFalse(reader.ready());
+
+ client.close();
+ }
+
+ @Test
+ public void testSYNThenSPDYPushIsReceived() throws Exception
+ {
+ final byte[] data = "0123456789ABCDEF".getBytes("UTF-8");
+ InetSocketAddress proxyAddress = startProxy(startServer(new ServerSessionFrameListener.Adapter()
+ {
+ @Override
+ public StreamFrameListener onSyn(Stream stream, SynInfo synInfo)
+ {
+ Headers responseHeaders = new Headers();
+ responseHeaders.put(HTTPSPDYHeader.VERSION.name(version()), "HTTP/1.1");
+ responseHeaders.put(HTTPSPDYHeader.STATUS.name(version()), "200 OK");
+ stream.reply(new ReplyInfo(responseHeaders, false));
+
+ Headers pushHeaders = new Headers();
+ pushHeaders.put(HTTPSPDYHeader.URI.name(version()), "/push");
+ stream.syn(new SynInfo(pushHeaders, false), 5, TimeUnit.SECONDS, new Handler.Adapter<Stream>()
+ {
+ @Override
+ public void completed(Stream pushStream)
+ {
+ pushStream.data(new BytesDataInfo(data, true));
+ }
+ });
+
+ stream.data(new BytesDataInfo(data, true));
+
+ return null;
+ }
+ }));
+ proxyConnector.setDefaultAsyncConnectionFactory(proxyConnector.getAsyncConnectionFactory("spdy/" + version()));
+
+ final CountDownLatch pushSynLatch = new CountDownLatch(1);
+ final CountDownLatch pushDataLatch = new CountDownLatch(1);
+ Session client = factory.newSPDYClient(version()).connect(proxyAddress, new SessionFrameListener.Adapter()
+ {
+ @Override
+ public StreamFrameListener onSyn(Stream stream, SynInfo synInfo)
+ {
+ pushSynLatch.countDown();
+ return new StreamFrameListener.Adapter()
+ {
+ @Override
+ public void onData(Stream stream, DataInfo dataInfo)
+ {
+ dataInfo.consume(dataInfo.length());
+ if (dataInfo.isClose())
+ pushDataLatch.countDown();
+ }
+ };
+ }
+ }).get(5, TimeUnit.SECONDS);
+
+ Headers headers = new Headers();
+ headers.put(HTTPSPDYHeader.HOST.name(version()), "localhost:" + proxyAddress.getPort());
+ final CountDownLatch replyLatch = new CountDownLatch(1);
+ final CountDownLatch dataLatch = new CountDownLatch(1);
+ client.syn(new SynInfo(headers, true), new StreamFrameListener.Adapter()
+ {
+ @Override
+ public void onReply(Stream stream, ReplyInfo replyInfo)
+ {
+ replyLatch.countDown();
+ }
+
+ @Override
+ public void onData(Stream stream, DataInfo dataInfo)
+ {
+ dataInfo.consume(dataInfo.length());
+ if (dataInfo.isClose())
+ dataLatch.countDown();
+ }
+ });
+
+ Assert.assertTrue(replyLatch.await(5, TimeUnit.SECONDS));
+ Assert.assertTrue(pushSynLatch.await(5, TimeUnit.SECONDS));
+ Assert.assertTrue(pushDataLatch.await(5, TimeUnit.SECONDS));
+ Assert.assertTrue(dataLatch.await(5, TimeUnit.SECONDS));
+
+ client.goAway().get(5, TimeUnit.SECONDS);
+ }
+
+ @Test
+ public void testPING() throws Exception
+ {
+ // PING is per hop, and it does not carry the information to which server to ping to
+ // We just verify that it works
+
+ InetSocketAddress proxyAddress = startProxy(startServer(new ServerSessionFrameListener.Adapter()));
+ proxyConnector.setDefaultAsyncConnectionFactory(proxyConnector.getAsyncConnectionFactory("spdy/" + version()));
+
+ final CountDownLatch pingLatch = new CountDownLatch(1);
+ Session client = factory.newSPDYClient(version()).connect(proxyAddress, new SessionFrameListener.Adapter()
+ {
+ @Override
+ public void onPing(Session session, PingInfo pingInfo)
+ {
+ pingLatch.countDown();
+ }
+ }).get(5, TimeUnit.SECONDS);
+
+ client.ping().get(5, TimeUnit.SECONDS);
+
+ Assert.assertTrue(pingLatch.await(5, TimeUnit.SECONDS));
+
+ client.goAway().get(5, TimeUnit.SECONDS);
+ }
+
+ @Test
+ public void testGETThenReset() throws Exception
+ {
+ InetSocketAddress proxyAddress = startProxy(startServer(new ServerSessionFrameListener.Adapter()
+ {
+ @Override
+ public StreamFrameListener onSyn(Stream stream, SynInfo synInfo)
+ {
+ Assert.assertTrue(synInfo.isClose());
+ Headers requestHeaders = synInfo.getHeaders();
+ Assert.assertNotNull(requestHeaders.get("via"));
+
+ stream.getSession().rst(new RstInfo(stream.getId(), StreamStatus.REFUSED_STREAM));
+
+ return null;
+ }
+ }));
+
+ Socket client = new Socket();
+ client.connect(proxyAddress);
+ OutputStream output = client.getOutputStream();
+
+ String request = "" +
+ "GET / HTTP/1.1\r\n" +
+ "Host: localhost:" + proxyAddress.getPort() + "\r\n" +
+ "\r\n";
+ output.write(request.getBytes("UTF-8"));
+ output.flush();
+
+ InputStream input = client.getInputStream();
+ BufferedReader reader = new BufferedReader(new InputStreamReader(input, "UTF-8"));
+ Assert.assertNull(reader.readLine());
+
+ client.close();
+ }
+
+ @Test
+ public void testSYNThenReset() throws Exception
+ {
+ InetSocketAddress proxyAddress = startProxy(startServer(new ServerSessionFrameListener.Adapter()
+ {
+ @Override
+ public StreamFrameListener onSyn(Stream stream, SynInfo synInfo)
+ {
+ Assert.assertTrue(synInfo.isClose());
+ Headers requestHeaders = synInfo.getHeaders();
+ Assert.assertNotNull(requestHeaders.get("via"));
+
+ stream.getSession().rst(new RstInfo(stream.getId(), StreamStatus.REFUSED_STREAM));
+
+ return null;
+ }
+ }));
+ proxyConnector.setDefaultAsyncConnectionFactory(proxyConnector.getAsyncConnectionFactory("spdy/" + version()));
+
+ final CountDownLatch resetLatch = new CountDownLatch(1);
+ Session client = factory.newSPDYClient(version()).connect(proxyAddress, new SessionFrameListener.Adapter()
+ {
+ @Override
+ public void onRst(Session session, RstInfo rstInfo)
+ {
+ resetLatch.countDown();
+ }
+ }).get(5, TimeUnit.SECONDS);
+
+ Headers headers = new Headers();
+ headers.put(HTTPSPDYHeader.HOST.name(version()), "localhost:" + proxyAddress.getPort());
+ client.syn(new SynInfo(headers, true), null);
+
+ Assert.assertTrue(resetLatch.await(5, TimeUnit.SECONDS));
+
+ client.goAway().get(5, TimeUnit.SECONDS);
+ }
+}
diff --git a/jetty-spdy/spdy-jetty/src/main/java/org/eclipse/jetty/spdy/AsyncConnectionFactory.java b/jetty-spdy/spdy-jetty/src/main/java/org/eclipse/jetty/spdy/AsyncConnectionFactory.java
index 3707787047..97f9db59c4 100644
--- a/jetty-spdy/spdy-jetty/src/main/java/org/eclipse/jetty/spdy/AsyncConnectionFactory.java
+++ b/jetty-spdy/spdy-jetty/src/main/java/org/eclipse/jetty/spdy/AsyncConnectionFactory.java
@@ -1,18 +1,16 @@
-/*
- * Copyright (c) 2012 the original author or authors.
- *
- * 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.
- */
+//========================================================================
+//Copyright 2011-2012 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.spdy;
diff --git a/jetty-spdy/spdy-jetty/src/main/java/org/eclipse/jetty/spdy/EmptyAsyncConnection.java b/jetty-spdy/spdy-jetty/src/main/java/org/eclipse/jetty/spdy/EmptyAsyncConnection.java
index 70a9ac146a..a2888ce88e 100644
--- a/jetty-spdy/spdy-jetty/src/main/java/org/eclipse/jetty/spdy/EmptyAsyncConnection.java
+++ b/jetty-spdy/spdy-jetty/src/main/java/org/eclipse/jetty/spdy/EmptyAsyncConnection.java
@@ -1,18 +1,16 @@
-/*
- * Copyright (c) 2012 the original author or authors.
- *
- * 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.
- */
+//========================================================================
+//Copyright 2011-2012 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.spdy;
diff --git a/jetty-spdy/spdy-jetty/src/main/java/org/eclipse/jetty/spdy/EmptyAsyncEndPoint.java b/jetty-spdy/spdy-jetty/src/main/java/org/eclipse/jetty/spdy/EmptyAsyncEndPoint.java
index c1fd5e2e25..58dbc8a9aa 100644
--- a/jetty-spdy/spdy-jetty/src/main/java/org/eclipse/jetty/spdy/EmptyAsyncEndPoint.java
+++ b/jetty-spdy/spdy-jetty/src/main/java/org/eclipse/jetty/spdy/EmptyAsyncEndPoint.java
@@ -1,18 +1,16 @@
-/*
- * Copyright (c) 2012 the original author or authors.
- *
- * 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.
- */
+//========================================================================
+//Copyright 2011-2012 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.spdy;
diff --git a/jetty-spdy/spdy-jetty/src/main/java/org/eclipse/jetty/spdy/FlowControlStrategyFactory.java b/jetty-spdy/spdy-jetty/src/main/java/org/eclipse/jetty/spdy/FlowControlStrategyFactory.java
new file mode 100644
index 0000000000..a668f2f2f0
--- /dev/null
+++ b/jetty-spdy/spdy-jetty/src/main/java/org/eclipse/jetty/spdy/FlowControlStrategyFactory.java
@@ -0,0 +1,37 @@
+//========================================================================
+//Copyright 2011-2012 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.spdy;
+
+import org.eclipse.jetty.spdy.api.SPDY;
+
+public class FlowControlStrategyFactory
+{
+ private FlowControlStrategyFactory()
+ {
+ }
+
+ public static FlowControlStrategy newFlowControlStrategy(short version)
+ {
+ switch (version)
+ {
+ case SPDY.V2:
+ return new FlowControlStrategy.None();
+ case SPDY.V3:
+ return new SPDYv3FlowControlStrategy();
+ default:
+ throw new IllegalStateException();
+ }
+ }
+}
diff --git a/jetty-spdy/spdy-jetty/src/main/java/org/eclipse/jetty/spdy/SPDYAsyncConnection.java b/jetty-spdy/spdy-jetty/src/main/java/org/eclipse/jetty/spdy/SPDYAsyncConnection.java
index 40dfecde36..bb6b45cd5e 100644
--- a/jetty-spdy/spdy-jetty/src/main/java/org/eclipse/jetty/spdy/SPDYAsyncConnection.java
+++ b/jetty-spdy/spdy-jetty/src/main/java/org/eclipse/jetty/spdy/SPDYAsyncConnection.java
@@ -1,18 +1,16 @@
-/*
- * Copyright (c) 2012 the original author or authors.
- *
- * 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.
- */
+//========================================================================
+//Copyright 2011-2012 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.spdy;
@@ -122,7 +120,8 @@ public class SPDYAsyncConnection extends AbstractConnection implements AsyncConn
catch (Exception x)
{
close(false);
- handler.failed(x);
+ handler.failed(context, x);
+ return -1;
}
finally
{
@@ -222,6 +221,7 @@ public class SPDYAsyncConnection extends AbstractConnection implements AsyncConn
@Override
public void onIdleExpired(long idleForMs)
{
+ logger.debug("Idle timeout expired for {}", getEndPoint());
session.goAway();
}
@@ -234,4 +234,9 @@ public class SPDYAsyncConnection extends AbstractConnection implements AsyncConn
{
this.session = session;
}
+
+ public String toString()
+ {
+ return String.format("%s@%x{endp=%s@%x}",getClass().getSimpleName(),hashCode(),getEndPoint().getClass().getSimpleName(),getEndPoint().hashCode());
+ }
}
diff --git a/jetty-spdy/spdy-jetty/src/main/java/org/eclipse/jetty/spdy/SPDYClient.java b/jetty-spdy/spdy-jetty/src/main/java/org/eclipse/jetty/spdy/SPDYClient.java
index 438e2e3cf0..65ecc2f53a 100644
--- a/jetty-spdy/spdy-jetty/src/main/java/org/eclipse/jetty/spdy/SPDYClient.java
+++ b/jetty-spdy/spdy-jetty/src/main/java/org/eclipse/jetty/spdy/SPDYClient.java
@@ -1,23 +1,16 @@
-/*
- * Copyright (c) 2012 the original author or authors.
- *
- * 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.
- */
-
-/*
- * To change this template, choose Tools | Templates
- * and open the template in the editor.
- */
+//========================================================================
+//Copyright 2011-2012 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.spdy;
@@ -38,7 +31,6 @@ import java.util.concurrent.Executors;
import java.util.concurrent.Future;
import java.util.concurrent.RejectedExecutionException;
import java.util.concurrent.ScheduledExecutorService;
-import java.util.concurrent.atomic.AtomicReference;
import javax.net.ssl.SSLEngine;
import javax.net.ssl.SSLException;
@@ -64,7 +56,8 @@ public class SPDYClient
private final short version;
private final Factory factory;
private SocketAddress bindAddress;
- private long maxIdleTime;
+ private long maxIdleTime = -1;
+ private volatile int initialWindowSize = 65536;
protected SPDYClient(short version, Factory factory)
{
@@ -101,7 +94,7 @@ public class SPDYClient
channel.socket().setTcpNoDelay(true);
channel.configureBlocking(false);
- SessionPromise result = new SessionPromise(this, listener);
+ SessionPromise result = new SessionPromise(channel, this, listener);
channel.connect(address);
factory.selector.register(channel, result);
@@ -119,6 +112,16 @@ public class SPDYClient
this.maxIdleTime = maxIdleTime;
}
+ public int getInitialWindowSize()
+ {
+ return initialWindowSize;
+ }
+
+ public void setInitialWindowSize(int initialWindowSize)
+ {
+ this.initialWindowSize = initialWindowSize;
+ }
+
protected String selectProtocol(List<String> serverProtocols)
{
if (serverProtocols == null)
@@ -173,6 +176,11 @@ public class SPDYClient
return engine;
}
+ protected FlowControlStrategy newFlowControlStrategy()
+ {
+ return FlowControlStrategyFactory.newFlowControlStrategy(version);
+ }
+
public static class Factory extends AggregateLifeCycle
{
private final Map<String, AsyncConnectionFactory> factories = new ConcurrentHashMap<>();
@@ -314,7 +322,7 @@ public class SPDYClient
}
@Override
- public AsyncConnection newConnection(final SocketChannel channel, AsyncEndPoint endPoint, Object attachment)
+ public AsyncConnection newConnection(final SocketChannel channel, AsyncEndPoint endPoint, final Object attachment)
{
SessionPromise sessionPromise = (SessionPromise)attachment;
final SPDYClient client = sessionPromise.client;
@@ -323,31 +331,18 @@ public class SPDYClient
{
if (sslContextFactory != null)
{
- final AtomicReference<AsyncEndPoint> sslEndPointRef = new AtomicReference<>();
- final AtomicReference<Object> attachmentRef = new AtomicReference<>(attachment);
- SSLEngine engine = client.newSSLEngine(sslContextFactory, channel);
+ final SSLEngine engine = client.newSSLEngine(sslContextFactory, channel);
SslConnection sslConnection = new SslConnection(engine, endPoint)
{
@Override
public void onClose()
{
- sslEndPointRef.set(null);
- attachmentRef.set(null);
+ NextProtoNego.remove(engine);
super.onClose();
}
};
endPoint.setConnection(sslConnection);
- AsyncEndPoint sslEndPoint = sslConnection.getSslEndPoint();
- sslEndPointRef.set(sslEndPoint);
-
- // Instances of the ClientProvider inner class strong reference the
- // SslEndPoint (via lexical scoping), which strong references the SSLEngine.
- // Since NextProtoNego stores in a WeakHashMap the SSLEngine as key
- // and this instance as value, we are in the situation where the value
- // of a WeakHashMap refers indirectly to the key, which is bad because
- // the entry will never be removed from the WeakHashMap.
- // We use AtomicReferences to be captured via lexical scoping,
- // and we null them out above when the connection is closed.
+ final AsyncEndPoint sslEndPoint = sslConnection.getSslEndPoint();
NextProtoNego.put(engine, new NextProtoNego.ClientProvider()
{
@Override
@@ -361,8 +356,7 @@ public class SPDYClient
{
// Server does not support NPN, but this is a SPDY client, so hardcode SPDY
ClientSPDYAsyncConnectionFactory connectionFactory = new ClientSPDYAsyncConnectionFactory();
- AsyncEndPoint sslEndPoint = sslEndPointRef.get();
- AsyncConnection connection = connectionFactory.newAsyncConnection(channel, sslEndPoint, attachmentRef.get());
+ AsyncConnection connection = connectionFactory.newAsyncConnection(channel, sslEndPoint, attachment);
sslEndPoint.setConnection(connection);
}
@@ -374,8 +368,7 @@ public class SPDYClient
return null;
AsyncConnectionFactory connectionFactory = client.getAsyncConnectionFactory(protocol);
- AsyncEndPoint sslEndPoint = sslEndPointRef.get();
- AsyncConnection connection = connectionFactory.newAsyncConnection(channel, sslEndPoint, attachmentRef.get());
+ AsyncConnection connection = connectionFactory.newAsyncConnection(channel, sslEndPoint, attachment);
sslEndPoint.setConnection(connection);
return protocol;
}
@@ -398,7 +391,7 @@ public class SPDYClient
}
catch (RuntimeException x)
{
- sessionPromise.failed(x);
+ sessionPromise.failed(null,x);
throw x;
}
}
@@ -419,14 +412,31 @@ public class SPDYClient
private static class SessionPromise extends Promise<Session>
{
+ private final SocketChannel channel;
private final SPDYClient client;
private final SessionFrameListener listener;
- private SessionPromise(SPDYClient client, SessionFrameListener listener)
+ private SessionPromise(SocketChannel channel, SPDYClient client, SessionFrameListener listener)
{
+ this.channel = channel;
this.client = client;
this.listener = listener;
}
+
+ @Override
+ public boolean cancel(boolean mayInterruptIfRunning)
+ {
+ try
+ {
+ super.cancel(mayInterruptIfRunning);
+ channel.close();
+ return true;
+ }
+ catch (IOException x)
+ {
+ return true;
+ }
+ }
}
private static class ClientSPDYAsyncConnectionFactory implements AsyncConnectionFactory
@@ -435,7 +445,8 @@ public class SPDYClient
public AsyncConnection newAsyncConnection(SocketChannel channel, AsyncEndPoint endPoint, Object attachment)
{
SessionPromise sessionPromise = (SessionPromise)attachment;
- Factory factory = sessionPromise.client.factory;
+ SPDYClient client = sessionPromise.client;
+ Factory factory = client.factory;
CompressionFactory compressionFactory = new StandardCompressionFactory();
Parser parser = new Parser(compressionFactory.newDecompressor());
@@ -444,7 +455,10 @@ public class SPDYClient
SPDYAsyncConnection connection = new ClientSPDYAsyncConnection(endPoint, factory.bufferPool, parser, factory);
endPoint.setConnection(connection);
- StandardSession session = new StandardSession(sessionPromise.client.version, factory.bufferPool, factory.threadPool, factory.scheduler, connection, connection, 1, sessionPromise.listener, generator);
+ FlowControlStrategy flowControlStrategy = client.newFlowControlStrategy();
+
+ StandardSession session = new StandardSession(client.version, factory.bufferPool, factory.threadPool, factory.scheduler, connection, connection, 1, sessionPromise.listener, generator, flowControlStrategy);
+ session.setWindowSize(client.getInitialWindowSize());
parser.addListener(session);
sessionPromise.completed(session);
connection.setSession(session);
diff --git a/jetty-spdy/spdy-jetty/src/main/java/org/eclipse/jetty/spdy/SPDYServerConnector.java b/jetty-spdy/spdy-jetty/src/main/java/org/eclipse/jetty/spdy/SPDYServerConnector.java
index 41412b3f0c..f85327189e 100644
--- a/jetty-spdy/spdy-jetty/src/main/java/org/eclipse/jetty/spdy/SPDYServerConnector.java
+++ b/jetty-spdy/spdy-jetty/src/main/java/org/eclipse/jetty/spdy/SPDYServerConnector.java
@@ -1,21 +1,20 @@
-/*
- * Copyright (c) 2012 the original author or authors.
- *
- * 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.
- */
+//========================================================================
+//Copyright 2011-2012 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.spdy;
+import java.io.IOException;
import java.nio.channels.SocketChannel;
import java.util.ArrayList;
import java.util.Collection;
@@ -27,9 +26,9 @@ import java.util.Queue;
import java.util.concurrent.ConcurrentLinkedQueue;
import java.util.concurrent.Executor;
import java.util.concurrent.Executors;
+import java.util.concurrent.RejectedExecutionException;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;
-import java.util.concurrent.atomic.AtomicReference;
import javax.net.ssl.SSLEngine;
import javax.net.ssl.SSLException;
@@ -41,6 +40,7 @@ import org.eclipse.jetty.server.nio.SelectChannelConnector;
import org.eclipse.jetty.spdy.api.SPDY;
import org.eclipse.jetty.spdy.api.Session;
import org.eclipse.jetty.spdy.api.server.ServerSessionFrameListener;
+import org.eclipse.jetty.util.component.AggregateLifeCycle;
import org.eclipse.jetty.util.log.Log;
import org.eclipse.jetty.util.log.Logger;
import org.eclipse.jetty.util.ssl.SslContextFactory;
@@ -54,10 +54,12 @@ public class SPDYServerConnector extends SelectChannelConnector
private final Map<String, AsyncConnectionFactory> factories = new LinkedHashMap<>();
private final Queue<Session> sessions = new ConcurrentLinkedQueue<>();
private final ByteBufferPool bufferPool = new StandardByteBufferPool();
+ private final Executor executor = new LazyExecutor();
private final ScheduledExecutorService scheduler = Executors.newSingleThreadScheduledExecutor();
private final ServerSessionFrameListener listener;
private final SslContextFactory sslContextFactory;
- private AsyncConnectionFactory defaultConnectionFactory;
+ private volatile AsyncConnectionFactory defaultConnectionFactory;
+ private volatile int initialWindowSize = 65536;
public SPDYServerConnector(ServerSessionFrameListener listener)
{
@@ -70,6 +72,9 @@ public class SPDYServerConnector extends SelectChannelConnector
this.sslContextFactory = sslContextFactory;
if (sslContextFactory != null)
addBean(sslContextFactory);
+ putAsyncConnectionFactory("spdy/3", new ServerSPDYAsyncConnectionFactory(SPDY.V3, bufferPool, executor, scheduler, listener));
+ putAsyncConnectionFactory("spdy/2", new ServerSPDYAsyncConnectionFactory(SPDY.V2, bufferPool, executor, scheduler, listener));
+ setDefaultAsyncConnectionFactory(getAsyncConnectionFactory("spdy/2"));
}
public ByteBufferPool getByteBufferPool()
@@ -79,17 +84,7 @@ public class SPDYServerConnector extends SelectChannelConnector
public Executor getExecutor()
{
- final ThreadPool threadPool = getThreadPool();
- if (threadPool instanceof Executor)
- return (Executor)threadPool;
- return new Executor()
- {
- @Override
- public void execute(Runnable command)
- {
- threadPool.dispatch(command);
- }
- };
+ return executor;
}
public ScheduledExecutorService getScheduler()
@@ -97,6 +92,11 @@ public class SPDYServerConnector extends SelectChannelConnector
return scheduler;
}
+ public ServerSessionFrameListener getServerSessionFrameListener()
+ {
+ return listener;
+ }
+
public SslContextFactory getSslContextFactory()
{
return sslContextFactory;
@@ -106,8 +106,6 @@ public class SPDYServerConnector extends SelectChannelConnector
protected void doStart() throws Exception
{
super.doStart();
- defaultConnectionFactory = new ServerSPDYAsyncConnectionFactory(SPDY.V2, getByteBufferPool(), getExecutor(), scheduler, listener);
- putAsyncConnectionFactory("spdy/2", defaultConnectionFactory);
logger.info("SPDY support is experimental. Please report feedback at jetty-dev@eclipse.org");
}
@@ -158,6 +156,14 @@ public class SPDYServerConnector extends SelectChannelConnector
}
}
+ public void clearAsyncConnectionFactories()
+ {
+ synchronized (factories)
+ {
+ factories.clear();
+ }
+ }
+
protected List<String> provideProtocols()
{
synchronized (factories)
@@ -166,46 +172,39 @@ public class SPDYServerConnector extends SelectChannelConnector
}
}
- protected AsyncConnectionFactory getDefaultAsyncConnectionFactory()
+ public AsyncConnectionFactory getDefaultAsyncConnectionFactory()
{
return defaultConnectionFactory;
}
+ public void setDefaultAsyncConnectionFactory(AsyncConnectionFactory defaultConnectionFactory)
+ {
+ this.defaultConnectionFactory = defaultConnectionFactory;
+ }
+
@Override
protected AsyncConnection newConnection(final SocketChannel channel, AsyncEndPoint endPoint)
{
if (sslContextFactory != null)
{
- SSLEngine engine = newSSLEngine(sslContextFactory, channel);
- final AtomicReference<AsyncEndPoint> sslEndPointRef = new AtomicReference<>();
+ final SSLEngine engine = newSSLEngine(sslContextFactory, channel);
SslConnection sslConnection = new SslConnection(engine, endPoint)
{
@Override
public void onClose()
{
- sslEndPointRef.set(null);
+ NextProtoNego.remove(engine);
super.onClose();
}
};
endPoint.setConnection(sslConnection);
- AsyncEndPoint sslEndPoint = sslConnection.getSslEndPoint();
- sslEndPointRef.set(sslEndPoint);
-
- // Instances of the ServerProvider inner class strong reference the
- // SslEndPoint (via lexical scoping), which strong references the SSLEngine.
- // Since NextProtoNego stores in a WeakHashMap the SSLEngine as key
- // and this instance as value, we are in the situation where the value
- // of a WeakHashMap refers indirectly to the key, which is bad because
- // the entry will never be removed from the WeakHashMap.
- // We use AtomicReferences to be captured via lexical scoping,
- // and we null them out above when the connection is closed.
+ final AsyncEndPoint sslEndPoint = sslConnection.getSslEndPoint();
NextProtoNego.put(engine, new NextProtoNego.ServerProvider()
{
@Override
public void unsupported()
{
AsyncConnectionFactory connectionFactory = getDefaultAsyncConnectionFactory();
- AsyncEndPoint sslEndPoint = sslEndPointRef.get();
AsyncConnection connection = connectionFactory.newAsyncConnection(channel, sslEndPoint, SPDYServerConnector.this);
sslEndPoint.setConnection(connection);
}
@@ -220,7 +219,6 @@ public class SPDYServerConnector extends SelectChannelConnector
public void protocolSelected(String protocol)
{
AsyncConnectionFactory connectionFactory = getAsyncConnectionFactory(protocol);
- AsyncEndPoint sslEndPoint = sslEndPointRef.get();
AsyncConnection connection = connectionFactory.newAsyncConnection(channel, sslEndPoint, SPDYServerConnector.this);
sslEndPoint.setConnection(connection);
}
@@ -242,6 +240,11 @@ public class SPDYServerConnector extends SelectChannelConnector
}
}
+ protected FlowControlStrategy newFlowControlStrategy(short version)
+ {
+ return FlowControlStrategyFactory.newFlowControlStrategy(version);
+ }
+
protected SSLEngine newSSLEngine(SslContextFactory sslContextFactory, SocketChannel channel)
{
String peerHost = channel.socket().getInetAddress().getHostAddress();
@@ -287,4 +290,36 @@ public class SPDYServerConnector extends SelectChannelConnector
{
return Collections.unmodifiableCollection(sessions);
}
+
+ public int getInitialWindowSize()
+ {
+ return initialWindowSize;
+ }
+
+ public void setInitialWindowSize(int initialWindowSize)
+ {
+ this.initialWindowSize = initialWindowSize;
+ }
+
+ private class LazyExecutor implements Executor
+ {
+ @Override
+ public void execute(Runnable command)
+ {
+ ThreadPool threadPool = getThreadPool();
+ if (threadPool == null)
+ throw new RejectedExecutionException();
+ threadPool.dispatch(command);
+ }
+ }
+
+
+ @Override
+ public void dump(Appendable out, String indent) throws IOException
+ {
+ super.dump(out,indent);
+ AggregateLifeCycle.dump(out, indent, new ArrayList<Session>(sessions));
+ }
+
+
}
diff --git a/jetty-spdy/spdy-jetty/src/main/java/org/eclipse/jetty/spdy/ServerSPDYAsyncConnectionFactory.java b/jetty-spdy/spdy-jetty/src/main/java/org/eclipse/jetty/spdy/ServerSPDYAsyncConnectionFactory.java
index 79ac28d1a0..4e45eedf74 100644
--- a/jetty-spdy/spdy-jetty/src/main/java/org/eclipse/jetty/spdy/ServerSPDYAsyncConnectionFactory.java
+++ b/jetty-spdy/spdy-jetty/src/main/java/org/eclipse/jetty/spdy/ServerSPDYAsyncConnectionFactory.java
@@ -1,18 +1,16 @@
-/*
- * Copyright (c) 2012 the original author or authors.
- *
- * 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.
- */
+//========================================================================
+//Copyright 2011-2012 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.spdy;
@@ -50,6 +48,11 @@ public class ServerSPDYAsyncConnectionFactory implements AsyncConnectionFactory
this.listener = listener;
}
+ public short getVersion()
+ {
+ return version;
+ }
+
@Override
public AsyncConnection newAsyncConnection(SocketChannel channel, AsyncEndPoint endPoint, Object attachment)
{
@@ -57,16 +60,17 @@ public class ServerSPDYAsyncConnectionFactory implements AsyncConnectionFactory
Parser parser = new Parser(compressionFactory.newDecompressor());
Generator generator = new Generator(bufferPool, compressionFactory.newCompressor());
- ServerSessionFrameListener listener = this.listener;
- if (listener == null)
- listener = newServerSessionFrameListener(endPoint, attachment);
-
SPDYServerConnector connector = (SPDYServerConnector)attachment;
+ ServerSessionFrameListener listener = provideServerSessionFrameListener(endPoint, attachment);
SPDYAsyncConnection connection = new ServerSPDYAsyncConnection(endPoint, bufferPool, parser, listener, connector);
endPoint.setConnection(connection);
- final StandardSession session = new StandardSession(version, bufferPool, threadPool, scheduler, connection, connection, 2, listener, generator);
+ FlowControlStrategy flowControlStrategy = connector.newFlowControlStrategy(version);
+
+ StandardSession session = new StandardSession(version, bufferPool, threadPool, scheduler, connection, connection, 2, listener, generator, flowControlStrategy);
+ session.setAttribute("org.eclipse.jetty.spdy.remoteAddress", endPoint.getRemoteAddr());
+ session.setWindowSize(connector.getInitialWindowSize());
parser.addListener(session);
connection.setSession(session);
@@ -75,7 +79,7 @@ public class ServerSPDYAsyncConnectionFactory implements AsyncConnectionFactory
return connection;
}
- protected ServerSessionFrameListener newServerSessionFrameListener(AsyncEndPoint endPoint, Object attachment)
+ protected ServerSessionFrameListener provideServerSessionFrameListener(AsyncEndPoint endPoint, Object attachment)
{
return listener;
}
diff --git a/jetty-spdy/spdy-jetty/src/test/java/org/eclipse/jetty/spdy/AbstractTest.java b/jetty-spdy/spdy-jetty/src/test/java/org/eclipse/jetty/spdy/AbstractTest.java
index b30db27724..ea99abd3e2 100644
--- a/jetty-spdy/spdy-jetty/src/test/java/org/eclipse/jetty/spdy/AbstractTest.java
+++ b/jetty-spdy/spdy-jetty/src/test/java/org/eclipse/jetty/spdy/AbstractTest.java
@@ -1,18 +1,16 @@
-/*
- * Copyright (c) 2012 the original author or authors.
- *
- * 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.
- */
+//========================================================================
+//Copyright 2011-2012 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.spdy;
@@ -53,8 +51,16 @@ public abstract class AbstractTest
protected InetSocketAddress startServer(ServerSessionFrameListener listener) throws Exception
{
+ return startServer(SPDY.V2, listener);
+ }
+
+ protected InetSocketAddress startServer(short version, ServerSessionFrameListener listener) throws Exception
+ {
if (connector == null)
connector = newSPDYServerConnector(listener);
+ if (listener == null)
+ listener = connector.getServerSessionFrameListener();
+ connector.setDefaultAsyncConnectionFactory(new ServerSPDYAsyncConnectionFactory(version, connector.getByteBufferPool(), connector.getExecutor(), connector.getScheduler(), listener));
connector.setPort(0);
server = new Server();
server.addConnector(connector);
@@ -69,6 +75,11 @@ public abstract class AbstractTest
protected Session startClient(InetSocketAddress socketAddress, SessionFrameListener listener) throws Exception
{
+ return startClient(SPDY.V2, socketAddress, listener);
+ }
+
+ protected Session startClient(short version, InetSocketAddress socketAddress, SessionFrameListener listener) throws Exception
+ {
if (clientFactory == null)
{
QueuedThreadPool threadPool = new QueuedThreadPool();
@@ -76,7 +87,7 @@ public abstract class AbstractTest
clientFactory = newSPDYClientFactory(threadPool);
clientFactory.start();
}
- return clientFactory.newSPDYClient(SPDY.V2).connect(socketAddress, listener).get(5, TimeUnit.SECONDS);
+ return clientFactory.newSPDYClient(version).connect(socketAddress, listener).get(5, TimeUnit.SECONDS);
}
protected SPDYClient.Factory newSPDYClientFactory(Executor threadPool)
diff --git a/jetty-spdy/spdy-jetty/src/test/java/org/eclipse/jetty/spdy/ClosedStreamTest.java b/jetty-spdy/spdy-jetty/src/test/java/org/eclipse/jetty/spdy/ClosedStreamTest.java
index 7b399f35f1..a6108a3aa6 100644
--- a/jetty-spdy/spdy-jetty/src/test/java/org/eclipse/jetty/spdy/ClosedStreamTest.java
+++ b/jetty-spdy/spdy-jetty/src/test/java/org/eclipse/jetty/spdy/ClosedStreamTest.java
@@ -1,18 +1,15 @@
-/*
- * Copyright (c) 2012 the original author or authors.
- *
- * 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.
- */
+//========================================================================
+//Copyright 2011-2012 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.spdy;
@@ -38,7 +35,6 @@ import org.eclipse.jetty.spdy.api.StringDataInfo;
import org.eclipse.jetty.spdy.api.SynInfo;
import org.eclipse.jetty.spdy.api.server.ServerSessionFrameListener;
import org.eclipse.jetty.spdy.frames.ControlFrame;
-import org.eclipse.jetty.spdy.frames.DataFrame;
import org.eclipse.jetty.spdy.frames.GoAwayFrame;
import org.eclipse.jetty.spdy.frames.RstStreamFrame;
import org.eclipse.jetty.spdy.frames.SynReplyFrame;
@@ -145,14 +141,12 @@ public class ClosedStreamTest extends AbstractTest
public void onReply(Stream stream, ReplyInfo replyInfo)
{
replyReceivedLatch.countDown();
- super.onReply(stream,replyInfo);
}
@Override
public void onData(Stream stream, DataInfo dataInfo)
{
clientReceivedDataLatch.countDown();
- super.onData(stream,dataInfo);
}
}).get();
assertThat("reply has been received by client",replyReceivedLatch.await(5,TimeUnit.SECONDS),is(true));
@@ -204,7 +198,6 @@ public class ClosedStreamTest extends AbstractTest
public void onData(Stream stream, DataInfo dataInfo)
{
serverDataReceivedLatch.countDown();
- super.onData(stream,dataInfo);
}
};
}
@@ -217,7 +210,7 @@ public class ClosedStreamTest extends AbstractTest
final Generator generator = new Generator(new StandardByteBufferPool(),new StandardCompressionFactory().newCompressor());
int streamId = 1;
- ByteBuffer synData = generator.control(new SynStreamFrame(version,SynInfo.FLAG_CLOSE, streamId,0,(byte)0,new Headers()));
+ ByteBuffer synData = generator.control(new SynStreamFrame(version,SynInfo.FLAG_CLOSE, streamId,0,(byte)0,(short)0,new Headers()));
final SocketChannel socketChannel = SocketChannel.open(startServer);
socketChannel.write(synData);
@@ -250,13 +243,6 @@ public class ClosedStreamTest extends AbstractTest
{
clientResetReceivedLatch.countDown();
}
- super.onControlFrame(frame);
- }
-
- @Override
- public void onDataFrame(DataFrame frame, ByteBuffer data)
- {
- super.onDataFrame(frame,data);
}
});
ByteBuffer response = ByteBuffer.allocate(28);
@@ -272,7 +258,7 @@ public class ClosedStreamTest extends AbstractTest
Assert.assertThat(buffer.hasRemaining(), is(false));
assertThat("GoAway frame is received by server", goAwayReceivedLatch.await(5,TimeUnit.SECONDS), is(true));
-
+
socketChannel.close();
}
}
diff --git a/jetty-spdy/spdy-jetty/src/test/java/org/eclipse/jetty/spdy/FlowControlTest.java b/jetty-spdy/spdy-jetty/src/test/java/org/eclipse/jetty/spdy/FlowControlTest.java
index db2303cea3..00c624fc5f 100644
--- a/jetty-spdy/spdy-jetty/src/test/java/org/eclipse/jetty/spdy/FlowControlTest.java
+++ b/jetty-spdy/spdy-jetty/src/test/java/org/eclipse/jetty/spdy/FlowControlTest.java
@@ -1,18 +1,16 @@
-/*
- * Copyright (c) 2012 the original author or authors.
- *
- * 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.
- */
+//========================================================================
+//Copyright 2011-2012 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.spdy;
@@ -25,9 +23,11 @@ import java.util.concurrent.TimeoutException;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.atomic.AtomicReference;
+import org.eclipse.jetty.spdy.api.ByteBufferDataInfo;
import org.eclipse.jetty.spdy.api.BytesDataInfo;
import org.eclipse.jetty.spdy.api.DataInfo;
import org.eclipse.jetty.spdy.api.ReplyInfo;
+import org.eclipse.jetty.spdy.api.SPDY;
import org.eclipse.jetty.spdy.api.SPDYException;
import org.eclipse.jetty.spdy.api.Session;
import org.eclipse.jetty.spdy.api.SessionFrameListener;
@@ -40,6 +40,9 @@ import org.eclipse.jetty.spdy.api.server.ServerSessionFrameListener;
import org.junit.Assert;
import org.junit.Test;
+import static org.hamcrest.Matchers.is;
+import static org.junit.Assert.assertThat;
+
public class FlowControlTest extends AbstractTest
{
@Test
@@ -53,7 +56,7 @@ public class FlowControlTest extends AbstractTest
final AtomicReference<DataInfo> dataInfoRef = new AtomicReference<>();
final CountDownLatch dataLatch = new CountDownLatch(2);
final CountDownLatch settingsLatch = new CountDownLatch(1);
- Session session = startClient(startServer(new ServerSessionFrameListener.Adapter()
+ Session session = startClient(SPDY.V3, startServer(SPDY.V3, new ServerSessionFrameListener.Adapter()
{
@Override
public StreamFrameListener onSyn(Stream stream, SynInfo synInfo)
@@ -112,7 +115,7 @@ public class FlowControlTest extends AbstractTest
final int windowSize = 1536;
final int length = 5 * windowSize;
final CountDownLatch settingsLatch = new CountDownLatch(1);
- Session session = startClient(startServer(new ServerSessionFrameListener.Adapter()
+ Session session = startClient(SPDY.V3, startServer(SPDY.V3, new ServerSessionFrameListener.Adapter()
{
@Override
public void onSettings(Session session, SettingsInfo settingsInfo)
@@ -183,43 +186,22 @@ public class FlowControlTest extends AbstractTest
});
DataInfo dataInfo = exchanger.exchange(null, 5, TimeUnit.SECONDS);
- // Check that we are flow control stalled
- expectException(TimeoutException.class, new Callable<DataInfo>()
- {
- @Override
- public DataInfo call() throws Exception
- {
- return exchanger.exchange(null, 1, TimeUnit.SECONDS);
- }
- });
+ checkThatWeAreFlowControlStalled(exchanger);
+
Assert.assertEquals(windowSize, dataInfo.available());
Assert.assertEquals(0, dataInfo.consumed());
dataInfo.asByteBuffer(true);
dataInfo = exchanger.exchange(null, 5, TimeUnit.SECONDS);
- // Check that we are flow control stalled
- expectException(TimeoutException.class, new Callable<DataInfo>()
- {
- @Override
- public DataInfo call() throws Exception
- {
- return exchanger.exchange(null, 1, TimeUnit.SECONDS);
- }
- });
+ checkThatWeAreFlowControlStalled(exchanger);
+
Assert.assertEquals(0, dataInfo.available());
Assert.assertEquals(0, dataInfo.consumed());
dataInfo.consume(dataInfo.length());
dataInfo = exchanger.exchange(null, 5, TimeUnit.SECONDS);
- // Check that we are flow control stalled
- expectException(TimeoutException.class, new Callable<DataInfo>()
- {
- @Override
- public DataInfo call() throws Exception
- {
- return exchanger.exchange(null, 1, TimeUnit.SECONDS);
- }
- });
+ checkThatWeAreFlowControlStalled(exchanger);
+
Assert.assertEquals(dataInfo.length() / 2, dataInfo.consumed());
dataInfo.asByteBuffer(true);
@@ -236,7 +218,7 @@ public class FlowControlTest extends AbstractTest
final int windowSize = 1536;
final Exchanger<DataInfo> exchanger = new Exchanger<>();
final CountDownLatch settingsLatch = new CountDownLatch(1);
- Session session = startClient(startServer(new ServerSessionFrameListener.Adapter()
+ Session session = startClient(SPDY.V3, startServer(SPDY.V3, new ServerSessionFrameListener.Adapter()
{
@Override
public void onConnect(Session session)
@@ -312,43 +294,22 @@ public class FlowControlTest extends AbstractTest
stream.data(new BytesDataInfo(new byte[length], true));
DataInfo dataInfo = exchanger.exchange(null, 5, TimeUnit.SECONDS);
- // Check that we are flow control stalled
- expectException(TimeoutException.class, new Callable<DataInfo>()
- {
- @Override
- public DataInfo call() throws Exception
- {
- return exchanger.exchange(null, 1, TimeUnit.SECONDS);
- }
- });
+ checkThatWeAreFlowControlStalled(exchanger);
+
Assert.assertEquals(windowSize, dataInfo.available());
Assert.assertEquals(0, dataInfo.consumed());
dataInfo.asByteBuffer(true);
dataInfo = exchanger.exchange(null, 5, TimeUnit.SECONDS);
- // Check that we are flow control stalled
- expectException(TimeoutException.class, new Callable<DataInfo>()
- {
- @Override
- public DataInfo call() throws Exception
- {
- return exchanger.exchange(null, 1, TimeUnit.SECONDS);
- }
- });
+ checkThatWeAreFlowControlStalled(exchanger);
+
Assert.assertEquals(0, dataInfo.available());
Assert.assertEquals(0, dataInfo.consumed());
dataInfo.consume(dataInfo.length());
dataInfo = exchanger.exchange(null, 5, TimeUnit.SECONDS);
- // Check that we are flow control stalled
- expectException(TimeoutException.class, new Callable<DataInfo>()
- {
- @Override
- public DataInfo call() throws Exception
- {
- return exchanger.exchange(null, 1, TimeUnit.SECONDS);
- }
- });
+ checkThatWeAreFlowControlStalled(exchanger);
+
Assert.assertEquals(dataInfo.length() / 2, dataInfo.consumed());
dataInfo.asByteBuffer(true);
@@ -364,7 +325,7 @@ public class FlowControlTest extends AbstractTest
{
final int windowSize = 1024;
final CountDownLatch settingsLatch = new CountDownLatch(1);
- Session session = startClient(startServer(new ServerSessionFrameListener.Adapter()
+ Session session = startClient(SPDY.V3, startServer(SPDY.V3, new ServerSessionFrameListener.Adapter()
{
@Override
public void onSettings(Session session, SettingsInfo settingsInfo)
@@ -451,6 +412,64 @@ public class FlowControlTest extends AbstractTest
Assert.assertTrue(latch.await(5, TimeUnit.SECONDS));
}
+ @Test
+ public void testSendBigFileWithoutFlowControl() throws Exception
+ {
+ testSendBigFile(SPDY.V2);
+ }
+
+ @Test
+ public void testSendBigFileWithFlowControl() throws Exception
+ {
+ testSendBigFile(SPDY.V3);
+ }
+
+ private void testSendBigFile(short version) throws Exception
+ {
+ final int dataSize = 1024 * 1024;
+ final ByteBufferDataInfo bigByteBufferDataInfo = new ByteBufferDataInfo(ByteBuffer.allocate(dataSize),false);
+ final CountDownLatch allDataReceivedLatch = new CountDownLatch(1);
+
+ Session session = startClient(version, startServer(version, new ServerSessionFrameListener.Adapter()
+ {
+ @Override
+ public StreamFrameListener onSyn(Stream stream, SynInfo synInfo)
+ {
+ stream.reply(new ReplyInfo(false));
+ stream.data(bigByteBufferDataInfo);
+ return null;
+ }
+ }),new SessionFrameListener.Adapter());
+
+ session.syn(new SynInfo(false),new StreamFrameListener.Adapter()
+ {
+ private int dataBytesReceived;
+
+ @Override
+ public void onData(Stream stream, DataInfo dataInfo)
+ {
+ dataBytesReceived = dataBytesReceived + dataInfo.length();
+ dataInfo.consume(dataInfo.length());
+ if (dataBytesReceived == dataSize)
+ allDataReceivedLatch.countDown();
+ }
+ });
+
+ assertThat("all data bytes have been received by the client", allDataReceivedLatch.await(5, TimeUnit.SECONDS), is(true));
+ }
+
+ private void checkThatWeAreFlowControlStalled(final Exchanger<DataInfo> exchanger)
+ {
+ expectException(TimeoutException.class, new Callable<DataInfo>()
+ {
+ @Override
+ public DataInfo call() throws Exception
+ {
+ return exchanger.exchange(null, 1, TimeUnit.SECONDS);
+ }
+ });
+ }
+
private void expectException(Class<? extends Exception> exception, Callable<DataInfo> command)
{
try
diff --git a/jetty-spdy/spdy-jetty/src/test/java/org/eclipse/jetty/spdy/GoAwayTest.java b/jetty-spdy/spdy-jetty/src/test/java/org/eclipse/jetty/spdy/GoAwayTest.java
index ec2a0f6f67..3f6be74c2d 100644
--- a/jetty-spdy/spdy-jetty/src/test/java/org/eclipse/jetty/spdy/GoAwayTest.java
+++ b/jetty-spdy/spdy-jetty/src/test/java/org/eclipse/jetty/spdy/GoAwayTest.java
@@ -1,18 +1,15 @@
-/*
- * Copyright (c) 2012 the original author or authors.
- *
- * 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.
- */
+//========================================================================
+//Copyright 2011-2012 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.spdy;
@@ -219,10 +216,10 @@ public class GoAwayTest extends AbstractTest
Assert.assertThat(x.getCause(), CoreMatchers.instanceOf(ClosedChannelException.class));
}
- // Be sure the last good stream is the first
+ // The last good stream is the second, because it was received by the server
Assert.assertTrue(goAwayLatch.await(5, TimeUnit.SECONDS));
GoAwayInfo goAway = goAwayRef.get();
Assert.assertNotNull(goAway);
- Assert.assertEquals(stream1.getId(), goAway.getLastStreamId());
+ Assert.assertEquals(stream2.getId(), goAway.getLastStreamId());
}
}
diff --git a/jetty-spdy/spdy-jetty/src/test/java/org/eclipse/jetty/spdy/HeadersTest.java b/jetty-spdy/spdy-jetty/src/test/java/org/eclipse/jetty/spdy/HeadersTest.java
index 154909b00e..20f8a2af52 100644
--- a/jetty-spdy/spdy-jetty/src/test/java/org/eclipse/jetty/spdy/HeadersTest.java
+++ b/jetty-spdy/spdy-jetty/src/test/java/org/eclipse/jetty/spdy/HeadersTest.java
@@ -1,18 +1,16 @@
-/*
- * Copyright (c) 2012 the original author or authors.
- *
- * 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.
- */
+//========================================================================
+//Copyright 2011-2012 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.spdy;
diff --git a/jetty-spdy/spdy-jetty/src/test/java/org/eclipse/jetty/spdy/IdleTimeoutTest.java b/jetty-spdy/spdy-jetty/src/test/java/org/eclipse/jetty/spdy/IdleTimeoutTest.java
index 3138bce5f9..2611bf28c9 100644
--- a/jetty-spdy/spdy-jetty/src/test/java/org/eclipse/jetty/spdy/IdleTimeoutTest.java
+++ b/jetty-spdy/spdy-jetty/src/test/java/org/eclipse/jetty/spdy/IdleTimeoutTest.java
@@ -1,18 +1,16 @@
-/*
- * Copyright (c) 2012 the original author or authors.
- *
- * 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.
- */
+//========================================================================
+//Copyright 2011-2012 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.spdy;
@@ -20,7 +18,6 @@ import java.net.InetSocketAddress;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;
-import org.eclipse.jetty.server.Server;
import org.eclipse.jetty.spdy.api.GoAwayInfo;
import org.eclipse.jetty.spdy.api.ReplyInfo;
import org.eclipse.jetty.spdy.api.SPDY;
@@ -39,7 +36,6 @@ public class IdleTimeoutTest extends AbstractTest
@Test
public void testServerEnforcingIdleTimeout() throws Exception
{
- server = new Server();
connector = newSPDYServerConnector(new ServerSessionFrameListener.Adapter()
{
@Override
@@ -49,13 +45,11 @@ public class IdleTimeoutTest extends AbstractTest
return null;
}
});
- server.addConnector(connector);
int maxIdleTime = 1000;
connector.setMaxIdleTime(maxIdleTime);
- server.start();
final CountDownLatch latch = new CountDownLatch(1);
- Session session = startClient(new InetSocketAddress("localhost", connector.getLocalPort()), new SessionFrameListener.Adapter()
+ Session session = startClient(startServer(null), new SessionFrameListener.Adapter()
{
@Override
public void onGoAway(Session session, GoAwayInfo goAwayInfo)
@@ -72,15 +66,12 @@ public class IdleTimeoutTest extends AbstractTest
@Test
public void testServerEnforcingIdleTimeoutWithUnrespondedStream() throws Exception
{
- server = new Server();
connector = newSPDYServerConnector(null);
- server.addConnector(connector);
int maxIdleTime = 1000;
connector.setMaxIdleTime(maxIdleTime);
- server.start();
final CountDownLatch latch = new CountDownLatch(1);
- Session session = startClient(new InetSocketAddress("localhost", connector.getLocalPort()), new SessionFrameListener.Adapter()
+ Session session = startClient(startServer(null), new SessionFrameListener.Adapter()
{
@Override
public void onGoAway(Session session, GoAwayInfo goAwayInfo)
@@ -99,7 +90,6 @@ public class IdleTimeoutTest extends AbstractTest
public void testServerNotEnforcingIdleTimeoutWithPendingStream() throws Exception
{
final int maxIdleTime = 1000;
- server = new Server();
connector = newSPDYServerConnector(new ServerSessionFrameListener.Adapter()
{
@Override
@@ -118,12 +108,10 @@ public class IdleTimeoutTest extends AbstractTest
}
}
});
- server.addConnector(connector);
connector.setMaxIdleTime(maxIdleTime);
- server.start();
final CountDownLatch latch = new CountDownLatch(1);
- Session session = startClient(new InetSocketAddress("localhost", connector.getLocalPort()), new SessionFrameListener.Adapter()
+ Session session = startClient(startServer(null), new SessionFrameListener.Adapter()
{
@Override
public void onGoAway(Session session, GoAwayInfo goAwayInfo)
diff --git a/jetty-spdy/spdy-jetty/src/test/java/org/eclipse/jetty/spdy/PingTest.java b/jetty-spdy/spdy-jetty/src/test/java/org/eclipse/jetty/spdy/PingTest.java
index aca05954d1..9229e7e883 100644
--- a/jetty-spdy/spdy-jetty/src/test/java/org/eclipse/jetty/spdy/PingTest.java
+++ b/jetty-spdy/spdy-jetty/src/test/java/org/eclipse/jetty/spdy/PingTest.java
@@ -1,18 +1,16 @@
-/*
- * Copyright (c) 2012 the original author or authors.
- *
- * 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.
- */
+//========================================================================
+//Copyright 2011-2012 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.spdy;
diff --git a/jetty-spdy/spdy-jetty/src/test/java/org/eclipse/jetty/spdy/ProtocolViolationsTest.java b/jetty-spdy/spdy-jetty/src/test/java/org/eclipse/jetty/spdy/ProtocolViolationsTest.java
index 791b690677..b0c19f7fe5 100644
--- a/jetty-spdy/spdy-jetty/src/test/java/org/eclipse/jetty/spdy/ProtocolViolationsTest.java
+++ b/jetty-spdy/spdy-jetty/src/test/java/org/eclipse/jetty/spdy/ProtocolViolationsTest.java
@@ -1,3 +1,16 @@
+//========================================================================
+//Copyright 2011-2012 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.spdy;
import static org.junit.Assert.*;
diff --git a/jetty-spdy/spdy-jetty/src/test/java/org/eclipse/jetty/spdy/PushStreamTest.java b/jetty-spdy/spdy-jetty/src/test/java/org/eclipse/jetty/spdy/PushStreamTest.java
index 8843dc12a8..cd21fe5fc5 100644
--- a/jetty-spdy/spdy-jetty/src/test/java/org/eclipse/jetty/spdy/PushStreamTest.java
+++ b/jetty-spdy/spdy-jetty/src/test/java/org/eclipse/jetty/spdy/PushStreamTest.java
@@ -1,41 +1,60 @@
-/*
- * Copyright (c) 2012 the original author or authors.
- *
- * 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.
- */
+//========================================================================
+//Copyright 2011-2012 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.spdy;
+import java.io.IOException;
+import java.net.InetSocketAddress;
import java.nio.ByteBuffer;
+import java.nio.channels.SocketChannel;
import java.util.Arrays;
import java.util.Random;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.CyclicBarrier;
import java.util.concurrent.Exchanger;
+import java.util.concurrent.ExecutionException;
import java.util.concurrent.TimeUnit;
+import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.atomic.AtomicReference;
import org.eclipse.jetty.spdy.api.BytesDataInfo;
import org.eclipse.jetty.spdy.api.DataInfo;
+import org.eclipse.jetty.spdy.api.GoAwayInfo;
import org.eclipse.jetty.spdy.api.Handler;
+import org.eclipse.jetty.spdy.api.Headers;
import org.eclipse.jetty.spdy.api.ReplyInfo;
+import org.eclipse.jetty.spdy.api.RstInfo;
+import org.eclipse.jetty.spdy.api.SPDY;
import org.eclipse.jetty.spdy.api.Session;
import org.eclipse.jetty.spdy.api.SessionFrameListener;
+import org.eclipse.jetty.spdy.api.SessionStatus;
import org.eclipse.jetty.spdy.api.Stream;
import org.eclipse.jetty.spdy.api.StreamFrameListener;
+import org.eclipse.jetty.spdy.api.StreamStatus;
import org.eclipse.jetty.spdy.api.StringDataInfo;
import org.eclipse.jetty.spdy.api.SynInfo;
import org.eclipse.jetty.spdy.api.server.ServerSessionFrameListener;
+import org.eclipse.jetty.spdy.frames.ControlFrame;
+import org.eclipse.jetty.spdy.frames.DataFrame;
+import org.eclipse.jetty.spdy.frames.GoAwayFrame;
+import org.eclipse.jetty.spdy.frames.RstStreamFrame;
+import org.eclipse.jetty.spdy.frames.SynStreamFrame;
+import org.eclipse.jetty.spdy.frames.WindowUpdateFrame;
+import org.eclipse.jetty.spdy.generator.Generator;
+import org.eclipse.jetty.spdy.parser.Parser;
+import org.eclipse.jetty.spdy.parser.Parser.Listener;
+import org.junit.Assert;
import org.junit.Test;
import static org.hamcrest.Matchers.is;
@@ -66,10 +85,10 @@ public class PushStreamTest extends AbstractTest
@Override
public StreamFrameListener onSyn(Stream stream, SynInfo synInfo)
{
- assertThat("streamId is even", stream.getId() % 2, is(0));
- assertThat("stream is unidirectional", stream.isUnidirectional(), is(true));
- assertThat("stream is closed", stream.isClosed(), is(true));
- assertThat("stream has associated stream", stream.getAssociatedStream(), notNullValue());
+ assertThat("streamId is even",stream.getId() % 2,is(0));
+ assertThat("stream is unidirectional",stream.isUnidirectional(),is(true));
+ assertThat("stream is closed",stream.isClosed(),is(true));
+ assertThat("stream has associated stream",stream.getAssociatedStream(),notNullValue());
try
{
stream.reply(new ReplyInfo(false));
@@ -85,10 +104,10 @@ public class PushStreamTest extends AbstractTest
}
});
- Stream stream = clientSession.syn(new SynInfo(true), null).get();
- assertThat("onSyn has been called", pushStreamLatch.await(5, TimeUnit.SECONDS), is(true));
+ Stream stream = clientSession.syn(new SynInfo(true),null).get();
+ assertThat("onSyn has been called",pushStreamLatch.await(5,TimeUnit.SECONDS),is(true));
Stream pushStream = pushStreamRef.get();
- assertThat("main stream and associated stream are the same", stream, sameInstance(pushStream.getAssociatedStream()));
+ assertThat("main stream and associated stream are the same",stream,sameInstance(pushStream.getAssociatedStream()));
}
@Test
@@ -221,7 +240,7 @@ public class PushStreamTest extends AbstractTest
stream.syn(new SynInfo(false),1,TimeUnit.SECONDS,new Handler.Adapter<Stream>()
{
@Override
- public void failed(Throwable x)
+ public void failed(Stream stream, Throwable x)
{
pushStreamFailedLatch.countDown();
}
@@ -321,6 +340,170 @@ public class PushStreamTest extends AbstractTest
return bytes;
}
+
+ @Test
+ public void testClientResetsStreamAfterPushSynDoesPreventSendingDataFramesWithFlowControl() throws Exception
+ {
+ final boolean flowControl = true;
+ testNoMoreFramesAreSentOnPushStreamAfterClientResetsThePushStream(flowControl);
+ }
+
+ @Test
+ public void testClientResetsStreamAfterPushSynDoesPreventSendingDataFramesWithoutFlowControl() throws Exception
+ {
+ final boolean flowControl = false;
+ testNoMoreFramesAreSentOnPushStreamAfterClientResetsThePushStream(flowControl);
+ }
+
+ private volatile boolean read = true;
+ private void testNoMoreFramesAreSentOnPushStreamAfterClientResetsThePushStream(final boolean flowControl) throws Exception, IOException, InterruptedException
+ {
+ final short version = SPDY.V3;
+ final AtomicBoolean unexpectedExceptionOccured = new AtomicBoolean(false);
+ final CountDownLatch resetReceivedLatch = new CountDownLatch(1);
+ final CountDownLatch allDataFramesReceivedLatch = new CountDownLatch(1);
+ final CountDownLatch goAwayReceivedLatch = new CountDownLatch(1);
+ final int dataSizeInBytes = 1024 * 256;
+ final byte[] transferBytes = createHugeByteArray(dataSizeInBytes);
+
+ InetSocketAddress serverAddress = startServer(new ServerSessionFrameListener.Adapter()
+ {
+ @Override
+ public StreamFrameListener onSyn(final Stream stream, SynInfo synInfo)
+ {
+ new Thread(new Runnable()
+ {
+
+ @Override
+ public void run()
+ {
+ Stream pushStream=null;
+ try
+ {
+ stream.reply(new ReplyInfo(false));
+ pushStream = stream.syn(new SynInfo(false)).get();
+ resetReceivedLatch.await(5,TimeUnit.SECONDS);
+ }
+ catch (InterruptedException | ExecutionException e)
+ {
+ e.printStackTrace();
+ unexpectedExceptionOccured.set(true);
+ }
+ pushStream.data(new BytesDataInfo(transferBytes,true));
+ stream.data(new StringDataInfo("close",true));
+ }
+ }).start();
+ return null;
+ }
+
+ @Override
+ public void onRst(Session session, RstInfo rstInfo)
+ {
+ resetReceivedLatch.countDown();
+ }
+
+ @Override
+ public void onGoAway(Session session, GoAwayInfo goAwayInfo)
+ {
+ goAwayReceivedLatch.countDown();
+ }
+ }/*TODO, flowControl*/);
+
+ final SocketChannel channel = SocketChannel.open(serverAddress);
+ final Generator generator = new Generator(new StandardByteBufferPool(),new StandardCompressionFactory.StandardCompressor());
+ int streamId = 1;
+ ByteBuffer writeBuffer = generator.control(new SynStreamFrame(version,(byte)0,streamId,0,(byte)0,(short)0,new Headers()));
+ channel.write(writeBuffer);
+ assertThat("writeBuffer is fully written",writeBuffer.hasRemaining(), is(false));
+
+ final Parser parser = new Parser(new StandardCompressionFactory.StandardDecompressor());
+ parser.addListener(new Listener.Adapter()
+ {
+ int bytesRead = 0;
+
+ @Override
+ public void onControlFrame(ControlFrame frame)
+ {
+ if(frame instanceof SynStreamFrame){
+ int pushStreamId = ((SynStreamFrame)frame).getStreamId();
+ ByteBuffer writeBuffer = generator.control(new RstStreamFrame(version,pushStreamId,StreamStatus.CANCEL_STREAM.getCode(version)));
+ try
+ {
+ channel.write(writeBuffer);
+ }
+ catch (IOException e)
+ {
+ e.printStackTrace();
+ unexpectedExceptionOccured.set(true);
+ }
+ }
+ }
+
+ @Override
+ public void onDataFrame(DataFrame frame, ByteBuffer data)
+ {
+ if(frame.getStreamId() == 2)
+ bytesRead = bytesRead + frame.getLength();
+ if(bytesRead == dataSizeInBytes){
+ allDataFramesReceivedLatch.countDown();
+ return;
+ }
+ if (flowControl)
+ {
+ ByteBuffer writeBuffer = generator.control(new WindowUpdateFrame(version,frame.getStreamId(),frame.getLength()));
+ try
+ {
+ channel.write(writeBuffer);
+ }
+ catch (IOException e)
+ {
+ e.printStackTrace();
+ unexpectedExceptionOccured.set(true);
+ }
+ }
+ }
+ });
+
+ Thread reader = new Thread(new Runnable()
+ {
+ @Override
+ public void run()
+ {
+ ByteBuffer readBuffer = ByteBuffer.allocate(dataSizeInBytes*2);
+ while (read)
+ {
+ try
+ {
+ channel.read(readBuffer);
+ }
+ catch (IOException e)
+ {
+ e.printStackTrace();
+ unexpectedExceptionOccured.set(true);
+ }
+ readBuffer.flip();
+ parser.parse(readBuffer);
+ readBuffer.clear();
+ }
+
+ }
+ });
+ reader.start();
+ read = false;
+
+ assertThat("no unexpected exceptions occured", unexpectedExceptionOccured.get(), is(false));
+ assertThat("not all dataframes have been received as the pushstream has been reset by the client.",allDataFramesReceivedLatch.await(streamId,TimeUnit.SECONDS),is(false));
+
+
+ ByteBuffer buffer = generator.control(new GoAwayFrame(version, streamId, SessionStatus.OK.getCode()));
+ channel.write(buffer);
+ Assert.assertThat(buffer.hasRemaining(), is(false));
+
+ assertThat("GoAway frame is received by server", goAwayReceivedLatch.await(5,TimeUnit.SECONDS), is(true));
+ channel.shutdownOutput();
+ channel.close();
+ }
+
@Test
public void testOddEvenStreamIds() throws Exception
{
@@ -367,6 +550,6 @@ public class PushStreamTest extends AbstractTest
private void assertThatNoExceptionOccured(final CountDownLatch exceptionCountDownLatch) throws InterruptedException
{
- assertThat("No exception occured", exceptionCountDownLatch.await(1,TimeUnit.SECONDS),is(false));
+ assertThat("No exception occured",exceptionCountDownLatch.await(1,TimeUnit.SECONDS),is(false));
}
}
diff --git a/jetty-spdy/spdy-jetty/src/test/java/org/eclipse/jetty/spdy/ResetStreamTest.java b/jetty-spdy/spdy-jetty/src/test/java/org/eclipse/jetty/spdy/ResetStreamTest.java
index 654bb5fddd..3430ff441c 100644
--- a/jetty-spdy/spdy-jetty/src/test/java/org/eclipse/jetty/spdy/ResetStreamTest.java
+++ b/jetty-spdy/spdy-jetty/src/test/java/org/eclipse/jetty/spdy/ResetStreamTest.java
@@ -1,10 +1,17 @@
-package org.eclipse.jetty.spdy;
+//========================================================================
+//Copyright 2011-2012 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.hamcrest.Matchers.is;
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertFalse;
-import static org.junit.Assert.assertThat;
-import static org.junit.Assert.assertTrue;
+package org.eclipse.jetty.spdy;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;
@@ -23,12 +30,18 @@ import org.eclipse.jetty.spdy.api.SynInfo;
import org.eclipse.jetty.spdy.api.server.ServerSessionFrameListener;
import org.junit.Test;
+import static org.hamcrest.Matchers.is;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertThat;
+import static org.junit.Assert.assertTrue;
+
public class ResetStreamTest extends AbstractTest
{
@Test
public void testResetStreamIsRemoved() throws Exception
{
- Session session = startClient(startServer(new ServerSessionFrameListener.Adapter()),null);
+ Session session = startClient(startServer(new ServerSessionFrameListener.Adapter()/*TODO, true*/),null);
Stream stream = session.syn(new SynInfo(false),null).get(5,TimeUnit.SECONDS);
session.rst(new RstInfo(stream.getId(),StreamStatus.CANCEL_STREAM)).get(5,TimeUnit.SECONDS);
@@ -169,7 +182,7 @@ public class ResetStreamTest extends AbstractTest
stream.data(new StringDataInfo("2nd dataframe",false),5L,TimeUnit.SECONDS,new Handler.Adapter<Void>()
{
@Override
- public void failed(Throwable x)
+ public void failed(Void context, Throwable x)
{
failLatch.countDown();
}
diff --git a/jetty-spdy/spdy-jetty/src/test/java/org/eclipse/jetty/spdy/SPDYClientFactoryTest.java b/jetty-spdy/spdy-jetty/src/test/java/org/eclipse/jetty/spdy/SPDYClientFactoryTest.java
index 8124d674a8..84e571b312 100644
--- a/jetty-spdy/spdy-jetty/src/test/java/org/eclipse/jetty/spdy/SPDYClientFactoryTest.java
+++ b/jetty-spdy/spdy-jetty/src/test/java/org/eclipse/jetty/spdy/SPDYClientFactoryTest.java
@@ -1,18 +1,16 @@
-/*
- * Copyright (c) 2012 the original author or authors.
- *
- * 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.
- */
+//========================================================================
+//Copyright 2011-2012 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.spdy;
diff --git a/jetty-spdy/spdy-jetty/src/test/java/org/eclipse/jetty/spdy/SPDYServerConnectorTest.java b/jetty-spdy/spdy-jetty/src/test/java/org/eclipse/jetty/spdy/SPDYServerConnectorTest.java
index d168b11d78..0b46d750ca 100644
--- a/jetty-spdy/spdy-jetty/src/test/java/org/eclipse/jetty/spdy/SPDYServerConnectorTest.java
+++ b/jetty-spdy/spdy-jetty/src/test/java/org/eclipse/jetty/spdy/SPDYServerConnectorTest.java
@@ -1,18 +1,16 @@
-/*
- * Copyright (c) 2012 the original author or authors.
- *
- * 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.
- */
+//========================================================================
+//Copyright 2011-2012 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.spdy;
diff --git a/jetty-spdy/spdy-jetty/src/test/java/org/eclipse/jetty/spdy/SSLEngineLeakTest.java b/jetty-spdy/spdy-jetty/src/test/java/org/eclipse/jetty/spdy/SSLEngineLeakTest.java
index 2e5855118c..d6c4b600f7 100644
--- a/jetty-spdy/spdy-jetty/src/test/java/org/eclipse/jetty/spdy/SSLEngineLeakTest.java
+++ b/jetty-spdy/spdy-jetty/src/test/java/org/eclipse/jetty/spdy/SSLEngineLeakTest.java
@@ -1,3 +1,16 @@
+//========================================================================
+//Copyright 2011-2012 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.spdy;
import java.lang.reflect.Field;
diff --git a/jetty-spdy/spdy-jetty/src/test/java/org/eclipse/jetty/spdy/SSLSynReplyTest.java b/jetty-spdy/spdy-jetty/src/test/java/org/eclipse/jetty/spdy/SSLSynReplyTest.java
index ee8ecdf70c..aa398e0073 100644
--- a/jetty-spdy/spdy-jetty/src/test/java/org/eclipse/jetty/spdy/SSLSynReplyTest.java
+++ b/jetty-spdy/spdy-jetty/src/test/java/org/eclipse/jetty/spdy/SSLSynReplyTest.java
@@ -1,18 +1,16 @@
-/*
- * Copyright (c) 2012 the original author or authors.
- *
- * 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.
- */
+//========================================================================
+//Copyright 2011-2012 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.spdy;
diff --git a/jetty-spdy/spdy-jetty/src/test/java/org/eclipse/jetty/spdy/SettingsTest.java b/jetty-spdy/spdy-jetty/src/test/java/org/eclipse/jetty/spdy/SettingsTest.java
index 9ac5f678c4..8a7731d267 100644
--- a/jetty-spdy/spdy-jetty/src/test/java/org/eclipse/jetty/spdy/SettingsTest.java
+++ b/jetty-spdy/spdy-jetty/src/test/java/org/eclipse/jetty/spdy/SettingsTest.java
@@ -1,18 +1,16 @@
-/*
- * Copyright (c) 2012 the original author or authors.
- *
- * 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.
- */
+//========================================================================
+//Copyright 2011-2012 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.spdy;
diff --git a/jetty-spdy/spdy-jetty/src/test/java/org/eclipse/jetty/spdy/SynDataReplyDataLoadTest.java b/jetty-spdy/spdy-jetty/src/test/java/org/eclipse/jetty/spdy/SynDataReplyDataLoadTest.java
index 129ddd86ac..fe9d070add 100644
--- a/jetty-spdy/spdy-jetty/src/test/java/org/eclipse/jetty/spdy/SynDataReplyDataLoadTest.java
+++ b/jetty-spdy/spdy-jetty/src/test/java/org/eclipse/jetty/spdy/SynDataReplyDataLoadTest.java
@@ -1,18 +1,16 @@
-/*
- * Copyright (c) 2012 the original author or authors.
- *
- * 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.
- */
+//========================================================================
+//Copyright 2011-2012 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.spdy;
diff --git a/jetty-spdy/spdy-jetty/src/test/java/org/eclipse/jetty/spdy/SynReplyTest.java b/jetty-spdy/spdy-jetty/src/test/java/org/eclipse/jetty/spdy/SynReplyTest.java
index 207e1335b0..7d5db72cb0 100644
--- a/jetty-spdy/spdy-jetty/src/test/java/org/eclipse/jetty/spdy/SynReplyTest.java
+++ b/jetty-spdy/spdy-jetty/src/test/java/org/eclipse/jetty/spdy/SynReplyTest.java
@@ -1,18 +1,15 @@
-/*
- * Copyright (c) 2012 the original author or authors.
- *
- * 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.
- */
+//========================================================================
+//Copyright 2011-2012 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.spdy;
diff --git a/jetty-spdy/spdy-jetty/src/test/java/org/eclipse/jetty/spdy/UnsupportedVersionTest.java b/jetty-spdy/spdy-jetty/src/test/java/org/eclipse/jetty/spdy/UnsupportedVersionTest.java
index 78f2163272..0f996bb9e6 100644
--- a/jetty-spdy/spdy-jetty/src/test/java/org/eclipse/jetty/spdy/UnsupportedVersionTest.java
+++ b/jetty-spdy/spdy-jetty/src/test/java/org/eclipse/jetty/spdy/UnsupportedVersionTest.java
@@ -1,3 +1,16 @@
+//========================================================================
+//Copyright 2011-2012 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.spdy;
import java.net.InetSocketAddress;
@@ -44,7 +57,7 @@ public class UnsupportedVersionTest extends AbstractTest
}
});
- SynStreamFrame frame = new SynStreamFrame(SPDY.V2, SynInfo.FLAG_CLOSE, 1, 0, (byte)0, new Headers());
+ SynStreamFrame frame = new SynStreamFrame(SPDY.V2, SynInfo.FLAG_CLOSE, 1, 0, (byte)0, (short)0, new Headers());
Generator generator = new Generator(new StandardByteBufferPool(), new StandardCompressionFactory.StandardCompressor());
ByteBuffer buffer = generator.control(frame);
// Replace the version byte with an unsupported version
diff --git a/jetty-start/src/main/java/org/eclipse/jetty/start/CommandLineBuilder.java b/jetty-start/src/main/java/org/eclipse/jetty/start/CommandLineBuilder.java
index 7d2eb7d3e1..ba2e8b9dc8 100644
--- a/jetty-start/src/main/java/org/eclipse/jetty/start/CommandLineBuilder.java
+++ b/jetty-start/src/main/java/org/eclipse/jetty/start/CommandLineBuilder.java
@@ -1,4 +1,16 @@
package org.eclipse.jetty.start;
+//========================================================================
+//Copyright (c) 2006-2012 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.util.ArrayList;
import java.util.List;
diff --git a/jetty-start/src/main/java/org/eclipse/jetty/start/Main.java b/jetty-start/src/main/java/org/eclipse/jetty/start/Main.java
index d4f503b45e..d5ca325f0d 100644
--- a/jetty-start/src/main/java/org/eclipse/jetty/start/Main.java
+++ b/jetty-start/src/main/java/org/eclipse/jetty/start/Main.java
@@ -31,6 +31,7 @@ import java.lang.reflect.Method;
import java.net.ConnectException;
import java.net.InetAddress;
import java.net.Socket;
+import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
@@ -53,6 +54,9 @@ import java.util.Set;
*/
public class Main
{
+ private static final String START_LOG_FILENAME = "start.log";
+ private static final SimpleDateFormat START_LOG_ROLLOVER_DATEFORMAT = new SimpleDateFormat("yyyy_MM_dd-HHmmSSSSS.'" + START_LOG_FILENAME + "'");
+
private static final int EXIT_USAGE = 1;
private static final int ERR_LOGGING = -1;
private static final int ERR_INVOKE_MAIN = -2;
@@ -71,7 +75,7 @@ public class Main
private String _jettyHome;
- public static void main(String[] args)
+ public static void main(String[] args)
{
try
{
@@ -107,7 +111,6 @@ public class Main
if (arg.length() > 6)
{
arguments.addAll(loadStartIni(new File(arg.substring(6))));
- continue;
}
}
else if (arg.startsWith("--config="))
@@ -152,7 +155,7 @@ public class Main
}
return ini_args;
}
-
+
public List<String> processCommandLine(List<String> arguments) throws Exception
{
// The XML Configuration Files to initialize with
@@ -212,7 +215,9 @@ public class Main
File startDir = new File(System.getProperty("jetty.logs","logs"));
if (!startDir.exists() || !startDir.canWrite())
startDir = new File(".");
- File startLog = new File(startDir,"start.log");
+
+ File startLog = new File(startDir, START_LOG_ROLLOVER_DATEFORMAT.format(new Date()));
+
if (!startLog.exists() && !startLog.createNewFile())
{
// Output about error is lost in majority of cases.
@@ -231,7 +236,7 @@ public class Main
PrintStream logger = new PrintStream(new FileOutputStream(startLog,false));
System.setOut(logger);
System.setErr(logger);
- System.out.println("Establishing start.log on " + new Date());
+ System.out.println("Establishing "+ START_LOG_FILENAME + " on " + new Date());
continue;
}
@@ -475,7 +480,7 @@ public class Main
}
/* ------------------------------------------------------------ */
- public void start(List<String> xmls) throws FileNotFoundException, IOException, InterruptedException
+ public void start(List<String> xmls) throws IOException, InterruptedException
{
// Setup Start / Stop Monitoring
int port = Integer.parseInt(Config.getProperty("STOP.PORT","-1"));
@@ -528,7 +533,7 @@ public class Main
// Show all options with version information
if (_listOptions)
{
- showAllOptionsWithVersions(classpath);
+ showAllOptionsWithVersions();
return;
}
@@ -550,7 +555,7 @@ public class Main
if (_exec)
{
CommandLineBuilder cmd = buildCommandLine(classpath,configuredXmls);
-
+
ProcessBuilder pbuilder = new ProcessBuilder(cmd.getArgs());
final Process process = pbuilder.start();
Runtime.getRuntime().addShutdownHook(new Thread()
@@ -562,13 +567,13 @@ public class Main
process.destroy();
}
});
-
+
copyInThread(process.getErrorStream(),System.err);
copyInThread(process.getInputStream(),System.out);
copyInThread(System.in,process.getOutputStream());
monitor.setProcess(process);
process.waitFor();
-
+
return;
}
@@ -734,7 +739,7 @@ public class Main
return exe;
}
- private void showAllOptionsWithVersions(Classpath classpath)
+ private void showAllOptionsWithVersions()
{
Set<String> sectionIds = _config.getSectionIds();
@@ -1046,19 +1051,15 @@ public class Main
System.err.println(" java -jar start.jar --help # for more information");
System.exit(exit);
}
-
+
/**
* Convert a start.ini format file into an argument list.
*/
static List<String> loadStartIni(File ini)
{
- File startIniFile = ini;
- if (!startIniFile.exists())
+ if (!ini.exists())
{
- if (ini != null)
- {
- System.err.println("Warning - can't find ini file: " + ini);
- }
+ System.err.println("Warning - can't find ini file: " + ini);
// No start.ini found, skip load.
return Collections.emptyList();
}
diff --git a/jetty-start/src/main/java/org/eclipse/jetty/start/Monitor.java b/jetty-start/src/main/java/org/eclipse/jetty/start/Monitor.java
index 17cffd7d0e..4cc367736c 100644
--- a/jetty-start/src/main/java/org/eclipse/jetty/start/Monitor.java
+++ b/jetty-start/src/main/java/org/eclipse/jetty/start/Monitor.java
@@ -99,7 +99,10 @@ public class Monitor extends Thread
new LineNumberReader(new InputStreamReader(socket.getInputStream()));
String key=lin.readLine();
if (!_key.equals(key))
+ {
+ System.err.println("Ignoring command with incorrect key");
continue;
+ }
String cmd=lin.readLine();
Config.debug("command=" + cmd);
@@ -108,7 +111,18 @@ public class Monitor extends Thread
try {socket.close();}catch(Exception e){e.printStackTrace();}
try {_socket.close();}catch(Exception e){e.printStackTrace();}
if (_process!=null)
+ {
+ //if we have a child process, wait for it to finish before we stop
+ try
+ {
_process.destroy();
+ _process.waitFor();
+ }
+ catch (InterruptedException e)
+ {
+ System.err.println("Interrupted waiting for child to terminate");
+ }
+ }
System.exit(0);
}
else if ("status".equals(cmd))
diff --git a/jetty-start/src/test/java/org/eclipse/jetty/start/CommandLineBuilderTest.java b/jetty-start/src/test/java/org/eclipse/jetty/start/CommandLineBuilderTest.java
index 089ed135c2..c4ff43e326 100644
--- a/jetty-start/src/test/java/org/eclipse/jetty/start/CommandLineBuilderTest.java
+++ b/jetty-start/src/test/java/org/eclipse/jetty/start/CommandLineBuilderTest.java
@@ -1,4 +1,16 @@
package org.eclipse.jetty.start;
+//========================================================================
+//Copyright (c) 2006-2012 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.hamcrest.Matchers.*;
import org.junit.Assert;
diff --git a/jetty-util/src/main/java/org/eclipse/jetty/util/Atomics.java b/jetty-util/src/main/java/org/eclipse/jetty/util/Atomics.java
new file mode 100644
index 0000000000..97a3e1be52
--- /dev/null
+++ b/jetty-util/src/main/java/org/eclipse/jetty/util/Atomics.java
@@ -0,0 +1,68 @@
+// ========================================================================
+// Copyright (c) 2012 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.util;
+
+import java.util.concurrent.atomic.AtomicInteger;
+import java.util.concurrent.atomic.AtomicLong;
+
+public class Atomics
+{
+ private Atomics()
+ {
+ }
+
+ public static void updateMin(AtomicLong currentMin, long newValue)
+ {
+ long oldValue = currentMin.get();
+ while (newValue < oldValue)
+ {
+ if (currentMin.compareAndSet(oldValue, newValue))
+ break;
+ oldValue = currentMin.get();
+ }
+ }
+
+ public static void updateMax(AtomicLong currentMax, long newValue)
+ {
+ long oldValue = currentMax.get();
+ while (newValue > oldValue)
+ {
+ if (currentMax.compareAndSet(oldValue, newValue))
+ break;
+ oldValue = currentMax.get();
+ }
+ }
+
+ public static void updateMin(AtomicInteger currentMin, int newValue)
+ {
+ int oldValue = currentMin.get();
+ while (newValue < oldValue)
+ {
+ if (currentMin.compareAndSet(oldValue, newValue))
+ break;
+ oldValue = currentMin.get();
+ }
+ }
+
+ public static void updateMax(AtomicInteger currentMax, int newValue)
+ {
+ int oldValue = currentMax.get();
+ while (newValue > oldValue)
+ {
+ if (currentMax.compareAndSet(oldValue, newValue))
+ break;
+ oldValue = currentMax.get();
+ }
+ }
+}
diff --git a/jetty-util/src/main/java/org/eclipse/jetty/util/ConcurrentHashSet.java b/jetty-util/src/main/java/org/eclipse/jetty/util/ConcurrentHashSet.java
index 844db3a7d5..1aa79efcc4 100644
--- a/jetty-util/src/main/java/org/eclipse/jetty/util/ConcurrentHashSet.java
+++ b/jetty-util/src/main/java/org/eclipse/jetty/util/ConcurrentHashSet.java
@@ -1,4 +1,16 @@
package org.eclipse.jetty.util;
+//========================================================================
+//Copyright (c) 2006-2012 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.util.AbstractSet;
import java.util.Collection;
diff --git a/jetty-util/src/main/java/org/eclipse/jetty/util/Loader.java b/jetty-util/src/main/java/org/eclipse/jetty/util/Loader.java
index 6ede17ad73..b02b6cf1fd 100644
--- a/jetty-util/src/main/java/org/eclipse/jetty/util/Loader.java
+++ b/jetty-util/src/main/java/org/eclipse/jetty/util/Loader.java
@@ -13,11 +13,15 @@
package org.eclipse.jetty.util;
+import java.io.File;
import java.net.URL;
+import java.net.URLClassLoader;
import java.util.Locale;
import java.util.MissingResourceException;
import java.util.ResourceBundle;
+import org.eclipse.jetty.util.resource.Resource;
+
/* ------------------------------------------------------------ */
/** ClassLoader Helper.
* This helper class allows classes to be loaded either from the
@@ -112,7 +116,10 @@ public class Loader
return c;
throw ex;
}
-
+
+
+
+ /* ------------------------------------------------------------ */
public static ResourceBundle getResourceBundle(Class<?> loadClass,String name,boolean checkParents, Locale locale)
throws MissingResourceException
{
@@ -145,6 +152,38 @@ public class Loader
throw ex;
}
-
+
+ /* ------------------------------------------------------------ */
+ /**
+ * Generate the classpath (as a string) of all classloaders
+ * above the given classloader.
+ *
+ * This is primarily used for jasper.
+ * @return the system class path
+ */
+ public static String getClassPath(ClassLoader loader) throws Exception
+ {
+ StringBuilder classpath=new StringBuilder();
+ while (loader != null && (loader instanceof URLClassLoader))
+ {
+ URL[] urls = ((URLClassLoader)loader).getURLs();
+ if (urls != null)
+ {
+ for (int i=0;i<urls.length;i++)
+ {
+ Resource resource = Resource.newResource(urls[i]);
+ File file=resource.getFile();
+ if (file!=null && file.exists())
+ {
+ if (classpath.length()>0)
+ classpath.append(File.pathSeparatorChar);
+ classpath.append(file.getAbsolutePath());
+ }
+ }
+ }
+ loader = loader.getParent();
+ }
+ return classpath.toString();
+ }
}
diff --git a/jetty-util/src/main/java/org/eclipse/jetty/util/MultiPartInputStream.java b/jetty-util/src/main/java/org/eclipse/jetty/util/MultiPartInputStream.java
index 8de5efbcda..d483ea8222 100644
--- a/jetty-util/src/main/java/org/eclipse/jetty/util/MultiPartInputStream.java
+++ b/jetty-util/src/main/java/org/eclipse/jetty/util/MultiPartInputStream.java
@@ -371,7 +371,7 @@ public class MultiPartInputStream
if (!_tmpDir.exists())
_tmpDir.mkdirs();
- String boundary="--"+QuotedStringTokenizer.unquote(value(_contentType.substring(_contentType.indexOf("boundary="))).trim());
+ String boundary="--"+QuotedStringTokenizer.unquote(value(_contentType.substring(_contentType.indexOf("boundary=")), true).trim());
byte[] byteBoundary=(boundary+"--").getBytes(StringUtil.__ISO_8859_1);
// Get first boundary
@@ -440,9 +440,9 @@ public class MultiPartInputStream
if(t.startsWith("form-data"))
form_data=true;
else if(tl.startsWith("name="))
- name=value(t);
+ name=value(t, true);
else if(tl.startsWith("filename="))
- filename=value(t);
+ filename=value(t, false);
}
// Check disposition
@@ -588,7 +588,7 @@ public class MultiPartInputStream
/* ------------------------------------------------------------ */
- private String value(String nameEqualsValue)
+ private String value(String nameEqualsValue, boolean splitAfterSpace)
{
String value=nameEqualsValue.substring(nameEqualsValue.indexOf('=')+1).trim();
int i=value.indexOf(';');
@@ -598,7 +598,7 @@ public class MultiPartInputStream
{
value=value.substring(1,value.indexOf('"',1));
}
- else
+ else if (splitAfterSpace)
{
i=value.indexOf(' ');
if(i>0)
diff --git a/jetty-util/src/main/java/org/eclipse/jetty/util/PatternMatcher.java b/jetty-util/src/main/java/org/eclipse/jetty/util/PatternMatcher.java
index d573906979..12ceff0116 100644
--- a/jetty-util/src/main/java/org/eclipse/jetty/util/PatternMatcher.java
+++ b/jetty-util/src/main/java/org/eclipse/jetty/util/PatternMatcher.java
@@ -1,4 +1,16 @@
package org.eclipse.jetty.util;
+//========================================================================
+//Copyright (c) 2006-2012 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 java.util.ArrayList;
diff --git a/jetty-util/src/main/java/org/eclipse/jetty/util/RunningStats.java b/jetty-util/src/main/java/org/eclipse/jetty/util/RunningStats.java
deleted file mode 100644
index e69de29bb2..0000000000
--- a/jetty-util/src/main/java/org/eclipse/jetty/util/RunningStats.java
+++ /dev/null
diff --git a/jetty-util/src/main/java/org/eclipse/jetty/util/SimpleStats.java b/jetty-util/src/main/java/org/eclipse/jetty/util/SimpleStats.java
deleted file mode 100644
index e69de29bb2..0000000000
--- a/jetty-util/src/main/java/org/eclipse/jetty/util/SimpleStats.java
+++ /dev/null
diff --git a/jetty-util/src/main/java/org/eclipse/jetty/util/URIUtil.java b/jetty-util/src/main/java/org/eclipse/jetty/util/URIUtil.java
index 6a4c066a3f..d18d9a3f72 100644
--- a/jetty-util/src/main/java/org/eclipse/jetty/util/URIUtil.java
+++ b/jetty-util/src/main/java/org/eclipse/jetty/util/URIUtil.java
@@ -252,7 +252,7 @@ public class URIUtil
}
/* ------------------------------------------------------------ */
- /* Decode a URI path.
+ /* Decode a URI path and strip parameters
* @param path The path the encode
* @param buf StringBuilder to encode path into
*/
@@ -260,8 +260,10 @@ public class URIUtil
{
if (path==null)
return null;
+ // Array to hold all converted characters
char[] chars=null;
int n=0;
+ // Array to hold a sequence of %encodings
byte[] bytes=null;
int b=0;
@@ -283,14 +285,26 @@ public class URIUtil
i+=2;
continue;
}
+ else if (c==';')
+ {
+ if (chars==null)
+ {
+ chars=new char[len];
+ path.getChars(0,i,chars,0);
+ n=i;
+ }
+ break;
+ }
else if (bytes==null)
{
n++;
continue;
}
+ // Do we have some bytes to convert?
if (b>0)
{
+ // convert series of bytes and add to chars
String s;
try
{
@@ -311,8 +325,10 @@ public class URIUtil
if (chars==null)
return path;
+ // if we have a remaining sequence of bytes
if (b>0)
{
+ // convert series of bytes and add to chars
String s;
try
{
@@ -330,7 +346,7 @@ public class URIUtil
}
/* ------------------------------------------------------------ */
- /* Decode a URI path.
+ /* Decode a URI path and strip parameters.
* @param path The path the encode
* @param buf StringBuilder to encode path into
*/
@@ -348,6 +364,11 @@ public class URIUtil
b=(byte)(0xff&TypeUtil.parseInt(buf,i+offset+1,2,16));
i+=2;
}
+ else if (b==';')
+ {
+ length=i;
+ break;
+ }
else if (bytes==null)
{
n++;
@@ -439,20 +460,6 @@ public class URIUtil
}
/* ------------------------------------------------------------ */
- /** Strip parameters from a path.
- * Return path upto any semicolon parameters.
- */
- public static String stripPath(String path)
- {
- if (path==null)
- return null;
- int semi=path.indexOf(';');
- if (semi<0)
- return path;
- return path.substring(0,semi);
- }
-
- /* ------------------------------------------------------------ */
/** Convert a path to a cananonical form.
* All instances of "." and ".." are factored out. Null is returned
* if the path tries to .. above its root.
diff --git a/jetty-util/src/main/java/org/eclipse/jetty/util/component/AggregateLifeCycle.java b/jetty-util/src/main/java/org/eclipse/jetty/util/component/AggregateLifeCycle.java
index 917d9ddfc7..55b38fb632 100644
--- a/jetty-util/src/main/java/org/eclipse/jetty/util/component/AggregateLifeCycle.java
+++ b/jetty-util/src/main/java/org/eclipse/jetty/util/component/AggregateLifeCycle.java
@@ -1,4 +1,16 @@
package org.eclipse.jetty.util.component;
+//========================================================================
+//Copyright (c) 2006-2012 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.util.ArrayList;
@@ -374,10 +386,10 @@ public class AggregateLifeCycle extends AbstractLifeCycle implements Destroyable
for (Bean b : _beans)
{
i++;
-
+
+ out.append(indent).append(" +- ");
if (b._managed)
{
- out.append(indent).append(" +- ");
if (b._bean instanceof Dumpable)
((Dumpable)b._bean).dump(out,indent+(i==size?" ":" | "));
else
diff --git a/jetty-util/src/main/java/org/eclipse/jetty/util/component/Destroyable.java b/jetty-util/src/main/java/org/eclipse/jetty/util/component/Destroyable.java
index 2a541ac4d5..62b4c05f53 100644
--- a/jetty-util/src/main/java/org/eclipse/jetty/util/component/Destroyable.java
+++ b/jetty-util/src/main/java/org/eclipse/jetty/util/component/Destroyable.java
@@ -1,4 +1,16 @@
package org.eclipse.jetty.util.component;
+//========================================================================
+//Copyright (c) 2006-2012 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.
+//========================================================================
diff --git a/jetty-util/src/main/java/org/eclipse/jetty/util/component/Dumpable.java b/jetty-util/src/main/java/org/eclipse/jetty/util/component/Dumpable.java
index 061d29225c..429a040ec4 100644
--- a/jetty-util/src/main/java/org/eclipse/jetty/util/component/Dumpable.java
+++ b/jetty-util/src/main/java/org/eclipse/jetty/util/component/Dumpable.java
@@ -1,4 +1,16 @@
package org.eclipse.jetty.util.component;
+//========================================================================
+//Copyright (c) 2006-2012 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;
diff --git a/jetty-util/src/main/java/org/eclipse/jetty/util/component/FileDestroyable.java b/jetty-util/src/main/java/org/eclipse/jetty/util/component/FileDestroyable.java
index 4f5b7b1d0a..566a4b3748 100644
--- a/jetty-util/src/main/java/org/eclipse/jetty/util/component/FileDestroyable.java
+++ b/jetty-util/src/main/java/org/eclipse/jetty/util/component/FileDestroyable.java
@@ -1,4 +1,16 @@
package org.eclipse.jetty.util.component;
+//========================================================================
+//Copyright (c) 2006-2012 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.File;
import java.io.IOException;
diff --git a/jetty-util/src/main/java/org/eclipse/jetty/util/log/AbstractLogger.java b/jetty-util/src/main/java/org/eclipse/jetty/util/log/AbstractLogger.java
index 1320a9fc42..eafbf2bf3c 100644
--- a/jetty-util/src/main/java/org/eclipse/jetty/util/log/AbstractLogger.java
+++ b/jetty-util/src/main/java/org/eclipse/jetty/util/log/AbstractLogger.java
@@ -1,4 +1,16 @@
package org.eclipse.jetty.util.log;
+//========================================================================
+//Copyright (c) 2006-2012 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.
+//========================================================================
/* ------------------------------------------------------------ */
diff --git a/jetty-util/src/main/java/org/eclipse/jetty/util/security/Constraint.java b/jetty-util/src/main/java/org/eclipse/jetty/util/security/Constraint.java
index 320625ca96..ef353c7669 100644
--- a/jetty-util/src/main/java/org/eclipse/jetty/util/security/Constraint.java
+++ b/jetty-util/src/main/java/org/eclipse/jetty/util/security/Constraint.java
@@ -37,6 +37,8 @@ public class Constraint implements Cloneable, Serializable
public final static String __SPNEGO_AUTH = "SPNEGO";
+ public final static String __NEGOTIATE_AUTH = "NEGOTIATE";
+
public static boolean validateMethod (String method)
{
if (method == null)
@@ -47,7 +49,8 @@ public class Constraint implements Cloneable, Serializable
|| method.equals (__DIGEST_AUTH)
|| method.equals (__CERT_AUTH)
|| method.equals(__CERT_AUTH2)
- || method.equals(__SPNEGO_AUTH));
+ || method.equals(__SPNEGO_AUTH)
+ || method.equals(__NEGOTIATE_AUTH));
}
/* ------------------------------------------------------------ */
diff --git a/jetty-util/src/main/java/org/eclipse/jetty/util/statistic/CounterStatistic.java b/jetty-util/src/main/java/org/eclipse/jetty/util/statistic/CounterStatistic.java
index 8c9b33d310..79ec208289 100644
--- a/jetty-util/src/main/java/org/eclipse/jetty/util/statistic/CounterStatistic.java
+++ b/jetty-util/src/main/java/org/eclipse/jetty/util/statistic/CounterStatistic.java
@@ -4,17 +4,19 @@
// All rights reserved. This program and the accompanying materials
// are made available under the terms of the Eclipse Public License v1.0
// and Apache License v2.0 which accompanies this distribution.
-// The Eclipse Public License is available at
+// The Eclipse Public License is available at
// http://www.eclipse.org/legal/epl-v10.html
// The Apache License v2.0 is available at
// http://www.opensource.org/licenses/apache2.0.php
-// You may elect to redistribute this code under either of these licenses.
+// You may elect to redistribute this code under either of these licenses.
// ========================================================================
package org.eclipse.jetty.util.statistic;
import java.util.concurrent.atomic.AtomicLong;
+import org.eclipse.jetty.util.Atomics;
+
/* ------------------------------------------------------------ */
/** Statistics on a counter value.
@@ -22,9 +24,9 @@ import java.util.concurrent.atomic.AtomicLong;
* Keep total, current and maximum values of a counter that
* can be incremented and decremented. The total refers only
* to increments.
- *
+ *
*/
-public class CounterStatistic
+public class CounterStatistic
{
protected final AtomicLong _max = new AtomicLong();
protected final AtomicLong _curr = new AtomicLong();
@@ -39,11 +41,11 @@ public class CounterStatistic
/* ------------------------------------------------------------ */
public void reset(final long value)
{
- _max.set(value);
+ _max.set(value);
_curr.set(value);
_total.set(0); // total always set to 0 to properly calculate cumulative total
}
-
+
/* ------------------------------------------------------------ */
/**
* @param delta the amount to add to the count
@@ -53,15 +55,9 @@ public class CounterStatistic
long value=_curr.addAndGet(delta);
if (delta > 0)
_total.addAndGet(delta);
- long oldValue = _max.get();
- while (value > oldValue)
- {
- if (_max.compareAndSet(oldValue, value))
- break;
- oldValue = _max.get();
- }
+ Atomics.updateMax(_max,value);
}
-
+
/* ------------------------------------------------------------ */
/**
* @param delta the amount to subtract the count by.
@@ -70,7 +66,7 @@ public class CounterStatistic
{
add(-delta);
}
-
+
/* ------------------------------------------------------------ */
/**
*/
@@ -78,7 +74,7 @@ public class CounterStatistic
{
add(1);
}
-
+
/* ------------------------------------------------------------ */
/**
*/
@@ -95,7 +91,7 @@ public class CounterStatistic
{
return _max.get();
}
-
+
/* ------------------------------------------------------------ */
/**
* @return current value
@@ -104,7 +100,7 @@ public class CounterStatistic
{
return _curr.get();
}
-
+
/* ------------------------------------------------------------ */
/**
* @return total value
@@ -113,9 +109,4 @@ public class CounterStatistic
{
return _total.get();
}
-
- /* ------------------------------------------------------------ */
- protected void upxdateMax(long value)
- {
- }
}
diff --git a/jetty-util/src/main/java/org/eclipse/jetty/util/statistic/SampleStatistic.java b/jetty-util/src/main/java/org/eclipse/jetty/util/statistic/SampleStatistic.java
index fbdb422b0b..b887588cc1 100644
--- a/jetty-util/src/main/java/org/eclipse/jetty/util/statistic/SampleStatistic.java
+++ b/jetty-util/src/main/java/org/eclipse/jetty/util/statistic/SampleStatistic.java
@@ -4,23 +4,25 @@
// All rights reserved. This program and the accompanying materials
// are made available under the terms of the Eclipse Public License v1.0
// and Apache License v2.0 which accompanies this distribution.
-// The Eclipse Public License is available at
+// The Eclipse Public License is available at
// http://www.eclipse.org/legal/epl-v10.html
// The Apache License v2.0 is available at
// http://www.opensource.org/licenses/apache2.0.php
-// You may elect to redistribute this code under either of these licenses.
+// You may elect to redistribute this code under either of these licenses.
// ========================================================================
package org.eclipse.jetty.util.statistic;
import java.util.concurrent.atomic.AtomicLong;
+import org.eclipse.jetty.util.Atomics;
+
/* ------------------------------------------------------------ */
/**
* SampledStatistics
* <p>
- * Provides max, total, mean, count, variance, and standard
+ * Provides max, total, mean, count, variance, and standard
* deviation of continuous sequence of samples.
* <p>
* Calculates estimates of mean, variance, and standard deviation
@@ -53,25 +55,17 @@ public class SampleStatistic
{
long total = _total.addAndGet(sample);
long count = _count.incrementAndGet();
-
+
if (count>1)
{
long mean10 = total*10/count;
long delta10 = sample*10 - mean10;
_totalVariance100.addAndGet(delta10*delta10);
- }
-
- long oldMax = _max.get();
- while (sample > oldMax)
- {
- if (_max.compareAndSet(oldMax, sample))
- break;
- oldMax = _max.get();
}
-
+
+ Atomics.updateMax(_max, sample);
}
- /* ------------------------------------------------------------ */
/**
* @return the max value
*/
@@ -80,37 +74,31 @@ public class SampleStatistic
return _max.get();
}
- /* ------------------------------------------------------------ */
public long getTotal()
{
return _total.get();
}
- /* ------------------------------------------------------------ */
public long getCount()
{
return _count.get();
}
- /* ------------------------------------------------------------ */
public double getMean()
{
return (double)_total.get()/_count.get();
}
- /* ------------------------------------------------------------ */
public double getVariance()
{
final long variance100 = _totalVariance100.get();
final long count = _count.get();
-
+
return count>1?((double)variance100)/100.0/(count-1):0.0;
}
- /* ------------------------------------------------------------ */
public double getStdDev()
{
return Math.sqrt(getVariance());
}
-
}
diff --git a/jetty-util/src/main/java/org/eclipse/jetty/util/thread/ShutdownThread.java b/jetty-util/src/main/java/org/eclipse/jetty/util/thread/ShutdownThread.java
index d0bbce9fe0..eb5e9b744c 100644
--- a/jetty-util/src/main/java/org/eclipse/jetty/util/thread/ShutdownThread.java
+++ b/jetty-util/src/main/java/org/eclipse/jetty/util/thread/ShutdownThread.java
@@ -121,8 +121,11 @@ public class ShutdownThread extends Thread
{
try
{
- lifeCycle.stop();
- LOG.debug("Stopped {}",lifeCycle);
+ if (lifeCycle.isStarted())
+ {
+ lifeCycle.stop();
+ LOG.debug("Stopped {}",lifeCycle);
+ }
}
catch (Exception ex)
{
diff --git a/jetty-util/src/test/java/org/eclipse/jetty/util/MultiExceptionTest.java b/jetty-util/src/test/java/org/eclipse/jetty/util/MultiExceptionTest.java
index c6427bc405..51d7b2f8d2 100644
--- a/jetty-util/src/test/java/org/eclipse/jetty/util/MultiExceptionTest.java
+++ b/jetty-util/src/test/java/org/eclipse/jetty/util/MultiExceptionTest.java
@@ -1,4 +1,16 @@
package org.eclipse.jetty.util;
+//========================================================================
+//Copyright (c) 2006-2012 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.junit.Assert.assertTrue;
diff --git a/jetty-util/src/test/java/org/eclipse/jetty/util/MultiMapTest.java b/jetty-util/src/test/java/org/eclipse/jetty/util/MultiMapTest.java
index fe0522021d..dbf221980d 100644
--- a/jetty-util/src/test/java/org/eclipse/jetty/util/MultiMapTest.java
+++ b/jetty-util/src/test/java/org/eclipse/jetty/util/MultiMapTest.java
@@ -1,4 +1,16 @@
package org.eclipse.jetty.util;
+//========================================================================
+//Copyright (c) 2006-2012 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.util.ArrayList;
import java.util.HashMap;
diff --git a/jetty-util/src/test/java/org/eclipse/jetty/util/MultiPartInputStreamTest.java b/jetty-util/src/test/java/org/eclipse/jetty/util/MultiPartInputStreamTest.java
index b4b0b8f611..38e8c49d50 100644
--- a/jetty-util/src/test/java/org/eclipse/jetty/util/MultiPartInputStreamTest.java
+++ b/jetty-util/src/test/java/org/eclipse/jetty/util/MultiPartInputStreamTest.java
@@ -13,9 +13,16 @@
package org.eclipse.jetty.util;
+import static org.hamcrest.Matchers.is;
+import static org.hamcrest.Matchers.not;
+import static org.hamcrest.Matchers.notNullValue;
+import static org.hamcrest.Matchers.nullValue;
+import static org.junit.Assert.assertThat;
+
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.File;
+import java.io.IOException;
import java.io.InputStream;
import java.util.Collection;
@@ -25,6 +32,8 @@ import javax.servlet.http.Part;
import junit.framework.TestCase;
+import org.eclipse.jetty.util.MultiPartInputStream.MultiPart;
+
/**
* MultiPartInputStreamTest
*
@@ -32,19 +41,9 @@ import junit.framework.TestCase;
*/
public class MultiPartInputStreamTest extends TestCase
{
+ private static final String FILENAME = "stuff.txt";
protected String _contentType = "multipart/form-data, boundary=AaB03x";
- protected String _multi =
- "--AaB03x\r\n"+
- "content-disposition: form-data; name=\"field1\"\r\n"+
- "\r\n"+
- "Joe Blow\r\n"+
- "--AaB03x\r\n"+
- "content-disposition: form-data; name=\"stuff\"; filename=\"stuff.txt\"\r\n"+
- "Content-Type: text/plain\r\n"+
- "\r\n"+
- "000000000000000000000000000000000000000000000000000\r\n"+
- "--AaB03x--\r\n";
-
+ protected String _multi = createMultipartRequestString(FILENAME);
protected String _dirname = System.getProperty("java.io.tmpdir")+File.separator+"myfiles-"+System.currentTimeMillis();
@@ -115,17 +114,27 @@ public class MultiPartInputStreamTest extends TestCase
public void testMulti ()
throws Exception
{
+ testMulti(FILENAME);
+ }
+
+ public void testMultiWithSpaceInFilename() throws Exception
+ {
+ testMulti("stuff with spaces.txt");
+ }
+
+ private void testMulti(String filename) throws IOException, ServletException
+ {
MultipartConfigElement config = new MultipartConfigElement(_dirname, 1024, 3072, 50);
- MultiPartInputStream mpis = new MultiPartInputStream(new ByteArrayInputStream(_multi.getBytes()),
- _contentType,
- config,
- new File(_dirname));
+ MultiPartInputStream mpis = new MultiPartInputStream(new ByteArrayInputStream(createMultipartRequestString(filename).getBytes()),
+ _contentType,
+ config,
+ new File(_dirname));
Collection<Part> parts = mpis.getParts();
- assertEquals(2, parts.size());
+ assertThat(parts.size(), is(2));
Part field1 = mpis.getPart("field1");
- assertNotNull(field1);
- assertEquals("field1", field1.getName());
+ assertThat(field1,notNullValue());
+ assertThat(field1.getName(),is("field1"));
InputStream is = field1.getInputStream();
ByteArrayOutputStream os = new ByteArrayOutputStream();
IO.copy(is, os);
@@ -143,23 +152,23 @@ public class MultiPartInputStreamTest extends TestCase
assertFalse(f.exists()); //should have been renamed
field1.delete(); //file should be deleted
assertFalse(f2.exists());
-
- Part stuff = mpis.getPart("stuff");
- assertEquals("text/plain", stuff.getContentType());
- assertEquals("text/plain", stuff.getHeader("Content-Type"));
- assertEquals(1, stuff.getHeaders("content-type").size());
- assertEquals("form-data; name=\"stuff\"; filename=\"stuff.txt\"", stuff.getHeader("content-disposition"));
- assertEquals(2, stuff.getHeaderNames().size());
- assertEquals(51, stuff.getSize());
+ MultiPart stuff = (MultiPart)mpis.getPart("stuff");
+ assertThat(stuff.getContentDispositionFilename(), is(filename));
+ assertThat(stuff.getContentType(),is("text/plain"));
+ assertThat(stuff.getHeader("Content-Type"),is("text/plain"));
+ assertThat(stuff.getHeaders("content-type").size(),is(1));
+ assertThat(stuff.getHeader("content-disposition"),is("form-data; name=\"stuff\"; filename=\"" + filename + "\""));
+ assertThat(stuff.getHeaderNames().size(),is(2));
+ assertThat(stuff.getSize(),is(51L));
f = ((MultiPartInputStream.MultiPart)stuff).getFile();
- assertNotNull(f); // longer than 100 bytes, should already be a file
- assertNull(((MultiPartInputStream.MultiPart)stuff).getBytes()); //not in internal buffer any more
- assertTrue(f.exists());
- assertNotSame("stuff.txt", f.getName());
- stuff.write("stuff.txt");
- f = new File(_dirname+File.separator+"stuff.txt");
- assertTrue(f.exists());
+ assertThat(f,notNullValue()); // longer than 100 bytes, should already be a file
+ assertThat(((MultiPartInputStream.MultiPart)stuff).getBytes(),nullValue()); //not in internal buffer any more
+ assertThat(f.exists(),is(true));
+ assertThat(f.getName(),is(not("stuff with space.txt")));
+ stuff.write(filename);
+ f = new File(_dirname+File.separator+filename);
+ assertThat(f.exists(),is(true));
}
public void testMultiSameNames ()
@@ -193,4 +202,18 @@ public class MultiPartInputStreamTest extends TestCase
assertNotNull(p);
assertEquals(5, p.getSize());
}
+
+ private String createMultipartRequestString(String filename)
+ {
+ return "--AaB03x\r\n"+
+ "content-disposition: form-data; name=\"field1\"\r\n"+
+ "\r\n"+
+ "Joe Blow\r\n"+
+ "--AaB03x\r\n"+
+ "content-disposition: form-data; name=\"stuff\"; filename=\"" + filename + "\"\r\n"+
+ "Content-Type: text/plain\r\n"+
+ "\r\n"+
+ "000000000000000000000000000000000000000000000000000\r\n"+
+ "--AaB03x--\r\n";
+ }
}
diff --git a/jetty-util/src/test/java/org/eclipse/jetty/util/ScannerTest.java b/jetty-util/src/test/java/org/eclipse/jetty/util/ScannerTest.java
index a7992b533e..08011517c5 100644
--- a/jetty-util/src/test/java/org/eclipse/jetty/util/ScannerTest.java
+++ b/jetty-util/src/test/java/org/eclipse/jetty/util/ScannerTest.java
@@ -1,4 +1,16 @@
package org.eclipse.jetty.util;
+//========================================================================
+//Copyright (c) 2006-2012 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.File;
import java.io.FileOutputStream;
diff --git a/jetty-util/src/test/java/org/eclipse/jetty/util/URITest.java b/jetty-util/src/test/java/org/eclipse/jetty/util/URITest.java
index 79f350ff1c..b0e8fc8fa7 100644
--- a/jetty-util/src/test/java/org/eclipse/jetty/util/URITest.java
+++ b/jetty-util/src/test/java/org/eclipse/jetty/util/URITest.java
@@ -51,8 +51,8 @@ public class URITest
@Test
public void testDecodePath()
{
- assertEquals("foo%23;,:=b a r",URIUtil.decodePath("foo%2523%3b%2c:%3db%20a%20r"));
- assertEquals("foo%23;,:=b a r=",URIUtil.decodePath("xxxfoo%2523%3b%2c:%3db%20a%20r%3Dxxx".getBytes(),3,30));
+ assertEquals("foo%23;,:=b a r",URIUtil.decodePath("foo%2523%3b%2c:%3db%20a%20r;rubbish"));
+ assertEquals("foo%23;,:=b a r=",URIUtil.decodePath("xxxfoo%2523%3b%2c:%3db%20a%20r%3Dxxx;rubbish".getBytes(),3,30));
assertEquals("fää%23;,:=b a r=",URIUtil.decodePath("fää%2523%3b%2c:%3db%20a%20r%3D"));
assertEquals("f\u0629\u0629%23;,:=b a r",URIUtil.decodePath("f%d8%a9%d8%a9%2523%3b%2c:%3db%20a%20r"));
}
diff --git a/jetty-util/src/test/java/org/eclipse/jetty/util/component/AggregateLifeCycleTest.java b/jetty-util/src/test/java/org/eclipse/jetty/util/component/AggregateLifeCycleTest.java
index 495c6fd587..ded0981170 100644
--- a/jetty-util/src/test/java/org/eclipse/jetty/util/component/AggregateLifeCycleTest.java
+++ b/jetty-util/src/test/java/org/eclipse/jetty/util/component/AggregateLifeCycleTest.java
@@ -1,4 +1,16 @@
package org.eclipse.jetty.util.component;
+//========================================================================
+//Copyright (c) 2006-2012 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.util.concurrent.atomic.AtomicInteger;
diff --git a/jetty-util/src/test/java/org/eclipse/jetty/util/log/Blue.java b/jetty-util/src/test/java/org/eclipse/jetty/util/log/Blue.java
index 37e91fa919..0fe0cfe530 100644
--- a/jetty-util/src/test/java/org/eclipse/jetty/util/log/Blue.java
+++ b/jetty-util/src/test/java/org/eclipse/jetty/util/log/Blue.java
@@ -1,4 +1,16 @@
package org.eclipse.jetty.util.log;
+//========================================================================
+//Copyright (c) 2006-2012 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.
+//========================================================================
public class Blue
{
diff --git a/jetty-util/src/test/java/org/eclipse/jetty/util/log/CapturingJULHandler.java b/jetty-util/src/test/java/org/eclipse/jetty/util/log/CapturingJULHandler.java
index 1ec646e669..d38b052e4c 100644
--- a/jetty-util/src/test/java/org/eclipse/jetty/util/log/CapturingJULHandler.java
+++ b/jetty-util/src/test/java/org/eclipse/jetty/util/log/CapturingJULHandler.java
@@ -1,4 +1,16 @@
package org.eclipse.jetty.util.log;
+//========================================================================
+//Copyright (c) 2006-2012 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.hamcrest.Matchers.containsString;
diff --git a/jetty-util/src/test/java/org/eclipse/jetty/util/log/Green.java b/jetty-util/src/test/java/org/eclipse/jetty/util/log/Green.java
index 5b4bae7d8d..e5241ebce1 100644
--- a/jetty-util/src/test/java/org/eclipse/jetty/util/log/Green.java
+++ b/jetty-util/src/test/java/org/eclipse/jetty/util/log/Green.java
@@ -1,4 +1,16 @@
package org.eclipse.jetty.util.log;
+//========================================================================
+//Copyright (c) 2006-2012 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.
+//========================================================================
public class Green
{
diff --git a/jetty-util/src/test/java/org/eclipse/jetty/util/log/JavaUtilLogTest.java b/jetty-util/src/test/java/org/eclipse/jetty/util/log/JavaUtilLogTest.java
index 244b1e1306..468de4fdb4 100644
--- a/jetty-util/src/test/java/org/eclipse/jetty/util/log/JavaUtilLogTest.java
+++ b/jetty-util/src/test/java/org/eclipse/jetty/util/log/JavaUtilLogTest.java
@@ -1,4 +1,16 @@
package org.eclipse.jetty.util.log;
+//========================================================================
+//Copyright (c) 2006-2012 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.hamcrest.Matchers.is;
diff --git a/jetty-util/src/test/java/org/eclipse/jetty/util/log/NamedLogTest.java b/jetty-util/src/test/java/org/eclipse/jetty/util/log/NamedLogTest.java
index 4377d5feaf..a1ac4a1c5e 100644
--- a/jetty-util/src/test/java/org/eclipse/jetty/util/log/NamedLogTest.java
+++ b/jetty-util/src/test/java/org/eclipse/jetty/util/log/NamedLogTest.java
@@ -1,4 +1,16 @@
package org.eclipse.jetty.util.log;
+//========================================================================
+//Copyright (c) 2006-2012 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 org.junit.Test;
diff --git a/jetty-util/src/test/java/org/eclipse/jetty/util/log/Red.java b/jetty-util/src/test/java/org/eclipse/jetty/util/log/Red.java
index a0c89b45f2..338f63809c 100644
--- a/jetty-util/src/test/java/org/eclipse/jetty/util/log/Red.java
+++ b/jetty-util/src/test/java/org/eclipse/jetty/util/log/Red.java
@@ -1,4 +1,16 @@
package org.eclipse.jetty.util.log;
+//========================================================================
+//Copyright (c) 2006-2012 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.
+//========================================================================
public class Red
{
diff --git a/jetty-util/src/test/java/org/eclipse/jetty/util/log/Slf4jHelper.java b/jetty-util/src/test/java/org/eclipse/jetty/util/log/Slf4jHelper.java
index 10b2d02c20..d4ce0a88f0 100644
--- a/jetty-util/src/test/java/org/eclipse/jetty/util/log/Slf4jHelper.java
+++ b/jetty-util/src/test/java/org/eclipse/jetty/util/log/Slf4jHelper.java
@@ -1,4 +1,16 @@
package org.eclipse.jetty.util.log;
+//========================================================================
+//Copyright (c) 2006-2012 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.File;
import java.io.FileFilter;
diff --git a/jetty-util/src/test/java/org/eclipse/jetty/util/log/StdErrCapture.java b/jetty-util/src/test/java/org/eclipse/jetty/util/log/StdErrCapture.java
index cd55fc125a..f84b06e1a8 100644
--- a/jetty-util/src/test/java/org/eclipse/jetty/util/log/StdErrCapture.java
+++ b/jetty-util/src/test/java/org/eclipse/jetty/util/log/StdErrCapture.java
@@ -1,4 +1,16 @@
package org.eclipse.jetty.util.log;
+//========================================================================
+//Copyright (c) 2006-2012 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.hamcrest.Matchers.containsString;
import static org.hamcrest.Matchers.not;
diff --git a/jetty-util/src/test/java/org/eclipse/jetty/util/ssl/SslContextFactoryTest.java b/jetty-util/src/test/java/org/eclipse/jetty/util/ssl/SslContextFactoryTest.java
index 4e2c7e1861..9779486eea 100644
--- a/jetty-util/src/test/java/org/eclipse/jetty/util/ssl/SslContextFactoryTest.java
+++ b/jetty-util/src/test/java/org/eclipse/jetty/util/ssl/SslContextFactoryTest.java
@@ -1,4 +1,16 @@
package org.eclipse.jetty.util.ssl;
+//========================================================================
+//Copyright (c) 2006-2012 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 junit.framework.Assert.assertTrue;
diff --git a/jetty-util/src/test/java/org/eclipse/jetty/util/statistic/SampleStatisticTest.java b/jetty-util/src/test/java/org/eclipse/jetty/util/statistic/SampleStatisticTest.java
index 14be1dd65f..3c784ac723 100644
--- a/jetty-util/src/test/java/org/eclipse/jetty/util/statistic/SampleStatisticTest.java
+++ b/jetty-util/src/test/java/org/eclipse/jetty/util/statistic/SampleStatisticTest.java
@@ -1,4 +1,16 @@
package org.eclipse.jetty.util.statistic;
+//========================================================================
+//Copyright (c) 2006-2012 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.junit.Assert.assertTrue;
diff --git a/jetty-webapp/src/main/java/org/eclipse/jetty/webapp/AbstractConfiguration.java b/jetty-webapp/src/main/java/org/eclipse/jetty/webapp/AbstractConfiguration.java
index 8a5d35d37a..90b9739206 100644
--- a/jetty-webapp/src/main/java/org/eclipse/jetty/webapp/AbstractConfiguration.java
+++ b/jetty-webapp/src/main/java/org/eclipse/jetty/webapp/AbstractConfiguration.java
@@ -1,4 +1,16 @@
package org.eclipse.jetty.webapp;
+//========================================================================
+//Copyright (c) 2006-2012 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.
+//========================================================================
public class AbstractConfiguration implements Configuration
{
diff --git a/jetty-webapp/src/main/java/org/eclipse/jetty/webapp/CloneConfiguration.java b/jetty-webapp/src/main/java/org/eclipse/jetty/webapp/CloneConfiguration.java
index d5c06ae93e..23288bfcda 100644
--- a/jetty-webapp/src/main/java/org/eclipse/jetty/webapp/CloneConfiguration.java
+++ b/jetty-webapp/src/main/java/org/eclipse/jetty/webapp/CloneConfiguration.java
@@ -1,4 +1,16 @@
package org.eclipse.jetty.webapp;
+//========================================================================
+//Copyright (c) 2006-2012 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.
+//========================================================================
public class CloneConfiguration extends AbstractConfiguration
diff --git a/jetty-webapp/src/main/java/org/eclipse/jetty/webapp/MetaDataComplete.java b/jetty-webapp/src/main/java/org/eclipse/jetty/webapp/MetaDataComplete.java
index 7b14925f4f..86867c98a5 100644
--- a/jetty-webapp/src/main/java/org/eclipse/jetty/webapp/MetaDataComplete.java
+++ b/jetty-webapp/src/main/java/org/eclipse/jetty/webapp/MetaDataComplete.java
@@ -1,3 +1,15 @@
package org.eclipse.jetty.webapp;
+//========================================================================
+//Copyright (c) 2006-2012 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.
+//========================================================================
public enum MetaDataComplete {NotSet, True, False} \ No newline at end of file
diff --git a/jetty-webapp/src/main/java/org/eclipse/jetty/webapp/Origin.java b/jetty-webapp/src/main/java/org/eclipse/jetty/webapp/Origin.java
index 496de7f854..55c2dada20 100644
--- a/jetty-webapp/src/main/java/org/eclipse/jetty/webapp/Origin.java
+++ b/jetty-webapp/src/main/java/org/eclipse/jetty/webapp/Origin.java
@@ -1,3 +1,15 @@
package org.eclipse.jetty.webapp;
+//========================================================================
+//Copyright (c) 2006-2012 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.
+//========================================================================
public enum Origin {NotSet, WebXml, WebDefaults, WebOverride, WebFragment, Annotation} \ No newline at end of file
diff --git a/jetty-webapp/src/main/java/org/eclipse/jetty/webapp/StandardDescriptorProcessor.java b/jetty-webapp/src/main/java/org/eclipse/jetty/webapp/StandardDescriptorProcessor.java
index 452bbb077e..5d9630f056 100644
--- a/jetty-webapp/src/main/java/org/eclipse/jetty/webapp/StandardDescriptorProcessor.java
+++ b/jetty-webapp/src/main/java/org/eclipse/jetty/webapp/StandardDescriptorProcessor.java
@@ -252,46 +252,33 @@ public class StandardDescriptorProcessor extends IterativeDescriptorProcessor
String servlet_class = node.getString("servlet-class", false, true);
// Handle JSP
- String jspServletName=null;
String jspServletClass=null;;
- boolean hasJSP=false;
+
+ //Handle the default jsp servlet instance
if (id != null && id.equals("jsp"))
{
- jspServletName = servlet_name;
jspServletClass = servlet_class;
try
{
Loader.loadClass(this.getClass(), servlet_class);
- hasJSP = true;
+
+ //Ensure there is a scratch dir
+ if (holder.getInitParameter("scratchdir") == null)
+ {
+ File tmp = context.getTempDirectory();
+ File scratch = new File(tmp, "jsp");
+ if (!scratch.exists()) scratch.mkdir();
+ holder.setInitParameter("scratchdir", scratch.getAbsolutePath());
+ }
}
catch (ClassNotFoundException e)
{
LOG.info("NO JSP Support for {}, did not find {}", context.getContextPath(), servlet_class);
jspServletClass = servlet_class = "org.eclipse.jetty.servlet.NoJspServlet";
}
- if (holder.getInitParameter("scratchdir") == null)
- {
- File tmp = context.getTempDirectory();
- File scratch = new File(tmp, "jsp");
- if (!scratch.exists()) scratch.mkdir();
- holder.setInitParameter("scratchdir", scratch.getAbsolutePath());
-
- if ("?".equals(holder.getInitParameter("classpath")))
- {
- String classpath = context.getClassPath();
- LOG.debug("classpath=" + classpath);
- if (classpath != null)
- holder.setInitParameter("classpath", classpath);
- }
- }
-
- /* Set the webapp's classpath for Jasper */
- context.setAttribute("org.apache.catalina.jsp_classpath", context.getClassPath());
-
- /* Set the system classpath for Jasper */
- holder.setInitParameter("com.sun.appserv.jsp.classpath", getSystemClassPath(context));
}
+
//Set the servlet-class
if (servlet_class != null)
{
@@ -329,14 +316,12 @@ public class StandardDescriptorProcessor extends IterativeDescriptorProcessor
}
}
- // Handler JSP file
+ // Handle JSP file
String jsp_file = node.getString("jsp-file", false, true);
if (jsp_file != null)
{
holder.setForcedPath(jsp_file);
- holder.setClassName(jspServletClass);
- //set the system classpath explicitly for the holder that will represent the JspServlet instance
- holder.setInitParameter("com.sun.appserv.jsp.classpath", getSystemClassPath(context));
+ holder.setClassName(jspServletClass); //only use our default instance
}
// handle load-on-startup
@@ -636,7 +621,8 @@ public class StandardDescriptorProcessor extends IterativeDescriptorProcessor
{
//no servlet mappings
context.getMetaData().setOrigin(servlet_name+".servlet.mappings", descriptor);
- addServletMapping(servlet_name, node, context);
+ ServletMapping mapping = addServletMapping(servlet_name, node, context);
+ mapping.setDefault(context.getMetaData().getOrigin(servlet_name+".servlet.mappings") == Origin.WebDefaults);
break;
}
case WebXml:
@@ -1179,7 +1165,7 @@ public class StandardDescriptorProcessor extends IterativeDescriptorProcessor
* @param node
* @param context
*/
- protected void addServletMapping (String servletName, XmlParser.Node node, WebAppContext context)
+ protected ServletMapping addServletMapping (String servletName, XmlParser.Node node, WebAppContext context)
{
ServletMapping mapping = new ServletMapping();
mapping.setServletName(servletName);
@@ -1194,6 +1180,7 @@ public class StandardDescriptorProcessor extends IterativeDescriptorProcessor
}
mapping.setPathSpecs((String[]) paths.toArray(new String[paths.size()]));
context.getServletHandler().addServletMapping(mapping);
+ return mapping;
}
/**
@@ -1903,46 +1890,5 @@ public class StandardDescriptorProcessor extends IterativeDescriptorProcessor
return p;
}
- /**
- * Generate the classpath (as a string) of all classloaders
- * above the webapp's classloader.
- *
- * This is primarily used for jasper.
- * @return the system class path
- */
- protected String getSystemClassPath(WebAppContext context)
- {
- ClassLoader loader = context.getClassLoader();
- if (loader.getParent() != null)
- loader = loader.getParent();
-
- StringBuilder classpath=new StringBuilder();
- while (loader != null && (loader instanceof URLClassLoader))
- {
- URL[] urls = ((URLClassLoader)loader).getURLs();
- if (urls != null)
- {
- for (int i=0;i<urls.length;i++)
- {
- try
- {
- Resource resource = context.newResource(urls[i]);
- File file=resource.getFile();
- if (file!=null && file.exists())
- {
- if (classpath.length()>0)
- classpath.append(File.pathSeparatorChar);
- classpath.append(file.getAbsolutePath());
- }
- }
- catch (IOException e)
- {
- LOG.debug(e);
- }
- }
- }
- loader = loader.getParent();
- }
- return classpath.toString();
- }
+
}
diff --git a/jetty-webapp/src/main/java/org/eclipse/jetty/webapp/WebAppContext.java b/jetty-webapp/src/main/java/org/eclipse/jetty/webapp/WebAppContext.java
index 47a061342d..764fb0eb83 100644
--- a/jetty-webapp/src/main/java/org/eclipse/jetty/webapp/WebAppContext.java
+++ b/jetty-webapp/src/main/java/org/eclipse/jetty/webapp/WebAppContext.java
@@ -76,7 +76,9 @@ public class WebAppContext extends ServletContextHandler implements WebAppClassL
public final static String SERVER_CONFIG = "org.eclipse.jetty.webapp.configuration";
public final static String SERVER_SYS_CLASSES = "org.eclipse.jetty.webapp.systemClasses";
public final static String SERVER_SRV_CLASSES = "org.eclipse.jetty.webapp.serverClasses";
-
+
+ private String[] __dftProtectedTargets = {"/web-inf", "/meta-inf"};
+
private static String[] __dftConfigurationClasses =
{
"org.eclipse.jetty.webapp.WebInfConfiguration",
@@ -151,6 +153,8 @@ public class WebAppContext extends ServletContextHandler implements WebAppClassL
private boolean _configurationsSet=false;
private boolean _allowDuplicateFragmentNames = false;
private boolean _throwUnavailableOnStartupException = false;
+
+
private MetaData _metadata=new MetaData();
@@ -172,6 +176,7 @@ public class WebAppContext extends ServletContextHandler implements WebAppClassL
super(SESSIONS|SECURITY);
_scontext=new Context();
setErrorHandler(new ErrorPageErrorHandler());
+ setProtectedTargets(__dftProtectedTargets);
}
/* ------------------------------------------------------------ */
@@ -186,6 +191,7 @@ public class WebAppContext extends ServletContextHandler implements WebAppClassL
setContextPath(contextPath);
setWar(webApp);
setErrorHandler(new ErrorPageErrorHandler());
+ setProtectedTargets(__dftProtectedTargets);
}
/* ------------------------------------------------------------ */
@@ -200,6 +206,7 @@ public class WebAppContext extends ServletContextHandler implements WebAppClassL
_scontext=new Context();
setWar(webApp);
setErrorHandler(new ErrorPageErrorHandler());
+ setProtectedTargets(__dftProtectedTargets);
}
/* ------------------------------------------------------------ */
@@ -216,6 +223,7 @@ public class WebAppContext extends ServletContextHandler implements WebAppClassL
super(null, sessionHandler, securityHandler, servletHandler, errorHandler);
_scontext = new Context();
setErrorHandler(errorHandler != null ? errorHandler : new ErrorPageErrorHandler());
+ setProtectedTargets(__dftProtectedTargets);
}
/* ------------------------------------------------------------ */
@@ -833,16 +841,7 @@ public class WebAppContext extends ServletContextHandler implements WebAppClassL
}
}
- /* ------------------------------------------------------------ */
- @Override
- protected boolean isProtectedTarget(String target)
- {
- while (target.startsWith("//"))
- target=URIUtil.compactPath(target);
-
- return StringUtil.startsWithIgnoreCase(target, "/web-inf") || StringUtil.startsWithIgnoreCase(target, "/meta-inf");
- }
-
+
/* ------------------------------------------------------------ */
@Override
diff --git a/jetty-webapp/src/main/java/org/eclipse/jetty/webapp/WebInfConfiguration.java b/jetty-webapp/src/main/java/org/eclipse/jetty/webapp/WebInfConfiguration.java
index ba48c12f4d..53bc8b0557 100644
--- a/jetty-webapp/src/main/java/org/eclipse/jetty/webapp/WebInfConfiguration.java
+++ b/jetty-webapp/src/main/java/org/eclipse/jetty/webapp/WebInfConfiguration.java
@@ -1,4 +1,16 @@
package org.eclipse.jetty.webapp;
+//========================================================================
+//Copyright (c) 2006-2012 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.File;
import java.io.IOException;
diff --git a/jetty-webapp/src/test/java/org/acme/webapp/ClassInJarA.java b/jetty-webapp/src/test/java/org/acme/webapp/ClassInJarA.java
index 1d8d3a79f2..6fe83162b3 100644
--- a/jetty-webapp/src/test/java/org/acme/webapp/ClassInJarA.java
+++ b/jetty-webapp/src/test/java/org/acme/webapp/ClassInJarA.java
@@ -1,4 +1,16 @@
package org.acme.webapp;
+//========================================================================
+//Copyright (c) 2006-2012 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.
+//========================================================================
public class ClassInJarA
{
diff --git a/jetty-webapp/src/test/java/org/eclipse/jetty/webapp/WebAppClassLoaderTest.java b/jetty-webapp/src/test/java/org/eclipse/jetty/webapp/WebAppClassLoaderTest.java
index ba572a6de5..4e2de068c7 100644
--- a/jetty-webapp/src/test/java/org/eclipse/jetty/webapp/WebAppClassLoaderTest.java
+++ b/jetty-webapp/src/test/java/org/eclipse/jetty/webapp/WebAppClassLoaderTest.java
@@ -1,4 +1,16 @@
package org.eclipse.jetty.webapp;
+//========================================================================
+//Copyright (c) 2006-2012 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.junit.Assert.assertTrue;
diff --git a/jetty-webapp/src/test/java/org/eclipse/jetty/webapp/WebAppContextTest.java b/jetty-webapp/src/test/java/org/eclipse/jetty/webapp/WebAppContextTest.java
index e3c49ad895..9984b64a5a 100644
--- a/jetty-webapp/src/test/java/org/eclipse/jetty/webapp/WebAppContextTest.java
+++ b/jetty-webapp/src/test/java/org/eclipse/jetty/webapp/WebAppContextTest.java
@@ -12,6 +12,7 @@
// ========================================================================
package org.eclipse.jetty.webapp;
+import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue;
@@ -168,6 +169,16 @@ public class WebAppContextTest
}
+
+ @Test
+ public void testIsProtected() throws Exception
+ {
+ WebAppContext context = new WebAppContext();
+ assertTrue(context.isProtectedTarget("/web-inf/lib/foo.jar"));
+ assertTrue(context.isProtectedTarget("/meta-inf/readme.txt"));
+ assertFalse(context.isProtectedTarget("/something-else/web-inf"));
+ }
+
class ServletA extends GenericServlet
{
@Override
diff --git a/jetty-websocket/src/main/java/org/eclipse/jetty/websocket/WebSocketHandler.java b/jetty-websocket/src/main/java/org/eclipse/jetty/websocket/WebSocketHandler.java
index d90780f5c3..5e4bc38582 100644
--- a/jetty-websocket/src/main/java/org/eclipse/jetty/websocket/WebSocketHandler.java
+++ b/jetty-websocket/src/main/java/org/eclipse/jetty/websocket/WebSocketHandler.java
@@ -51,7 +51,10 @@ public abstract class WebSocketHandler extends HandlerWrapper implements WebSock
public void handle(String target, Request baseRequest, HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException
{
if (_webSocketFactory.acceptWebSocket(request,response) || response.isCommitted())
+ {
+ baseRequest.setHandled(true);
return;
+ }
super.handle(target,baseRequest,request,response);
}
diff --git a/jetty-websocket/src/test/java/org/eclipse/jetty/websocket/WebSocketServletRFCTest.java b/jetty-websocket/src/test/java/org/eclipse/jetty/websocket/WebSocketServletRFCTest.java
index fcde6e3135..06e3078390 100644
--- a/jetty-websocket/src/test/java/org/eclipse/jetty/websocket/WebSocketServletRFCTest.java
+++ b/jetty-websocket/src/test/java/org/eclipse/jetty/websocket/WebSocketServletRFCTest.java
@@ -1,4 +1,16 @@
package org.eclipse.jetty.websocket;
+//========================================================================
+//Copyright 2011-2012 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.hamcrest.Matchers.*;
diff --git a/jetty-xml/src/main/java/org/eclipse/jetty/xml/XmlConfiguration.java b/jetty-xml/src/main/java/org/eclipse/jetty/xml/XmlConfiguration.java
index af8aec2b66..cee3c27cb0 100644
--- a/jetty-xml/src/main/java/org/eclipse/jetty/xml/XmlConfiguration.java
+++ b/jetty-xml/src/main/java/org/eclipse/jetty/xml/XmlConfiguration.java
@@ -16,6 +16,7 @@ package org.eclipse.jetty.xml;
import java.io.IOException;
import java.io.InputStream;
import java.io.StringReader;
+import java.lang.reflect.Array;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
@@ -25,20 +26,21 @@ import java.net.InetAddress;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.UnknownHostException;
-import java.security.AccessControlException;
import java.security.AccessController;
import java.security.PrivilegedAction;
-import java.util.Arrays;
+import java.util.ArrayList;
import java.util.Collection;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.HashSet;
-import java.util.Iterator;
+import java.util.List;
import java.util.Map;
import java.util.Properties;
+import java.util.Queue;
import java.util.Set;
import java.util.concurrent.atomic.AtomicReference;
+import org.eclipse.jetty.util.ArrayQueue;
import org.eclipse.jetty.util.LazyList;
import org.eclipse.jetty.util.Loader;
import org.eclipse.jetty.util.TypeUtil;
@@ -46,6 +48,7 @@ import org.eclipse.jetty.util.component.LifeCycle;
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.xml.XmlParser.Node;
import org.xml.sax.InputSource;
import org.xml.sax.SAXException;
@@ -68,9 +71,14 @@ public class XmlConfiguration
private static final Class<?>[] __primitiveHolders =
{ Boolean.class, Character.class, Byte.class, Short.class, Integer.class, Long.class, Float.class, Double.class, Void.class };
- private static final Integer ZERO = new Integer(0);
+
+ private static final Class<?>[] __supportedCollections =
+ { ArrayList.class,ArrayQueue.class,HashSet.class,Queue.class,List.class,Set.class,Collection.class,};
private static final Iterable<?> __factoryLoader;
+
+ private static final XmlParser __parser = initParser();
+
static
{
Iterable<?> loader=null;
@@ -93,57 +101,53 @@ public class XmlConfiguration
}
/* ------------------------------------------------------------ */
- private static XmlParser __parser;
private URL _url;
- private XmlParser.Node _config;
private String _dtd;
private ConfigurationProcessor _processor;
private final Map<String, Object> _idMap = new HashMap<String, Object>();
private final Map<String, String> _propertyMap = new HashMap<String, String>();
/* ------------------------------------------------------------ */
- private synchronized static void initParser() throws IOException
+ private synchronized static XmlParser initParser()
{
- if (__parser != null)
- return;
-
- __parser = new XmlParser();
+ XmlParser parser = new XmlParser();
try
{
URL config60 = Loader.getResource(XmlConfiguration.class,"org/eclipse/jetty/xml/configure_6_0.dtd",true);
URL config76 = Loader.getResource(XmlConfiguration.class,"org/eclipse/jetty/xml/configure_7_6.dtd",true);
- __parser.redirectEntity("configure.dtd",config76);
- __parser.redirectEntity("configure_1_0.dtd",config60);
- __parser.redirectEntity("configure_1_1.dtd",config60);
- __parser.redirectEntity("configure_1_2.dtd",config60);
- __parser.redirectEntity("configure_1_3.dtd",config60);
- __parser.redirectEntity("configure_6_0.dtd",config60);
- __parser.redirectEntity("configure_7_6.dtd",config76);
-
-
- __parser.redirectEntity("http://jetty.mortbay.org/configure.dtd",config76);
- __parser.redirectEntity("http://jetty.eclipse.org/configure.dtd",config76);
- __parser.redirectEntity("http://www.eclipse.org/jetty/configure.dtd",config76);
-
- __parser.redirectEntity("-//Mort Bay Consulting//DTD Configure//EN",config76);
- __parser.redirectEntity("-//Jetty//Configure//EN",config76);
+ parser.redirectEntity("configure.dtd",config76);
+ parser.redirectEntity("configure_1_0.dtd",config60);
+ parser.redirectEntity("configure_1_1.dtd",config60);
+ parser.redirectEntity("configure_1_2.dtd",config60);
+ parser.redirectEntity("configure_1_3.dtd",config60);
+ parser.redirectEntity("configure_6_0.dtd",config60);
+ parser.redirectEntity("configure_7_6.dtd",config76);
+
+ parser.redirectEntity("http://jetty.mortbay.org/configure.dtd",config76);
+ parser.redirectEntity("http://jetty.eclipse.org/configure.dtd",config76);
+ parser.redirectEntity("http://www.eclipse.org/jetty/configure.dtd",config76);
+
+ parser.redirectEntity("-//Mort Bay Consulting//DTD Configure//EN",config76);
+ parser.redirectEntity("-//Jetty//Configure//EN",config76);
}
catch (ClassNotFoundException e)
{
LOG.warn(e.toString());
LOG.debug(e);
}
+ return parser;
}
/* ------------------------------------------------------------ */
/**
- * Constructor. Reads the XML configuration file.
+ * Reads and parses the XML configuration file.
*
- * @param configuration
+ * @param configuration the URL of the XML configuration
+ * @throws IOException if the configuration could not be read
+ * @throws SAXException if the configuration could not be parsed
*/
public XmlConfiguration(URL configuration) throws SAXException, IOException
{
- initParser();
synchronized (__parser)
{
_url=configuration;
@@ -154,16 +158,15 @@ public class XmlConfiguration
/* ------------------------------------------------------------ */
/**
- * Constructor.
+ * Reads and parses the XML configuration string.
*
- * @param configuration
- * String of XML configuration commands excluding the normal XML preamble. The String should start with a " <Configure ...." element.
- * @exception SAXException
- * @exception IOException
+ * @param configuration String of XML configuration commands excluding the normal XML preamble.
+ * The String should start with a "&lt;Configure ....&gt;" element.
+ * @throws IOException if the configuration could not be read
+ * @throws SAXException if the configuration could not be parsed
*/
public XmlConfiguration(String configuration) throws SAXException, IOException
{
- initParser();
configuration = "<?xml version=\"1.0\" encoding=\"ISO-8859-1\"?>\n<!DOCTYPE Configure PUBLIC \"-//Mort Bay Consulting//DTD Configure 1.2//EN\" \"http://jetty.eclipse.org/configure_1_2.dtd\">"
+ configuration;
InputSource source = new InputSource(new StringReader(configuration));
@@ -176,16 +179,14 @@ public class XmlConfiguration
/* ------------------------------------------------------------ */
/**
- * Constructor.
+ * Reads and parses the XML configuration stream.
*
- * @param configuration
- * An input stream containing a complete e.g. configuration file
- * @exception SAXException
- * @exception IOException
+ * @param configuration An input stream containing a complete configuration file
+ * @throws IOException if the configuration could not be read
+ * @throws SAXException if the configuration could not be parsed
*/
public XmlConfiguration(InputStream configuration) throws SAXException, IOException
{
- initParser();
InputSource source = new InputSource(configuration);
synchronized (__parser)
{
@@ -197,7 +198,6 @@ public class XmlConfiguration
/* ------------------------------------------------------------ */
private void setConfig(XmlParser.Node config)
{
- _config=config;
if ("Configure".equals(config.getTag()))
{
_processor=new JettyXmlConfiguration();
@@ -228,7 +228,7 @@ public class XmlConfiguration
{
throw new IllegalArgumentException("Unknown XML tag:"+config.getTag());
}
- _processor.init(_url,_config,_idMap, _propertyMap);
+ _processor.init(_url,config,_idMap, _propertyMap);
}
@@ -240,8 +240,10 @@ public class XmlConfiguration
/* ------------------------------------------------------------ */
/**
+ * @param map the ID map
* @deprecated use {@link #getIdMap()}.put(...)
*/
+ @Deprecated
public void setIdMap(Map<String, Object> map)
{
_idMap.clear();
@@ -250,8 +252,10 @@ public class XmlConfiguration
/* ------------------------------------------------------------ */
/**
+ * @param map the properties map
* @deprecated use {@link #getProperties()}.putAll(...)
*/
+ @Deprecated
public void setProperties(Map<String, String> map)
{
_propertyMap.clear();
@@ -266,13 +270,12 @@ public class XmlConfiguration
/* ------------------------------------------------------------ */
/**
- * Configure an object.
- *
- * <p>Apply the XML configuration script to the passed object.</p>
+ * Applies the XML configuration script to the given object.
*
- * @param obj
- * The object to be configured, which must be of a type or super type of the class attribute of the Configure element.
- * @exception Exception
+ * @param obj The object to be configured, which must be of a type or super type
+ * of the class attribute of the &lt;Configure&gt; element.
+ * @throws Exception if the configuration fails
+ * @return the configured object
*/
public Object configure(Object obj) throws Exception
{
@@ -281,10 +284,13 @@ public class XmlConfiguration
/* ------------------------------------------------------------ */
/**
- * Configure an object. If the configuration has an ID, an object is looked up by ID and it's type check. Otherwise a new object is created.
+ * Applies the XML configuration script.
+ * If the root element of the configuration has an ID, an object is looked up by ID and its type checked
+ * against the root element's type.
+ * Otherwise a new object of the type specified by the root element is created.
*
* @return The newly created configured object.
- * @exception Exception
+ * @throws Exception if the configuration fails
*/
public Object configure() throws Exception
{
@@ -311,7 +317,7 @@ public class XmlConfiguration
public Object configure(Object obj) throws Exception
{
// Check the class of the object
- Class<?> oClass = (Class<?>)nodeClass(_config);
+ Class<?> oClass = nodeClass(_config);
if (oClass != null && !oClass.isInstance(obj))
{
String loaders = (oClass.getClassLoader()==obj.getClass().getClassLoader())?"":"Object Class and type Class are from different loaders.";
@@ -324,7 +330,7 @@ public class XmlConfiguration
/* ------------------------------------------------------------ */
public Object configure() throws Exception
{
- Class<?> oClass = (Class<?>)nodeClass(_config);
+ Class<?> oClass = nodeClass(_config);
String id = _config.getAttribute("id");
Object obj = id == null?null:_idMap.get(id);
@@ -340,7 +346,7 @@ public class XmlConfiguration
}
/* ------------------------------------------------------------ */
- private Class<?> nodeClass(XmlParser.Node node) throws ClassNotFoundException
+ private static Class<?> nodeClass(XmlParser.Node node) throws ClassNotFoundException
{
String className = node.getAttribute("class");
if (className == null)
@@ -351,12 +357,13 @@ public class XmlConfiguration
/* ------------------------------------------------------------ */
/**
- * Recursive configuration step. This method applies the remaining Set, Put and Call elements to the current object.
+ * Recursive configuration routine.
+ * This method applies the nested Set, Put, Call, etc. elements to the given object.
*
- * @param obj
- * @param cfg
- * @param i
- * @exception Exception
+ * @param obj the object to configure
+ * @param cfg the XML nodes of the configuration
+ * @param i the index of the XML nodes
+ * @throws Exception if the configuration fails
*/
public void configure(Object obj, XmlParser.Node cfg, int i) throws Exception
{
@@ -389,7 +396,7 @@ public class XmlConfiguration
else if ("Ref".equals(tag))
refObj(obj,node);
else if ("Property".equals(tag))
- propertyObj(obj,node);
+ propertyObj(node);
else
throw new IllegalStateException("Unknown tag: " + tag);
}
@@ -417,13 +424,13 @@ public class XmlConfiguration
Object[] arg =
{ value };
- Class oClass = nodeClass(node);
+ Class<?> oClass = nodeClass(node);
if (oClass != null)
obj = null;
else
oClass = obj.getClass();
- Class[] vClass =
+ Class<?>[] vClass =
{ Object.class };
if (value != null)
vClass[0] = value.getClass();
@@ -455,7 +462,7 @@ public class XmlConfiguration
try
{
Field type = vClass[0].getField("TYPE");
- vClass[0] = (Class)type.get(null);
+ vClass[0] = (Class<?>)type.get(null);
Method set = oClass.getMethod(name,vClass);
set.invoke(obj,arg);
return;
@@ -497,7 +504,6 @@ public class XmlConfiguration
Method set = null;
for (int s = 0; sets != null && s < sets.length; s++)
{
-
Class<?>[] paramTypes = sets[s].getParameterTypes();
if (name.equals(sets[s].getName()) && paramTypes.length == 1)
{
@@ -518,27 +524,18 @@ public class XmlConfiguration
LOG.ignore(e);
}
- // Can we convert to a collection
- if (paramTypes[0].isAssignableFrom(Collection.class) && value.getClass().isArray())
+ try
{
- try
- {
- if (paramTypes[0].isAssignableFrom(Set.class))
- sets[s].invoke(obj,new Object[]
- { new HashSet<Object>(Arrays.asList((Object[])value)) });
- else
- sets[s].invoke(obj,new Object[]
- { Arrays.asList((Object[])value) });
- return;
- }
- catch (IllegalArgumentException e)
- {
- LOG.ignore(e);
- }
- catch (IllegalAccessException e)
- {
- LOG.ignore(e);
- }
+ for (Class<?> c : __supportedCollections)
+ if (paramTypes[0].isAssignableFrom(c))
+ {
+ sets[s].invoke(obj,convertArrayToCollection(value,c));
+ return;
+ }
+ }
+ catch (IllegalAccessException e)
+ {
+ LOG.ignore(e);
}
}
}
@@ -548,7 +545,7 @@ public class XmlConfiguration
{
try
{
- Class sClass = set.getParameterTypes()[0];
+ Class<?> sClass = set.getParameterTypes()[0];
if (sClass.isPrimitive())
{
for (int t = 0; t < __primitives.length; t++)
@@ -560,7 +557,7 @@ public class XmlConfiguration
}
}
}
- Constructor cons = sClass.getConstructor(vClass);
+ Constructor<?> cons = sClass.getConstructor(vClass);
arg[0] = cons.newInstance(arg);
set.invoke(obj,arg);
return;
@@ -583,6 +580,42 @@ public class XmlConfiguration
throw new NoSuchMethodException(oClass + "." + name + "(" + vClass[0] + ")");
}
+ /**
+ * @param array the array to convert
+ * @param collectionType the desired collection type
+ * @return a collection of the desired type if the array can be converted
+ */
+ private static Collection<?> convertArrayToCollection(Object array, Class<?> collectionType)
+ {
+ Collection<?> collection = null;
+ if (array.getClass().isArray())
+ {
+ if (collectionType.isAssignableFrom(ArrayList.class))
+ collection = convertArrayToArrayList(array);
+ else if (collectionType.isAssignableFrom(HashSet.class))
+ collection = new HashSet<Object>(convertArrayToArrayList(array));
+ else if (collectionType.isAssignableFrom(ArrayQueue.class))
+ {
+ ArrayQueue<Object> q= new ArrayQueue<Object>();
+ q.addAll(convertArrayToArrayList(array));
+ collection=q;
+ }
+ }
+ if (collection==null)
+ throw new IllegalArgumentException("Can't convert \"" + array.getClass() + "\" to " + collectionType);
+ return collection;
+ }
+
+ /* ------------------------------------------------------------ */
+ private static ArrayList<Object> convertArrayToArrayList(Object array)
+ {
+ int length = Array.getLength(array);
+ ArrayList<Object> list = new ArrayList<Object>(length);
+ for (int i = 0; i < length; i++)
+ list.add(Array.get(array,i));
+ return list;
+ }
+
/* ------------------------------------------------------------ */
/*
* Call a put method.
@@ -593,6 +626,7 @@ public class XmlConfiguration
{
if (!(obj instanceof Map))
throw new IllegalArgumentException("Object for put is not a Map: " + obj);
+ @SuppressWarnings("unchecked")
Map<Object, Object> map = (Map<Object, Object>)obj;
String name = node.getAttribute("name");
@@ -610,7 +644,7 @@ public class XmlConfiguration
*/
private Object get(Object obj, XmlParser.Node node) throws Exception
{
- Class oClass = nodeClass(node);
+ Class<?> oClass = nodeClass(node);
if (oClass != null)
obj = null;
else
@@ -657,7 +691,7 @@ public class XmlConfiguration
private Object call(Object obj, XmlParser.Node node) throws Exception
{
String id = node.getAttribute("id");
- Class oClass = nodeClass(node);
+ Class<?> oClass = nodeClass(node);
if (oClass != null)
obj = null;
else if (obj != null)
@@ -718,7 +752,7 @@ public class XmlConfiguration
*/
private Object newObj(Object obj, XmlParser.Node node) throws Exception
{
- Class oClass = nodeClass(node);
+ Class<?> oClass = nodeClass(node);
String id = node.getAttribute("id");
int size = 0;
int argi = node.size();
@@ -748,7 +782,7 @@ public class XmlConfiguration
LOG.debug("XML new " + oClass);
// Lets just try all constructors for now
- Constructor[] constructors = oClass.getConstructors();
+ Constructor<?>[] constructors = oClass.getConstructors();
for (int c = 0; constructors != null && c < constructors.length; c++)
{
if (constructors[c].getParameterTypes().length != size)
@@ -809,7 +843,7 @@ public class XmlConfiguration
{
// Get the type
- Class aClass = java.lang.Object.class;
+ Class<?> aClass = java.lang.Object.class;
String type = node.getAttribute("type");
final String id = node.getAttribute("id");
if (type != null)
@@ -830,13 +864,12 @@ public class XmlConfiguration
Object al = null;
- Iterator iter = node.iterator("Item");
- while (iter.hasNext())
+ for (Object nodeObject : node)
{
- XmlParser.Node item = (XmlParser.Node)iter.next();
+ XmlParser.Node item = (Node)nodeObject;
String nid = item.getAttribute("id");
Object v = value(obj,item);
- al = LazyList.add(al,(v == null && aClass.isPrimitive())?ZERO:v);
+ al = LazyList.add(al,(v == null && aClass.isPrimitive())?0:v);
if (nid != null)
_idMap.put(nid,v);
}
@@ -859,9 +892,8 @@ public class XmlConfiguration
if (id != null)
_idMap.put(id,map);
- for (int i = 0; i < node.size(); i++)
+ for (Object o : node)
{
- Object o = node.get(i);
if (o instanceof String)
continue;
XmlParser.Node entry = (XmlParser.Node)o;
@@ -871,12 +903,11 @@ public class XmlConfiguration
XmlParser.Node key = null;
XmlParser.Node value = null;
- for (int j = 0; j < entry.size(); j++)
+ for (Object object : entry)
{
- o = entry.get(j);
- if (o instanceof String)
+ if (object instanceof String)
continue;
- XmlParser.Node item = (XmlParser.Node)o;
+ XmlParser.Node item = (XmlParser.Node)object;
if (!item.getTag().equals("Item"))
throw new IllegalStateException("Not an Item");
if (key == null)
@@ -907,25 +938,27 @@ public class XmlConfiguration
/*
* Get a Property.
*
- * @param obj @param node @return @exception Exception
+ * @param node
+ * @return
+ * @exception Exception
*/
- private Object propertyObj(Object obj, XmlParser.Node node) throws Exception
+ private Object propertyObj(XmlParser.Node node) throws Exception
{
String id = node.getAttribute("id");
String name = node.getAttribute("name");
- String defval = node.getAttribute("default");
- Object prop = null;
+ String defaultValue = node.getAttribute("default");
+ Object prop;
if (_propertyMap != null && _propertyMap.containsKey(name))
prop = _propertyMap.get(name);
else
- prop = defval;
+ prop = defaultValue;
if (id != null)
_idMap.put(id,prop);
if (prop != null)
configure(prop,node,0);
return prop;
}
-
+
/* ------------------------------------------------------------ */
/*
@@ -934,7 +967,7 @@ public class XmlConfiguration
*/
private Object value(Object obj, XmlParser.Node node) throws Exception
{
- Object value = null;
+ Object value;
// Get the type
String type = node.getAttribute("type");
@@ -963,7 +996,7 @@ public class XmlConfiguration
if (type == null || !"String".equals(type))
{
// Skip leading white
- Object item = null;
+ Object item;
while (first <= last)
{
item = node.get(first);
@@ -1019,19 +1052,19 @@ public class XmlConfiguration
// Try to type the object
if (type == null)
{
- if (value != null && value instanceof String)
+ if (value instanceof String)
return ((String)value).trim();
return value;
}
- if ("String".equals(type) || "java.lang.String".equals(type))
+ if (isTypeMatchingClass(type,String.class))
return value.toString();
Class<?> pClass = TypeUtil.fromName(type);
if (pClass != null)
return TypeUtil.valueOf(pClass,value.toString());
- if ("URL".equals(type) || "java.net.URL".equals(type))
+ if (isTypeMatchingClass(type,URL.class))
{
if (value instanceof URL)
return value;
@@ -1045,7 +1078,7 @@ public class XmlConfiguration
}
}
- if ("InetAddress".equals(type) || "java.net.InetAddress".equals(type))
+ if (isTypeMatchingClass(type,InetAddress.class))
{
if (value instanceof InetAddress)
return value;
@@ -1059,10 +1092,22 @@ public class XmlConfiguration
}
}
+ for (Class<?> collectionClass : __supportedCollections)
+ {
+ if (isTypeMatchingClass(type,collectionClass))
+ return convertArrayToCollection(value,collectionClass);
+ }
+
throw new IllegalStateException("Unknown type " + type);
}
/* ------------------------------------------------------------ */
+ private static boolean isTypeMatchingClass(String type, Class<?> classToMatch)
+ {
+ return classToMatch.getSimpleName().equalsIgnoreCase(type) || classToMatch.getName().equals(type);
+ }
+
+ /* ------------------------------------------------------------ */
/*
* Get the value of a single element. @param obj @param item @return @exception Exception
*/
@@ -1087,7 +1132,7 @@ public class XmlConfiguration
if ("Map".equals(tag))
return newMap(obj,node);
if ("Property".equals(tag))
- return propertyObj(obj,node);
+ return propertyObj(node);
if ("SystemProperty".equals(tag))
{
@@ -1095,7 +1140,7 @@ public class XmlConfiguration
String defaultValue = node.getAttribute("default");
return System.getProperty(name,defaultValue);
}
-
+
if ("Env".equals(tag))
{
String name = node.getAttribute("name");
@@ -1128,8 +1173,8 @@ public class XmlConfiguration
*
* @param args
* array of property and xml configuration filenames or {@link Resource}s.
+ * @throws Exception if the XML configurations cannot be run
*/
- @SuppressWarnings("unchecked")
public static void main(final String[] args) throws Exception
{
@@ -1198,7 +1243,7 @@ public class XmlConfiguration
{
props.put(key.toString(),String.valueOf(properties.get(key)));
}
- configuration.setProperties(props);
+ configuration.getProperties().putAll(props);
}
obj[i] = configuration.configure();
last = configuration;
diff --git a/jetty-xml/src/test/java/org/eclipse/jetty/xml/ConstructorArgTestClass.java b/jetty-xml/src/test/java/org/eclipse/jetty/xml/ConstructorArgTestClass.java
new file mode 100644
index 0000000000..59d144837b
--- /dev/null
+++ b/jetty-xml/src/test/java/org/eclipse/jetty/xml/ConstructorArgTestClass.java
@@ -0,0 +1,77 @@
+// ========================================================================
+// 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.xml;
+
+import java.util.ArrayList;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Set;
+
+/* ------------------------------------------------------------ */
+/**
+ */
+public class ConstructorArgTestClass
+{
+ @SuppressWarnings("rawtypes")
+ private List list;
+
+ @SuppressWarnings("rawtypes")
+ private ArrayList arrayList;
+
+ @SuppressWarnings("rawtypes")
+ private Set set;
+
+ @SuppressWarnings("rawtypes")
+ public ConstructorArgTestClass(LinkedList list)
+ {
+ // not supported yet
+ }
+
+ @SuppressWarnings("rawtypes")
+ public ConstructorArgTestClass(ArrayList arrayList, List list)
+ {
+ this.arrayList = arrayList;
+ this.list = list;
+ }
+
+ @SuppressWarnings("rawtypes")
+ public ConstructorArgTestClass(ArrayList list)
+ {
+ this.list = list;
+ }
+
+ @SuppressWarnings("rawtypes")
+ public ConstructorArgTestClass(Set set)
+ {
+ this.set = set;
+ }
+
+ @SuppressWarnings("rawtypes")
+ public List getList()
+ {
+ return list;
+ }
+
+ @SuppressWarnings("rawtypes")
+ public ArrayList getArrayList()
+ {
+ return arrayList;
+ }
+
+ @SuppressWarnings("rawtypes")
+ public Set getSet()
+ {
+ return set;
+ }
+}
diff --git a/jetty-xml/src/test/java/org/eclipse/jetty/xml/TestConfiguration.java b/jetty-xml/src/test/java/org/eclipse/jetty/xml/TestConfiguration.java
index 9c8e55ee23..8c35a8e8e2 100644
--- a/jetty-xml/src/test/java/org/eclipse/jetty/xml/TestConfiguration.java
+++ b/jetty-xml/src/test/java/org/eclipse/jetty/xml/TestConfiguration.java
@@ -14,7 +14,12 @@
package org.eclipse.jetty.xml;
import java.net.URL;
+import java.util.ArrayList;
import java.util.HashMap;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
import org.junit.Ignore;
@@ -33,6 +38,12 @@ public class TestConfiguration extends HashMap<String,Object>
public int testField1;
public int testField2;
public int propValue;
+ @SuppressWarnings("rawtypes")
+ private List list;
+ @SuppressWarnings("rawtypes")
+ private Set set;
+ private ConstructorArgTestClass constructorArgTestClass;
+ public Map map;
public void setTest(Object value)
{
@@ -43,7 +54,7 @@ public class TestConfiguration extends HashMap<String,Object>
{
testInt=value;
}
-
+
public void setPropertyTest(int value)
{
propValue=value;
@@ -87,4 +98,54 @@ public class TestConfiguration extends HashMap<String,Object>
{
this.ia=ia;
}
+
+ @SuppressWarnings("rawtypes")
+ public List getList()
+ {
+ if (constructorArgTestClass != null)
+ return constructorArgTestClass.getList();
+ return list;
+ }
+
+ @SuppressWarnings("rawtypes")
+ public void setList(List list)
+ {
+ this.list = list;
+ }
+
+ @SuppressWarnings("rawtypes")
+ public void setLinkedList(LinkedList list)
+ {
+ this.list = list;
+ }
+
+ @SuppressWarnings("rawtypes")
+ public void setArrayList(ArrayList list)
+ {
+ this.list = list;
+ }
+
+ @SuppressWarnings("rawtypes")
+ public Set getSet()
+ {
+ if (constructorArgTestClass != null)
+ return constructorArgTestClass.getSet();
+ return set;
+ }
+
+ @SuppressWarnings("rawtypes")
+ public void setSet(Set set)
+ {
+ this.set = set;
+ }
+
+ public void setConstructorArgTestClass(ConstructorArgTestClass constructorArgTestClass)
+ {
+ this.constructorArgTestClass = constructorArgTestClass;
+ }
+
+ public void setMap(Map map)
+ {
+ this.map = map;
+ }
}
diff --git a/jetty-xml/src/test/java/org/eclipse/jetty/xml/XmlConfigurationTest.java b/jetty-xml/src/test/java/org/eclipse/jetty/xml/XmlConfigurationTest.java
index 16965d4201..49cb229254 100644
--- a/jetty-xml/src/test/java/org/eclipse/jetty/xml/XmlConfigurationTest.java
+++ b/jetty-xml/src/test/java/org/eclipse/jetty/xml/XmlConfigurationTest.java
@@ -13,27 +13,35 @@
package org.eclipse.jetty.xml;
-import static junit.framework.Assert.assertEquals;
-import static org.junit.Assert.assertTrue;
-
import java.net.URL;
import java.util.HashMap;
import java.util.Map;
+import org.junit.Assert;
import org.junit.Test;
+import static junit.framework.Assert.assertEquals;
+import static org.hamcrest.CoreMatchers.is;
+import static org.hamcrest.CoreMatchers.not;
+import static org.hamcrest.CoreMatchers.nullValue;
+import static org.junit.Assert.assertThat;
+import static org.junit.Assert.assertTrue;
+
public class XmlConfigurationTest
{
protected String _configure="org/eclipse/jetty/xml/configure.xml";
+ private static final String STRING_ARRAY_XML = "<Array type=\"String\"><Item type=\"String\">String1</Item><Item type=\"String\">String2</Item></Array>";
+ private static final String INT_ARRAY_XML = "<Array type=\"int\"><Item type=\"int\">1</Item><Item type=\"int\">2</Item></Array>";
+
@Test
public void testMortBay() throws Exception
{
URL url = XmlConfigurationTest.class.getClassLoader().getResource("org/eclipse/jetty/xml/mortbay.xml");
XmlConfiguration configuration = new XmlConfiguration(url);
- Object o=configuration.configure();
+ configuration.configure();
}
-
+
@Test
public void testPassedObject() throws Exception
{
@@ -49,7 +57,7 @@ public class XmlConfigurationTest
assertEquals("Set String","SetValue",tc.testObject);
assertEquals("Set Type",2,tc.testInt);
-
+
assertEquals(18080, tc.propValue);
assertEquals("Put","PutValue",tc.get("Test"));
@@ -72,7 +80,7 @@ public class XmlConfigurationTest
assertEquals( "SystemProperty", System.getProperty("user.dir")+"/stuff",tc.get("SystemProperty"));
assertEquals( "Env", System.getenv("HOME"),tc.get("Env"));
-
+
assertEquals( "Property", "xxx", tc.get("Property"));
@@ -100,12 +108,12 @@ public class XmlConfigurationTest
assertEquals("nested config","Call1",tc2.testObject);
assertEquals("nested config",4,tc2.testInt);
assertEquals( "nested call", "http://www.eclipse.com/",tc2.url.toString());
-
+
assertEquals("static to field",tc.testField1,77);
assertEquals("field to field",tc.testField2,2);
assertEquals("literal to static",TestConfiguration.VALUE,42);
}
-
+
@Test
public void testNewObject() throws Exception
{
@@ -120,7 +128,7 @@ public class XmlConfigurationTest
assertEquals("Set String","SetValue",tc.testObject);
assertEquals("Set Type",2,tc.testInt);
-
+
assertEquals(18080, tc.propValue);
assertEquals("Put","PutValue",tc.get("Test"));
@@ -169,13 +177,13 @@ public class XmlConfigurationTest
assertEquals("nested config","Call1",tc2.testObject);
assertEquals("nested config",4,tc2.testInt);
assertEquals( "nested call", "http://www.eclipse.com/",tc2.url.toString());
-
+
assertEquals("static to field",71,tc.testField1);
assertEquals("field to field",2,tc.testField2);
assertEquals("literal to static",42,TestConfiguration.VALUE);
}
-
-
+
+
@Test
public void testStringConfiguration() throws Exception
{
@@ -185,6 +193,153 @@ public class XmlConfigurationTest
configuration.configure(tc);
assertEquals("Set String 3","SetValue",tc.testObject);
assertEquals("Set Type 3",2,tc.testInt);
+ }
+
+ @Test
+ public void testListConstructorArg() throws Exception
+ {
+ XmlConfiguration xmlConfiguration = new XmlConfiguration("<Configure class=\"org.eclipse.jetty.xml.TestConfiguration\">"
+ + "<Set name=\"constructorArgTestClass\"><New class=\"org.eclipse.jetty.xml.ConstructorArgTestClass\"><Arg type=\"List\">"
+ + STRING_ARRAY_XML + "</Arg></New></Set></Configure>");
+ TestConfiguration tc = new TestConfiguration();
+ assertThat("tc.getList() returns null as it's not configured yet",tc.getList(),is(nullValue()));
+ xmlConfiguration.configure(tc);
+ assertThat("tc.getList() returns not null",tc.getList(),not(nullValue()));
+ assertThat("tc.getList() has two entries as specified in the xml",tc.getList().size(),is(2));
+ }
+
+ @Test
+ public void testTwoArgumentListConstructorArg() throws Exception
+ {
+ XmlConfiguration xmlConfiguration = new XmlConfiguration("<Configure class=\"org.eclipse.jetty.xml.TestConfiguration\">"
+ + "<Set name=\"constructorArgTestClass\"><New class=\"org.eclipse.jetty.xml.ConstructorArgTestClass\">"
+ + "<Arg type=\"List\">" + STRING_ARRAY_XML + "</Arg>"
+ + "<Arg type=\"List\">" + STRING_ARRAY_XML + "</Arg>"
+ + "</New></Set></Configure>");
+ TestConfiguration tc = new TestConfiguration();
+ assertThat("tc.getList() returns null as it's not configured yet",tc.getList(),is(nullValue()));
+ xmlConfiguration.configure(tc);
+ assertThat("tc.getList() returns not null",tc.getList(),not(nullValue()));
+ assertThat("tc.getList() has two entries as specified in the xml",tc.getList().size(),is(2));
+ }
+
+ @Test(expected = IllegalArgumentException.class)
+ public void testListNotContainingArray() throws Exception
+ {
+ XmlConfiguration xmlConfiguration = new XmlConfiguration("<Configure class=\"org.eclipse.jetty.xml.TestConfiguration\">"
+ + "<New class=\"org.eclipse.jetty.xml.ConstructorArgTestClass\"><Arg type=\"List\">Some String</Arg></New></Configure>");
+ TestConfiguration tc = new TestConfiguration();
+ xmlConfiguration.configure(tc);
+ }
+
+ @Test
+ public void testSetConstructorArg() throws Exception
+ {
+ XmlConfiguration xmlConfiguration = new XmlConfiguration("<Configure class=\"org.eclipse.jetty.xml.TestConfiguration\">"
+ + "<Set name=\"constructorArgTestClass\"><New class=\"org.eclipse.jetty.xml.ConstructorArgTestClass\"><Arg type=\"Set\">"
+ + STRING_ARRAY_XML + "</Arg></New></Set></Configure>");
+ TestConfiguration tc = new TestConfiguration();
+ assertThat("tc.getList() returns null as it's not configured yet",tc.getSet(),is(nullValue()));
+ xmlConfiguration.configure(tc);
+ assertThat("tc.getList() returns not null",tc.getSet(),not(nullValue()));
+ assertThat("tc.getList() has two entries as specified in the xml",tc.getSet().size(),is(2));
+ }
+ @Test(expected = IllegalArgumentException.class)
+ public void testSetNotContainingArray() throws Exception
+ {
+ XmlConfiguration xmlConfiguration = new XmlConfiguration("<Configure class=\"org.eclipse.jetty.xml.TestConfiguration\">"
+ + "<New class=\"org.eclipse.jetty.xml.ConstructorArgTestClass\"><Arg type=\"Set\">Some String</Arg></New></Configure>");
+ TestConfiguration tc = new TestConfiguration();
+ xmlConfiguration.configure(tc);
+ }
+
+ @Test
+ public void testListSetterWithStringArray() throws Exception
+ {
+ XmlConfiguration xmlConfiguration = new XmlConfiguration("<Configure class=\"org.eclipse.jetty.xml.TestConfiguration\"><Set name=\"List\">"
+ + STRING_ARRAY_XML + "</Set></Configure>");
+ TestConfiguration tc = new TestConfiguration();
+ assertThat("tc.getList() returns null as it's not configured yet",tc.getList(),is(nullValue()));
+ xmlConfiguration.configure(tc);
+ assertThat("tc.getList() has two entries as specified in the xml",tc.getList().size(),is(2));
+ }
+
+ @Test
+ public void testListSetterWithPrimitiveArray() throws Exception
+ {
+ XmlConfiguration xmlConfiguration = new XmlConfiguration("<Configure class=\"org.eclipse.jetty.xml.TestConfiguration\"><Set name=\"List\">"
+ + INT_ARRAY_XML + "</Set></Configure>");
+ TestConfiguration tc = new TestConfiguration();
+ assertThat("tc.getList() returns null as it's not configured yet",tc.getList(),is(nullValue()));
+ xmlConfiguration.configure(tc);
+ assertThat("tc.getList() has two entries as specified in the xml",tc.getList().size(),is(2));
+ }
+
+ @Test(expected=NoSuchMethodException.class)
+ public void testNotSupportedLinkedListSetter() throws Exception
+ {
+ XmlConfiguration xmlConfiguration = new XmlConfiguration("<Configure class=\"org.eclipse.jetty.xml.TestConfiguration\"><Set name=\"LinkedList\">"
+ + INT_ARRAY_XML + "</Set></Configure>");
+ TestConfiguration tc = new TestConfiguration();
+ assertThat("tc.getSet() returns null as it's not configured yet",tc.getList(),is(nullValue()));
+ xmlConfiguration.configure(tc);
+ }
+
+ @Test
+ public void testArrayListSetter() throws Exception
+ {
+ XmlConfiguration xmlConfiguration = new XmlConfiguration("<Configure class=\"org.eclipse.jetty.xml.TestConfiguration\"><Set name=\"ArrayList\">"
+ + INT_ARRAY_XML + "</Set></Configure>");
+ TestConfiguration tc = new TestConfiguration();
+ assertThat("tc.getSet() returns null as it's not configured yet",tc.getList(),is(nullValue()));
+ xmlConfiguration.configure(tc);
+ assertThat("tc.getSet() has two entries as specified in the xml",tc.getList().size(),is(2));
+ }
+
+ @Test
+ public void testSetSetter() throws Exception
+ {
+ XmlConfiguration xmlConfiguration = new XmlConfiguration("<Configure class=\"org.eclipse.jetty.xml.TestConfiguration\"><Set name=\"Set\">"
+ + STRING_ARRAY_XML + "</Set></Configure>");
+ TestConfiguration tc = new TestConfiguration();
+ assertThat("tc.getSet() returns null as it's not configured yet",tc.getSet(),is(nullValue()));
+ xmlConfiguration.configure(tc);
+ assertThat("tc.getSet() has two entries as specified in the xml",tc.getSet().size(),is(2));
+ }
+
+ @Test
+ public void testSetSetterWithPrimitiveArray() throws Exception
+ {
+ XmlConfiguration xmlConfiguration = new XmlConfiguration("<Configure class=\"org.eclipse.jetty.xml.TestConfiguration\"><Set name=\"Set\">"
+ + INT_ARRAY_XML + "</Set></Configure>");
+ TestConfiguration tc = new TestConfiguration();
+ assertThat("tc.getSet() returns null as it's not configured yet",tc.getSet(),is(nullValue()));
+ xmlConfiguration.configure(tc);
+ assertThat("tc.getSet() has two entries as specified in the xml",tc.getSet().size(),is(2));
+ }
+
+ @Test
+ public void testMap() throws Exception
+ {
+ XmlConfiguration xmlConfiguration = new XmlConfiguration("" +
+ "<Configure class=\"org.eclipse.jetty.xml.TestConfiguration\">" +
+ " <Set name=\"map\">" +
+ " <Map>" +
+ " <Entry>" +
+ " <Item>key1</Item>" +
+ " <Item>value1</Item>" +
+ " </Entry>" +
+ " <Entry>" +
+ " <Item>key2</Item>" +
+ " <Item>value2</Item>" +
+ " </Entry>" +
+ " </Map>" +
+ " </Set>" +
+ "</Configure>");
+ TestConfiguration tc = new TestConfiguration();
+ Assert.assertNull("tc.map is null as it's not configured yet", tc.map);
+ xmlConfiguration.configure(tc);
+ Assert.assertEquals("tc.map is has two entries as specified in the XML", 2, tc.map.size());
}
}
diff --git a/pom.xml b/pom.xml
index 17a91d5dc1..3d7ffd6078 100644
--- a/pom.xml
+++ b/pom.xml
@@ -10,7 +10,6 @@
<name>Jetty :: Project</name>
<url>${jetty.url}</url>
<packaging>pom</packaging>
-
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<jetty.url>http://www.eclipse.org/jetty</jetty.url>
diff --git a/test-continuation-jetty6/src/test/java/org/eclipse/jetty/continuation/TestProxyServer.java b/test-continuation-jetty6/src/test/java/org/eclipse/jetty/continuation/TestProxyServer.java
index 2f4410ca8b..8f2087aa5b 100644
--- a/test-continuation-jetty6/src/test/java/org/eclipse/jetty/continuation/TestProxyServer.java
+++ b/test-continuation-jetty6/src/test/java/org/eclipse/jetty/continuation/TestProxyServer.java
@@ -1,4 +1,16 @@
package org.eclipse.jetty.continuation;
+//========================================================================
+//Copyright 2011-2012 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 org.eclipse.jetty.servlets.ProxyServlet;
import org.junit.Ignore;
diff --git a/test-jetty-nested/src/main/java/org/eclipse/jetty/nested/NestedJettyServlet.java b/test-jetty-nested/src/main/java/org/eclipse/jetty/nested/NestedJettyServlet.java
index b8b5fc9c97..9c0068104b 100644
--- a/test-jetty-nested/src/main/java/org/eclipse/jetty/nested/NestedJettyServlet.java
+++ b/test-jetty-nested/src/main/java/org/eclipse/jetty/nested/NestedJettyServlet.java
@@ -1,4 +1,16 @@
package org.eclipse.jetty.nested;
+//========================================================================
+//Copyright 2011-2012 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.File;
import java.io.IOException;
diff --git a/test-jetty-nested/src/main/java/org/eclipse/jetty/nested/TestServlet.java b/test-jetty-nested/src/main/java/org/eclipse/jetty/nested/TestServlet.java
index 42222e66b4..dbaaa608a9 100644
--- a/test-jetty-nested/src/main/java/org/eclipse/jetty/nested/TestServlet.java
+++ b/test-jetty-nested/src/main/java/org/eclipse/jetty/nested/TestServlet.java
@@ -1,4 +1,16 @@
package org.eclipse.jetty.nested;
+//========================================================================
+//Copyright (c) 2006-2012 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.BufferedInputStream;
import java.io.BufferedReader;
diff --git a/test-jetty-servlet/src/main/java/Jetty400Repro.java b/test-jetty-servlet/src/main/java/Jetty400Repro.java
index 1bdd320c6d..bbb3d72550 100644
--- a/test-jetty-servlet/src/main/java/Jetty400Repro.java
+++ b/test-jetty-servlet/src/main/java/Jetty400Repro.java
@@ -1,3 +1,16 @@
+//========================================================================
+//Copyright 2011-2012 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.net.MalformedURLException;
import java.net.Socket;
diff --git a/test-jetty-webapp/src/main/java/com/acme/Counter.java b/test-jetty-webapp/src/main/java/com/acme/Counter.java
index d5546e5be9..d830d515a8 100644
--- a/test-jetty-webapp/src/main/java/com/acme/Counter.java
+++ b/test-jetty-webapp/src/main/java/com/acme/Counter.java
@@ -1,15 +1,14 @@
//========================================================================
-//Copyright 2004-2008 Mort Bay Consulting Pty. Ltd.
+//Copyright 2011-2012 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.
+//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 com.acme;
diff --git a/test-jetty-webapp/src/main/java/com/acme/Date2Tag.java b/test-jetty-webapp/src/main/java/com/acme/Date2Tag.java
index de9c9f49b6..9b7a1b3237 100644
--- a/test-jetty-webapp/src/main/java/com/acme/Date2Tag.java
+++ b/test-jetty-webapp/src/main/java/com/acme/Date2Tag.java
@@ -1,15 +1,14 @@
//========================================================================
-//Copyright 2004-2008 Mort Bay Consulting Pty. Ltd.
+//Copyright 2011-2012 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.
+//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 com.acme;
diff --git a/test-jetty-webapp/src/main/java/com/acme/DateTag.java b/test-jetty-webapp/src/main/java/com/acme/DateTag.java
index a54c72dda7..0ba8ad6e4a 100644
--- a/test-jetty-webapp/src/main/java/com/acme/DateTag.java
+++ b/test-jetty-webapp/src/main/java/com/acme/DateTag.java
@@ -1,15 +1,14 @@
//========================================================================
-//Copyright 2004-2008 Mort Bay Consulting Pty. Ltd.
+//Copyright 2011-2012 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.
+//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 com.acme;
diff --git a/test-jetty-webapp/src/main/java/com/acme/WebSocketChatServlet.java b/test-jetty-webapp/src/main/java/com/acme/WebSocketChatServlet.java
index 378a6c56aa..6aec62c686 100644
--- a/test-jetty-webapp/src/main/java/com/acme/WebSocketChatServlet.java
+++ b/test-jetty-webapp/src/main/java/com/acme/WebSocketChatServlet.java
@@ -1,4 +1,16 @@
package com.acme;
+//========================================================================
+//Copyright 2011-2012 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.util.Set;
diff --git a/test-jetty-webapp/src/test/java/org/eclipse/jetty/DispatchServletTest.java b/test-jetty-webapp/src/test/java/org/eclipse/jetty/DispatchServletTest.java
index 113b07e86e..9d2f469cad 100644
--- a/test-jetty-webapp/src/test/java/org/eclipse/jetty/DispatchServletTest.java
+++ b/test-jetty-webapp/src/test/java/org/eclipse/jetty/DispatchServletTest.java
@@ -1,16 +1,16 @@
-// ========================================================================
-// Copyright 2009 Webtide LLC
-// ------------------------------------------------------------------------
-// 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.
-// ========================================================================
+//========================================================================
+//Copyright 2011-2012 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;
import junit.framework.TestCase;
diff --git a/tests/test-integration/src/test/java/org/eclipse/jetty/test/DigestPostTest.java b/tests/test-integration/src/test/java/org/eclipse/jetty/test/DigestPostTest.java
index bb491353fc..870aa3e9f1 100644
--- a/tests/test-integration/src/test/java/org/eclipse/jetty/test/DigestPostTest.java
+++ b/tests/test-integration/src/test/java/org/eclipse/jetty/test/DigestPostTest.java
@@ -1,4 +1,16 @@
package org.eclipse.jetty.test;
+//========================================================================
+//Copyright 2011-2012 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.BufferedInputStream;
import java.io.FileInputStream;
diff --git a/tests/test-sessions/test-hash-sessions/src/test/java/org/eclipse/jetty/server/session/HashTestServer.java b/tests/test-sessions/test-hash-sessions/src/test/java/org/eclipse/jetty/server/session/HashTestServer.java
index 720d90f356..05e11f3d54 100644
--- a/tests/test-sessions/test-hash-sessions/src/test/java/org/eclipse/jetty/server/session/HashTestServer.java
+++ b/tests/test-sessions/test-hash-sessions/src/test/java/org/eclipse/jetty/server/session/HashTestServer.java
@@ -1,16 +1,15 @@
-// ========================================================================
-// Copyright 2004-2005 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.
-// ========================================================================
+//========================================================================
+//Copyright 2011-2012 Mort Bay Consulting Pty. Ltd.
+//------------------------------------------------------------------------
+//All rights reserved. This program and the accompanying materials
+//are made available under the terms of the Eclipse Public License v1.0
+//and Apache License v2.0 which accompanies this distribution.
+//The Eclipse Public License is available at
+//http://www.eclipse.org/legal/epl-v10.html
+//The Apache License v2.0 is available at
+//http://www.opensource.org/licenses/apache2.0.php
+//You may elect to redistribute this code under either of these licenses.
+//========================================================================
package org.eclipse.jetty.server.session;
diff --git a/tests/test-sessions/test-hash-sessions/src/test/java/org/eclipse/jetty/server/session/RemoveSessionTest.java b/tests/test-sessions/test-hash-sessions/src/test/java/org/eclipse/jetty/server/session/RemoveSessionTest.java
index 6663343ef1..17d68132b2 100644
--- a/tests/test-sessions/test-hash-sessions/src/test/java/org/eclipse/jetty/server/session/RemoveSessionTest.java
+++ b/tests/test-sessions/test-hash-sessions/src/test/java/org/eclipse/jetty/server/session/RemoveSessionTest.java
@@ -1,4 +1,16 @@
package org.eclipse.jetty.server.session;
+//========================================================================
+//Copyright 2011-2012 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 org.junit.Test;
diff --git a/tests/test-sessions/test-hash-sessions/src/test/java/org/eclipse/jetty/server/session/SessionInvalidateAndCreateTest.java b/tests/test-sessions/test-hash-sessions/src/test/java/org/eclipse/jetty/server/session/SessionInvalidateAndCreateTest.java
index 67b56ee7ce..df347d8535 100644
--- a/tests/test-sessions/test-hash-sessions/src/test/java/org/eclipse/jetty/server/session/SessionInvalidateAndCreateTest.java
+++ b/tests/test-sessions/test-hash-sessions/src/test/java/org/eclipse/jetty/server/session/SessionInvalidateAndCreateTest.java
@@ -1,4 +1,16 @@
package org.eclipse.jetty.server.session;
+//========================================================================
+//Copyright 2011-2012 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 org.junit.Test;
diff --git a/tests/test-sessions/test-sessions-common/src/main/java/org/eclipse/jetty/server/session/AbstractRemoveSessionTest.java b/tests/test-sessions/test-sessions-common/src/main/java/org/eclipse/jetty/server/session/AbstractRemoveSessionTest.java
index 7742d16d41..f19646b5e1 100644
--- a/tests/test-sessions/test-sessions-common/src/main/java/org/eclipse/jetty/server/session/AbstractRemoveSessionTest.java
+++ b/tests/test-sessions/test-sessions-common/src/main/java/org/eclipse/jetty/server/session/AbstractRemoveSessionTest.java
@@ -1,4 +1,16 @@
package org.eclipse.jetty.server.session;
+//========================================================================
+//Copyright 2011-2012 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.*;
diff --git a/tests/test-sessions/test-sessions-common/src/main/java/org/eclipse/jetty/server/session/AbstractSessionMigrationTest.java b/tests/test-sessions/test-sessions-common/src/main/java/org/eclipse/jetty/server/session/AbstractSessionMigrationTest.java
index ff9b489287..eb027c1698 100644
--- a/tests/test-sessions/test-sessions-common/src/main/java/org/eclipse/jetty/server/session/AbstractSessionMigrationTest.java
+++ b/tests/test-sessions/test-sessions-common/src/main/java/org/eclipse/jetty/server/session/AbstractSessionMigrationTest.java
@@ -111,11 +111,11 @@ public abstract class AbstractSessionMigrationTest
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException
{
HttpSession session = request.getSession(false);
- if (session == null) session = request.getSession(true);
String action = request.getParameter("action");
if ("set".equals(action))
{
+ if (session == null) session = request.getSession(true);
int value = Integer.parseInt(request.getParameter("value"));
session.setAttribute("value", value);
PrintWriter writer = response.getWriter();
@@ -125,6 +125,8 @@ public abstract class AbstractSessionMigrationTest
else if ("get".equals(action))
{
int value = (Integer)session.getAttribute("value");
+ int x = ((AbstractSession)session).getMaxInactiveInterval();
+ assertTrue(x > 0);
PrintWriter writer = response.getWriter();
writer.println(value);
writer.flush();

Back to the top