Skip to main content
aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--README.TXT1
-rw-r--r--VERSION.txt59
-rw-r--r--aggregates/jetty-all/pom.xml2
-rw-r--r--apache-jsp/pom.xml2
-rw-r--r--apache-jstl/pom.xml2
-rw-r--r--examples/async-rest/async-rest-jar/pom.xml2
-rw-r--r--examples/async-rest/async-rest-webapp/pom.xml2
-rw-r--r--examples/async-rest/pom.xml2
-rw-r--r--examples/embedded/pom.xml2
-rw-r--r--examples/embedded/src/main/java/org/eclipse/jetty/embedded/SimplestServer.java1
-rw-r--r--examples/pom.xml3
-rw-r--r--examples/quickstart/pom.xml183
-rw-r--r--jetty-alpn/jetty-alpn-client/pom.xml2
-rw-r--r--jetty-alpn/jetty-alpn-server/pom.xml2
-rw-r--r--jetty-alpn/jetty-alpn-server/src/main/config/modules/protonego-impl/alpn-1.7.0_65.mod8
-rw-r--r--jetty-alpn/jetty-alpn-server/src/main/config/modules/protonego-impl/alpn-1.8.0_11.mod8
-rw-r--r--jetty-alpn/pom.xml2
-rw-r--r--jetty-annotations/pom.xml4
-rw-r--r--jetty-annotations/src/main/java/org/eclipse/jetty/annotations/AnnotationConfiguration.java19
-rw-r--r--jetty-annotations/src/main/java/org/eclipse/jetty/annotations/ServletContainerInitializersStarter.java4
-rw-r--r--jetty-annotations/src/main/java/org/eclipse/jetty/annotations/ServletSecurityAnnotationHandler.java1
-rw-r--r--jetty-ant/pom.xml2
-rw-r--r--jetty-client/pom.xml2
-rw-r--r--jetty-client/src/main/java/org/eclipse/jetty/client/GZIPContentDecoder.java2
-rw-r--r--jetty-client/src/main/java/org/eclipse/jetty/client/HttpClient.java1
-rw-r--r--jetty-client/src/main/java/org/eclipse/jetty/client/HttpContent.java1
-rw-r--r--jetty-client/src/main/java/org/eclipse/jetty/client/HttpDestination.java3
-rw-r--r--jetty-client/src/main/java/org/eclipse/jetty/client/HttpReceiver.java155
-rw-r--r--jetty-client/src/main/java/org/eclipse/jetty/client/HttpSender.java136
-rw-r--r--jetty-client/src/main/java/org/eclipse/jetty/client/api/Connection.java2
-rw-r--r--jetty-client/src/main/java/org/eclipse/jetty/client/api/ContentProvider.java6
-rw-r--r--jetty-client/src/main/java/org/eclipse/jetty/client/api/Destination.java2
-rw-r--r--jetty-client/src/main/java/org/eclipse/jetty/client/api/Request.java3
-rw-r--r--jetty-client/src/main/java/org/eclipse/jetty/client/api/Response.java1
-rw-r--r--jetty-client/src/main/java/org/eclipse/jetty/client/http/HttpReceiverOverHTTP.java3
-rw-r--r--jetty-client/src/main/java/org/eclipse/jetty/client/http/HttpSenderOverHTTP.java11
-rw-r--r--jetty-client/src/main/java/org/eclipse/jetty/client/util/BasicAuthentication.java2
-rw-r--r--jetty-client/src/main/java/org/eclipse/jetty/client/util/ByteBufferContentProvider.java2
-rw-r--r--jetty-client/src/main/java/org/eclipse/jetty/client/util/BytesContentProvider.java2
-rw-r--r--jetty-client/src/main/java/org/eclipse/jetty/client/util/DeferredContentProvider.java3
-rw-r--r--jetty-client/src/main/java/org/eclipse/jetty/client/util/DigestAuthentication.java2
-rw-r--r--jetty-client/src/main/java/org/eclipse/jetty/client/util/FormContentProvider.java1
-rw-r--r--jetty-client/src/main/java/org/eclipse/jetty/client/util/InputStreamContentProvider.java3
-rw-r--r--jetty-client/src/main/java/org/eclipse/jetty/client/util/InputStreamResponseListener.java42
-rw-r--r--jetty-client/src/main/java/org/eclipse/jetty/client/util/OutputStreamContentProvider.java3
-rw-r--r--jetty-client/src/main/java/org/eclipse/jetty/client/util/PathContentProvider.java1
-rw-r--r--jetty-client/src/main/java/org/eclipse/jetty/client/util/StringContentProvider.java2
-rw-r--r--jetty-client/src/test/java/org/eclipse/jetty/client/HostnameVerificationTest.java5
-rw-r--r--jetty-client/src/test/java/org/eclipse/jetty/client/HttpClientAuthenticationTest.java6
-rw-r--r--jetty-client/src/test/java/org/eclipse/jetty/client/HttpClientGZIPTest.java209
-rw-r--r--jetty-client/src/test/java/org/eclipse/jetty/client/HttpClientTest.java28
-rw-r--r--jetty-client/src/test/java/org/eclipse/jetty/client/HttpResponseConcurrentAbortTest.java198
-rw-r--r--jetty-client/src/test/java/org/eclipse/jetty/client/http/HttpReceiverOverHTTPTest.java59
-rw-r--r--jetty-client/src/test/java/org/eclipse/jetty/client/ssl/SslBytesServerTest.java14
-rw-r--r--jetty-continuation/pom.xml2
-rw-r--r--jetty-continuation/src/main/java/org/eclipse/jetty/continuation/Continuation.java5
-rw-r--r--jetty-continuation/src/main/java/org/eclipse/jetty/continuation/ContinuationListener.java2
-rw-r--r--jetty-deploy/pom.xml2
-rw-r--r--jetty-deploy/src/main/java/org/eclipse/jetty/deploy/AppProvider.java2
-rw-r--r--jetty-deploy/src/main/java/org/eclipse/jetty/deploy/providers/WebAppProvider.java1
-rw-r--r--jetty-deploy/src/test/java/org/eclipse/jetty/deploy/AppLifeCycleTest.java6
-rw-r--r--jetty-deploy/src/test/java/org/eclipse/jetty/deploy/bindings/GlobalWebappConfigBindingTest.java1
-rw-r--r--jetty-deploy/src/test/java/org/eclipse/jetty/deploy/providers/ScanningAppProviderStartupTest.java4
-rw-r--r--jetty-distribution/pom.xml2
-rw-r--r--jetty-fcgi/fcgi-client/pom.xml2
-rw-r--r--jetty-fcgi/fcgi-client/src/main/java/org/eclipse/jetty/fcgi/client/http/HttpConnectionOverFCGI.java3
-rw-r--r--jetty-fcgi/fcgi-client/src/main/java/org/eclipse/jetty/fcgi/parser/ParamsContentParser.java8
-rw-r--r--jetty-fcgi/fcgi-client/src/main/java/org/eclipse/jetty/fcgi/parser/ResponseContentParser.java15
-rw-r--r--jetty-fcgi/fcgi-client/src/main/java/org/eclipse/jetty/fcgi/parser/StreamContentParser.java8
-rw-r--r--jetty-fcgi/fcgi-server/pom.xml2
-rw-r--r--jetty-fcgi/fcgi-server/src/main/java/org/eclipse/jetty/fcgi/server/ServerFCGIConnection.java3
-rw-r--r--jetty-fcgi/fcgi-server/src/test/java/org/eclipse/jetty/fcgi/server/HttpClientTest.java2
-rw-r--r--jetty-fcgi/pom.xml2
-rw-r--r--jetty-http-spi/pom.xml2
-rw-r--r--jetty-http-spi/src/main/java/org/eclipse/jetty/http/spi/JettyHttpContext.java4
-rw-r--r--jetty-http-spi/src/main/java/org/eclipse/jetty/http/spi/JettyHttpServer.java538
-rw-r--r--jetty-http-spi/src/main/java/org/eclipse/jetty/http/spi/JettyHttpServerProvider.java4
-rw-r--r--jetty-http/pom.xml2
-rw-r--r--jetty-http/src/main/java/org/eclipse/jetty/http/HttpParser.java4
-rw-r--r--jetty-http/src/main/java/org/eclipse/jetty/http/HttpURI.java2
-rw-r--r--jetty-http/src/test/java/org/eclipse/jetty/http/HttpFieldsTest.java4
-rw-r--r--jetty-http/src/test/java/org/eclipse/jetty/http/HttpParserTest.java4
-rw-r--r--jetty-http/src/test/java/org/eclipse/jetty/http/HttpURITest.java4
-rw-r--r--jetty-io/pom.xml2
-rw-r--r--jetty-io/src/main/java/org/eclipse/jetty/io/Connection.java2
-rw-r--r--jetty-io/src/main/java/org/eclipse/jetty/io/EndPoint.java2
-rw-r--r--jetty-io/src/main/java/org/eclipse/jetty/io/NetworkTrafficSelectChannelEndPoint.java1
-rw-r--r--jetty-io/src/main/java/org/eclipse/jetty/io/SelectorManager.java5
-rw-r--r--jetty-io/src/main/java/org/eclipse/jetty/io/ssl/SslConnection.java2
-rw-r--r--jetty-jaas/pom.xml2
-rw-r--r--jetty-jaas/src/main/java/org/eclipse/jetty/jaas/JAASLoginService.java2
-rw-r--r--jetty-jaspi/pom.xml2
-rw-r--r--jetty-jaspi/src/main/java/org/eclipse/jetty/security/jaspi/modules/FormAuthModule.java3
-rw-r--r--jetty-jmx/pom.xml2
-rw-r--r--jetty-jmx/src/main/java/org/eclipse/jetty/jmx/ConnectorServer.java24
-rw-r--r--jetty-jndi/pom.xml2
-rw-r--r--jetty-jndi/src/main/java/org/eclipse/jetty/jndi/DataSourceCloser.java1
-rw-r--r--jetty-jsp/pom.xml2
-rw-r--r--jetty-jspc-maven-plugin/pom.xml2
-rw-r--r--jetty-jspc-maven-plugin/src/main/java/org/eclipse/jetty/jspc/plugin/JspcMojo.java30
-rw-r--r--jetty-maven-plugin/pom.xml7
-rw-r--r--jetty-maven-plugin/src/main/java/org/eclipse/jetty/maven/plugin/AbstractJettyMojo.java3
-rw-r--r--jetty-maven-plugin/src/main/java/org/eclipse/jetty/maven/plugin/JettyEffectiveWebXml.java157
-rw-r--r--jetty-maven-plugin/src/main/java/org/eclipse/jetty/maven/plugin/JettyRunForkedMojo.java633
-rw-r--r--jetty-maven-plugin/src/main/java/org/eclipse/jetty/maven/plugin/JettyRunMojo.java3
-rw-r--r--jetty-maven-plugin/src/main/java/org/eclipse/jetty/maven/plugin/JettyWebAppContext.java120
-rw-r--r--jetty-maven-plugin/src/main/java/org/eclipse/jetty/maven/plugin/MavenQuickStartConfiguration.java92
-rw-r--r--jetty-maven-plugin/src/main/java/org/eclipse/jetty/maven/plugin/Starter.java17
-rw-r--r--jetty-monitor/pom.xml2
-rw-r--r--jetty-monitor/src/main/java/org/eclipse/jetty/monitor/jmx/ServiceConnection.java2
-rw-r--r--jetty-nosql/pom.xml2
-rw-r--r--jetty-nosql/src/main/java/org/eclipse/jetty/nosql/NoSqlSession.java2
-rw-r--r--jetty-nosql/src/main/java/org/eclipse/jetty/nosql/mongodb/MongoSessionIdManager.java2
-rw-r--r--jetty-nosql/src/main/java/org/eclipse/jetty/nosql/mongodb/MongoSessionManager.java4
-rw-r--r--jetty-osgi/jetty-osgi-alpn/pom.xml2
-rw-r--r--jetty-osgi/jetty-osgi-boot-jsp/pom.xml2
-rw-r--r--jetty-osgi/jetty-osgi-boot-warurl/pom.xml2
-rw-r--r--jetty-osgi/jetty-osgi-boot/pom.xml2
-rw-r--r--jetty-osgi/jetty-osgi-boot/src/main/java/org/eclipse/jetty/osgi/annotations/AnnotationConfiguration.java3
-rw-r--r--jetty-osgi/jetty-osgi-boot/src/main/java/org/eclipse/jetty/osgi/annotations/AnnotationParser.java12
-rw-r--r--jetty-osgi/jetty-osgi-boot/src/main/java/org/eclipse/jetty/osgi/boot/OSGiMetaInfConfiguration.java129
-rw-r--r--jetty-osgi/jetty-osgi-boot/src/main/java/org/eclipse/jetty/osgi/boot/OSGiWebInfConfiguration.java52
-rw-r--r--jetty-osgi/jetty-osgi-httpservice/pom.xml2
-rw-r--r--jetty-osgi/jetty-osgi-httpservice/src/main/java/org/eclipse/jetty/osgi/httpservice/HttpServiceErrorHandlerHelper.java22
-rw-r--r--jetty-osgi/jetty-osgi-httpservice/src/main/java/org/eclipse/jetty/osgi/httpservice/HttpServiceErrorPageErrorHandler.java80
-rw-r--r--jetty-osgi/jetty-osgi-npn/pom.xml2
-rw-r--r--jetty-osgi/pom.xml2
-rw-r--r--jetty-osgi/test-jetty-osgi-context/pom.xml2
-rw-r--r--jetty-osgi/test-jetty-osgi-webapp/pom.xml2
-rw-r--r--jetty-osgi/test-jetty-osgi/pom.xml59
-rw-r--r--jetty-osgi/test-jetty-osgi/src/test/java/org/eclipse/jetty/osgi/test/TestJettyOSGiBootCore.java28
-rw-r--r--jetty-overlay-deployer/src/test/java/org/eclipse/jetty/overlays/OverlayServer.java2
-rw-r--r--jetty-plus/pom.xml2
-rw-r--r--jetty-plus/src/main/java/org/eclipse/jetty/plus/annotation/ContainerInitializer.java3
-rw-r--r--jetty-plus/src/main/java/org/eclipse/jetty/plus/security/DataSourceLoginService.java33
-rw-r--r--jetty-plus/src/main/java/org/eclipse/jetty/plus/webapp/EnvConfiguration.java1
-rw-r--r--jetty-proxy/pom.xml2
-rw-r--r--jetty-proxy/src/main/java/org/eclipse/jetty/proxy/AsyncProxyServlet.java37
-rw-r--r--jetty-proxy/src/main/java/org/eclipse/jetty/proxy/BalancerServlet.java18
-rw-r--r--jetty-proxy/src/main/java/org/eclipse/jetty/proxy/ConnectHandler.java3
-rw-r--r--jetty-proxy/src/main/java/org/eclipse/jetty/proxy/ProxyConnection.java116
-rw-r--r--jetty-proxy/src/main/java/org/eclipse/jetty/proxy/ProxyServlet.java55
-rw-r--r--jetty-proxy/src/test/java/org/eclipse/jetty/proxy/ProxyServletTest.java210
-rw-r--r--jetty-quickstart/pom.xml72
-rw-r--r--jetty-quickstart/src/main/java/org/eclipse/jetty/quickstart/QuickStartConfiguration.java25
-rw-r--r--jetty-quickstart/src/main/java/org/eclipse/jetty/quickstart/QuickStartDescriptorGenerator.java659
-rw-r--r--jetty-quickstart/src/main/java/org/eclipse/jetty/quickstart/QuickStartWebApp.java560
-rw-r--r--jetty-rewrite/pom.xml2
-rw-r--r--jetty-rewrite/src/main/java/org/eclipse/jetty/rewrite/handler/RuleContainer.java1
-rw-r--r--jetty-rhttp/jetty-rhttp-gateway/src/main/java/org/eclipse/jetty/rhttp/gateway/GatewayServer.java4
-rw-r--r--jetty-runner/pom.xml2
-rw-r--r--jetty-security/pom.xml2
-rw-r--r--jetty-security/src/main/java/org/eclipse/jetty/security/ConstraintSecurityHandler.java25
-rw-r--r--jetty-security/src/main/java/org/eclipse/jetty/security/CrossContextPsuedoSession.java1
-rw-r--r--jetty-security/src/main/java/org/eclipse/jetty/security/HashCrossContextPsuedoSession.java1
-rw-r--r--jetty-security/src/main/java/org/eclipse/jetty/security/IdentityService.java1
-rw-r--r--jetty-security/src/main/java/org/eclipse/jetty/security/SecurityHandler.java1
-rw-r--r--jetty-security/src/main/java/org/eclipse/jetty/security/authentication/DeferredAuthentication.java40
-rw-r--r--jetty-security/src/main/java/org/eclipse/jetty/security/authentication/DigestAuthenticator.java1
-rw-r--r--jetty-security/src/main/java/org/eclipse/jetty/security/authentication/SpnegoAuthenticator.java8
-rw-r--r--jetty-security/src/test/java/org/eclipse/jetty/security/AliasedConstraintTest.java174
-rw-r--r--jetty-security/src/test/java/org/eclipse/jetty/security/ConstraintTest.java2
-rw-r--r--jetty-security/src/test/resources/docroot/all/index.txt1
-rw-r--r--jetty-security/src/test/resources/docroot/forbid/index.txt1
-rw-r--r--jetty-server/pom.xml2
-rw-r--r--jetty-server/src/main/java/org/eclipse/jetty/server/AbstractConnector.java38
-rw-r--r--jetty-server/src/main/java/org/eclipse/jetty/server/AbstractNCSARequestLog.java1
-rw-r--r--jetty-server/src/main/java/org/eclipse/jetty/server/Connector.java1
-rw-r--r--jetty-server/src/main/java/org/eclipse/jetty/server/ForwardedRequestCustomizer.java2
-rw-r--r--jetty-server/src/main/java/org/eclipse/jetty/server/Handler.java2
-rw-r--r--jetty-server/src/main/java/org/eclipse/jetty/server/HostHeaderCustomizer.java2
-rw-r--r--jetty-server/src/main/java/org/eclipse/jetty/server/HttpChannel.java9
-rw-r--r--jetty-server/src/main/java/org/eclipse/jetty/server/HttpConfiguration.java20
-rw-r--r--jetty-server/src/main/java/org/eclipse/jetty/server/HttpConnection.java18
-rw-r--r--jetty-server/src/main/java/org/eclipse/jetty/server/HttpOutput.java7
-rw-r--r--jetty-server/src/main/java/org/eclipse/jetty/server/InclusiveByteRange.java4
-rw-r--r--jetty-server/src/main/java/org/eclipse/jetty/server/LocalConnector.java5
-rw-r--r--jetty-server/src/main/java/org/eclipse/jetty/server/Request.java2
-rw-r--r--jetty-server/src/main/java/org/eclipse/jetty/server/ResourceCache.java1
-rw-r--r--jetty-server/src/main/java/org/eclipse/jetty/server/Response.java16
-rw-r--r--jetty-server/src/main/java/org/eclipse/jetty/server/SecureRequestCustomizer.java14
-rw-r--r--jetty-server/src/main/java/org/eclipse/jetty/server/Server.java34
-rw-r--r--jetty-server/src/main/java/org/eclipse/jetty/server/ServerConnector.java6
-rw-r--r--jetty-server/src/main/java/org/eclipse/jetty/server/ServletRequestHttpWrapper.java34
-rw-r--r--jetty-server/src/main/java/org/eclipse/jetty/server/SessionManager.java1
-rw-r--r--jetty-server/src/main/java/org/eclipse/jetty/server/ShutdownMonitor.java47
-rw-r--r--jetty-server/src/main/java/org/eclipse/jetty/server/handler/AbstractHandlerContainer.java2
-rw-r--r--jetty-server/src/main/java/org/eclipse/jetty/server/handler/ContextHandler.java102
-rw-r--r--jetty-server/src/main/java/org/eclipse/jetty/server/handler/ContextHandlerCollection.java274
-rw-r--r--jetty-server/src/main/java/org/eclipse/jetty/server/handler/DefaultHandler.java101
-rw-r--r--jetty-server/src/main/java/org/eclipse/jetty/server/handler/HandlerCollection.java9
-rw-r--r--jetty-server/src/main/java/org/eclipse/jetty/server/handler/HandlerWrapper.java1
-rw-r--r--jetty-server/src/main/java/org/eclipse/jetty/server/handler/ResourceHandler.java9
-rw-r--r--jetty-server/src/main/java/org/eclipse/jetty/server/handler/ShutdownHandler.java1
-rw-r--r--jetty-server/src/main/java/org/eclipse/jetty/server/session/AbstractSession.java1
-rw-r--r--jetty-server/src/main/java/org/eclipse/jetty/server/session/AbstractSessionManager.java6
-rw-r--r--jetty-server/src/main/java/org/eclipse/jetty/server/session/HashSessionIdManager.java2
-rw-r--r--jetty-server/src/main/java/org/eclipse/jetty/server/session/HashSessionManager.java42
-rw-r--r--jetty-server/src/main/java/org/eclipse/jetty/server/session/HashedSession.java19
-rw-r--r--jetty-server/src/main/java/org/eclipse/jetty/server/session/JDBCSessionIdManager.java6
-rw-r--r--jetty-server/src/main/java/org/eclipse/jetty/server/session/JDBCSessionManager.java4
-rw-r--r--jetty-server/src/main/java/org/eclipse/jetty/server/session/SessionHandler.java10
-rw-r--r--jetty-server/src/test/java/org/eclipse/jetty/server/CheckReverseProxyHeadersTest.java4
-rw-r--r--jetty-server/src/test/java/org/eclipse/jetty/server/GracefulStopTest.java31
-rw-r--r--jetty-server/src/test/java/org/eclipse/jetty/server/HttpConnectionTest.java1
-rw-r--r--jetty-server/src/test/java/org/eclipse/jetty/server/HttpURITest.java10
-rw-r--r--jetty-server/src/test/java/org/eclipse/jetty/server/NetworkTrafficListenerTest.java1
-rw-r--r--jetty-server/src/test/java/org/eclipse/jetty/server/PartialRFC2616Test.java1
-rw-r--r--jetty-server/src/test/java/org/eclipse/jetty/server/RequestTest.java9
-rw-r--r--jetty-server/src/test/java/org/eclipse/jetty/server/ServerConnectorTest.java197
-rw-r--r--jetty-server/src/test/java/org/eclipse/jetty/server/ShutdownMonitorTest.java76
-rw-r--r--jetty-server/src/test/java/org/eclipse/jetty/server/handler/ContextHandlerCollectionTest.java201
-rw-r--r--jetty-server/src/test/java/org/eclipse/jetty/server/session/HashSessionManagerTest.java26
-rw-r--r--jetty-server/src/test/java/org/eclipse/jetty/server/ssl/SelectChannelServerSslTest.java10
-rw-r--r--jetty-servlet/pom.xml2
-rw-r--r--jetty-servlet/src/main/java/org/eclipse/jetty/servlet/DefaultServlet.java38
-rw-r--r--jetty-servlet/src/main/java/org/eclipse/jetty/servlet/FilterMapping.java31
-rw-r--r--jetty-servlet/src/main/java/org/eclipse/jetty/servlet/Holder.java4
-rw-r--r--jetty-servlet/src/main/java/org/eclipse/jetty/servlet/Invoker.java16
-rw-r--r--jetty-servlet/src/main/java/org/eclipse/jetty/servlet/ServletContextHandler.java8
-rw-r--r--jetty-servlet/src/main/java/org/eclipse/jetty/servlet/ServletHandler.java93
-rw-r--r--jetty-servlet/src/main/java/org/eclipse/jetty/servlet/ServletHolder.java23
-rw-r--r--jetty-servlet/src/main/java/org/eclipse/jetty/servlet/ServletTester.java4
-rw-r--r--jetty-servlet/src/main/java/org/eclipse/jetty/servlet/listener/ELContextCleaner.java10
-rw-r--r--jetty-servlet/src/test/java/org/eclipse/jetty/servlet/AsyncContextDispatchWithQueryStrings.java104
-rw-r--r--jetty-servlet/src/test/java/org/eclipse/jetty/servlet/AsyncIOServletTest.java3
-rw-r--r--jetty-servlet/src/test/java/org/eclipse/jetty/servlet/AsyncServletTest.java124
-rw-r--r--jetty-servlet/src/test/java/org/eclipse/jetty/servlet/ServletContextHandlerTest.java2
-rw-r--r--jetty-servlet/src/test/java/org/eclipse/jetty/servlet/ServletHandlerTest.java7
-rw-r--r--jetty-servlets/pom.xml2
-rw-r--r--jetty-servlets/src/main/java/org/eclipse/jetty/servlets/AsyncGzipFilter.java18
-rw-r--r--jetty-servlets/src/main/java/org/eclipse/jetty/servlets/DoSFilter.java197
-rw-r--r--jetty-servlets/src/main/java/org/eclipse/jetty/servlets/GzipFilter.java16
-rw-r--r--jetty-servlets/src/main/java/org/eclipse/jetty/servlets/QoSFilter.java265
-rw-r--r--jetty-servlets/src/main/java/org/eclipse/jetty/servlets/WelcomeFilter.java6
-rw-r--r--jetty-servlets/src/main/java/org/eclipse/jetty/servlets/gzip/GzipHandler.java1
-rw-r--r--jetty-servlets/src/test/java/org/eclipse/jetty/servlets/CloseableDoSFilterTest.java2
-rw-r--r--jetty-servlets/src/test/java/org/eclipse/jetty/servlets/DoSFilterTest.java9
-rw-r--r--jetty-servlets/src/test/java/org/eclipse/jetty/servlets/GzipFilterDefaultNoRecompressTest.java1
-rw-r--r--jetty-servlets/src/test/java/org/eclipse/jetty/servlets/GzipFilterDefaultTest.java55
-rw-r--r--jetty-servlets/src/test/java/org/eclipse/jetty/servlets/QoSFilterTest.java90
-rw-r--r--jetty-servlets/src/test/java/org/eclipse/jetty/servlets/gzip/GzipTester.java6
-rw-r--r--jetty-servlets/src/test/java/org/eclipse/jetty/servlets/gzip/TestServletBufferTypeLengthWrite.java1
-rw-r--r--jetty-servlets/src/test/java/org/eclipse/jetty/servlets/gzip/TestServletLengthStreamTypeWrite.java2
-rw-r--r--jetty-servlets/src/test/java/org/eclipse/jetty/servlets/gzip/TestServletLengthTypeStreamWrite.java2
-rw-r--r--jetty-servlets/src/test/java/org/eclipse/jetty/servlets/gzip/TestServletStreamLengthTypeWrite.java2
-rw-r--r--jetty-servlets/src/test/java/org/eclipse/jetty/servlets/gzip/TestServletStreamLengthTypeWriteWithFlush.java2
-rw-r--r--jetty-servlets/src/test/java/org/eclipse/jetty/servlets/gzip/TestServletStreamTypeLengthWrite.java2
-rw-r--r--jetty-servlets/src/test/java/org/eclipse/jetty/servlets/gzip/TestServletTypeLengthStreamWrite.java2
-rw-r--r--jetty-servlets/src/test/java/org/eclipse/jetty/servlets/gzip/TestServletTypeStreamLengthWrite.java2
-rw-r--r--jetty-servlets/src/test/resources/jetty-logging.properties2
-rw-r--r--jetty-spdy/pom.xml2
-rw-r--r--jetty-spdy/spdy-alpn-tests/pom.xml2
-rw-r--r--jetty-spdy/spdy-client/pom.xml2
-rw-r--r--jetty-spdy/spdy-core/pom.xml2
-rw-r--r--jetty-spdy/spdy-example-webapp/pom.xml2
-rw-r--r--jetty-spdy/spdy-http-client-transport/pom.xml2
-rw-r--r--jetty-spdy/spdy-http-common/pom.xml2
-rw-r--r--jetty-spdy/spdy-http-server/pom.xml2
-rw-r--r--jetty-spdy/spdy-http-server/src/main/config/modules/protonego-impl/npn-1.7.0_65.mod8
-rw-r--r--jetty-spdy/spdy-http-server/src/test/java/org/eclipse/jetty/spdy/server/http/ServerHTTPSPDYTest.java115
-rw-r--r--jetty-spdy/spdy-npn-tests/pom.xml2
-rw-r--r--jetty-spdy/spdy-server/pom.xml2
-rw-r--r--jetty-spdy/spdy-server/src/test/java/org/eclipse/jetty/spdy/server/SPDYClientFactoryTest.java13
-rw-r--r--jetty-spring/pom.xml2
-rw-r--r--jetty-start/pom.xml2
-rw-r--r--jetty-start/src/main/java/org/eclipse/jetty/start/Main.java64
-rw-r--r--jetty-start/src/main/java/org/eclipse/jetty/start/PathMatchers.java12
-rw-r--r--jetty-start/src/main/java/org/eclipse/jetty/start/StartArgs.java8
-rw-r--r--jetty-start/src/test/java/org/eclipse/jetty/start/ConfigurationAssert.java13
-rw-r--r--jetty-start/src/test/java/org/eclipse/jetty/start/MainTest.java48
-rw-r--r--jetty-util-ajax/pom.xml2
-rw-r--r--jetty-util/pom.xml2
-rw-r--r--jetty-util/src/main/java/org/eclipse/jetty/util/ArrayTernaryTrie.java6
-rw-r--r--jetty-util/src/main/java/org/eclipse/jetty/util/ArrayTrie.java8
-rw-r--r--jetty-util/src/main/java/org/eclipse/jetty/util/B64Code.java1
-rw-r--r--jetty-util/src/main/java/org/eclipse/jetty/util/BufferUtil.java3
-rw-r--r--jetty-util/src/main/java/org/eclipse/jetty/util/ClassLoadingObjectInputStream.java4
-rw-r--r--jetty-util/src/main/java/org/eclipse/jetty/util/ConcurrentArrayQueue.java19
-rw-r--r--jetty-util/src/main/java/org/eclipse/jetty/util/ForkInvoker.java135
-rw-r--r--jetty-util/src/main/java/org/eclipse/jetty/util/FutureCallback.java2
-rw-r--r--jetty-util/src/main/java/org/eclipse/jetty/util/FuturePromise.java2
-rw-r--r--jetty-util/src/main/java/org/eclipse/jetty/util/IteratingCallback.java205
-rw-r--r--jetty-util/src/main/java/org/eclipse/jetty/util/LeakDetector.java1
-rw-r--r--jetty-util/src/main/java/org/eclipse/jetty/util/MultiException.java5
-rw-r--r--jetty-util/src/main/java/org/eclipse/jetty/util/MultiPartInputStreamParser.java18
-rw-r--r--jetty-util/src/main/java/org/eclipse/jetty/util/SharedBlockingCallback.java18
-rw-r--r--jetty-util/src/main/java/org/eclipse/jetty/util/URIUtil.java90
-rw-r--r--jetty-util/src/main/java/org/eclipse/jetty/util/UrlEncoded.java142
-rw-r--r--jetty-util/src/main/java/org/eclipse/jetty/util/Utf8LineParser.java2
-rw-r--r--jetty-util/src/main/java/org/eclipse/jetty/util/log/AbstractLogger.java4
-rw-r--r--jetty-util/src/main/java/org/eclipse/jetty/util/log/StdErrLog.java6
-rw-r--r--jetty-util/src/main/java/org/eclipse/jetty/util/preventers/GCThreadLeakPreventer.java2
-rw-r--r--jetty-util/src/main/java/org/eclipse/jetty/util/resource/Resource.java2
-rw-r--r--jetty-util/src/main/java/org/eclipse/jetty/util/security/Credential.java10
-rw-r--r--jetty-util/src/main/java/org/eclipse/jetty/util/thread/QueuedThreadPool.java1
-rw-r--r--jetty-util/src/main/java/org/eclipse/jetty/util/thread/ThreadPool.java1
-rw-r--r--jetty-util/src/test/java/org/eclipse/jetty/util/URIUtilTest.java1
-rw-r--r--jetty-util/src/test/java/org/eclipse/jetty/util/URLEncodedTest.java2
-rw-r--r--jetty-util/src/test/java/org/eclipse/jetty/util/resource/AbstractFSResourceTest.java8
-rw-r--r--jetty-webapp/pom.xml2
-rw-r--r--jetty-webapp/src/main/java/org/eclipse/jetty/webapp/Descriptor.java1
-rw-r--r--jetty-webapp/src/main/java/org/eclipse/jetty/webapp/FragmentConfiguration.java8
-rw-r--r--jetty-webapp/src/main/java/org/eclipse/jetty/webapp/MetaInfConfiguration.java57
-rw-r--r--jetty-webapp/src/main/java/org/eclipse/jetty/webapp/StandardDescriptorProcessor.java15
-rw-r--r--jetty-webapp/src/main/java/org/eclipse/jetty/webapp/WebAppClassLoader.java2
-rw-r--r--jetty-webapp/src/main/java/org/eclipse/jetty/webapp/WebAppContext.java2
-rw-r--r--jetty-webapp/src/test/java/org/eclipse/jetty/webapp/WebAppClassLoaderTest.java1
-rw-r--r--jetty-websocket/javax-websocket-client-impl/pom.xml2
-rw-r--r--jetty-websocket/javax-websocket-client-impl/src/main/java/org/eclipse/jetty/websocket/jsr356/DecoderFactory.java11
-rw-r--r--jetty-websocket/javax-websocket-client-impl/src/main/java/org/eclipse/jetty/websocket/jsr356/EncoderFactory.java11
-rw-r--r--jetty-websocket/javax-websocket-client-impl/src/main/java/org/eclipse/jetty/websocket/jsr356/MessageHandlerFactory.java26
-rw-r--r--jetty-websocket/javax-websocket-client-impl/src/main/java/org/eclipse/jetty/websocket/jsr356/annotations/AnnotatedEndpointScanner.java16
-rw-r--r--jetty-websocket/javax-websocket-client-impl/src/main/java/org/eclipse/jetty/websocket/jsr356/annotations/JsrEvents.java26
-rw-r--r--jetty-websocket/javax-websocket-client-impl/src/main/java/org/eclipse/jetty/websocket/jsr356/endpoints/JsrAnnotatedEventDriver.java46
-rw-r--r--jetty-websocket/javax-websocket-client-impl/src/main/java/org/eclipse/jetty/websocket/jsr356/endpoints/JsrEndpointEventDriver.java22
-rw-r--r--jetty-websocket/javax-websocket-client-impl/src/test/java/org/eclipse/jetty/websocket/jsr356/DecoderReaderTest.java7
-rw-r--r--jetty-websocket/javax-websocket-client-impl/src/test/java/org/eclipse/jetty/websocket/jsr356/EncoderTest.java8
-rw-r--r--jetty-websocket/javax-websocket-client-impl/src/test/java/org/eclipse/jetty/websocket/jsr356/EndpointEchoClient.java8
-rw-r--r--jetty-websocket/javax-websocket-client-impl/src/test/java/org/eclipse/jetty/websocket/jsr356/EndpointEchoTest.java29
-rw-r--r--jetty-websocket/javax-websocket-client-impl/src/test/java/org/eclipse/jetty/websocket/jsr356/MessageQueue.java5
-rw-r--r--jetty-websocket/javax-websocket-client-impl/src/test/java/org/eclipse/jetty/websocket/jsr356/endpoints/ClientAnnotatedEndpointScanner_InvalidSignaturesTest.java8
-rw-r--r--jetty-websocket/javax-websocket-client-impl/src/test/java/org/eclipse/jetty/websocket/jsr356/endpoints/TrackingSocket.java12
-rw-r--r--jetty-websocket/javax-websocket-client-impl/src/test/java/org/eclipse/jetty/websocket/jsr356/samples/AbstractStringEndpoint.java6
-rw-r--r--jetty-websocket/javax-websocket-server-impl/pom.xml2
-rw-r--r--jetty-websocket/javax-websocket-server-impl/src/main/java/org/eclipse/jetty/websocket/jsr356/server/BasicServerEndpointConfigurator.java6
-rw-r--r--jetty-websocket/javax-websocket-server-impl/src/main/java/org/eclipse/jetty/websocket/jsr356/server/JsrCreator.java7
-rw-r--r--jetty-websocket/javax-websocket-server-impl/src/main/java/org/eclipse/jetty/websocket/jsr356/server/deploy/WebSocketServerContainerInitializer.java44
-rw-r--r--jetty-websocket/javax-websocket-server-impl/src/test/java/org/eclipse/jetty/websocket/jsr356/server/ConfiguratorTest.java9
-rw-r--r--jetty-websocket/javax-websocket-server-impl/src/test/java/org/eclipse/jetty/websocket/jsr356/server/DummyConnection.java3
-rw-r--r--jetty-websocket/javax-websocket-server-impl/src/test/java/org/eclipse/jetty/websocket/jsr356/server/IdleTimeoutTest.java19
-rw-r--r--jetty-websocket/javax-websocket-server-impl/src/test/java/org/eclipse/jetty/websocket/jsr356/server/ServerAnnotatedEndpointScanner_InvalidSignaturesTest.java8
-rw-r--r--jetty-websocket/javax-websocket-server-impl/src/test/java/org/eclipse/jetty/websocket/jsr356/server/StreamTest.java12
-rw-r--r--jetty-websocket/javax-websocket-server-impl/src/test/java/org/eclipse/jetty/websocket/jsr356/server/TrackingSocket.java12
-rw-r--r--jetty-websocket/javax-websocket-server-impl/src/test/java/org/eclipse/jetty/websocket/jsr356/server/WSServer.java8
-rw-r--r--jetty-websocket/javax-websocket-server-impl/src/test/java/org/eclipse/jetty/websocket/jsr356/server/browser/JsrBrowserSocket.java7
-rw-r--r--jetty-websocket/javax-websocket-server-impl/src/test/java/org/eclipse/jetty/websocket/jsr356/server/samples/pong/PongSocket.java4
-rw-r--r--jetty-websocket/pom.xml2
-rw-r--r--jetty-websocket/websocket-api/pom.xml2
-rw-r--r--jetty-websocket/websocket-client/pom.xml2
-rw-r--r--jetty-websocket/websocket-client/src/main/java/org/eclipse/jetty/websocket/client/WebSocketClient.java32
-rw-r--r--jetty-websocket/websocket-client/src/main/java/org/eclipse/jetty/websocket/client/io/UpgradeConnection.java6
-rw-r--r--jetty-websocket/websocket-client/src/main/java/org/eclipse/jetty/websocket/client/io/WebSocketClientSelectorManager.java10
-rw-r--r--jetty-websocket/websocket-client/src/test/java/org/eclipse/jetty/websocket/client/ClientConnectTest.java22
-rw-r--r--jetty-websocket/websocket-common/pom.xml2
-rw-r--r--jetty-websocket/websocket-common/src/main/java/org/eclipse/jetty/websocket/common/WebSocketSession.java3
-rw-r--r--jetty-websocket/websocket-common/src/main/java/org/eclipse/jetty/websocket/common/events/AbstractEventDriver.java9
-rw-r--r--jetty-websocket/websocket-common/src/main/java/org/eclipse/jetty/websocket/common/events/JettyAnnotatedScanner.java3
-rw-r--r--jetty-websocket/websocket-common/src/main/java/org/eclipse/jetty/websocket/common/events/JettyListenerEventDriver.java3
-rw-r--r--jetty-websocket/websocket-common/src/main/java/org/eclipse/jetty/websocket/common/extensions/ExtensionStack.java17
-rw-r--r--jetty-websocket/websocket-common/src/main/java/org/eclipse/jetty/websocket/common/extensions/compress/CompressExtension.java19
-rw-r--r--jetty-websocket/websocket-common/src/main/java/org/eclipse/jetty/websocket/common/extensions/fragment/FragmentExtension.java12
-rw-r--r--jetty-websocket/websocket-common/src/main/java/org/eclipse/jetty/websocket/common/io/AbstractWebSocketConnection.java33
-rw-r--r--jetty-websocket/websocket-common/src/main/java/org/eclipse/jetty/websocket/common/io/FrameFlusher.java7
-rw-r--r--jetty-websocket/websocket-common/src/main/java/org/eclipse/jetty/websocket/common/io/FutureWriteCallback.java6
-rw-r--r--jetty-websocket/websocket-common/src/main/java/org/eclipse/jetty/websocket/common/io/IOState.java18
-rw-r--r--jetty-websocket/websocket-common/src/main/java/org/eclipse/jetty/websocket/common/message/MessageInputStream.java12
-rw-r--r--jetty-websocket/websocket-common/src/main/java/org/eclipse/jetty/websocket/common/message/MessageOutputStream.java8
-rw-r--r--jetty-websocket/websocket-common/src/main/java/org/eclipse/jetty/websocket/common/message/MessageReader.java1
-rw-r--r--jetty-websocket/websocket-common/src/main/java/org/eclipse/jetty/websocket/common/message/MessageWriter.java8
-rw-r--r--jetty-websocket/websocket-common/src/test/java/org/eclipse/jetty/websocket/common/events/EventCapture.java11
-rw-r--r--jetty-websocket/websocket-common/src/test/java/org/eclipse/jetty/websocket/common/io/LocalWebSocketConnection.java15
-rw-r--r--jetty-websocket/websocket-common/src/test/java/org/eclipse/jetty/websocket/common/message/MessageWriterTest.java7
-rw-r--r--jetty-websocket/websocket-common/src/test/java/org/eclipse/jetty/websocket/common/message/TrackingInputStreamSocket.java10
-rw-r--r--jetty-websocket/websocket-server/pom.xml2
-rw-r--r--jetty-websocket/websocket-server/src/main/java/org/eclipse/jetty/websocket/server/WebSocketServerFactory.java15
-rw-r--r--jetty-websocket/websocket-server/src/main/java/org/eclipse/jetty/websocket/server/WebSocketUpgradeFilter.java5
-rw-r--r--jetty-websocket/websocket-server/src/main/java/org/eclipse/jetty/websocket/server/pathmap/PathMappings.java3
-rw-r--r--jetty-websocket/websocket-servlet/pom.xml2
-rw-r--r--jetty-xml/pom.xml2
-rw-r--r--jetty-xml/src/main/java/org/eclipse/jetty/xml/XmlAppendable.java7
-rw-r--r--jetty-xml/src/test/java/org/eclipse/jetty/xml/TestConfiguration.java2
-rw-r--r--jetty-xml/src/test/java/org/eclipse/jetty/xml/XmlAppendableTest.java8
-rw-r--r--pom.xml29
-rw-r--r--tests/pom.xml2
-rw-r--r--tests/test-continuation/pom.xml2
-rw-r--r--tests/test-integration/pom.xml2
-rw-r--r--tests/test-integration/src/test/java/org/eclipse/jetty/test/rfcs/RFC2616BaseTest.java2
-rw-r--r--tests/test-loginservice/pom.xml86
-rw-r--r--tests/test-loginservice/src/test/java/org/eclipse/jetty/DataSourceLoginServiceTest.java204
-rw-r--r--tests/test-loginservice/src/test/java/org/eclipse/jetty/DatabaseLoginServiceTestServer.java250
-rw-r--r--tests/test-loginservice/src/test/java/org/eclipse/jetty/JdbcLoginServiceTest.java287
-rw-r--r--tests/test-loginservice/src/test/resources/droptables.sql6
-rw-r--r--tests/test-loginservice/src/test/resources/jdbcrealm.properties2
-rw-r--r--tests/test-loginservice/src/test/resources/jetty-logging.properties3
-rw-r--r--tests/test-sessions/pom.xml2
-rw-r--r--tests/test-sessions/test-hash-sessions/pom.xml2
-rw-r--r--tests/test-sessions/test-jdbc-sessions/pom.xml2
-rw-r--r--tests/test-sessions/test-jdbc-sessions/src/test/java/org/eclipse/jetty/server/session/SessionValueSavingTest.java32
-rw-r--r--tests/test-sessions/test-mongodb-sessions/pom.xml2
-rw-r--r--tests/test-sessions/test-sessions-common/pom.xml2
-rw-r--r--tests/test-sessions/test-sessions-common/src/main/java/org/eclipse/jetty/server/session/AbstractSessionValueSavingTest.java20
-rw-r--r--tests/test-webapps/pom.xml2
-rw-r--r--tests/test-webapps/test-dispatch-webapp/pom.xml2
-rw-r--r--tests/test-webapps/test-jaas-webapp/pom.xml2
-rw-r--r--tests/test-webapps/test-jetty-webapp/pom.xml2
-rw-r--r--tests/test-webapps/test-jetty-webapp/src/main/java/com/acme/Counter.java4
-rw-r--r--tests/test-webapps/test-jetty-webapp/src/main/java/com/acme/DateTag.java16
-rw-r--r--tests/test-webapps/test-jetty-webapp/src/main/java/com/acme/Dump.java16
-rw-r--r--tests/test-webapps/test-jetty-webapp/src/main/java/com/acme/HelloWorld.java2
-rw-r--r--tests/test-webapps/test-jetty-webapp/src/main/java/com/acme/LoginServlet.java2
-rw-r--r--tests/test-webapps/test-jetty-webapp/src/main/java/com/acme/RegTest.java2
-rw-r--r--tests/test-webapps/test-jetty-webapp/src/main/java/com/acme/SecureModeServlet.java2
-rw-r--r--tests/test-webapps/test-jndi-webapp/pom.xml2
-rw-r--r--tests/test-webapps/test-mock-resources/pom.xml2
-rw-r--r--tests/test-webapps/test-proxy-webapp/pom.xml2
-rw-r--r--tests/test-webapps/test-servlet-spec/pom.xml2
-rw-r--r--tests/test-webapps/test-servlet-spec/test-container-initializer/pom.xml2
-rw-r--r--tests/test-webapps/test-servlet-spec/test-spec-webapp/pom.xml2
-rw-r--r--tests/test-webapps/test-servlet-spec/test-spec-webapp/src/main/java/com/acme/Bar.java8
-rw-r--r--tests/test-webapps/test-servlet-spec/test-web-fragment/pom.xml2
-rw-r--r--tests/test-webapps/test-webapp-rfc2616/pom.xml2
412 files changed, 6687 insertions, 4170 deletions
diff --git a/README.TXT b/README.TXT
index 12c781192c..9157b3eaa5 100644
--- a/README.TXT
+++ b/README.TXT
@@ -1,6 +1,5 @@
This is a source checkout of the Jetty webserver.
-
To build, use:
mvn clean install
diff --git a/VERSION.txt b/VERSION.txt
index e1b0835f12..dafe08e00c 100644
--- a/VERSION.txt
+++ b/VERSION.txt
@@ -1,4 +1,61 @@
-jetty-9.2.2-SNAPSHOT
+jetty-9.2.3-SNAPSHOT
+
+jetty-9.2.2-v20140723 - 23 July 2014
+ + 411323 DosFilter/QoSFilter should use AsyncContext rather than
+ Continuations.
+ + 432815 Fixed selector stop race
+ + 434536 Improved Customizer javadoc
+ + 435322 Fixed Iterating Callback close
+ + 435653 encode async dispatched requestURI
+ + 435895 jetty spring module is not in distribution
+ + 436874 WebSocket client throwing a NullPointer when handling a pong
+ + 436894 GzipFilter code cleanup
+ + 436916 CGI: "Search docroot for a matching execCmd" logic is wrong
+ + 436987 limited range of default acceptors and selectors
+ + 437051 Refactor Filter chain handling of Request.isAsyncSupported
+ + 437395 Start / Properties in template sections should be default applied for
+ enabled modules
+ + 437419 Allow scanning of META-INF for resources,fragments,tlds for unpacked
+ jars
+ + 437430 jettyXml not consistent between jetty:run and jetty:run-forked
+ + 437462 consistent test failure in jetty-start under windows
+ + 437706 ServletTester calls LocalConnector method with hardcoded timeout
+ + 437800 URLs with single quote and spaces return 404
+ + 437996 avoid async status race by not setting 200 on handled
+ + 438079 Review garbage creation in 9.2.x series.
+ + 438190 findbug improvements
+ + 438204 leave IPv6 addresses [] wrapped in getServerName
+ + 438327 Remove hard coded Allow from OPTIONS *
+ + 438331 AbstractLogger.debug(String,long) infinite loop
+ + 438434 ResourceHandler checks aliases
+ + 438895 Add mvn jetty:effective-web-xml goal
+ + 439066 javadoc setStopAtShutdown
+ + 439067 Improved graceful stop timeout handling
+ + 439194 Do not configure fake server for jetty:run-forked
+ + 439201 GzipFilter and AsyncGzipFilter should strip charset from Content-Type
+ before making exclusion comparison in doFilter
+ + 439369 Deprecate CrossContextPseudoSession
+ + 439387 Ensure empty servlet-class never generated for quickstart
+ + 439390 Ensure jsp scratchdir is created same way for quickstart and
+ non-quickstart
+ + 439394 load-on-startup with value 0 not preserved for quickstart
+ + 439399 Scan tlds for apache jasper standard taglib with jetty-maven-plugin
+ + 439438 DataSourceLoginService does not refresh passwords when changed in
+ database
+ + 439507 Possible timing side-channel when comparing MD5-Credentials
+ + 439540 setReuseAddress() in ServerConnector.java is not coded properly
+ + 439652 GzipHandler super.doStart
+ + 439663 Allow mappings to be declared before servlet/filter
+ + 439672 support using Apache commons daemon for managing Jetty
+ + 439753 ConstraintSecurityHandler has dead code for processing constraints
+ + 439788 CORS filter headers gone between 9.2.0.M0 and 9.2.1 .v20140609 for
+ ProxyServlet requests.
+ + 439809 mvn jetty:jspc cannot find taglibs in dependency jars
+ + 439895 No event callback should be invoked after the "failure" callback.
+ + 440020 Abort bad proxy responses with sendError(-1)
+ + 440038 Content decoding may fail.
+ + 440114 ContextHandlerCollection does not skip context wrappers
+ + 440122 Remove usages of ForkInvoker.
jetty-9.2.1.v20140609 - 09 June 2014
+ 347110 Supprt ClassFileTransormers in WebAppClassLoader
diff --git a/aggregates/jetty-all/pom.xml b/aggregates/jetty-all/pom.xml
index 0eb2a3494b..9e2d09b059 100644
--- a/aggregates/jetty-all/pom.xml
+++ b/aggregates/jetty-all/pom.xml
@@ -2,7 +2,7 @@
<parent>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-project</artifactId>
- <version>9.2.2-SNAPSHOT</version>
+ <version>9.2.3-SNAPSHOT</version>
<relativePath>../../pom.xml</relativePath>
</parent>
<modelVersion>4.0.0</modelVersion>
diff --git a/apache-jsp/pom.xml b/apache-jsp/pom.xml
index 38c0a37dec..2dc05a269a 100644
--- a/apache-jsp/pom.xml
+++ b/apache-jsp/pom.xml
@@ -2,7 +2,7 @@
<parent>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-project</artifactId>
- <version>9.2.2-SNAPSHOT</version>
+ <version>9.2.3-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>apache-jsp</artifactId>
diff --git a/apache-jstl/pom.xml b/apache-jstl/pom.xml
index 16a4b5d0f7..669f7f4215 100644
--- a/apache-jstl/pom.xml
+++ b/apache-jstl/pom.xml
@@ -2,7 +2,7 @@
<parent>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-project</artifactId>
- <version>9.2.2-SNAPSHOT</version>
+ <version>9.2.3-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>apache-jstl</artifactId>
diff --git a/examples/async-rest/async-rest-jar/pom.xml b/examples/async-rest/async-rest-jar/pom.xml
index fc606f9dd3..5c88728c67 100644
--- a/examples/async-rest/async-rest-jar/pom.xml
+++ b/examples/async-rest/async-rest-jar/pom.xml
@@ -2,7 +2,7 @@
<parent>
<groupId>org.eclipse.jetty</groupId>
<artifactId>example-async-rest</artifactId>
- <version>9.2.2-SNAPSHOT</version>
+ <version>9.2.3-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<groupId>org.eclipse.jetty.example-async-rest</groupId>
diff --git a/examples/async-rest/async-rest-webapp/pom.xml b/examples/async-rest/async-rest-webapp/pom.xml
index 8bec78955d..d5fe3a50e8 100644
--- a/examples/async-rest/async-rest-webapp/pom.xml
+++ b/examples/async-rest/async-rest-webapp/pom.xml
@@ -2,7 +2,7 @@
<parent>
<groupId>org.eclipse.jetty</groupId>
<artifactId>example-async-rest</artifactId>
- <version>9.2.2-SNAPSHOT</version>
+ <version>9.2.3-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<groupId>org.eclipse.jetty.example-async-rest</groupId>
diff --git a/examples/async-rest/pom.xml b/examples/async-rest/pom.xml
index 4793c2e5c9..91de8f1c8a 100644
--- a/examples/async-rest/pom.xml
+++ b/examples/async-rest/pom.xml
@@ -2,7 +2,7 @@
<parent>
<groupId>org.eclipse.jetty.examples</groupId>
<artifactId>examples-parent</artifactId>
- <version>9.2.2-SNAPSHOT</version>
+ <version>9.2.3-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>
<modelVersion>4.0.0</modelVersion>
diff --git a/examples/embedded/pom.xml b/examples/embedded/pom.xml
index e033692720..4dbab32188 100644
--- a/examples/embedded/pom.xml
+++ b/examples/embedded/pom.xml
@@ -2,7 +2,7 @@
<parent>
<groupId>org.eclipse.jetty.examples</groupId>
<artifactId>examples-parent</artifactId>
- <version>9.2.2-SNAPSHOT</version>
+ <version>9.2.3-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>
<modelVersion>4.0.0</modelVersion>
diff --git a/examples/embedded/src/main/java/org/eclipse/jetty/embedded/SimplestServer.java b/examples/embedded/src/main/java/org/eclipse/jetty/embedded/SimplestServer.java
index bd0540fe6e..482194f351 100644
--- a/examples/embedded/src/main/java/org/eclipse/jetty/embedded/SimplestServer.java
+++ b/examples/embedded/src/main/java/org/eclipse/jetty/embedded/SimplestServer.java
@@ -29,6 +29,7 @@ public class SimplestServer
{
Server server = new Server(8080);
server.start();
+ server.dumpStdErr();
server.join();
}
}
diff --git a/examples/pom.xml b/examples/pom.xml
index 71ea930e14..f0add209d8 100644
--- a/examples/pom.xml
+++ b/examples/pom.xml
@@ -21,7 +21,7 @@
<parent>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-project</artifactId>
- <version>9.2.2-SNAPSHOT</version>
+ <version>9.2.3-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>
<groupId>org.eclipse.jetty.examples</groupId>
@@ -47,5 +47,6 @@
-->
<module>async-rest</module>
<module>embedded</module>
+ <module>quickstart</module>
</modules>
</project>
diff --git a/examples/quickstart/pom.xml b/examples/quickstart/pom.xml
new file mode 100644
index 0000000000..812b8e7b5c
--- /dev/null
+++ b/examples/quickstart/pom.xml
@@ -0,0 +1,183 @@
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+ <parent>
+ <groupId>org.eclipse.jetty.examples</groupId>
+ <artifactId>examples-parent</artifactId>
+ <version>9.2.3-SNAPSHOT</version>
+ <relativePath>../pom.xml</relativePath>
+ </parent>
+ <modelVersion>4.0.0</modelVersion>
+ <groupId>org.eclipse.jetty</groupId>
+ <artifactId>example-jetty-quickstart</artifactId>
+ <name>Example :: Jetty Quick Start</name>
+ <description>Jetty Quick Start Example</description>
+ <url>http://www.eclipse.org/jetty</url>
+ <dependencies>
+ <dependency>
+ <groupId>org.eclipse.jetty</groupId>
+ <artifactId>jetty-webapp</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.eclipse.jetty</groupId>
+ <artifactId>jetty-jmx</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.eclipse.jetty</groupId>
+ <artifactId>jetty-plus</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.eclipse.jetty</groupId>
+ <artifactId>jetty-annotations</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>javax.transaction</groupId>
+ <artifactId>javax.transaction-api</artifactId>
+ <version>1.2</version>
+ <scope>compile</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.eclipse.jetty.tests</groupId>
+ <artifactId>test-mock-resources</artifactId>
+ <version>${project.version}</version>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.eclipse.jetty.orbit</groupId>
+ <artifactId>javax.mail.glassfish</artifactId>
+ <version>1.4.1.v201005082020</version>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.eclipse.jetty</groupId>
+ <artifactId>jetty-servlets</artifactId>
+ <version>${project.version}</version>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.eclipse.jetty.tests</groupId>
+ <artifactId>test-jndi-webapp</artifactId>
+ <version>${project.version}</version>
+ <type>war</type>
+ <scope>provided</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.eclipse.jetty.tests</groupId>
+ <artifactId>test-spec-webapp</artifactId>
+ <version>${project.version}</version>
+ <type>war</type>
+ <scope>provided</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.eclipse.jetty</groupId>
+ <artifactId>test-jetty-webapp</artifactId>
+ <version>${project.version}</version>
+ <type>war</type>
+ <scope>provided</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.eclipse.jetty.websocket</groupId>
+ <artifactId>javax-websocket-server-impl</artifactId>
+ <version>${project.version}</version>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.eclipse.jetty.websocket</groupId>
+ <artifactId>websocket-server</artifactId>
+ <version>${project.version}</version>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.eclipse.jetty</groupId>
+ <artifactId>apache-jsp</artifactId>
+ <version>${project.version}</version>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.eclipse.jetty</groupId>
+ <artifactId>apache-jstl</artifactId>
+ <version>${project.version}</version>
+ <scope>test</scope>
+ </dependency>
+ </dependencies>
+ <build>
+ <plugins>
+ <plugin>
+ <groupId>org.codehaus.mojo</groupId>
+ <artifactId>appassembler-maven-plugin</artifactId>
+ <version>1.7</version>
+ <configuration>
+ <platforms>
+ <platform>unix</platform>
+ </platforms>
+ <programs>
+ <program>
+ <id>preconfigure</id>
+ <mainClass>org.eclipse.jetty.quickstart.PreconfigureQuickStartWar</mainClass>
+ </program>
+ <program>
+ <mainClass>org.eclipse.jetty.quickstart.QuickStartWar</mainClass>
+ <id>quickstart</id>
+ </program>
+ </programs>
+ </configuration>
+ <dependencies>
+ <dependency>
+ <groupId>org.eclipse.jetty</groupId>
+ <artifactId>jetty-webapp</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+ </dependencies>
+ </plugin>
+
+ <plugin>
+ <artifactId>maven-dependency-plugin</artifactId>
+ <executions>
+ <execution>
+ <id>copy</id>
+ <phase>generate-resources</phase>
+ <goals>
+ <goal>copy</goal>
+ </goals>
+ <configuration>
+ <artifactItems>
+ <artifactItem>
+ <groupId>org.eclipse.jetty.tests</groupId>
+ <artifactId>test-jndi-webapp</artifactId>
+ <version>${project.version}</version>
+ <type>war</type>
+ <overWrite>true</overWrite>
+ <includes>**</includes>
+ <outputDirectory>${basedir}/target</outputDirectory>
+ <destFileName>test-jndi.war</destFileName>
+ </artifactItem>
+ <artifactItem>
+ <groupId>org.eclipse.jetty.tests</groupId>
+ <artifactId>test-spec-webapp</artifactId>
+ <version>${project.version}</version>
+ <type>war</type>
+ <overWrite>true</overWrite>
+ <includes>**</includes>
+ <outputDirectory>${basedir}/target</outputDirectory>
+ <destFileName>test-spec.war</destFileName>
+ </artifactItem>
+ <artifactItem>
+ <groupId>org.eclipse.jetty</groupId>
+ <artifactId>test-jetty-webapp</artifactId>
+ <version>${project.version}</version>
+ <type>war</type>
+ <overWrite>true</overWrite>
+ <includes>**</includes>
+ <outputDirectory>${basedir}/target</outputDirectory>
+ <destFileName>test-standard.war</destFileName>
+ </artifactItem>
+ </artifactItems>
+ </configuration>
+ </execution>
+ </executions>
+ </plugin>
+ </plugins>
+ </build>
+</project>
diff --git a/jetty-alpn/jetty-alpn-client/pom.xml b/jetty-alpn/jetty-alpn-client/pom.xml
index 4e1bb361b3..780ed306d7 100644
--- a/jetty-alpn/jetty-alpn-client/pom.xml
+++ b/jetty-alpn/jetty-alpn-client/pom.xml
@@ -2,7 +2,7 @@
<parent>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-alpn-parent</artifactId>
- <version>9.2.2-SNAPSHOT</version>
+ <version>9.2.3-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>jetty-alpn-client</artifactId>
diff --git a/jetty-alpn/jetty-alpn-server/pom.xml b/jetty-alpn/jetty-alpn-server/pom.xml
index ee7683684c..a4c42aaf55 100644
--- a/jetty-alpn/jetty-alpn-server/pom.xml
+++ b/jetty-alpn/jetty-alpn-server/pom.xml
@@ -2,7 +2,7 @@
<parent>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-alpn-parent</artifactId>
- <version>9.2.2-SNAPSHOT</version>
+ <version>9.2.3-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>jetty-alpn-server</artifactId>
diff --git a/jetty-alpn/jetty-alpn-server/src/main/config/modules/protonego-impl/alpn-1.7.0_65.mod b/jetty-alpn/jetty-alpn-server/src/main/config/modules/protonego-impl/alpn-1.7.0_65.mod
new file mode 100644
index 0000000000..45bbad75c9
--- /dev/null
+++ b/jetty-alpn/jetty-alpn-server/src/main/config/modules/protonego-impl/alpn-1.7.0_65.mod
@@ -0,0 +1,8 @@
+[name]
+protonego-boot
+
+[files]
+http://central.maven.org/maven2/org/mortbay/jetty/alpn/alpn-boot/7.0.0.v20140317/alpn-boot-7.0.0.v20140317.jar|lib/alpn/alpn-boot-7.0.0.v20140317.jar
+
+[exec]
+-Xbootclasspath/p:lib/alpn/alpn-boot-7.0.0.v20140317.jar
diff --git a/jetty-alpn/jetty-alpn-server/src/main/config/modules/protonego-impl/alpn-1.8.0_11.mod b/jetty-alpn/jetty-alpn-server/src/main/config/modules/protonego-impl/alpn-1.8.0_11.mod
new file mode 100644
index 0000000000..65e6cb3c4d
--- /dev/null
+++ b/jetty-alpn/jetty-alpn-server/src/main/config/modules/protonego-impl/alpn-1.8.0_11.mod
@@ -0,0 +1,8 @@
+[name]
+protonego-boot
+
+[files]
+http://central.maven.org/maven2/org/mortbay/jetty/alpn/alpn-boot/8.0.0.v20140317/alpn-boot-8.0.0.v20140317.jar|lib/alpn/alpn-boot-8.0.0.v20140317.jar
+
+[exec]
+-Xbootclasspath/p:lib/alpn/alpn-boot-8.0.0.v20140317.jar
diff --git a/jetty-alpn/pom.xml b/jetty-alpn/pom.xml
index 2bfc776fa7..899ee2719f 100644
--- a/jetty-alpn/pom.xml
+++ b/jetty-alpn/pom.xml
@@ -2,7 +2,7 @@
<parent>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-project</artifactId>
- <version>9.2.2-SNAPSHOT</version>
+ <version>9.2.3-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>jetty-alpn-parent</artifactId>
diff --git a/jetty-annotations/pom.xml b/jetty-annotations/pom.xml
index 189d8fb8b1..e58f4be958 100644
--- a/jetty-annotations/pom.xml
+++ b/jetty-annotations/pom.xml
@@ -2,7 +2,7 @@
<parent>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-project</artifactId>
- <version>9.2.2-SNAPSHOT</version>
+ <version>9.2.3-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>jetty-annotations</artifactId>
@@ -43,7 +43,7 @@
</goals>
<configuration>
<instructions>
- <Import-Package>javax.servlet.*;version="[2.6.0,3.2)",org.objectweb.asm.*;version=4,*</Import-Package>
+ <Import-Package>javax.servlet.*;version="[2.6.0,3.2)",org.objectweb.asm.*;version=5,*</Import-Package>
<Require-Capability>osgi.serviceloader; filter:="(osgi.serviceloader=javax.servlet.ServletContainerInitializer)";resolution:=optional;cardinality:=multiple, osgi.extender; filter:="(osgi.extender=osgi.serviceloader.processor)"</Require-Capability>
</instructions>
</configuration>
diff --git a/jetty-annotations/src/main/java/org/eclipse/jetty/annotations/AnnotationConfiguration.java b/jetty-annotations/src/main/java/org/eclipse/jetty/annotations/AnnotationConfiguration.java
index 4845caaa59..8b8d7e28df 100644
--- a/jetty-annotations/src/main/java/org/eclipse/jetty/annotations/AnnotationConfiguration.java
+++ b/jetty-annotations/src/main/java/org/eclipse/jetty/annotations/AnnotationConfiguration.java
@@ -36,7 +36,6 @@ import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.Semaphore;
import java.util.concurrent.TimeUnit;
-
import javax.servlet.ServletContainerInitializer;
import javax.servlet.annotation.HandlesTypes;
@@ -442,14 +441,14 @@ public class AnnotationConfiguration extends AbstractConfiguration
// Resolve container initializers
List<ContainerInitializer> initializers =
- (List<ContainerInitializer>)context.getAttribute(AnnotationConfiguration.CONTAINER_INITIALIZERS);
+ (List<ContainerInitializer>)context.getAttribute(AnnotationConfiguration.CONTAINER_INITIALIZERS);
if (initializers != null && initializers.size()>0)
{
Map<String, Set<String>> map = ( Map<String, Set<String>>) context.getAttribute(AnnotationConfiguration.CLASS_INHERITANCE_MAP);
if (map == null)
LOG.warn ("ServletContainerInitializers: detected. Class hierarchy: empty");
for (ContainerInitializer i : initializers)
- i.resolveClasses(context,map);
+ i.resolveClasses(context,map);
}
}
@@ -557,16 +556,16 @@ public class AnnotationConfiguration extends AbstractConfiguration
boolean timeout = !latch.await(getMaxScanWait(context), TimeUnit.SECONDS);
if (LOG.isDebugEnabled())
- {
+ {
for (ParserTask p:_parserTasks)
LOG.debug("Scanned {} in {}ms", p.getResource(), TimeUnit.MILLISECONDS.convert(p.getStatistic().getElapsed(), TimeUnit.NANOSECONDS));
+
+ LOG.debug("Scanned {} container path jars, {} WEB-INF/lib jars, {} WEB-INF/classes dirs in {}ms for context {}",
+ _containerPathStats.getTotal(), _webInfLibStats.getTotal(), _webInfClassesStats.getTotal(),
+ (TimeUnit.MILLISECONDS.convert(System.nanoTime()-start, TimeUnit.NANOSECONDS)),
+ context);
}
-
- LOG.debug("Scanned {} container path jars, {} WEB-INF/lib jars, {} WEB-INF/classes dirs in {}ms for context {}",
- _containerPathStats.getTotal(), _webInfLibStats.getTotal(), _webInfClassesStats.getTotal(),
- (TimeUnit.MILLISECONDS.convert(System.nanoTime()-start, TimeUnit.NANOSECONDS)),
- context);
-
+
if (timeout)
me.add(new Exception("Timeout scanning annotations"));
me.ifExceptionThrow();
diff --git a/jetty-annotations/src/main/java/org/eclipse/jetty/annotations/ServletContainerInitializersStarter.java b/jetty-annotations/src/main/java/org/eclipse/jetty/annotations/ServletContainerInitializersStarter.java
index 2ebaa9623a..387c6f9e36 100644
--- a/jetty-annotations/src/main/java/org/eclipse/jetty/annotations/ServletContainerInitializersStarter.java
+++ b/jetty-annotations/src/main/java/org/eclipse/jetty/annotations/ServletContainerInitializersStarter.java
@@ -19,12 +19,8 @@
package org.eclipse.jetty.annotations;
import java.util.List;
-import java.util.Set;
-import java.util.concurrent.ConcurrentHashMap;
-
import org.eclipse.jetty.plus.annotation.ContainerInitializer;
import org.eclipse.jetty.servlet.ServletContextHandler;
-import org.eclipse.jetty.util.ConcurrentHashSet;
import org.eclipse.jetty.util.component.AbstractLifeCycle;
import org.eclipse.jetty.util.log.Log;
import org.eclipse.jetty.util.log.Logger;
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 743826793a..8020101faa 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
@@ -35,7 +35,6 @@ import org.eclipse.jetty.servlet.ServletMapping;
import org.eclipse.jetty.util.log.Log;
import org.eclipse.jetty.util.log.Logger;
import org.eclipse.jetty.util.security.Constraint;
-import org.eclipse.jetty.webapp.Origin;
import org.eclipse.jetty.webapp.WebAppContext;
/**
diff --git a/jetty-ant/pom.xml b/jetty-ant/pom.xml
index d8292b0516..511b5ea85f 100644
--- a/jetty-ant/pom.xml
+++ b/jetty-ant/pom.xml
@@ -2,7 +2,7 @@
<parent>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-project</artifactId>
- <version>9.2.2-SNAPSHOT</version>
+ <version>9.2.3-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>jetty-ant</artifactId>
diff --git a/jetty-client/pom.xml b/jetty-client/pom.xml
index 79fa747945..476cd46bbf 100644
--- a/jetty-client/pom.xml
+++ b/jetty-client/pom.xml
@@ -2,7 +2,7 @@
<parent>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-project</artifactId>
- <version>9.2.2-SNAPSHOT</version>
+ <version>9.2.3-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
diff --git a/jetty-client/src/main/java/org/eclipse/jetty/client/GZIPContentDecoder.java b/jetty-client/src/main/java/org/eclipse/jetty/client/GZIPContentDecoder.java
index ab8f2a40b5..6a7d6fa8ac 100644
--- a/jetty-client/src/main/java/org/eclipse/jetty/client/GZIPContentDecoder.java
+++ b/jetty-client/src/main/java/org/eclipse/jetty/client/GZIPContentDecoder.java
@@ -251,7 +251,7 @@ public class GZIPContentDecoder implements ContentDecoder
else
{
// Accumulate inflated bytes and loop to see if we have finished
- byte[] newOutput = Arrays.copyOf(output, output.length+decoded);
+ byte[] newOutput = Arrays.copyOf(output, output.length + decoded);
System.arraycopy(bytes, 0, newOutput, output.length, decoded);
output = newOutput;
}
diff --git a/jetty-client/src/main/java/org/eclipse/jetty/client/HttpClient.java b/jetty-client/src/main/java/org/eclipse/jetty/client/HttpClient.java
index 28ea589492..646c36122d 100644
--- a/jetty-client/src/main/java/org/eclipse/jetty/client/HttpClient.java
+++ b/jetty-client/src/main/java/org/eclipse/jetty/client/HttpClient.java
@@ -24,7 +24,6 @@ import java.net.CookiePolicy;
import java.net.CookieStore;
import java.net.SocketAddress;
import java.net.URI;
-import java.nio.channels.SocketChannel;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
diff --git a/jetty-client/src/main/java/org/eclipse/jetty/client/HttpContent.java b/jetty-client/src/main/java/org/eclipse/jetty/client/HttpContent.java
index d9cd89136c..598d11e133 100644
--- a/jetty-client/src/main/java/org/eclipse/jetty/client/HttpContent.java
+++ b/jetty-client/src/main/java/org/eclipse/jetty/client/HttpContent.java
@@ -24,7 +24,6 @@ import java.util.Collections;
import java.util.Iterator;
import org.eclipse.jetty.client.api.ContentProvider;
-import org.eclipse.jetty.client.util.DeferredContentProvider;
import org.eclipse.jetty.util.BufferUtil;
import org.eclipse.jetty.util.Callback;
import org.eclipse.jetty.util.log.Log;
diff --git a/jetty-client/src/main/java/org/eclipse/jetty/client/HttpDestination.java b/jetty-client/src/main/java/org/eclipse/jetty/client/HttpDestination.java
index 45e3878b38..20bbb12ab5 100644
--- a/jetty-client/src/main/java/org/eclipse/jetty/client/HttpDestination.java
+++ b/jetty-client/src/main/java/org/eclipse/jetty/client/HttpDestination.java
@@ -214,7 +214,8 @@ public abstract class HttpDestination implements Destination, Closeable, Dumpabl
public void close()
{
abort(new AsynchronousCloseException());
- LOG.debug("Closed {}", this);
+ if (LOG.isDebugEnabled())
+ LOG.debug("Closed {}", this);
}
public void release(Connection connection)
diff --git a/jetty-client/src/main/java/org/eclipse/jetty/client/HttpReceiver.java b/jetty-client/src/main/java/org/eclipse/jetty/client/HttpReceiver.java
index 7e163caab0..4b8546594c 100644
--- a/jetty-client/src/main/java/org/eclipse/jetty/client/HttpReceiver.java
+++ b/jetty-client/src/main/java/org/eclipse/jetty/client/HttpReceiver.java
@@ -21,6 +21,7 @@ package org.eclipse.jetty.client;
import java.io.IOException;
import java.net.URI;
import java.nio.ByteBuffer;
+import java.util.ArrayList;
import java.util.Collections;
import java.util.Enumeration;
import java.util.HashMap;
@@ -49,9 +50,8 @@ import org.eclipse.jetty.util.log.Logger;
* is available</li>
* <li>{@link #responseHeader(HttpExchange, HttpField)}, when a HTTP field is available</li>
* <li>{@link #responseHeaders(HttpExchange)}, when all HTTP headers are available</li>
- * <li>{@link #responseContent(HttpExchange, ByteBuffer, Callback)}, when HTTP content is available; this is the only
- * method that may be invoked multiple times with different buffers containing different content</li>
- * <li>{@link #responseSuccess(HttpExchange)}, when the response is complete</li>
+ * <li>{@link #responseContent(HttpExchange, ByteBuffer, Callback)}, when HTTP content is available</li>
+ * <li>{@link #responseSuccess(HttpExchange)}, when the response is successful</li>
* </ol>
* At any time, subclasses may invoke {@link #responseFailure(Throwable)} to indicate that the response has failed
* (for example, because of I/O exceptions).
@@ -69,7 +69,8 @@ public abstract class HttpReceiver
private final AtomicReference<ResponseState> responseState = new AtomicReference<>(ResponseState.IDLE);
private final HttpChannel channel;
- private volatile ContentDecoder decoder;
+ private ContentDecoder decoder;
+ private Throwable failure;
protected HttpReceiver(HttpChannel channel)
{
@@ -104,7 +105,7 @@ public abstract class HttpReceiver
*/
protected boolean responseBegin(HttpExchange exchange)
{
- if (!updateResponseState(ResponseState.IDLE, ResponseState.BEGIN))
+ if (!updateResponseState(ResponseState.IDLE, ResponseState.TRANSIENT))
return false;
HttpConversation conversation = exchange.getConversation();
@@ -127,6 +128,9 @@ public abstract class HttpReceiver
ResponseNotifier notifier = destination.getResponseNotifier();
notifier.notifyBegin(conversation.getResponseListeners(), response);
+ if (!updateResponseState(ResponseState.TRANSIENT, ResponseState.BEGIN))
+ terminateResponse(exchange, failure);
+
return true;
}
@@ -152,7 +156,7 @@ public abstract class HttpReceiver
case BEGIN:
case HEADER:
{
- if (updateResponseState(current, ResponseState.HEADER))
+ if (updateResponseState(current, ResponseState.TRANSIENT))
break out;
break;
}
@@ -188,6 +192,9 @@ public abstract class HttpReceiver
}
}
+ if (!updateResponseState(ResponseState.TRANSIENT, ResponseState.HEADER))
+ terminateResponse(exchange, failure);
+
return true;
}
@@ -205,7 +212,8 @@ public abstract class HttpReceiver
}
catch (IOException x)
{
- LOG.debug(x);
+ if (LOG.isDebugEnabled())
+ LOG.debug(x);
}
}
@@ -227,7 +235,7 @@ public abstract class HttpReceiver
case BEGIN:
case HEADER:
{
- if (updateResponseState(current, ResponseState.HEADERS))
+ if (updateResponseState(current, ResponseState.TRANSIENT))
break out;
break;
}
@@ -260,6 +268,9 @@ public abstract class HttpReceiver
}
}
+ if (!updateResponseState(ResponseState.TRANSIENT, ResponseState.HEADERS))
+ terminateResponse(exchange, failure);
+
return true;
}
@@ -272,7 +283,7 @@ public abstract class HttpReceiver
* @param buffer the response HTTP content buffer
* @return whether the processing should continue
*/
- protected boolean responseContent(HttpExchange exchange, ByteBuffer buffer, Callback callback)
+ protected boolean responseContent(HttpExchange exchange, ByteBuffer buffer, final Callback callback)
{
out: while (true)
{
@@ -282,7 +293,7 @@ public abstract class HttpReceiver
case HEADERS:
case CONTENT:
{
- if (updateResponseState(current, ResponseState.CONTENT))
+ if (updateResponseState(current, ResponseState.TRANSIENT))
break out;
break;
}
@@ -297,16 +308,49 @@ public abstract class HttpReceiver
if (LOG.isDebugEnabled())
LOG.debug("Response content {}{}{}", response, System.lineSeparator(), BufferUtil.toDetailString(buffer));
+ ResponseNotifier notifier = getHttpDestination().getResponseNotifier();
+ List<Response.ResponseListener> listeners = exchange.getConversation().getResponseListeners();
+
ContentDecoder decoder = this.decoder;
- if (decoder != null)
+ if (decoder == null)
{
- buffer = decoder.decode(buffer);
- if (LOG.isDebugEnabled())
- LOG.debug("Response content decoded ({}) {}{}{}", decoder, response, System.lineSeparator(), BufferUtil.toDetailString(buffer));
+ notifier.notifyContent(listeners, response, buffer, callback);
}
+ else
+ {
+ List<ByteBuffer> decodeds = new ArrayList<>(2);
+ while (buffer.hasRemaining())
+ {
+ ByteBuffer decoded = decoder.decode(buffer);
+ if (!decoded.hasRemaining())
+ continue;
+ decodeds.add(decoded);
+ if (LOG.isDebugEnabled())
+ LOG.debug("Response content decoded ({}) {}{}{}", decoder, response, System.lineSeparator(), BufferUtil.toDetailString(decoded));
+ }
- ResponseNotifier notifier = getHttpDestination().getResponseNotifier();
- notifier.notifyContent(exchange.getConversation().getResponseListeners(), response, buffer, callback);
+ if (decodeds.isEmpty())
+ {
+ callback.succeeded();
+ }
+ else
+ {
+ Callback partial = new Callback.Adapter()
+ {
+ @Override
+ public void failed(Throwable x)
+ {
+ callback.failed(x);
+ }
+ };
+
+ for (int i = 1, size = decodeds.size(); i <= size; ++i)
+ notifier.notifyContent(listeners, response, decodeds.get(i - 1), i < size ? partial : callback);
+ }
+ }
+
+ if (!updateResponseState(ResponseState.TRANSIENT, ResponseState.CONTENT))
+ terminateResponse(exchange, failure);
return true;
}
@@ -328,16 +372,17 @@ public abstract class HttpReceiver
if (!completed)
return false;
- // Reset to be ready for another response
+ responseState.set(ResponseState.IDLE);
+
+ // Reset to be ready for another response.
reset();
// Mark atomically the response as terminated and succeeded,
// with respect to concurrency between request and response.
- // If there is a non-null result, then both sender and
- // receiver are reset and ready to be reused, and the
- // connection closed/pooled (depending on the transport).
Result result = exchange.terminateResponse(null);
+ // It is important to notify *after* we reset and terminate
+ // because the notification may trigger another request/response.
HttpResponse response = exchange.getResponse();
if (LOG.isDebugEnabled())
LOG.debug("Response success {}", response);
@@ -345,17 +390,7 @@ public abstract class HttpReceiver
ResponseNotifier notifier = getHttpDestination().getResponseNotifier();
notifier.notifySuccess(listeners, response);
- if (result != null)
- {
- boolean ordered = getHttpDestination().getHttpClient().isStrictEventOrdering();
- if (!ordered)
- channel.exchangeTerminated(result);
- if (LOG.isDebugEnabled())
- LOG.debug("Request/Response succeeded {}", response);
- notifier.notifyComplete(listeners, result);
- if (ordered)
- channel.exchangeTerminated(result);
- }
+ terminateResponse(exchange, result);
return true;
}
@@ -384,7 +419,20 @@ public abstract class HttpReceiver
if (!completed)
return false;
- // Dispose to avoid further responses
+ this.failure = failure;
+
+ // Update the state to avoid more response processing.
+ boolean fail;
+ while (true)
+ {
+ ResponseState current = responseState.get();
+ if (updateResponseState(current, ResponseState.FAILURE))
+ {
+ fail = current != ResponseState.TRANSIENT;
+ break;
+ }
+ }
+
dispose();
// Mark atomically the response as terminated and failed,
@@ -398,19 +446,45 @@ public abstract class HttpReceiver
ResponseNotifier notifier = getHttpDestination().getResponseNotifier();
notifier.notifyFailure(listeners, response, failure);
+ if (fail)
+ {
+ terminateResponse(exchange, result);
+ }
+ else
+ {
+ if (LOG.isDebugEnabled())
+ LOG.debug("Concurrent failure: response termination skipped, performed by helpers");
+ }
+
+ return true;
+ }
+
+ private void terminateResponse(HttpExchange exchange, Throwable failure)
+ {
+ Result result = exchange.terminateResponse(failure);
+ terminateResponse(exchange, result);
+ }
+
+ private void terminateResponse(HttpExchange exchange, Result result)
+ {
+ HttpResponse response = exchange.getResponse();
+
+ if (LOG.isDebugEnabled())
+ LOG.debug("Response complete {}", response);
+
if (result != null)
{
boolean ordered = getHttpDestination().getHttpClient().isStrictEventOrdering();
if (!ordered)
channel.exchangeTerminated(result);
if (LOG.isDebugEnabled())
- LOG.debug("Request/Response failed {}", response);
+ LOG.debug("Request/Response {} {}", failure == null ? "succeeded" : "failed", response);
+ List<Response.ResponseListener> listeners = exchange.getConversation().getResponseListeners();
+ ResponseNotifier notifier = getHttpDestination().getResponseNotifier();
notifier.notifyComplete(listeners, result);
if (ordered)
channel.exchangeTerminated(result);
}
-
- return true;
}
/**
@@ -423,7 +497,6 @@ public abstract class HttpReceiver
protected void reset()
{
decoder = null;
- responseState.set(ResponseState.IDLE);
}
/**
@@ -436,7 +509,6 @@ public abstract class HttpReceiver
protected void dispose()
{
decoder = null;
- responseState.set(ResponseState.FAILURE);
}
public boolean abort(Throwable cause)
@@ -448,7 +520,10 @@ public abstract class HttpReceiver
{
boolean updated = responseState.compareAndSet(from, to);
if (!updated)
- LOG.debug("State update failed: {} -> {}: {}", from, to, responseState.get());
+ {
+ if (LOG.isDebugEnabled())
+ LOG.debug("State update failed: {} -> {}: {}", from, to, responseState.get());
+ }
return updated;
}
@@ -458,6 +533,10 @@ public abstract class HttpReceiver
private enum ResponseState
{
/**
+ * One of the response*() methods is being executed.
+ */
+ TRANSIENT,
+ /**
* The response is not yet received, the initial state
*/
IDLE,
diff --git a/jetty-client/src/main/java/org/eclipse/jetty/client/HttpSender.java b/jetty-client/src/main/java/org/eclipse/jetty/client/HttpSender.java
index 26302064d6..85d4d0b55a 100644
--- a/jetty-client/src/main/java/org/eclipse/jetty/client/HttpSender.java
+++ b/jetty-client/src/main/java/org/eclipse/jetty/client/HttpSender.java
@@ -65,7 +65,8 @@ public abstract class HttpSender implements AsyncContentProvider.Listener
private final IteratingCallback contentCallback = new ContentCallback();
private final Callback lastCallback = new LastContentCallback();
private final HttpChannel channel;
- private volatile HttpContent content;
+ private HttpContent content;
+ private Throwable failure;
protected HttpSender(HttpChannel channel)
{
@@ -197,34 +198,40 @@ public abstract class HttpSender implements AsyncContentProvider.Listener
protected boolean queuedToBegin(Request request)
{
- if (!updateRequestState(RequestState.QUEUED, RequestState.BEGIN))
+ if (!updateRequestState(RequestState.QUEUED, RequestState.TRANSIENT))
return false;
if (LOG.isDebugEnabled())
LOG.debug("Request begin {}", request);
RequestNotifier notifier = getHttpChannel().getHttpDestination().getRequestNotifier();
notifier.notifyBegin(request);
+ if (!updateRequestState(RequestState.TRANSIENT, RequestState.BEGIN))
+ terminateRequest(getHttpExchange(), failure, false);
return true;
}
protected boolean beginToHeaders(Request request)
{
- if (!updateRequestState(RequestState.BEGIN, RequestState.HEADERS))
+ if (!updateRequestState(RequestState.BEGIN, RequestState.TRANSIENT))
return false;
if (LOG.isDebugEnabled())
LOG.debug("Request headers {}{}{}", request, System.getProperty("line.separator"), request.getHeaders().toString().trim());
RequestNotifier notifier = getHttpChannel().getHttpDestination().getRequestNotifier();
notifier.notifyHeaders(request);
+ if (!updateRequestState(RequestState.TRANSIENT, RequestState.HEADERS))
+ terminateRequest(getHttpExchange(), failure, false);
return true;
}
protected boolean headersToCommit(Request request)
{
- if (!updateRequestState(RequestState.HEADERS, RequestState.COMMIT))
+ if (!updateRequestState(RequestState.HEADERS, RequestState.TRANSIENT))
return false;
if (LOG.isDebugEnabled())
LOG.debug("Request committed {}", request);
RequestNotifier notifier = getHttpChannel().getHttpDestination().getRequestNotifier();
notifier.notifyCommit(request);
+ if (!updateRequestState(RequestState.TRANSIENT, RequestState.COMMIT))
+ terminateRequest(getHttpExchange(), failure, true);
return true;
}
@@ -236,21 +243,19 @@ public abstract class HttpSender implements AsyncContentProvider.Listener
case COMMIT:
case CONTENT:
{
- if (!updateRequestState(current, RequestState.CONTENT))
+ if (!updateRequestState(current, RequestState.TRANSIENT_CONTENT))
return false;
if (LOG.isDebugEnabled())
LOG.debug("Request content {}{}{}", request, System.getProperty("line.separator"), BufferUtil.toDetailString(content));
RequestNotifier notifier = getHttpChannel().getHttpDestination().getRequestNotifier();
notifier.notifyContent(request, content);
+ if (!updateRequestState(RequestState.TRANSIENT_CONTENT, RequestState.CONTENT))
+ terminateRequest(getHttpExchange(), failure, true);
return true;
}
- case FAILURE:
- {
- return false;
- }
default:
{
- throw new IllegalStateException(current.toString());
+ return false;
}
}
}
@@ -269,43 +274,28 @@ public abstract class HttpSender implements AsyncContentProvider.Listener
if (!completed)
return false;
- // Reset to be ready for another request
+ requestState.set(RequestState.QUEUED);
+
+ // Reset to be ready for another request.
reset();
// Mark atomically the request as terminated and succeeded,
// with respect to concurrency between request and response.
Result result = exchange.terminateRequest(null);
- // It is important to notify completion *after* we reset because
- // the notification may trigger another request/response
Request request = exchange.getRequest();
if (LOG.isDebugEnabled())
LOG.debug("Request success {}", request);
HttpDestination destination = getHttpChannel().getHttpDestination();
destination.getRequestNotifier().notifySuccess(exchange.getRequest());
- if (result != null)
- {
- boolean ordered = destination.getHttpClient().isStrictEventOrdering();
- if (!ordered)
- channel.exchangeTerminated(result);
- if (LOG.isDebugEnabled())
- LOG.debug("Request/Response succeded {}", request);
- HttpConversation conversation = exchange.getConversation();
- destination.getResponseNotifier().notifyComplete(conversation.getResponseListeners(), result);
- if (ordered)
- channel.exchangeTerminated(result);
- }
+ terminateRequest(exchange, null, true, result);
return true;
}
- case FAILURE:
- {
- return false;
- }
default:
{
- throw new IllegalStateException(current.toString());
+ return false;
}
}
}
@@ -322,8 +312,22 @@ public abstract class HttpSender implements AsyncContentProvider.Listener
if (!completed)
return false;
- // Dispose to avoid further requests
- RequestState requestState = dispose();
+ this.failure = failure;
+
+ // Update the state to avoid more request processing.
+ RequestState current;
+ boolean fail;
+ while (true)
+ {
+ current = requestState.get();
+ if (updateRequestState(current, RequestState.FAILURE))
+ {
+ fail = current != RequestState.TRANSIENT && current != RequestState.TRANSIENT_CONTENT;
+ break;
+ }
+ }
+
+ dispose();
// Mark atomically the request as terminated and failed,
// with respect to concurrency between request and response.
@@ -335,8 +339,36 @@ public abstract class HttpSender implements AsyncContentProvider.Listener
HttpDestination destination = getHttpChannel().getHttpDestination();
destination.getRequestNotifier().notifyFailure(request, failure);
- boolean notCommitted = isBeforeCommit(requestState);
- if (result == null && notCommitted && request.getAbortCause() == null)
+ if (fail)
+ {
+ terminateRequest(exchange, failure, !isBeforeCommit(current), result);
+ }
+ else
+ {
+ if (LOG.isDebugEnabled())
+ LOG.debug("Concurrent failure: request termination skipped, performed by helpers");
+ }
+
+ return true;
+ }
+
+ private void terminateRequest(HttpExchange exchange, Throwable failure, boolean committed)
+ {
+ if (exchange != null)
+ {
+ Result result = exchange.terminateRequest(failure);
+ terminateRequest(exchange, failure, committed, result);
+ }
+ }
+
+ private void terminateRequest(HttpExchange exchange, Throwable failure, boolean committed, Result result)
+ {
+ Request request = exchange.getRequest();
+
+ if (LOG.isDebugEnabled())
+ LOG.debug("Terminating request {}", request);
+
+ if (failure != null && !committed && result == null && request.getAbortCause() == null)
{
// Complete the response from here
if (exchange.responseComplete())
@@ -349,18 +381,17 @@ public abstract class HttpSender implements AsyncContentProvider.Listener
if (result != null)
{
+ HttpDestination destination = getHttpChannel().getHttpDestination();
boolean ordered = destination.getHttpClient().isStrictEventOrdering();
if (!ordered)
channel.exchangeTerminated(result);
if (LOG.isDebugEnabled())
- LOG.debug("Request/Response failed {}", request);
+ LOG.debug("Request/Response {} {}", failure == null ? "succeeded" : "failed", request);
HttpConversation conversation = exchange.getConversation();
destination.getResponseNotifier().notifyComplete(conversation.getResponseListeners(), result);
if (ordered)
channel.exchangeTerminated(result);
}
-
- return true;
}
/**
@@ -398,23 +429,14 @@ public abstract class HttpSender implements AsyncContentProvider.Listener
{
content.close();
content = null;
- requestState.set(RequestState.QUEUED);
senderState.set(SenderState.IDLE);
}
- protected RequestState dispose()
+ protected void dispose()
{
- while (true)
- {
- RequestState current = requestState.get();
- if (updateRequestState(current, RequestState.FAILURE))
- {
- HttpContent content = this.content;
- if (content != null)
- content.close();
- return current;
- }
- }
+ HttpContent content = this.content;
+ if (content != null)
+ content.close();
}
public void proceed(HttpExchange exchange, Throwable failure)
@@ -485,7 +507,7 @@ public abstract class HttpSender implements AsyncContentProvider.Listener
return abortable && anyToFailure(failure);
}
- protected boolean updateRequestState(RequestState from, RequestState to)
+ private boolean updateRequestState(RequestState from, RequestState to)
{
boolean updated = requestState.compareAndSet(from, to);
if (!updated)
@@ -505,6 +527,7 @@ public abstract class HttpSender implements AsyncContentProvider.Listener
{
switch (requestState)
{
+ case TRANSIENT:
case QUEUED:
case BEGIN:
case HEADERS:
@@ -518,6 +541,7 @@ public abstract class HttpSender implements AsyncContentProvider.Listener
{
switch (requestState)
{
+ case TRANSIENT_CONTENT:
case COMMIT:
case CONTENT:
return true;
@@ -534,9 +558,17 @@ public abstract class HttpSender implements AsyncContentProvider.Listener
/**
* The request states {@link HttpSender} goes through when sending a request.
*/
- protected enum RequestState
+ private enum RequestState
{
/**
+ * One of the state transition methods is being executed.
+ */
+ TRANSIENT,
+ /**
+ * The content transition method is being executed.
+ */
+ TRANSIENT_CONTENT,
+ /**
* The request is queued, the initial state
*/
QUEUED,
diff --git a/jetty-client/src/main/java/org/eclipse/jetty/client/api/Connection.java b/jetty-client/src/main/java/org/eclipse/jetty/client/api/Connection.java
index 3c2d2604fa..a7ab28ce08 100644
--- a/jetty-client/src/main/java/org/eclipse/jetty/client/api/Connection.java
+++ b/jetty-client/src/main/java/org/eclipse/jetty/client/api/Connection.java
@@ -20,8 +20,6 @@ package org.eclipse.jetty.client.api;
import java.io.Closeable;
-import org.eclipse.jetty.util.Promise;
-
/**
* {@link Connection} represent a connection to a {@link Destination} and allow applications to send
* requests via {@link #send(Request, Response.CompleteListener)}.
diff --git a/jetty-client/src/main/java/org/eclipse/jetty/client/api/ContentProvider.java b/jetty-client/src/main/java/org/eclipse/jetty/client/api/ContentProvider.java
index 371b22bd82..9833e5beed 100644
--- a/jetty-client/src/main/java/org/eclipse/jetty/client/api/ContentProvider.java
+++ b/jetty-client/src/main/java/org/eclipse/jetty/client/api/ContentProvider.java
@@ -18,13 +18,7 @@
package org.eclipse.jetty.client.api;
-import java.io.Closeable;
-import java.io.InputStream;
import java.nio.ByteBuffer;
-import java.util.Iterator;
-
-import org.eclipse.jetty.client.util.ByteBufferContentProvider;
-import org.eclipse.jetty.client.util.PathContentProvider;
/**
* {@link ContentProvider} provides a source of request content.
diff --git a/jetty-client/src/main/java/org/eclipse/jetty/client/api/Destination.java b/jetty-client/src/main/java/org/eclipse/jetty/client/api/Destination.java
index 9a15564467..53a6f006ef 100644
--- a/jetty-client/src/main/java/org/eclipse/jetty/client/api/Destination.java
+++ b/jetty-client/src/main/java/org/eclipse/jetty/client/api/Destination.java
@@ -18,8 +18,6 @@
package org.eclipse.jetty.client.api;
-import org.eclipse.jetty.client.HttpClient;
-import org.eclipse.jetty.util.FuturePromise;
import org.eclipse.jetty.util.Promise;
/**
diff --git a/jetty-client/src/main/java/org/eclipse/jetty/client/api/Request.java b/jetty-client/src/main/java/org/eclipse/jetty/client/api/Request.java
index f37988cc4b..3e28e8e759 100644
--- a/jetty-client/src/main/java/org/eclipse/jetty/client/api/Request.java
+++ b/jetty-client/src/main/java/org/eclipse/jetty/client/api/Request.java
@@ -21,7 +21,6 @@ package org.eclipse.jetty.client.api;
import java.io.IOException;
import java.net.HttpCookie;
import java.net.URI;
-import java.net.URLEncoder;
import java.nio.ByteBuffer;
import java.nio.file.Path;
import java.util.EventListener;
@@ -31,8 +30,6 @@ import java.util.concurrent.ExecutionException;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;
-import org.eclipse.jetty.client.HttpClient;
-import org.eclipse.jetty.client.util.InputStreamResponseListener;
import org.eclipse.jetty.http.HttpFields;
import org.eclipse.jetty.http.HttpHeader;
import org.eclipse.jetty.http.HttpMethod;
diff --git a/jetty-client/src/main/java/org/eclipse/jetty/client/api/Response.java b/jetty-client/src/main/java/org/eclipse/jetty/client/api/Response.java
index 77d2d597b0..1f92b1eb74 100644
--- a/jetty-client/src/main/java/org/eclipse/jetty/client/api/Response.java
+++ b/jetty-client/src/main/java/org/eclipse/jetty/client/api/Response.java
@@ -22,7 +22,6 @@ import java.nio.ByteBuffer;
import java.util.EventListener;
import java.util.List;
-import org.eclipse.jetty.client.util.BufferingResponseListener;
import org.eclipse.jetty.http.HttpField;
import org.eclipse.jetty.http.HttpFields;
import org.eclipse.jetty.http.HttpVersion;
diff --git a/jetty-client/src/main/java/org/eclipse/jetty/client/http/HttpReceiverOverHTTP.java b/jetty-client/src/main/java/org/eclipse/jetty/client/http/HttpReceiverOverHTTP.java
index aa62323d01..37dfdaa802 100644
--- a/jetty-client/src/main/java/org/eclipse/jetty/client/http/HttpReceiverOverHTTP.java
+++ b/jetty-client/src/main/java/org/eclipse/jetty/client/http/HttpReceiverOverHTTP.java
@@ -120,7 +120,8 @@ public class HttpReceiverOverHTTP extends HttpReceiver implements HttpParser.Res
}
catch (Throwable x)
{
- LOG.debug(x);
+ if (LOG.isDebugEnabled())
+ LOG.debug(x);
failAndClose(x);
return true;
}
diff --git a/jetty-client/src/main/java/org/eclipse/jetty/client/http/HttpSenderOverHTTP.java b/jetty-client/src/main/java/org/eclipse/jetty/client/http/HttpSenderOverHTTP.java
index d176826fc9..c8ce04168a 100644
--- a/jetty-client/src/main/java/org/eclipse/jetty/client/http/HttpSenderOverHTTP.java
+++ b/jetty-client/src/main/java/org/eclipse/jetty/client/http/HttpSenderOverHTTP.java
@@ -123,7 +123,8 @@ public class HttpSenderOverHTTP extends HttpSender
}
catch (Throwable x)
{
- LOG.debug(x);
+ if (LOG.isDebugEnabled())
+ LOG.debug(x);
callback.failed(x);
}
}
@@ -181,7 +182,8 @@ public class HttpSenderOverHTTP extends HttpSender
}
catch (Exception x)
{
- LOG.debug(x);
+ if (LOG.isDebugEnabled())
+ LOG.debug(x);
callback.failed(x);
}
}
@@ -194,12 +196,11 @@ public class HttpSenderOverHTTP extends HttpSender
}
@Override
- protected RequestState dispose()
+ protected void dispose()
{
generator.abort();
- RequestState result = super.dispose();
+ super.dispose();
shutdownOutput();
- return result;
}
private void shutdownOutput()
diff --git a/jetty-client/src/main/java/org/eclipse/jetty/client/util/BasicAuthentication.java b/jetty-client/src/main/java/org/eclipse/jetty/client/util/BasicAuthentication.java
index 4302374e79..7c283464aa 100644
--- a/jetty-client/src/main/java/org/eclipse/jetty/client/util/BasicAuthentication.java
+++ b/jetty-client/src/main/java/org/eclipse/jetty/client/util/BasicAuthentication.java
@@ -21,9 +21,7 @@ package org.eclipse.jetty.client.util;
import java.net.URI;
import java.nio.charset.StandardCharsets;
-import org.eclipse.jetty.client.HttpClient;
import org.eclipse.jetty.client.api.Authentication;
-import org.eclipse.jetty.client.api.AuthenticationStore;
import org.eclipse.jetty.client.api.ContentResponse;
import org.eclipse.jetty.client.api.Request;
import org.eclipse.jetty.http.HttpHeader;
diff --git a/jetty-client/src/main/java/org/eclipse/jetty/client/util/ByteBufferContentProvider.java b/jetty-client/src/main/java/org/eclipse/jetty/client/util/ByteBufferContentProvider.java
index e8a695f0d6..724e3bddb6 100644
--- a/jetty-client/src/main/java/org/eclipse/jetty/client/util/ByteBufferContentProvider.java
+++ b/jetty-client/src/main/java/org/eclipse/jetty/client/util/ByteBufferContentProvider.java
@@ -22,8 +22,6 @@ import java.nio.ByteBuffer;
import java.util.Iterator;
import java.util.NoSuchElementException;
-import org.eclipse.jetty.client.api.ContentProvider;
-
/**
* A {@link ContentProvider} for {@link ByteBuffer}s.
* <p />
diff --git a/jetty-client/src/main/java/org/eclipse/jetty/client/util/BytesContentProvider.java b/jetty-client/src/main/java/org/eclipse/jetty/client/util/BytesContentProvider.java
index 7b356ef1a6..d64fa2385c 100644
--- a/jetty-client/src/main/java/org/eclipse/jetty/client/util/BytesContentProvider.java
+++ b/jetty-client/src/main/java/org/eclipse/jetty/client/util/BytesContentProvider.java
@@ -22,8 +22,6 @@ import java.nio.ByteBuffer;
import java.util.Iterator;
import java.util.NoSuchElementException;
-import org.eclipse.jetty.client.api.ContentProvider;
-
/**
* A {@link ContentProvider} for byte arrays.
*/
diff --git a/jetty-client/src/main/java/org/eclipse/jetty/client/util/DeferredContentProvider.java b/jetty-client/src/main/java/org/eclipse/jetty/client/util/DeferredContentProvider.java
index 3f34a23a6d..106983190b 100644
--- a/jetty-client/src/main/java/org/eclipse/jetty/client/util/DeferredContentProvider.java
+++ b/jetty-client/src/main/java/org/eclipse/jetty/client/util/DeferredContentProvider.java
@@ -30,9 +30,6 @@ import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.atomic.AtomicReference;
import org.eclipse.jetty.client.AsyncContentProvider;
-import org.eclipse.jetty.client.api.ContentProvider;
-import org.eclipse.jetty.client.api.Request;
-import org.eclipse.jetty.client.api.Response;
import org.eclipse.jetty.util.ArrayQueue;
import org.eclipse.jetty.util.BufferUtil;
import org.eclipse.jetty.util.Callback;
diff --git a/jetty-client/src/main/java/org/eclipse/jetty/client/util/DigestAuthentication.java b/jetty-client/src/main/java/org/eclipse/jetty/client/util/DigestAuthentication.java
index b7a32ab35b..98b9f940d3 100644
--- a/jetty-client/src/main/java/org/eclipse/jetty/client/util/DigestAuthentication.java
+++ b/jetty-client/src/main/java/org/eclipse/jetty/client/util/DigestAuthentication.java
@@ -33,9 +33,7 @@ import java.util.concurrent.atomic.AtomicInteger;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
-import org.eclipse.jetty.client.HttpClient;
import org.eclipse.jetty.client.api.Authentication;
-import org.eclipse.jetty.client.api.AuthenticationStore;
import org.eclipse.jetty.client.api.ContentResponse;
import org.eclipse.jetty.client.api.Request;
import org.eclipse.jetty.http.HttpHeader;
diff --git a/jetty-client/src/main/java/org/eclipse/jetty/client/util/FormContentProvider.java b/jetty-client/src/main/java/org/eclipse/jetty/client/util/FormContentProvider.java
index 39c490a570..cb626dbfda 100644
--- a/jetty-client/src/main/java/org/eclipse/jetty/client/util/FormContentProvider.java
+++ b/jetty-client/src/main/java/org/eclipse/jetty/client/util/FormContentProvider.java
@@ -24,7 +24,6 @@ import java.nio.charset.Charset;
import java.nio.charset.StandardCharsets;
import java.nio.charset.UnsupportedCharsetException;
-import org.eclipse.jetty.client.api.ContentProvider;
import org.eclipse.jetty.util.Fields;
/**
diff --git a/jetty-client/src/main/java/org/eclipse/jetty/client/util/InputStreamContentProvider.java b/jetty-client/src/main/java/org/eclipse/jetty/client/util/InputStreamContentProvider.java
index caa6a974d1..0a7e0ae1f9 100644
--- a/jetty-client/src/main/java/org/eclipse/jetty/client/util/InputStreamContentProvider.java
+++ b/jetty-client/src/main/java/org/eclipse/jetty/client/util/InputStreamContentProvider.java
@@ -173,7 +173,8 @@ public class InputStreamContentProvider implements ContentProvider
}
catch (Throwable x)
{
- LOG.debug(x);
+ if (LOG.isDebugEnabled())
+ LOG.debug(x);
if (failure == null)
{
failure = x;
diff --git a/jetty-client/src/main/java/org/eclipse/jetty/client/util/InputStreamResponseListener.java b/jetty-client/src/main/java/org/eclipse/jetty/client/util/InputStreamResponseListener.java
index aba6602b80..789b525365 100644
--- a/jetty-client/src/main/java/org/eclipse/jetty/client/util/InputStreamResponseListener.java
+++ b/jetty-client/src/main/java/org/eclipse/jetty/client/util/InputStreamResponseListener.java
@@ -32,7 +32,6 @@ import java.util.concurrent.TimeoutException;
import java.util.concurrent.atomic.AtomicLong;
import java.util.concurrent.atomic.AtomicReference;
-import org.eclipse.jetty.client.HttpClient;
import org.eclipse.jetty.client.api.Response;
import org.eclipse.jetty.client.api.Response.Listener;
import org.eclipse.jetty.client.api.Result;
@@ -146,27 +145,40 @@ public class InputStreamResponseListener extends Listener.Adapter
}
@Override
+ public void onSuccess(Response response)
+ {
+ if (LOG.isDebugEnabled())
+ LOG.debug("Queuing end of content {}{}", EOF, "");
+ queue.offer(EOF);
+ signal();
+ }
+
+ @Override
+ public void onFailure(Response response, Throwable failure)
+ {
+ fail(failure);
+ signal();
+ }
+
+ @Override
public void onComplete(Result result)
{
+ if (result.isFailed() && failure == null)
+ fail(result.getFailure());
this.result = result;
- if (result.isSucceeded())
- {
- if (LOG.isDebugEnabled())
- LOG.debug("Queuing end of content {}{}", EOF, "");
- queue.offer(EOF);
- }
- else
- {
- if (LOG.isDebugEnabled())
- LOG.debug("Queuing failure {} {}", FAILURE, failure);
- queue.offer(FAILURE);
- this.failure = result.getFailure();
- responseLatch.countDown();
- }
resultLatch.countDown();
signal();
}
+ private void fail(Throwable failure)
+ {
+ if (LOG.isDebugEnabled())
+ LOG.debug("Queuing failure {} {}", FAILURE, failure);
+ queue.offer(FAILURE);
+ this.failure = failure;
+ responseLatch.countDown();
+ }
+
protected boolean await()
{
try
diff --git a/jetty-client/src/main/java/org/eclipse/jetty/client/util/OutputStreamContentProvider.java b/jetty-client/src/main/java/org/eclipse/jetty/client/util/OutputStreamContentProvider.java
index cc90b5178c..d9203380be 100644
--- a/jetty-client/src/main/java/org/eclipse/jetty/client/util/OutputStreamContentProvider.java
+++ b/jetty-client/src/main/java/org/eclipse/jetty/client/util/OutputStreamContentProvider.java
@@ -24,9 +24,6 @@ import java.nio.ByteBuffer;
import java.util.Iterator;
import org.eclipse.jetty.client.AsyncContentProvider;
-import org.eclipse.jetty.client.api.ContentProvider;
-import org.eclipse.jetty.client.api.Request;
-import org.eclipse.jetty.client.api.Response;
/**
* A {@link ContentProvider} that provides content asynchronously through an {@link OutputStream}
diff --git a/jetty-client/src/main/java/org/eclipse/jetty/client/util/PathContentProvider.java b/jetty-client/src/main/java/org/eclipse/jetty/client/util/PathContentProvider.java
index 8d480d87fc..e69a2e6e6a 100644
--- a/jetty-client/src/main/java/org/eclipse/jetty/client/util/PathContentProvider.java
+++ b/jetty-client/src/main/java/org/eclipse/jetty/client/util/PathContentProvider.java
@@ -30,7 +30,6 @@ import java.nio.file.StandardOpenOption;
import java.util.Iterator;
import java.util.NoSuchElementException;
-import org.eclipse.jetty.client.api.ContentProvider;
import org.eclipse.jetty.util.log.Log;
import org.eclipse.jetty.util.log.Logger;
diff --git a/jetty-client/src/main/java/org/eclipse/jetty/client/util/StringContentProvider.java b/jetty-client/src/main/java/org/eclipse/jetty/client/util/StringContentProvider.java
index 7475c3febf..d6a58177ea 100644
--- a/jetty-client/src/main/java/org/eclipse/jetty/client/util/StringContentProvider.java
+++ b/jetty-client/src/main/java/org/eclipse/jetty/client/util/StringContentProvider.java
@@ -21,8 +21,6 @@ package org.eclipse.jetty.client.util;
import java.nio.charset.Charset;
import java.nio.charset.StandardCharsets;
-import org.eclipse.jetty.client.api.ContentProvider;
-
/**
* A {@link ContentProvider} for strings.
* <p />
diff --git a/jetty-client/src/test/java/org/eclipse/jetty/client/HostnameVerificationTest.java b/jetty-client/src/test/java/org/eclipse/jetty/client/HostnameVerificationTest.java
index 838932fbca..9147704e97 100644
--- a/jetty-client/src/test/java/org/eclipse/jetty/client/HostnameVerificationTest.java
+++ b/jetty-client/src/test/java/org/eclipse/jetty/client/HostnameVerificationTest.java
@@ -116,6 +116,11 @@ public class HostnameVerificationTest
// ExecutionException wraps an SSLHandshakeException
Throwable cause = x.getCause();
+ if (cause==null)
+ {
+ x.printStackTrace();
+ Assert.fail("No cause?");
+ }
if (cause instanceof SSLHandshakeException)
Assert.assertThat(cause.getCause().getCause(), Matchers.instanceOf(CertificateException.class));
else
diff --git a/jetty-client/src/test/java/org/eclipse/jetty/client/HttpClientAuthenticationTest.java b/jetty-client/src/test/java/org/eclipse/jetty/client/HttpClientAuthenticationTest.java
index 4c287cbdaa..a0f70f5c18 100644
--- a/jetty-client/src/test/java/org/eclipse/jetty/client/HttpClientAuthenticationTest.java
+++ b/jetty-client/src/test/java/org/eclipse/jetty/client/HttpClientAuthenticationTest.java
@@ -25,6 +25,7 @@ import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.atomic.AtomicReference;
+
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
@@ -46,6 +47,7 @@ import org.eclipse.jetty.server.Handler;
import org.eclipse.jetty.server.Server;
import org.eclipse.jetty.server.handler.AbstractHandler;
import org.eclipse.jetty.toolchain.test.MavenTestingUtils;
+import org.eclipse.jetty.util.URIUtil;
import org.eclipse.jetty.util.security.Constraint;
import org.eclipse.jetty.util.ssl.SslContextFactory;
import org.junit.Assert;
@@ -187,7 +189,7 @@ public class HttpClientAuthenticationTest extends AbstractHttpClientServerTest
{
baseRequest.setHandled(true);
if (requests.incrementAndGet() == 1)
- response.sendRedirect(scheme + "://" + request.getServerName() + ":" + request.getServerPort() + request.getRequestURI());
+ response.sendRedirect(URIUtil.newURI(scheme,request.getServerName(),request.getServerPort(),request.getRequestURI(),null));
}
});
@@ -226,7 +228,7 @@ public class HttpClientAuthenticationTest extends AbstractHttpClientServerTest
{
baseRequest.setHandled(true);
if (request.getRequestURI().endsWith("/redirect"))
- response.sendRedirect(scheme + "://" + request.getServerName() + ":" + request.getServerPort() + "/secure");
+ response.sendRedirect(URIUtil.newURI(scheme,request.getServerName(),request.getServerPort(),"/secure",null));
}
});
diff --git a/jetty-client/src/test/java/org/eclipse/jetty/client/HttpClientGZIPTest.java b/jetty-client/src/test/java/org/eclipse/jetty/client/HttpClientGZIPTest.java
new file mode 100644
index 0000000000..98aaf9966c
--- /dev/null
+++ b/jetty-client/src/test/java/org/eclipse/jetty/client/HttpClientGZIPTest.java
@@ -0,0 +1,209 @@
+//
+// ========================================================================
+// Copyright (c) 1995-2014 Mort Bay Consulting Pty. Ltd.
+// ------------------------------------------------------------------------
+// All rights reserved. This program and the accompanying materials
+// are made available under the terms of the Eclipse Public License v1.0
+// and Apache License v2.0 which accompanies this distribution.
+//
+// The Eclipse Public License is available at
+// http://www.eclipse.org/legal/epl-v10.html
+//
+// The Apache License v2.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.ByteArrayOutputStream;
+import java.io.IOException;
+import java.io.InterruptedIOException;
+import java.util.Arrays;
+import java.util.concurrent.TimeUnit;
+import java.util.zip.GZIPOutputStream;
+import javax.servlet.ServletException;
+import javax.servlet.ServletOutputStream;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import org.eclipse.jetty.client.api.ContentResponse;
+import org.eclipse.jetty.server.Request;
+import org.eclipse.jetty.server.handler.AbstractHandler;
+import org.eclipse.jetty.util.ssl.SslContextFactory;
+import org.junit.Assert;
+import org.junit.Test;
+
+public class HttpClientGZIPTest extends AbstractHttpClientServerTest
+{
+ public HttpClientGZIPTest(SslContextFactory sslContextFactory)
+ {
+ super(sslContextFactory);
+ }
+
+ @Test
+ public void testGZIPContentEncoding() throws Exception
+ {
+ final byte[] data = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9};
+ start(new AbstractHandler()
+ {
+ @Override
+ public void handle(String target, org.eclipse.jetty.server.Request baseRequest, HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException
+ {
+ baseRequest.setHandled(true);
+ response.setHeader("Content-Encoding", "gzip");
+ GZIPOutputStream gzipOutput = new GZIPOutputStream(response.getOutputStream());
+ gzipOutput.write(data);
+ gzipOutput.finish();
+ }
+ });
+
+ ContentResponse response = client.newRequest("localhost", connector.getLocalPort())
+ .scheme(scheme)
+ .timeout(5, TimeUnit.SECONDS)
+ .send();
+
+ Assert.assertEquals(200, response.getStatus());
+ Assert.assertArrayEquals(data, response.getContent());
+ }
+
+ @Test
+ public void testGZIPContentOneByteAtATime() throws Exception
+ {
+ final byte[] data = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9};
+ start(new AbstractHandler()
+ {
+ @Override
+ public void handle(String target, Request baseRequest, HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException
+ {
+ baseRequest.setHandled(true);
+ response.setHeader("Content-Encoding", "gzip");
+
+ ByteArrayOutputStream gzipData = new ByteArrayOutputStream();
+ GZIPOutputStream gzipOutput = new GZIPOutputStream(gzipData);
+ gzipOutput.write(data);
+ gzipOutput.finish();
+
+ ServletOutputStream output = response.getOutputStream();
+ byte[] gzipBytes = gzipData.toByteArray();
+ for (byte gzipByte : gzipBytes)
+ {
+ output.write(gzipByte);
+ output.flush();
+ sleep(100);
+ }
+ }
+ });
+
+ ContentResponse response = client.newRequest("localhost", connector.getLocalPort())
+ .scheme(scheme)
+ .send();
+
+ Assert.assertEquals(200, response.getStatus());
+ Assert.assertArrayEquals(data, response.getContent());
+ }
+
+ @Test
+ public void testGZIPContentSentTwiceInOneWrite() throws Exception
+ {
+ final byte[] data = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9};
+ start(new AbstractHandler()
+ {
+ @Override
+ public void handle(String target, Request baseRequest, HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException
+ {
+ baseRequest.setHandled(true);
+ response.setHeader("Content-Encoding", "gzip");
+
+ ByteArrayOutputStream gzipData = new ByteArrayOutputStream();
+ GZIPOutputStream gzipOutput = new GZIPOutputStream(gzipData);
+ gzipOutput.write(data);
+ gzipOutput.finish();
+
+ byte[] gzipBytes = gzipData.toByteArray();
+ byte[] content = Arrays.copyOf(gzipBytes, 2 * gzipBytes.length);
+ System.arraycopy(gzipBytes, 0, content, gzipBytes.length, gzipBytes.length);
+
+ ServletOutputStream output = response.getOutputStream();
+ output.write(content);
+ }
+ });
+
+ ContentResponse response = client.newRequest("localhost", connector.getLocalPort())
+ .scheme(scheme)
+ .send();
+
+ Assert.assertEquals(200, response.getStatus());
+
+ byte[] expected = Arrays.copyOf(data, 2 * data.length);
+ System.arraycopy(data, 0, expected, data.length, data.length);
+ Assert.assertArrayEquals(expected, response.getContent());
+ }
+
+ @Test
+ public void testGZIPContentFragmentedBeforeTrailer() throws Exception
+ {
+ // There are 8 trailer bytes to gzip encoding.
+ testGZIPContentFragmented(9);
+ }
+
+ @Test
+ public void testGZIPContentFragmentedAtTrailer() throws Exception
+ {
+ // There are 8 trailer bytes to gzip encoding.
+ testGZIPContentFragmented(1);
+ }
+
+ private void testGZIPContentFragmented(final int fragment) throws Exception
+ {
+ final byte[] data = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9};
+ start(new AbstractHandler()
+ {
+ @Override
+ public void handle(String target, Request baseRequest, HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException
+ {
+ baseRequest.setHandled(true);
+ response.setHeader("Content-Encoding", "gzip");
+
+ ByteArrayOutputStream gzipData = new ByteArrayOutputStream();
+ GZIPOutputStream gzipOutput = new GZIPOutputStream(gzipData);
+ gzipOutput.write(data);
+ gzipOutput.finish();
+
+ byte[] gzipBytes = gzipData.toByteArray();
+ byte[] chunk1 = Arrays.copyOfRange(gzipBytes, 0, gzipBytes.length - fragment);
+ byte[] chunk2 = Arrays.copyOfRange(gzipBytes, gzipBytes.length - fragment, gzipBytes.length);
+
+ ServletOutputStream output = response.getOutputStream();
+ output.write(chunk1);
+ output.flush();
+
+ sleep(500);
+
+ output.write(chunk2);
+ output.flush();
+ }
+ });
+
+ ContentResponse response = client.newRequest("localhost", connector.getLocalPort())
+ .scheme(scheme)
+ .send();
+
+ Assert.assertEquals(200, response.getStatus());
+ Assert.assertArrayEquals(data, response.getContent());
+ }
+
+ private static void sleep(long ms) throws IOException
+ {
+ try
+ {
+ TimeUnit.MILLISECONDS.sleep(ms);
+ }
+ catch (InterruptedException x)
+ {
+ throw new InterruptedIOException();
+ }
+ }
+}
diff --git a/jetty-client/src/test/java/org/eclipse/jetty/client/HttpClientTest.java b/jetty-client/src/test/java/org/eclipse/jetty/client/HttpClientTest.java
index 9b77675ff0..1cab93ae99 100644
--- a/jetty-client/src/test/java/org/eclipse/jetty/client/HttpClientTest.java
+++ b/jetty-client/src/test/java/org/eclipse/jetty/client/HttpClientTest.java
@@ -43,8 +43,6 @@ import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.atomic.AtomicLong;
-import java.util.zip.GZIPOutputStream;
-
import javax.servlet.ServletException;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletRequest;
@@ -672,32 +670,6 @@ public class HttpClientTest extends AbstractHttpClientServerTest
Assert.assertTrue(latch.await(5, TimeUnit.SECONDS));
}
- @Test
- public void test_GZIP_ContentEncoding() throws Exception
- {
- final byte[] data = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9};
- start(new AbstractHandler()
- {
- @Override
- public void handle(String target, org.eclipse.jetty.server.Request baseRequest, HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException
- {
- baseRequest.setHandled(true);
- response.setHeader("Content-Encoding", "gzip");
- GZIPOutputStream gzipOutput = new GZIPOutputStream(response.getOutputStream());
- gzipOutput.write(data);
- gzipOutput.finish();
- }
- });
-
- ContentResponse response = client.newRequest("localhost", connector.getLocalPort())
- .scheme(scheme)
- .timeout(5, TimeUnit.SECONDS)
- .send();
-
- Assert.assertEquals(200, response.getStatus());
- Assert.assertArrayEquals(data, response.getContent());
- }
-
@Slow
@Test
public void test_Request_IdleTimeout() throws Exception
diff --git a/jetty-client/src/test/java/org/eclipse/jetty/client/HttpResponseConcurrentAbortTest.java b/jetty-client/src/test/java/org/eclipse/jetty/client/HttpResponseConcurrentAbortTest.java
new file mode 100644
index 0000000000..a608942115
--- /dev/null
+++ b/jetty-client/src/test/java/org/eclipse/jetty/client/HttpResponseConcurrentAbortTest.java
@@ -0,0 +1,198 @@
+//
+// ========================================================================
+// Copyright (c) 1995-2014 Mort Bay Consulting Pty. Ltd.
+// ------------------------------------------------------------------------
+// All rights reserved. This program and the accompanying materials
+// are made available under the terms of the Eclipse Public License v1.0
+// and Apache License v2.0 which accompanies this distribution.
+//
+// The Eclipse Public License is available at
+// http://www.eclipse.org/legal/epl-v10.html
+//
+// The Apache License v2.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.IOException;
+import java.io.OutputStream;
+import java.nio.ByteBuffer;
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.atomic.AtomicBoolean;
+import javax.servlet.ServletException;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import org.eclipse.jetty.client.api.Response;
+import org.eclipse.jetty.client.api.Result;
+import org.eclipse.jetty.http.HttpField;
+import org.eclipse.jetty.server.Request;
+import org.eclipse.jetty.server.handler.AbstractHandler;
+import org.eclipse.jetty.util.log.Log;
+import org.eclipse.jetty.util.log.Logger;
+import org.eclipse.jetty.util.ssl.SslContextFactory;
+import org.junit.Assert;
+import org.junit.Test;
+
+public class HttpResponseConcurrentAbortTest extends AbstractHttpClientServerTest
+{
+ private final CountDownLatch callbackLatch = new CountDownLatch(1);
+ private final CountDownLatch failureLatch = new CountDownLatch(1);
+ private final CountDownLatch completeLatch = new CountDownLatch(1);
+ private final AtomicBoolean success = new AtomicBoolean();
+
+ public HttpResponseConcurrentAbortTest(SslContextFactory sslContextFactory)
+ {
+ super(sslContextFactory);
+ }
+
+ @Test
+ public void testAbortOnBegin() throws Exception
+ {
+ start(new EmptyServerHandler());
+
+ client.newRequest("localhost", connector.getLocalPort())
+ .scheme(scheme)
+ .onResponseBegin(new Response.BeginListener()
+ {
+ @Override
+ public void onBegin(Response response)
+ {
+ abort(response);
+ }
+ })
+ .send(new TestResponseListener());
+ Assert.assertTrue(callbackLatch.await(5, TimeUnit.SECONDS));
+ Assert.assertTrue(completeLatch.await(6, TimeUnit.SECONDS));
+ Assert.assertTrue(success.get());
+ }
+
+ @Test
+ public void testAbortOnHeader() throws Exception
+ {
+ start(new EmptyServerHandler());
+
+ client.newRequest("localhost", connector.getLocalPort())
+ .scheme(scheme)
+ .onResponseHeader(new Response.HeaderListener()
+ {
+ @Override
+ public boolean onHeader(Response response, HttpField field)
+ {
+ abort(response);
+ return true;
+ }
+ })
+ .send(new TestResponseListener());
+ Assert.assertTrue(callbackLatch.await(5, TimeUnit.SECONDS));
+ Assert.assertTrue(completeLatch.await(5, TimeUnit.SECONDS));
+ Assert.assertTrue(success.get());
+ }
+
+ @Test
+ public void testAbortOnHeaders() throws Exception
+ {
+ start(new EmptyServerHandler());
+
+ client.newRequest("localhost", connector.getLocalPort())
+ .scheme(scheme)
+ .onResponseHeaders(new Response.HeadersListener()
+ {
+ @Override
+ public void onHeaders(Response response)
+ {
+ abort(response);
+ }
+ })
+ .send(new TestResponseListener());
+ Assert.assertTrue(callbackLatch.await(5, TimeUnit.SECONDS));
+ Assert.assertTrue(completeLatch.await(5, TimeUnit.SECONDS));
+ Assert.assertTrue(success.get());
+ }
+
+ @Test
+ public void testAbortOnContent() throws Exception
+ {
+ start(new AbstractHandler()
+ {
+ @Override
+ public void handle(String target, Request baseRequest, HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException
+ {
+ baseRequest.setHandled(true);
+ OutputStream output = response.getOutputStream();
+ output.write(1);
+ output.flush();
+ }
+ });
+
+ client.newRequest("localhost", connector.getLocalPort())
+ .scheme(scheme)
+ .onResponseContent(new Response.ContentListener()
+ {
+ @Override
+ public void onContent(Response response, ByteBuffer content)
+ {
+ abort(response);
+ }
+ })
+ .send(new TestResponseListener());
+ Assert.assertTrue(callbackLatch.await(5, TimeUnit.SECONDS));
+ Assert.assertTrue(completeLatch.await(5, TimeUnit.SECONDS));
+ Assert.assertTrue(success.get());
+ }
+
+ private void abort(final Response response)
+ {
+ Logger logger = Log.getLogger(getClass());
+
+ new Thread("abort")
+ {
+ @Override
+ public void run()
+ {
+ response.abort(new Exception());
+ }
+ }.start();
+
+ try
+ {
+ // The failure callback must be executed asynchronously.
+ boolean latched = failureLatch.await(4, TimeUnit.SECONDS);
+ success.set(latched);
+ logger.info("SIMON - STEP 1");
+
+ // The complete callback must not be executed
+ // until we return from this callback.
+ latched = completeLatch.await(1, TimeUnit.SECONDS);
+ success.set(!latched);
+ logger.info("SIMON - STEP 2");
+
+ callbackLatch.countDown();
+ }
+ catch (InterruptedException x)
+ {
+ throw new RuntimeException(x);
+ }
+ }
+
+ private class TestResponseListener extends Response.Listener.Adapter
+ {
+ @Override
+ public void onFailure(Response response, Throwable failure)
+ {
+ failureLatch.countDown();
+ }
+
+ @Override
+ public void onComplete(Result result)
+ {
+ Assert.assertTrue(result.isFailed());
+ completeLatch.countDown();
+ }
+ }
+}
diff --git a/jetty-client/src/test/java/org/eclipse/jetty/client/http/HttpReceiverOverHTTPTest.java b/jetty-client/src/test/java/org/eclipse/jetty/client/http/HttpReceiverOverHTTPTest.java
index 0be2b91397..e7564b5e64 100644
--- a/jetty-client/src/test/java/org/eclipse/jetty/client/http/HttpReceiverOverHTTPTest.java
+++ b/jetty-client/src/test/java/org/eclipse/jetty/client/http/HttpReceiverOverHTTPTest.java
@@ -18,23 +18,18 @@
package org.eclipse.jetty.client.http;
-import java.io.ByteArrayOutputStream;
import java.io.EOFException;
-import java.nio.ByteBuffer;
import java.nio.charset.StandardCharsets;
import java.util.Collections;
-import java.util.concurrent.CountDownLatch;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;
-import java.util.zip.GZIPOutputStream;
import org.eclipse.jetty.client.HttpClient;
import org.eclipse.jetty.client.HttpExchange;
import org.eclipse.jetty.client.HttpRequest;
import org.eclipse.jetty.client.HttpResponseException;
import org.eclipse.jetty.client.Origin;
-import org.eclipse.jetty.client.api.ContentResponse;
import org.eclipse.jetty.client.api.Response;
import org.eclipse.jetty.client.util.FutureResponseListener;
import org.eclipse.jetty.http.HttpFields;
@@ -205,58 +200,4 @@ public class HttpReceiverOverHTTPTest
Assert.assertTrue(e.getCause() instanceof HttpResponseException);
}
}
-
- @Test
- public void test_Receive_GZIPResponseContent_Fragmented() throws Exception
- {
- byte[] data = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9};
- ByteArrayOutputStream baos = new ByteArrayOutputStream();
- try (GZIPOutputStream gzipOutput = new GZIPOutputStream(baos))
- {
- gzipOutput.write(data);
- }
- byte[] gzip = baos.toByteArray();
-
- endPoint.setInput("" +
- "HTTP/1.1 200 OK\r\n" +
- "Content-Length: " + gzip.length + "\r\n" +
- "Content-Encoding: gzip\r\n" +
- "\r\n");
-
- HttpRequest request = (HttpRequest)client.newRequest("http://localhost");
- final CountDownLatch latch = new CountDownLatch(1);
- FutureResponseListener listener = new FutureResponseListener(request)
- {
- @Override
- public void onContent(Response response, ByteBuffer content)
- {
- super.onContent(response, content);
- latch.countDown();
- }
- };
- HttpExchange exchange = new HttpExchange(destination, request, Collections.<Response.ResponseListener>singletonList(listener));
- connection.getHttpChannel().associate(exchange);
- exchange.requestComplete();
- exchange.terminateRequest(null);
- connection.getHttpChannel().receive();
- endPoint.reset();
-
- ByteBuffer buffer = ByteBuffer.wrap(gzip);
- int fragment = buffer.limit() - 1;
- buffer.limit(fragment);
- endPoint.setInput(buffer);
- connection.getHttpChannel().receive();
- endPoint.reset();
-
- buffer.limit(gzip.length);
- buffer.position(fragment);
- endPoint.setInput(buffer);
- connection.getHttpChannel().receive();
-
- ContentResponse response = listener.get(5, TimeUnit.SECONDS);
- Assert.assertNotNull(response);
- Assert.assertEquals(200, response.getStatus());
- Assert.assertTrue(latch.await(5, TimeUnit.SECONDS));
- Assert.assertArrayEquals(data, response.getContent());
- }
}
diff --git a/jetty-client/src/test/java/org/eclipse/jetty/client/ssl/SslBytesServerTest.java b/jetty-client/src/test/java/org/eclipse/jetty/client/ssl/SslBytesServerTest.java
index bdef5f21fd..1f4077f83c 100644
--- a/jetty-client/src/test/java/org/eclipse/jetty/client/ssl/SslBytesServerTest.java
+++ b/jetty-client/src/test/java/org/eclipse/jetty/client/ssl/SslBytesServerTest.java
@@ -1049,9 +1049,9 @@ public class SslBytesServerTest extends SslBytesTest
@Test
public void testRequestWithBigContentWriteBlockedThenReset() throws Exception
{
- // Don't run on Windows (buggy JVM)
- Assume.assumeTrue(!OS.IS_WINDOWS);
-
+ // Don't run on Windows (buggy JVM)
+ Assume.assumeTrue(!OS.IS_WINDOWS);
+
final SSLSocket client = newClient();
SimpleProxy.AutomaticFlow automaticProxyFlow = proxy.startAutomaticFlow();
@@ -1110,10 +1110,10 @@ public class SslBytesServerTest extends SslBytesTest
@Test
public void testRequestWithBigContentReadBlockedThenReset() throws Exception
{
- // Don't run on Windows (buggy JVM)
- Assume.assumeTrue(!OS.IS_WINDOWS);
-
- final SSLSocket client = newClient();
+ // Don't run on Windows (buggy JVM)
+ Assume.assumeTrue(!OS.IS_WINDOWS);
+
+ final SSLSocket client = newClient();
SimpleProxy.AutomaticFlow automaticProxyFlow = proxy.startAutomaticFlow();
client.startHandshake();
diff --git a/jetty-continuation/pom.xml b/jetty-continuation/pom.xml
index e4cd29f827..ed2e787cdc 100644
--- a/jetty-continuation/pom.xml
+++ b/jetty-continuation/pom.xml
@@ -2,7 +2,7 @@
<parent>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-project</artifactId>
- <version>9.2.2-SNAPSHOT</version>
+ <version>9.2.3-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>jetty-continuation</artifactId>
diff --git a/jetty-continuation/src/main/java/org/eclipse/jetty/continuation/Continuation.java b/jetty-continuation/src/main/java/org/eclipse/jetty/continuation/Continuation.java
index 0eb8ca0efd..da0239cb7e 100644
--- a/jetty-continuation/src/main/java/org/eclipse/jetty/continuation/Continuation.java
+++ b/jetty-continuation/src/main/java/org/eclipse/jetty/continuation/Continuation.java
@@ -18,12 +18,7 @@
package org.eclipse.jetty.continuation;
-import javax.servlet.Filter;
-import javax.servlet.FilterChain;
-import javax.servlet.Servlet;
-import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
-import javax.servlet.ServletResponseWrapper;
/* ------------------------------------------------------------ */
/**
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 4b960d5f09..b6c337e9dd 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
@@ -20,8 +20,6 @@ package org.eclipse.jetty.continuation;
import java.util.EventListener;
-import javax.servlet.ServletRequestListener;
-
/* ------------------------------------------------------------ */
/** A Continuation Listener
diff --git a/jetty-deploy/pom.xml b/jetty-deploy/pom.xml
index ee18417a37..316224fee9 100644
--- a/jetty-deploy/pom.xml
+++ b/jetty-deploy/pom.xml
@@ -2,7 +2,7 @@
<parent>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-project</artifactId>
- <version>9.2.2-SNAPSHOT</version>
+ <version>9.2.3-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>jetty-deploy</artifactId>
diff --git a/jetty-deploy/src/main/java/org/eclipse/jetty/deploy/AppProvider.java b/jetty-deploy/src/main/java/org/eclipse/jetty/deploy/AppProvider.java
index 1ad17bc235..a0e84ee362 100644
--- a/jetty-deploy/src/main/java/org/eclipse/jetty/deploy/AppProvider.java
+++ b/jetty-deploy/src/main/java/org/eclipse/jetty/deploy/AppProvider.java
@@ -18,8 +18,6 @@
package org.eclipse.jetty.deploy;
-import java.io.IOException;
-
import org.eclipse.jetty.server.handler.ContextHandler;
import org.eclipse.jetty.util.component.LifeCycle;
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 7e50a96433..d8d5b15053 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
@@ -25,7 +25,6 @@ import java.util.Locale;
import org.eclipse.jetty.deploy.App;
import org.eclipse.jetty.deploy.ConfigurationManager;
import org.eclipse.jetty.deploy.util.FileID;
-import org.eclipse.jetty.server.Server;
import org.eclipse.jetty.server.handler.ContextHandler;
import org.eclipse.jetty.util.URIUtil;
import org.eclipse.jetty.util.annotation.ManagedAttribute;
diff --git a/jetty-deploy/src/test/java/org/eclipse/jetty/deploy/AppLifeCycleTest.java b/jetty-deploy/src/test/java/org/eclipse/jetty/deploy/AppLifeCycleTest.java
index 78f113967d..d296611946 100644
--- a/jetty-deploy/src/test/java/org/eclipse/jetty/deploy/AppLifeCycleTest.java
+++ b/jetty-deploy/src/test/java/org/eclipse/jetty/deploy/AppLifeCycleTest.java
@@ -36,10 +36,10 @@ import org.junit.Test;
*/
public class AppLifeCycleTest
{
- @Rule
- public TestingDir testdir = new TestingDir();
+ @Rule
+ public TestingDir testdir = new TestingDir();
- private void assertNoPath(String from, String to)
+ private void assertNoPath(String from, String to)
{
assertPath(from,to,new ArrayList<String>());
}
diff --git a/jetty-deploy/src/test/java/org/eclipse/jetty/deploy/bindings/GlobalWebappConfigBindingTest.java b/jetty-deploy/src/test/java/org/eclipse/jetty/deploy/bindings/GlobalWebappConfigBindingTest.java
index 3acec97f29..7d80fc092c 100644
--- a/jetty-deploy/src/test/java/org/eclipse/jetty/deploy/bindings/GlobalWebappConfigBindingTest.java
+++ b/jetty-deploy/src/test/java/org/eclipse/jetty/deploy/bindings/GlobalWebappConfigBindingTest.java
@@ -26,7 +26,6 @@ import static org.hamcrest.Matchers.not;
import java.io.File;
import java.util.List;
-import org.eclipse.jetty.deploy.providers.ScanningAppProvider;
import org.eclipse.jetty.deploy.test.XmlConfiguredJetty;
import org.eclipse.jetty.toolchain.test.IO;
import org.eclipse.jetty.toolchain.test.MavenTestingUtils;
diff --git a/jetty-deploy/src/test/java/org/eclipse/jetty/deploy/providers/ScanningAppProviderStartupTest.java b/jetty-deploy/src/test/java/org/eclipse/jetty/deploy/providers/ScanningAppProviderStartupTest.java
index eb7e0c0e69..949acfd626 100644
--- a/jetty-deploy/src/test/java/org/eclipse/jetty/deploy/providers/ScanningAppProviderStartupTest.java
+++ b/jetty-deploy/src/test/java/org/eclipse/jetty/deploy/providers/ScanningAppProviderStartupTest.java
@@ -30,8 +30,8 @@ import org.junit.Test;
*/
public class ScanningAppProviderStartupTest
{
- @Rule
- public TestingDir testdir = new TestingDir();
+ @Rule
+ public TestingDir testdir = new TestingDir();
private static XmlConfiguredJetty jetty;
@Before
diff --git a/jetty-distribution/pom.xml b/jetty-distribution/pom.xml
index c08257930b..91a2d9608b 100644
--- a/jetty-distribution/pom.xml
+++ b/jetty-distribution/pom.xml
@@ -3,7 +3,7 @@
<parent>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-project</artifactId>
- <version>9.2.2-SNAPSHOT</version>
+ <version>9.2.3-SNAPSHOT</version>
</parent>
<artifactId>jetty-distribution</artifactId>
<name>Jetty :: Distribution Assemblies</name>
diff --git a/jetty-fcgi/fcgi-client/pom.xml b/jetty-fcgi/fcgi-client/pom.xml
index 597f56add6..8308f0928f 100644
--- a/jetty-fcgi/fcgi-client/pom.xml
+++ b/jetty-fcgi/fcgi-client/pom.xml
@@ -3,7 +3,7 @@
<parent>
<groupId>org.eclipse.jetty.fcgi</groupId>
<artifactId>fcgi-parent</artifactId>
- <version>9.2.2-SNAPSHOT</version>
+ <version>9.2.3-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
diff --git a/jetty-fcgi/fcgi-client/src/main/java/org/eclipse/jetty/fcgi/client/http/HttpConnectionOverFCGI.java b/jetty-fcgi/fcgi-client/src/main/java/org/eclipse/jetty/fcgi/client/http/HttpConnectionOverFCGI.java
index ab41fe689d..91f0dee799 100644
--- a/jetty-fcgi/fcgi-client/src/main/java/org/eclipse/jetty/fcgi/client/http/HttpConnectionOverFCGI.java
+++ b/jetty-fcgi/fcgi-client/src/main/java/org/eclipse/jetty/fcgi/client/http/HttpConnectionOverFCGI.java
@@ -150,7 +150,8 @@ public class HttpConnectionOverFCGI extends AbstractConnection implements Connec
}
catch (Exception x)
{
- LOG.debug(x);
+ if (LOG.isDebugEnabled())
+ LOG.debug(x);
close(x);
return false;
}
diff --git a/jetty-fcgi/fcgi-client/src/main/java/org/eclipse/jetty/fcgi/parser/ParamsContentParser.java b/jetty-fcgi/fcgi-client/src/main/java/org/eclipse/jetty/fcgi/parser/ParamsContentParser.java
index 42cbee811d..261c1b1a82 100644
--- a/jetty-fcgi/fcgi-client/src/main/java/org/eclipse/jetty/fcgi/parser/ParamsContentParser.java
+++ b/jetty-fcgi/fcgi-client/src/main/java/org/eclipse/jetty/fcgi/parser/ParamsContentParser.java
@@ -27,7 +27,7 @@ import org.eclipse.jetty.util.log.Logger;
public class ParamsContentParser extends ContentParser
{
- private static final Logger logger = Log.getLogger(ParamsContentParser.class);
+ private static final Logger LOG = Log.getLogger(ParamsContentParser.class);
private final ServerParser.Listener listener;
private State state = State.LENGTH;
@@ -212,7 +212,8 @@ public class ParamsContentParser extends ContentParser
}
catch (Throwable x)
{
- logger.debug("Exception while invoking listener " + listener, x);
+ if (LOG.isDebugEnabled())
+ LOG.debug("Exception while invoking listener " + listener, x);
}
}
@@ -224,7 +225,8 @@ public class ParamsContentParser extends ContentParser
}
catch (Throwable x)
{
- logger.debug("Exception while invoking listener " + listener, x);
+ if (LOG.isDebugEnabled())
+ LOG.debug("Exception while invoking listener " + listener, x);
}
}
diff --git a/jetty-fcgi/fcgi-client/src/main/java/org/eclipse/jetty/fcgi/parser/ResponseContentParser.java b/jetty-fcgi/fcgi-client/src/main/java/org/eclipse/jetty/fcgi/parser/ResponseContentParser.java
index 0e1b685bcb..595c78ca8d 100644
--- a/jetty-fcgi/fcgi-client/src/main/java/org/eclipse/jetty/fcgi/parser/ResponseContentParser.java
+++ b/jetty-fcgi/fcgi-client/src/main/java/org/eclipse/jetty/fcgi/parser/ResponseContentParser.java
@@ -187,7 +187,8 @@ public class ResponseContentParser extends StreamContentParser
}
catch (Throwable x)
{
- logger.debug("Exception while invoking listener " + listener, x);
+ if (LOG.isDebugEnabled())
+ LOG.debug("Exception while invoking listener " + listener, x);
}
return false;
}
@@ -200,7 +201,8 @@ public class ResponseContentParser extends StreamContentParser
}
catch (Throwable x)
{
- logger.debug("Exception while invoking listener " + listener, x);
+ if (LOG.isDebugEnabled())
+ LOG.debug("Exception while invoking listener " + listener, x);
}
}
@@ -212,7 +214,8 @@ public class ResponseContentParser extends StreamContentParser
}
catch (Throwable x)
{
- logger.debug("Exception while invoking listener " + listener, x);
+ if (LOG.isDebugEnabled())
+ LOG.debug("Exception while invoking listener " + listener, x);
}
}
@@ -233,7 +236,8 @@ public class ResponseContentParser extends StreamContentParser
}
catch (Throwable x)
{
- logger.debug("Exception while invoking listener " + listener, x);
+ if (LOG.isDebugEnabled())
+ LOG.debug("Exception while invoking listener " + listener, x);
}
}
@@ -265,7 +269,8 @@ public class ResponseContentParser extends StreamContentParser
}
catch (Throwable x)
{
- logger.debug("Exception while invoking listener " + listener, x);
+ if (LOG.isDebugEnabled())
+ LOG.debug("Exception while invoking listener " + listener, x);
return false;
}
}
diff --git a/jetty-fcgi/fcgi-client/src/main/java/org/eclipse/jetty/fcgi/parser/StreamContentParser.java b/jetty-fcgi/fcgi-client/src/main/java/org/eclipse/jetty/fcgi/parser/StreamContentParser.java
index 655a4d24bf..9770b5fef9 100644
--- a/jetty-fcgi/fcgi-client/src/main/java/org/eclipse/jetty/fcgi/parser/StreamContentParser.java
+++ b/jetty-fcgi/fcgi-client/src/main/java/org/eclipse/jetty/fcgi/parser/StreamContentParser.java
@@ -26,7 +26,7 @@ import org.eclipse.jetty.util.log.Logger;
public class StreamContentParser extends ContentParser
{
- protected static final Logger logger = Log.getLogger(StreamContentParser.class);
+ private static final Logger LOG = Log.getLogger(StreamContentParser.class);
private final FCGI.StreamType streamType;
private final Parser.Listener listener;
@@ -87,7 +87,8 @@ public class StreamContentParser extends ContentParser
}
catch (Throwable x)
{
- logger.debug("Exception while invoking listener " + listener, x);
+ if (LOG.isDebugEnabled())
+ LOG.debug("Exception while invoking listener " + listener, x);
}
}
@@ -99,7 +100,8 @@ public class StreamContentParser extends ContentParser
}
catch (Throwable x)
{
- logger.debug("Exception while invoking listener " + listener, x);
+ if (LOG.isDebugEnabled())
+ LOG.debug("Exception while invoking listener " + listener, x);
return false;
}
}
diff --git a/jetty-fcgi/fcgi-server/pom.xml b/jetty-fcgi/fcgi-server/pom.xml
index bc91733147..b8df5d1aef 100644
--- a/jetty-fcgi/fcgi-server/pom.xml
+++ b/jetty-fcgi/fcgi-server/pom.xml
@@ -3,7 +3,7 @@
<parent>
<groupId>org.eclipse.jetty.fcgi</groupId>
<artifactId>fcgi-parent</artifactId>
- <version>9.2.2-SNAPSHOT</version>
+ <version>9.2.3-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
diff --git a/jetty-fcgi/fcgi-server/src/main/java/org/eclipse/jetty/fcgi/server/ServerFCGIConnection.java b/jetty-fcgi/fcgi-server/src/main/java/org/eclipse/jetty/fcgi/server/ServerFCGIConnection.java
index 027bf00daa..7b7291e725 100644
--- a/jetty-fcgi/fcgi-server/src/main/java/org/eclipse/jetty/fcgi/server/ServerFCGIConnection.java
+++ b/jetty-fcgi/fcgi-server/src/main/java/org/eclipse/jetty/fcgi/server/ServerFCGIConnection.java
@@ -94,7 +94,8 @@ public class ServerFCGIConnection extends AbstractConnection
}
catch (Exception x)
{
- LOG.debug(x);
+ if (LOG.isDebugEnabled())
+ LOG.debug(x);
// TODO: fail and close ?
}
finally
diff --git a/jetty-fcgi/fcgi-server/src/test/java/org/eclipse/jetty/fcgi/server/HttpClientTest.java b/jetty-fcgi/fcgi-server/src/test/java/org/eclipse/jetty/fcgi/server/HttpClientTest.java
index e97750f8b5..08ccf9c643 100644
--- a/jetty-fcgi/fcgi-server/src/test/java/org/eclipse/jetty/fcgi/server/HttpClientTest.java
+++ b/jetty-fcgi/fcgi-server/src/test/java/org/eclipse/jetty/fcgi/server/HttpClientTest.java
@@ -697,7 +697,7 @@ public class HttpClientTest extends AbstractHttpClientServerTest
contentLatch.set(new CountDownLatch(1));
callback.succeeded();
- Assert.assertTrue(completeLatch.await(555, TimeUnit.SECONDS));
+ Assert.assertTrue(completeLatch.await(5, TimeUnit.SECONDS));
Assert.assertEquals(2, contentCount.get());
}
}
diff --git a/jetty-fcgi/pom.xml b/jetty-fcgi/pom.xml
index addd9a8124..23b724eead 100644
--- a/jetty-fcgi/pom.xml
+++ b/jetty-fcgi/pom.xml
@@ -3,7 +3,7 @@
<parent>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-project</artifactId>
- <version>9.2.2-SNAPSHOT</version>
+ <version>9.2.3-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
diff --git a/jetty-http-spi/pom.xml b/jetty-http-spi/pom.xml
index af221b5421..48d699e361 100644
--- a/jetty-http-spi/pom.xml
+++ b/jetty-http-spi/pom.xml
@@ -2,7 +2,7 @@
<parent>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-project</artifactId>
- <version>9.2.2-SNAPSHOT</version>
+ <version>9.2.3-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>jetty-http-spi</artifactId>
diff --git a/jetty-http-spi/src/main/java/org/eclipse/jetty/http/spi/JettyHttpContext.java b/jetty-http-spi/src/main/java/org/eclipse/jetty/http/spi/JettyHttpContext.java
index 531e02464d..b7b838f274 100644
--- a/jetty-http-spi/src/main/java/org/eclipse/jetty/http/spi/JettyHttpContext.java
+++ b/jetty-http-spi/src/main/java/org/eclipse/jetty/http/spi/JettyHttpContext.java
@@ -97,8 +97,8 @@ public class JettyHttpContext extends com.sun.net.httpserver.HttpContext
@Override
public Authenticator setAuthenticator(Authenticator auth)
{
- Authenticator previous = _authenticator;
- _authenticator = auth;
+ Authenticator previous = _authenticator;
+ _authenticator = auth;
return previous;
}
diff --git a/jetty-http-spi/src/main/java/org/eclipse/jetty/http/spi/JettyHttpServer.java b/jetty-http-spi/src/main/java/org/eclipse/jetty/http/spi/JettyHttpServer.java
index 417169c0ce..7f1af098d4 100644
--- a/jetty-http-spi/src/main/java/org/eclipse/jetty/http/spi/JettyHttpServer.java
+++ b/jetty-http-spi/src/main/java/org/eclipse/jetty/http/spi/JettyHttpServer.java
@@ -1,271 +1,271 @@
-//
-// ========================================================================
-// Copyright (c) 1995-2014 Mort Bay Consulting Pty. Ltd.
-// ------------------------------------------------------------------------
-// All rights reserved. This program and the accompanying materials
-// are made available under the terms of the Eclipse Public License v1.0
-// and Apache License v2.0 which accompanies this distribution.
-//
-// The Eclipse Public License is available at
-// http://www.eclipse.org/legal/epl-v10.html
-//
-// The Apache License v2.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.http.spi;
-
-import java.io.IOException;
-import java.net.InetSocketAddress;
-import java.util.Collection;
-import java.util.HashMap;
-import java.util.Map;
-import java.util.concurrent.Executor;
-import java.util.concurrent.ThreadPoolExecutor;
-
-import org.eclipse.jetty.server.Connector;
-import org.eclipse.jetty.server.Handler;
-import org.eclipse.jetty.server.NetworkConnector;
-import org.eclipse.jetty.server.Server;
-import org.eclipse.jetty.server.ServerConnector;
-import org.eclipse.jetty.server.handler.ContextHandler;
-import org.eclipse.jetty.server.handler.ContextHandlerCollection;
-import org.eclipse.jetty.server.handler.HandlerCollection;
-import org.eclipse.jetty.util.log.Log;
-import org.eclipse.jetty.util.log.Logger;
-import org.eclipse.jetty.util.thread.ThreadPool;
-
-import com.sun.net.httpserver.HttpContext;
-import com.sun.net.httpserver.HttpHandler;
-
-/**
- * Jetty implementation of {@link com.sun.net.httpserver.HttpServer}.
- */
-public class JettyHttpServer extends com.sun.net.httpserver.HttpServer
+//
+// ========================================================================
+// Copyright (c) 1995-2014 Mort Bay Consulting Pty. Ltd.
+// ------------------------------------------------------------------------
+// All rights reserved. This program and the accompanying materials
+// are made available under the terms of the Eclipse Public License v1.0
+// and Apache License v2.0 which accompanies this distribution.
+//
+// The Eclipse Public License is available at
+// http://www.eclipse.org/legal/epl-v10.html
+//
+// The Apache License v2.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.http.spi;
+
+import java.io.IOException;
+import java.net.InetSocketAddress;
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.concurrent.Executor;
+import java.util.concurrent.ThreadPoolExecutor;
+
+import org.eclipse.jetty.server.Connector;
+import org.eclipse.jetty.server.Handler;
+import org.eclipse.jetty.server.NetworkConnector;
+import org.eclipse.jetty.server.Server;
+import org.eclipse.jetty.server.ServerConnector;
+import org.eclipse.jetty.server.handler.ContextHandler;
+import org.eclipse.jetty.server.handler.ContextHandlerCollection;
+import org.eclipse.jetty.server.handler.HandlerCollection;
+import org.eclipse.jetty.util.log.Log;
+import org.eclipse.jetty.util.log.Logger;
+import org.eclipse.jetty.util.thread.ThreadPool;
+
+import com.sun.net.httpserver.HttpContext;
+import com.sun.net.httpserver.HttpHandler;
+
+/**
+ * Jetty implementation of {@link com.sun.net.httpserver.HttpServer}.
+ */
+public class JettyHttpServer extends com.sun.net.httpserver.HttpServer
{
private static final Logger LOG = Log.getLogger(JettyHttpServer.class);
-
-
- private Server _server;
-
- private boolean _serverShared;
-
- private InetSocketAddress _addr;
-
- private ThreadPoolExecutor _executor;
-
- private Map<String, JettyHttpContext> _contexts = new HashMap<String, JettyHttpContext>();
-
- private Map<String, Connector> _connectors = new HashMap<String, Connector>();
-
-
- public JettyHttpServer(Server server, boolean shared)
- {
- this._server = server;
- this._serverShared = shared;
- }
-
- @Override
- public void bind(InetSocketAddress addr, int backlog) throws IOException
- {
- // check if there is already a connector listening
- Collection<NetworkConnector> connectors = _server.getBeans(NetworkConnector.class);
- if (connectors != null)
- {
- for (NetworkConnector connector : connectors)
- {
- if (connector.getPort() == addr.getPort()) {
- if (LOG.isDebugEnabled()) LOG.debug("server already bound to port " + addr.getPort() + ", no need to rebind");
- return;
- }
- }
- }
-
- if (_serverShared)
- throw new IOException("jetty server is not bound to port " + addr.getPort());
-
- this._addr = addr;
-
- if (LOG.isDebugEnabled()) LOG.debug("binding server to port " + addr.getPort());
- ServerConnector connector = new ServerConnector(_server);
- connector.setPort(addr.getPort());
- connector.setHost(addr.getHostName());
- _server.addConnector(connector);
-
- _connectors.put(addr.getHostName() + addr.getPort(), connector);
- }
-
- @Override
- public InetSocketAddress getAddress()
- {
- return _addr;
- }
-
- @Override
- public void start()
- {
- if (_serverShared) return;
-
- try
- {
- _server.start();
- }
- catch (Exception ex)
- {
- throw new RuntimeException(ex);
- }
- }
-
- @Override
- public void setExecutor(Executor executor)
- {
- if (executor == null)
- throw new IllegalArgumentException("missing required 'executor' argument");
- ThreadPool threadPool = _server.getThreadPool();
- if (threadPool instanceof DelegatingThreadPool)
- ((DelegatingThreadPool)_server.getThreadPool()).setExecutor(executor);
- else
- throw new UnsupportedOperationException("!DelegatingThreadPool");
- }
-
- @Override
- public Executor getExecutor()
- {
- ThreadPool threadPool = _server.getThreadPool();
- if (threadPool instanceof DelegatingThreadPool)
- return ((DelegatingThreadPool)_server.getThreadPool()).getExecutor();
- return threadPool;
- }
-
- @Override
- public void stop(int delay)
- {
- cleanUpContexts();
- cleanUpConnectors();
-
- if (_serverShared) return;
-
- try
- {
- _server.stop();
- }
- catch (Exception ex)
- {
- throw new RuntimeException(ex);
- }
- }
-
- private void cleanUpContexts()
- {
- for (Map.Entry<String, JettyHttpContext> stringJettyHttpContextEntry : _contexts.entrySet())
- {
- JettyHttpContext context = stringJettyHttpContextEntry.getValue();
- _server.removeBean(context.getJettyContextHandler());
- }
- _contexts.clear();
- }
-
- private void cleanUpConnectors()
- {
- for (Map.Entry<String, Connector> stringConnectorEntry : _connectors.entrySet())
- {
- Connector connector = stringConnectorEntry.getValue();
- try
- {
- connector.stop();
- } catch (Exception ex) {
- LOG.warn(ex);
- }
- _server.removeConnector(connector);
- }
- _connectors.clear();
- }
-
- @Override
- public HttpContext createContext(String path, HttpHandler httpHandler)
- {
- checkIfContextIsFree(path);
-
- JettyHttpContext context = new JettyHttpContext(this, path, httpHandler);
- HttpSpiContextHandler jettyContextHandler = context.getJettyContextHandler();
-
- ContextHandlerCollection chc = findContextHandlerCollection(_server.getHandlers());
- if (chc == null)
- throw new RuntimeException("could not find ContextHandlerCollection, you must configure one");
-
- chc.addHandler(jettyContextHandler);
- _contexts.put(path, context);
-
- return context;
- }
-
- private ContextHandlerCollection findContextHandlerCollection(Handler[] handlers)
- {
- if (handlers == null)
- return null;
-
- for (Handler handler : handlers)
- {
- if (handler instanceof ContextHandlerCollection)
- {
- return (ContextHandlerCollection) handler;
- }
-
- if (handler instanceof HandlerCollection)
- {
- HandlerCollection hc = (HandlerCollection) handler;
- ContextHandlerCollection chc = findContextHandlerCollection(hc.getHandlers());
- if (chc != null)
- return chc;
- }
- }
- return null;
- }
-
- private void checkIfContextIsFree(String path)
- {
- Handler serverHandler = _server.getHandler();
- if (serverHandler instanceof ContextHandler)
- {
- ContextHandler ctx = (ContextHandler) serverHandler;
- if (ctx.getContextPath().equals(path))
- throw new RuntimeException("another context already bound to path " + path);
- }
-
- Handler[] handlers = _server.getHandlers();
- if (handlers == null) return;
-
- for (Handler handler : handlers)
- {
- if (handler instanceof ContextHandler) {
- ContextHandler ctx = (ContextHandler) handler;
- if (ctx.getContextPath().equals(path))
- throw new RuntimeException("another context already bound to path " + path);
- }
- }
- }
-
- @Override
- public HttpContext createContext(String path)
- {
- return createContext(path, null);
- }
-
- @Override
- public void removeContext(String path) throws IllegalArgumentException
- {
- JettyHttpContext context = _contexts.remove(path);
- if (context == null) return;
- _server.removeBean(context.getJettyContextHandler());
- }
-
- @Override
- public void removeContext(HttpContext context)
- {
- removeContext(context.getPath());
- }
-
-}
+
+
+ private Server _server;
+
+ private boolean _serverShared;
+
+ private InetSocketAddress _addr;
+
+ private ThreadPoolExecutor _executor;
+
+ private Map<String, JettyHttpContext> _contexts = new HashMap<String, JettyHttpContext>();
+
+ private Map<String, Connector> _connectors = new HashMap<String, Connector>();
+
+
+ public JettyHttpServer(Server server, boolean shared)
+ {
+ this._server = server;
+ this._serverShared = shared;
+ }
+
+ @Override
+ public void bind(InetSocketAddress addr, int backlog) throws IOException
+ {
+ // check if there is already a connector listening
+ Collection<NetworkConnector> connectors = _server.getBeans(NetworkConnector.class);
+ if (connectors != null)
+ {
+ for (NetworkConnector connector : connectors)
+ {
+ if (connector.getPort() == addr.getPort()) {
+ if (LOG.isDebugEnabled()) LOG.debug("server already bound to port " + addr.getPort() + ", no need to rebind");
+ return;
+ }
+ }
+ }
+
+ if (_serverShared)
+ throw new IOException("jetty server is not bound to port " + addr.getPort());
+
+ this._addr = addr;
+
+ if (LOG.isDebugEnabled()) LOG.debug("binding server to port " + addr.getPort());
+ ServerConnector connector = new ServerConnector(_server);
+ connector.setPort(addr.getPort());
+ connector.setHost(addr.getHostName());
+ _server.addConnector(connector);
+
+ _connectors.put(addr.getHostName() + addr.getPort(), connector);
+ }
+
+ @Override
+ public InetSocketAddress getAddress()
+ {
+ return _addr;
+ }
+
+ @Override
+ public void start()
+ {
+ if (_serverShared) return;
+
+ try
+ {
+ _server.start();
+ }
+ catch (Exception ex)
+ {
+ throw new RuntimeException(ex);
+ }
+ }
+
+ @Override
+ public void setExecutor(Executor executor)
+ {
+ if (executor == null)
+ throw new IllegalArgumentException("missing required 'executor' argument");
+ ThreadPool threadPool = _server.getThreadPool();
+ if (threadPool instanceof DelegatingThreadPool)
+ ((DelegatingThreadPool)_server.getThreadPool()).setExecutor(executor);
+ else
+ throw new UnsupportedOperationException("!DelegatingThreadPool");
+ }
+
+ @Override
+ public Executor getExecutor()
+ {
+ ThreadPool threadPool = _server.getThreadPool();
+ if (threadPool instanceof DelegatingThreadPool)
+ return ((DelegatingThreadPool)_server.getThreadPool()).getExecutor();
+ return threadPool;
+ }
+
+ @Override
+ public void stop(int delay)
+ {
+ cleanUpContexts();
+ cleanUpConnectors();
+
+ if (_serverShared) return;
+
+ try
+ {
+ _server.stop();
+ }
+ catch (Exception ex)
+ {
+ throw new RuntimeException(ex);
+ }
+ }
+
+ private void cleanUpContexts()
+ {
+ for (Map.Entry<String, JettyHttpContext> stringJettyHttpContextEntry : _contexts.entrySet())
+ {
+ JettyHttpContext context = stringJettyHttpContextEntry.getValue();
+ _server.removeBean(context.getJettyContextHandler());
+ }
+ _contexts.clear();
+ }
+
+ private void cleanUpConnectors()
+ {
+ for (Map.Entry<String, Connector> stringConnectorEntry : _connectors.entrySet())
+ {
+ Connector connector = stringConnectorEntry.getValue();
+ try
+ {
+ connector.stop();
+ } catch (Exception ex) {
+ LOG.warn(ex);
+ }
+ _server.removeConnector(connector);
+ }
+ _connectors.clear();
+ }
+
+ @Override
+ public HttpContext createContext(String path, HttpHandler httpHandler)
+ {
+ checkIfContextIsFree(path);
+
+ JettyHttpContext context = new JettyHttpContext(this, path, httpHandler);
+ HttpSpiContextHandler jettyContextHandler = context.getJettyContextHandler();
+
+ ContextHandlerCollection chc = findContextHandlerCollection(_server.getHandlers());
+ if (chc == null)
+ throw new RuntimeException("could not find ContextHandlerCollection, you must configure one");
+
+ chc.addHandler(jettyContextHandler);
+ _contexts.put(path, context);
+
+ return context;
+ }
+
+ private ContextHandlerCollection findContextHandlerCollection(Handler[] handlers)
+ {
+ if (handlers == null)
+ return null;
+
+ for (Handler handler : handlers)
+ {
+ if (handler instanceof ContextHandlerCollection)
+ {
+ return (ContextHandlerCollection) handler;
+ }
+
+ if (handler instanceof HandlerCollection)
+ {
+ HandlerCollection hc = (HandlerCollection) handler;
+ ContextHandlerCollection chc = findContextHandlerCollection(hc.getHandlers());
+ if (chc != null)
+ return chc;
+ }
+ }
+ return null;
+ }
+
+ private void checkIfContextIsFree(String path)
+ {
+ Handler serverHandler = _server.getHandler();
+ if (serverHandler instanceof ContextHandler)
+ {
+ ContextHandler ctx = (ContextHandler) serverHandler;
+ if (ctx.getContextPath().equals(path))
+ throw new RuntimeException("another context already bound to path " + path);
+ }
+
+ Handler[] handlers = _server.getHandlers();
+ if (handlers == null) return;
+
+ for (Handler handler : handlers)
+ {
+ if (handler instanceof ContextHandler) {
+ ContextHandler ctx = (ContextHandler) handler;
+ if (ctx.getContextPath().equals(path))
+ throw new RuntimeException("another context already bound to path " + path);
+ }
+ }
+ }
+
+ @Override
+ public HttpContext createContext(String path)
+ {
+ return createContext(path, null);
+ }
+
+ @Override
+ public void removeContext(String path) throws IllegalArgumentException
+ {
+ JettyHttpContext context = _contexts.remove(path);
+ if (context == null) return;
+ _server.removeBean(context.getJettyContextHandler());
+ }
+
+ @Override
+ public void removeContext(HttpContext context)
+ {
+ removeContext(context.getPath());
+ }
+
+}
diff --git a/jetty-http-spi/src/main/java/org/eclipse/jetty/http/spi/JettyHttpServerProvider.java b/jetty-http-spi/src/main/java/org/eclipse/jetty/http/spi/JettyHttpServerProvider.java
index 39083bb207..6cff91d55e 100644
--- a/jetty-http-spi/src/main/java/org/eclipse/jetty/http/spi/JettyHttpServerProvider.java
+++ b/jetty-http-spi/src/main/java/org/eclipse/jetty/http/spi/JettyHttpServerProvider.java
@@ -43,7 +43,7 @@ public class JettyHttpServerProvider extends HttpServerProvider
public static void setServer(Server server)
{
- _server = server;
+ _server = server;
}
@Override
@@ -51,7 +51,7 @@ public class JettyHttpServerProvider extends HttpServerProvider
throws IOException
{
Server server = _server;
- boolean shared = true;
+ boolean shared = true;
if (server == null)
{
diff --git a/jetty-http/pom.xml b/jetty-http/pom.xml
index 4a06f998d5..4ebb0e5e5b 100644
--- a/jetty-http/pom.xml
+++ b/jetty-http/pom.xml
@@ -3,7 +3,7 @@
<parent>
<artifactId>jetty-project</artifactId>
<groupId>org.eclipse.jetty</groupId>
- <version>9.2.2-SNAPSHOT</version>
+ <version>9.2.3-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>jetty-http</artifactId>
diff --git a/jetty-http/src/main/java/org/eclipse/jetty/http/HttpParser.java b/jetty-http/src/main/java/org/eclipse/jetty/http/HttpParser.java
index 79f1c28d90..f54d02b973 100644
--- a/jetty-http/src/main/java/org/eclipse/jetty/http/HttpParser.java
+++ b/jetty-http/src/main/java/org/eclipse/jetty/http/HttpParser.java
@@ -35,7 +35,7 @@ import org.eclipse.jetty.util.log.Logger;
/* ------------------------------------------------------------ */
/** A Parser for HTTP 0.9, 1.0 and 1.1
* <p>
- * The is parser parses HTTP client and server messages from buffers
+ * This parser parses HTTP client and server messages from buffers
* passed in the {@link #parseNext(ByteBuffer)} method. The parsed
* elements of the HTTP message are passed as event calls to the
* {@link HttpHandler} instance the parser is constructed with.
@@ -860,7 +860,7 @@ public class HttpParser
{
throw new BadMessage(HttpStatus.BAD_REQUEST_400,"Bad IPv6 Host header");
}
- host = host.substring(1,len-1);
+ host = host.substring(0,len);
}
else if (len!=host.length())
host = host.substring(0,len);
diff --git a/jetty-http/src/main/java/org/eclipse/jetty/http/HttpURI.java b/jetty-http/src/main/java/org/eclipse/jetty/http/HttpURI.java
index afe925e1ca..ea5b4f1cf5 100644
--- a/jetty-http/src/main/java/org/eclipse/jetty/http/HttpURI.java
+++ b/jetty-http/src/main/java/org/eclipse/jetty/http/HttpURI.java
@@ -539,8 +539,6 @@ public class HttpURI
{
if (_host==_port)
return null;
- if (_raw[_host]=='[')
- return new String(_raw,_host+1,_port-_host-2,_charset);
return new String(_raw,_host,_port-_host,_charset);
}
diff --git a/jetty-http/src/test/java/org/eclipse/jetty/http/HttpFieldsTest.java b/jetty-http/src/test/java/org/eclipse/jetty/http/HttpFieldsTest.java
index f021210206..f2a814433f 100644
--- a/jetty-http/src/test/java/org/eclipse/jetty/http/HttpFieldsTest.java
+++ b/jetty-http/src/test/java/org/eclipse/jetty/http/HttpFieldsTest.java
@@ -27,10 +27,6 @@ import static org.junit.Assert.assertTrue;
import java.nio.ByteBuffer;
import java.util.Enumeration;
-import java.util.HashSet;
-import java.util.Locale;
-import java.util.Set;
-
import org.eclipse.jetty.util.BufferUtil;
import org.hamcrest.Matchers;
import org.junit.Assert;
diff --git a/jetty-http/src/test/java/org/eclipse/jetty/http/HttpParserTest.java b/jetty-http/src/test/java/org/eclipse/jetty/http/HttpParserTest.java
index 6bc6ae23e4..70b4cbb542 100644
--- a/jetty-http/src/test/java/org/eclipse/jetty/http/HttpParserTest.java
+++ b/jetty-http/src/test/java/org/eclipse/jetty/http/HttpParserTest.java
@@ -1294,7 +1294,7 @@ public class HttpParserTest
HttpParser.RequestHandler<ByteBuffer> handler = new Handler();
HttpParser parser= new HttpParser(handler);
parser.parseNext(buffer);
- assertEquals("::1",_host);
+ assertEquals("[::1]",_host);
assertEquals(0,_port);
}
@@ -1372,7 +1372,7 @@ public class HttpParserTest
HttpParser.RequestHandler<ByteBuffer> handler = new Handler();
HttpParser parser= new HttpParser(handler);
parser.parseNext(buffer);
- assertEquals("::1",_host);
+ assertEquals("[::1]",_host);
assertEquals(8888,_port);
}
diff --git a/jetty-http/src/test/java/org/eclipse/jetty/http/HttpURITest.java b/jetty-http/src/test/java/org/eclipse/jetty/http/HttpURITest.java
index e28678ea14..fd5023a56c 100644
--- a/jetty-http/src/test/java/org/eclipse/jetty/http/HttpURITest.java
+++ b/jetty-http/src/test/java/org/eclipse/jetty/http/HttpURITest.java
@@ -33,9 +33,9 @@ public class HttpURITest
{
{"/path/to/context",null,null,"-1","/path/to/context",null,null,null},
{"http://example.com/path/to/context;param?query=%22value%22#fragment","http","example.com","-1","/path/to/context","param","query=%22value%22","fragment"},
- {"http://[::1]/path/to/context;param?query=%22value%22#fragment","http","::1","-1","/path/to/context","param","query=%22value%22","fragment"},
+ {"http://[::1]/path/to/context;param?query=%22value%22#fragment","http","[::1]","-1","/path/to/context","param","query=%22value%22","fragment"},
{"http://example.com:8080/path/to/context;param?query=%22value%22#fragment","http","example.com","8080","/path/to/context","param","query=%22value%22","fragment"},
- {"http://[::1]:8080/path/to/context;param?query=%22value%22#fragment","http","::1","8080","/path/to/context","param","query=%22value%22","fragment"},
+ {"http://[::1]:8080/path/to/context;param?query=%22value%22#fragment","http","[::1]","8080","/path/to/context","param","query=%22value%22","fragment"},
};
public static int
diff --git a/jetty-io/pom.xml b/jetty-io/pom.xml
index 41d2403214..d879de68d9 100644
--- a/jetty-io/pom.xml
+++ b/jetty-io/pom.xml
@@ -2,7 +2,7 @@
<parent>
<artifactId>jetty-project</artifactId>
<groupId>org.eclipse.jetty</groupId>
- <version>9.2.2-SNAPSHOT</version>
+ <version>9.2.3-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>jetty-io</artifactId>
diff --git a/jetty-io/src/main/java/org/eclipse/jetty/io/Connection.java b/jetty-io/src/main/java/org/eclipse/jetty/io/Connection.java
index 96baa01676..7bd08ad66f 100644
--- a/jetty-io/src/main/java/org/eclipse/jetty/io/Connection.java
+++ b/jetty-io/src/main/java/org/eclipse/jetty/io/Connection.java
@@ -20,8 +20,6 @@ package org.eclipse.jetty.io;
import java.io.Closeable;
-import org.eclipse.jetty.util.Callback;
-
/**
* <p>A {@link Connection} is associated to an {@link EndPoint} so that I/O events
* happening on the {@link EndPoint} can be processed by the {@link Connection}.</p>
diff --git a/jetty-io/src/main/java/org/eclipse/jetty/io/EndPoint.java b/jetty-io/src/main/java/org/eclipse/jetty/io/EndPoint.java
index 87adb40be1..4aa404fe3b 100644
--- a/jetty-io/src/main/java/org/eclipse/jetty/io/EndPoint.java
+++ b/jetty-io/src/main/java/org/eclipse/jetty/io/EndPoint.java
@@ -26,8 +26,6 @@ import java.nio.channels.ReadPendingException;
import java.nio.channels.WritePendingException;
import org.eclipse.jetty.util.Callback;
-import org.eclipse.jetty.util.FutureCallback;
-
/**
*
diff --git a/jetty-io/src/main/java/org/eclipse/jetty/io/NetworkTrafficSelectChannelEndPoint.java b/jetty-io/src/main/java/org/eclipse/jetty/io/NetworkTrafficSelectChannelEndPoint.java
index a4b6f7d2a1..25093f02bc 100644
--- a/jetty-io/src/main/java/org/eclipse/jetty/io/NetworkTrafficSelectChannelEndPoint.java
+++ b/jetty-io/src/main/java/org/eclipse/jetty/io/NetworkTrafficSelectChannelEndPoint.java
@@ -25,7 +25,6 @@ import java.nio.channels.SelectionKey;
import java.nio.channels.SocketChannel;
import java.util.List;
-import org.eclipse.jetty.util.BufferUtil;
import org.eclipse.jetty.util.log.Log;
import org.eclipse.jetty.util.log.Logger;
import org.eclipse.jetty.util.thread.Scheduler;
diff --git a/jetty-io/src/main/java/org/eclipse/jetty/io/SelectorManager.java b/jetty-io/src/main/java/org/eclipse/jetty/io/SelectorManager.java
index 66da637c77..0e6fd889da 100644
--- a/jetty-io/src/main/java/org/eclipse/jetty/io/SelectorManager.java
+++ b/jetty-io/src/main/java/org/eclipse/jetty/io/SelectorManager.java
@@ -21,8 +21,6 @@ package org.eclipse.jetty.io;
import java.io.Closeable;
import java.io.IOException;
import java.net.ConnectException;
-import java.net.Socket;
-import java.net.SocketAddress;
import java.net.SocketTimeoutException;
import java.nio.channels.CancelledKeyException;
import java.nio.channels.SelectionKey;
@@ -488,7 +486,8 @@ public abstract class SelectorManager extends AbstractLifeCycle implements Dumpa
LOG.debug("Starting {} on {}", _thread, this);
while (isRunning())
select();
- runChanges();
+ while(isStopping())
+ runChanges();
}
finally
{
diff --git a/jetty-io/src/main/java/org/eclipse/jetty/io/ssl/SslConnection.java b/jetty-io/src/main/java/org/eclipse/jetty/io/ssl/SslConnection.java
index ee9e449b15..95b9c8bcd1 100644
--- a/jetty-io/src/main/java/org/eclipse/jetty/io/ssl/SslConnection.java
+++ b/jetty-io/src/main/java/org/eclipse/jetty/io/ssl/SslConnection.java
@@ -38,7 +38,6 @@ import org.eclipse.jetty.io.EndPoint;
import org.eclipse.jetty.io.EofException;
import org.eclipse.jetty.io.FillInterest;
import org.eclipse.jetty.io.RuntimeIOException;
-import org.eclipse.jetty.io.SelectChannelEndPoint;
import org.eclipse.jetty.io.WriteFlusher;
import org.eclipse.jetty.util.BufferUtil;
import org.eclipse.jetty.util.Callback;
@@ -820,7 +819,6 @@ public class SslConnection extends AbstractConnection
}
catch (Exception e)
{
- getEndPoint().close();
throw e;
}
finally
diff --git a/jetty-jaas/pom.xml b/jetty-jaas/pom.xml
index af72ff887d..992ea1a74f 100644
--- a/jetty-jaas/pom.xml
+++ b/jetty-jaas/pom.xml
@@ -2,7 +2,7 @@
<parent>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-project</artifactId>
- <version>9.2.2-SNAPSHOT</version>
+ <version>9.2.3-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>jetty-jaas</artifactId>
diff --git a/jetty-jaas/src/main/java/org/eclipse/jetty/jaas/JAASLoginService.java b/jetty-jaas/src/main/java/org/eclipse/jetty/jaas/JAASLoginService.java
index a46ff32034..d850e65ad4 100644
--- a/jetty-jaas/src/main/java/org/eclipse/jetty/jaas/JAASLoginService.java
+++ b/jetty-jaas/src/main/java/org/eclipse/jetty/jaas/JAASLoginService.java
@@ -210,7 +210,7 @@ public class JAASLoginService extends AbstractLifeCycle implements LoginService
}
else if (callback instanceof RequestParameterCallback)
{
- HttpChannel channel = HttpChannel.getCurrentHttpChannel();
+ HttpChannel channel = HttpChannel.getCurrentHttpChannel();
if (channel == null)
return;
diff --git a/jetty-jaspi/pom.xml b/jetty-jaspi/pom.xml
index 52e262b25c..0eeeb7f5dd 100644
--- a/jetty-jaspi/pom.xml
+++ b/jetty-jaspi/pom.xml
@@ -2,7 +2,7 @@
<parent>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-project</artifactId>
- <version>9.2.2-SNAPSHOT</version>
+ <version>9.2.3-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>jetty-jaspi</artifactId>
diff --git a/jetty-jaspi/src/main/java/org/eclipse/jetty/security/jaspi/modules/FormAuthModule.java b/jetty-jaspi/src/main/java/org/eclipse/jetty/security/jaspi/modules/FormAuthModule.java
index fbe2b62b95..9215eddaf0 100644
--- a/jetty-jaspi/src/main/java/org/eclipse/jetty/security/jaspi/modules/FormAuthModule.java
+++ b/jetty-jaspi/src/main/java/org/eclipse/jetty/security/jaspi/modules/FormAuthModule.java
@@ -92,6 +92,9 @@ public class FormAuthModule extends BaseAuthModule
setErrorPage(errorPage);
}
+ /**
+ * @deprecated
+ */
public FormAuthModule(CallbackHandler callbackHandler, CrossContextPsuedoSession<UserInfo> ssoSource,
String loginPage, String errorPage)
{
diff --git a/jetty-jmx/pom.xml b/jetty-jmx/pom.xml
index cd5e3f8c2f..bfe00ae8ed 100644
--- a/jetty-jmx/pom.xml
+++ b/jetty-jmx/pom.xml
@@ -2,7 +2,7 @@
<parent>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-project</artifactId>
- <version>9.2.2-SNAPSHOT</version>
+ <version>9.2.3-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>jetty-jmx</artifactId>
diff --git a/jetty-jmx/src/main/java/org/eclipse/jetty/jmx/ConnectorServer.java b/jetty-jmx/src/main/java/org/eclipse/jetty/jmx/ConnectorServer.java
index 4062400185..343de02d9b 100644
--- a/jetty-jmx/src/main/java/org/eclipse/jetty/jmx/ConnectorServer.java
+++ b/jetty-jmx/src/main/java/org/eclipse/jetty/jmx/ConnectorServer.java
@@ -82,23 +82,23 @@ public class ConnectorServer extends AbstractLifeCycle
public ConnectorServer(JMXServiceURL svcUrl, Map<String,?> environment, String name)
throws Exception
{
- String urlPath = svcUrl.getURLPath();
- int idx = urlPath.indexOf("rmi://");
- if (idx > 0)
- {
- String hostPort = urlPath.substring(idx+6, urlPath.indexOf('/', idx+6));
- String regHostPort = startRegistry(hostPort);
- if (regHostPort != null) {
- urlPath = urlPath.replace(hostPort,regHostPort);
- svcUrl = new JMXServiceURL(svcUrl.getProtocol(), svcUrl.getHost(), svcUrl.getPort(), urlPath);
- }
- }
+ String urlPath = svcUrl.getURLPath();
+ int idx = urlPath.indexOf("rmi://");
+ if (idx > 0)
+ {
+ String hostPort = urlPath.substring(idx+6, urlPath.indexOf('/', idx+6));
+ String regHostPort = startRegistry(hostPort);
+ if (regHostPort != null) {
+ urlPath = urlPath.replace(hostPort,regHostPort);
+ svcUrl = new JMXServiceURL(svcUrl.getProtocol(), svcUrl.getHost(), svcUrl.getPort(), urlPath);
+ }
+ }
MBeanServer mbeanServer = ManagementFactory.getPlatformMBeanServer();
_connectorServer = JMXConnectorServerFactory.newJMXConnectorServer(svcUrl, environment, mbeanServer);
mbeanServer.registerMBean(_connectorServer,new ObjectName(name));
}
- /* ------------------------------------------------------------ */
+ /* ------------------------------------------------------------ */
/**
* @see org.eclipse.jetty.util.component.AbstractLifeCycle#doStart()
*/
diff --git a/jetty-jndi/pom.xml b/jetty-jndi/pom.xml
index 0a7a244f01..4729221221 100644
--- a/jetty-jndi/pom.xml
+++ b/jetty-jndi/pom.xml
@@ -2,7 +2,7 @@
<parent>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-project</artifactId>
- <version>9.2.2-SNAPSHOT</version>
+ <version>9.2.3-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>jetty-jndi</artifactId>
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 acdf3149e9..6df677e0ae 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
@@ -24,7 +24,6 @@ import java.sql.Statement;
import javax.sql.DataSource;
-import org.eclipse.jetty.util.component.ContainerLifeCycle;
import org.eclipse.jetty.util.component.Destroyable;
import org.eclipse.jetty.util.log.Log;
import org.eclipse.jetty.util.log.Logger;
diff --git a/jetty-jsp/pom.xml b/jetty-jsp/pom.xml
index 7c6dac5007..7ff01b1eb0 100644
--- a/jetty-jsp/pom.xml
+++ b/jetty-jsp/pom.xml
@@ -2,7 +2,7 @@
<parent>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-project</artifactId>
- <version>9.2.2-SNAPSHOT</version>
+ <version>9.2.3-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>jetty-jsp</artifactId>
diff --git a/jetty-jspc-maven-plugin/pom.xml b/jetty-jspc-maven-plugin/pom.xml
index 41838212d3..2fc3528a09 100644
--- a/jetty-jspc-maven-plugin/pom.xml
+++ b/jetty-jspc-maven-plugin/pom.xml
@@ -2,7 +2,7 @@
<parent>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-project</artifactId>
- <version>9.2.2-SNAPSHOT</version>
+ <version>9.2.3-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>jetty-jspc-maven-plugin</artifactId>
diff --git a/jetty-jspc-maven-plugin/src/main/java/org/eclipse/jetty/jspc/plugin/JspcMojo.java b/jetty-jspc-maven-plugin/src/main/java/org/eclipse/jetty/jspc/plugin/JspcMojo.java
index ac3e45f3f5..3e524b05be 100644
--- a/jetty-jspc-maven-plugin/src/main/java/org/eclipse/jetty/jspc/plugin/JspcMojo.java
+++ b/jetty-jspc-maven-plugin/src/main/java/org/eclipse/jetty/jspc/plugin/JspcMojo.java
@@ -83,6 +83,21 @@ public class JspcMojo extends AbstractMojo
/**
+ * JettyJspC
+ *
+ * Add some extra setters to standard JspC class to help configure it
+ * for running in maven.
+ */
+ public static class JettyJspC extends JspC
+ {
+ public void setClassLoader (ClassLoader loader)
+ {
+ this.loader = loader;
+ }
+ }
+
+
+ /**
* Whether or not to include dependencies on the plugin's classpath with &lt;scope&gt;provided&lt;/scope&gt;
* Use WITH CAUTION as you may wind up with duplicate jars/classes.
*
@@ -219,7 +234,7 @@ public class JspcMojo extends AbstractMojo
*
* @parameter
*/
- private JspC jspc;
+ private JettyJspC jspc;
@@ -286,19 +301,22 @@ public class JspcMojo extends AbstractMojo
if (i+1<webAppUrls.size())
webAppClassPath.append(System.getProperty("path.separator"));
}
-
- Thread.currentThread().setContextClassLoader(webAppClassLoader);
+
+ //Interpose a fake classloader as the webapp class loader. This is because the Apache JspC class
+ //uses a TldScanner which ignores jars outside of the WEB-INF/lib path on the webapp classloader.
+ //It will, however, look at all jars on the parents of the webapp classloader.
+ URLClassLoader fakeWebAppClassLoader = new URLClassLoader(new URL[0], webAppClassLoader);
+ Thread.currentThread().setContextClassLoader(fakeWebAppClassLoader);
if (jspc == null)
- jspc = new JspC();
+ jspc = new JettyJspC();
jspc.setWebXmlFragment(webXmlFragment);
jspc.setUriroot(webAppSourceDirectory);
jspc.setOutputDir(generatedClasses);
jspc.setClassPath(sysClassPath+System.getProperty("path.separator")+webAppClassPath.toString());
+ jspc.setClassLoader(fakeWebAppClassLoader);
jspc.setCompile(true);
- //jspc.setSystemClassPath(sysClassPath);
-
// JspC#setExtensions() does not exist, so
// always set concrete list of files that will be processed.
diff --git a/jetty-maven-plugin/pom.xml b/jetty-maven-plugin/pom.xml
index 462627c328..6fe9531ce7 100644
--- a/jetty-maven-plugin/pom.xml
+++ b/jetty-maven-plugin/pom.xml
@@ -2,7 +2,7 @@
<parent>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-project</artifactId>
- <version>9.2.2-SNAPSHOT</version>
+ <version>9.2.3-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>jetty-maven-plugin</artifactId>
@@ -82,6 +82,11 @@
</dependency>
<dependency>
<groupId>org.eclipse.jetty</groupId>
+ <artifactId>jetty-quickstart</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-jaas</artifactId>
<version>${project.version}</version>
</dependency>
diff --git a/jetty-maven-plugin/src/main/java/org/eclipse/jetty/maven/plugin/AbstractJettyMojo.java b/jetty-maven-plugin/src/main/java/org/eclipse/jetty/maven/plugin/AbstractJettyMojo.java
index e9e979f50a..5b95c26962 100644
--- a/jetty-maven-plugin/src/main/java/org/eclipse/jetty/maven/plugin/AbstractJettyMojo.java
+++ b/jetty-maven-plugin/src/main/java/org/eclipse/jetty/maven/plugin/AbstractJettyMojo.java
@@ -27,7 +27,6 @@ import java.net.URL;
import java.net.URLClassLoader;
import java.util.ArrayList;
import java.util.Arrays;
-import java.util.Collections;
import java.util.Enumeration;
import java.util.Iterator;
import java.util.List;
@@ -684,7 +683,7 @@ public abstract class AbstractJettyMojo extends AbstractMojo
/**
*
*/
- private void printSystemProperties ()
+ protected void printSystemProperties ()
{
// print out which system properties were set up
if (getLog().isDebugEnabled())
diff --git a/jetty-maven-plugin/src/main/java/org/eclipse/jetty/maven/plugin/JettyEffectiveWebXml.java b/jetty-maven-plugin/src/main/java/org/eclipse/jetty/maven/plugin/JettyEffectiveWebXml.java
new file mode 100644
index 0000000000..6c607c85df
--- /dev/null
+++ b/jetty-maven-plugin/src/main/java/org/eclipse/jetty/maven/plugin/JettyEffectiveWebXml.java
@@ -0,0 +1,157 @@
+//
+// ========================================================================
+// Copyright (c) 1995-2014 Mort Bay Consulting Pty. Ltd.
+// ------------------------------------------------------------------------
+// All rights reserved. This program and the accompanying materials
+// are made available under the terms of the Eclipse Public License v1.0
+// and Apache License v2.0 which accompanies this distribution.
+//
+// The Eclipse Public License is available at
+// http://www.eclipse.org/legal/epl-v10.html
+//
+// The Apache License v2.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.maven.plugin;
+
+import java.io.File;
+import java.io.IOException;
+
+import org.apache.maven.plugin.MojoExecutionException;
+import org.apache.maven.plugin.MojoFailureException;
+import org.eclipse.jetty.annotations.AnnotationConfiguration;
+import org.eclipse.jetty.util.IO;
+import org.eclipse.jetty.util.resource.Resource;
+import org.eclipse.jetty.util.thread.QueuedThreadPool;
+
+/**
+ * JettyEffectiveWebXml
+ *
+ * @goal effective-web-xml
+ * @requiresDependencyResolution test
+ * @execute phase="test-compile"
+ * @description Runs jetty on the unassembled webapp to generate the effective web.xml
+ */
+public class JettyEffectiveWebXml extends JettyRunMojo
+{
+ /**
+ * The target directory
+ *
+ * @parameter expression="${project.build.directory}"
+ * @required
+ * @readonly
+ */
+ protected File target;
+
+ /**
+ * The target directory
+ *
+ * @parameter
+ */
+ protected File effectiveWebXml;
+
+
+ protected boolean deleteOnExit = true;
+
+
+ /**
+ * @see org.apache.maven.plugin.Mojo#execute()
+ */
+ public void execute() throws MojoExecutionException, MojoFailureException
+ {
+ super.execute();
+ }
+
+
+ @Override
+ public void startJetty() throws MojoExecutionException
+ {
+ //Only do enough setup to be able to produce a quickstart-web.xml file to
+ //pass onto the forked process to run
+
+ //if the user didn't nominate a file to generate into, pick the name and
+ //make sure that it is deleted on exit
+ if (effectiveWebXml == null)
+ {
+ deleteOnExit = true;
+ effectiveWebXml = new File(target, "effective-web.xml");
+ effectiveWebXml.deleteOnExit();
+ }
+
+ Resource descriptor = Resource.newResource(effectiveWebXml);
+
+ QueuedThreadPool tpool = null;
+
+ try
+ {
+ printSystemProperties();
+
+ //apply any config from a jetty.xml file first to our "fake" server instance
+ //TODO probably not necessary
+ applyJettyXml ();
+
+
+ server.configureHandlers();
+
+ //ensure config of the webapp based on settings in plugin
+ configureWebApplication();
+
+
+ //set the webapp up to do very little other than generate the quickstart-web.xml
+ webApp.setCopyWebDir(false);
+ webApp.setCopyWebInf(false);
+ webApp.setGenerateQuickStart(true);
+
+ if (!effectiveWebXml.getParentFile().exists())
+ effectiveWebXml.getParentFile().mkdirs();
+ if (!effectiveWebXml.exists())
+ effectiveWebXml.createNewFile();
+
+ webApp.setQuickStartWebDescriptor(descriptor);
+
+ server.addWebApplication(webApp);
+
+ //if our server has a thread pool associated we can do any annotation scanning multithreaded,
+ //otherwise scanning will be single threaded
+ tpool = server.getBean(QueuedThreadPool.class);
+ if (tpool != null)
+ tpool.start();
+ else
+ webApp.setAttribute(AnnotationConfiguration.MULTI_THREADED, Boolean.FALSE.toString());
+
+ webApp.start(); //just enough to generate the quickstart
+
+ }
+ catch (Exception e)
+ {
+ throw new MojoExecutionException("Effective web.xml generation failed", e);
+ }
+ finally
+ {
+ try {webApp.stop();}catch (Exception x) {};
+
+ try {if (tpool != null) tpool.stop();} catch (Exception x) {};
+ }
+
+
+ if (deleteOnExit)
+ {
+ try
+ {
+ //just show the result in the log
+ getLog().info(IO.toString(descriptor.getInputStream()));
+ }
+ catch (IOException e)
+ {
+ throw new MojoExecutionException("Unable to output effective web.xml", e);
+ }
+
+ }
+
+ }
+}
diff --git a/jetty-maven-plugin/src/main/java/org/eclipse/jetty/maven/plugin/JettyRunForkedMojo.java b/jetty-maven-plugin/src/main/java/org/eclipse/jetty/maven/plugin/JettyRunForkedMojo.java
index efb1284c01..97b7219ca0 100644
--- a/jetty-maven-plugin/src/main/java/org/eclipse/jetty/maven/plugin/JettyRunForkedMojo.java
+++ b/jetty-maven-plugin/src/main/java/org/eclipse/jetty/maven/plugin/JettyRunForkedMojo.java
@@ -39,34 +39,36 @@ import java.util.Random;
import java.util.Set;
import org.apache.maven.artifact.Artifact;
-import org.apache.maven.plugin.AbstractMojo;
import org.apache.maven.plugin.MojoExecutionException;
import org.apache.maven.plugin.MojoFailureException;
import org.apache.maven.plugin.descriptor.PluginDescriptor;
-import org.apache.maven.project.MavenProject;
+import org.eclipse.jetty.annotations.AnnotationConfiguration;
+import org.eclipse.jetty.quickstart.QuickStartDescriptorGenerator;
import org.eclipse.jetty.util.IO;
import org.eclipse.jetty.util.resource.Resource;
import org.eclipse.jetty.util.resource.ResourceCollection;
+import org.eclipse.jetty.util.thread.QueuedThreadPool;
/**
* <p>
- * This goal is used to assemble your webapp into a war and automatically deploy it to Jetty in a forked JVM.
+ * This goal is used to deploy your unassembled webapp into a forked JVM.
* </p>
* <p>
- * You need to define a jetty.xml file to configure connectors etc and a context xml file that sets up anything special
- * about your webapp. This plugin will fill in the:
- * <ul>
- * <li>context path
- * <li>classes
- * <li>web.xml
- * <li>root of the webapp
- * </ul>
- * Based on a combination of information that you supply and the location of files in your unassembled webapp.
+ * You need to define a jetty.xml file to configure connectors etc. You can use the normal setters of o.e.j.webapp.WebAppContext on the <b>webApp</b>
+ * configuration element for this plugin. You may also need context xml file for any particularly complex webapp setup.
+ * about your webapp.
* </p>
* <p>
- * There is a <a href="run-war-mojo.html">reference guide</a> to the configuration parameters for this plugin, and more detailed information
- * with examples in the <a href="http://docs.codehaus.org/display/JETTY/Maven+Jetty+Plugin/">Configuration Guide</a>.
+ * Unlike the other jetty goals, this does NOT support the <b>scanIntervalSeconds</b> parameter: the webapp will be deployed only once.
+ * </p>
+ * <p>
+ * The <b>stopKey</b>, <b>stopPort</b> configuration elements can be used to control the stopping of the forked process. By default, this plugin will launch
+ * the forked jetty instance and wait for it to complete (in which case it acts much like the <b>jetty:run</b> goal, and you will need to Cntrl-C to stop).
+ * By setting the configuration element <b>waitForChild</b> to <b>false</b>, the plugin will terminate after having forked the jetty process. In this case
+ * you can use the <b>jetty:stop</b> goal to terminate the process.
+ * <p>
+ * See <a href="http://www.eclipse.org/jetty/documentation/">http://www.eclipse.org/jetty/documentation</a> for more information on this and other jetty plugins.
* </p>
*
* @goal run-forked
@@ -75,50 +77,18 @@ import org.eclipse.jetty.util.resource.ResourceCollection;
* @description Runs Jetty in forked JVM on an unassembled webapp
*
*/
-public class JettyRunForkedMojo extends AbstractMojo
+public class JettyRunForkedMojo extends JettyRunMojo
{
public static final String DEFAULT_WEBAPP_SRC = "src"+File.separator+"main"+File.separator+"webapp";
public static final String FAKE_WEBAPP = "webapp-tmp";
public String PORT_SYSPROPERTY = "jetty.port";
-
- /**
- * Whether or not to include dependencies on the plugin's classpath with &lt;scope&gt;provided&lt;/scope&gt;
- * Use WITH CAUTION as you may wind up with duplicate jars/classes.
- * @parameter default-value="false"
- */
- protected boolean useProvidedScope;
-
-
- /**
- * The maven project.
- *
- * @parameter expression="${project}"
- * @required
- * @readonly
- */
- private MavenProject project;
- /**
- * If true, the &lt;testOutputDirectory&gt;
- * and the dependencies of &lt;scope&gt;test&lt;scope&gt;
- * will be put first on the runtime classpath.
- * @parameter alias="useTestClasspath" default-value="false"
- */
- private boolean useTestScope;
+
- /**
- * The default location of the web.xml file. Will be used
- * if &lt;webAppConfig&gt;&lt;descriptor&gt; is not set.
- *
- * @parameter expression="${basedir}/src/main/webapp/WEB-INF/web.xml"
- * @readonly
- */
- private String webXml;
-
/**
* The target directory
@@ -129,120 +99,15 @@ public class JettyRunForkedMojo extends AbstractMojo
*/
protected File target;
-
/**
- * The temporary directory to use for the webapp.
- * Defaults to target/tmp
- *
- * @parameter alias="tmpDirectory" expression="${project.build.directory}/tmp"
- * @required
- * @readonly
- */
- protected File tempDirectory;
-
-
-
- /**
- * Whether temporary directory contents should survive webapp restarts.
+ * The file into which to generate the quickstart web xml for the forked process to use
*
- * @parameter default-value="false"
+ * @parameter expression="${project.build.directory}/fork-web.xml"
*/
- private boolean persistTempDirectory;
-
-
- /**
- * The directory containing generated classes.
- *
- * @parameter expression="${project.build.outputDirectory}"
- * @required
- *
- */
- private File classesDirectory;
+ protected File forkWebXml;
/**
- * The directory containing generated test classes.
- *
- * @parameter expression="${project.build.testOutputDirectory}"
- * @required
- */
- private File testClassesDirectory;
-
-
- /**
- * Root directory for all html/jsp etc files
- *
- * @parameter expression="${basedir}/src/main/webapp"
- *
- */
- private File webAppSourceDirectory;
-
- /**
- * Resource Bases
- *
- * @parameter
- *
- */
- private String[] resourceBases;
-
- /**
- * If true, the webAppSourceDirectory will be first on the list of
- * resources that form the resource base for the webapp. If false,
- * it will be last.
- *
- * @parameter default-value="true"
- */
- private boolean baseAppFirst;
-
-
- /**
- * Location of jetty xml configuration files whose contents
- * will be applied before any plugin configuration. Optional.
- * @parameter
- */
- private String jettyXml;
-
- /**
- * The context path for the webapp. Defaults to / for jetty-9
- *
- * @parameter expression="/"
- */
- private String contextPath;
-
-
- /**
- * Location of a context xml configuration file whose contents
- * will be applied to the webapp AFTER anything in &lt;webAppConfig&gt;.Optional.
- * @parameter
- */
- private String contextXml;
-
-
- /**
- * @parameter expression="${jetty.skip}" default-value="false"
- */
- private boolean skip;
-
-
- /**
- * Port to listen to stop jetty on executing -DSTOP.PORT=&lt;stopPort&gt;
- * -DSTOP.KEY=&lt;stopKey&gt; -jar start.jar --stop
- * @parameter
- * @required
- */
- protected int stopPort;
-
-
- /**
- * Key to provide when stopping jetty on executing java -DSTOP.KEY=&lt;stopKey&gt;
- * -DSTOP.PORT=&lt;stopPort&gt; -jar start.jar --stop
- * @parameter
- * @required
- */
- protected String stopKey;
-
-
- /**
* Arbitrary jvm args to pass to the forked process
* @parameter
*/
@@ -284,9 +149,9 @@ public class JettyRunForkedMojo extends AbstractMojo
*/
private Random random;
+
-
-
+ private Resource originalBaseResource;
/**
@@ -360,21 +225,192 @@ public class JettyRunForkedMojo extends AbstractMojo
*/
public void execute() throws MojoExecutionException, MojoFailureException
{
- getLog().info("Configuring Jetty for project: " + project.getName());
- if (skip)
- {
- getLog().info("Skipping Jetty start: jetty.skip==true");
- return;
- }
- PluginLog.setLog(getLog());
Runtime.getRuntime().addShutdownHook(new ShutdownThread());
random = new Random();
- startJettyRunner();
+ super.execute();
}
-
-
+
+
+ @Override
+ public void startJetty() throws MojoExecutionException
+ {
+ //Only do enough setup to be able to produce a quickstart-web.xml file to
+ //pass onto the forked process to run
+
+ if (forkWebXml == null)
+ forkWebXml = new File (target, "fork-web.xml");
+
+ try
+ {
+ printSystemProperties();
+
+ //do NOT apply the jettyXml configuration - as the jvmArgs may be needed for it to work
+
+ //ensure handler structure enabled
+ server.configureHandlers();
+
+ //ensure config of the webapp based on settings in plugin
+ configureWebApplication();
+
+ //copy the base resource as configured by the plugin
+ originalBaseResource = webApp.getBaseResource();
+
+ //set the webapp up to do very little other than generate the quickstart-web.xml
+ webApp.setCopyWebDir(false);
+ webApp.setCopyWebInf(false);
+ webApp.setGenerateQuickStart(true);
+
+ if (!forkWebXml.getParentFile().exists())
+ forkWebXml.getParentFile().mkdirs();
+ if (!forkWebXml.exists())
+ forkWebXml.createNewFile();
+
+ webApp.setQuickStartWebDescriptor(Resource.newResource(forkWebXml));
+
+ //add webapp to our fake server instance
+ server.addWebApplication(webApp);
+
+ //if our server has a thread pool associated we can do annotation scanning multithreaded,
+ //otherwise scanning will be single threaded
+ QueuedThreadPool tpool = server.getBean(QueuedThreadPool.class);
+ if (tpool != null)
+ tpool.start();
+ else
+ webApp.setAttribute(AnnotationConfiguration.MULTI_THREADED, Boolean.FALSE.toString());
+
+ webApp.start(); //just enough to generate the quickstart
+
+ //save config of the webapp BEFORE we stop
+ File props = prepareConfiguration();
+
+ webApp.stop();
+
+ if (tpool != null)
+ tpool.stop();
+
+ List<String> cmd = new ArrayList<String>();
+ cmd.add(getJavaBin());
+
+ if (jvmArgs != null)
+ {
+ String[] args = jvmArgs.split(" ");
+ for (int i=0;args != null && i<args.length;i++)
+ {
+ if (args[i] !=null && !"".equals(args[i]))
+ cmd.add(args[i].trim());
+ }
+ }
+
+ String classPath = getContainerClassPath();
+ if (classPath != null && classPath.length() > 0)
+ {
+ cmd.add("-cp");
+ cmd.add(classPath);
+ }
+ cmd.add(Starter.class.getCanonicalName());
+
+ if (stopPort > 0 && stopKey != null)
+ {
+ cmd.add("--stop-port");
+ cmd.add(Integer.toString(stopPort));
+ cmd.add("--stop-key");
+ cmd.add(stopKey);
+ }
+ if (jettyXml != null)
+ {
+ cmd.add("--jetty-xml");
+ cmd.add(jettyXml);
+ }
+
+ if (contextXml != null)
+ {
+ cmd.add("--context-xml");
+ cmd.add(contextXml);
+ }
+
+ cmd.add("--props");
+ cmd.add(props.getAbsolutePath());
+
+ String token = createToken();
+ cmd.add("--token");
+ cmd.add(token);
+
+ ProcessBuilder builder = new ProcessBuilder(cmd);
+ builder.directory(project.getBasedir());
+
+ if (PluginLog.getLog().isDebugEnabled())
+ PluginLog.getLog().debug(Arrays.toString(cmd.toArray()));
+
+ PluginLog.getLog().info("Forked process starting");
+
+ if (waitForChild)
+ {
+ forkedProcess = builder.start();
+ startPump("STDOUT",forkedProcess.getInputStream());
+ startPump("STDERR",forkedProcess.getErrorStream());
+ int exitcode = forkedProcess.waitFor();
+ PluginLog.getLog().info("Forked execution exit: "+exitcode);
+ }
+ else
+ { //merge stderr and stdout from child
+ builder.redirectErrorStream(true);
+ forkedProcess = builder.start();
+
+ //wait for the child to be ready before terminating.
+ //child indicates it has finished starting by printing on stdout the token passed to it
+ try
+ {
+ String line = "";
+ try (InputStream is = forkedProcess.getInputStream();
+ LineNumberReader reader = new LineNumberReader(new InputStreamReader(is)))
+ {
+ int attempts = maxStartupLines; //max lines we'll read trying to get token
+ while (attempts>0 && line != null)
+ {
+ --attempts;
+ line = reader.readLine();
+ if (line != null && line.startsWith(token))
+ break;
+ }
+
+ }
+
+ if (line != null && line.trim().equals(token))
+ PluginLog.getLog().info("Forked process started.");
+ else
+ {
+ String err = (line == null?"":(line.startsWith(token)?line.substring(token.length()):line));
+ PluginLog.getLog().info("Forked process startup errors"+(!"".equals(err)?", received: "+err:""));
+ }
+ }
+ catch (Exception e)
+ {
+ throw new MojoExecutionException ("Problem determining if forked process is ready: "+e.getMessage());
+ }
+
+ }
+ }
+ catch (InterruptedException ex)
+ {
+ if (forkedProcess != null && waitForChild)
+ forkedProcess.destroy();
+
+ throw new MojoExecutionException("Failed to start Jetty within time limit");
+ }
+ catch (Exception ex)
+ {
+ if (forkedProcess != null && waitForChild)
+ forkedProcess.destroy();
+
+ throw new MojoExecutionException("Failed to create Jetty process", ex);
+ }
+ }
+
+
+
+
/**
* @return
* @throws MojoExecutionException
@@ -428,76 +464,63 @@ public class JettyRunForkedMojo extends AbstractMojo
//web.xml
- if (webXml != null)
- props.put("web.xml", webXml);
+ if (webApp.getDescriptor() != null)
+ {
+ props.put("web.xml", webApp.getDescriptor());
+ }
+
+ if (webApp.getQuickStartWebDescriptor() != null)
+ {
+ props.put("quickstart.web.xml", webApp.getQuickStartWebDescriptor().getFile().getAbsolutePath());
+ }
//sort out the context path
- if (contextPath != null)
- props.put("context.path", contextPath);
-
- //sort out the tmp directory (make it if it doesn't exist)
- if (tempDirectory != null)
+ if (webApp.getContextPath() != null)
{
- if (!tempDirectory.exists())
- tempDirectory.mkdirs();
- props.put("tmp.dir", tempDirectory.getAbsolutePath());
+ props.put("context.path", webApp.getContextPath());
}
-
- props.put("tmp.dir.persist", Boolean.toString(persistTempDirectory));
- if (resourceBases == null)
+ //tmp dir
+ props.put("tmp.dir", webApp.getTempDirectory().getAbsolutePath());
+ props.put("tmp.dir.persist", Boolean.toString(webApp.isPersistTempDirectory()));
+
+ //resource bases - these are what has been configured BEFORE the webapp started and
+ //potentially reordered them and included any resources from META-INF
+ if (originalBaseResource != null)
{
- //sort out base dir of webapp
- if (webAppSourceDirectory == null || !webAppSourceDirectory.exists())
+ StringBuffer rb = new StringBuffer();
+ if (originalBaseResource instanceof ResourceCollection)
{
- webAppSourceDirectory = new File (project.getBasedir(), DEFAULT_WEBAPP_SRC);
- if (!webAppSourceDirectory.exists())
+ ResourceCollection resources = ((ResourceCollection)originalBaseResource);
+ for (Resource r:resources.getResources())
{
- //try last resort of making a fake empty dir
- File target = new File(project.getBuild().getDirectory());
- webAppSourceDirectory = new File(target, FAKE_WEBAPP);
- if (!webAppSourceDirectory.exists())
- webAppSourceDirectory.mkdirs();
- }
+ if (rb.length() > 0) rb.append(",");
+ rb.append(r.toString());
+ }
}
- resourceBases = new String[] { webAppSourceDirectory.getAbsolutePath() };
- }
- StringBuffer rb = new StringBuffer(resourceBases[0]);
- for (int i=1; i<resourceBases.length; i++)
- {
- rb.append(File.pathSeparator);
- rb.append(resourceBases[i]);
+ else
+ rb.append(originalBaseResource.toString());
+
+ props.put("base.dirs", rb.toString());
}
- props.put("base.dirs", rb.toString());
//sort out the resource base directories of the webapp
- StringBuilder builder = new StringBuilder();
- props.put("base.first", Boolean.toString(baseAppFirst));
+ props.put("base.first", Boolean.toString(webApp.getBaseAppFirst()));
//web-inf classes
- List<File> classDirs = getClassesDirs();
- StringBuffer strbuff = new StringBuffer();
- for (int i=0; i<classDirs.size(); i++)
- {
- File f = classDirs.get(i);
- strbuff.append(f.getAbsolutePath());
- if (i < classDirs.size()-1)
- strbuff.append(",");
- }
-
- if (classesDirectory != null)
+ if (webApp.getClasses() != null)
{
- props.put("classes.dir", classesDirectory.getAbsolutePath());
+ props.put("classes.dir",webApp.getClasses().getAbsolutePath());
}
- if (useTestScope && testClassesDirectory != null)
+ if (useTestScope && webApp.getTestClasses() != null)
{
- props.put("testClasses.dir", testClassesDirectory.getAbsolutePath());
+ props.put("testClasses.dir", webApp.getTestClasses().getAbsolutePath());
}
//web-inf lib
- List<File> deps = getDependencyFiles();
- strbuff.setLength(0);
+ List<File> deps = webApp.getWebInfLib();
+ StringBuffer strbuff = new StringBuffer();
for (int i=0; i<deps.size(); i++)
{
File d = deps.get(i);
@@ -550,25 +573,6 @@ public class JettyRunForkedMojo extends AbstractMojo
- /**
- * @return
- */
- private List<File> getClassesDirs ()
- {
- List<File> classesDirs = new ArrayList<File>();
-
- //if using the test classes, make sure they are first
- //on the list
- if (useTestScope && (testClassesDirectory != null))
- classesDirs.add(testClassesDirectory);
-
- if (classesDirectory != null)
- classesDirs.add(classesDirectory);
-
- return classesDirs;
- }
-
-
/**
@@ -594,30 +598,6 @@ public class JettyRunForkedMojo extends AbstractMojo
- /**
- * @return
- */
- private List<File> getDependencyFiles ()
- {
- List<File> dependencyFiles = new ArrayList<File>();
-
- for ( Iterator<Artifact> iter = project.getArtifacts().iterator(); iter.hasNext(); )
- {
- Artifact artifact = (Artifact) iter.next();
- // Test never appears here !
- if (((!Artifact.SCOPE_PROVIDED.equals(artifact.getScope())) && (!Artifact.SCOPE_TEST.equals( artifact.getScope())))
- ||
- (useTestScope && Artifact.SCOPE_TEST.equals( artifact.getScope())))
- {
- dependencyFiles.add(artifact.getFile());
- getLog().debug( "Adding artifact " + artifact.getFile().getName() + " for WEB-INF/lib " );
- }
- }
-
- return dependencyFiles;
- }
-
-
/**
@@ -675,143 +655,14 @@ public class JettyRunForkedMojo extends AbstractMojo
-
- /**
- * @throws MojoExecutionException
- */
- public void startJettyRunner() throws MojoExecutionException
- {
- try
- {
-
- File props = prepareConfiguration();
-
- List<String> cmd = new ArrayList<String>();
- cmd.add(getJavaBin());
-
- if (jvmArgs != null)
- {
- String[] args = jvmArgs.split(" ");
- for (int i=0;args != null && i<args.length;i++)
- {
- if (args[i] !=null && !"".equals(args[i]))
- cmd.add(args[i].trim());
- }
- }
-
- String classPath = getClassPath();
- if (classPath != null && classPath.length() > 0)
- {
- cmd.add("-cp");
- cmd.add(classPath);
- }
- cmd.add(Starter.class.getCanonicalName());
-
- if (stopPort > 0 && stopKey != null)
- {
- cmd.add("--stop-port");
- cmd.add(Integer.toString(stopPort));
- cmd.add("--stop-key");
- cmd.add(stopKey);
- }
- if (jettyXml != null)
- {
- cmd.add("--jetty-xml");
- cmd.add(jettyXml);
- }
-
- if (contextXml != null)
- {
- cmd.add("--context-xml");
- cmd.add(contextXml);
- }
-
- cmd.add("--props");
- cmd.add(props.getAbsolutePath());
-
- String token = createToken();
- cmd.add("--token");
- cmd.add(token);
-
- ProcessBuilder builder = new ProcessBuilder(cmd);
- builder.directory(project.getBasedir());
-
- if (PluginLog.getLog().isDebugEnabled())
- PluginLog.getLog().debug(Arrays.toString(cmd.toArray()));
-
- PluginLog.getLog().info("Forked process starting");
-
- if (waitForChild)
- {
- forkedProcess = builder.start();
- startPump("STDOUT",forkedProcess.getInputStream());
- startPump("STDERR",forkedProcess.getErrorStream());
- int exitcode = forkedProcess.waitFor();
- PluginLog.getLog().info("Forked execution exit: "+exitcode);
- }
- else
- { //merge stderr and stdout from child
- builder.redirectErrorStream(true);
- forkedProcess = builder.start();
-
- //wait for the child to be ready before terminating.
- //child indicates it has finished starting by printing on stdout the token passed to it
- try
- {
- String line = "";
- try (InputStream is = forkedProcess.getInputStream();
- LineNumberReader reader = new LineNumberReader(new InputStreamReader(is)))
- {
- int attempts = maxStartupLines; //max lines we'll read trying to get token
- while (attempts>0 && line != null)
- {
- --attempts;
- line = reader.readLine();
- if (line != null && line.startsWith(token))
- break;
- }
-
- }
-
- if (line != null && line.trim().equals(token))
- PluginLog.getLog().info("Forked process started.");
- else
- {
- String err = (line == null?"":(line.startsWith(token)?line.substring(token.length()):line));
- PluginLog.getLog().info("Forked process startup errors"+(!"".equals(err)?", received: "+err:""));
- }
- }
- catch (Exception e)
- {
- throw new MojoExecutionException ("Problem determining if forked process is ready: "+e.getMessage());
- }
-
- }
- }
- catch (InterruptedException ex)
- {
- if (forkedProcess != null && waitForChild)
- forkedProcess.destroy();
-
- throw new MojoExecutionException("Failed to start Jetty within time limit");
- }
- catch (Exception ex)
- {
- if (forkedProcess != null && waitForChild)
- forkedProcess.destroy();
-
- throw new MojoExecutionException("Failed to create Jetty process", ex);
- }
- }
-
-
+
/**
* @return
* @throws Exception
*/
- public String getClassPath() throws Exception
+ public String getContainerClassPath() throws Exception
{
StringBuilder classPath = new StringBuilder();
for (Object obj : pluginArtifacts)
diff --git a/jetty-maven-plugin/src/main/java/org/eclipse/jetty/maven/plugin/JettyRunMojo.java b/jetty-maven-plugin/src/main/java/org/eclipse/jetty/maven/plugin/JettyRunMojo.java
index 41147fca0d..130dd52504 100644
--- a/jetty-maven-plugin/src/main/java/org/eclipse/jetty/maven/plugin/JettyRunMojo.java
+++ b/jetty-maven-plugin/src/main/java/org/eclipse/jetty/maven/plugin/JettyRunMojo.java
@@ -55,8 +55,7 @@ import org.eclipse.jetty.webapp.WebAppContext;
* This can be used, for example, to deploy a static webapp that is not part of your maven build.
* </p>
* <p>
- * There is a <a href="run-mojo.html">reference guide</a> to the configuration parameters for this plugin, and more detailed information
- * with examples in the <a href="http://docs.codehaus.org/display/JETTY/Maven+Jetty+Plugin">Configuration Guide</a>.
+ * There is a <a href="http://www.eclipse.org/jetty/documentation/current/maven-and-jetty.html">reference guide</a> to the configuration parameters for this plugin.
* </p>
*
*
diff --git a/jetty-maven-plugin/src/main/java/org/eclipse/jetty/maven/plugin/JettyWebAppContext.java b/jetty-maven-plugin/src/main/java/org/eclipse/jetty/maven/plugin/JettyWebAppContext.java
index 700d0b9372..6bdb013412 100644
--- a/jetty-maven-plugin/src/main/java/org/eclipse/jetty/maven/plugin/JettyWebAppContext.java
+++ b/jetty-maven-plugin/src/main/java/org/eclipse/jetty/maven/plugin/JettyWebAppContext.java
@@ -19,6 +19,7 @@
package org.eclipse.jetty.maven.plugin;
import java.io.File;
+import java.io.FileOutputStream;
import java.io.IOException;
import java.net.MalformedURLException;
import java.util.ArrayList;
@@ -32,6 +33,8 @@ import java.util.TreeSet;
import org.eclipse.jetty.annotations.AnnotationConfiguration;
import org.eclipse.jetty.plus.webapp.EnvConfiguration;
import org.eclipse.jetty.plus.webapp.PlusConfiguration;
+import org.eclipse.jetty.quickstart.PreconfigureDescriptorProcessor;
+import org.eclipse.jetty.quickstart.QuickStartDescriptorGenerator;
import org.eclipse.jetty.servlet.FilterHolder;
import org.eclipse.jetty.servlet.FilterMapping;
import org.eclipse.jetty.servlet.ServletHolder;
@@ -61,20 +64,40 @@ import org.eclipse.jetty.webapp.WebXmlConfiguration;
public class JettyWebAppContext extends WebAppContext
{
private static final Logger LOG = Log.getLogger(JettyWebAppContext.class);
+
+
- private static final String DEFAULT_CONTAINER_INCLUDE_JAR_PATTERN = ".*/javax.servlet-[^/]*\\.jar$|.*/servlet-api-[^/]*\\.jar$|.*javax.servlet.jsp.jstl-[^/]*\\.jar";
+ private static final String DEFAULT_CONTAINER_INCLUDE_JAR_PATTERN = ".*/javax.servlet-[^/]*\\.jar$|.*/servlet-api-[^/]*\\.jar$|.*javax.servlet.jsp.jstl-[^/]*\\.jar|.*taglibs-standard-impl-.*\\.jar";
private static final String WEB_INF_CLASSES_PREFIX = "/WEB-INF/classes";
private static final String WEB_INF_LIB_PREFIX = "/WEB-INF/lib";
+ private final Configuration[] _defaultConfigurations = {
+ new MavenWebInfConfiguration(),
+ new WebXmlConfiguration(),
+ new MetaInfConfiguration(),
+ new FragmentConfiguration(),
+ new EnvConfiguration(),
+ new PlusConfiguration(),
+ new AnnotationConfiguration(),
+ new JettyWebXmlConfiguration()
+ };
+
+ private final Configuration[] _quickStartConfigurations = {
+ new MavenQuickStartConfiguration(),
+ new EnvConfiguration(),
+ new PlusConfiguration(),
+ new JettyWebXmlConfiguration()
+ };
+
private File _classes = null;
private File _testClasses = null;
private final List<File> _webInfClasses = new ArrayList<File>();
private final List<File> _webInfJars = new ArrayList<File>();
private final Map<String, File> _webInfJarMap = new HashMap<String, File>();
- private final EnvConfiguration _envConfig;
private List<File> _classpathFiles; //webInfClasses+testClasses+webInfJars
private String _jettyEnvXml;
private List<Overlay> _overlays;
+ private Resource _quickStartWebXml;
@@ -99,28 +122,24 @@ public class JettyWebAppContext extends WebAppContext
*/
private boolean _baseAppFirst = true;
+
+
+ private boolean _isGenerateQuickStart;
+ private PreconfigureDescriptorProcessor _preconfigProcessor;
+
+
public JettyWebAppContext ()
throws Exception
{
super();
- setConfigurations(new Configuration[]{
- new MavenWebInfConfiguration(),
- new WebXmlConfiguration(),
- new MetaInfConfiguration(),
- new FragmentConfiguration(),
- _envConfig = new EnvConfiguration(),
- new PlusConfiguration(),
- new AnnotationConfiguration(),
- new JettyWebXmlConfiguration()
- });
// Turn off copyWebInf option as it is not applicable for plugin.
super.setCopyWebInf(false);
}
public void setContainerIncludeJarPattern(String pattern)
{
- _containerIncludeJarPattern = pattern;
+ _containerIncludeJarPattern = pattern;
}
public String getContainerIncludeJarPattern()
@@ -131,7 +150,7 @@ public class JettyWebAppContext extends WebAppContext
public String getWebInfIncludeJarPattern()
{
- return _webInfIncludeJarPattern;
+ return _webInfIncludeJarPattern;
}
public void setWebInfIncludeJarPattern(String pattern)
{
@@ -209,7 +228,19 @@ public class JettyWebAppContext extends WebAppContext
{
return _baseAppFirst;
}
-
+
+ /* ------------------------------------------------------------ */
+ public void setQuickStartWebDescriptor (Resource quickStartWebXml)
+ {
+ _quickStartWebXml = quickStartWebXml;
+ }
+
+ /* ------------------------------------------------------------ */
+ public Resource getQuickStartWebDescriptor ()
+ {
+ return _quickStartWebXml;
+ }
+
/* ------------------------------------------------------------ */
/**
* This method is provided as a convenience for jetty maven plugin configuration
@@ -233,9 +264,65 @@ public class JettyWebAppContext extends WebAppContext
{
return _webInfJars;
}
+
+ public void setGenerateQuickStart (boolean quickStart)
+ {
+ _isGenerateQuickStart = quickStart;
+ }
+
+ public boolean isGenerateQuickStart()
+ {
+ return _isGenerateQuickStart;
+ }
+
+
+
+
+ @Override
+ protected void startWebapp() throws Exception
+ {
+ if (isGenerateQuickStart())
+ {
+ if (getQuickStartWebDescriptor() == null)
+ throw new IllegalStateException ("No location to generate quickstart descriptor");
+
+ QuickStartDescriptorGenerator generator = new QuickStartDescriptorGenerator(this, _preconfigProcessor.getXML());
+ try (FileOutputStream fos = new FileOutputStream(getQuickStartWebDescriptor().getFile()))
+ {
+ generator.generateQuickStartWebXml(fos);
+ }
+ }
+ else
+ super.startWebapp();
+ }
+
+ @Override
public void doStart () throws Exception
{
+ //choose if this will be a quickstart or normal start
+ if (!isGenerateQuickStart() && getQuickStartWebDescriptor() != null)
+ setConfigurations(_quickStartConfigurations);
+ else
+ {
+ setConfigurations(_defaultConfigurations);
+ if (isGenerateQuickStart())
+ {
+ _preconfigProcessor = new PreconfigureDescriptorProcessor();
+ getMetaData().addDescriptorProcessor(_preconfigProcessor);
+ }
+ }
+
+
+ //inject configurations with config from maven plugin
+ for (Configuration c:getConfigurations())
+ {
+ if (c instanceof EnvConfiguration && getJettyEnvXml() != null)
+ ((EnvConfiguration)c).setJettyEnvXml(Resource.toURL(new File(getJettyEnvXml())));
+ else if (c instanceof MavenQuickStartConfiguration && getQuickStartWebDescriptor() != null)
+ ((MavenQuickStartConfiguration)c).setQuickStartWebXml(getQuickStartWebDescriptor());
+ }
+
//Set up the pattern that tells us where the jars are that need scanning
//Allow user to set up pattern for names of jars from the container classpath
@@ -273,9 +360,6 @@ public class JettyWebAppContext extends WebAppContext
if (fileName.endsWith(".jar"))
_webInfJarMap.put(fileName, file);
}
-
- if (this._jettyEnvXml != null)
- _envConfig.setJettyEnvXml(Resource.toURL(new File(this._jettyEnvXml)));
// CHECK setShutdown(false);
super.doStart();
diff --git a/jetty-maven-plugin/src/main/java/org/eclipse/jetty/maven/plugin/MavenQuickStartConfiguration.java b/jetty-maven-plugin/src/main/java/org/eclipse/jetty/maven/plugin/MavenQuickStartConfiguration.java
new file mode 100644
index 0000000000..295bd06242
--- /dev/null
+++ b/jetty-maven-plugin/src/main/java/org/eclipse/jetty/maven/plugin/MavenQuickStartConfiguration.java
@@ -0,0 +1,92 @@
+//
+// ========================================================================
+// Copyright (c) 1995-2014 Mort Bay Consulting Pty. Ltd.
+// ------------------------------------------------------------------------
+// All rights reserved. This program and the accompanying materials
+// are made available under the terms of the Eclipse Public License v1.0
+// and Apache License v2.0 which accompanies this distribution.
+//
+// The Eclipse Public License is available at
+// http://www.eclipse.org/legal/epl-v10.html
+//
+// The Apache License v2.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.maven.plugin;
+
+import java.io.File;
+import java.util.Iterator;
+
+import org.eclipse.jetty.quickstart.QuickStartConfiguration;
+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.webapp.WebAppClassLoader;
+import org.eclipse.jetty.webapp.WebAppContext;
+
+/**
+ * MavenQuickStartConfiguration
+ *
+ *
+ */
+public class MavenQuickStartConfiguration extends QuickStartConfiguration
+{
+ private static final Logger LOG = Log.getLogger(QuickStartConfiguration.class);
+
+ private Resource _quickStartWebXml;
+
+
+ public void setQuickStartWebXml (Resource r)
+ {
+ _quickStartWebXml = r;
+ }
+
+
+
+ @Override
+ public Resource getQuickStartWebXml(WebAppContext context) throws Exception
+ {
+ return _quickStartWebXml;
+ }
+
+
+
+ @Override
+ public void configure(WebAppContext context) throws Exception
+ {
+
+ JettyWebAppContext jwac = (JettyWebAppContext)context;
+
+ //put the classes dir and all dependencies into the classpath
+ if (jwac.getClassPathFiles() != null)
+ {
+ if (LOG.isDebugEnabled()) LOG.debug("Setting up classpath ...");
+ Iterator itor = jwac.getClassPathFiles().iterator();
+ while (itor.hasNext())
+ ((WebAppClassLoader)context.getClassLoader()).addClassPath(((File)itor.next()).getCanonicalPath());
+ }
+
+ //Set up the quickstart environment for the context
+ super.configure(context);
+
+ // knock out environmental maven and plexus classes from webAppContext
+ String[] existingServerClasses = context.getServerClasses();
+ String[] newServerClasses = new String[2+(existingServerClasses==null?0:existingServerClasses.length)];
+ newServerClasses[0] = "org.apache.maven.";
+ newServerClasses[1] = "org.codehaus.plexus.";
+ System.arraycopy( existingServerClasses, 0, newServerClasses, 2, existingServerClasses.length );
+ if (LOG.isDebugEnabled())
+ {
+ LOG.debug("Server classes:");
+ for (int i=0;i<newServerClasses.length;i++)
+ LOG.debug(newServerClasses[i]);
+ }
+ context.setServerClasses( newServerClasses );
+ }
+
+}
diff --git a/jetty-maven-plugin/src/main/java/org/eclipse/jetty/maven/plugin/Starter.java b/jetty-maven-plugin/src/main/java/org/eclipse/jetty/maven/plugin/Starter.java
index d16b89d842..574259a882 100644
--- a/jetty-maven-plugin/src/main/java/org/eclipse/jetty/maven/plugin/Starter.java
+++ b/jetty-maven-plugin/src/main/java/org/eclipse/jetty/maven/plugin/Starter.java
@@ -23,7 +23,6 @@ import java.io.FileInputStream;
import java.io.InputStream;
import java.net.URL;
import java.util.ArrayList;
-import java.util.Collections;
import java.util.Enumeration;
import java.util.HashSet;
import java.util.Iterator;
@@ -156,6 +155,14 @@ public class Starter
//configure webapp from properties file describing unassembled webapp
configureWebApp();
+ //make it a quickstart if the quickstart-web.xml file exists
+ if (webApp.getTempDirectory() != null)
+ {
+ File qs = new File (webApp.getTempDirectory(), "quickstart-web.xml");
+ if (qs.exists() && qs.isFile())
+ webApp.setQuickStartWebDescriptor(Resource.newResource(qs));
+ }
+
//set up the webapp from the context xml file provided
//NOTE: just like jetty:run mojo this means that the context file can
//potentially override settings made in the pom. Ideally, we'd like
@@ -203,6 +210,9 @@ public class Starter
if (str != null)
webApp.setDescriptor(str);
+ str = (String)props.get("quickstart.web.xml");
+ if (str != null)
+ webApp.setQuickStartWebDescriptor(Resource.newResource(new File(str)));
// - the tmp directory
str = (String)props.getProperty("tmp.dir");
@@ -217,8 +227,9 @@ public class Starter
str = (String)props.getProperty("base.dirs");
if (str != null && !"".equals(str.trim()))
{
- webApp.setWar(str);
- webApp.setBaseResource(new ResourceCollection(str.split(File.pathSeparator)));
+ ResourceCollection bases = new ResourceCollection(str.split(","));
+ webApp.setWar(bases.getResources()[0].toString());
+ webApp.setBaseResource(bases);
}
// - put virtual webapp base resource first on resource path or not
diff --git a/jetty-monitor/pom.xml b/jetty-monitor/pom.xml
index 6dd98ec090..8f470d841c 100644
--- a/jetty-monitor/pom.xml
+++ b/jetty-monitor/pom.xml
@@ -19,7 +19,7 @@
<parent>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-project</artifactId>
- <version>9.2.2-SNAPSHOT</version>
+ <version>9.2.3-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>jetty-monitor</artifactId>
diff --git a/jetty-monitor/src/main/java/org/eclipse/jetty/monitor/jmx/ServiceConnection.java b/jetty-monitor/src/main/java/org/eclipse/jetty/monitor/jmx/ServiceConnection.java
index 0f11428ff7..bdce382fed 100644
--- a/jetty-monitor/src/main/java/org/eclipse/jetty/monitor/jmx/ServiceConnection.java
+++ b/jetty-monitor/src/main/java/org/eclipse/jetty/monitor/jmx/ServiceConnection.java
@@ -82,7 +82,7 @@ public class ServiceConnection
*/
public String getServiceUrl()
{
- return _serviceUrl;
+ return _serviceUrl;
}
/* ------------------------------------------------------------ */
diff --git a/jetty-nosql/pom.xml b/jetty-nosql/pom.xml
index 0d847cad39..ae7de4ff05 100644
--- a/jetty-nosql/pom.xml
+++ b/jetty-nosql/pom.xml
@@ -2,7 +2,7 @@
<parent>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-project</artifactId>
- <version>9.2.2-SNAPSHOT</version>
+ <version>9.2.3-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>jetty-nosql</artifactId>
diff --git a/jetty-nosql/src/main/java/org/eclipse/jetty/nosql/NoSqlSession.java b/jetty-nosql/src/main/java/org/eclipse/jetty/nosql/NoSqlSession.java
index 8b732d4d2b..ae92051e7a 100644
--- a/jetty-nosql/src/main/java/org/eclipse/jetty/nosql/NoSqlSession.java
+++ b/jetty-nosql/src/main/java/org/eclipse/jetty/nosql/NoSqlSession.java
@@ -207,7 +207,7 @@ public class NoSqlSession extends MemSession
/* ------------------------------------------------------------ */
public Object getVersion()
{
- return _version;
+ return _version;
}
@Override
diff --git a/jetty-nosql/src/main/java/org/eclipse/jetty/nosql/mongodb/MongoSessionIdManager.java b/jetty-nosql/src/main/java/org/eclipse/jetty/nosql/mongodb/MongoSessionIdManager.java
index 69722e79dd..e599b27149 100644
--- a/jetty-nosql/src/main/java/org/eclipse/jetty/nosql/mongodb/MongoSessionIdManager.java
+++ b/jetty-nosql/src/main/java/org/eclipse/jetty/nosql/mongodb/MongoSessionIdManager.java
@@ -23,8 +23,6 @@ import java.net.UnknownHostException;
import java.util.HashSet;
import java.util.Random;
import java.util.Set;
-import java.util.Timer;
-import java.util.TimerTask;
import java.util.concurrent.TimeUnit;
import javax.servlet.http.HttpServletRequest;
diff --git a/jetty-nosql/src/main/java/org/eclipse/jetty/nosql/mongodb/MongoSessionManager.java b/jetty-nosql/src/main/java/org/eclipse/jetty/nosql/mongodb/MongoSessionManager.java
index d8556da87a..50384666f5 100644
--- a/jetty-nosql/src/main/java/org/eclipse/jetty/nosql/mongodb/MongoSessionManager.java
+++ b/jetty-nosql/src/main/java/org/eclipse/jetty/nosql/mongodb/MongoSessionManager.java
@@ -654,7 +654,7 @@ public class MongoSessionManager extends NoSqlSessionManager
/*------------------------------------------------------------ */
private String getContextKey()
{
- return __CONTEXT + "." + _contextId;
+ return __CONTEXT + "." + _contextId;
}
/*------------------------------------------------------------ */
@@ -664,7 +664,7 @@ public class MongoSessionManager extends NoSqlSessionManager
*/
private String getContextAttributeKey(String attr)
{
- return getContextKey()+ "." + attr;
+ return getContextKey()+ "." + attr;
}
@ManagedOperation(value="purge invalid sessions in the session store based on normal criteria", impact="ACTION")
diff --git a/jetty-osgi/jetty-osgi-alpn/pom.xml b/jetty-osgi/jetty-osgi-alpn/pom.xml
index ab26c53353..3004245c40 100644
--- a/jetty-osgi/jetty-osgi-alpn/pom.xml
+++ b/jetty-osgi/jetty-osgi-alpn/pom.xml
@@ -2,7 +2,7 @@
<parent>
<groupId>org.eclipse.jetty.osgi</groupId>
<artifactId>jetty-osgi-project</artifactId>
- <version>9.2.2-SNAPSHOT</version>
+ <version>9.2.3-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>jetty-osgi-alpn</artifactId>
diff --git a/jetty-osgi/jetty-osgi-boot-jsp/pom.xml b/jetty-osgi/jetty-osgi-boot-jsp/pom.xml
index 0a2d06cc86..2a36eb3472 100644
--- a/jetty-osgi/jetty-osgi-boot-jsp/pom.xml
+++ b/jetty-osgi/jetty-osgi-boot-jsp/pom.xml
@@ -2,7 +2,7 @@
<parent>
<groupId>org.eclipse.jetty.osgi</groupId>
<artifactId>jetty-osgi-project</artifactId>
- <version>9.2.2-SNAPSHOT</version>
+ <version>9.2.3-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>jetty-osgi-boot-jsp</artifactId>
diff --git a/jetty-osgi/jetty-osgi-boot-warurl/pom.xml b/jetty-osgi/jetty-osgi-boot-warurl/pom.xml
index 3a1d106142..7ce039ab5e 100644
--- a/jetty-osgi/jetty-osgi-boot-warurl/pom.xml
+++ b/jetty-osgi/jetty-osgi-boot-warurl/pom.xml
@@ -2,7 +2,7 @@
<parent>
<groupId>org.eclipse.jetty.osgi</groupId>
<artifactId>jetty-osgi-project</artifactId>
- <version>9.2.2-SNAPSHOT</version>
+ <version>9.2.3-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>
<modelVersion>4.0.0</modelVersion>
diff --git a/jetty-osgi/jetty-osgi-boot/pom.xml b/jetty-osgi/jetty-osgi-boot/pom.xml
index 01b3383dee..4545bc5f5c 100644
--- a/jetty-osgi/jetty-osgi-boot/pom.xml
+++ b/jetty-osgi/jetty-osgi-boot/pom.xml
@@ -2,7 +2,7 @@
<parent>
<groupId>org.eclipse.jetty.osgi</groupId>
<artifactId>jetty-osgi-project</artifactId>
- <version>9.2.2-SNAPSHOT</version>
+ <version>9.2.3-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>jetty-osgi-boot</artifactId>
diff --git a/jetty-osgi/jetty-osgi-boot/src/main/java/org/eclipse/jetty/osgi/annotations/AnnotationConfiguration.java b/jetty-osgi/jetty-osgi-boot/src/main/java/org/eclipse/jetty/osgi/annotations/AnnotationConfiguration.java
index 322aec55e7..14c796d213 100644
--- a/jetty-osgi/jetty-osgi-boot/src/main/java/org/eclipse/jetty/osgi/annotations/AnnotationConfiguration.java
+++ b/jetty-osgi/jetty-osgi-boot/src/main/java/org/eclipse/jetty/osgi/annotations/AnnotationConfiguration.java
@@ -23,6 +23,7 @@ import java.util.Set;
import org.eclipse.jetty.annotations.AnnotationParser.Handler;
import org.eclipse.jetty.annotations.ClassNameResolver;
+import org.eclipse.jetty.osgi.boot.OSGiWebInfConfiguration;
import org.eclipse.jetty.osgi.boot.OSGiWebappConstants;
import org.eclipse.jetty.osgi.boot.utils.internal.PackageAdminServiceTracker;
import org.eclipse.jetty.util.log.Log;
@@ -92,7 +93,7 @@ public class AnnotationConfiguration extends org.eclipse.jetty.annotations.Annot
AnnotationParser oparser = (AnnotationParser)parser;
Bundle webbundle = (Bundle) context.getAttribute(OSGiWebappConstants.JETTY_OSGI_BUNDLE);
- Bundle[] fragAndRequiredBundles = PackageAdminServiceTracker.INSTANCE.getFragmentsAndRequiredBundles(webbundle);
+ Set<Bundle> fragAndRequiredBundles = (Set<Bundle>)context.getAttribute(OSGiWebInfConfiguration.FRAGMENT_AND_REQUIRED_BUNDLES);
if (fragAndRequiredBundles != null)
{
//index and scan fragments
diff --git a/jetty-osgi/jetty-osgi-boot/src/main/java/org/eclipse/jetty/osgi/annotations/AnnotationParser.java b/jetty-osgi/jetty-osgi-boot/src/main/java/org/eclipse/jetty/osgi/annotations/AnnotationParser.java
index 8887036f59..9275bc76fe 100644
--- a/jetty-osgi/jetty-osgi-boot/src/main/java/org/eclipse/jetty/osgi/annotations/AnnotationParser.java
+++ b/jetty-osgi/jetty-osgi-boot/src/main/java/org/eclipse/jetty/osgi/annotations/AnnotationParser.java
@@ -23,9 +23,6 @@ import java.net.URI;
import java.net.URL;
import java.util.Comparator;
import java.util.Enumeration;
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.Map;
import java.util.Set;
import java.util.StringTokenizer;
import java.util.TreeSet;
@@ -35,7 +32,6 @@ import org.eclipse.jetty.annotations.ClassNameResolver;
import org.eclipse.jetty.osgi.boot.utils.BundleFileLocatorHelper;
import org.eclipse.jetty.util.ConcurrentHashSet;
import org.eclipse.jetty.util.resource.Resource;
-import org.objectweb.asm.Opcodes;
import org.osgi.framework.Bundle;
import org.osgi.framework.Constants;
@@ -51,13 +47,6 @@ public class AnnotationParser extends org.eclipse.jetty.annotations.AnnotationPa
private ConcurrentHashMap<Resource, Bundle> _resourceToBundle = new ConcurrentHashMap<Resource, Bundle>();
private ConcurrentHashMap<Bundle,URI> _bundleToUri = new ConcurrentHashMap<Bundle, URI>();
- static
- {
- //As of jetty 9.2.0, the impl of asm visitor classes is compatible with both asm4 and asm5.
- //We need to use asm4 with osgi, because we need to use aries spifly to support annotations,
- //and currently this only supports asm4. Therefore, we set the asm api version to be 4 for osgi.
- ASM_OPCODE_VERSION = Opcodes.ASM4;
- }
/**
* Keep track of a jetty URI Resource and its associated OSGi bundle.
@@ -212,5 +201,4 @@ public class AnnotationParser extends org.eclipse.jetty.annotations.AnnotationPa
scanClass(handlers, getResource(bundle), classUrl.openStream());
}
}
-
}
diff --git a/jetty-osgi/jetty-osgi-boot/src/main/java/org/eclipse/jetty/osgi/boot/OSGiMetaInfConfiguration.java b/jetty-osgi/jetty-osgi-boot/src/main/java/org/eclipse/jetty/osgi/boot/OSGiMetaInfConfiguration.java
deleted file mode 100644
index 7b85f62a2d..0000000000
--- a/jetty-osgi/jetty-osgi-boot/src/main/java/org/eclipse/jetty/osgi/boot/OSGiMetaInfConfiguration.java
+++ /dev/null
@@ -1,129 +0,0 @@
-//
-// ========================================================================
-// Copyright (c) 1995-2014 Mort Bay Consulting Pty. Ltd.
-// ------------------------------------------------------------------------
-// All rights reserved. This program and the accompanying materials
-// are made available under the terms of the Eclipse Public License v1.0
-// and Apache License v2.0 which accompanies this distribution.
-//
-// The Eclipse Public License is available at
-// http://www.eclipse.org/legal/epl-v10.html
-//
-// The Apache License v2.0 is available at
-// http://www.opensource.org/licenses/apache2.0.php
-//
-// You may elect to redistribute this code under either of these licenses.
-// ========================================================================
-//
-
-package org.eclipse.jetty.osgi.boot;
-
-import java.net.URL;
-import java.util.ArrayList;
-import java.util.Enumeration;
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
-
-import org.eclipse.jetty.osgi.boot.utils.BundleFileLocatorHelperFactory;
-import org.eclipse.jetty.osgi.boot.utils.internal.PackageAdminServiceTracker;
-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.webapp.MetaInfConfiguration;
-import org.eclipse.jetty.webapp.WebAppContext;
-import org.osgi.framework.Bundle;
-
-/**
- * OSGiMetaInfConfiguration
- *
- * Extension of standard Jetty MetaInfConfiguration class to handle OSGi bundle
- * fragments that may also need to be scanned for META-INF info.
- *
- * @deprecated
- */
-public class OSGiMetaInfConfiguration extends MetaInfConfiguration
-{
- private static final Logger LOG = Log.getLogger(OSGiMetaInfConfiguration.class);
-
-
- /**
- * Inspect bundle fragments associated with the bundle of the webapp for web-fragment, resources, tlds.
- *
- * @see org.eclipse.jetty.webapp.MetaInfConfiguration#preConfigure(org.eclipse.jetty.webapp.WebAppContext)
- */
- @Override
- public void preConfigure(final WebAppContext context) throws Exception
- {
- Map<Resource, Resource> frags = (Map<Resource, Resource>) context.getAttribute(METAINF_FRAGMENTS);
- Set<Resource> resfrags = (Set<Resource>) context.getAttribute(METAINF_RESOURCES);
- List<Resource> tldfrags = (List<Resource>) context.getAttribute(METAINF_TLDS);
-
- Bundle[] fragments = PackageAdminServiceTracker.INSTANCE.getFragmentsAndRequiredBundles((Bundle)context.getAttribute(OSGiWebappConstants.JETTY_OSGI_BUNDLE));
- //TODO not convinced we need to do this, as we added any fragment jars to the MetaData.webInfJars in OSGiWebInfConfiguration,
- //so surely the web-fragments and resources tlds etc can be discovered normally?
- for (Bundle frag : fragments)
- {
- URL webFrag = frag.getEntry("/META-INF/web-fragment.xml");
- Enumeration<URL> resEnum = frag.findEntries("/META-INF/resources", "*", true);
- Enumeration<URL> tldEnum = frag.findEntries("/META-INF", "*.tld", false);
- if (webFrag != null || (resEnum != null && resEnum.hasMoreElements()) || (tldEnum != null && tldEnum.hasMoreElements()))
- {
- try
- {
- if (webFrag != null)
- {
- if (frags == null)
- {
- frags = new HashMap<Resource,Resource>();
- context.setAttribute(METAINF_FRAGMENTS, frags);
- }
- frags.put(Resource.newResource(BundleFileLocatorHelperFactory.getFactory().getHelper().getBundleInstallLocation(frag).toURI()),
- Resource.newResource(webFrag));
- }
- if (resEnum != null && resEnum.hasMoreElements())
- {
- URL resourcesEntry = frag.getEntry("/META-INF/resources/");
- if (resourcesEntry == null)
- {
- // probably we found some fragments to a
- // bundle.
- // those are already contributed.
- // so we skip this.
- }
- else
- {
- if (resfrags == null)
- {
- resfrags = new HashSet<Resource>();
- context.setAttribute(METAINF_RESOURCES, resfrags);
- }
- resfrags.add(Resource.newResource(BundleFileLocatorHelperFactory.getFactory().getHelper().getLocalURL(resourcesEntry)));
- }
- }
- if (tldEnum != null && tldEnum.hasMoreElements())
- {
- if (tldfrags == null)
- {
- tldfrags = new ArrayList<Resource>();
- context.setAttribute(METAINF_TLDS, tldfrags);
- }
- while (tldEnum.hasMoreElements())
- {
- URL tldUrl = tldEnum.nextElement();
- tldfrags.add(Resource.newResource(BundleFileLocatorHelperFactory.getFactory().getHelper().getLocalURL(tldUrl)));
- }
- }
- }
- catch (Exception e)
- {
- LOG.warn("Unable to locate the bundle " + frag.getBundleId(), e);
- }
- }
- }
-
- super.preConfigure(context);
- }
-}
diff --git a/jetty-osgi/jetty-osgi-boot/src/main/java/org/eclipse/jetty/osgi/boot/OSGiWebInfConfiguration.java b/jetty-osgi/jetty-osgi-boot/src/main/java/org/eclipse/jetty/osgi/boot/OSGiWebInfConfiguration.java
index ce3c141ae5..69a7ce8cdb 100644
--- a/jetty-osgi/jetty-osgi-boot/src/main/java/org/eclipse/jetty/osgi/boot/OSGiWebInfConfiguration.java
+++ b/jetty-osgi/jetty-osgi-boot/src/main/java/org/eclipse/jetty/osgi/boot/OSGiWebInfConfiguration.java
@@ -23,6 +23,7 @@ import java.net.URL;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
+import java.util.Set;
import java.util.StringTokenizer;
import java.util.TreeMap;
import java.util.regex.Pattern;
@@ -51,6 +52,9 @@ public class OSGiWebInfConfiguration extends WebInfConfiguration
public static final String CONTAINER_BUNDLE_PATTERN = "org.eclipse.jetty.server.webapp.containerIncludeBundlePattern";
+ public static final String FRAGMENT_AND_REQUIRED_BUNDLES = "org.eclipse.jetty.osgi.fragmentAndRequiredBundles";
+ public static final String FRAGMENT_AND_REQUIRED_RESOURCES = "org.eclipse.jetty.osgi.fragmentAndRequiredResources";
+
/* ------------------------------------------------------------ */
/**
@@ -87,7 +91,6 @@ public class OSGiWebInfConfiguration extends WebInfConfiguration
while (tokenizer.hasMoreTokens())
names.add(tokenizer.nextToken());
}
-
HashSet<Resource> matchingResources = new HashSet<Resource>();
if ( !names.isEmpty() || pattern != null)
{
@@ -111,14 +114,20 @@ public class OSGiWebInfConfiguration extends WebInfConfiguration
matchingResources.addAll(getBundleAsResource(bundle));
}
}
- }
-
+ }
for (Resource r:matchingResources)
{
context.getMetaData().addContainerResource(r);
}
}
+ @Override
+ public void postConfigure(WebAppContext context) throws Exception
+ {
+ context.setAttribute(FRAGMENT_AND_REQUIRED_BUNDLES, null);
+ context.setAttribute(FRAGMENT_AND_REQUIRED_RESOURCES, null);
+ super.postConfigure(context);
+ }
/* ------------------------------------------------------------ */
/**
@@ -137,12 +146,34 @@ public class OSGiWebInfConfiguration extends WebInfConfiguration
if (webInfJars != null)
mergedResources.addAll(webInfJars);
- //add fragment jars as if in WEB-INF/lib of the associated webapp
- Bundle[] fragments = PackageAdminServiceTracker.INSTANCE.getFragmentsAndRequiredBundles((Bundle)context.getAttribute(OSGiWebappConstants.JETTY_OSGI_BUNDLE));
- for (Bundle frag : fragments)
+ //add fragment jars and any Required-Bundles as if in WEB-INF/lib of the associated webapp
+ Bundle[] bundles = PackageAdminServiceTracker.INSTANCE.getFragmentsAndRequiredBundles((Bundle)context.getAttribute(OSGiWebappConstants.JETTY_OSGI_BUNDLE));
+ if (bundles != null && bundles.length > 0)
{
- File fragFile = BundleFileLocatorHelperFactory.getFactory().getHelper().getBundleInstallLocation(frag);
- mergedResources.add(Resource.newResource(fragFile.toURI()));
+ Set<Bundle> fragsAndReqsBundles = (Set<Bundle>)context.getAttribute(FRAGMENT_AND_REQUIRED_BUNDLES);
+ if (fragsAndReqsBundles == null)
+ {
+ fragsAndReqsBundles = new HashSet<Bundle>();
+ context.setAttribute(FRAGMENT_AND_REQUIRED_BUNDLES, fragsAndReqsBundles);
+ }
+
+ Set<Resource> fragsAndReqsResources = (Set<Resource>)context.getAttribute(FRAGMENT_AND_REQUIRED_RESOURCES);
+ if (fragsAndReqsResources == null)
+ {
+ fragsAndReqsResources = new HashSet<Resource>();
+ context.setAttribute(FRAGMENT_AND_REQUIRED_RESOURCES, fragsAndReqsResources);
+ }
+
+ for (Bundle b : bundles)
+ {
+ //add to context attribute storing associated fragments and required bundles
+ fragsAndReqsBundles.add(b);
+ File f = BundleFileLocatorHelperFactory.getFactory().getHelper().getBundleInstallLocation(b);
+ Resource r = Resource.newResource(f.toURI());
+ //add to convenience context attribute storing fragments and required bundles as Resources
+ fragsAndReqsResources.add(r);
+ mergedResources.add(r);
+ }
}
return mergedResources;
@@ -165,9 +196,8 @@ public class OSGiWebInfConfiguration extends WebInfConfiguration
Bundle bundle = (Bundle)context.getAttribute(OSGiWebappConstants.JETTY_OSGI_BUNDLE);
if (bundle != null)
{
- //TODO anything we need to do to improve PackageAdminServiceTracker?
- Bundle[] fragments = PackageAdminServiceTracker.INSTANCE.getFragmentsAndRequiredBundles(bundle);
- if (fragments != null && fragments.length != 0)
+ Set<Bundle> fragments = (Set<Bundle>)context.getAttribute(FRAGMENT_AND_REQUIRED_BUNDLES);
+ if (fragments != null && !fragments.isEmpty())
{
// sorted extra resource base found in the fragments.
// the resources are either overriding the resourcebase found in the
diff --git a/jetty-osgi/jetty-osgi-httpservice/pom.xml b/jetty-osgi/jetty-osgi-httpservice/pom.xml
index 4e98ff781d..812e72a05c 100644
--- a/jetty-osgi/jetty-osgi-httpservice/pom.xml
+++ b/jetty-osgi/jetty-osgi-httpservice/pom.xml
@@ -2,7 +2,7 @@
<parent>
<groupId>org.eclipse.jetty.osgi</groupId>
<artifactId>jetty-osgi-project</artifactId>
- <version>9.2.2-SNAPSHOT</version>
+ <version>9.2.3-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>jetty-httpservice</artifactId>
diff --git a/jetty-osgi/jetty-osgi-httpservice/src/main/java/org/eclipse/jetty/osgi/httpservice/HttpServiceErrorHandlerHelper.java b/jetty-osgi/jetty-osgi-httpservice/src/main/java/org/eclipse/jetty/osgi/httpservice/HttpServiceErrorHandlerHelper.java
index 35f186681f..f8fdc636f8 100644
--- a/jetty-osgi/jetty-osgi-httpservice/src/main/java/org/eclipse/jetty/osgi/httpservice/HttpServiceErrorHandlerHelper.java
+++ b/jetty-osgi/jetty-osgi-httpservice/src/main/java/org/eclipse/jetty/osgi/httpservice/HttpServiceErrorHandlerHelper.java
@@ -30,16 +30,16 @@ import javax.servlet.http.HttpServlet;
*/
public class HttpServiceErrorHandlerHelper
{
- private static HttpServlet _customErrorHandler;
+ private static HttpServlet _customErrorHandler;
- public static HttpServlet getCustomErrorHandler()
- {
- return _customErrorHandler;
- }
-
- public static void setHttpServiceErrorHandler(HttpServlet servlet)
- {
- _customErrorHandler = servlet;
- }
-
+ public static HttpServlet getCustomErrorHandler()
+ {
+ return _customErrorHandler;
+ }
+
+ public static void setHttpServiceErrorHandler(HttpServlet servlet)
+ {
+ _customErrorHandler = servlet;
+ }
+
}
diff --git a/jetty-osgi/jetty-osgi-httpservice/src/main/java/org/eclipse/jetty/osgi/httpservice/HttpServiceErrorPageErrorHandler.java b/jetty-osgi/jetty-osgi-httpservice/src/main/java/org/eclipse/jetty/osgi/httpservice/HttpServiceErrorPageErrorHandler.java
index 1b08f9b13a..e9ebc85562 100644
--- a/jetty-osgi/jetty-osgi-httpservice/src/main/java/org/eclipse/jetty/osgi/httpservice/HttpServiceErrorPageErrorHandler.java
+++ b/jetty-osgi/jetty-osgi-httpservice/src/main/java/org/eclipse/jetty/osgi/httpservice/HttpServiceErrorPageErrorHandler.java
@@ -35,46 +35,46 @@ import org.eclipse.jetty.servlet.ErrorPageErrorHandler;
public class HttpServiceErrorPageErrorHandler extends ErrorPageErrorHandler
{
- private static HttpServiceErrorPageErrorHandler INSTANCE;
-
- public static HttpServiceErrorPageErrorHandler getInstance()
- {
- return INSTANCE;
- }
-
- public HttpServiceErrorPageErrorHandler()
- {
- INSTANCE = this;
- }
+ private static HttpServiceErrorPageErrorHandler INSTANCE;
+
+ public static HttpServiceErrorPageErrorHandler getInstance()
+ {
+ return INSTANCE;
+ }
+
+ public HttpServiceErrorPageErrorHandler()
+ {
+ INSTANCE = this;
+ }
- @Override
- public void handle(String target, Request baseRequest,
- HttpServletRequest request, HttpServletResponse response)
- throws IOException {
- if (HttpServiceErrorHandlerHelper.getCustomErrorHandler() != null)
- {
- try
- {
- HttpServiceErrorHandlerHelper.getCustomErrorHandler().service(request, response);
- }
- catch (ServletException e)
- {
- //well
- }
- }
- if (!response.isCommitted())
- {
- super.handle(target, baseRequest, request, response);
- }
- }
+ @Override
+ public void handle(String target, Request baseRequest,
+ HttpServletRequest request, HttpServletResponse response)
+ throws IOException {
+ if (HttpServiceErrorHandlerHelper.getCustomErrorHandler() != null)
+ {
+ try
+ {
+ HttpServiceErrorHandlerHelper.getCustomErrorHandler().service(request, response);
+ }
+ catch (ServletException e)
+ {
+ //well
+ }
+ }
+ if (!response.isCommitted())
+ {
+ super.handle(target, baseRequest, request, response);
+ }
+ }
- @Override
- protected void doStop() throws Exception
- {
- INSTANCE = null;
- super.doStop();
- }
-
-
-
+ @Override
+ protected void doStop() throws Exception
+ {
+ INSTANCE = null;
+ super.doStop();
+ }
+
+
+
}
diff --git a/jetty-osgi/jetty-osgi-npn/pom.xml b/jetty-osgi/jetty-osgi-npn/pom.xml
index d7b2b0fa4f..1c96b56bb8 100644
--- a/jetty-osgi/jetty-osgi-npn/pom.xml
+++ b/jetty-osgi/jetty-osgi-npn/pom.xml
@@ -2,7 +2,7 @@
<parent>
<groupId>org.eclipse.jetty.osgi</groupId>
<artifactId>jetty-osgi-project</artifactId>
- <version>9.2.2-SNAPSHOT</version>
+ <version>9.2.3-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>jetty-osgi-npn</artifactId>
diff --git a/jetty-osgi/pom.xml b/jetty-osgi/pom.xml
index 6ed12b2fbd..f7c3f8e47b 100644
--- a/jetty-osgi/pom.xml
+++ b/jetty-osgi/pom.xml
@@ -3,7 +3,7 @@
<parent>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-project</artifactId>
- <version>9.2.2-SNAPSHOT</version>
+ <version>9.2.3-SNAPSHOT</version>
</parent>
<groupId>org.eclipse.jetty.osgi</groupId>
<artifactId>jetty-osgi-project</artifactId>
diff --git a/jetty-osgi/test-jetty-osgi-context/pom.xml b/jetty-osgi/test-jetty-osgi-context/pom.xml
index cc53094969..73f9efdac6 100644
--- a/jetty-osgi/test-jetty-osgi-context/pom.xml
+++ b/jetty-osgi/test-jetty-osgi-context/pom.xml
@@ -2,7 +2,7 @@
<parent>
<groupId>org.eclipse.jetty.osgi</groupId>
<artifactId>jetty-osgi-project</artifactId>
- <version>9.2.2-SNAPSHOT</version>
+ <version>9.2.3-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>test-jetty-osgi-context</artifactId>
diff --git a/jetty-osgi/test-jetty-osgi-webapp/pom.xml b/jetty-osgi/test-jetty-osgi-webapp/pom.xml
index 3bd52bbbb7..3db9ea9df3 100644
--- a/jetty-osgi/test-jetty-osgi-webapp/pom.xml
+++ b/jetty-osgi/test-jetty-osgi-webapp/pom.xml
@@ -2,7 +2,7 @@
<parent>
<groupId>org.eclipse.jetty.osgi</groupId>
<artifactId>jetty-osgi-project</artifactId>
- <version>9.2.2-SNAPSHOT</version>
+ <version>9.2.3-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>
<modelVersion>4.0.0</modelVersion>
diff --git a/jetty-osgi/test-jetty-osgi/pom.xml b/jetty-osgi/test-jetty-osgi/pom.xml
index 0cb6a7e40b..6b545473d5 100644
--- a/jetty-osgi/test-jetty-osgi/pom.xml
+++ b/jetty-osgi/test-jetty-osgi/pom.xml
@@ -2,7 +2,7 @@
<parent>
<groupId>org.eclipse.jetty.osgi</groupId>
<artifactId>jetty-osgi-project</artifactId>
- <version>9.2.2-SNAPSHOT</version>
+ <version>9.2.3-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>
<modelVersion>4.0.0</modelVersion>
@@ -164,24 +164,10 @@
<dependency>
<groupId>org.apache.aries.spifly</groupId>
<artifactId>org.apache.aries.spifly.dynamic.bundle</artifactId>
- <version>1.0.0</version>
+ <version>1.0.1</version>
<scope>test</scope>
</dependency>
- <dependency>
- <groupId>org.ow2.asm</groupId>
- <artifactId>asm</artifactId>
- <version>4.1</version>
- </dependency>
- <dependency>
- <groupId>org.ow2.asm</groupId>
- <artifactId>asm-commons</artifactId>
- <version>4.1</version>
- </dependency>
- <dependency>
- <groupId>org.ow2.asm</groupId>
- <artifactId>asm-tree</artifactId>
- <version>4.1</version>
- </dependency>
+
<!-- Jetty Deps -->
@@ -189,20 +175,6 @@
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-annotations</artifactId>
<scope>runtime</scope>
- <exclusions>
- <exclusion>
- <groupId>org.ow2.asm</groupId>
- <artifactId>asm</artifactId>
- </exclusion>
- <exclusion>
- <groupId>org.ow2.asm</groupId>
- <artifactId>asm-commons</artifactId>
- </exclusion>
- <exclusion>
- <groupId>org.ow2.asm</groupId>
- <artifactId>asm-tree</artifactId>
- </exclusion>
- </exclusions>
</dependency>
<dependency>
<groupId>org.eclipse.jetty</groupId>
@@ -362,31 +334,6 @@
</dependency>
<!-- Eclipse OSGi Deps -->
-<!--
- <dependency>
- <groupId>org.eclipse.osgi</groupId>
- <artifactId>org.eclipse.osgi</artifactId>
- <scope>runtime</scope>
- </dependency>
- <dependency>
- <groupId>org.eclipse.osgi</groupId>
- <artifactId>org.eclipse.osgi.services</artifactId>
- <scope>runtime</scope>
- <exclusions>
- <exclusion>
- <groupId>javax.servlet</groupId>
- <artifactId>servlet-api</artifactId>
- </exclusion>
- </exclusions>
- </dependency>
- <dependency>
- <groupId>org.eclipse.equinox.http</groupId>
- <artifactId>servlet</artifactId>
- <scope>runtime</scope>
- </dependency>
-
--->
-
<dependency>
<groupId>org.eclipse.jetty</groupId>
<artifactId>test-jetty-webapp</artifactId>
diff --git a/jetty-osgi/test-jetty-osgi/src/test/java/org/eclipse/jetty/osgi/test/TestJettyOSGiBootCore.java b/jetty-osgi/test-jetty-osgi/src/test/java/org/eclipse/jetty/osgi/test/TestJettyOSGiBootCore.java
index d31760d79f..2565c5be95 100644
--- a/jetty-osgi/test-jetty-osgi/src/test/java/org/eclipse/jetty/osgi/test/TestJettyOSGiBootCore.java
+++ b/jetty-osgi/test-jetty-osgi/src/test/java/org/eclipse/jetty/osgi/test/TestJettyOSGiBootCore.java
@@ -31,13 +31,12 @@ import javax.inject.Inject;
import org.junit.Ignore;
import org.junit.Test;
import org.junit.runner.RunWith;
+import org.ops4j.pax.exam.Configuration;
import org.ops4j.pax.exam.CoreOptions;
import org.ops4j.pax.exam.MavenUtils;
import org.ops4j.pax.exam.Option;
-import org.ops4j.pax.exam.Configuration;
import org.ops4j.pax.exam.junit.PaxExam;
import org.ops4j.pax.exam.options.MavenUrlReference.VersionResolver;
-import org.osgi.framework.Bundle;
import org.osgi.framework.BundleContext;
@@ -64,7 +63,7 @@ public class TestJettyOSGiBootCore
options.addAll(Arrays.asList(options(systemProperty("pax.exam.logging").value("none"))));
options.addAll(Arrays.asList(options(systemProperty("org.ops4j.pax.logging.DefaultServiceLog.level").value(LOG_LEVEL))));
options.addAll(Arrays.asList(options(systemProperty("org.eclipse.jetty.LEVEL").value(LOG_LEVEL))));
-
+ options.addAll(Arrays.asList(options(systemProperty("org.eclipse.jetty.annotations.LEVEL").value("DEBUG"))));
return options.toArray(new Option[options.size()]);
}
@@ -82,20 +81,12 @@ public class TestJettyOSGiBootCore
public static List<Option> coreJettyDependencies()
{
List<Option> res = new ArrayList<Option>();
-
- String jdk = System.getProperty("java.version");
- int firstdot = jdk.indexOf(".");
- jdk = jdk.substring(0,firstdot+2);
- double version = Double.parseDouble(jdk);
- if (version < 1.8)
- {
- res.add(mavenBundle().groupId( "org.ow2.asm" ).artifactId( "asm" ).versionAsInProject().start());
- res.add(mavenBundle().groupId( "org.ow2.asm" ).artifactId( "asm-commons" ).versionAsInProject().start());
- res.add(mavenBundle().groupId( "org.ow2.asm" ).artifactId( "asm-tree" ).versionAsInProject().start());
- res.add(mavenBundle().groupId( "org.apache.aries" ).artifactId( "org.apache.aries.util" ).version("1.0.0").start());
- res.add(mavenBundle().groupId( "org.apache.aries.spifly" ).artifactId( "org.apache.aries.spifly.dynamic.bundle" ).version("1.0.0").start());
- }
+ res.add(mavenBundle().groupId( "org.ow2.asm" ).artifactId( "asm" ).versionAsInProject().start());
+ res.add(mavenBundle().groupId( "org.ow2.asm" ).artifactId( "asm-commons" ).versionAsInProject().start());
+ res.add(mavenBundle().groupId( "org.ow2.asm" ).artifactId( "asm-tree" ).versionAsInProject().start());
+ res.add(mavenBundle().groupId( "org.apache.aries" ).artifactId( "org.apache.aries.util" ).versionAsInProject().start());
+ res.add(mavenBundle().groupId( "org.apache.aries.spifly" ).artifactId( "org.apache.aries.spifly.dynamic.bundle" ).versionAsInProject().start());
res.add(mavenBundle().groupId( "javax.servlet" ).artifactId( "javax.servlet-api" ).versionAsInProject().noStart());
res.add(mavenBundle().groupId( "javax.annotation" ).artifactId( "javax.annotation-api" ).versionAsInProject().noStart());
@@ -119,10 +110,7 @@ public class TestJettyOSGiBootCore
res.add(mavenBundle().groupId( "org.eclipse.jetty" ).artifactId( "jetty-client" ).versionAsInProject().noStart());
res.add(mavenBundle().groupId( "org.eclipse.jetty" ).artifactId( "jetty-jndi" ).versionAsInProject().noStart());
res.add(mavenBundle().groupId( "org.eclipse.jetty" ).artifactId( "jetty-plus" ).versionAsInProject().noStart());
- if (version < 1.8)
- {
- res.add(mavenBundle().groupId( "org.eclipse.jetty" ).artifactId( "jetty-annotations" ).versionAsInProject().start());
- }
+ res.add(mavenBundle().groupId( "org.eclipse.jetty" ).artifactId( "jetty-annotations" ).versionAsInProject().start());
res.add(mavenBundle().groupId( "org.eclipse.jetty.websocket" ).artifactId( "websocket-api" ).versionAsInProject().noStart());
res.add(mavenBundle().groupId( "org.eclipse.jetty.websocket" ).artifactId( "websocket-common" ).versionAsInProject().noStart());
res.add(mavenBundle().groupId( "org.eclipse.jetty.websocket" ).artifactId( "websocket-servlet" ).versionAsInProject().noStart());
diff --git a/jetty-overlay-deployer/src/test/java/org/eclipse/jetty/overlays/OverlayServer.java b/jetty-overlay-deployer/src/test/java/org/eclipse/jetty/overlays/OverlayServer.java
index 8a6f4e7f7a..c7cb7d977e 100644
--- a/jetty-overlay-deployer/src/test/java/org/eclipse/jetty/overlays/OverlayServer.java
+++ b/jetty-overlay-deployer/src/test/java/org/eclipse/jetty/overlays/OverlayServer.java
@@ -86,7 +86,7 @@ public class OverlayServer
server.setStopAtShutdown(true);
//server.setSendServerVersion(true);
- // Uncomment to work with JNDI examples
+ // Uncomment to work with JNDI examples
// new org.eclipse.jetty.plus.jndi.Transaction(new com.atomikos.icatch.jta.UserTransactionImp());
diff --git a/jetty-plus/pom.xml b/jetty-plus/pom.xml
index d31ca19071..6c556a9304 100644
--- a/jetty-plus/pom.xml
+++ b/jetty-plus/pom.xml
@@ -2,7 +2,7 @@
<parent>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-project</artifactId>
- <version>9.2.2-SNAPSHOT</version>
+ <version>9.2.3-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>jetty-plus</artifactId>
diff --git a/jetty-plus/src/main/java/org/eclipse/jetty/plus/annotation/ContainerInitializer.java b/jetty-plus/src/main/java/org/eclipse/jetty/plus/annotation/ContainerInitializer.java
index 321a9ab7f5..8176916cc5 100644
--- a/jetty-plus/src/main/java/org/eclipse/jetty/plus/annotation/ContainerInitializer.java
+++ b/jetty-plus/src/main/java/org/eclipse/jetty/plus/annotation/ContainerInitializer.java
@@ -19,7 +19,6 @@
package org.eclipse.jetty.plus.annotation;
import java.util.ArrayList;
-import java.util.Arrays;
import java.util.Collections;
import java.util.HashSet;
import java.util.List;
@@ -158,7 +157,7 @@ public class ContainerInitializer
interested.add(c.getName());
}
- return String.format("ContainerInitializer{%s,interested=%s,applicable=%s,annotated=%s}",_target.getClass().getName(),interested,_applicableTypeNames,_annotatedTypeNames);
+ return String.format("ContainerInitializer{%s,interested=%s,applicable=%s,annotated=%s}",_target.getClass().getName(),interested,_applicableTypeNames,_annotatedTypeNames);
}
public void resolveClasses(WebAppContext context, Map<String, Set<String>> classMap)
diff --git a/jetty-plus/src/main/java/org/eclipse/jetty/plus/security/DataSourceLoginService.java b/jetty-plus/src/main/java/org/eclipse/jetty/plus/security/DataSourceLoginService.java
index b315682f8f..1c8edde16b 100644
--- a/jetty-plus/src/main/java/org/eclipse/jetty/plus/security/DataSourceLoginService.java
+++ b/jetty-plus/src/main/java/org/eclipse/jetty/plus/security/DataSourceLoginService.java
@@ -41,12 +41,11 @@ import org.eclipse.jetty.server.Server;
import org.eclipse.jetty.server.UserIdentity;
import org.eclipse.jetty.util.log.Log;
import org.eclipse.jetty.util.log.Logger;
-import org.eclipse.jetty.util.security.Password;
+import org.eclipse.jetty.util.security.Credential;
/**
*
- * //TODO JASPI cf JDBCLoginService
* DataSourceUserRealm
*
* Obtain user/password/role information from a database
@@ -70,6 +69,7 @@ public class DataSourceLoginService extends MappedLoginService
private String _userRoleTableUserKey = "user_id";
private String _userRoleTableRoleKey = "role_id";
private int _cacheMs = 30000;
+ private long _lastPurge = 0;
private String _userSql;
private String _roleSql;
private boolean _createTables = false;
@@ -282,7 +282,9 @@ public class DataSourceLoginService extends MappedLoginService
protected void loadUsers()
{
}
-
+
+
+
/* ------------------------------------------------------------ */
/** Load user's info from database.
*
@@ -293,9 +295,8 @@ public class DataSourceLoginService extends MappedLoginService
{
try
{
- initDb();
try (Connection connection = getConnection();
- PreparedStatement statement1 = connection.prepareStatement(_userSql))
+ PreparedStatement statement1 = connection.prepareStatement(_userSql))
{
statement1.setObject(1, userName);
try (ResultSet rs1 = statement1.executeQuery())
@@ -311,10 +312,12 @@ public class DataSourceLoginService extends MappedLoginService
try (ResultSet rs2 = statement2.executeQuery())
{
while (rs2.next())
+ {
roles.add(rs2.getString(_roleTableRoleField));
+ }
}
}
- return putUser(userName,new Password(credentials), roles.toArray(new String[roles.size()]));
+ return putUser(userName, Credential.getCredential(credentials), roles.toArray(new String[roles.size()]));
}
}
}
@@ -329,6 +332,22 @@ public class DataSourceLoginService extends MappedLoginService
}
return null;
}
+
+
+
+ /* ------------------------------------------------------------ */
+ @Override
+ public UserIdentity login(String username, Object credentials)
+ {
+ long now = System.currentTimeMillis();
+ if (now - _lastPurge > _cacheMs || _cacheMs == 0)
+ {
+ _users.clear();
+ _lastPurge = now;
+ }
+
+ return super.login(username,credentials);
+ }
/* ------------------------------------------------------------ */
/**
@@ -347,7 +366,7 @@ public class DataSourceLoginService extends MappedLoginService
InitialContext ic = new InitialContext();
assert ic!=null;
- //TODO webapp scope?
+ //TODO Should we try webapp scope too?
//try finding the datasource in the Server scope
if (_server != null)
diff --git a/jetty-plus/src/main/java/org/eclipse/jetty/plus/webapp/EnvConfiguration.java b/jetty-plus/src/main/java/org/eclipse/jetty/plus/webapp/EnvConfiguration.java
index 068c03b0af..ed609ba2a4 100644
--- a/jetty-plus/src/main/java/org/eclipse/jetty/plus/webapp/EnvConfiguration.java
+++ b/jetty-plus/src/main/java/org/eclipse/jetty/plus/webapp/EnvConfiguration.java
@@ -40,7 +40,6 @@ import org.eclipse.jetty.plus.jndi.NamingEntryUtil;
import org.eclipse.jetty.util.log.Log;
import org.eclipse.jetty.util.log.Logger;
import org.eclipse.jetty.webapp.AbstractConfiguration;
-import org.eclipse.jetty.webapp.Configuration;
import org.eclipse.jetty.webapp.WebAppContext;
import org.eclipse.jetty.xml.XmlConfiguration;
diff --git a/jetty-proxy/pom.xml b/jetty-proxy/pom.xml
index 72c5202802..223f976626 100644
--- a/jetty-proxy/pom.xml
+++ b/jetty-proxy/pom.xml
@@ -2,7 +2,7 @@
<parent>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-project</artifactId>
- <version>9.2.2-SNAPSHOT</version>
+ <version>9.2.3-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>jetty-proxy</artifactId>
diff --git a/jetty-proxy/src/main/java/org/eclipse/jetty/proxy/AsyncProxyServlet.java b/jetty-proxy/src/main/java/org/eclipse/jetty/proxy/AsyncProxyServlet.java
index 6ebc85ca21..29b34f378f 100644
--- a/jetty-proxy/src/main/java/org/eclipse/jetty/proxy/AsyncProxyServlet.java
+++ b/jetty-proxy/src/main/java/org/eclipse/jetty/proxy/AsyncProxyServlet.java
@@ -60,7 +60,8 @@ public class AsyncProxyServlet extends ProxyServlet
{
try
{
- _log.debug("{} proxying content to downstream: {} bytes", getRequestId(request), length);
+ if (_log.isDebugEnabled())
+ _log.debug("{} proxying content to downstream: {} bytes", getRequestId(request), length);
StreamWriter writeListener = (StreamWriter)request.getAttribute(WRITE_LISTENER_ATTRIBUTE);
if (writeListener == null)
{
@@ -84,7 +85,7 @@ public class AsyncProxyServlet extends ProxyServlet
catch (Throwable x)
{
callback.failed(x);
- onResponseFailure(request, response, proxyResponse, x);
+ proxyResponse.abort(x);
}
}
@@ -130,24 +131,30 @@ public class AsyncProxyServlet extends ProxyServlet
{
int requestId = getRequestId(request);
ServletInputStream input = request.getInputStream();
- _log.debug("{} asynchronous read start on {}", requestId, input);
+ if (_log.isDebugEnabled())
+ _log.debug("{} asynchronous read start on {}", requestId, input);
// First check for isReady() because it has
// side effects, and then for isFinished().
while (input.isReady() && !input.isFinished())
{
int read = input.read(buffer);
- _log.debug("{} asynchronous read {} bytes on {}", requestId, read, input);
+ if (_log.isDebugEnabled())
+ _log.debug("{} asynchronous read {} bytes on {}", requestId, read, input);
if (read > 0)
{
- _log.debug("{} proxying content to upstream: {} bytes", requestId, read);
+ if (_log.isDebugEnabled())
+ _log.debug("{} proxying content to upstream: {} bytes", requestId, read);
onRequestContent(proxyRequest, request, provider, buffer, 0, read, this);
// Do not call isReady() so that we can apply backpressure.
break;
}
}
if (!input.isFinished())
- _log.debug("{} asynchronous read pending on {}", requestId, input);
+ {
+ if (_log.isDebugEnabled())
+ _log.debug("{} asynchronous read pending on {}", requestId, input);
+ }
}
protected void onRequestContent(Request proxyRequest, HttpServletRequest request, DeferredContentProvider provider, byte[] buffer, int offset, int length, Callback callback)
@@ -158,7 +165,8 @@ public class AsyncProxyServlet extends ProxyServlet
@Override
public void onAllDataRead() throws IOException
{
- _log.debug("{} proxying content to upstream completed", getRequestId(request));
+ if (_log.isDebugEnabled())
+ _log.debug("{} proxying content to upstream completed", getRequestId(request));
provider.close();
}
@@ -225,23 +233,27 @@ public class AsyncProxyServlet extends ProxyServlet
if (state == WriteState.READY)
{
// There is data to write.
- _log.debug("{} asynchronous write start of {} bytes on {}", requestId, length, output);
+ if (_log.isDebugEnabled())
+ _log.debug("{} asynchronous write start of {} bytes on {}", requestId, length, output);
output.write(buffer, offset, length);
state = WriteState.PENDING;
if (output.isReady())
{
- _log.debug("{} asynchronous write of {} bytes completed on {}", requestId, length, output);
+ if (_log.isDebugEnabled())
+ _log.debug("{} asynchronous write of {} bytes completed on {}", requestId, length, output);
complete();
}
else
{
- _log.debug("{} asynchronous write of {} bytes pending on {}", requestId, length, output);
+ if (_log.isDebugEnabled())
+ _log.debug("{} asynchronous write of {} bytes pending on {}", requestId, length, output);
}
}
else if (state == WriteState.PENDING)
{
// The write blocked but is now complete.
- _log.debug("{} asynchronous write of {} bytes completing on {}", requestId, length, output);
+ if (_log.isDebugEnabled())
+ _log.debug("{} asynchronous write of {} bytes completing on {}", requestId, length, output);
complete();
}
else
@@ -267,8 +279,7 @@ public class AsyncProxyServlet extends ProxyServlet
@Override
public void onError(Throwable failure)
{
- HttpServletResponse response = (HttpServletResponse)request.getAsyncContext().getResponse();
- onResponseFailure(request, response, proxyResponse, failure);
+ proxyResponse.abort(failure);
}
}
diff --git a/jetty-proxy/src/main/java/org/eclipse/jetty/proxy/BalancerServlet.java b/jetty-proxy/src/main/java/org/eclipse/jetty/proxy/BalancerServlet.java
index 6877134521..ff4ae867db 100644
--- a/jetty-proxy/src/main/java/org/eclipse/jetty/proxy/BalancerServlet.java
+++ b/jetty-proxy/src/main/java/org/eclipse/jetty/proxy/BalancerServlet.java
@@ -26,12 +26,13 @@ import java.util.LinkedList;
import java.util.List;
import java.util.Set;
import java.util.concurrent.atomic.AtomicLong;
-
import javax.servlet.ServletException;
import javax.servlet.UnavailableException;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
+import org.eclipse.jetty.util.URIUtil;
+
public class BalancerServlet extends ProxyServlet
{
private static final String BALANCER_MEMBER_PREFIX = "balancerMember.";
@@ -86,7 +87,7 @@ public class BalancerServlet extends ProxyServlet
}
}
- private void initStickySessions() throws ServletException
+ private void initStickySessions()
{
_stickySessions = Boolean.parseBoolean(getServletConfig().getInitParameter("stickySessions"));
}
@@ -131,7 +132,8 @@ public class BalancerServlet extends ProxyServlet
protected URI rewriteURI(HttpServletRequest request)
{
BalancerMember balancerMember = selectBalancerMember(request);
- _log.debug("Selected {}", balancerMember);
+ if (_log.isDebugEnabled())
+ _log.debug("Selected {}", balancerMember);
String path = request.getRequestURI();
String query = request.getQueryString();
if (query != null)
@@ -219,17 +221,17 @@ public class BalancerServlet extends ProxyServlet
URI locationURI = URI.create(headerValue).normalize();
if (locationURI.isAbsolute() && isBackendLocation(locationURI))
{
- String newURI = request.getScheme() + "://" + request.getServerName() + ":" + request.getServerPort();
+ StringBuilder newURI = URIUtil.newURIBuilder(request.getScheme(), request.getServerName(), request.getServerPort());
String component = locationURI.getRawPath();
if (component != null)
- newURI += component;
+ newURI.append(component);
component = locationURI.getRawQuery();
if (component != null)
- newURI += "?" + component;
+ newURI.append('?').append(component);
component = locationURI.getRawFragment();
if (component != null)
- newURI += "#" + component;
- return URI.create(newURI).normalize().toString();
+ newURI.append('#').append(component);
+ return URI.create(newURI.toString()).normalize().toString();
}
}
return headerValue;
diff --git a/jetty-proxy/src/main/java/org/eclipse/jetty/proxy/ConnectHandler.java b/jetty-proxy/src/main/java/org/eclipse/jetty/proxy/ConnectHandler.java
index 14b2155b98..b43ce7338c 100644
--- a/jetty-proxy/src/main/java/org/eclipse/jetty/proxy/ConnectHandler.java
+++ b/jetty-proxy/src/main/java/org/eclipse/jetty/proxy/ConnectHandler.java
@@ -456,7 +456,8 @@ public class ConnectHandler extends HandlerWrapper
@Override
public Connection newConnection(SocketChannel channel, EndPoint endpoint, Object attachment) throws IOException
{
- ConnectHandler.LOG.debug("Connected to {}", channel.getRemoteAddress());
+ if (ConnectHandler.LOG.isDebugEnabled())
+ ConnectHandler.LOG.debug("Connected to {}", channel.getRemoteAddress());
ConnectContext connectContext = (ConnectContext)attachment;
UpstreamConnection connection = newUpstreamConnection(endpoint, connectContext);
connection.setInputBufferSize(getBufferSize());
diff --git a/jetty-proxy/src/main/java/org/eclipse/jetty/proxy/ProxyConnection.java b/jetty-proxy/src/main/java/org/eclipse/jetty/proxy/ProxyConnection.java
index f857294983..3a620f43a1 100644
--- a/jetty-proxy/src/main/java/org/eclipse/jetty/proxy/ProxyConnection.java
+++ b/jetty-proxy/src/main/java/org/eclipse/jetty/proxy/ProxyConnection.java
@@ -28,13 +28,13 @@ import org.eclipse.jetty.io.ByteBufferPool;
import org.eclipse.jetty.io.Connection;
import org.eclipse.jetty.io.EndPoint;
import org.eclipse.jetty.util.Callback;
-import org.eclipse.jetty.util.ForkInvoker;
+import org.eclipse.jetty.util.IteratingCallback;
import org.eclipse.jetty.util.log.Logger;
public abstract class ProxyConnection extends AbstractConnection
{
protected static final Logger LOG = ConnectHandler.LOG;
- private final ForkInvoker<Void> invoker = new ProxyForkInvoker();
+ private final IteratingCallback pipe = new ProxyIteratingCallback();
private final ByteBufferPool bufferPool;
private final ConcurrentMap<String, Object> context;
private Connection connection;
@@ -69,52 +69,7 @@ public abstract class ProxyConnection extends AbstractConnection
@Override
public void onFillable()
{
- final ByteBuffer buffer = getByteBufferPool().acquire(getInputBufferSize(), true);
- try
- {
- final int filled = read(getEndPoint(), buffer);
- if (LOG.isDebugEnabled())
- LOG.debug("{} filled {} bytes", this, filled);
- if (filled > 0)
- {
- write(getConnection().getEndPoint(), buffer, new Callback()
- {
- @Override
- public void succeeded()
- {
- if (LOG.isDebugEnabled())
- LOG.debug("{} wrote {} bytes", this, filled);
- bufferPool.release(buffer);
- invoker.invoke(null);
- }
-
- @Override
- public void failed(Throwable x)
- {
- LOG.debug(this + " failed to write " + filled + " bytes", x);
- bufferPool.release(buffer);
- connection.close();
- }
- });
- }
- else if (filled == 0)
- {
- bufferPool.release(buffer);
- fillInterested();
- }
- else
- {
- bufferPool.release(buffer);
- connection.getEndPoint().shutdownOutput();
- }
- }
- catch (IOException x)
- {
- LOG.debug(this + " could not fill", x);
- bufferPool.release(buffer);
- close();
- connection.close();
- }
+ pipe.iterate();
}
protected abstract int read(EndPoint endPoint, ByteBuffer buffer) throws IOException;
@@ -130,29 +85,74 @@ public abstract class ProxyConnection extends AbstractConnection
getEndPoint().getRemoteAddress().getPort());
}
- private class ProxyForkInvoker extends ForkInvoker<Void> implements Runnable
+ private class ProxyIteratingCallback extends IteratingCallback
{
- private ProxyForkInvoker()
+ private ByteBuffer buffer;
+ private int filled;
+
+ @Override
+ protected Action process() throws Exception
{
- super(4);
+ buffer = bufferPool.acquire(getInputBufferSize(), true);
+ try
+ {
+ int filled = this.filled = read(getEndPoint(), buffer);
+ if (LOG.isDebugEnabled())
+ LOG.debug("{} filled {} bytes", ProxyConnection.this, filled);
+ if (filled > 0)
+ {
+ write(connection.getEndPoint(), buffer, this);
+ return Action.SCHEDULED;
+ }
+ else if (filled == 0)
+ {
+ bufferPool.release(buffer);
+ fillInterested();
+ return Action.IDLE;
+ }
+ else
+ {
+ bufferPool.release(buffer);
+ connection.getEndPoint().shutdownOutput();
+ return Action.SUCCEEDED;
+ }
+ }
+ catch (IOException x)
+ {
+ if (LOG.isDebugEnabled())
+ LOG.debug(ProxyConnection.this + " could not fill", x);
+ disconnect();
+ return Action.SUCCEEDED;
+ }
}
@Override
- public void fork(Void arg)
+ public void succeeded()
{
- getExecutor().execute(this);
+ if (LOG.isDebugEnabled())
+ LOG.debug("{} wrote {} bytes", ProxyConnection.this, filled);
+ bufferPool.release(buffer);
+ super.succeeded();
}
-
+
@Override
- public void run()
+ protected void onCompleteSuccess()
{
- onFillable();
}
@Override
- public void call(Void arg)
+ protected void onCompleteFailure(Throwable x)
+ {
+ if (LOG.isDebugEnabled())
+ LOG.debug(ProxyConnection.this + " failed to write " + filled + " bytes", x);
+ disconnect();
+ }
+
+ private void disconnect()
{
- onFillable();
+ bufferPool.release(buffer);
+ ProxyConnection.this.close();
+ connection.close();
}
}
}
diff --git a/jetty-proxy/src/main/java/org/eclipse/jetty/proxy/ProxyServlet.java b/jetty-proxy/src/main/java/org/eclipse/jetty/proxy/ProxyServlet.java
index 7dbe2a9bb4..ed00af2564 100644
--- a/jetty-proxy/src/main/java/org/eclipse/jetty/proxy/ProxyServlet.java
+++ b/jetty-proxy/src/main/java/org/eclipse/jetty/proxy/ProxyServlet.java
@@ -201,7 +201,8 @@ public class ProxyServlet extends HttpServlet
}
catch (Exception x)
{
- _log.debug(x);
+ if (_log.isDebugEnabled())
+ _log.debug(x);
}
}
@@ -362,7 +363,8 @@ public class ProxyServlet extends HttpServlet
{
if (!_whiteList.contains(hostPort))
{
- _log.debug("Host {}:{} not whitelisted", host, port);
+ if (_log.isDebugEnabled())
+ _log.debug("Host {}:{} not whitelisted", host, port);
return false;
}
}
@@ -370,7 +372,8 @@ public class ProxyServlet extends HttpServlet
{
if (_blackList.contains(hostPort))
{
- _log.debug("Host {}:{} blacklisted", host, port);
+ if (_log.isDebugEnabled())
+ _log.debug("Host {}:{} blacklisted", host, port);
return false;
}
}
@@ -389,7 +392,8 @@ public class ProxyServlet extends HttpServlet
StringBuffer uri = request.getRequestURL();
if (request.getQueryString() != null)
uri.append("?").append(request.getQueryString());
- _log.debug("{} rewriting: {} -> {}", requestId, uri, rewrittenURI);
+ if (_log.isDebugEnabled())
+ _log.debug("{} rewriting: {} -> {}", requestId, uri, rewrittenURI);
}
if (rewrittenURI == null)
@@ -493,7 +497,8 @@ public class ProxyServlet extends HttpServlet
protected void onClientRequestFailure(Request proxyRequest, HttpServletRequest request, Throwable failure)
{
- _log.debug(getRequestId(request) + " client request failure", failure);
+ if (_log.isDebugEnabled())
+ _log.debug(getRequestId(request) + " client request failure", failure);
proxyRequest.abort(failure);
}
@@ -517,10 +522,6 @@ public class ProxyServlet extends HttpServlet
protected void onResponseHeaders(HttpServletRequest request, HttpServletResponse response, Response proxyResponse)
{
- // Clear the response headers in case it comes with predefined ones.
- for (String name : response.getHeaderNames())
- response.setHeader(name, null);
-
for (HttpField field : proxyResponse.getHeaders())
{
String headerName = field.getName();
@@ -540,7 +541,8 @@ public class ProxyServlet extends HttpServlet
{
try
{
- _log.debug("{} proxying content to downstream: {} bytes", getRequestId(request), length);
+ if (_log.isDebugEnabled())
+ _log.debug("{} proxying content to downstream: {} bytes", getRequestId(request), length);
response.getOutputStream().write(buffer, offset, length);
callback.succeeded();
}
@@ -552,16 +554,34 @@ public class ProxyServlet extends HttpServlet
protected void onResponseSuccess(HttpServletRequest request, HttpServletResponse response, Response proxyResponse)
{
- _log.debug("{} proxying successful", getRequestId(request));
+ if (_log.isDebugEnabled())
+ _log.debug("{} proxying successful", getRequestId(request));
AsyncContext asyncContext = request.getAsyncContext();
asyncContext.complete();
}
protected void onResponseFailure(HttpServletRequest request, HttpServletResponse response, Response proxyResponse, Throwable failure)
{
- _log.debug(getRequestId(request) + " proxying failed", failure);
- if (!response.isCommitted())
+ if (_log.isDebugEnabled())
+ _log.debug(getRequestId(request) + " proxying failed", failure);
+ if (response.isCommitted())
+ {
+ try
+ {
+ // Use Jetty specific behavior to close connection.
+ response.sendError(-1);
+ AsyncContext asyncContext = request.getAsyncContext();
+ asyncContext.complete();
+ }
+ catch (IOException x)
+ {
+ if (_log.isDebugEnabled())
+ _log.debug(getRequestId(request) + " could not close the connection", failure);
+ }
+ }
+ else
{
+ response.resetBuffer();
if (failure instanceof TimeoutException)
response.setStatus(HttpServletResponse.SC_GATEWAY_TIMEOUT);
else
@@ -674,7 +694,8 @@ public class ProxyServlet extends HttpServlet
String contextPath = config.getServletContext().getContextPath();
_prefix = _prefix == null ? contextPath : (contextPath + _prefix);
- proxyServlet._log.debug(config.getServletName() + " @ " + _prefix + " to " + _proxyTo);
+ if (proxyServlet._log.isDebugEnabled())
+ proxyServlet._log.debug(config.getServletName() + " @ " + _prefix + " to " + _proxyTo);
}
protected URI rewriteURI(HttpServletRequest request)
@@ -794,7 +815,8 @@ public class ProxyServlet extends HttpServlet
onResponseSuccess(request, response, result.getResponse());
else
onResponseFailure(request, response, result.getResponse(), result.getFailure());
- _log.debug("{} proxying complete", getRequestId(request));
+ if (_log.isDebugEnabled())
+ _log.debug("{} proxying complete", getRequestId(request));
}
}
@@ -819,7 +841,8 @@ public class ProxyServlet extends HttpServlet
@Override
protected ByteBuffer onRead(byte[] buffer, int offset, int length)
{
- _log.debug("{} proxying content to upstream: {} bytes", getRequestId(request), length);
+ if (_log.isDebugEnabled())
+ _log.debug("{} proxying content to upstream: {} bytes", getRequestId(request), length);
return onRequestContent(proxyRequest, request, buffer, offset, length);
}
diff --git a/jetty-proxy/src/test/java/org/eclipse/jetty/proxy/ProxyServletTest.java b/jetty-proxy/src/test/java/org/eclipse/jetty/proxy/ProxyServletTest.java
index 5884a14f82..40d99b06e6 100644
--- a/jetty-proxy/src/test/java/org/eclipse/jetty/proxy/ProxyServletTest.java
+++ b/jetty-proxy/src/test/java/org/eclipse/jetty/proxy/ProxyServletTest.java
@@ -19,8 +19,10 @@
package org.eclipse.jetty.proxy;
import java.io.ByteArrayOutputStream;
+import java.io.EOFException;
import java.io.IOException;
import java.io.InputStream;
+import java.io.InterruptedIOException;
import java.io.OutputStream;
import java.io.PrintWriter;
import java.net.ConnectException;
@@ -30,6 +32,7 @@ import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.StandardOpenOption;
import java.util.Arrays;
+import java.util.EnumSet;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
@@ -42,7 +45,14 @@ import java.util.zip.GZIPOutputStream;
import javax.servlet.AsyncContext;
import javax.servlet.AsyncEvent;
import javax.servlet.AsyncListener;
+import javax.servlet.DispatcherType;
+import javax.servlet.Filter;
+import javax.servlet.FilterChain;
+import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
+import javax.servlet.ServletOutputStream;
+import javax.servlet.ServletRequest;
+import javax.servlet.ServletResponse;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
@@ -55,11 +65,16 @@ import org.eclipse.jetty.client.api.ContentResponse;
import org.eclipse.jetty.client.api.Request;
import org.eclipse.jetty.client.api.Response;
import org.eclipse.jetty.client.api.Result;
+import org.eclipse.jetty.client.http.HttpDestinationOverHTTP;
import org.eclipse.jetty.client.util.BufferingResponseListener;
import org.eclipse.jetty.client.util.BytesContentProvider;
+import org.eclipse.jetty.client.util.InputStreamResponseListener;
import org.eclipse.jetty.http.HttpMethod;
+import org.eclipse.jetty.server.HttpConfiguration;
+import org.eclipse.jetty.server.HttpConnectionFactory;
import org.eclipse.jetty.server.Server;
import org.eclipse.jetty.server.ServerConnector;
+import org.eclipse.jetty.servlet.FilterHolder;
import org.eclipse.jetty.servlet.ServletContextHandler;
import org.eclipse.jetty.servlet.ServletHolder;
import org.eclipse.jetty.toolchain.test.MavenTestingUtils;
@@ -95,6 +110,7 @@ public class ProxyServletTest
private HttpClient client;
private Server proxy;
private ServerConnector proxyConnector;
+ private ServletContextHandler proxyContext;
private ProxyServlet proxyServlet;
private Server server;
private ServerConnector serverConnector;
@@ -112,13 +128,20 @@ public class ProxyServletTest
private void prepareProxy(Map<String, String> initParams) throws Exception
{
proxy = new Server();
- proxyConnector = new ServerConnector(proxy);
+
+ HttpConfiguration configuration = new HttpConfiguration();
+ configuration.setSendDateHeader(false);
+ configuration.setSendServerVersion(false);
+ String value = initParams.get("outputBufferSize");
+ if (value != null)
+ configuration.setOutputBufferSize(Integer.valueOf(value));
+ proxyConnector = new ServerConnector(proxy, new HttpConnectionFactory(configuration));
proxy.addConnector(proxyConnector);
- ServletContextHandler proxyCtx = new ServletContextHandler(proxy, "/", true, false);
+ proxyContext = new ServletContextHandler(proxy, "/", true, false);
ServletHolder proxyServletHolder = new ServletHolder(proxyServlet);
proxyServletHolder.setInitParameters(initParams);
- proxyCtx.addServlet(proxyServletHolder, "/*");
+ proxyContext.addServlet(proxyServletHolder, "/*");
proxy.start();
@@ -331,7 +354,7 @@ public class ProxyServletTest
ContentResponse response = client.newRequest("localhost", serverConnector.getLocalPort())
.method(HttpMethod.POST)
.content(new BytesContentProvider(content))
- .timeout(555, TimeUnit.SECONDS)
+ .timeout(5, TimeUnit.SECONDS)
.send();
Assert.assertEquals(200, response.getStatus());
@@ -899,5 +922,184 @@ public class ProxyServletTest
Assert.assertTrue(response3.getHeaders().containsKey(PROXIED_HEADER));
}
+ @Test
+ public void testProxyRequestFailureInTheMiddleOfProxyingSmallContent() throws Exception
+ {
+ final long proxyTimeout = 1000;
+ Map<String, String> proxyParams = new HashMap<>();
+ proxyParams.put("timeout", String.valueOf(proxyTimeout));
+ prepareProxy(proxyParams);
+
+ final CountDownLatch chunk1Latch = new CountDownLatch(1);
+ final int chunk1 = 'q';
+ final int chunk2 = 'w';
+ prepareServer(new HttpServlet()
+ {
+ @Override
+ protected void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException
+ {
+ ServletOutputStream output = response.getOutputStream();
+ output.write(chunk1);
+ response.flushBuffer();
+
+ // Wait for the client to receive this chunk.
+ await(chunk1Latch, 5000);
+
+ // Send second chunk, must not be received by proxy.
+ output.write(chunk2);
+ }
+
+ private boolean await(CountDownLatch latch, long ms) throws IOException
+ {
+ try
+ {
+ return latch.await(ms, TimeUnit.MILLISECONDS);
+ }
+ catch (InterruptedException x)
+ {
+ throw new InterruptedIOException();
+ }
+ }
+ });
+
+ HttpClient client = prepareClient();
+ InputStreamResponseListener listener = new InputStreamResponseListener();
+ int port = serverConnector.getLocalPort();
+ client.newRequest("localhost", port).send(listener);
+
+ // Make the proxy request fail; given the small content, the
+ // proxy-to-client response is not committed yet so it will be reset.
+ TimeUnit.MILLISECONDS.sleep(2 * proxyTimeout);
+
+ Response response = listener.get(5, TimeUnit.SECONDS);
+ Assert.assertEquals(504, response.getStatus());
+
+ // Make sure there is no content, as the proxy-to-client response has been reset.
+ InputStream input = listener.getInputStream();
+ Assert.assertEquals(-1, input.read());
+
+ chunk1Latch.countDown();
+
+ // Result succeeds because a 504 is a valid HTTP response.
+ Result result = listener.await(5, TimeUnit.SECONDS);
+ Assert.assertTrue(result.isSucceeded());
+
+ // Make sure the proxy does not receive chunk2.
+ Assert.assertEquals(-1, input.read());
+
+ HttpDestinationOverHTTP destination = (HttpDestinationOverHTTP)client.getDestination("http", "localhost", port);
+ Assert.assertEquals(0, destination.getConnectionPool().getIdleConnections().size());
+ }
+
+ @Test
+ public void testProxyRequestFailureInTheMiddleOfProxyingBigContent() throws Exception
+ {
+ final long proxyTimeout = 1000;
+ int outputBufferSize = 1024;
+ Map<String, String> proxyParams = new HashMap<>();
+ proxyParams.put("timeout", String.valueOf(proxyTimeout));
+ proxyParams.put("outputBufferSize", String.valueOf(outputBufferSize));
+ prepareProxy(proxyParams);
+
+ final CountDownLatch chunk1Latch = new CountDownLatch(1);
+ final byte[] chunk1 = new byte[outputBufferSize];
+ new Random().nextBytes(chunk1);
+ final int chunk2 = 'w';
+ prepareServer(new HttpServlet()
+ {
+ @Override
+ protected void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException
+ {
+ ServletOutputStream output = response.getOutputStream();
+ output.write(chunk1);
+ response.flushBuffer();
+
+ // Wait for the client to receive this chunk.
+ await(chunk1Latch, 5000);
+
+ // Send second chunk, must not be received by proxy.
+ output.write(chunk2);
+ }
+
+ private boolean await(CountDownLatch latch, long ms) throws IOException
+ {
+ try
+ {
+ return latch.await(ms, TimeUnit.MILLISECONDS);
+ }
+ catch (InterruptedException x)
+ {
+ throw new InterruptedIOException();
+ }
+ }
+ });
+
+ HttpClient client = prepareClient();
+ InputStreamResponseListener listener = new InputStreamResponseListener();
+ int port = serverConnector.getLocalPort();
+ client.newRequest("localhost", port).send(listener);
+
+ Response response = listener.get(5, TimeUnit.SECONDS);
+ Assert.assertEquals(200, response.getStatus());
+
+ InputStream input = listener.getInputStream();
+ for (int i = 0; i < chunk1.length; ++i)
+ Assert.assertEquals(chunk1[i] & 0xFF, input.read());
+
+ TimeUnit.MILLISECONDS.sleep(2 * proxyTimeout);
+
+ chunk1Latch.countDown();
+
+ try
+ {
+ // Make sure the proxy does not receive chunk2.
+ input.read();
+ Assert.fail();
+ }
+ catch (EOFException x)
+ {
+ // Expected
+ }
+
+ HttpDestinationOverHTTP destination = (HttpDestinationOverHTTP)client.getDestination("http", "localhost", port);
+ Assert.assertEquals(0, destination.getConnectionPool().getIdleConnections().size());
+ }
+
+ @Test
+ public void testResponseHeadersAreNotRemoved() throws Exception
+ {
+ prepareProxy();
+ proxyContext.stop();
+ final String headerName = "X-Test";
+ final String headerValue = "test-value";
+ proxyContext.addFilter(new FilterHolder(new Filter()
+ {
+ @Override
+ public void init(FilterConfig filterConfig) throws ServletException
+ {
+ }
+
+ @Override
+ public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException
+ {
+ ((HttpServletResponse)response).addHeader(headerName, headerValue);
+ chain.doFilter(request, response);
+ }
+
+ @Override
+ public void destroy()
+ {
+ }
+ }), "/*", EnumSet.of(DispatcherType.REQUEST));
+ proxyContext.start();
+ prepareServer(new EmptyHttpServlet());
+
+ HttpClient client = prepareClient();
+ ContentResponse response = client.newRequest("localhost", serverConnector.getLocalPort()).send();
+
+ Assert.assertEquals(200, response.getStatus());
+ Assert.assertEquals(headerValue, response.getHeaders().get(headerName));
+ }
+
// TODO: test proxy authentication
}
diff --git a/jetty-quickstart/pom.xml b/jetty-quickstart/pom.xml
index 380b81b2dd..d360d7a92b 100644
--- a/jetty-quickstart/pom.xml
+++ b/jetty-quickstart/pom.xml
@@ -2,12 +2,12 @@
<parent>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-project</artifactId>
- <version>9.2.2-SNAPSHOT</version>
+ <version>9.2.3-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-quickstart</artifactId>
- <name>Example :: Jetty Quick Start</name>
+ <name>Jetty :: Quick Start</name>
<description>Jetty Quick Start</description>
<url>http://www.eclipse.org/jetty</url>
<dependencies>
@@ -82,74 +82,6 @@
</dependencies>
<build>
<plugins>
-
- <plugin>
- <groupId>org.codehaus.mojo</groupId>
- <artifactId>appassembler-maven-plugin</artifactId>
- <version>1.7</version>
- <configuration>
- <platforms>
- <platform>unix</platform>
- </platforms>
- <programs>
- <program>
- <id>preconfigure</id>
- <mainClass>org.eclipse.jetty.quickstart.PreconfigureQuickStartWar</mainClass>
- </program>
- <program>
- <mainClass>org.eclipse.jetty.quickstart.QuickStartWar</mainClass>
- <id>quickstart</id>
- </program>
- </programs>
- </configuration>
- </plugin>
-
- <plugin>
- <artifactId>maven-dependency-plugin</artifactId>
- <executions>
- <execution>
- <id>copy</id>
- <phase>generate-resources</phase>
- <goals>
- <goal>copy</goal>
- </goals>
- <configuration>
- <artifactItems>
- <artifactItem>
- <groupId>org.eclipse.jetty.tests</groupId>
- <artifactId>test-jndi-webapp</artifactId>
- <version>${project.version}</version>
- <type>war</type>
- <overWrite>true</overWrite>
- <includes>**</includes>
- <outputDirectory>${basedir}/target</outputDirectory>
- <destFileName>test-jndi.war</destFileName>
- </artifactItem>
- <artifactItem>
- <groupId>org.eclipse.jetty.tests</groupId>
- <artifactId>test-spec-webapp</artifactId>
- <version>${project.version}</version>
- <type>war</type>
- <overWrite>true</overWrite>
- <includes>**</includes>
- <outputDirectory>${basedir}/target</outputDirectory>
- <destFileName>test-spec.war</destFileName>
- </artifactItem>
- <artifactItem>
- <groupId>org.eclipse.jetty</groupId>
- <artifactId>test-jetty-webapp</artifactId>
- <version>${project.version}</version>
- <type>war</type>
- <overWrite>true</overWrite>
- <includes>**</includes>
- <outputDirectory>${basedir}/target</outputDirectory>
- <destFileName>test-standard.war</destFileName>
- </artifactItem>
- </artifactItems>
- </configuration>
- </execution>
- </executions>
- </plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-assembly-plugin</artifactId>
diff --git a/jetty-quickstart/src/main/java/org/eclipse/jetty/quickstart/QuickStartConfiguration.java b/jetty-quickstart/src/main/java/org/eclipse/jetty/quickstart/QuickStartConfiguration.java
index 313c5c03c8..85f95dcb6a 100644
--- a/jetty-quickstart/src/main/java/org/eclipse/jetty/quickstart/QuickStartConfiguration.java
+++ b/jetty-quickstart/src/main/java/org/eclipse/jetty/quickstart/QuickStartConfiguration.java
@@ -72,7 +72,23 @@ public class QuickStartConfiguration extends WebInfConfiguration
LOG.debug("webapp={}",webApp);
- //look for effective-web.xml in WEB-INF of webapp
+ //look for quickstart-web.xml in WEB-INF of webapp
+ Resource quickStartWebXml = getQuickStartWebXml(context);
+ LOG.debug("quickStartWebXml={}",quickStartWebXml);
+
+ context.getMetaData().setWebXml(quickStartWebXml);
+ }
+
+
+ /**
+ * Get the quickstart-web.xml file as a Resource.
+ *
+ * @param context
+ * @return
+ * @throws Exception
+ */
+ public Resource getQuickStartWebXml (WebAppContext context) throws Exception
+ {
Resource webInf = context.getWebInf();
if (webInf == null || !webInf.exists())
throw new IllegalStateException("No WEB-INF");
@@ -81,11 +97,10 @@ public class QuickStartConfiguration extends WebInfConfiguration
Resource quickStartWebXml = webInf.addPath("quickstart-web.xml");
if (!quickStartWebXml.exists())
throw new IllegalStateException ("No WEB-INF/quickstart-web.xml");
- LOG.debug("quickStartWebXml={}",quickStartWebXml);
-
- context.getMetaData().setWebXml(quickStartWebXml);
+ return quickStartWebXml;
}
-
+
+
/**
* @see org.eclipse.jetty.webapp.AbstractConfiguration#configure(org.eclipse.jetty.webapp.WebAppContext)
diff --git a/jetty-quickstart/src/main/java/org/eclipse/jetty/quickstart/QuickStartDescriptorGenerator.java b/jetty-quickstart/src/main/java/org/eclipse/jetty/quickstart/QuickStartDescriptorGenerator.java
new file mode 100644
index 0000000000..5a56625fb0
--- /dev/null
+++ b/jetty-quickstart/src/main/java/org/eclipse/jetty/quickstart/QuickStartDescriptorGenerator.java
@@ -0,0 +1,659 @@
+//
+// ========================================================================
+// Copyright (c) 1995-2014 Mort Bay Consulting Pty. Ltd.
+// ------------------------------------------------------------------------
+// All rights reserved. This program and the accompanying materials
+// are made available under the terms of the Eclipse Public License v1.0
+// and Apache License v2.0 which accompanies this distribution.
+//
+// The Eclipse Public License is available at
+// http://www.eclipse.org/legal/epl-v10.html
+//
+// The Apache License v2.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.quickstart;
+
+import java.io.File;
+import java.io.FileNotFoundException;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.OutputStream;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.EventListener;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Set;
+
+import javax.servlet.DispatcherType;
+import javax.servlet.MultipartConfigElement;
+import javax.servlet.ServletContext;
+import javax.servlet.SessionCookieConfig;
+import javax.servlet.SessionTrackingMode;
+import javax.servlet.descriptor.JspPropertyGroupDescriptor;
+import javax.servlet.descriptor.TaglibDescriptor;
+
+import org.eclipse.jetty.annotations.AnnotationConfiguration;
+import org.eclipse.jetty.http.MimeTypes;
+import org.eclipse.jetty.plus.annotation.LifeCycleCallback;
+import org.eclipse.jetty.plus.annotation.LifeCycleCallbackCollection;
+import org.eclipse.jetty.security.ConstraintAware;
+import org.eclipse.jetty.security.ConstraintMapping;
+import org.eclipse.jetty.security.SecurityHandler;
+import org.eclipse.jetty.security.authentication.FormAuthenticator;
+import org.eclipse.jetty.servlet.ErrorPageErrorHandler;
+import org.eclipse.jetty.servlet.FilterHolder;
+import org.eclipse.jetty.servlet.FilterMapping;
+import org.eclipse.jetty.servlet.Holder;
+import org.eclipse.jetty.servlet.ServletHandler;
+import org.eclipse.jetty.servlet.ServletHolder;
+import org.eclipse.jetty.servlet.ServletMapping;
+import org.eclipse.jetty.servlet.ServletContextHandler.JspConfig;
+import org.eclipse.jetty.util.QuotedStringTokenizer;
+import org.eclipse.jetty.util.log.Log;
+import org.eclipse.jetty.util.log.Logger;
+import org.eclipse.jetty.util.security.Constraint;
+import org.eclipse.jetty.webapp.MetaData;
+import org.eclipse.jetty.webapp.MetaData.OriginInfo;
+import org.eclipse.jetty.webapp.MetaInfConfiguration;
+import org.eclipse.jetty.webapp.WebAppContext;
+import org.eclipse.jetty.xml.XmlAppendable;
+
+
+
+/**
+ * QuickStartDescriptorGenerator
+ *
+ * Generate an effective web.xml from a WebAppContext, including all components
+ * from web.xml, web-fragment.xmls annotations etc.
+ */
+public class QuickStartDescriptorGenerator
+{
+ private static final Logger LOG = Log.getLogger(QuickStartDescriptorGenerator.class);
+
+ public static final String DEFAULT_QUICKSTART_DESCRIPTOR_NAME = "quickstart-web.xml";
+
+ protected WebAppContext _webApp;
+ protected String _extraXML;
+
+
+
+ /**
+ * @param w the source WebAppContext
+ * @param extraXML any extra xml snippet to append
+ */
+ public QuickStartDescriptorGenerator (WebAppContext w, String extraXML)
+ {
+ _webApp = w;
+ _extraXML = extraXML;
+ }
+
+
+ /**
+ * Perform the generation of the xml file
+ * @throws IOException
+ * @throws FileNotFoundException
+ * @throws Exception
+ */
+ public void generateQuickStartWebXml (OutputStream stream) throws FileNotFoundException, IOException
+ {
+ if (_webApp == null)
+ throw new IllegalStateException("No webapp for quickstart generation");
+ if (stream == null)
+ throw new IllegalStateException("No output for quickstart generation");
+
+ _webApp.getMetaData().getOrigins();
+
+ if (_webApp.getBaseResource()==null)
+ throw new IllegalArgumentException("No base resource for "+this);
+
+ LOG.info("Quickstart generating");
+
+ XmlAppendable out = new XmlAppendable(stream,"UTF-8");
+
+ MetaData md = _webApp.getMetaData();
+
+ Map<String, String> webappAttr = new HashMap<>();
+ webappAttr.put("xmlns","http://xmlns.jcp.org/xml/ns/javaee");
+ webappAttr.put("xmlns:xsi","http://www.w3.org/2001/XMLSchema-instance");
+ webappAttr.put("xsi:schemaLocation","http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd");
+ webappAttr.put("metadata-complete","true");
+ webappAttr.put("version","3.1");
+
+ out.openTag("web-app",webappAttr);
+ if (_webApp.getDisplayName() != null)
+ out.tag("display-name",_webApp.getDisplayName());
+
+ // Set some special context parameters
+
+ // The location of the war file on disk
+ String resourceBase = _webApp.getBaseResource().getFile().getCanonicalFile().getAbsoluteFile().toURI().toString();
+
+ // The library order
+ addContextParamFromAttribute(out,ServletContext.ORDERED_LIBS);
+ //the servlet container initializers
+ addContextParamFromAttribute(out,AnnotationConfiguration.CONTAINER_INITIALIZERS);
+ //the tlds discovered
+ addContextParamFromAttribute(out,MetaInfConfiguration.METAINF_TLDS,resourceBase);
+ //the META-INF/resources discovered
+ addContextParamFromAttribute(out,MetaInfConfiguration.METAINF_RESOURCES,resourceBase);
+
+
+ // init params
+ for (String p : _webApp.getInitParams().keySet())
+ out.openTag("context-param",origin(md,"context-param." + p))
+ .tag("param-name",p)
+ .tag("param-value",_webApp.getInitParameter(p))
+ .closeTag();
+
+ if (_webApp.getEventListeners() != null)
+ for (EventListener e : _webApp.getEventListeners())
+ out.openTag("listener",origin(md,e.getClass().getCanonicalName() + ".listener"))
+ .tag("listener-class",e.getClass().getCanonicalName())
+ .closeTag();
+
+ ServletHandler servlets = _webApp.getServletHandler();
+
+ if (servlets.getFilters() != null)
+ {
+ for (FilterHolder holder : servlets.getFilters())
+ outholder(out,md,"filter",holder);
+ }
+
+ if (servlets.getFilterMappings() != null)
+ {
+ for (FilterMapping mapping : servlets.getFilterMappings())
+ {
+ out.openTag("filter-mapping");
+ out.tag("filter-name",mapping.getFilterName());
+ if (mapping.getPathSpecs() != null)
+ for (String s : mapping.getPathSpecs())
+ out.tag("url-pattern",s);
+ if (mapping.getServletNames() != null)
+ for (String n : mapping.getServletNames())
+ out.tag("servlet-name",n);
+
+ if (!mapping.isDefaultDispatches())
+ {
+ if (mapping.appliesTo(DispatcherType.REQUEST))
+ out.tag("dispatcher","REQUEST");
+ if (mapping.appliesTo(DispatcherType.ASYNC))
+ out.tag("dispatcher","ASYNC");
+ if (mapping.appliesTo(DispatcherType.ERROR))
+ out.tag("dispatcher","ERROR");
+ if (mapping.appliesTo(DispatcherType.FORWARD))
+ out.tag("dispatcher","FORWARD");
+ if (mapping.appliesTo(DispatcherType.INCLUDE))
+ out.tag("dispatcher","INCLUDE");
+ }
+ out.closeTag();
+ }
+ }
+
+ if (servlets.getServlets() != null)
+ {
+ for (ServletHolder holder : servlets.getServlets())
+ outholder(out,md,"servlet",holder);
+ }
+
+ if (servlets.getServletMappings() != null)
+ {
+ for (ServletMapping mapping : servlets.getServletMappings())
+ {
+ out.openTag("servlet-mapping",origin(md,mapping.getServletName() + ".servlet.mappings"));
+ out.tag("servlet-name",mapping.getServletName());
+ if (mapping.getPathSpecs() != null)
+ for (String s : mapping.getPathSpecs())
+ out.tag("url-pattern",s);
+ out.closeTag();
+ }
+ }
+
+ // Security elements
+ SecurityHandler security =_webApp. getSecurityHandler();
+
+ if (security!=null && (security.getRealmName()!=null || security.getAuthMethod()!=null))
+ {
+ out.openTag("login-config");
+ if (security.getAuthMethod()!=null)
+ out.tag("auth-method",origin(md,"auth-method"),security.getAuthMethod());
+ if (security.getRealmName()!=null)
+ out.tag("realm-name",origin(md,"realm-name"),security.getRealmName());
+
+
+ if (Constraint.__FORM_AUTH.equalsIgnoreCase(security.getAuthMethod()))
+ {
+ out.openTag("form-login-config");
+ out.tag("form-login-page",origin(md,"form-login-page"),security.getInitParameter(FormAuthenticator.__FORM_LOGIN_PAGE));
+ out.tag("form-error-page",origin(md,"form-error-page"),security.getInitParameter(FormAuthenticator.__FORM_ERROR_PAGE));
+ out.closeTag();
+ }
+
+ out.closeTag();
+ }
+
+ if (security instanceof ConstraintAware)
+ {
+ ConstraintAware ca = (ConstraintAware)security;
+ for (String r:ca.getRoles())
+ out.openTag("security-role")
+ .tag("role-name",r)
+ .closeTag();
+
+ for (ConstraintMapping m : ca.getConstraintMappings())
+ {
+ out.openTag("security-constraint");
+
+ if (m.getConstraint().getAuthenticate())
+ {
+ out.openTag("auth-constraint");
+ if (m.getConstraint().getRoles()!=null)
+ for (String r : m.getConstraint().getRoles())
+ out.tag("role-name",r);
+
+ out.closeTag();
+ }
+
+ switch (m.getConstraint().getDataConstraint())
+ {
+ case Constraint.DC_NONE:
+ out.openTag("user-data-constraint").tag("transport-guarantee","NONE").closeTag();
+ break;
+
+ case Constraint.DC_INTEGRAL:
+ out.openTag("user-data-constraint").tag("transport-guarantee","INTEGRAL").closeTag();
+ break;
+
+ case Constraint.DC_CONFIDENTIAL:
+ out.openTag("user-data-constraint").tag("transport-guarantee","CONFIDENTIAL").closeTag();
+ break;
+
+ default:
+ break;
+
+ }
+
+ out.openTag("web-resource-collection");
+ {
+ if (m.getConstraint().getName()!=null)
+ out.tag("web-resource-name",m.getConstraint().getName());
+ if (m.getPathSpec()!=null)
+ out.tag("url-pattern",origin(md,"constraint.url."+m.getPathSpec()),m.getPathSpec());
+ if (m.getMethod()!=null)
+ out.tag("http-method",m.getMethod());
+
+ if (m.getMethodOmissions()!=null)
+ for (String o:m.getMethodOmissions())
+ out.tag("http-method-omission",o);
+
+ out.closeTag();
+ }
+
+ out.closeTag();
+
+ }
+ }
+
+ if (_webApp.getWelcomeFiles() != null)
+ {
+ out.openTag("welcome-file-list");
+ for (String welcomeFile:_webApp.getWelcomeFiles())
+ {
+ out.tag("welcome-file", welcomeFile);
+ }
+ out.closeTag();
+ }
+
+ Map<String,String> localeEncodings = _webApp.getLocaleEncodings();
+ if (localeEncodings != null && !localeEncodings.isEmpty())
+ {
+ out.openTag("locale-encoding-mapping-list");
+ for (Map.Entry<String, String> entry:localeEncodings.entrySet())
+ {
+ out.openTag("locale-encoding-mapping", origin(md,"locale-encoding."+entry.getKey()));
+ out.tag("locale", entry.getKey());
+ out.tag("encoding", entry.getValue());
+ out.closeTag();
+ }
+ out.closeTag();
+ }
+
+ //session-config
+ if (_webApp.getSessionHandler().getSessionManager() != null)
+ {
+ out.openTag("session-config");
+ int maxInactiveSec = _webApp.getSessionHandler().getSessionManager().getMaxInactiveInterval();
+ out.tag("session-timeout", (maxInactiveSec==0?"0":Integer.toString(maxInactiveSec/60)));
+
+ Set<SessionTrackingMode> modes =_webApp. getSessionHandler().getSessionManager().getEffectiveSessionTrackingModes();
+ if (modes != null)
+ {
+ for (SessionTrackingMode mode:modes)
+ out.tag("tracking-mode", mode.toString());
+ }
+
+ //cookie-config
+ SessionCookieConfig cookieConfig = _webApp.getSessionHandler().getSessionManager().getSessionCookieConfig();
+ if (cookieConfig != null)
+ {
+ out.openTag("cookie-config");
+ if (cookieConfig.getName() != null)
+ out.tag("name", origin(md,"cookie-config.name"), cookieConfig.getName());
+
+ if (cookieConfig.getDomain() != null)
+ out.tag("domain", origin(md, "cookie-config.domain"), cookieConfig.getDomain());
+
+ if (cookieConfig.getPath() != null)
+ out.tag("path", origin(md, "cookie-config.path"), cookieConfig.getPath());
+
+ if (cookieConfig.getComment() != null)
+ out.tag("comment", origin(md, "cookie-config.comment"), cookieConfig.getComment());
+
+ out.tag("http-only", origin(md, "cookie-config.http-only"), Boolean.toString(cookieConfig.isHttpOnly()));
+ out.tag("secure", origin(md, "cookie-config.secure"), Boolean.toString(cookieConfig.isSecure()));
+ out.tag("max-age", origin(md, "cookie-config.max-age"), Integer.toString(cookieConfig.getMaxAge()));
+ out.closeTag();
+ }
+ out.closeTag();
+ }
+
+ //error-pages
+ Map<String,String> errorPages = ((ErrorPageErrorHandler)_webApp.getErrorHandler()).getErrorPages();
+ if (errorPages != null)
+ {
+ for (Map.Entry<String, String> entry:errorPages.entrySet())
+ {
+ out.openTag("error-page", origin(md, "error."+entry.getKey()));
+ //a global or default error page has no code or exception
+ if (!ErrorPageErrorHandler.GLOBAL_ERROR_PAGE.equals(entry.getKey()))
+ {
+ if (entry.getKey().matches("\\d{3}"))
+ out.tag("error-code", entry.getKey());
+ else
+ out.tag("exception-type", entry.getKey());
+ }
+ out.tag("location", entry.getValue());
+ out.closeTag();
+ }
+ }
+
+ //mime-types
+ MimeTypes mimeTypes = _webApp.getMimeTypes();
+ if (mimeTypes != null)
+ {
+ for (Map.Entry<String, String> entry:mimeTypes.getMimeMap().entrySet())
+ {
+ out.openTag("mime-mapping");
+ out.tag("extension", origin(md, "extension."+entry.getKey()), entry.getKey());
+ out.tag("mime-type", entry.getValue());
+ out.closeTag();
+ }
+ }
+
+ //jsp-config
+ JspConfig jspConfig = (JspConfig)_webApp.getServletContext().getJspConfigDescriptor();
+ if (jspConfig != null)
+ {
+ out.openTag("jsp-config");
+ Collection<TaglibDescriptor> tlds = jspConfig.getTaglibs();
+ if (tlds != null && !tlds.isEmpty())
+ {
+ for (TaglibDescriptor tld:tlds)
+ {
+ out.openTag("taglib");
+ out.tag("taglib-uri", tld.getTaglibURI());
+ out.tag("taglib-location", tld.getTaglibLocation());
+ out.closeTag();
+ }
+ }
+
+ Collection<JspPropertyGroupDescriptor> jspPropertyGroups = jspConfig.getJspPropertyGroups();
+ if (jspPropertyGroups != null && !jspPropertyGroups.isEmpty())
+ {
+ for (JspPropertyGroupDescriptor jspPropertyGroup:jspPropertyGroups)
+ {
+ out.openTag("jsp-property-group");
+ Collection<String> strings = jspPropertyGroup.getUrlPatterns();
+ if (strings != null && !strings.isEmpty())
+ {
+ for (String urlPattern:strings)
+ out.tag("url-pattern", urlPattern);
+ }
+
+ if (jspPropertyGroup.getElIgnored() != null)
+ out.tag("el-ignored", jspPropertyGroup.getElIgnored());
+
+ if (jspPropertyGroup.getPageEncoding() != null)
+ out.tag("page-encoding", jspPropertyGroup.getPageEncoding());
+
+ if (jspPropertyGroup.getScriptingInvalid() != null)
+ out.tag("scripting-invalid", jspPropertyGroup.getScriptingInvalid());
+
+ if (jspPropertyGroup.getIsXml() != null)
+ out.tag("is-xml", jspPropertyGroup.getIsXml());
+
+ if (jspPropertyGroup.getDeferredSyntaxAllowedAsLiteral() != null)
+ out.tag("deferred-syntax-allowed-as-literal", jspPropertyGroup.getDeferredSyntaxAllowedAsLiteral());
+
+ if (jspPropertyGroup.getTrimDirectiveWhitespaces() != null)
+ out.tag("trim-directive-whitespaces", jspPropertyGroup.getTrimDirectiveWhitespaces());
+
+ if (jspPropertyGroup.getDefaultContentType() != null)
+ out.tag("default-content-type", jspPropertyGroup.getDefaultContentType());
+
+ if (jspPropertyGroup.getBuffer() != null)
+ out.tag("buffer", jspPropertyGroup.getBuffer());
+
+ if (jspPropertyGroup.getErrorOnUndeclaredNamespace() != null)
+ out.tag("error-on-undeclared-namespace", jspPropertyGroup.getErrorOnUndeclaredNamespace());
+
+ strings = jspPropertyGroup.getIncludePreludes();
+ if (strings != null && !strings.isEmpty())
+ {
+ for (String prelude:strings)
+ out.tag("include-prelude", prelude);
+ }
+
+ strings = jspPropertyGroup.getIncludeCodas();
+ if (strings != null && !strings.isEmpty())
+ {
+ for (String coda:strings)
+ out.tag("include-coda", coda);
+ }
+
+ out.closeTag();
+ }
+ }
+
+ out.closeTag();
+ }
+
+ //lifecycle: post-construct, pre-destroy
+ LifeCycleCallbackCollection lifecycles = ((LifeCycleCallbackCollection)_webApp.getAttribute(LifeCycleCallbackCollection.LIFECYCLE_CALLBACK_COLLECTION));
+ if (lifecycles != null)
+ {
+ Collection<LifeCycleCallback> tmp = lifecycles.getPostConstructCallbacks();
+
+ for (LifeCycleCallback c:tmp)
+ {
+ out.openTag("post-construct");
+ out.tag("lifecycle-callback-class", c.getTargetClassName());
+ out.tag("lifecycle-callback-method", c.getMethodName());
+ out.closeTag();
+ }
+
+ tmp = lifecycles.getPreDestroyCallbacks();
+ for (LifeCycleCallback c:tmp)
+ {
+ out.openTag("pre-destroy");
+ out.tag("lifecycle-callback-class", c.getTargetClassName());
+ out.tag("lifecycle-callback-method", c.getMethodName());
+ out.closeTag();
+ }
+ }
+
+ out.literal(_extraXML);
+
+ out.closeTag();
+ }
+
+ /**
+ * Turn attribute into context-param to store.
+ *
+ * @param out
+ * @param attribute
+ * @throws IOException
+ */
+ private void addContextParamFromAttribute(XmlAppendable out, String attribute) throws IOException
+ {
+ addContextParamFromAttribute(out,attribute,null);
+ }
+
+ /**
+ * Turn context attribute into context-param to store.
+ *
+ * @param out
+ * @param attribute
+ * @param resourceBase
+ * @throws IOException
+ */
+ private void addContextParamFromAttribute(XmlAppendable out, String attribute, String resourceBase) throws IOException
+ {
+ Object o = _webApp.getAttribute(attribute);
+ if (o == null)
+ return;
+
+ Collection<?> c = (o instanceof Collection)? (Collection<?>)o:Collections.singletonList(o);
+ StringBuilder v=new StringBuilder();
+ for (Object i:c)
+ {
+ if (i!=null)
+ {
+ if (v.length()>0)
+ v.append(",\n ");
+ else
+ v.append("\n ");
+ if (resourceBase==null)
+ QuotedStringTokenizer.quote(v,i.toString());
+ else
+ QuotedStringTokenizer.quote(v,i.toString().replace(resourceBase,"${WAR}/"));
+ }
+ }
+ out.openTag("context-param")
+ .tag("param-name",attribute)
+ .tagCDATA("param-value",v.toString())
+ .closeTag();
+ }
+
+ /**
+ * Generate xml for a Holder (Filter/Servlet)
+ *
+ * @param out
+ * @param md
+ * @param tag
+ * @param holder
+ * @throws IOException
+ */
+ private void outholder(XmlAppendable out, MetaData md, String tag, Holder<?> holder) throws IOException
+ {
+ out.openTag(tag,Collections.singletonMap("source",holder.getSource().toString()));
+ String n = holder.getName();
+ out.tag(tag + "-name",n);
+
+ String ot = n + "." + tag + ".";
+
+ if (holder instanceof FilterHolder)
+ out.tag(tag + "-class",origin(md,ot + tag + "-class"),holder.getClassName());
+ else if (holder instanceof ServletHolder)
+ {
+ ServletHolder s = (ServletHolder)holder;
+ if (s.getForcedPath() != null && s.getClassName() == null)
+ out.tag("jsp-file",s.getForcedPath());
+ else
+ out.tag(tag + "-class",origin(md,ot + tag + "-class"),s.getClassName());
+
+ }
+
+ for (String p : holder.getInitParameters().keySet())
+ {
+ if ("scratchdir".equalsIgnoreCase(p)) //don't preconfigure the temp dir for jsp output
+ continue;
+ out.openTag("init-param",origin(md,ot + "init-param." + p))
+ .tag("param-name",p)
+ .tag("param-value",holder.getInitParameter(p))
+ .closeTag();
+ }
+
+ if (holder instanceof ServletHolder)
+ {
+ ServletHolder s = (ServletHolder)holder;
+ if (s.getInitOrder() >= 0)
+ out.tag("load-on-startup",Integer.toString(s.getInitOrder()));
+
+ if (s.getRunAsRole() != null)
+ out.openTag("run-as",origin(md,ot + "run-as"))
+ .tag("role-name",s.getRunAsRole())
+ .closeTag();
+
+ Map<String,String> roles = s.getRoleRefMap();
+ if (roles!=null)
+ {
+ for (Map.Entry<String, String> e : roles.entrySet())
+ {
+ out.openTag("security-role-ref",origin(md,ot+"role-name."+e.getKey()))
+ .tag("role-name",e.getKey())
+ .tag("role-link",e.getValue())
+ .closeTag();
+ }
+ }
+
+ if (!s.isEnabled())
+ out.tag("enabled",origin(md,ot + "enabled"),"false");
+
+ //multipart-config
+ MultipartConfigElement multipartConfig = ((ServletHolder.Registration)s.getRegistration()).getMultipartConfig();
+ if (multipartConfig != null)
+ {
+ out.openTag("multipart-config", origin(md, s.getName()+".servlet.multipart-config"));
+ if (multipartConfig.getLocation() != null)
+ out.tag("location", multipartConfig.getLocation());
+ out.tag("max-file-size", Long.toString(multipartConfig.getMaxFileSize()));
+ out.tag("max-request-size", Long.toString(multipartConfig.getMaxRequestSize()));
+ out.tag("file-size-threshold", Long.toString(multipartConfig.getFileSizeThreshold()));
+ out.closeTag();
+ }
+ }
+
+ out.tag("async-supported",origin(md,ot + "async-supported"),holder.isAsyncSupported()?"true":"false");
+ out.closeTag();
+ }
+
+
+
+ /**
+ * Find the origin (web.xml, fragment, annotation etc) of a web artifact from MetaData.
+ *
+ * @param md
+ * @param name
+ * @return
+ */
+ public Map<String, String> origin(MetaData md, String name)
+ {
+ if (!LOG.isDebugEnabled())
+ return Collections.emptyMap();
+ if (name == null)
+ return Collections.emptyMap();
+ OriginInfo origin = md.getOriginInfo(name);
+ if (LOG.isDebugEnabled()) LOG.debug("origin of "+name+" is "+origin);
+ if (origin == null)
+ return Collections.emptyMap();
+ return Collections.singletonMap("origin",origin.toString());
+ }
+
+}
diff --git a/jetty-quickstart/src/main/java/org/eclipse/jetty/quickstart/QuickStartWebApp.java b/jetty-quickstart/src/main/java/org/eclipse/jetty/quickstart/QuickStartWebApp.java
index bcbcab8080..0372e52cb9 100644
--- a/jetty-quickstart/src/main/java/org/eclipse/jetty/quickstart/QuickStartWebApp.java
+++ b/jetty-quickstart/src/main/java/org/eclipse/jetty/quickstart/QuickStartWebApp.java
@@ -18,51 +18,13 @@
package org.eclipse.jetty.quickstart;
-import java.io.File;
import java.io.FileOutputStream;
-import java.io.IOException;
-import java.util.Arrays;
-import java.util.Collection;
-import java.util.Collections;
-import java.util.EventListener;
-import java.util.HashMap;
-import java.util.Map;
-import java.util.Set;
-import javax.servlet.DispatcherType;
-import javax.servlet.MultipartConfigElement;
-import javax.servlet.ServletContext;
-import javax.servlet.SessionCookieConfig;
-import javax.servlet.SessionTrackingMode;
-import javax.servlet.descriptor.JspPropertyGroupDescriptor;
-import javax.servlet.descriptor.TaglibDescriptor;
-
-import org.eclipse.jetty.annotations.AnnotationConfiguration;
-import org.eclipse.jetty.http.MimeTypes;
-import org.eclipse.jetty.plus.annotation.LifeCycleCallback;
-import org.eclipse.jetty.plus.annotation.LifeCycleCallbackCollection;
-import org.eclipse.jetty.security.ConstraintAware;
-import org.eclipse.jetty.security.ConstraintMapping;
-import org.eclipse.jetty.security.SecurityHandler;
-import org.eclipse.jetty.security.authentication.FormAuthenticator;
-import org.eclipse.jetty.servlet.ErrorPageErrorHandler;
-import org.eclipse.jetty.servlet.FilterHolder;
-import org.eclipse.jetty.servlet.FilterMapping;
-import org.eclipse.jetty.servlet.Holder;
-import org.eclipse.jetty.servlet.ServletHandler;
-import org.eclipse.jetty.servlet.ServletHolder;
-import org.eclipse.jetty.servlet.ServletMapping;
-import org.eclipse.jetty.util.QuotedStringTokenizer;
import org.eclipse.jetty.util.log.Log;
import org.eclipse.jetty.util.log.Logger;
import org.eclipse.jetty.util.resource.JarResource;
import org.eclipse.jetty.util.resource.Resource;
-import org.eclipse.jetty.util.security.Constraint;
-import org.eclipse.jetty.webapp.MetaData;
-import org.eclipse.jetty.webapp.MetaData.OriginInfo;
-import org.eclipse.jetty.webapp.MetaInfConfiguration;
import org.eclipse.jetty.webapp.WebAppContext;
-import org.eclipse.jetty.xml.XmlAppendable;
/**
* QuickStartWar
@@ -72,6 +34,8 @@ public class QuickStartWebApp extends WebAppContext
{
private static final Logger LOG = Log.getLogger(QuickStartWebApp.class);
+
+
public static final String[] __configurationClasses = new String[]
{
org.eclipse.jetty.quickstart.QuickStartConfiguration.class.getCanonicalName(),
@@ -190,8 +154,7 @@ public class QuickStartWebApp extends WebAppContext
{
LOG.info("Quickstart preconfigure: {}(war={},dir={})",this,war,dir);
- _preconfigProcessor = new PreconfigureDescriptorProcessor();
-
+ _preconfigProcessor = new PreconfigureDescriptorProcessor();
getMetaData().addDescriptorProcessor(_preconfigProcessor);
setPreconfigure(true);
_startWebapp=true;
@@ -203,518 +166,17 @@ public class QuickStartWebApp extends WebAppContext
}
- public void generateQuickstartWebXml(String extraXML) throws IOException
- {
- getMetaData().getOrigins();
- // dumpStdErr();
-
- if (getBaseResource()==null)
- throw new IllegalArgumentException("No base resource for "+this);
-
- File webxml = new File(getWebInf().getFile(),"quickstart-web.xml");
-
- LOG.info("Quickstart generate {}",webxml);
-
- XmlAppendable out = new XmlAppendable(new FileOutputStream(webxml),"UTF-8");
- MetaData md = getMetaData();
-
- Map<String, String> webappAttr = new HashMap<>();
- webappAttr.put("xmlns","http://xmlns.jcp.org/xml/ns/javaee");
- webappAttr.put("xmlns:xsi","http://www.w3.org/2001/XMLSchema-instance");
- webappAttr.put("xsi:schemaLocation","http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd");
- webappAttr.put("metadata-complete","true");
- webappAttr.put("version","3.1");
-
- out.open("web-app",webappAttr);
-
- if (getDisplayName() != null)
- out.tag("display-name",getDisplayName());
-
- // Set some special context parameters
-
- // The location of the war file on disk
- String resourceBase=getBaseResource().getFile().getCanonicalFile().getAbsoluteFile().toURI().toString();
-
- // The library order
- addContextParamFromAttribute(out,ServletContext.ORDERED_LIBS);
- //the servlet container initializers
- addContextParamFromAttribute(out,AnnotationConfiguration.CONTAINER_INITIALIZERS);
- //the tlds discovered
- addContextParamFromAttribute(out,MetaInfConfiguration.METAINF_TLDS,resourceBase);
- //the META-INF/resources discovered
- addContextParamFromAttribute(out,MetaInfConfiguration.METAINF_RESOURCES,resourceBase);
-
-
- // init params
- for (String p : getInitParams().keySet())
- out.open("context-param",origin(md,"context-param." + p))
- .tag("param-name",p)
- .tag("param-value",getInitParameter(p))
- .close();
-
- if (getEventListeners() != null)
- for (EventListener e : getEventListeners())
- out.open("listener",origin(md,e.getClass().getCanonicalName() + ".listener"))
- .tag("listener-class",e.getClass().getCanonicalName())
- .close();
-
- ServletHandler servlets = getServletHandler();
-
- if (servlets.getFilters() != null)
- {
- for (FilterHolder holder : servlets.getFilters())
- outholder(out,md,"filter",holder);
- }
-
- if (servlets.getFilterMappings() != null)
- {
- for (FilterMapping mapping : servlets.getFilterMappings())
- {
- out.open("filter-mapping");
- out.tag("filter-name",mapping.getFilterName());
- if (mapping.getPathSpecs() != null)
- for (String s : mapping.getPathSpecs())
- out.tag("url-pattern",s);
- if (mapping.getServletNames() != null)
- for (String n : mapping.getServletNames())
- out.tag("servlet-name",n);
-
- if (!mapping.isDefaultDispatches())
- {
- if (mapping.appliesTo(DispatcherType.REQUEST))
- out.tag("dispatcher","REQUEST");
- if (mapping.appliesTo(DispatcherType.ASYNC))
- out.tag("dispatcher","ASYNC");
- if (mapping.appliesTo(DispatcherType.ERROR))
- out.tag("dispatcher","ERROR");
- if (mapping.appliesTo(DispatcherType.FORWARD))
- out.tag("dispatcher","FORWARD");
- if (mapping.appliesTo(DispatcherType.INCLUDE))
- out.tag("dispatcher","INCLUDE");
- }
- out.close();
- }
- }
-
- if (servlets.getServlets() != null)
- {
- for (ServletHolder holder : servlets.getServlets())
- outholder(out,md,"servlet",holder);
- }
-
- if (servlets.getServletMappings() != null)
- {
- for (ServletMapping mapping : servlets.getServletMappings())
- {
- out.open("servlet-mapping",origin(md,mapping.getServletName() + ".servlet.mappings"));
- out.tag("servlet-name",mapping.getServletName());
- if (mapping.getPathSpecs() != null)
- for (String s : mapping.getPathSpecs())
- out.tag("url-pattern",s);
- out.close();
- }
- }
-
- // Security elements
- SecurityHandler security = getSecurityHandler();
-
- if (security!=null && (security.getRealmName()!=null || security.getAuthMethod()!=null))
- {
- out.open("login-config");
- if (security.getAuthMethod()!=null)
- out.tag("auth-method",origin(md,"auth-method"),security.getAuthMethod());
- if (security.getRealmName()!=null)
- out.tag("realm-name",origin(md,"realm-name"),security.getRealmName());
-
-
- if (Constraint.__FORM_AUTH.equalsIgnoreCase(security.getAuthMethod()))
- {
- out.open("form-login-config");
- out.tag("form-login-page",origin(md,"form-login-page"),security.getInitParameter(FormAuthenticator.__FORM_LOGIN_PAGE));
- out.tag("form-error-page",origin(md,"form-error-page"),security.getInitParameter(FormAuthenticator.__FORM_ERROR_PAGE));
- out.close();
- }
-
- out.close();
- }
-
- if (security instanceof ConstraintAware)
- {
- ConstraintAware ca = (ConstraintAware)security;
- for (String r:ca.getRoles())
- out.open("security-role")
- .tag("role-name",r)
- .close();
-
- for (ConstraintMapping m : ca.getConstraintMappings())
- {
- out.open("security-constraint");
-
- if (m.getConstraint().getAuthenticate())
- {
- out.open("auth-constraint");
- if (m.getConstraint().getRoles()!=null)
- for (String r : m.getConstraint().getRoles())
- out.tag("role-name",r);
-
- out.close();
- }
-
- switch (m.getConstraint().getDataConstraint())
- {
- case Constraint.DC_NONE:
- out.open("user-data-constraint").tag("transport-guarantee","NONE").close();
- break;
-
- case Constraint.DC_INTEGRAL:
- out.open("user-data-constraint").tag("transport-guarantee","INTEGRAL").close();
- break;
-
- case Constraint.DC_CONFIDENTIAL:
- out.open("user-data-constraint").tag("transport-guarantee","CONFIDENTIAL").close();
- break;
-
- default:
- break;
-
- }
-
- out.open("web-resource-collection");
- {
- if (m.getConstraint().getName()!=null)
- out.tag("web-resource-name",m.getConstraint().getName());
- if (m.getPathSpec()!=null)
- out.tag("url-pattern",origin(md,"constraint.url."+m.getPathSpec()),m.getPathSpec());
- if (m.getMethod()!=null)
- out.tag("http-method",m.getMethod());
-
- if (m.getMethodOmissions()!=null)
- for (String o:m.getMethodOmissions())
- out.tag("http-method-omission",o);
-
- out.close();
- }
-
- out.close();
-
- }
- }
-
- if (getWelcomeFiles() != null)
- {
- out.open("welcome-file-list");
- for (String welcomeFile:getWelcomeFiles())
- {
- out.tag("welcome-file", welcomeFile);
- }
- out.close();
- }
-
- Map<String,String> localeEncodings = getLocaleEncodings();
- if (localeEncodings != null && !localeEncodings.isEmpty())
- {
- out.open("locale-encoding-mapping-list");
- for (Map.Entry<String, String> entry:localeEncodings.entrySet())
- {
- out.open("locale-encoding-mapping", origin(md,"locale-encoding."+entry.getKey()));
- out.tag("locale", entry.getKey());
- out.tag("encoding", entry.getValue());
- out.close();
- }
- out.close();
- }
-
- //session-config
- if (getSessionHandler().getSessionManager() != null)
- {
- out.open("session-config");
- int maxInactiveSec = getSessionHandler().getSessionManager().getMaxInactiveInterval();
- out.tag("session-timeout", (maxInactiveSec==0?"0":Integer.toString(maxInactiveSec/60)));
-
- Set<SessionTrackingMode> modes = getSessionHandler().getSessionManager().getEffectiveSessionTrackingModes();
- if (modes != null)
- {
- for (SessionTrackingMode mode:modes)
- out.tag("tracking-mode", mode.toString());
- }
-
- //cookie-config
- SessionCookieConfig cookieConfig = getSessionHandler().getSessionManager().getSessionCookieConfig();
- if (cookieConfig != null)
- {
- out.open("cookie-config");
- if (cookieConfig.getName() != null)
- out.tag("name", origin(md,"cookie-config.name"), cookieConfig.getName());
-
- if (cookieConfig.getDomain() != null)
- out.tag("domain", origin(md, "cookie-config.domain"), cookieConfig.getDomain());
-
- if (cookieConfig.getPath() != null)
- out.tag("path", origin(md, "cookie-config.path"), cookieConfig.getPath());
-
- if (cookieConfig.getComment() != null)
- out.tag("comment", origin(md, "cookie-config.comment"), cookieConfig.getComment());
-
- out.tag("http-only", origin(md, "cookie-config.http-only"), Boolean.toString(cookieConfig.isHttpOnly()));
- out.tag("secure", origin(md, "cookie-config.secure"), Boolean.toString(cookieConfig.isSecure()));
- out.tag("max-age", origin(md, "cookie-config.max-age"), Integer.toString(cookieConfig.getMaxAge()));
- out.close();
- }
- out.close();
- }
-
- //error-pages
- Map<String,String> errorPages = ((ErrorPageErrorHandler)getErrorHandler()).getErrorPages();
- if (errorPages != null)
- {
- for (Map.Entry<String, String> entry:errorPages.entrySet())
- {
- out.open("error-page", origin(md, "error."+entry.getKey()));
- //a global or default error page has no code or exception
- if (!ErrorPageErrorHandler.GLOBAL_ERROR_PAGE.equals(entry.getKey()))
- {
- if (entry.getKey().matches("\\d{3}"))
- out.tag("error-code", entry.getKey());
- else
- out.tag("exception-type", entry.getKey());
- }
- out.tag("location", entry.getValue());
- out.close();
- }
- }
-
- //mime-types
- MimeTypes mimeTypes = getMimeTypes();
- if (mimeTypes != null)
- {
- for (Map.Entry<String, String> entry:mimeTypes.getMimeMap().entrySet())
- {
- out.open("mime-mapping");
- out.tag("extension", origin(md, "extension."+entry.getKey()), entry.getKey());
- out.tag("mime-type", entry.getValue());
- out.close();
- }
- }
-
- //jsp-config
- JspConfig jspConfig = (JspConfig)getServletContext().getJspConfigDescriptor();
- if (jspConfig != null)
- {
- out.open("jsp-config");
- Collection<TaglibDescriptor> tlds = jspConfig.getTaglibs();
- if (tlds != null && !tlds.isEmpty())
- {
- for (TaglibDescriptor tld:tlds)
- {
- out.open("taglib");
- out.tag("taglib-uri", tld.getTaglibURI());
- out.tag("taglib-location", tld.getTaglibLocation());
- out.close();
- }
- }
-
- Collection<JspPropertyGroupDescriptor> jspPropertyGroups = jspConfig.getJspPropertyGroups();
- if (jspPropertyGroups != null && !jspPropertyGroups.isEmpty())
- {
- for (JspPropertyGroupDescriptor jspPropertyGroup:jspPropertyGroups)
- {
- out.open("jsp-property-group");
- Collection<String> strings = jspPropertyGroup.getUrlPatterns();
- if (strings != null && !strings.isEmpty())
- {
- for (String urlPattern:strings)
- out.tag("url-pattern", urlPattern);
- }
-
- if (jspPropertyGroup.getElIgnored() != null)
- out.tag("el-ignored", jspPropertyGroup.getElIgnored());
-
- if (jspPropertyGroup.getPageEncoding() != null)
- out.tag("page-encoding", jspPropertyGroup.getPageEncoding());
-
- if (jspPropertyGroup.getScriptingInvalid() != null)
- out.tag("scripting-invalid", jspPropertyGroup.getScriptingInvalid());
-
- if (jspPropertyGroup.getIsXml() != null)
- out.tag("is-xml", jspPropertyGroup.getIsXml());
-
- if (jspPropertyGroup.getDeferredSyntaxAllowedAsLiteral() != null)
- out.tag("deferred-syntax-allowed-as-literal", jspPropertyGroup.getDeferredSyntaxAllowedAsLiteral());
-
- if (jspPropertyGroup.getTrimDirectiveWhitespaces() != null)
- out.tag("trim-directive-whitespaces", jspPropertyGroup.getTrimDirectiveWhitespaces());
-
- if (jspPropertyGroup.getDefaultContentType() != null)
- out.tag("default-content-type", jspPropertyGroup.getDefaultContentType());
-
- if (jspPropertyGroup.getBuffer() != null)
- out.tag("buffer", jspPropertyGroup.getBuffer());
-
- if (jspPropertyGroup.getErrorOnUndeclaredNamespace() != null)
- out.tag("error-on-undeclared-namespace", jspPropertyGroup.getErrorOnUndeclaredNamespace());
-
- strings = jspPropertyGroup.getIncludePreludes();
- if (strings != null && !strings.isEmpty())
- {
- for (String prelude:strings)
- out.tag("include-prelude", prelude);
- }
-
- strings = jspPropertyGroup.getIncludeCodas();
- if (strings != null && !strings.isEmpty())
- {
- for (String coda:strings)
- out.tag("include-coda", coda);
- }
-
- out.close();
- }
- }
-
- out.close();
- }
-
- //lifecycle: post-construct, pre-destroy
- LifeCycleCallbackCollection lifecycles = ((LifeCycleCallbackCollection)getAttribute(LifeCycleCallbackCollection.LIFECYCLE_CALLBACK_COLLECTION));
- if (lifecycles != null)
- {
- Collection<LifeCycleCallback> tmp = lifecycles.getPostConstructCallbacks();
-
- for (LifeCycleCallback c:tmp)
- {
- out.open("post-construct");
- out.tag("lifecycle-callback-class", c.getTargetClassName());
- out.tag("lifecycle-callback-method", c.getMethodName());
- out.close();
- }
-
- tmp = lifecycles.getPreDestroyCallbacks();
- for (LifeCycleCallback c:tmp)
- {
- out.open("pre-destroy");
- out.tag("lifecycle-callback-class", c.getTargetClassName());
- out.tag("lifecycle-callback-method", c.getMethodName());
- out.close();
- }
- }
-
- out.literal(extraXML);
-
- out.close();
- }
-
- private void addContextParamFromAttribute(XmlAppendable out, String attribute) throws IOException
- {
- addContextParamFromAttribute(out,attribute,null);
- }
-
- private void addContextParamFromAttribute(XmlAppendable out, String attribute, String resourceBase) throws IOException
- {
- Object o=getAttribute(attribute);
- if (o==null)
- return;
-
- Collection<?> c = (o instanceof Collection)? (Collection<?>)o:Collections.singletonList(o);
- StringBuilder v=new StringBuilder();
- for (Object i:c)
- {
- if (i!=null)
- {
- if (v.length()>0)
- v.append(",\n ");
- else
- v.append("\n ");
- if (resourceBase==null)
- QuotedStringTokenizer.quote(v,i.toString());
- else
- QuotedStringTokenizer.quote(v,i.toString().replace(resourceBase,"${WAR}/"));
- }
- }
- out.open("context-param")
- .tag("param-name",attribute)
- .tagCDATA("param-value",v.toString())
- .close();
- }
-
- private static void outholder(XmlAppendable out, MetaData md, String tag, Holder<?> holder) throws IOException
+ public void generateQuickstartWebXml(String extraXML) throws Exception
{
- out.open(tag,Collections.singletonMap("source",holder.getSource().toString()));
- String n = holder.getName();
- out.tag(tag + "-name",n);
-
- String ot = n + "." + tag + ".";
-
- out.tag(tag + "-class",origin(md,ot + tag + "-class"),holder.getClassName());
-
- for (String p : holder.getInitParameters().keySet())
+ Resource descriptor = getWebInf().addPath(QuickStartDescriptorGenerator.DEFAULT_QUICKSTART_DESCRIPTOR_NAME);
+ if (!descriptor.exists())
+ descriptor.getFile().createNewFile();
+ QuickStartDescriptorGenerator generator = new QuickStartDescriptorGenerator(this, extraXML);
+ try (FileOutputStream fos = new FileOutputStream(descriptor.getFile()))
{
- if ("scratchdir".equalsIgnoreCase(p)) //don't preconfigure the temp dir for jsp output
- continue;
- out.open("init-param",origin(md,ot + "init-param." + p))
- .tag("param-name",p)
- .tag("param-value",holder.getInitParameter(p))
- .close();
- }
-
- if (holder instanceof ServletHolder)
- {
- ServletHolder s = (ServletHolder)holder;
- if (s.getForcedPath() != null)
- out.tag("jsp-file",s.getForcedPath());
-
- if (s.getInitOrder() != 0)
- out.tag("load-on-startup",Integer.toString(s.getInitOrder()));
-
- if (s.getRunAsRole() != null)
- out.open("run-as",origin(md,ot + "run-as"))
- .tag("role-name",s.getRunAsRole())
- .close();
-
- Map<String,String> roles = s.getRoleRefMap();
- if (roles!=null)
- {
- for (Map.Entry<String, String> e : roles.entrySet())
- {
- out.open("security-role-ref",origin(md,ot+"role-name."+e.getKey()))
- .tag("role-name",e.getKey())
- .tag("role-link",e.getValue())
- .close();
- }
- }
-
- if (!s.isEnabled())
- out.tag("enabled",origin(md,ot + "enabled"),"false");
-
- //multipart-config
- MultipartConfigElement multipartConfig = ((ServletHolder.Registration)s.getRegistration()).getMultipartConfig();
- if (multipartConfig != null)
- {
- out.open("multipart-config", origin(md, s.getName()+".servlet.multipart-config"));
- if (multipartConfig.getLocation() != null)
- out.tag("location", multipartConfig.getLocation());
- out.tag("max-file-size", Long.toString(multipartConfig.getMaxFileSize()));
- out.tag("max-request-size", Long.toString(multipartConfig.getMaxRequestSize()));
- out.tag("file-size-threshold", Long.toString(multipartConfig.getFileSizeThreshold()));
- out.close();
- }
+ generator.generateQuickStartWebXml(fos);
}
-
- out.tag("async-supported",origin(md,ot + "async-supported"),holder.isAsyncSupported()?"true":"false");
- out.close();
}
- public static Map<String, String> origin(MetaData md, String name)
- {
- if (!LOG.isDebugEnabled())
- return Collections.emptyMap();
- if (name == null)
- return Collections.emptyMap();
- OriginInfo origin = md.getOriginInfo(name);
- // System.err.println("origin of "+name+" is "+origin);
- if (origin == null)
- return Collections.emptyMap();
- return Collections.singletonMap("origin",origin.toString());
-
- }
-
+
}
diff --git a/jetty-rewrite/pom.xml b/jetty-rewrite/pom.xml
index b9c3d818dd..f63095706e 100644
--- a/jetty-rewrite/pom.xml
+++ b/jetty-rewrite/pom.xml
@@ -2,7 +2,7 @@
<parent>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-project</artifactId>
- <version>9.2.2-SNAPSHOT</version>
+ <version>9.2.3-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>jetty-rewrite</artifactId>
diff --git a/jetty-rewrite/src/main/java/org/eclipse/jetty/rewrite/handler/RuleContainer.java b/jetty-rewrite/src/main/java/org/eclipse/jetty/rewrite/handler/RuleContainer.java
index eea013eee3..f20e9142c7 100644
--- a/jetty-rewrite/src/main/java/org/eclipse/jetty/rewrite/handler/RuleContainer.java
+++ b/jetty-rewrite/src/main/java/org/eclipse/jetty/rewrite/handler/RuleContainer.java
@@ -27,7 +27,6 @@ import org.eclipse.jetty.server.HttpChannel;
import org.eclipse.jetty.server.Request;
import org.eclipse.jetty.util.ArrayUtil;
import org.eclipse.jetty.util.URIUtil;
-import org.eclipse.jetty.util.UrlEncoded;
import org.eclipse.jetty.util.log.Log;
import org.eclipse.jetty.util.log.Logger;
diff --git a/jetty-rhttp/jetty-rhttp-gateway/src/main/java/org/eclipse/jetty/rhttp/gateway/GatewayServer.java b/jetty-rhttp/jetty-rhttp-gateway/src/main/java/org/eclipse/jetty/rhttp/gateway/GatewayServer.java
index 83068d10d7..713b4fe0ee 100644
--- a/jetty-rhttp/jetty-rhttp-gateway/src/main/java/org/eclipse/jetty/rhttp/gateway/GatewayServer.java
+++ b/jetty-rhttp/jetty-rhttp-gateway/src/main/java/org/eclipse/jetty/rhttp/gateway/GatewayServer.java
@@ -102,7 +102,7 @@ public class GatewayServer extends Server
public GatewayServer()
{
- this("",DFT_EXT_PATH,DFT_CONNECT_PATH,new StandardTargetIdRetriever());
+ this("",DFT_EXT_PATH,DFT_CONNECT_PATH,new StandardTargetIdRetriever());
}
public GatewayServer(String contextPath, String externalServletPath,String gatewayServletPath, TargetIdRetriever targetIdRetriever)
@@ -145,7 +145,7 @@ public class GatewayServer extends Server
public Gateway getGateway()
{
- return gateway;
+ return gateway;
}
public ServletHolder getExternalServlet()
diff --git a/jetty-runner/pom.xml b/jetty-runner/pom.xml
index 5d7d082cb3..3ac3f0b8a6 100644
--- a/jetty-runner/pom.xml
+++ b/jetty-runner/pom.xml
@@ -2,7 +2,7 @@
<parent>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-project</artifactId>
- <version>9.2.2-SNAPSHOT</version>
+ <version>9.2.3-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>jetty-runner</artifactId>
diff --git a/jetty-security/pom.xml b/jetty-security/pom.xml
index 8edcee4fa6..a1bc14e5f5 100644
--- a/jetty-security/pom.xml
+++ b/jetty-security/pom.xml
@@ -2,7 +2,7 @@
<parent>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-project</artifactId>
- <version>9.2.2-SNAPSHOT</version>
+ <version>9.2.3-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>jetty-security</artifactId>
diff --git a/jetty-security/src/main/java/org/eclipse/jetty/security/ConstraintSecurityHandler.java b/jetty-security/src/main/java/org/eclipse/jetty/security/ConstraintSecurityHandler.java
index 201618d89d..7b7f2a395e 100644
--- a/jetty-security/src/main/java/org/eclipse/jetty/security/ConstraintSecurityHandler.java
+++ b/jetty-security/src/main/java/org/eclipse/jetty/security/ConstraintSecurityHandler.java
@@ -46,6 +46,7 @@ import org.eclipse.jetty.server.Request;
import org.eclipse.jetty.server.Response;
import org.eclipse.jetty.server.UserIdentity;
import org.eclipse.jetty.server.handler.ContextHandler;
+import org.eclipse.jetty.util.URIUtil;
import org.eclipse.jetty.util.log.Log;
import org.eclipse.jetty.util.log.Logger;
import org.eclipse.jetty.util.security.Constraint;
@@ -510,21 +511,6 @@ public class ConstraintSecurityHandler extends SecurityHandler implements Constr
mappings.put(ALL_METHODS,roleInfo);
}
}
- else
- {
- //combine with any entry that covers all methods
- if (httpMethod == null)
- {
- for (Map.Entry<String, RoleInfo> entry : mappings.entrySet())
- {
- if (entry.getKey() != null)
- {
- RoleInfo specific = entry.getValue();
- specific.combine(roleInfo);
- }
- }
- }
- }
}
/* ------------------------------------------------------------ */
@@ -627,7 +613,7 @@ public class ConstraintSecurityHandler extends SecurityHandler implements Constr
@Override
protected RoleInfo prepareConstraintInfo(String pathInContext, Request request)
{
- Map<String, RoleInfo> mappings = (Map<String, RoleInfo>)_constraintMap.match(pathInContext);
+ Map<String, RoleInfo> mappings = _constraintMap.match(pathInContext);
if (mappings != null)
{
@@ -700,11 +686,8 @@ public class ConstraintSecurityHandler extends SecurityHandler implements Constr
{
String scheme = httpConfig.getSecureScheme();
int port = httpConfig.getSecurePort();
- String url = ("https".equalsIgnoreCase(scheme) && port==443)
- ? "https://"+request.getServerName()+request.getRequestURI()
- : scheme + "://" + request.getServerName() + ":" + port + request.getRequestURI();
- if (request.getQueryString() != null)
- url += "?" + request.getQueryString();
+
+ String url = URIUtil.newURI(scheme, request.getServerName(), port,request.getRequestURI(),request.getQueryString());
response.setContentLength(0);
response.sendRedirect(url);
}
diff --git a/jetty-security/src/main/java/org/eclipse/jetty/security/CrossContextPsuedoSession.java b/jetty-security/src/main/java/org/eclipse/jetty/security/CrossContextPsuedoSession.java
index e2de9f7db2..a67eb96d6f 100644
--- a/jetty-security/src/main/java/org/eclipse/jetty/security/CrossContextPsuedoSession.java
+++ b/jetty-security/src/main/java/org/eclipse/jetty/security/CrossContextPsuedoSession.java
@@ -23,6 +23,7 @@ import javax.servlet.http.HttpServletResponse;
/**
* @version $Rev: 4466 $ $Date: 2009-02-10 23:42:54 +0100 (Tue, 10 Feb 2009) $
+ * @deprecated
*/
public interface CrossContextPsuedoSession<T>
{
diff --git a/jetty-security/src/main/java/org/eclipse/jetty/security/HashCrossContextPsuedoSession.java b/jetty-security/src/main/java/org/eclipse/jetty/security/HashCrossContextPsuedoSession.java
index 8499a609d3..2f94908acb 100644
--- a/jetty-security/src/main/java/org/eclipse/jetty/security/HashCrossContextPsuedoSession.java
+++ b/jetty-security/src/main/java/org/eclipse/jetty/security/HashCrossContextPsuedoSession.java
@@ -29,6 +29,7 @@ import javax.servlet.http.HttpServletResponse;
/**
* @version $Rev: 4660 $ $Date: 2009-02-25 17:29:53 +0100 (Wed, 25 Feb 2009) $
+ * @deprecated
*/
public class HashCrossContextPsuedoSession<T> implements CrossContextPsuedoSession<T>
{
diff --git a/jetty-security/src/main/java/org/eclipse/jetty/security/IdentityService.java b/jetty-security/src/main/java/org/eclipse/jetty/security/IdentityService.java
index 99094c17a9..21eba25164 100644
--- a/jetty-security/src/main/java/org/eclipse/jetty/security/IdentityService.java
+++ b/jetty-security/src/main/java/org/eclipse/jetty/security/IdentityService.java
@@ -22,7 +22,6 @@ import java.security.Principal;
import javax.security.auth.Subject;
-import org.eclipse.jetty.server.Request;
import org.eclipse.jetty.server.UserIdentity;
/* ------------------------------------------------------------ */
diff --git a/jetty-security/src/main/java/org/eclipse/jetty/security/SecurityHandler.java b/jetty-security/src/main/java/org/eclipse/jetty/security/SecurityHandler.java
index a6e108e9a7..9460736f47 100644
--- a/jetty-security/src/main/java/org/eclipse/jetty/security/SecurityHandler.java
+++ b/jetty-security/src/main/java/org/eclipse/jetty/security/SecurityHandler.java
@@ -43,7 +43,6 @@ import org.eclipse.jetty.server.handler.ContextHandler;
import org.eclipse.jetty.server.handler.ContextHandler.Context;
import org.eclipse.jetty.server.handler.HandlerWrapper;
import org.eclipse.jetty.server.session.AbstractSession;
-import org.eclipse.jetty.util.component.LifeCycle;
import org.eclipse.jetty.util.log.Log;
import org.eclipse.jetty.util.log.Logger;
diff --git a/jetty-security/src/main/java/org/eclipse/jetty/security/authentication/DeferredAuthentication.java b/jetty-security/src/main/java/org/eclipse/jetty/security/authentication/DeferredAuthentication.java
index df0f7d92f3..fe4c64b8bb 100644
--- a/jetty-security/src/main/java/org/eclipse/jetty/security/authentication/DeferredAuthentication.java
+++ b/jetty-security/src/main/java/org/eclipse/jetty/security/authentication/DeferredAuthentication.java
@@ -331,28 +331,28 @@ public class DeferredAuthentication implements Authentication.Deferred
}
@Override
- public Collection<String> getHeaderNames()
- {
- return Collections.emptyList();
- }
-
- @Override
- public String getHeader(String arg0)
- {
- return null;
- }
-
- @Override
- public Collection<String> getHeaders(String arg0)
- {
+ public Collection<String> getHeaderNames()
+ {
return Collections.emptyList();
- }
+ }
+
+ @Override
+ public String getHeader(String arg0)
+ {
+ return null;
+ }
- @Override
- public int getStatus()
- {
- return 0;
- }
+ @Override
+ public Collection<String> getHeaders(String arg0)
+ {
+ return Collections.emptyList();
+ }
+
+ @Override
+ public int getStatus()
+ {
+ return 0;
+ }
};
diff --git a/jetty-security/src/main/java/org/eclipse/jetty/security/authentication/DigestAuthenticator.java b/jetty-security/src/main/java/org/eclipse/jetty/security/authentication/DigestAuthenticator.java
index 13537e6cb7..be5db7ef7b 100644
--- a/jetty-security/src/main/java/org/eclipse/jetty/security/authentication/DigestAuthenticator.java
+++ b/jetty-security/src/main/java/org/eclipse/jetty/security/authentication/DigestAuthenticator.java
@@ -34,7 +34,6 @@ import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.eclipse.jetty.http.HttpHeader;
-import org.eclipse.jetty.security.SecurityHandler;
import org.eclipse.jetty.security.ServerAuthException;
import org.eclipse.jetty.security.UserAuthentication;
import org.eclipse.jetty.server.Authentication;
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 8469c0a800..e0248b2e59 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
@@ -50,7 +50,7 @@ public class SpnegoAuthenticator extends LoginAuthenticator
*/
public SpnegoAuthenticator( String authMethod )
{
- _authMethod = authMethod;
+ _authMethod = authMethod;
}
@Override
@@ -77,10 +77,10 @@ public class SpnegoAuthenticator extends LoginAuthenticator
{
try
{
- if (DeferredAuthentication.isDeferred(res))
- {
+ if (DeferredAuthentication.isDeferred(res))
+ {
return Authentication.UNAUTHENTICATED;
- }
+ }
LOG.debug("SpengoAuthenticator: sending challenge");
res.setHeader(HttpHeader.WWW_AUTHENTICATE.asString(), HttpHeader.NEGOTIATE.asString());
diff --git a/jetty-security/src/test/java/org/eclipse/jetty/security/AliasedConstraintTest.java b/jetty-security/src/test/java/org/eclipse/jetty/security/AliasedConstraintTest.java
new file mode 100644
index 0000000000..6267cf9ad6
--- /dev/null
+++ b/jetty-security/src/test/java/org/eclipse/jetty/security/AliasedConstraintTest.java
@@ -0,0 +1,174 @@
+//
+// ========================================================================
+// Copyright (c) 1995-2014 Mort Bay Consulting Pty. Ltd.
+// ------------------------------------------------------------------------
+// All rights reserved. This program and the accompanying materials
+// are made available under the terms of the Eclipse Public License v1.0
+// and Apache License v2.0 which accompanies this distribution.
+//
+// The Eclipse Public License is available at
+// http://www.eclipse.org/legal/epl-v10.html
+//
+// The Apache License v2.0 is available at
+// http://www.opensource.org/licenses/apache2.0.php
+//
+// You may elect to redistribute this code under either of these licenses.
+// ========================================================================
+//
+
+package org.eclipse.jetty.security;
+
+import static org.hamcrest.Matchers.*;
+import static org.junit.Assert.*;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+
+import org.eclipse.jetty.http.HttpStatus;
+import org.eclipse.jetty.server.Connector;
+import org.eclipse.jetty.server.LocalConnector;
+import org.eclipse.jetty.server.Server;
+import org.eclipse.jetty.server.handler.ContextHandler;
+import org.eclipse.jetty.server.handler.ResourceHandler;
+import org.eclipse.jetty.server.session.SessionHandler;
+import org.eclipse.jetty.toolchain.test.MavenTestingUtils;
+import org.eclipse.jetty.util.security.Constraint;
+import org.eclipse.jetty.util.security.Password;
+import org.junit.AfterClass;
+import org.junit.BeforeClass;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.Parameterized;
+import org.junit.runners.Parameterized.Parameter;
+import org.junit.runners.Parameterized.Parameters;
+
+/**
+ * Some requests for static data that is served by ResourceHandler, but some is secured.
+ * <p>
+ * This is mainly here to test security bypass techniques using aliased names that should be caught.
+ */
+@RunWith(Parameterized.class)
+public class AliasedConstraintTest
+{
+ private static final String TEST_REALM = "TestRealm";
+ private static Server server;
+ private static LocalConnector connector;
+ private static ConstraintSecurityHandler security;
+
+ @BeforeClass
+ public static void startServer() throws Exception
+ {
+ server = new Server();
+ connector = new LocalConnector(server);
+ server.setConnectors(new Connector[] { connector });
+
+ ContextHandler context = new ContextHandler();
+ SessionHandler session = new SessionHandler();
+
+ HashLoginService loginService = new HashLoginService(TEST_REALM);
+ loginService.putUser("user0",new Password("password"),new String[] {});
+ loginService.putUser("user",new Password("password"),new String[] { "user" });
+ loginService.putUser("user2",new Password("password"),new String[] { "user" });
+ loginService.putUser("admin",new Password("password"),new String[] { "user", "administrator" });
+ loginService.putUser("user3",new Password("password"),new String[] { "foo" });
+
+ context.setContextPath("/ctx");
+ context.setResourceBase(MavenTestingUtils.getTestResourceDir("docroot").getAbsolutePath());
+ server.setHandler(context);
+ context.setHandler(session);
+ // context.addAliasCheck(new AllowSymLinkAliasChecker());
+
+ server.addBean(loginService);
+
+ security = new ConstraintSecurityHandler();
+ session.setHandler(security);
+ ResourceHandler handler = new ResourceHandler();
+ security.setHandler(handler);
+
+ List<ConstraintMapping> constraints = new ArrayList<>();
+
+ Constraint constraint0 = new Constraint();
+ constraint0.setAuthenticate(true);
+ constraint0.setName("forbid");
+ ConstraintMapping mapping0 = new ConstraintMapping();
+ mapping0.setPathSpec("/forbid/*");
+ mapping0.setConstraint(constraint0);
+ constraints.add(mapping0);
+
+ Set<String> knownRoles = new HashSet<>();
+ knownRoles.add("user");
+ knownRoles.add("administrator");
+
+ security.setConstraintMappings(constraints,knownRoles);
+ server.start();
+ }
+
+ @AfterClass
+ public static void stopServer() throws Exception
+ {
+ server.stop();
+ }
+
+ @Parameters(name = "{0}: {1}")
+ public static Collection<Object[]> data()
+ {
+ List<Object[]> data = new ArrayList<>();
+
+ final String OPENCONTENT = "this is open content";
+
+ data.add(new Object[] { "/ctx/all/index.txt", HttpStatus.OK_200, OPENCONTENT });
+ data.add(new Object[] { "/ctx/ALL/index.txt", HttpStatus.NOT_FOUND_404, null });
+ data.add(new Object[] { "/ctx/ALL/Fred/../index.txt", HttpStatus.NOT_FOUND_404, null });
+ data.add(new Object[] { "/ctx/../bar/../ctx/all/index.txt", HttpStatus.OK_200, OPENCONTENT });
+ data.add(new Object[] { "/ctx/forbid/index.txt", HttpStatus.FORBIDDEN_403, null });
+ data.add(new Object[] { "/ctx/all/../forbid/index.txt", HttpStatus.FORBIDDEN_403, null });
+ data.add(new Object[] { "/ctx/FoRbId/index.txt", HttpStatus.NOT_FOUND_404, null });
+
+ return data;
+ }
+
+ @Parameter(value = 0)
+ public String uri;
+
+ @Parameter(value = 1)
+ public int expectedStatusCode;
+
+ @Parameter(value = 2)
+ public String expectedContent;
+
+ @Test
+ public void testAccess() throws Exception
+ {
+ StringBuilder request = new StringBuilder();
+ request.append("GET ").append(uri).append(" HTTP/1.1\r\n");
+ request.append("Host: localhost\r\n");
+ request.append("Connection: close\r\n");
+ request.append("\r\n");
+
+ String response = connector.getResponses(request.toString());
+
+ switch (expectedStatusCode)
+ {
+ case 200:
+ assertThat(response,startsWith("HTTP/1.1 200 OK"));
+ break;
+ case 403:
+ assertThat(response,startsWith("HTTP/1.1 403 Forbidden"));
+ break;
+ case 404:
+ assertThat(response,startsWith("HTTP/1.1 404 Not Found"));
+ break;
+ default:
+ fail("Write a handler for response status code: " + expectedStatusCode);
+ break;
+ }
+
+ if (expectedContent != null)
+ {
+ assertThat(response,containsString("this is open content"));
+ }
+ }
+}
diff --git a/jetty-security/src/test/java/org/eclipse/jetty/security/ConstraintTest.java b/jetty-security/src/test/java/org/eclipse/jetty/security/ConstraintTest.java
index 8897caa712..93b32c7123 100644
--- a/jetty-security/src/test/java/org/eclipse/jetty/security/ConstraintTest.java
+++ b/jetty-security/src/test/java/org/eclipse/jetty/security/ConstraintTest.java
@@ -441,7 +441,7 @@ public class ConstraintTest
Constraint constraint6 = new Constraint();
constraint6.setAuthenticate(true);
- constraint6.setName("omit POST and GET");
+ constraint6.setName("omit HEAD and GET");
constraint6.setRoles(new String[]{"user"});
ConstraintMapping mapping6 = new ConstraintMapping();
mapping6.setPathSpec("/omit/*");
diff --git a/jetty-security/src/test/resources/docroot/all/index.txt b/jetty-security/src/test/resources/docroot/all/index.txt
new file mode 100644
index 0000000000..290f702703
--- /dev/null
+++ b/jetty-security/src/test/resources/docroot/all/index.txt
@@ -0,0 +1 @@
+this is open content. \ No newline at end of file
diff --git a/jetty-security/src/test/resources/docroot/forbid/index.txt b/jetty-security/src/test/resources/docroot/forbid/index.txt
new file mode 100644
index 0000000000..aed1cf32e1
--- /dev/null
+++ b/jetty-security/src/test/resources/docroot/forbid/index.txt
@@ -0,0 +1 @@
+this is forbidden content. \ No newline at end of file
diff --git a/jetty-server/pom.xml b/jetty-server/pom.xml
index 3a3f5ee4fb..d2a4d712db 100644
--- a/jetty-server/pom.xml
+++ b/jetty-server/pom.xml
@@ -2,7 +2,7 @@
<parent>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-project</artifactId>
- <version>9.2.2-SNAPSHOT</version>
+ <version>9.2.3-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>jetty-server</artifactId>
diff --git a/jetty-server/src/main/java/org/eclipse/jetty/server/AbstractConnector.java b/jetty-server/src/main/java/org/eclipse/jetty/server/AbstractConnector.java
index 7d3402fbfa..3106eec257 100644
--- a/jetty-server/src/main/java/org/eclipse/jetty/server/AbstractConnector.java
+++ b/jetty-server/src/main/java/org/eclipse/jetty/server/AbstractConnector.java
@@ -19,8 +19,6 @@
package org.eclipse.jetty.server;
import java.io.IOException;
-import java.net.Socket;
-import java.nio.ByteBuffer;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
@@ -37,9 +35,7 @@ import java.util.concurrent.TimeUnit;
import org.eclipse.jetty.io.ArrayByteBufferPool;
import org.eclipse.jetty.io.ByteBufferPool;
-import org.eclipse.jetty.io.Connection;
import org.eclipse.jetty.io.EndPoint;
-import org.eclipse.jetty.io.ssl.SslConnection;
import org.eclipse.jetty.util.FutureCallback;
import org.eclipse.jetty.util.annotation.ManagedAttribute;
import org.eclipse.jetty.util.annotation.ManagedObject;
@@ -47,7 +43,6 @@ import org.eclipse.jetty.util.component.ContainerLifeCycle;
import org.eclipse.jetty.util.component.Dumpable;
import org.eclipse.jetty.util.log.Log;
import org.eclipse.jetty.util.log.Logger;
-import org.eclipse.jetty.util.ssl.SslContextFactory;
import org.eclipse.jetty.util.thread.ScheduledExecutorScheduler;
import org.eclipse.jetty.util.thread.Scheduler;
@@ -145,7 +140,7 @@ public abstract class AbstractConnector extends ContainerLifeCycle implements Co
private final Scheduler _scheduler;
private final ByteBufferPool _byteBufferPool;
private final Thread[] _acceptors;
- private final Set<EndPoint> _endpoints = Collections.newSetFromMap(new ConcurrentHashMap());
+ private final Set<EndPoint> _endpoints = Collections.newSetFromMap(new ConcurrentHashMap<EndPoint, Boolean>());
private final Set<EndPoint> _immutableEndPoints = Collections.unmodifiableSet(_endpoints);
private volatile CountDownLatch _stopping;
private long _idleTimeout = 30000;
@@ -191,9 +186,9 @@ public abstract class AbstractConnector extends ContainerLifeCycle implements Co
int cores = Runtime.getRuntime().availableProcessors();
if (acceptors < 0)
- acceptors = 1 + cores / 16;
- if (acceptors > 2 * cores)
- LOG.warn("Acceptors should be <= 2*availableProcessors: " + this);
+ acceptors=Math.max(1, Math.min(4,cores/8));
+ if (acceptors > cores)
+ LOG.warn("Acceptors should be <= availableProcessors: " + this);
_acceptors = new Thread[acceptors];
}
@@ -261,7 +256,11 @@ public abstract class AbstractConnector extends ContainerLifeCycle implements Co
_stopping=new CountDownLatch(_acceptors.length);
for (int i = 0; i < _acceptors.length; i++)
- getExecutor().execute(new Acceptor(i));
+ {
+ Acceptor a = new Acceptor(i);
+ addBean(a);
+ getExecutor().execute(a);
+ }
LOG.info("Started {}", this);
}
@@ -299,6 +298,9 @@ public abstract class AbstractConnector extends ContainerLifeCycle implements Co
_stopping=null;
super.doStop();
+
+ for (Acceptor a : getBeans(Acceptor.class))
+ removeBean(a);
LOG.info("Stopped {}", this);
}
@@ -440,6 +442,7 @@ public abstract class AbstractConnector extends ContainerLifeCycle implements Co
private class Acceptor implements Runnable
{
private final int _acceptor;
+ private String _name;
private Acceptor(int id)
{
@@ -450,8 +453,9 @@ public abstract class AbstractConnector extends ContainerLifeCycle implements Co
public void run()
{
Thread current = Thread.currentThread();
- String name = current.getName();
- current.setName(name + "-acceptor-" + _acceptor + "-" + AbstractConnector.this);
+ String name=current.getName();
+ _name=String.format("%s-acceptor-%d@%x-%s",name,_acceptor,hashCode(),AbstractConnector.this.toString());
+ current.setName(_name);
synchronized (AbstractConnector.this)
{
@@ -488,6 +492,16 @@ public abstract class AbstractConnector extends ContainerLifeCycle implements Co
stopping.countDown();
}
}
+
+ @Override
+ public String toString()
+ {
+ String name=_name;
+ if (name==null)
+ return String.format("acceptor-%d@%x", _acceptor, hashCode());
+ return name;
+ }
+
}
diff --git a/jetty-server/src/main/java/org/eclipse/jetty/server/AbstractNCSARequestLog.java b/jetty-server/src/main/java/org/eclipse/jetty/server/AbstractNCSARequestLog.java
index dcaecbe50f..2a16bdd550 100644
--- a/jetty-server/src/main/java/org/eclipse/jetty/server/AbstractNCSARequestLog.java
+++ b/jetty-server/src/main/java/org/eclipse/jetty/server/AbstractNCSARequestLog.java
@@ -25,7 +25,6 @@ import javax.servlet.http.Cookie;
import org.eclipse.jetty.http.HttpHeader;
import org.eclipse.jetty.http.PathMap;
-import org.eclipse.jetty.server.handler.StatisticsHandler;
import org.eclipse.jetty.util.DateCache;
import org.eclipse.jetty.util.annotation.ManagedAttribute;
import org.eclipse.jetty.util.component.AbstractLifeCycle;
diff --git a/jetty-server/src/main/java/org/eclipse/jetty/server/Connector.java b/jetty-server/src/main/java/org/eclipse/jetty/server/Connector.java
index ce4544c900..0ea12cc734 100644
--- a/jetty-server/src/main/java/org/eclipse/jetty/server/Connector.java
+++ b/jetty-server/src/main/java/org/eclipse/jetty/server/Connector.java
@@ -24,7 +24,6 @@ import java.util.concurrent.Executor;
import org.eclipse.jetty.io.ByteBufferPool;
import org.eclipse.jetty.io.EndPoint;
-import org.eclipse.jetty.server.handler.ContextHandler;
import org.eclipse.jetty.util.annotation.ManagedAttribute;
import org.eclipse.jetty.util.annotation.ManagedObject;
import org.eclipse.jetty.util.component.Graceful;
diff --git a/jetty-server/src/main/java/org/eclipse/jetty/server/ForwardedRequestCustomizer.java b/jetty-server/src/main/java/org/eclipse/jetty/server/ForwardedRequestCustomizer.java
index 891e8ee1cf..ff8f14763d 100644
--- a/jetty-server/src/main/java/org/eclipse/jetty/server/ForwardedRequestCustomizer.java
+++ b/jetty-server/src/main/java/org/eclipse/jetty/server/ForwardedRequestCustomizer.java
@@ -20,8 +20,6 @@ package org.eclipse.jetty.server;
import java.net.InetSocketAddress;
-import javax.servlet.ServletRequest;
-
import org.eclipse.jetty.http.HttpFields;
import org.eclipse.jetty.http.HttpHeader;
import org.eclipse.jetty.http.HttpScheme;
diff --git a/jetty-server/src/main/java/org/eclipse/jetty/server/Handler.java b/jetty-server/src/main/java/org/eclipse/jetty/server/Handler.java
index cfe7b9a200..6b7f11fb1b 100644
--- a/jetty-server/src/main/java/org/eclipse/jetty/server/Handler.java
+++ b/jetty-server/src/main/java/org/eclipse/jetty/server/Handler.java
@@ -24,8 +24,6 @@ import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
-import org.eclipse.jetty.server.handler.HandlerCollection;
-import org.eclipse.jetty.server.handler.HandlerWrapper;
import org.eclipse.jetty.util.annotation.ManagedAttribute;
import org.eclipse.jetty.util.annotation.ManagedObject;
import org.eclipse.jetty.util.annotation.ManagedOperation;
diff --git a/jetty-server/src/main/java/org/eclipse/jetty/server/HostHeaderCustomizer.java b/jetty-server/src/main/java/org/eclipse/jetty/server/HostHeaderCustomizer.java
index b39b25dcf4..7911351ef0 100644
--- a/jetty-server/src/main/java/org/eclipse/jetty/server/HostHeaderCustomizer.java
+++ b/jetty-server/src/main/java/org/eclipse/jetty/server/HostHeaderCustomizer.java
@@ -20,8 +20,6 @@ package org.eclipse.jetty.server;
import java.util.Objects;
-import javax.servlet.http.HttpServletRequest;
-
/**
* Customizes requests that lack the {@code Host} header (for example, HTTP 1.0 requests).
* <p />
diff --git a/jetty-server/src/main/java/org/eclipse/jetty/server/HttpChannel.java b/jetty-server/src/main/java/org/eclipse/jetty/server/HttpChannel.java
index e86001ed54..9248d9f874 100644
--- a/jetty-server/src/main/java/org/eclipse/jetty/server/HttpChannel.java
+++ b/jetty-server/src/main/java/org/eclipse/jetty/server/HttpChannel.java
@@ -397,10 +397,14 @@ public class HttpChannel<T> implements HttpParser.RequestHandler<T>, Runnable, H
_state.completed();
if (!_response.isCommitted() && !_request.isHandled())
+ {
_response.sendError(404);
+ }
else
+ {
// Complete generating the response
_response.closeOutput();
+ }
}
catch(EofException|ClosedChannelException e)
{
@@ -795,10 +799,11 @@ public class HttpChannel<T> implements HttpParser.RequestHandler<T>, Runnable, H
/**
* If a write or similar to this channel fails this method should be called. The standard implementation
- * of {@link #failed()} is a noop. But the different implementations of HttpChannel might want to take actions.
+ * is to call {@link HttpTransport#abort()}
*/
- public void failed()
+ public void abort()
{
+ _transport.abort();
}
private class CommitCallback implements Callback
diff --git a/jetty-server/src/main/java/org/eclipse/jetty/server/HttpConfiguration.java b/jetty-server/src/main/java/org/eclipse/jetty/server/HttpConfiguration.java
index 352af25c75..f9c5054714 100644
--- a/jetty-server/src/main/java/org/eclipse/jetty/server/HttpConfiguration.java
+++ b/jetty-server/src/main/java/org/eclipse/jetty/server/HttpConfiguration.java
@@ -54,6 +54,23 @@ public class HttpConfiguration
private boolean _sendXPoweredBy = false; //send X-Powered-By: header
private boolean _sendDateHeader = true; //send Date: header
+
+ /* ------------------------------------------------------------ */
+ /**
+ * <p>An interface that allows a request object to be customized
+ * for a particular HTTP connector configuration. Unlike Filters, customizer are
+ * applied before the request is submitted for processing and can be specific to the
+ * connector on which the request was received.
+ *
+ * <p>Typically Customizers perform tasks such as: <ul>
+ * <li>process header fields that may be injected by a proxy or load balancer.
+ * <li>setup attributes that may come from the connection/connector such as SSL Session IDs
+ * <li>Allow a request to be marked as secure or authenticated if those have been offloaded
+ * and communicated by header, cookie or other out-of-band mechanism
+ * <li>Set request attributes/fields that are determined by the connector on which the
+ * request was received
+ * </ul>
+ */
public interface Customizer
{
public void customize(Connector connector, HttpConfiguration channelConfig, Request request);
@@ -103,7 +120,8 @@ public class HttpConfiguration
{
return _customizers;
}
-
+
+ /* ------------------------------------------------------------ */
public <T> T getCustomizer(Class<T> type)
{
for (Customizer c : _customizers)
diff --git a/jetty-server/src/main/java/org/eclipse/jetty/server/HttpConnection.java b/jetty-server/src/main/java/org/eclipse/jetty/server/HttpConnection.java
index 4d41cce3ab..cec4058cf6 100644
--- a/jetty-server/src/main/java/org/eclipse/jetty/server/HttpConnection.java
+++ b/jetty-server/src/main/java/org/eclipse/jetty/server/HttpConnection.java
@@ -426,11 +426,7 @@ public class HttpConnection extends AbstractConnection implements Runnable, Http
@Override
public void onClose()
{
- if (_sendCallback.isInUse())
- {
- LOG.warn("Closed with pending write:"+this);
- _sendCallback.failed(new EofException("Connection closed"));
- }
+ _sendCallback.close();
super.onClose();
}
@@ -541,11 +537,11 @@ public class HttpConnection extends AbstractConnection implements Runnable, Http
}
@Override
- public void failed()
+ public void abort()
{
- getEndPoint().shutdownOutput();
+ super.abort();
+ _generator.setPersistent(false);
}
-
@Override
public boolean messageComplete()
@@ -580,6 +576,10 @@ public class HttpConnection extends AbstractConnection implements Runnable, Http
_header = null;
_shutdownOut = false;
}
+ else if (isClosed())
+ {
+ callback.failed(new EofException());
+ }
else
{
callback.failed(new WritePendingException());
@@ -705,7 +705,7 @@ public class HttpConnection extends AbstractConnection implements Runnable, Http
@Override
public String toString()
{
- return String.format("SendCB@%x{s=%s,i=%s,cb=%s}",hashCode(),getState(),_info,_callback);
+ return String.format("%s[i=%s,cb=%s]",super.toString(),_info,_callback);
}
}
diff --git a/jetty-server/src/main/java/org/eclipse/jetty/server/HttpOutput.java b/jetty-server/src/main/java/org/eclipse/jetty/server/HttpOutput.java
index d638984a39..12a23d5fb3 100644
--- a/jetty-server/src/main/java/org/eclipse/jetty/server/HttpOutput.java
+++ b/jetty-server/src/main/java/org/eclipse/jetty/server/HttpOutput.java
@@ -24,10 +24,7 @@ import java.nio.ByteBuffer;
import java.nio.channels.ReadableByteChannel;
import java.nio.channels.WritePendingException;
import java.util.concurrent.atomic.AtomicReference;
-import javax.servlet.RequestDispatcher;
import javax.servlet.ServletOutputStream;
-import javax.servlet.ServletRequest;
-import javax.servlet.ServletResponse;
import javax.servlet.WriteListener;
import org.eclipse.jetty.http.HttpContent;
@@ -160,7 +157,7 @@ public class HttpOutput extends ServletOutputStream implements Runnable
catch(IOException e)
{
LOG.debug(e);
- _channel.failed();
+ _channel.abort();
}
releaseBuffer();
return;
@@ -195,7 +192,7 @@ public class HttpOutput extends ServletOutputStream implements Runnable
catch(IOException e)
{
LOG.debug(e);
- _channel.failed();
+ _channel.abort();
}
releaseBuffer();
return;
diff --git a/jetty-server/src/main/java/org/eclipse/jetty/server/InclusiveByteRange.java b/jetty-server/src/main/java/org/eclipse/jetty/server/InclusiveByteRange.java
index cb81d3c95e..95e894afc2 100644
--- a/jetty-server/src/main/java/org/eclipse/jetty/server/InclusiveByteRange.java
+++ b/jetty-server/src/main/java/org/eclipse/jetty/server/InclusiveByteRange.java
@@ -81,7 +81,7 @@ public class InclusiveByteRange
* @param size Size of the resource.
* @return LazyList of satisfiable ranges
*/
- public static List<InclusiveByteRange> satisfiableRanges(Enumeration headers, long size)
+ public static List<InclusiveByteRange> satisfiableRanges(Enumeration<String> headers, long size)
{
Object satRanges=null;
@@ -89,7 +89,7 @@ public class InclusiveByteRange
headers:
while (headers.hasMoreElements())
{
- String header = (String) headers.nextElement();
+ String header = headers.nextElement();
StringTokenizer tok = new StringTokenizer(header,"=,",false);
String t=null;
try
diff --git a/jetty-server/src/main/java/org/eclipse/jetty/server/LocalConnector.java b/jetty-server/src/main/java/org/eclipse/jetty/server/LocalConnector.java
index 1f05003a3d..26ff80fb5b 100644
--- a/jetty-server/src/main/java/org/eclipse/jetty/server/LocalConnector.java
+++ b/jetty-server/src/main/java/org/eclipse/jetty/server/LocalConnector.java
@@ -138,7 +138,8 @@ public class LocalConnector extends AbstractConnector
LocalEndPoint endp = executeRequest(requestsBuffer);
endp.waitUntilClosedOrIdleFor(idleFor,units);
ByteBuffer responses = endp.takeOutput();
- endp.getConnection().close();
+ if (endp.isOutputShutdown())
+ endp.close();
if (LOG.isDebugEnabled())
LOG.debug("responses {}", BufferUtil.toUTF8String(responses));
return responses;
@@ -157,6 +158,8 @@ public class LocalConnector extends AbstractConnector
private LocalEndPoint executeRequest(ByteBuffer rawRequest)
{
+ if (!isStarted())
+ throw new IllegalStateException("!STARTED");
LocalEndPoint endp = new LocalEndPoint();
endp.setInput(rawRequest);
_connects.add(endp);
diff --git a/jetty-server/src/main/java/org/eclipse/jetty/server/Request.java b/jetty-server/src/main/java/org/eclipse/jetty/server/Request.java
index 8dbb07792f..330bb40cd9 100644
--- a/jetty-server/src/main/java/org/eclipse/jetty/server/Request.java
+++ b/jetty-server/src/main/java/org/eclipse/jetty/server/Request.java
@@ -1247,7 +1247,7 @@ public class Request implements HttpServletRequest
_port=0;
return _serverName;
}
- _serverName = hostPort.substring(1,len-1);
+ _serverName = hostPort.substring(0,len);
}
else if (len==hostPort.length())
_serverName=hostPort;
diff --git a/jetty-server/src/main/java/org/eclipse/jetty/server/ResourceCache.java b/jetty-server/src/main/java/org/eclipse/jetty/server/ResourceCache.java
index e39c4a60fb..dc686260cd 100644
--- a/jetty-server/src/main/java/org/eclipse/jetty/server/ResourceCache.java
+++ b/jetty-server/src/main/java/org/eclipse/jetty/server/ResourceCache.java
@@ -33,7 +33,6 @@ import java.util.concurrent.atomic.AtomicReference;
import org.eclipse.jetty.http.DateGenerator;
import org.eclipse.jetty.http.HttpContent;
-import org.eclipse.jetty.http.HttpContent.ResourceAsHttpContent;
import org.eclipse.jetty.http.MimeTypes;
import org.eclipse.jetty.util.BufferUtil;
import org.eclipse.jetty.util.log.Log;
diff --git a/jetty-server/src/main/java/org/eclipse/jetty/server/Response.java b/jetty-server/src/main/java/org/eclipse/jetty/server/Response.java
index eb95e20401..79f4e4989c 100644
--- a/jetty-server/src/main/java/org/eclipse/jetty/server/Response.java
+++ b/jetty-server/src/main/java/org/eclipse/jetty/server/Response.java
@@ -541,10 +541,7 @@ public class Response implements HttpServletResponse
@Override
public void sendError(int sc) throws IOException
{
- if (sc == 102)
- sendProcessing();
- else
- sendError(sc, null);
+ sendError(sc, null);
}
@Override
@@ -553,6 +550,17 @@ public class Response implements HttpServletResponse
if (isIncluding())
return;
+ switch(code)
+ {
+ case -1:
+ _channel.abort();
+ return;
+ case 102:
+ sendProcessing();
+ return;
+ default:
+ }
+
if (isCommitted())
LOG.warn("Committed before "+code+" "+message);
diff --git a/jetty-server/src/main/java/org/eclipse/jetty/server/SecureRequestCustomizer.java b/jetty-server/src/main/java/org/eclipse/jetty/server/SecureRequestCustomizer.java
index b017461310..dd26b04b14 100644
--- a/jetty-server/src/main/java/org/eclipse/jetty/server/SecureRequestCustomizer.java
+++ b/jetty-server/src/main/java/org/eclipse/jetty/server/SecureRequestCustomizer.java
@@ -20,8 +20,10 @@ package org.eclipse.jetty.server;
import java.security.cert.X509Certificate;
+import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLEngine;
import javax.net.ssl.SSLSession;
+import javax.servlet.ServletRequest;
import org.eclipse.jetty.http.HttpScheme;
import org.eclipse.jetty.io.ssl.SslConnection;
@@ -31,6 +33,12 @@ import org.eclipse.jetty.util.log.Log;
import org.eclipse.jetty.util.log.Logger;
import org.eclipse.jetty.util.ssl.SslContextFactory;
+
+/* ------------------------------------------------------------ */
+/** Customizer that extracts the attribute from an {@link SSLContext}
+ * and sets them on the request with {@link ServletRequest#setAttribute(String, Object)}
+ * according to Servlet Specification Requirements.
+ */
public class SecureRequestCustomizer implements HttpConfiguration.Customizer
{
private static final Logger LOG = Log.getLogger(SecureRequestCustomizer.class);
@@ -40,7 +48,6 @@ public class SecureRequestCustomizer implements HttpConfiguration.Customizer
*/
public static final String CACHED_INFO_ATTR = CachedInfo.class.getName();
-
@Override
public void customize(Connector connector, HttpConfiguration channelConfig, Request request)
{
@@ -53,14 +60,11 @@ public class SecureRequestCustomizer implements HttpConfiguration.Customizer
SSLEngine sslEngine=sslConnection.getSSLEngine();
customize(sslEngine,request);
}
-
}
/* ------------------------------------------------------------ */
/*
- * Allow the Listener a chance to customise the request. before the server
- * does its stuff. <br>
- * This allows the required attributes to be set for SSL requests. <br>
+ * Customise the request attributes to be set for SSL requests. <br>
* The requirements of the Servlet specs are:
* <ul>
* <li> an attribute named "javax.servlet.request.ssl_session_id" of type
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 66919f42a7..ce4bdd9097 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
@@ -18,6 +18,7 @@
package org.eclipse.jetty.server;
+import java.awt.geom.PathIterator;
import java.io.IOException;
import java.lang.management.ManagementFactory;
import java.net.InetAddress;
@@ -32,6 +33,7 @@ import java.util.List;
import java.util.concurrent.CopyOnWriteArrayList;
import java.util.concurrent.Future;
import java.util.concurrent.TimeUnit;
+
import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
@@ -46,11 +48,13 @@ import org.eclipse.jetty.http.HttpStatus;
import org.eclipse.jetty.http.HttpURI;
import org.eclipse.jetty.server.handler.ContextHandler;
import org.eclipse.jetty.server.handler.HandlerWrapper;
+import org.eclipse.jetty.server.handler.StatisticsHandler;
import org.eclipse.jetty.util.Attributes;
import org.eclipse.jetty.util.AttributesMap;
import org.eclipse.jetty.util.Jetty;
import org.eclipse.jetty.util.MultiException;
import org.eclipse.jetty.util.URIUtil;
+import org.eclipse.jetty.util.UrlEncoded;
import org.eclipse.jetty.util.annotation.ManagedAttribute;
import org.eclipse.jetty.util.annotation.ManagedObject;
import org.eclipse.jetty.util.annotation.Name;
@@ -143,6 +147,25 @@ public class Server extends HandlerWrapper implements Attributes
}
/* ------------------------------------------------------------ */
+ /**
+ * Set a graceful stop time.
+ * The {@link StatisticsHandler} must be configured so that open connections can
+ * be tracked for a graceful shutdown.
+ * @see org.eclipse.jetty.util.component.ContainerLifeCycle#setStopTimeout(long)
+ */
+ @Override
+ public void setStopTimeout(long stopTimeout)
+ {
+ super.setStopTimeout(stopTimeout);
+ }
+
+ /* ------------------------------------------------------------ */
+ /** Set stop server at shutdown behaviour.
+ * @param stop If true, this server instance will be explicitly stopped when the
+ * JVM is shutdown. Otherwise the JVM is stopped with the server running.
+ * @see Runtime#addShutdownHook(Thread)
+ * @see ShutdownThread
+ */
public void setStopAtShutdown(boolean stop)
{
//if we now want to stop
@@ -397,7 +420,7 @@ public class Server extends HandlerWrapper implements Attributes
}
catch (Exception e)
{
- mex.add(e.getCause());
+ mex.add(e);
}
}
}
@@ -474,7 +497,6 @@ public class Server extends HandlerWrapper implements Attributes
response.sendError(HttpStatus.BAD_REQUEST_400);
request.setHandled(true);
response.setStatus(200);
- response.getHttpFields().put(HttpHeader.ALLOW,"GET,POST,HEAD,OPTIONS");
response.setContentLength(0);
response.closeOutput();
}
@@ -492,15 +514,15 @@ public class Server extends HandlerWrapper implements Attributes
final Request baseRequest=connection.getRequest();
final String path=event.getPath();
-
+
if (path!=null)
{
// this is a dispatch with a path
ServletContext context=event.getServletContext();
- HttpURI uri = new HttpURI(context==null?path:URIUtil.addPaths(context.getContextPath(),path));
+ HttpURI uri = new HttpURI(URIUtil.addPaths(context==null?null:context.getContextPath(), path));
baseRequest.setUri(uri);
baseRequest.setRequestURI(null);
- baseRequest.setPathInfo(baseRequest.getRequestURI());
+ baseRequest.setPathInfo(uri.getDecodedPath());
if (uri.getQuery()!=null)
baseRequest.mergeQueryParameters(uri.getQuery(), true); //we have to assume dispatch path and query are UTF8
}
@@ -606,6 +628,7 @@ public class Server extends HandlerWrapper implements Attributes
/**
* @return The URI of the first {@link NetworkConnector} and first {@link ContextHandler}, or null
*/
+ @SuppressWarnings("resource")
public URI getURI()
{
NetworkConnector connector=null;
@@ -652,6 +675,7 @@ public class Server extends HandlerWrapper implements Attributes
return this.getClass().getName()+"@"+Integer.toHexString(hashCode());
}
+ /* ------------------------------------------------------------ */
@Override
public void dump(Appendable out,String indent) throws IOException
{
diff --git a/jetty-server/src/main/java/org/eclipse/jetty/server/ServerConnector.java b/jetty-server/src/main/java/org/eclipse/jetty/server/ServerConnector.java
index a7d5fe0f2d..f4da30c004 100644
--- a/jetty-server/src/main/java/org/eclipse/jetty/server/ServerConnector.java
+++ b/jetty-server/src/main/java/org/eclipse/jetty/server/ServerConnector.java
@@ -20,12 +20,10 @@ package org.eclipse.jetty.server;
import java.io.IOException;
import java.net.InetSocketAddress;
-import java.net.ServerSocket;
import java.net.Socket;
import java.net.SocketException;
import java.nio.channels.Channel;
import java.nio.channels.SelectionKey;
-import java.nio.channels.Selector;
import java.nio.channels.ServerSocketChannel;
import java.nio.channels.SocketChannel;
import java.util.concurrent.Executor;
@@ -37,7 +35,6 @@ import org.eclipse.jetty.io.EndPoint;
import org.eclipse.jetty.io.SelectChannelEndPoint;
import org.eclipse.jetty.io.SelectorManager;
import org.eclipse.jetty.io.SelectorManager.ManagedSelector;
-import org.eclipse.jetty.util.Callback;
import org.eclipse.jetty.util.annotation.ManagedAttribute;
import org.eclipse.jetty.util.annotation.ManagedObject;
import org.eclipse.jetty.util.annotation.Name;
@@ -208,7 +205,8 @@ public class ServerConnector extends AbstractNetworkConnector
@Name("factories") ConnectionFactory... factories)
{
super(server,executor,scheduler,bufferPool,acceptors,factories);
- _manager = new ServerConnectorManager(getExecutor(), getScheduler(), selectors > 0 ? selectors : Runtime.getRuntime().availableProcessors());
+ _manager = new ServerConnectorManager(getExecutor(), getScheduler(),
+ selectors>0?selectors:Math.max(1,Math.min(4,Runtime.getRuntime().availableProcessors()/2)));
addBean(_manager, true);
}
diff --git a/jetty-server/src/main/java/org/eclipse/jetty/server/ServletRequestHttpWrapper.java b/jetty-server/src/main/java/org/eclipse/jetty/server/ServletRequestHttpWrapper.java
index 11f249e139..8ac5a48207 100644
--- a/jetty-server/src/main/java/org/eclipse/jetty/server/ServletRequestHttpWrapper.java
+++ b/jetty-server/src/main/java/org/eclipse/jetty/server/ServletRequestHttpWrapper.java
@@ -48,126 +48,151 @@ public class ServletRequestHttpWrapper extends ServletRequestWrapper implements
super(request);
}
+ @Override
public String getAuthType()
{
return null;
}
+ @Override
public Cookie[] getCookies()
{
return null;
}
+ @Override
public long getDateHeader(String name)
{
return 0;
}
+ @Override
public String getHeader(String name)
{
return null;
}
- public Enumeration getHeaders(String name)
+ @Override
+ public Enumeration<String> getHeaders(String name)
{
return null;
}
- public Enumeration getHeaderNames()
+ @Override
+ public Enumeration<String> getHeaderNames()
{
return null;
}
+ @Override
public int getIntHeader(String name)
{
return 0;
}
+ @Override
public String getMethod()
{
return null;
}
+ @Override
public String getPathInfo()
{
return null;
}
+ @Override
public String getPathTranslated()
{
return null;
}
+ @Override
public String getContextPath()
{
return null;
}
+ @Override
public String getQueryString()
{
return null;
}
+ @Override
public String getRemoteUser()
{
return null;
}
+ @Override
public boolean isUserInRole(String role)
{
return false;
}
+ @Override
public Principal getUserPrincipal()
{
return null;
}
+ @Override
public String getRequestedSessionId()
{
return null;
}
+ @Override
public String getRequestURI()
{
return null;
}
+ @Override
public StringBuffer getRequestURL()
{
return null;
}
+ @Override
public String getServletPath()
{
return null;
}
+ @Override
public HttpSession getSession(boolean create)
{
return null;
}
+ @Override
public HttpSession getSession()
{
return null;
}
+ @Override
public boolean isRequestedSessionIdValid()
{
return false;
}
+ @Override
public boolean isRequestedSessionIdFromCookie()
{
return false;
}
+ @Override
public boolean isRequestedSessionIdFromURL()
{
return false;
}
+ @Override
public boolean isRequestedSessionIdFromUrl()
{
return false;
@@ -176,6 +201,7 @@ public class ServletRequestHttpWrapper extends ServletRequestWrapper implements
/**
* @see javax.servlet.http.HttpServletRequest#authenticate(javax.servlet.http.HttpServletResponse)
*/
+ @Override
public boolean authenticate(HttpServletResponse response) throws IOException, ServletException
{
return false;
@@ -184,6 +210,7 @@ public class ServletRequestHttpWrapper extends ServletRequestWrapper implements
/**
* @see javax.servlet.http.HttpServletRequest#getPart(java.lang.String)
*/
+ @Override
public Part getPart(String name) throws IOException, ServletException
{
return null;
@@ -192,6 +219,7 @@ public class ServletRequestHttpWrapper extends ServletRequestWrapper implements
/**
* @see javax.servlet.http.HttpServletRequest#getParts()
*/
+ @Override
public Collection<Part> getParts() throws IOException, ServletException
{
return null;
@@ -200,6 +228,7 @@ public class ServletRequestHttpWrapper extends ServletRequestWrapper implements
/**
* @see javax.servlet.http.HttpServletRequest#login(java.lang.String, java.lang.String)
*/
+ @Override
public void login(String username, String password) throws ServletException
{
@@ -208,6 +237,7 @@ public class ServletRequestHttpWrapper extends ServletRequestWrapper implements
/**
* @see javax.servlet.http.HttpServletRequest#logout()
*/
+ @Override
public void logout() throws ServletException
{
diff --git a/jetty-server/src/main/java/org/eclipse/jetty/server/SessionManager.java b/jetty-server/src/main/java/org/eclipse/jetty/server/SessionManager.java
index 267391b56d..d6ca22d61e 100644
--- a/jetty-server/src/main/java/org/eclipse/jetty/server/SessionManager.java
+++ b/jetty-server/src/main/java/org/eclipse/jetty/server/SessionManager.java
@@ -23,7 +23,6 @@ import java.util.Set;
import javax.servlet.SessionCookieConfig;
import javax.servlet.SessionTrackingMode;
-import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;
diff --git a/jetty-server/src/main/java/org/eclipse/jetty/server/ShutdownMonitor.java b/jetty-server/src/main/java/org/eclipse/jetty/server/ShutdownMonitor.java
index abc6d61ef8..38b866574d 100644
--- a/jetty-server/src/main/java/org/eclipse/jetty/server/ShutdownMonitor.java
+++ b/jetty-server/src/main/java/org/eclipse/jetty/server/ShutdownMonitor.java
@@ -54,20 +54,18 @@ public class ShutdownMonitor
}
/**
- * ShutdownMonitorThread
+ * ShutdownMonitorRunnable
*
* Thread for listening to STOP.PORT for command to stop Jetty.
* If ShowndownMonitor.exitVm is true, then Sytem.exit will also be
* called after the stop.
*
*/
- public class ShutdownMonitorThread extends Thread
+ private class ShutdownMonitorRunnable implements Runnable
{
-
- public ShutdownMonitorThread ()
+ public ShutdownMonitorRunnable()
{
- setDaemon(true);
- setName("ShutdownMonitor");
+ startListenSocket();
}
@Override
@@ -102,7 +100,7 @@ public class ShutdownMonitor
// Graceful Shutdown
debug("Issuing graceful shutdown..");
ShutdownThread.getInstance().run();
-
+
//Stop accepting any more
close(serverSocket);
serverSocket = null;
@@ -148,28 +146,7 @@ public class ShutdownMonitor
}
}
- public void start()
- {
- if (isAlive())
- {
- // TODO why are we reentrant here?
- if (DEBUG)
- System.err.printf("ShutdownMonitorThread already started");
- return; // cannot start it again
- }
-
- startListenSocket();
-
- if (serverSocket == null)
- {
- return;
- }
- if (DEBUG)
- System.err.println("Starting ShutdownMonitorThread");
- super.start();
- }
-
- private void startListenSocket()
+ public void startListenSocket()
{
if (port < 0)
{
@@ -217,9 +194,7 @@ public class ShutdownMonitor
private String key;
private boolean exitVm;
private ServerSocket serverSocket;
- private ShutdownMonitorThread thread;
-
-
+ private Thread thread;
/**
* Create a ShutdownMonitor using configuration from the System properties.
@@ -372,18 +347,20 @@ public class ShutdownMonitor
protected void start() throws Exception
{
- ShutdownMonitorThread t = null;
+ Thread t = null;
+
synchronized (this)
{
if (thread != null && thread.isAlive())
{
- // TODO why are we reentrant here?
if (DEBUG)
System.err.printf("ShutdownMonitorThread already started");
return; // cannot start it again
}
- thread = new ShutdownMonitorThread();
+ thread = new Thread(new ShutdownMonitorRunnable());
+ thread.setDaemon(true);
+ thread.setName("ShutdownMonitor");
t = thread;
}
diff --git a/jetty-server/src/main/java/org/eclipse/jetty/server/handler/AbstractHandlerContainer.java b/jetty-server/src/main/java/org/eclipse/jetty/server/handler/AbstractHandlerContainer.java
index 0d54e536fb..16a09aca5f 100644
--- a/jetty-server/src/main/java/org/eclipse/jetty/server/handler/AbstractHandlerContainer.java
+++ b/jetty-server/src/main/java/org/eclipse/jetty/server/handler/AbstractHandlerContainer.java
@@ -58,6 +58,7 @@ public abstract class AbstractHandlerContainer extends AbstractHandler implement
}
/* ------------------------------------------------------------ */
+ @SuppressWarnings("unchecked")
@Override
public <T extends Handler> T getChildHandlerByClass(Class<T> byclass)
{
@@ -103,6 +104,7 @@ public abstract class AbstractHandlerContainer extends AbstractHandler implement
{
for (Handler h:branches)
{
+ @SuppressWarnings("unchecked")
T container = (T)h;
Handler[] candidates = container.getChildHandlersByClass(handler.getClass());
if (candidates!=null)
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 f01f73a4ab..ed6efd1b65 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
@@ -36,7 +36,6 @@ import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
-import java.util.ListIterator;
import java.util.Locale;
import java.util.Map;
import java.util.Set;
@@ -67,7 +66,6 @@ import javax.servlet.http.HttpServletResponse;
import org.eclipse.jetty.http.MimeTypes;
import org.eclipse.jetty.server.ClassLoaderDump;
-import org.eclipse.jetty.server.Connector;
import org.eclipse.jetty.server.Dispatcher;
import org.eclipse.jetty.server.Handler;
import org.eclipse.jetty.server.HandlerContainer;
@@ -108,7 +106,7 @@ public class ContextHandler extends ScopedHandler implements Attributes, Gracefu
{
public final static int SERVLET_MAJOR_VERSION=3;
public final static int SERVLET_MINOR_VERSION=0;
- public static final Class[] SERVLET_LISTENER_TYPES = new Class[] {ServletContextListener.class,
+ public static final Class<?>[] SERVLET_LISTENER_TYPES = new Class[] {ServletContextListener.class,
ServletContextAttributeListener.class,
ServletRequestListener.class,
ServletRequestAttributeListener.class};
@@ -510,8 +508,7 @@ public class ContextHandler extends ScopedHandler implements Attributes, Gracefu
/*
* @see javax.servlet.ServletContext#getInitParameterNames()
*/
- @SuppressWarnings("rawtypes")
- public Enumeration getInitParameterNames()
+ public Enumeration<String> getInitParameterNames()
{
return Collections.enumeration(_initParams.keySet());
}
@@ -873,27 +870,8 @@ public class ContextHandler extends ScopedHandler implements Attributes, Gracefu
_scontext.clearAttributes();
}
- /* ------------------------------------------------------------ */
- /*
- * @see org.eclipse.jetty.server.Handler#handle(javax.servlet.http.HttpServletRequest, javax.servlet.http.HttpServletResponse)
- */
- public boolean checkContext(final String target, final Request baseRequest, final HttpServletResponse response) throws IOException
+ public boolean checkVirtualHost(final Request baseRequest)
{
- DispatcherType dispatch = baseRequest.getDispatcherType();
-
- switch (_availability)
- {
- case SHUTDOWN:
- case UNAVAILABLE:
- baseRequest.setHandled(true);
- response.sendError(HttpServletResponse.SC_SERVICE_UNAVAILABLE);
- return false;
- default:
- if ((DispatcherType.REQUEST.equals(dispatch) && baseRequest.isHandled()))
- return false;
- }
-
- // Check the vhosts
if (_vhosts != null && _vhosts.length > 0)
{
String vhost = normalizeHostname(baseRequest.getServerName());
@@ -929,27 +907,61 @@ public class ContextHandler extends ScopedHandler implements Attributes, Gracefu
if (!match || connectorName && !connectorMatch)
return false;
}
-
+ return true;
+ }
+
+ public boolean checkContextPath(String uri)
+ {
// Are we not the root context?
if (_contextPath.length() > 1)
{
// reject requests that are not for us
- if (!target.startsWith(_contextPath))
+ if (!uri.startsWith(_contextPath))
return false;
- if (target.length() > _contextPath.length() && target.charAt(_contextPath.length()) != '/')
+ if (uri.length() > _contextPath.length() && uri.charAt(_contextPath.length()) != '/')
return false;
+ }
+ return true;
+ }
+
+ /* ------------------------------------------------------------ */
+ /*
+ * @see org.eclipse.jetty.server.Handler#handle(javax.servlet.http.HttpServletRequest, javax.servlet.http.HttpServletResponse)
+ */
+ public boolean checkContext(final String target, final Request baseRequest, final HttpServletResponse response) throws IOException
+ {
+ DispatcherType dispatch = baseRequest.getDispatcherType();
- // redirect null path infos
- if (!_allowNullPathInfo && _contextPath.length() == target.length())
- {
- // context request must end with /
+ // Check the vhosts
+ if (!checkVirtualHost(baseRequest))
+ return false;
+
+ if (!checkContextPath(target))
+ return false;
+
+ // Are we not the root context?
+ // redirect null path infos
+ if (!_allowNullPathInfo && _contextPath.length() == target.length() && _contextPath.length()>1)
+ {
+ // context request must end with /
+ baseRequest.setHandled(true);
+ if (baseRequest.getQueryString() != null)
+ response.sendRedirect(URIUtil.addPaths(baseRequest.getRequestURI(),URIUtil.SLASH) + "?" + baseRequest.getQueryString());
+ else
+ response.sendRedirect(URIUtil.addPaths(baseRequest.getRequestURI(),URIUtil.SLASH));
+ return false;
+ }
+
+ switch (_availability)
+ {
+ case SHUTDOWN:
+ case UNAVAILABLE:
baseRequest.setHandled(true);
- if (baseRequest.getQueryString() != null)
- response.sendRedirect(URIUtil.addPaths(baseRequest.getRequestURI(),URIUtil.SLASH) + "?" + baseRequest.getQueryString());
- else
- response.sendRedirect(URIUtil.addPaths(baseRequest.getRequestURI(),URIUtil.SLASH));
+ response.sendError(HttpServletResponse.SC_SERVICE_UNAVAILABLE);
return false;
- }
+ default:
+ if ((DispatcherType.REQUEST.equals(dispatch) && baseRequest.isHandled()))
+ return false;
}
return true;
@@ -1129,7 +1141,6 @@ public class ContextHandler extends ScopedHandler implements Attributes, Gracefu
if (!_requestAttributeListeners.isEmpty())
{
- ListIterator<ServletRequestAttributeListener> iter = _requestAttributeListeners.listIterator(_requestAttributeListeners.size());
for (int i=_requestAttributeListeners.size();i-->0;)
baseRequest.removeEventListener(_requestAttributeListeners.get(i));
}
@@ -1648,10 +1659,15 @@ public class ContextHandler extends ScopedHandler implements Attributes, Gracefu
}
/* ------------------------------------------------------------ */
+ /**
+ * @param path
+ * @param resource
+ * @return True if the alias is OK
+ */
public boolean checkAlias(String path, Resource resource)
{
// Is the resource aliased?
- if (resource.getAlias() != null)
+ if (resource.getAlias() != null)
{
if (LOG.isDebugEnabled())
LOG.debug("Aliased resource: " + resource + "~=" + resource.getAlias());
@@ -1880,7 +1896,7 @@ public class ContextHandler extends ScopedHandler implements Attributes, Gracefu
matched_path = context_path;
}
- if (matched_path.equals(context_path))
+ if (matched_path != null && matched_path.equals(context_path))
contexts.add(ch);
}
}
@@ -2058,7 +2074,6 @@ public class ContextHandler extends ScopedHandler implements Attributes, Gracefu
/*
* @see javax.servlet.ServletContext#getInitParameterNames()
*/
- @SuppressWarnings("unchecked")
@Override
public Enumeration<String> getInitParameterNames()
{
@@ -2195,6 +2210,7 @@ public class ContextHandler extends ScopedHandler implements Attributes, Gracefu
try
{
+ @SuppressWarnings("unchecked")
Class<? extends EventListener> clazz = _classLoader==null?Loader.loadClass(ContextHandler.class,className):_classLoader.loadClass(className);
addListener(clazz);
}
@@ -2289,9 +2305,9 @@ public class ContextHandler extends ScopedHandler implements Attributes, Gracefu
//classloader, or a parent of it
try
{
- Class reflect = Loader.loadClass(getClass(), "sun.reflect.Reflection");
+ Class<?> reflect = Loader.loadClass(getClass(), "sun.reflect.Reflection");
Method getCallerClass = reflect.getMethod("getCallerClass", Integer.TYPE);
- Class caller = (Class)getCallerClass.invoke(null, 2);
+ Class<?> caller = (Class<?>)getCallerClass.invoke(null, 2);
boolean ok = false;
ClassLoader callerLoader = caller.getClassLoader();
diff --git a/jetty-server/src/main/java/org/eclipse/jetty/server/handler/ContextHandlerCollection.java b/jetty-server/src/main/java/org/eclipse/jetty/server/handler/ContextHandlerCollection.java
index 4ade364903..2d77d1c2af 100644
--- a/jetty-server/src/main/java/org/eclipse/jetty/server/handler/ContextHandlerCollection.java
+++ b/jetty-server/src/main/java/org/eclipse/jetty/server/handler/ContextHandlerCollection.java
@@ -19,6 +19,15 @@
package org.eclipse.jetty.server.handler;
import java.io.IOException;
+import java.lang.reflect.Array;
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.ConcurrentMap;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
@@ -52,7 +61,8 @@ public class ContextHandlerCollection extends HandlerCollection
{
private static final Logger LOG = Log.getLogger(ContextHandlerCollection.class);
- private volatile Trie<ContextHandler[]> _contexts;
+ private final ConcurrentMap<ContextHandler,Handler> _contextBranches = new ConcurrentHashMap<>();
+ private volatile Trie<Map.Entry<String,Branch[]>> _pathBranches;
private Class<? extends ContextHandler> _contextClass = ContextHandler.class;
/* ------------------------------------------------------------ */
@@ -69,71 +79,70 @@ public class ContextHandlerCollection extends HandlerCollection
@ManagedOperation("update the mapping of context path to context")
public void mapContexts()
{
- int capacity=512;
+ _contextBranches.clear();
+
+ if (getHandlers()==null)
+ {
+ _pathBranches=new ArrayTernaryTrie<>(false,16);
+ return;
+ }
+
+ // Create map of contextPath to handler Branch
+ Map<String,Branch[]> map = new HashMap<>();
+ for (Handler handler:getHandlers())
+ {
+ Branch branch=new Branch(handler);
+ for (String contextPath : branch.getContextPaths())
+ {
+ Branch[] branches=map.get(contextPath);
+ map.put(contextPath, ArrayUtil.addToArray(branches, branch, Branch.class));
+ }
+
+ for (ContextHandler context : branch.getContextHandlers())
+ _contextBranches.putIfAbsent(context, branch.getHandler());
+ }
+
+ // Sort the branches so those with virtual hosts are considered before those without
+ for (Map.Entry<String,Branch[]> entry: map.entrySet())
+ {
+ Branch[] branches=entry.getValue();
+ Branch[] sorted=new Branch[branches.length];
+ int i=0;
+ for (Branch branch:branches)
+ if (branch.hasVirtualHost())
+ sorted[i++]=branch;
+ for (Branch branch:branches)
+ if (!branch.hasVirtualHost())
+ sorted[i++]=branch;
+ entry.setValue(sorted);
+ }
// Loop until we have a big enough trie to hold all the context paths
- Trie<ContextHandler[]> trie;
+ int capacity=512;
+ Trie<Map.Entry<String,Branch[]>> trie;
loop: while(true)
{
trie=new ArrayTernaryTrie<>(false,capacity);
-
- Handler[] branches = getHandlers();
-
- // loop over each group of contexts
- for (int b=0;branches!=null && b<branches.length;b++)
+ for (Map.Entry<String,Branch[]> entry: map.entrySet())
{
- Handler[] handlers=null;
-
- if (branches[b] instanceof ContextHandler)
+ if (!trie.put(entry.getKey().substring(1),entry))
{
- handlers = new Handler[]{ branches[b] };
- }
- else if (branches[b] instanceof HandlerContainer)
- {
- handlers = ((HandlerContainer)branches[b]).getChildHandlersByClass(ContextHandler.class);
- }
- else
- continue;
-
- // for each context handler in a group
- for (int i=0;handlers!=null && i<handlers.length;i++)
- {
- ContextHandler handler=(ContextHandler)handlers[i];
- String contextPath=handler.getContextPath().substring(1);
- ContextHandler[] contexts=trie.get(contextPath);
-
- if (!trie.put(contextPath,ArrayUtil.addToArray(contexts,handler,ContextHandler.class)))
- {
- capacity+=512;
- continue loop;
- }
+ capacity+=512;
+ continue loop;
}
}
-
- break;
+ break loop;
}
+
- // Sort the contexts so those with virtual hosts are considered before those without
- for (String ctx : trie.keySet())
+ if (LOG.isDebugEnabled())
{
- ContextHandler[] contexts=trie.get(ctx);
- ContextHandler[] sorted=new ContextHandler[contexts.length];
- int i=0;
- for (ContextHandler handler:contexts)
- if (handler.getVirtualHosts()!=null && handler.getVirtualHosts().length>0)
- sorted[i++]=handler;
- for (ContextHandler handler:contexts)
- if (handler.getVirtualHosts()==null || handler.getVirtualHosts().length==0)
- sorted[i++]=handler;
- trie.put(ctx,sorted);
+ for (String ctx : trie.keySet())
+ LOG.debug("{}->{}",ctx,Arrays.asList(trie.get(ctx).getValue()));
}
-
- //for (String ctx : trie.keySet())
- // System.err.printf("'%s'->%s%n",ctx,Arrays.asList(trie.get(ctx)));
- _contexts=trie;
+ _pathBranches=trie;
}
-
/* ------------------------------------------------------------ */
/*
* @see org.eclipse.jetty.server.server.handler.HandlerCollection#setHandlers(org.eclipse.jetty.server.server.Handler[])
@@ -164,60 +173,66 @@ public class ContextHandlerCollection extends HandlerCollection
{
Handler[] handlers = getHandlers();
if (handlers==null || handlers.length==0)
- return;
+ return;
- HttpChannelState async = baseRequest.getHttpChannelState();
- if (async.isAsync())
- {
- ContextHandler context=async.getContextHandler();
- if (context!=null)
- {
- context.handle(target,baseRequest,request, response);
- return;
- }
- }
-
- // data structure which maps a request to a context; first-best match wins
- // { context path => [ context ] }
- // }
- if (target.startsWith("/"))
- {
- int limit = target.length()-1;
-
- while (limit>=0)
- {
- // Get best match
- ContextHandler[] contexts = _contexts.getBest(target,1,limit);
- if (contexts==null)
- break;
+ HttpChannelState async = baseRequest.getHttpChannelState();
+ if (async.isAsync())
+ {
+ ContextHandler context=async.getContextHandler();
+ if (context!=null)
+ {
+ Handler branch = _contextBranches.get(context);
+
+ if (branch==null)
+ context.handle(target,baseRequest,request, response);
+ else
+ branch.handle(target, baseRequest, request, response);
+ return;
+ }
+ }
+
+ // data structure which maps a request to a context; first-best match wins
+ // { context path => [ context ] }
+ // }
+ if (target.startsWith("/"))
+ {
+ int limit = target.length()-1;
- int l=contexts[0].getContextPath().length();
- if (l==1 || target.length()==l || target.charAt(l)=='/')
- {
- for (ContextHandler handler : contexts)
- {
- handler.handle(target,baseRequest, request, response);
- if (baseRequest.isHandled())
- return;
- }
- }
-
- limit=l-2;
- }
- }
- else
- {
+ while (limit>=0)
+ {
+ // Get best match
+ Map.Entry<String,Branch[]> branches = _pathBranches.getBest(target,1,limit);
+
+
+ if (branches==null)
+ break;
+
+ int l=branches.getKey().length();
+ if (l==1 || target.length()==l || target.charAt(l)=='/')
+ {
+ for (Branch branch : branches.getValue())
+ {
+ branch.getHandler().handle(target,baseRequest, request, response);
+ if (baseRequest.isHandled())
+ return;
+ }
+ }
+
+ limit=l-2;
+ }
+ }
+ else
+ {
// This may not work in all circumstances... but then I think it should never be called
- for (int i=0;i<handlers.length;i++)
- {
- handlers[i].handle(target,baseRequest, request, response);
- if ( baseRequest.isHandled())
- return;
- }
- }
+ for (int i=0;i<handlers.length;i++)
+ {
+ handlers[i].handle(target,baseRequest, request, response);
+ if ( baseRequest.isHandled())
+ return;
+ }
+ }
}
-
/* ------------------------------------------------------------ */
/** Add a context handler.
* @param contextPath The context path to add
@@ -263,5 +278,64 @@ public class ContextHandlerCollection extends HandlerCollection
_contextClass = contextClass;
}
+ /* ------------------------------------------------------------ */
+ /* ------------------------------------------------------------ */
+ /* ------------------------------------------------------------ */
+ private final static class Branch
+ {
+ private final Handler _handler;
+ private final ContextHandler[] _contexts;
+
+ Branch(Handler handler)
+ {
+ _handler=handler;
+
+ if (handler instanceof ContextHandler)
+ {
+ _contexts = new ContextHandler[]{(ContextHandler)handler};
+ }
+ else if (handler instanceof HandlerContainer)
+ {
+ Handler[] contexts=((HandlerContainer)handler).getChildHandlersByClass(ContextHandler.class);
+ _contexts = new ContextHandler[contexts.length];
+ System.arraycopy(contexts, 0, _contexts, 0, contexts.length);
+ }
+ else
+ _contexts = new ContextHandler[0];
+ }
+
+ Set<String> getContextPaths()
+ {
+ Set<String> set = new HashSet<String>();
+ for (ContextHandler context:_contexts)
+ set.add(context.getContextPath());
+ return set;
+ }
+
+ boolean hasVirtualHost()
+ {
+ for (ContextHandler context:_contexts)
+ if (context.getVirtualHosts()!=null && context.getVirtualHosts().length>0)
+ return true;
+ return false;
+ }
+
+ ContextHandler[] getContextHandlers()
+ {
+ return _contexts;
+ }
+
+ Handler getHandler()
+ {
+ return _handler;
+ }
+
+ @Override
+ public String toString()
+ {
+ return String.format("{%s,%s}",_handler,Arrays.asList(_contexts));
+ }
+ }
+
}
diff --git a/jetty-server/src/main/java/org/eclipse/jetty/server/handler/DefaultHandler.java b/jetty-server/src/main/java/org/eclipse/jetty/server/handler/DefaultHandler.java
index f71720af41..cf92003c0e 100644
--- a/jetty-server/src/main/java/org/eclipse/jetty/server/handler/DefaultHandler.java
+++ b/jetty-server/src/main/java/org/eclipse/jetty/server/handler/DefaultHandler.java
@@ -117,62 +117,63 @@ public class DefaultHandler extends AbstractHandler
response.setStatus(HttpServletResponse.SC_NOT_FOUND);
response.setContentType(MimeTypes.Type.TEXT_HTML.toString());
- ByteArrayISO8859Writer writer = new ByteArrayISO8859Writer(1500);
-
- writer.write("<HTML>\n<HEAD>\n<TITLE>Error 404 - Not Found");
- writer.write("</TITLE>\n<BODY>\n<H2>Error 404 - Not Found.</H2>\n");
- writer.write("No context on this server matched or handled this request.<BR>");
- writer.write("Contexts known to this server are: <ul>");
+ try (ByteArrayISO8859Writer writer = new ByteArrayISO8859Writer(1500);)
+ {
+ writer.write("<HTML>\n<HEAD>\n<TITLE>Error 404 - Not Found");
+ writer.write("</TITLE>\n<BODY>\n<H2>Error 404 - Not Found.</H2>\n");
+ writer.write("No context on this server matched or handled this request.<BR>");
+ writer.write("Contexts known to this server are: <ul>");
- Server server = getServer();
- Handler[] handlers = server==null?null:server.getChildHandlersByClass(ContextHandler.class);
+ Server server = getServer();
+ Handler[] handlers = server==null?null:server.getChildHandlersByClass(ContextHandler.class);
- for (int i=0;handlers!=null && i<handlers.length;i++)
- {
- ContextHandler context = (ContextHandler)handlers[i];
- if (context.isRunning())
- {
- writer.write("<li><a href=\"");
- if (context.getVirtualHosts()!=null && context.getVirtualHosts().length>0)
- writer.write("http://"+context.getVirtualHosts()[0]+":"+request.getLocalPort());
- writer.write(context.getContextPath());
- if (context.getContextPath().length()>1 && context.getContextPath().endsWith("/"))
- writer.write("/");
- writer.write("\">");
- writer.write(context.getContextPath());
- if (context.getVirtualHosts()!=null && context.getVirtualHosts().length>0)
- writer.write("&nbsp;@&nbsp;"+context.getVirtualHosts()[0]+":"+request.getLocalPort());
- writer.write("&nbsp;--->&nbsp;");
- writer.write(context.toString());
- writer.write("</a></li>\n");
- }
- else
+ for (int i=0;handlers!=null && i<handlers.length;i++)
{
- writer.write("<li>");
- writer.write(context.getContextPath());
- if (context.getVirtualHosts()!=null && context.getVirtualHosts().length>0)
- writer.write("&nbsp;@&nbsp;"+context.getVirtualHosts()[0]+":"+request.getLocalPort());
- writer.write("&nbsp;--->&nbsp;");
- writer.write(context.toString());
- if (context.isFailed())
- writer.write(" [failed]");
- if (context.isStopped())
- writer.write(" [stopped]");
- writer.write("</li>\n");
+ ContextHandler context = (ContextHandler)handlers[i];
+ if (context.isRunning())
+ {
+ writer.write("<li><a href=\"");
+ if (context.getVirtualHosts()!=null && context.getVirtualHosts().length>0)
+ writer.write("http://"+context.getVirtualHosts()[0]+":"+request.getLocalPort());
+ writer.write(context.getContextPath());
+ if (context.getContextPath().length()>1 && context.getContextPath().endsWith("/"))
+ writer.write("/");
+ writer.write("\">");
+ writer.write(context.getContextPath());
+ if (context.getVirtualHosts()!=null && context.getVirtualHosts().length>0)
+ writer.write("&nbsp;@&nbsp;"+context.getVirtualHosts()[0]+":"+request.getLocalPort());
+ writer.write("&nbsp;--->&nbsp;");
+ writer.write(context.toString());
+ writer.write("</a></li>\n");
+ }
+ else
+ {
+ writer.write("<li>");
+ writer.write(context.getContextPath());
+ if (context.getVirtualHosts()!=null && context.getVirtualHosts().length>0)
+ writer.write("&nbsp;@&nbsp;"+context.getVirtualHosts()[0]+":"+request.getLocalPort());
+ writer.write("&nbsp;--->&nbsp;");
+ writer.write(context.toString());
+ if (context.isFailed())
+ writer.write(" [failed]");
+ if (context.isStopped())
+ writer.write(" [stopped]");
+ writer.write("</li>\n");
+ }
}
- }
- writer.write("</ul><hr>");
- writer.write("<a href=\"http://eclipse.org/jetty\"><img border=0 src=\"/favicon.ico\"/></a>&nbsp;");
- writer.write("<a href=\"http://eclipse.org/jetty\">Powered by Jetty:// Java Web Server</a><hr/>\n");
+ writer.write("</ul><hr>");
+ writer.write("<a href=\"http://eclipse.org/jetty\"><img border=0 src=\"/favicon.ico\"/></a>&nbsp;");
+ writer.write("<a href=\"http://eclipse.org/jetty\">Powered by Jetty:// Java Web Server</a><hr/>\n");
- writer.write("\n</BODY>\n</HTML>\n");
- writer.flush();
- response.setContentLength(writer.size());
- try (OutputStream out=response.getOutputStream())
- {
- writer.writeTo(out);
- }
+ writer.write("\n</BODY>\n</HTML>\n");
+ writer.flush();
+ response.setContentLength(writer.size());
+ try (OutputStream out=response.getOutputStream())
+ {
+ writer.writeTo(out);
+ }
+ }
}
/* ------------------------------------------------------------ */
diff --git a/jetty-server/src/main/java/org/eclipse/jetty/server/handler/HandlerCollection.java b/jetty-server/src/main/java/org/eclipse/jetty/server/handler/HandlerCollection.java
index c118c7ec1d..b79b75dc23 100644
--- a/jetty-server/src/main/java/org/eclipse/jetty/server/handler/HandlerCollection.java
+++ b/jetty-server/src/main/java/org/eclipse/jetty/server/handler/HandlerCollection.java
@@ -19,6 +19,7 @@
package org.eclipse.jetty.server.handler;
import java.io.IOException;
+import java.util.Arrays;
import java.util.List;
import javax.servlet.ServletException;
@@ -185,4 +186,12 @@ public class HandlerCollection extends AbstractHandlerContainer
child.destroy();
super.destroy();
}
+
+ /* ------------------------------------------------------------ */
+ @Override
+ public String toString()
+ {
+ Handler[] handlers=getHandlers();
+ return super.toString()+(handlers==null?"[]":Arrays.asList(getHandlers()).toString());
+ }
}
diff --git a/jetty-server/src/main/java/org/eclipse/jetty/server/handler/HandlerWrapper.java b/jetty-server/src/main/java/org/eclipse/jetty/server/handler/HandlerWrapper.java
index dcbf6ff5d5..88226c951e 100644
--- a/jetty-server/src/main/java/org/eclipse/jetty/server/handler/HandlerWrapper.java
+++ b/jetty-server/src/main/java/org/eclipse/jetty/server/handler/HandlerWrapper.java
@@ -30,7 +30,6 @@ import org.eclipse.jetty.server.Request;
import org.eclipse.jetty.server.Server;
import org.eclipse.jetty.util.annotation.ManagedAttribute;
import org.eclipse.jetty.util.annotation.ManagedObject;
-import org.eclipse.jetty.util.component.LifeCycle;
/* ------------------------------------------------------------ */
/** A <code>HandlerWrapper</code> acts as a {@link Handler} but delegates the {@link Handler#handle handle} method and
diff --git a/jetty-server/src/main/java/org/eclipse/jetty/server/handler/ResourceHandler.java b/jetty-server/src/main/java/org/eclipse/jetty/server/handler/ResourceHandler.java
index 1db4283bc6..7c3f2a3886 100644
--- a/jetty-server/src/main/java/org/eclipse/jetty/server/handler/ResourceHandler.java
+++ b/jetty-server/src/main/java/org/eclipse/jetty/server/handler/ResourceHandler.java
@@ -308,15 +308,16 @@ public class ResourceHandler extends HandlerWrapper
{
if (_context==null)
return null;
- base=_context.getBaseResource();
- if (base==null)
- return null;
+ return _context.getResource(path);
}
try
{
path=URIUtil.canonicalPath(path);
- return base.addPath(path);
+ Resource r = base.addPath(path);
+ if (r!=null && r.getAlias()!=null && !_context.checkAlias(path, r))
+ return null;
+ return r;
}
catch(Exception e)
{
diff --git a/jetty-server/src/main/java/org/eclipse/jetty/server/handler/ShutdownHandler.java b/jetty-server/src/main/java/org/eclipse/jetty/server/handler/ShutdownHandler.java
index 93c9f86a57..9c948ae0e7 100644
--- a/jetty-server/src/main/java/org/eclipse/jetty/server/handler/ShutdownHandler.java
+++ b/jetty-server/src/main/java/org/eclipse/jetty/server/handler/ShutdownHandler.java
@@ -133,6 +133,7 @@ public class ShutdownHandler extends HandlerWrapper
}
}
+ @SuppressWarnings("resource")
private String getServerUrl()
{
NetworkConnector connector=null;
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 ec586ac09c..3bed6cda0c 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
@@ -397,7 +397,6 @@ public abstract class AbstractSession implements AbstractSessionManager.SessionI
}
/* ------------------------------------------------------------ */
- @SuppressWarnings({ "unchecked" })
@Override
public Enumeration<String> getAttributeNames()
{
diff --git a/jetty-server/src/main/java/org/eclipse/jetty/server/session/AbstractSessionManager.java b/jetty-server/src/main/java/org/eclipse/jetty/server/session/AbstractSessionManager.java
index 1f966c5957..aa039081e6 100644
--- a/jetty-server/src/main/java/org/eclipse/jetty/server/session/AbstractSessionManager.java
+++ b/jetty-server/src/main/java/org/eclipse/jetty/server/session/AbstractSessionManager.java
@@ -227,10 +227,10 @@ public abstract class AbstractSessionManager extends ContainerLifeCycle implemen
_context=ContextHandler.getCurrentContext();
_loader=Thread.currentThread().getContextClassLoader();
- if (_sessionIdManager==null)
+ final Server server=getSessionHandler().getServer();
+ synchronized (server)
{
- final Server server=getSessionHandler().getServer();
- synchronized (server)
+ if (_sessionIdManager==null)
{
_sessionIdManager=server.getSessionIdManager();
if (_sessionIdManager==null)
diff --git a/jetty-server/src/main/java/org/eclipse/jetty/server/session/HashSessionIdManager.java b/jetty-server/src/main/java/org/eclipse/jetty/server/session/HashSessionIdManager.java
index a17bc06f76..382b633b5c 100644
--- a/jetty-server/src/main/java/org/eclipse/jetty/server/session/HashSessionIdManager.java
+++ b/jetty-server/src/main/java/org/eclipse/jetty/server/session/HashSessionIdManager.java
@@ -32,8 +32,6 @@ import java.util.Set;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;
-import org.eclipse.jetty.server.SessionIdManager;
-
/* ------------------------------------------------------------ */
/**
* HashSessionIdManager. An in-memory implementation of the session ID manager.
diff --git a/jetty-server/src/main/java/org/eclipse/jetty/server/session/HashSessionManager.java b/jetty-server/src/main/java/org/eclipse/jetty/server/session/HashSessionManager.java
index 1effd32f94..53ccd6398e 100644
--- a/jetty-server/src/main/java/org/eclipse/jetty/server/session/HashSessionManager.java
+++ b/jetty-server/src/main/java/org/eclipse/jetty/server/session/HashSessionManager.java
@@ -19,7 +19,6 @@
package org.eclipse.jetty.server.session;
import java.io.DataInputStream;
-import java.io.EOFException;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
@@ -34,10 +33,8 @@ import java.util.concurrent.TimeUnit;
import javax.servlet.ServletContext;
import javax.servlet.http.HttpServletRequest;
-import org.eclipse.jetty.server.SessionIdManager;
import org.eclipse.jetty.server.handler.ContextHandler;
import org.eclipse.jetty.util.ClassLoadingObjectInputStream;
-import org.eclipse.jetty.util.IO;
import org.eclipse.jetty.util.log.Logger;
import org.eclipse.jetty.util.thread.ScheduledExecutorScheduler;
import org.eclipse.jetty.util.thread.Scheduler;
@@ -308,9 +305,9 @@ public class HashSessionManager extends AbstractSessionManager
_scavengePeriodMs=period;
- if (_timer!=null && (period!=old_period || _task==null))
+ synchronized (this)
{
- synchronized (this)
+ if (_timer!=null && (period!=old_period || _task==null))
{
if (_task!=null)
{
@@ -569,18 +566,22 @@ public class HashSessionManager extends AbstractSessionManager
{
File file = new File(_storeDir,idInCuster);
- FileInputStream in = null;
Exception error = null;
- try
+ if (!file.exists())
{
- if (file.exists())
+ if (LOG.isDebugEnabled())
{
- in = new FileInputStream(file);
- HashedSession session = restoreSession(in, null);
- addSession(session, false);
- session.didActivate();
- return session;
+ LOG.debug("Not loading: {}",file);
}
+ return null;
+ }
+
+ try (FileInputStream in = new FileInputStream(file))
+ {
+ HashedSession session = restoreSession(in,null);
+ addSession(session,false);
+ session.didActivate();
+ return session;
}
catch (Exception e)
{
@@ -588,8 +589,6 @@ public class HashSessionManager extends AbstractSessionManager
}
finally
{
- if (in != null) IO.close(in);
-
if (error != null)
{
if (isDeleteUnrestorableSessions() && file.exists() && file.getParentFile().equals(_storeDir) )
@@ -603,7 +602,10 @@ public class HashSessionManager extends AbstractSessionManager
}
}
else
- file.delete(); //delete successfully restored file
+ {
+ // delete successfully restored file
+ file.delete();
+ }
}
return null;
}
@@ -641,8 +643,10 @@ public class HashSessionManager extends AbstractSessionManager
if (session == null)
session = (HashedSession)newSession(created, accessed, clusterId);
+
session.setRequests(requests);
+ // Attributes
int size = di.readInt();
restoreSessionAttributes(di, size, session);
@@ -652,7 +656,7 @@ public class HashSessionManager extends AbstractSessionManager
int maxIdle = di.readInt();
session.setMaxInactiveInterval(maxIdle);
}
- catch (EOFException e)
+ catch (IOException e)
{
LOG.debug("No maxInactiveInterval persisted for session "+clusterId);
LOG.ignore(e);
@@ -661,12 +665,14 @@ public class HashSessionManager extends AbstractSessionManager
return session;
}
-
+
+ @SuppressWarnings("resource")
private void restoreSessionAttributes (InputStream is, int size, HashedSession session)
throws Exception
{
if (size>0)
{
+ // input stream should not be closed here
ClassLoadingObjectInputStream ois = new ClassLoadingObjectInputStream(is);
for (int i=0; i<size;i++)
{
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 d36e4277e4..9bfa84d989 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
@@ -145,24 +145,23 @@ public class HashedSession extends MemSession
throws Exception
{
File file = null;
- FileOutputStream fos = null;
if (!_saveFailed && _hashSessionManager._storeDir != null)
{
- try
+ file = new File(_hashSessionManager._storeDir, super.getId());
+ if (file.exists())
+ {
+ file.delete();
+ }
+
+ try(FileOutputStream fos = new FileOutputStream(file,false))
{
- file = new File(_hashSessionManager._storeDir, super.getId());
- if (file.exists())
- file.delete();
- file.createNewFile();
- fos = new FileOutputStream(file);
save(fos);
- IO.close(fos);
}
catch (Exception e)
{
saveFailed(); // We won't try again for this session
- if (fos != null) IO.close(fos);
- if (file != null) file.delete(); // No point keeping the file if we didn't save the whole session
+ if (file != null)
+ file.delete(); // No point keeping the file if we didn't save the whole session
throw e;
}
}
diff --git a/jetty-server/src/main/java/org/eclipse/jetty/server/session/JDBCSessionIdManager.java b/jetty-server/src/main/java/org/eclipse/jetty/server/session/JDBCSessionIdManager.java
index a70d48ecfe..535dc5f02e 100644
--- a/jetty-server/src/main/java/org/eclipse/jetty/server/session/JDBCSessionIdManager.java
+++ b/jetty-server/src/main/java/org/eclipse/jetty/server/session/JDBCSessionIdManager.java
@@ -778,10 +778,10 @@ public class JDBCSessionIdManager extends AbstractSessionIdManager
if (LOG.isDebugEnabled())
LOG.debug("Scavenging every "+_scavengeIntervalMs+" ms");
- //if (_timer!=null && (period!=old_period || _task==null))
- if (_scheduler != null && (period!=old_period || _task==null))
+ synchronized (this)
{
- synchronized (this)
+ //if (_timer!=null && (period!=old_period || _task==null))
+ if (_scheduler != null && (period!=old_period || _task==null))
{
if (_task!=null)
_task.cancel();
diff --git a/jetty-server/src/main/java/org/eclipse/jetty/server/session/JDBCSessionManager.java b/jetty-server/src/main/java/org/eclipse/jetty/server/session/JDBCSessionManager.java
index fb4d7468c5..a84376b02a 100644
--- a/jetty-server/src/main/java/org/eclipse/jetty/server/session/JDBCSessionManager.java
+++ b/jetty-server/src/main/java/org/eclipse/jetty/server/session/JDBCSessionManager.java
@@ -37,10 +37,6 @@ import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicReference;
import javax.servlet.http.HttpServletRequest;
-import javax.servlet.http.HttpSessionEvent;
-import javax.servlet.http.HttpSessionListener;
-
-import org.eclipse.jetty.server.SessionIdManager;
import org.eclipse.jetty.server.handler.ContextHandler;
import org.eclipse.jetty.server.session.JDBCSessionIdManager.SessionTableSchema;
import org.eclipse.jetty.util.ClassLoadingObjectInputStream;
diff --git a/jetty-server/src/main/java/org/eclipse/jetty/server/session/SessionHandler.java b/jetty-server/src/main/java/org/eclipse/jetty/server/session/SessionHandler.java
index e85cc9e2ed..fc86f3de5f 100644
--- a/jetty-server/src/main/java/org/eclipse/jetty/server/session/SessionHandler.java
+++ b/jetty-server/src/main/java/org/eclipse/jetty/server/session/SessionHandler.java
@@ -49,10 +49,12 @@ public class SessionHandler extends ScopedHandler
final static Logger LOG = Log.getLogger("org.eclipse.jetty.server.session");
public final static EnumSet<SessionTrackingMode> DEFAULT_TRACKING = EnumSet.of(SessionTrackingMode.COOKIE,SessionTrackingMode.URL);
-
- public static final Class[] SESSION_LISTENER_TYPES = new Class[] {HttpSessionAttributeListener.class,
- HttpSessionIdListener.class,
- HttpSessionListener.class};
+
+ @SuppressWarnings("unchecked")
+ public static final Class<? extends EventListener>[] SESSION_LISTENER_TYPES =
+ new Class[] {HttpSessionAttributeListener.class,
+ HttpSessionIdListener.class,
+ HttpSessionListener.class};
diff --git a/jetty-server/src/test/java/org/eclipse/jetty/server/CheckReverseProxyHeadersTest.java b/jetty-server/src/test/java/org/eclipse/jetty/server/CheckReverseProxyHeadersTest.java
index 506ff9e2ea..cb60e0627d 100644
--- a/jetty-server/src/test/java/org/eclipse/jetty/server/CheckReverseProxyHeadersTest.java
+++ b/jetty-server/src/test/java/org/eclipse/jetty/server/CheckReverseProxyHeadersTest.java
@@ -66,7 +66,7 @@ public class CheckReverseProxyHeadersTest
@Override
public void validate(HttpServletRequest request)
{
- assertEquals("::1", request.getServerName());
+ assertEquals("[::1]", request.getServerName());
assertEquals(80, request.getServerPort());
assertEquals("10.20.30.40", request.getRemoteAddr());
assertEquals("10.20.30.40", request.getRemoteHost());
@@ -84,7 +84,7 @@ public class CheckReverseProxyHeadersTest
@Override
public void validate(HttpServletRequest request)
{
- assertEquals("::1", request.getServerName());
+ assertEquals("[::1]", request.getServerName());
assertEquals(8888, request.getServerPort());
assertEquals("10.20.30.40", request.getRemoteAddr());
assertEquals("10.20.30.40", request.getRemoteHost());
diff --git a/jetty-server/src/test/java/org/eclipse/jetty/server/GracefulStopTest.java b/jetty-server/src/test/java/org/eclipse/jetty/server/GracefulStopTest.java
index 2794cfb1f9..6943f768ce 100644
--- a/jetty-server/src/test/java/org/eclipse/jetty/server/GracefulStopTest.java
+++ b/jetty-server/src/test/java/org/eclipse/jetty/server/GracefulStopTest.java
@@ -30,6 +30,8 @@ import javax.servlet.http.HttpServletResponse;
import org.eclipse.jetty.server.handler.AbstractHandler;
import org.eclipse.jetty.server.handler.StatisticsHandler;
import org.eclipse.jetty.util.IO;
+import org.eclipse.jetty.util.log.Log;
+import org.eclipse.jetty.util.log.StdErrLog;
import org.hamcrest.Matchers;
import org.junit.Assert;
import org.junit.Before;
@@ -79,6 +81,35 @@ public class GracefulStopTest
Assert.assertThat(out,Matchers.containsString("200 OK"));
}
}
+
+ @Test
+ public void testGracefulTimout() throws Exception
+ {
+ server.setStopTimeout(100);
+ new Thread()
+ {
+ @Override
+ public void run()
+ {
+ try
+ {
+ TimeUnit.SECONDS.sleep(1);
+ server.stop();
+ }
+ catch (Exception e)
+ {
+ //e.printStackTrace();
+ }
+ }
+ }.start();
+
+ try(Socket socket = new Socket("localhost",server.getBean(NetworkConnector.class).getLocalPort());)
+ {
+ socket.getOutputStream().write("GET / HTTP/1.0\r\n\r\n".getBytes(StandardCharsets.ISO_8859_1));
+ String out = IO.toString(socket.getInputStream());
+ Assert.assertEquals("",out);
+ }
+ }
private static class TestHandler extends AbstractHandler
{
diff --git a/jetty-server/src/test/java/org/eclipse/jetty/server/HttpConnectionTest.java b/jetty-server/src/test/java/org/eclipse/jetty/server/HttpConnectionTest.java
index 96056fda5f..d582e578ce 100644
--- a/jetty-server/src/test/java/org/eclipse/jetty/server/HttpConnectionTest.java
+++ b/jetty-server/src/test/java/org/eclipse/jetty/server/HttpConnectionTest.java
@@ -723,7 +723,6 @@ public class HttpConnectionTest
"12345\015\012"+
"0;\015\012\015\012");
offset = checkContains(response,offset,"HTTP/1.1 200");
- offset = checkContains(response,offset,"Allow: GET,POST,HEAD");
offset=0;
response=connector.getResponses("GET * HTTP/1.1\n"+
diff --git a/jetty-server/src/test/java/org/eclipse/jetty/server/HttpURITest.java b/jetty-server/src/test/java/org/eclipse/jetty/server/HttpURITest.java
index e2b4f213d3..58497def1b 100644
--- a/jetty-server/src/test/java/org/eclipse/jetty/server/HttpURITest.java
+++ b/jetty-server/src/test/java/org/eclipse/jetty/server/HttpURITest.java
@@ -136,11 +136,11 @@ public class HttpURITest
/*33*/ {"/?abc=test",null, null, null,null,"/", null,"abc=test",null},
/*34*/ {"/#fragment",null, null, null,null,"/", null,null,"fragment"},
/*35*/ {"http://192.0.0.1:8080/","http","//192.0.0.1:8080","192.0.0.1","8080","/",null,null,null},
- /*36*/ {"http://[2001:db8::1]:8080/","http","//[2001:db8::1]:8080","2001:db8::1","8080","/",null,null,null},
- /*37*/ {"http://user@[2001:db8::1]:8080/","http","//user@[2001:db8::1]:8080","2001:db8::1","8080","/",null,null,null},
- /*38*/ {"http://[2001:db8::1]/","http","//[2001:db8::1]","2001:db8::1",null,"/",null,null,null},
+ /*36*/ {"http://[2001:db8::1]:8080/","http","//[2001:db8::1]:8080","[2001:db8::1]","8080","/",null,null,null},
+ /*37*/ {"http://user@[2001:db8::1]:8080/","http","//user@[2001:db8::1]:8080","[2001:db8::1]","8080","/",null,null,null},
+ /*38*/ {"http://[2001:db8::1]/","http","//[2001:db8::1]","[2001:db8::1]",null,"/",null,null,null},
/*39*/ {"//[2001:db8::1]:8080/",null,null,null,null,"//[2001:db8::1]:8080/",null,null,null},
- /*40*/ {"http://user@[2001:db8::1]:8080/","http","//user@[2001:db8::1]:8080","2001:db8::1","8080","/",null,null,null},
+ /*40*/ {"http://user@[2001:db8::1]:8080/","http","//user@[2001:db8::1]:8080","[2001:db8::1]","8080","/",null,null,null},
/*41*/ {"*",null,null,null,null,"*",null, null,null}
};
@@ -353,7 +353,7 @@ public class HttpURITest
{
/* 0*/ {" localhost:8080 ","localhost","8080"},
/* 1*/ {" 127.0.0.1:8080 ","127.0.0.1","8080"},
- /* 2*/ {" [127::0::0::1]:8080 ","127::0::0::1","8080"},
+ /* 2*/ {" [127::0::0::1]:8080 ","[127::0::0::1]","8080"},
/* 3*/ {" error ",null,null},
/* 4*/ {" http://localhost:8080/ ",null,null},
};
diff --git a/jetty-server/src/test/java/org/eclipse/jetty/server/NetworkTrafficListenerTest.java b/jetty-server/src/test/java/org/eclipse/jetty/server/NetworkTrafficListenerTest.java
index ca9d7999cb..21589a4442 100644
--- a/jetty-server/src/test/java/org/eclipse/jetty/server/NetworkTrafficListenerTest.java
+++ b/jetty-server/src/test/java/org/eclipse/jetty/server/NetworkTrafficListenerTest.java
@@ -41,7 +41,6 @@ import org.eclipse.jetty.io.NetworkTrafficListener;
import org.eclipse.jetty.server.handler.AbstractHandler;
import org.eclipse.jetty.util.BufferUtil;
import org.junit.After;
-import org.junit.Ignore;
import org.junit.Test;
public class NetworkTrafficListenerTest
diff --git a/jetty-server/src/test/java/org/eclipse/jetty/server/PartialRFC2616Test.java b/jetty-server/src/test/java/org/eclipse/jetty/server/PartialRFC2616Test.java
index 1643bab762..bfb52afab0 100644
--- a/jetty-server/src/test/java/org/eclipse/jetty/server/PartialRFC2616Test.java
+++ b/jetty-server/src/test/java/org/eclipse/jetty/server/PartialRFC2616Test.java
@@ -495,7 +495,6 @@ public class PartialRFC2616Test
"Host: localhost\n"+
"\n");
offset=checkContains(response,offset, "HTTP/1.1 200","200")+1;
- offset=checkContains(response,offset, "Allow: GET,POST,HEAD,OPTIONS","Allow")+1;
offset=0;
response=connector.getResponses("GET * HTTP/1.1\n"+
diff --git a/jetty-server/src/test/java/org/eclipse/jetty/server/RequestTest.java b/jetty-server/src/test/java/org/eclipse/jetty/server/RequestTest.java
index e9ed6d78d6..ef8025c70e 100644
--- a/jetty-server/src/test/java/org/eclipse/jetty/server/RequestTest.java
+++ b/jetty-server/src/test/java/org/eclipse/jetty/server/RequestTest.java
@@ -65,7 +65,6 @@ import org.eclipse.jetty.util.log.Logger;
import org.eclipse.jetty.util.log.StdErrLog;
import org.hamcrest.Matchers;
import org.junit.After;
-import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;
@@ -486,7 +485,7 @@ public class RequestTest
assertThat(response,Matchers.containsString("200 OK"));
assertEquals("http://[::1]/",results.get(i++));
assertEquals("0.0.0.0",results.get(i++));
- assertEquals("::1",results.get(i++));
+ assertEquals("[::1]",results.get(i++));
assertEquals("80",results.get(i++));
@@ -500,7 +499,7 @@ public class RequestTest
assertThat(response,Matchers.containsString("200 OK"));
assertEquals("http://[::1]:8888/",results.get(i++));
assertEquals("0.0.0.0",results.get(i++));
- assertEquals("::1",results.get(i++));
+ assertEquals("[::1]",results.get(i++));
assertEquals("8888",results.get(i++));
@@ -516,7 +515,7 @@ public class RequestTest
assertThat(response,Matchers.containsString("200 OK"));
assertEquals("https://[::1]/",results.get(i++));
assertEquals("remote",results.get(i++));
- assertEquals("::1",results.get(i++));
+ assertEquals("[::1]",results.get(i++));
assertEquals("443",results.get(i++));
@@ -532,7 +531,7 @@ public class RequestTest
assertThat(response,Matchers.containsString("200 OK"));
assertEquals("https://[::1]:8888/",results.get(i++));
assertEquals("remote",results.get(i++));
- assertEquals("::1",results.get(i++));
+ assertEquals("[::1]",results.get(i++));
assertEquals("8888",results.get(i++));
}
diff --git a/jetty-server/src/test/java/org/eclipse/jetty/server/ServerConnectorTest.java b/jetty-server/src/test/java/org/eclipse/jetty/server/ServerConnectorTest.java
new file mode 100644
index 0000000000..03ee046aa8
--- /dev/null
+++ b/jetty-server/src/test/java/org/eclipse/jetty/server/ServerConnectorTest.java
@@ -0,0 +1,197 @@
+//
+// ========================================================================
+// Copyright (c) 1995-2014 Mort Bay Consulting Pty. Ltd.
+// ------------------------------------------------------------------------
+// All rights reserved. This program and the accompanying materials
+// are made available under the terms of the Eclipse Public License v1.0
+// and Apache License v2.0 which accompanies this distribution.
+//
+// The Eclipse Public License is available at
+// http://www.eclipse.org/legal/epl-v10.html
+//
+// The Apache License v2.0 is available at
+// http://www.opensource.org/licenses/apache2.0.php
+//
+// You may elect to redistribute this code under either of these licenses.
+// ========================================================================
+//
+
+package org.eclipse.jetty.server;
+
+import static org.hamcrest.Matchers.*;
+import static org.junit.Assert.*;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.PrintWriter;
+import java.lang.reflect.Field;
+import java.net.HttpURLConnection;
+import java.net.MalformedURLException;
+import java.net.Socket;
+import java.net.URI;
+import java.net.URISyntaxException;
+import java.nio.charset.StandardCharsets;
+
+import javax.servlet.ServletException;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import org.eclipse.jetty.io.ChannelEndPoint;
+import org.eclipse.jetty.io.EndPoint;
+import org.eclipse.jetty.server.handler.AbstractHandler;
+import org.eclipse.jetty.server.handler.DefaultHandler;
+import org.eclipse.jetty.server.handler.HandlerList;
+import org.eclipse.jetty.util.IO;
+import org.junit.Test;
+
+public class ServerConnectorTest
+{
+ public static class ReuseInfoHandler extends AbstractHandler
+ {
+ @Override
+ public void handle(String target, Request baseRequest, HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException
+ {
+ response.setContentType("text/plain");
+
+ EndPoint endPoint = baseRequest.getHttpChannel().getEndPoint();
+ assertThat("Endpoint",endPoint,instanceOf(ChannelEndPoint.class));
+ ChannelEndPoint channelEndPoint = (ChannelEndPoint)endPoint;
+ Socket socket = channelEndPoint.getSocket();
+ ServerConnector connector = (ServerConnector)baseRequest.getHttpChannel().getConnector();
+
+ PrintWriter out = response.getWriter();
+ out.printf("connector.getReuseAddress() = %b%n",connector.getReuseAddress());
+
+ try
+ {
+ Field fld = connector.getClass().getDeclaredField("_reuseAddress");
+ assertThat("Field[_reuseAddress]",fld,notNullValue());
+ fld.setAccessible(true);
+ Object val = fld.get(connector);
+ out.printf("connector._reuseAddress() = %b%n",val);
+ }
+ catch (Throwable t)
+ {
+ t.printStackTrace(out);
+ }
+
+ out.printf("socket.getReuseAddress() = %b%n",socket.getReuseAddress());
+
+ baseRequest.setHandled(true);
+ }
+ }
+
+ private URI toServerURI(ServerConnector connector) throws URISyntaxException
+ {
+ String host = connector.getHost();
+ if (host == null)
+ {
+ host = "localhost";
+ }
+ int port = connector.getLocalPort();
+ return new URI(String.format("http://%s:%d/",host,port));
+ }
+
+ private String getResponse(URI uri) throws MalformedURLException, IOException
+ {
+ HttpURLConnection http = (HttpURLConnection)uri.toURL().openConnection();
+ assertThat("Valid Response Code",http.getResponseCode(),anyOf(is(200),is(404)));
+
+ try (InputStream in = http.getInputStream())
+ {
+ return IO.toString(in,StandardCharsets.UTF_8);
+ }
+ }
+
+ @Test
+ public void testReuseAddress_Default() throws Exception
+ {
+ Server server = new Server();
+ ServerConnector connector = new ServerConnector(server);
+ connector.setPort(0);
+ server.addConnector(connector);
+
+ HandlerList handlers = new HandlerList();
+ handlers.addHandler(new ReuseInfoHandler());
+ handlers.addHandler(new DefaultHandler());
+
+ server.setHandler(handlers);
+
+ try
+ {
+ server.start();
+
+ URI uri = toServerURI(connector);
+ String response = getResponse(uri);
+ assertThat("Response",response,containsString("connector.getReuseAddress() = true"));
+ assertThat("Response",response,containsString("connector._reuseAddress() = true"));
+ assertThat("Response",response,containsString("socket.getReuseAddress() = true"));
+ }
+ finally
+ {
+ server.stop();
+ }
+ }
+
+ @Test
+ public void testReuseAddress_True() throws Exception
+ {
+ Server server = new Server();
+ ServerConnector connector = new ServerConnector(server);
+ connector.setPort(0);
+ connector.setReuseAddress(true);
+ server.addConnector(connector);
+
+ HandlerList handlers = new HandlerList();
+ handlers.addHandler(new ReuseInfoHandler());
+ handlers.addHandler(new DefaultHandler());
+
+ server.setHandler(handlers);
+
+ try
+ {
+ server.start();
+
+ URI uri = toServerURI(connector);
+ String response = getResponse(uri);
+ assertThat("Response",response,containsString("connector.getReuseAddress() = true"));
+ assertThat("Response",response,containsString("connector._reuseAddress() = true"));
+ assertThat("Response",response,containsString("socket.getReuseAddress() = true"));
+ }
+ finally
+ {
+ server.stop();
+ }
+ }
+
+ @Test
+ public void testReuseAddress_False() throws Exception
+ {
+ Server server = new Server();
+ ServerConnector connector = new ServerConnector(server);
+ connector.setPort(0);
+ connector.setReuseAddress(false);
+ server.addConnector(connector);
+
+ HandlerList handlers = new HandlerList();
+ handlers.addHandler(new ReuseInfoHandler());
+ handlers.addHandler(new DefaultHandler());
+
+ server.setHandler(handlers);
+
+ try
+ {
+ server.start();
+
+ URI uri = toServerURI(connector);
+ String response = getResponse(uri);
+ assertThat("Response",response,containsString("connector.getReuseAddress() = false"));
+ assertThat("Response",response,containsString("connector._reuseAddress() = false"));
+ assertThat("Response",response,containsString("socket.getReuseAddress() = false"));
+ }
+ finally
+ {
+ server.stop();
+ }
+ }
+}
diff --git a/jetty-server/src/test/java/org/eclipse/jetty/server/ShutdownMonitorTest.java b/jetty-server/src/test/java/org/eclipse/jetty/server/ShutdownMonitorTest.java
index bd02b034d8..0b02ee1b8a 100644
--- a/jetty-server/src/test/java/org/eclipse/jetty/server/ShutdownMonitorTest.java
+++ b/jetty-server/src/test/java/org/eclipse/jetty/server/ShutdownMonitorTest.java
@@ -26,43 +26,36 @@ import java.io.LineNumberReader;
import java.io.OutputStream;
import java.net.InetAddress;
import java.net.Socket;
+import java.util.concurrent.TimeUnit;
import org.junit.Test;
/**
* ShutdownMonitorTest
- *
- *
- *
*/
public class ShutdownMonitorTest
{
-
-
@Test
- public void testShutdown ()
- throws Exception
+ public void testShutdown() throws Exception
{
-
- //test port and key assignment
+ // test port and key assignment
ShutdownMonitor.getInstance().setPort(0);
ShutdownMonitor.getInstance().setExitVm(false);
ShutdownMonitor.getInstance().start();
String key = ShutdownMonitor.getInstance().getKey();
int port = ShutdownMonitor.getInstance().getPort();
-
- //try starting a 2nd time (should be ignored)
- ShutdownMonitor.getInstance().start();
-
-
+
+ // try starting a 2nd time (should be ignored)
+ ShutdownMonitor.getInstance().start();
+
stop(port,key,true);
assertTrue(!ShutdownMonitor.getInstance().isAlive());
-
- //should be able to change port and key because it is stopped
+
+ // should be able to change port and key because it is stopped
ShutdownMonitor.getInstance().setPort(0);
- ShutdownMonitor.getInstance().setKey("foo");
+ ShutdownMonitor.getInstance().setKey("foo");
ShutdownMonitor.getInstance().start();
-
+
key = ShutdownMonitor.getInstance().getKey();
port = ShutdownMonitor.getInstance().getPort();
assertTrue(ShutdownMonitor.getInstance().isAlive());
@@ -71,41 +64,34 @@ public class ShutdownMonitorTest
assertTrue(!ShutdownMonitor.getInstance().isAlive());
}
-
- public void stop (int port, String key, boolean check)
- throws Exception
+ public void stop(int port, String key, boolean check) throws Exception
{
- Socket s = null;
-
- try
+ System.out.printf("Attempting stop to localhost:%d (%b)%n",port,check);
+ try (Socket s = new Socket(InetAddress.getByName("127.0.0.1"),port))
{
- //send stop command
- s = new Socket(InetAddress.getByName("127.0.0.1"),port);
-
- OutputStream out = s.getOutputStream();
- out.write((key + "\r\nstop\r\n").getBytes());
- out.flush();
-
- if (check)
+ // send stop command
+ try (OutputStream out = s.getOutputStream())
{
- //wait a little
- Thread.currentThread().sleep(600);
+ out.write((key + "\r\nstop\r\n").getBytes());
+ out.flush();
- //check for stop confirmation
- LineNumberReader lin = new LineNumberReader(new InputStreamReader(s.getInputStream()));
- String response;
- if ((response = lin.readLine()) != null)
+ if (check)
{
- assertEquals("Stopped", response);
+ // wait a little
+ TimeUnit.MILLISECONDS.sleep(600);
+
+ // check for stop confirmation
+ LineNumberReader lin = new LineNumberReader(new InputStreamReader(s.getInputStream()));
+ String response;
+ if ((response = lin.readLine()) != null)
+ {
+ assertEquals("Stopped",response);
+ }
+ else
+ throw new IllegalStateException("No stop confirmation");
}
- else
- throw new IllegalStateException("No stop confirmation");
}
}
- finally
- {
- if (s != null) s.close();
- }
}
}
diff --git a/jetty-server/src/test/java/org/eclipse/jetty/server/handler/ContextHandlerCollectionTest.java b/jetty-server/src/test/java/org/eclipse/jetty/server/handler/ContextHandlerCollectionTest.java
index 5e2adf2a2f..3c13fea0ae 100644
--- a/jetty-server/src/test/java/org/eclipse/jetty/server/handler/ContextHandlerCollectionTest.java
+++ b/jetty-server/src/test/java/org/eclipse/jetty/server/handler/ContextHandlerCollectionTest.java
@@ -18,17 +18,24 @@
package org.eclipse.jetty.server.handler;
+import static org.hamcrest.Matchers.containsString;
+import static org.hamcrest.Matchers.endsWith;
+import static org.hamcrest.Matchers.not;
+import static org.hamcrest.Matchers.startsWith;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertThat;
import static org.junit.Assert.assertTrue;
import java.io.IOException;
+import javax.servlet.AsyncContext;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.eclipse.jetty.server.Connector;
+import org.eclipse.jetty.server.Handler;
import org.eclipse.jetty.server.LocalConnector;
import org.eclipse.jetty.server.Request;
import org.eclipse.jetty.server.Server;
@@ -84,9 +91,9 @@ public class ContextHandlerCollectionTest
c.addHandler(contextC);
HandlerList list = new HandlerList();
- list.addHandler(contextD);
list.addHandler(contextE);
list.addHandler(contextF);
+ list.addHandler(contextD);
c.addHandler(list);
server.setHandler(c);
@@ -132,18 +139,22 @@ public class ContextHandlerCollectionTest
handlerE.reset();
handlerF.reset();
- // System.err.printf("test %d %s@%s --> %s | %s%n",i,uri,host,connector.getName(),handler);
+ String t = String.format("test %d %s@%s --> %s | %s%n",i,uri,host,connector.getName(),handler);
String response = connector.getResponses("GET "+uri+" HTTP/1.0\nHost: "+host+"\n\n");
if (handler==null)
{
- Assert.assertThat(response,Matchers.containsString(" 302 "));
+ Assert.assertThat(t,response,Matchers.containsString(" 302 "));
}
- else if (!handler.isHandled())
+ else
{
- System.err.printf("FAILED %d %s@%s --> %s | %s%n",i,uri,host,connector.getName(),handler);
- System.err.println(response);
- Assert.fail();
+ assertThat(t,response,endsWith(handler.toString()));
+ if (!handler.isHandled())
+ {
+ System.err.printf("FAILED %s",t);
+ System.err.println(response);
+ Assert.fail();
+ }
}
}
@@ -260,8 +271,148 @@ public class ContextHandlerCollectionTest
assertEquals(wrapperB,AbstractHandlerContainer.findContainerOf(contextB,HandlerWrapper.class,handlerB));
}
+
+ @Test
+ public void testWrappedContext() throws Exception
+ {
+ Server server = new Server();
+ LocalConnector connector = new LocalConnector(server);
+ server.setConnectors(new Connector[] { connector });
+
+ ContextHandler root = new ContextHandler("/");
+ root.setHandler(new IsHandledHandler("root"));
+
+ ContextHandler left = new ContextHandler("/left");
+ left.setHandler(new IsHandledHandler("left"));
+
+ HandlerList centre = new HandlerList();
+ ContextHandler centreLeft = new ContextHandler("/leftcentre");
+ centreLeft.setHandler(new IsHandledHandler("left of centre"));
+ ContextHandler centreRight = new ContextHandler("/rightcentre");
+ centreRight.setHandler(new IsHandledHandler("right of centre"));
+ centre.setHandlers(new Handler[]{centreLeft,new WrappedHandler(centreRight)});
+
+ ContextHandler right = new ContextHandler("/right");
+ right.setHandler(new IsHandledHandler("right"));
+
+ ContextHandlerCollection contexts = new ContextHandlerCollection();
+ contexts.setHandlers(new Handler[]{root,left,centre,new WrappedHandler(right)});
+
+ server.setHandler(contexts);
+ server.start();
+
+ String response=connector.getResponses("GET / HTTP/1.0\r\n\r\n");
+ assertThat(response, startsWith("HTTP/1.1 200 OK"));
+ assertThat(response, endsWith("root"));
+ assertThat(response, not(containsString("Wrapped: TRUE")));
+
+ response=connector.getResponses("GET /foobar/info HTTP/1.0\r\n\r\n");
+ assertThat(response, startsWith("HTTP/1.1 200 OK"));
+ assertThat(response, endsWith("root"));
+ assertThat(response, not(containsString("Wrapped: TRUE")));
+
+ response=connector.getResponses("GET /left/info HTTP/1.0\r\n\r\n");
+ assertThat(response, startsWith("HTTP/1.1 200 OK"));
+ assertThat(response, endsWith("left"));
+ assertThat(response, not(containsString("Wrapped: TRUE")));
+
+ response=connector.getResponses("GET /leftcentre/info HTTP/1.0\r\n\r\n");
+ assertThat(response, startsWith("HTTP/1.1 200 OK"));
+ assertThat(response, endsWith("left of centre"));
+ assertThat(response, not(containsString("Wrapped: TRUE")));
+
+ response=connector.getResponses("GET /rightcentre/info HTTP/1.0\r\n\r\n");
+ assertThat(response, startsWith("HTTP/1.1 200 OK"));
+ assertThat(response, endsWith("right of centre"));
+ assertThat(response, containsString("Wrapped: TRUE"));
+
+ response=connector.getResponses("GET /right/info HTTP/1.0\r\n\r\n");
+ assertThat(response, startsWith("HTTP/1.1 200 OK"));
+ assertThat(response, endsWith("right"));
+ assertThat(response, containsString("Wrapped: TRUE"));
+ }
+ @Test
+ public void testAsyncWrappedContext() throws Exception
+ {
+ Server server = new Server();
+ LocalConnector connector = new LocalConnector(server);
+ server.setConnectors(new Connector[] { connector });
+
+ ContextHandler root = new ContextHandler("/");
+ root.setHandler(new AsyncHandler("root"));
+
+ ContextHandler left = new ContextHandler("/left");
+ left.setHandler(new AsyncHandler("left"));
+
+ HandlerList centre = new HandlerList();
+ ContextHandler centreLeft = new ContextHandler("/leftcentre");
+ centreLeft.setHandler(new AsyncHandler("left of centre"));
+ ContextHandler centreRight = new ContextHandler("/rightcentre");
+ centreRight.setHandler(new AsyncHandler("right of centre"));
+ centre.setHandlers(new Handler[]{centreLeft,new WrappedHandler(centreRight)});
+
+ ContextHandler right = new ContextHandler("/right");
+ right.setHandler(new AsyncHandler("right"));
+
+ ContextHandlerCollection contexts = new ContextHandlerCollection();
+ contexts.setHandlers(new Handler[]{root,left,centre,new WrappedHandler(right)});
+
+ server.setHandler(contexts);
+ server.start();
+
+ String response=connector.getResponses("GET / HTTP/1.0\r\n\r\n");
+ assertThat(response, startsWith("HTTP/1.1 200 OK"));
+ assertThat(response, endsWith("root"));
+ assertThat(response, not(containsString("Wrapped: TRUE")));
+
+ response=connector.getResponses("GET /foobar/info HTTP/1.0\r\n\r\n");
+ assertThat(response, startsWith("HTTP/1.1 200 OK"));
+ assertThat(response, endsWith("root"));
+ assertThat(response, not(containsString("Wrapped: TRUE")));
+
+ response=connector.getResponses("GET /left/info HTTP/1.0\r\n\r\n");
+ assertThat(response, startsWith("HTTP/1.1 200 OK"));
+ assertThat(response, endsWith("left"));
+ assertThat(response, not(containsString("Wrapped: TRUE")));
+
+ response=connector.getResponses("GET /leftcentre/info HTTP/1.0\r\n\r\n");
+ assertThat(response, startsWith("HTTP/1.1 200 OK"));
+ assertThat(response, endsWith("left of centre"));
+ assertThat(response, not(containsString("Wrapped: TRUE")));
+
+ response=connector.getResponses("GET /rightcentre/info HTTP/1.0\r\n\r\n");
+ assertThat(response, startsWith("HTTP/1.1 200 OK"));
+ assertThat(response, endsWith("right of centre"));
+ assertThat(response, containsString("Wrapped: ASYNC"));
+
+ response=connector.getResponses("GET /right/info HTTP/1.0\r\n\r\n");
+ assertThat(response, startsWith("HTTP/1.1 200 OK"));
+ assertThat(response, endsWith("right"));
+ assertThat(response, containsString("Wrapped: ASYNC"));
+ }
+
+
+ private static final class WrappedHandler extends HandlerWrapper
+ {
+ WrappedHandler(Handler handler)
+ {
+ setHandler(handler);
+ }
+
+ @Override
+ public void handle(String target, Request baseRequest, HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException
+ {
+ if (response.containsHeader("Wrapped"))
+ response.setHeader("Wrapped", "ASYNC");
+ else
+ response.setHeader("Wrapped", "TRUE");
+ super.handle(target, baseRequest, request, response);
+ }
+ }
+
+
private static final class IsHandledHandler extends AbstractHandler
{
private boolean handled;
@@ -298,5 +449,41 @@ public class ContextHandlerCollectionTest
}
+
+ private static final class AsyncHandler extends AbstractHandler
+ {
+ private final String name;
+
+ public AsyncHandler(String string)
+ {
+ name=string;
+ }
+
+ @Override
+ public void handle(String s, Request baseRequest, HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException
+ {
+ baseRequest.setHandled(true);
+
+ String n = (String)baseRequest.getAttribute("async");
+ if (n==null)
+ {
+ AsyncContext async=baseRequest.startAsync();
+ async.setTimeout(1000);
+ baseRequest.setAttribute("async", name);
+ async.dispatch();
+ }
+ else
+ {
+ response.getWriter().print(n);
+ }
+ }
+
+ @Override
+ public String toString()
+ {
+ return name;
+ }
+ }
+
}
diff --git a/jetty-server/src/test/java/org/eclipse/jetty/server/session/HashSessionManagerTest.java b/jetty-server/src/test/java/org/eclipse/jetty/server/session/HashSessionManagerTest.java
index ebd686d53d..a562c09591 100644
--- a/jetty-server/src/test/java/org/eclipse/jetty/server/session/HashSessionManagerTest.java
+++ b/jetty-server/src/test/java/org/eclipse/jetty/server/session/HashSessionManagerTest.java
@@ -22,6 +22,7 @@ import java.io.File;
import org.eclipse.jetty.server.Request;
import org.eclipse.jetty.server.Server;
+import org.eclipse.jetty.toolchain.test.FS;
import org.eclipse.jetty.toolchain.test.MavenTestingUtils;
import org.eclipse.jetty.util.IO;
import org.eclipse.jetty.util.log.Log;
@@ -33,24 +34,6 @@ import org.junit.Test;
public class HashSessionManagerTest
{
- @After
- public void enableStacks()
- {
- enableStacks(true);
- }
-
- @Before
- public void quietStacks()
- {
- enableStacks(false);
- }
-
- protected void enableStacks(boolean enabled)
- {
- StdErrLog log = (StdErrLog)Log.getLogger("org.eclipse.jetty.server.session");
- log.setHideStacks(!enabled);
- }
-
@Test
public void testDangerousSessionIdRemoval() throws Exception
{
@@ -78,7 +61,8 @@ public class HashSessionManagerTest
manager.setDeleteUnrestorableSessions(true);
manager.setLazyLoad(true);
File testDir = MavenTestingUtils.getTargetTestingDir("hashes");
- testDir.mkdirs();
+ FS.ensureEmpty(testDir);
+
manager.setStoreDirectory(testDir);
Assert.assertTrue(new File(testDir, "validFile.session").createNewFile());
@@ -88,7 +72,6 @@ public class HashSessionManagerTest
manager.getSession("validFile.session");
Assert.assertTrue("File shouldn't exist!", !new File(testDir,"validFile.session").exists());
-
}
@Test
@@ -116,7 +99,6 @@ public class HashSessionManagerTest
server.start();
manager.start();
-
HashedSession session = (HashedSession)manager.newHttpSession(new Request(null, null));
String sessionId = session.getId();
@@ -124,7 +106,7 @@ public class HashSessionManagerTest
session.setAttribute("two", new Integer(2));
//stop will persist sessions
- manager.setMaxInactiveInterval(30); //change max inactive interval for *new* sessions
+ manager.setMaxInactiveInterval(30); // change max inactive interval for *new* sessions
manager.stop();
Assert.assertTrue("File should exist!", new File(testDir, session.getId()).exists());
diff --git a/jetty-server/src/test/java/org/eclipse/jetty/server/ssl/SelectChannelServerSslTest.java b/jetty-server/src/test/java/org/eclipse/jetty/server/ssl/SelectChannelServerSslTest.java
index 6cc241a9b0..6c5addb60d 100644
--- a/jetty-server/src/test/java/org/eclipse/jetty/server/ssl/SelectChannelServerSslTest.java
+++ b/jetty-server/src/test/java/org/eclipse/jetty/server/ssl/SelectChannelServerSslTest.java
@@ -63,9 +63,9 @@ public class SelectChannelServerSslTest extends HttpServerTestBase
@Override
public void testFullMethod() throws Exception
{
- // Don't run on Windows (buggy JVM)
- Assume.assumeTrue(!OS.IS_WINDOWS);
-
+ // Don't run on Windows (buggy JVM)
+ Assume.assumeTrue(!OS.IS_WINDOWS);
+
try
{
super.testFullMethod();
@@ -79,8 +79,8 @@ public class SelectChannelServerSslTest extends HttpServerTestBase
@Override
public void testFullURI() throws Exception
{
- // Don't run on Windows (buggy JVM)
- Assume.assumeTrue(!OS.IS_WINDOWS);
+ // Don't run on Windows (buggy JVM)
+ Assume.assumeTrue(!OS.IS_WINDOWS);
try
{
super.testFullURI();
diff --git a/jetty-servlet/pom.xml b/jetty-servlet/pom.xml
index 278c3c295b..1f8240ee85 100644
--- a/jetty-servlet/pom.xml
+++ b/jetty-servlet/pom.xml
@@ -3,7 +3,7 @@
<parent>
<artifactId>jetty-project</artifactId>
<groupId>org.eclipse.jetty</groupId>
- <version>9.2.2-SNAPSHOT</version>
+ <version>9.2.3-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>jetty-servlet</artifactId>
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 b17a112844..cf22ca3b4c 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
@@ -27,9 +27,7 @@ import java.net.URL;
import java.nio.ByteBuffer;
import java.util.ArrayList;
import java.util.Enumeration;
-import java.util.HashMap;
import java.util.List;
-import java.util.Map;
import java.util.StringTokenizer;
import javax.servlet.AsyncContext;
@@ -265,11 +263,11 @@ public class DefaultServlet extends HttpServlet implements ResourceFactory
try
{
- if (_cache==null && max_cached_files>0)
+ if (_cache==null && (max_cached_files!=-2 || max_cache_size!=-2 || max_cached_file_size!=-2))
{
_cache= new ResourceCache(null,this,_mimeTypes,_useFileMappedBuffer,_etags);
- if (max_cache_size>0)
+ if (max_cache_size>=0)
_cache.setMaxCacheSize(max_cache_size);
if (max_cached_file_size>=-1)
_cache.setMaxCachedFileSize(max_cached_file_size);
@@ -296,19 +294,19 @@ public class DefaultServlet extends HttpServlet implements ResourceFactory
}
}
else
- {
- //.svgz files are gzipped svg files and must be served with Content-Encoding:gzip
- _gzipEquivalentFileExtensions.add(".svgz");
- }
+ {
+ //.svgz files are gzipped svg files and must be served with Content-Encoding:gzip
+ _gzipEquivalentFileExtensions.add(".svgz");
+ }
- _servletHandler= _contextHandler.getChildHandlerByClass(ServletHandler.class);
- for (ServletHolder h :_servletHandler.getServlets())
- if (h.getServletInstance()==this)
- _defaultHolder=h;
+ _servletHandler= _contextHandler.getChildHandlerByClass(ServletHandler.class);
+ for (ServletHolder h :_servletHandler.getServlets())
+ if (h.getServletInstance()==this)
+ _defaultHolder=h;
-
- if (LOG.isDebugEnabled())
- LOG.debug("resource base = "+_resourceBase);
+
+ if (LOG.isDebugEnabled())
+ LOG.debug("resource base = "+_resourceBase);
}
/**
@@ -1060,7 +1058,15 @@ public class DefaultServlet extends HttpServlet implements ResourceFactory
/* ------------------------------------------------------------ */
protected void writeHeaders(HttpServletResponse response,HttpContent content,long count)
- {
+ {
+ if (content == null)
+ {
+ // No content, then no headers to process
+ // This is possible during bypass write because of wrapping
+ // See .sendData() for more details.
+ return;
+ }
+
if (content.getContentType()!=null && response.getContentType()==null)
response.setContentType(content.getContentType().toString());
diff --git a/jetty-servlet/src/main/java/org/eclipse/jetty/servlet/FilterMapping.java b/jetty-servlet/src/main/java/org/eclipse/jetty/servlet/FilterMapping.java
index 1d5a9a4205..d8265842f9 100644
--- a/jetty-servlet/src/main/java/org/eclipse/jetty/servlet/FilterMapping.java
+++ b/jetty-servlet/src/main/java/org/eclipse/jetty/servlet/FilterMapping.java
@@ -24,7 +24,6 @@ import java.util.EnumSet;
import javax.servlet.DispatcherType;
import org.eclipse.jetty.http.PathMap;
-import org.eclipse.jetty.server.Handler;
import org.eclipse.jetty.util.TypeUtil;
import org.eclipse.jetty.util.annotation.ManagedAttribute;
import org.eclipse.jetty.util.annotation.ManagedObject;
@@ -67,19 +66,19 @@ public class FilterMapping implements Dumpable
*/
public static int dispatch(DispatcherType type)
{
- switch(type)
- {
- case REQUEST:
- return REQUEST;
- case ASYNC:
- return ASYNC;
- case FORWARD:
- return FORWARD;
- case INCLUDE:
- return INCLUDE;
- case ERROR:
- return ERROR;
- }
+ switch(type)
+ {
+ case REQUEST:
+ return REQUEST;
+ case ASYNC:
+ return ASYNC;
+ case FORWARD:
+ return FORWARD;
+ case INCLUDE:
+ return INCLUDE;
+ case ERROR:
+ return ERROR;
+ }
throw new IllegalArgumentException(type.toString());
}
@@ -124,8 +123,8 @@ public class FilterMapping implements Dumpable
*/
boolean appliesTo(int type)
{
- if (_dispatches==0)
- return type==REQUEST || type==ASYNC && _holder.isAsyncSupported();
+ if (_dispatches==0)
+ return type==REQUEST || type==ASYNC && _holder.isAsyncSupported();
return (_dispatches&type)!=0;
}
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 2f690b17b5..9ee03cc88d 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
@@ -89,7 +89,7 @@ public class Holder<T> extends BaseHolder<T>
}
/* ------------------------------------------------------------ */
- public Enumeration getInitParameterNames()
+ public Enumeration<String> getInitParameterNames()
{
if (_initParams==null)
return Collections.enumeration(Collections.EMPTY_LIST);
@@ -227,7 +227,7 @@ public class Holder<T> extends BaseHolder<T>
}
/* -------------------------------------------------------- */
- public Enumeration getInitParameterNames()
+ public Enumeration<String> getInitParameterNames()
{
return Holder.this.getInitParameterNames();
}
diff --git a/jetty-servlet/src/main/java/org/eclipse/jetty/servlet/Invoker.java b/jetty-servlet/src/main/java/org/eclipse/jetty/servlet/Invoker.java
index 4613144baf..b7f0e748f7 100644
--- a/jetty-servlet/src/main/java/org/eclipse/jetty/servlet/Invoker.java
+++ b/jetty-servlet/src/main/java/org/eclipse/jetty/servlet/Invoker.java
@@ -72,8 +72,8 @@ public class Invoker extends HttpServlet
private ContextHandler _contextHandler;
private ServletHandler _servletHandler;
- private Map.Entry _invokerEntry;
- private Map _parameters;
+ private Map.Entry<String, ServletHolder> _invokerEntry;
+ private Map<String, String> _parameters;
private boolean _nonContextServlets;
private boolean _verbose;
@@ -87,10 +87,10 @@ public class Invoker extends HttpServlet
while (handler!=null && !(handler instanceof ServletHandler) && (handler instanceof HandlerWrapper))
handler=((HandlerWrapper)handler).getHandler();
_servletHandler = (ServletHandler)handler;
- Enumeration e = getInitParameterNames();
+ Enumeration<String> e = getInitParameterNames();
while(e.hasMoreElements())
{
- String param=(String)e.nextElement();
+ String param=e.nextElement();
String value=getInitParameter(param);
String lvalue=value.toLowerCase(Locale.ENGLISH);
if ("nonContextServlets".equals(param))
@@ -104,7 +104,7 @@ public class Invoker extends HttpServlet
else
{
if (_parameters==null)
- _parameters=new HashMap();
+ _parameters=new HashMap<String, String>();
_parameters.put(param,value);
}
}
@@ -112,7 +112,7 @@ public class Invoker extends HttpServlet
/* ------------------------------------------------------------ */
protected void service(HttpServletRequest request, HttpServletResponse response)
- throws ServletException, IOException
+ throws ServletException, IOException
{
// Get the requested path and info
boolean included=false;
@@ -151,7 +151,7 @@ public class Invoker extends HttpServlet
ServletMapping mapping = new ServletMapping();
mapping.setServletName(servlet);
mapping.setPathSpec(URIUtil.addPaths(servlet_path,servlet)+"/*");
- _servletHandler.setServletMappings((ServletMapping[])ArrayUtil.addToArray(_servletHandler.getServletMappings(), mapping, ServletMapping.class));
+ _servletHandler.setServletMappings(ArrayUtil.addToArray(_servletHandler.getServletMappings(), mapping, ServletMapping.class));
}
else
{
@@ -171,7 +171,7 @@ public class Invoker extends HttpServlet
// Check for existing mapping (avoid threaded race).
String path=URIUtil.addPaths(servlet_path,servlet);
- Map.Entry entry = _servletHandler.getHolderEntry(path);
+ Map.Entry<String, ServletHolder> entry = _servletHandler.getHolderEntry(path);
if (entry!=null && !entry.equals(_invokerEntry))
{
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 d01ddd2a26..7e2e22e6fc 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
@@ -35,8 +35,6 @@ import javax.servlet.Filter;
import javax.servlet.FilterRegistration;
import javax.servlet.RequestDispatcher;
import javax.servlet.Servlet;
-import javax.servlet.ServletContainerInitializer;
-import javax.servlet.ServletContext;
import javax.servlet.ServletContextEvent;
import javax.servlet.ServletContextListener;
import javax.servlet.ServletException;
@@ -290,9 +288,9 @@ public class ServletContextHandler extends ContextHandler
decorator.decorate(holder.getListener());
}
}
- }
- }
-
+ }
+ }
+
super.startContext();
// OK to Initialize servlet handler now that all relevant object trees have been started
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 d180e46fda..e650a709fc 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
@@ -116,8 +116,6 @@ public class ServletHandler extends ScopedHandler
private ServletHolder[] _servlets=new ServletHolder[0];
private ServletMapping[] _servletMappings;
- private Map<String,ServletMapping> _servletPathMappings = new HashMap<String,ServletMapping>();
-
private final Map<String,FilterHolder> _filterNameMap= new HashMap<>();
private List<FilterMapping> _filterPathMappings;
private MultiMap<FilterMapping> _filterNameMappings;
@@ -127,9 +125,12 @@ public class ServletHandler extends ScopedHandler
private ListenerHolder[] _listeners=new ListenerHolder[0];
- protected final ConcurrentMap<?, ?> _chainCache[] = new ConcurrentMap[FilterMapping.ALL];
- protected final Queue<?>[] _chainLRU = new Queue[FilterMapping.ALL];
-
+ @SuppressWarnings("unchecked")
+ protected final ConcurrentMap<String, FilterChain> _chainCache[] = new ConcurrentMap[FilterMapping.ALL];
+
+ @SuppressWarnings("unchecked")
+ protected final Queue<String>[] _chainLRU = new Queue[FilterMapping.ALL];
+
/* ------------------------------------------------------------ */
@@ -340,7 +341,6 @@ public class ServletHandler extends ScopedHandler
_filterPathMappings=null;
_filterNameMappings=null;
_servletPathMap=null;
- _servletPathMappings=null;
}
/* ------------------------------------------------------------ */
@@ -415,10 +415,26 @@ public class ServletHandler extends ScopedHandler
*/
public ServletMapping getServletMapping(String pathSpec)
{
- if (pathSpec == null || _servletPathMappings == null)
+ if (pathSpec == null || _servletMappings == null)
return null;
- return _servletPathMapping