Skip to main content
aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--.gitignore1
-rw-r--r--VERSION.txt271
-rw-r--r--example-async-rest/async-rest-jar/pom.xml24
-rw-r--r--example-async-rest/async-rest-jar/src/main/java/org/eclipse/jetty/example/asyncrest/AbstractRestServlet.java120
-rw-r--r--example-async-rest/async-rest-jar/src/main/java/org/eclipse/jetty/example/asyncrest/AsyncRestServlet.java211
-rw-r--r--example-async-rest/async-rest-jar/src/main/java/org/eclipse/jetty/example/asyncrest/SerialRestServlet.java106
-rw-r--r--example-async-rest/async-rest-jar/src/main/resources/META-INF/resources/asyncrest.html38
-rw-r--r--example-async-rest/async-rest-jar/src/main/resources/META-INF/resources/asyncrest/green.pngbin0 -> 166 bytes
-rw-r--r--example-async-rest/async-rest-jar/src/main/resources/META-INF/resources/asyncrest/red.pngbin0 -> 164 bytes
-rw-r--r--example-async-rest/async-rest-jar/src/main/resources/META-INF/web-fragment.xml22
-rw-r--r--example-async-rest/async-rest-webapp/pom.xml33
-rw-r--r--example-async-rest/async-rest-webapp/src/main/webapp/META-INF/MANIFEST.MF3
-rw-r--r--example-async-rest/async-rest-webapp/src/main/webapp/WEB-INF/web.xml9
-rw-r--r--example-async-rest/async-rest-webapp/src/main/webapp/index.html38
-rw-r--r--example-async-rest/async-rest-webapp/src/test/java/org/eclipse/jetty/example/asyncrest/DemoServer.java48
-rw-r--r--example-async-rest/pom.xml16
-rw-r--r--example-jetty-embedded/pom.xml2
-rw-r--r--example-jetty-embedded/src/main/java/org/eclipse/jetty/embedded/LikeJettyXml.java2
-rw-r--r--example-jetty-embedded/src/main/java/org/eclipse/jetty/embedded/ManyContexts.java1
-rw-r--r--example-jetty-embedded/src/main/java/org/eclipse/jetty/embedded/OneWebApp.java15
-rw-r--r--jetty-aggregate/jetty-all-server/pom.xml10
-rw-r--r--jetty-aggregate/jetty-all/pom.xml3
-rw-r--r--jetty-aggregate/jetty-client/pom.xml2
-rw-r--r--jetty-aggregate/jetty-plus/pom.xml2
-rw-r--r--jetty-aggregate/jetty-server/pom.xml2
-rw-r--r--jetty-aggregate/jetty-servlet/pom.xml2
-rw-r--r--jetty-aggregate/jetty-webapp/pom.xml2
-rw-r--r--jetty-aggregate/jetty-websocket/pom.xml2
-rw-r--r--jetty-aggregate/pom.xml2
-rw-r--r--jetty-ajp/pom.xml7
-rw-r--r--jetty-annotations/pom.xml21
-rw-r--r--jetty-annotations/src/main/config/etc/jetty-annotations.xml23
-rw-r--r--jetty-annotations/src/main/java/org/eclipse/jetty/annotations/AbstractDiscoverableAnnotationHandler.java23
-rw-r--r--jetty-annotations/src/main/java/org/eclipse/jetty/annotations/AnnotationConfiguration.java473
-rw-r--r--jetty-annotations/src/main/java/org/eclipse/jetty/annotations/AnnotationDecorator.java2
-rw-r--r--jetty-annotations/src/main/java/org/eclipse/jetty/annotations/AnnotationParser.java310
-rw-r--r--jetty-annotations/src/main/java/org/eclipse/jetty/annotations/ClassInheritanceHandler.java8
-rw-r--r--jetty-annotations/src/main/java/org/eclipse/jetty/annotations/ContainerInitializerAnnotationHandler.java83
-rw-r--r--jetty-annotations/src/main/java/org/eclipse/jetty/annotations/MultiPartConfigAnnotationHandler.java95
-rw-r--r--jetty-annotations/src/main/java/org/eclipse/jetty/annotations/RunAsAnnotationHandler.java2
-rw-r--r--jetty-annotations/src/main/java/org/eclipse/jetty/annotations/ServletContainerInitializerListener.java142
-rw-r--r--jetty-annotations/src/main/java/org/eclipse/jetty/annotations/ServletSecurityAnnotationHandler.java196
-rw-r--r--jetty-annotations/src/main/java/org/eclipse/jetty/annotations/Util.java3
-rw-r--r--jetty-annotations/src/main/java/org/eclipse/jetty/annotations/WebFilterAnnotation.java223
-rw-r--r--jetty-annotations/src/main/java/org/eclipse/jetty/annotations/WebFilterAnnotationHandler.java74
-rw-r--r--jetty-annotations/src/main/java/org/eclipse/jetty/annotations/WebListenerAnnotation.java96
-rw-r--r--jetty-annotations/src/main/java/org/eclipse/jetty/annotations/WebListenerAnnotationHandler.java71
-rw-r--r--jetty-annotations/src/main/java/org/eclipse/jetty/annotations/WebServletAnnotation.java227
-rw-r--r--jetty-annotations/src/main/java/org/eclipse/jetty/annotations/WebServletAnnotationHandler.java85
-rw-r--r--jetty-annotations/src/test/java/org/eclipse/jetty/annotations/FilterC.java4
-rw-r--r--jetty-annotations/src/test/java/org/eclipse/jetty/annotations/ListenerC.java2
-rw-r--r--jetty-annotations/src/test/java/org/eclipse/jetty/annotations/ServletC.java9
-rw-r--r--jetty-annotations/src/test/java/org/eclipse/jetty/annotations/TestAnnotationConfiguration.java58
-rw-r--r--jetty-annotations/src/test/java/org/eclipse/jetty/annotations/TestAnnotationInheritance.java55
-rw-r--r--jetty-annotations/src/test/java/org/eclipse/jetty/annotations/TestAnnotationParser.java21
-rw-r--r--jetty-annotations/src/test/java/org/eclipse/jetty/annotations/TestSecurityAnnotationConversions.java334
-rw-r--r--jetty-annotations/src/test/java/org/eclipse/jetty/annotations/TestServletAnnotations.java51
-rw-r--r--jetty-client/pom.xml2
-rw-r--r--jetty-continuation/pom.xml4
-rw-r--r--jetty-continuation/src/main/java/org/eclipse/jetty/continuation/ContinuationSupport.java13
-rw-r--r--jetty-continuation/src/main/java/org/eclipse/jetty/continuation/FauxContinuation.java2
-rw-r--r--jetty-continuation/src/main/java/org/eclipse/jetty/continuation/Servlet3Continuation.java13
-rw-r--r--jetty-deploy/pom.xml4
-rw-r--r--jetty-deploy/src/main/config/etc/jetty-deploy.xml2
-rw-r--r--jetty-distribution/pom.xml4
-rwxr-xr-xjetty-distribution/src/main/resources/bin/jetty-cygwin.sh20
-rwxr-xr-xjetty-distribution/src/main/resources/bin/jetty.sh16
-rw-r--r--jetty-distribution/src/main/resources/start.ini3
-rw-r--r--jetty-http-spi/pom.xml2
-rw-r--r--jetty-http/pom.xml4
-rw-r--r--jetty-http/src/main/java/org/eclipse/jetty/http/HttpFields.java45
-rw-r--r--jetty-http/src/main/java/org/eclipse/jetty/http/PathMap.java26
-rw-r--r--jetty-http/src/test/java/org/eclipse/jetty/http/HttpGeneratorClientTest.java8
-rw-r--r--jetty-http/src/test/java/org/eclipse/jetty/http/PathMapTest.java5
-rw-r--r--jetty-io/pom.xml2
-rw-r--r--jetty-io/src/main/java/org/eclipse/jetty/io/AbstractBuffer.java56
-rw-r--r--jetty-io/src/main/java/org/eclipse/jetty/io/Buffer.java6
-rw-r--r--jetty-io/src/main/java/org/eclipse/jetty/io/BufferUtil.java2
-rw-r--r--jetty-io/src/main/java/org/eclipse/jetty/io/UncheckedIOException.java (renamed from jetty-servlet/src/main/java/org/eclipse/jetty/servlet/api/ServletRegistration.java)33
-rw-r--r--jetty-jaspi/pom.xml8
-rw-r--r--jetty-jaspi/src/main/java/org/eclipse/jetty/security/jaspi/JaspiAuthenticator.java36
-rw-r--r--jetty-jaspi/src/main/java/org/eclipse/jetty/security/jaspi/SimpleAuthConfig.java2
-rw-r--r--jetty-jaspi/src/main/java/org/eclipse/jetty/security/jaspi/modules/FormAuthModule.java81
-rw-r--r--jetty-jmx/pom.xml2
-rw-r--r--jetty-jndi/pom.xml2
-rw-r--r--jetty-jsp/pom.xml10
-rw-r--r--jetty-monitor/pom.xml2
-rw-r--r--jetty-nested/pom.xml4
-rw-r--r--jetty-nested/src/main/java/org/eclipse/jetty/nested/NestedConnection.java2
-rw-r--r--jetty-nosql/pom.xml4
-rw-r--r--jetty-osgi/jetty-osgi-boot-jsp/pom.xml39
-rw-r--r--jetty-osgi/jetty-osgi-boot-logback/META-INF/readme.txt12
-rw-r--r--jetty-osgi/jetty-osgi-boot-logback/build.properties5
-rw-r--r--jetty-osgi/jetty-osgi-boot-logback/pom.xml126
-rw-r--r--jetty-osgi/jetty-osgi-boot-logback/src/main/java/org/eclipse/jetty/osgi/boot/logback/FragmentActivator.java92
-rw-r--r--jetty-osgi/jetty-osgi-boot-logback/src/main/java/org/eclipse/jetty/osgi/boot/logback/internal/LogbackInitializer.java102
-rw-r--r--jetty-osgi/jetty-osgi-boot-warurl/pom.xml4
-rw-r--r--jetty-osgi/jetty-osgi-boot-warurl/pom.xml.tycho14
-rw-r--r--jetty-osgi/jetty-osgi-boot/pom.xml17
-rw-r--r--jetty-osgi/jetty-osgi-boot/src/main/java/org/eclipse/jetty/osgi/annotations/AnnotationConfiguration.java210
-rw-r--r--jetty-osgi/jetty-osgi-boot/src/main/java/org/eclipse/jetty/osgi/annotations/AnnotationParser.java197
-rw-r--r--jetty-osgi/jetty-osgi-boot/src/main/java/org/eclipse/jetty/osgi/boot/internal/jsp/TldLocatableURLClassloader.java14
-rw-r--r--jetty-osgi/jetty-osgi-boot/src/main/java/org/eclipse/jetty/osgi/boot/utils/internal/PackageAdminServiceTracker.java1
-rw-r--r--jetty-osgi/jetty-osgi-equinoxtools/build.properties5
-rw-r--r--jetty-osgi/jetty-osgi-equinoxtools/equinoxconsole/index.html85
-rw-r--r--jetty-osgi/jetty-osgi-equinoxtools/equinoxconsole/ws/index.html109
-rw-r--r--jetty-osgi/jetty-osgi-equinoxtools/pom.xml120
-rw-r--r--jetty-osgi/jetty-osgi-equinoxtools/src/main/java/org/eclipse/jetty/osgi/equinoxtools/WebEquinoxToolsActivator.java133
-rw-r--r--jetty-osgi/jetty-osgi-equinoxtools/src/main/java/org/eclipse/jetty/osgi/equinoxtools/console/EquinoxChattingSupport.java156
-rw-r--r--jetty-osgi/jetty-osgi-equinoxtools/src/main/java/org/eclipse/jetty/osgi/equinoxtools/console/EquinoxConsoleContinuationServlet.java253
-rw-r--r--jetty-osgi/jetty-osgi-equinoxtools/src/main/java/org/eclipse/jetty/osgi/equinoxtools/console/EquinoxConsoleSyncServlet.java82
-rw-r--r--jetty-osgi/jetty-osgi-equinoxtools/src/main/java/org/eclipse/jetty/osgi/equinoxtools/console/EquinoxConsoleWebSocketServlet.java182
-rw-r--r--jetty-osgi/jetty-osgi-equinoxtools/src/main/java/org/eclipse/jetty/osgi/equinoxtools/console/WebConsoleSession.java189
-rw-r--r--jetty-osgi/jetty-osgi-equinoxtools/src/main/java/org/eclipse/jetty/osgi/equinoxtools/console/WebConsoleWriterOutputStream.java93
-rw-r--r--jetty-osgi/jetty-osgi-httpservice/contexts/httpservice.xml4
-rw-r--r--jetty-osgi/jetty-osgi-httpservice/pom.xml8
-rw-r--r--jetty-osgi/jetty-osgi-httpservice/pom.xml.tycho12
-rw-r--r--jetty-osgi/jetty-osgi-servletbridge/pom.xml53
-rw-r--r--jetty-osgi/jetty-osgi-servletbridge/src/main/java/org/eclipse/jetty/nested/Dump.java1017
-rw-r--r--jetty-osgi/jetty-osgi-servletbridge/src/main/java/org/eclipse/jetty/osgi/servletbridge/BridgeServletExtended.java56
-rw-r--r--jetty-osgi/jetty-osgi-servletbridge/src/main/java/org/eclipse/jetty/osgi/servletbridge/FrameworkLauncherExtended.java716
-rw-r--r--jetty-osgi/jetty-osgi-servletbridge/src/main/java/org/eclipse/jetty/osgi/servletbridge/hook/ServletBridgeClassLoaderDelegateHook.java97
-rw-r--r--jetty-osgi/jetty-osgi-servletbridge/src/main/webapp/WEB-INF/web.xml67
-rw-r--r--jetty-osgi/pom.xml23
-rw-r--r--jetty-osgi/test-jetty-osgi-context/pom.xml5
-rw-r--r--jetty-osgi/test-jetty-osgi-webapp/pom.xml4
-rw-r--r--jetty-osgi/test-jetty-osgi/pom.xml5
-rw-r--r--jetty-osgi/test-jetty-osgi/src/test/java/org/eclipse/jetty/osgi/boot/TestJettyOSGiBootWebAppAsService.java1
-rw-r--r--jetty-osgi/test-jetty-osgi/src/test/java/org/eclipse/jetty/osgi/boot/TestJettyOSGiBootWithJsp.java10
-rw-r--r--jetty-overlay-deployer/pom.xml2
-rw-r--r--jetty-plus/pom.xml4
-rw-r--r--jetty-plus/src/main/java/org/eclipse/jetty/plus/annotation/ContainerInitializer.java114
-rw-r--r--jetty-plus/src/test/java/org/eclipse/jetty/plus/webapp/PlusDescriptorProcessorTest.java176
-rw-r--r--jetty-plus/src/test/resources/web-fragment-1.xml27
-rw-r--r--jetty-plus/src/test/resources/web-fragment-2.xml27
-rw-r--r--jetty-plus/src/test/resources/web-fragment-3.xml27
-rw-r--r--jetty-plus/src/test/resources/web.xml23
-rw-r--r--jetty-policy/pom.xml2
-rw-r--r--jetty-rewrite/pom.xml7
-rw-r--r--jetty-rewrite/src/test/java/org/eclipse/jetty/rewrite/handler/HeaderPatternRuleTest.java8
-rw-r--r--jetty-security/pom.xml4
-rw-r--r--jetty-security/src/main/java/org/eclipse/jetty/security/ConstraintMapping.java16
-rw-r--r--jetty-security/src/main/java/org/eclipse/jetty/security/ConstraintSecurityHandler.java429
-rw-r--r--jetty-security/src/main/java/org/eclipse/jetty/security/authentication/BasicAuthenticator.java5
-rw-r--r--jetty-security/src/main/java/org/eclipse/jetty/security/authentication/ClientCertAuthenticator.java5
-rw-r--r--jetty-security/src/main/java/org/eclipse/jetty/security/authentication/DeferredAuthentication.java55
-rw-r--r--jetty-security/src/main/java/org/eclipse/jetty/security/authentication/DigestAuthenticator.java6
-rw-r--r--jetty-security/src/main/java/org/eclipse/jetty/security/authentication/FormAuthenticator.java26
-rw-r--r--jetty-security/src/main/java/org/eclipse/jetty/security/authentication/LoginAuthenticator.java17
-rw-r--r--jetty-security/src/main/java/org/eclipse/jetty/security/authentication/SessionAuthentication.java4
-rw-r--r--jetty-security/src/main/java/org/eclipse/jetty/security/authentication/SpnegoAuthenticator.java4
-rw-r--r--jetty-security/src/test/java/org/eclipse/jetty/security/ConstraintTest.java82
-rw-r--r--jetty-security/src/test/java/org/eclipse/jetty/security/SpecExampleConstraintTest.java311
-rw-r--r--jetty-server/pom.xml4
-rw-r--r--jetty-server/src/main/java/org/eclipse/jetty/server/AbstractHttpConnection.java8
-rw-r--r--jetty-server/src/main/java/org/eclipse/jetty/server/AsyncContext.java48
-rw-r--r--jetty-server/src/main/java/org/eclipse/jetty/server/AsyncContinuation.java233
-rw-r--r--jetty-server/src/main/java/org/eclipse/jetty/server/Authentication.java2
-rw-r--r--jetty-server/src/main/java/org/eclipse/jetty/server/Dispatcher.java19
-rw-r--r--jetty-server/src/main/java/org/eclipse/jetty/server/DispatcherType.java28
-rw-r--r--jetty-server/src/main/java/org/eclipse/jetty/server/Request.java189
-rw-r--r--jetty-server/src/main/java/org/eclipse/jetty/server/Response.java24
-rw-r--r--jetty-server/src/main/java/org/eclipse/jetty/server/Server.java4
-rw-r--r--jetty-server/src/main/java/org/eclipse/jetty/server/ServletRequestHttpWrapper.java45
-rw-r--r--jetty-server/src/main/java/org/eclipse/jetty/server/ServletResponseHttpWrapper.java33
-rw-r--r--jetty-server/src/main/java/org/eclipse/jetty/server/SessionManager.java66
-rw-r--r--jetty-server/src/main/java/org/eclipse/jetty/server/handler/ContextHandler.java313
-rw-r--r--jetty-server/src/main/java/org/eclipse/jetty/server/handler/IPAccessHandler.java2
-rw-r--r--jetty-server/src/main/java/org/eclipse/jetty/server/handler/RequestLogHandler.java2
-rw-r--r--jetty-server/src/main/java/org/eclipse/jetty/server/session/AbstractSessionManager.java316
-rw-r--r--jetty-server/src/main/java/org/eclipse/jetty/server/session/HashSessionManager.java1
-rw-r--r--jetty-server/src/main/java/org/eclipse/jetty/server/session/JDBCSessionManager.java2
-rw-r--r--jetty-server/src/main/java/org/eclipse/jetty/server/session/SessionHandler.java9
-rw-r--r--jetty-server/src/test/java/org/eclipse/jetty/server/AsyncStressTest.java33
-rw-r--r--jetty-server/src/test/java/org/eclipse/jetty/server/LocalAsyncContextTest.java440
-rw-r--r--jetty-server/src/test/java/org/eclipse/jetty/server/RequestTest.java161
-rw-r--r--jetty-server/src/test/java/org/eclipse/jetty/server/ResponseTest.java16
-rw-r--r--jetty-server/src/test/java/org/eclipse/jetty/server/SelectChannelTimeoutTest.java4
-rw-r--r--jetty-server/src/test/java/org/eclipse/jetty/server/SuspendHandler.java38
-rw-r--r--jetty-server/src/test/java/org/eclipse/jetty/server/session/SessionCookieTest.java199
-rw-r--r--jetty-server/src/test/java/org/eclipse/jetty/server/session/SessionHandlerTest.java260
-rw-r--r--jetty-servlet/pom.xml4
-rw-r--r--jetty-servlet/src/main/java/org/eclipse/jetty/servlet/FilterHolder.java16
-rw-r--r--jetty-servlet/src/main/java/org/eclipse/jetty/servlet/FilterMapping.java4
-rw-r--r--jetty-servlet/src/main/java/org/eclipse/jetty/servlet/Holder.java40
-rw-r--r--jetty-servlet/src/main/java/org/eclipse/jetty/servlet/ServletContextHandler.java741
-rw-r--r--jetty-servlet/src/main/java/org/eclipse/jetty/servlet/ServletHandler.java61
-rw-r--r--jetty-servlet/src/main/java/org/eclipse/jetty/servlet/ServletHolder.java196
-rw-r--r--jetty-servlet/src/main/java/org/eclipse/jetty/servlet/ServletMapping.java21
-rw-r--r--jetty-servlet/src/main/java/org/eclipse/jetty/servlet/api/FilterRegistration.java45
-rw-r--r--jetty-servlet/src/main/java/org/eclipse/jetty/servlet/api/Registration.java43
-rw-r--r--jetty-servlet/src/test/java/org/eclipse/jetty/servlet/AsyncContextTest.java66
-rw-r--r--jetty-servlet/src/test/java/org/eclipse/jetty/servlet/DefaultServletTest.java7
-rw-r--r--jetty-servlet/src/test/java/org/eclipse/jetty/servlet/DispatcherTest.java6
-rw-r--r--jetty-servlet/src/test/java/org/eclipse/jetty/servlet/HolderTest.java95
-rw-r--r--jetty-servlets/pom.xml7
-rw-r--r--jetty-servlets/src/main/java/org/eclipse/jetty/servlets/DoSFilter.java21
-rw-r--r--jetty-servlets/src/main/java/org/eclipse/jetty/servlets/MultiPartFilter.java336
-rw-r--r--jetty-servlets/src/test/java/org/eclipse/jetty/servlets/AbstractDoSFilterTest.java11
-rw-r--r--jetty-servlets/src/test/java/org/eclipse/jetty/servlets/AsyncProxyServer.java6
-rw-r--r--jetty-servlets/src/test/java/org/eclipse/jetty/servlets/CloseableDoSFilterTest.java1
-rw-r--r--jetty-servlets/src/test/java/org/eclipse/jetty/servlets/CrossOriginFilterTest.java33
-rw-r--r--jetty-servlets/src/test/java/org/eclipse/jetty/servlets/DoSFilterTest.java3
-rw-r--r--jetty-servlets/src/test/java/org/eclipse/jetty/servlets/GzipWithPipeliningTest.java5
-rw-r--r--jetty-servlets/src/test/java/org/eclipse/jetty/servlets/IncludableGzipFilterTest.java2
-rw-r--r--jetty-servlets/src/test/java/org/eclipse/jetty/servlets/MultipartFilterTest.java17
-rw-r--r--jetty-servlets/src/test/java/org/eclipse/jetty/servlets/PutFilterTest.java4
-rw-r--r--jetty-servlets/src/test/java/org/eclipse/jetty/servlets/QoSFilterTest.java8
-rw-r--r--jetty-servlets/src/test/java/org/eclipse/jetty/servlets/gzip/GzipTester.java4
-rw-r--r--jetty-spdy/pom.xml2
-rw-r--r--jetty-spdy/spdy-core/pom.xml2
-rw-r--r--jetty-spdy/spdy-jetty-http-webapp/pom.xml2
-rw-r--r--jetty-spdy/spdy-jetty-http/pom.xml2
-rw-r--r--jetty-spdy/spdy-jetty/pom.xml2
-rw-r--r--jetty-start/pom.xml2
-rw-r--r--jetty-start/src/main/resources/org/eclipse/jetty/start/start.config6
-rw-r--r--jetty-util/pom.xml9
-rw-r--r--jetty-util/src/main/java/org/eclipse/jetty/util/MultiMap.java2
-rw-r--r--jetty-util/src/main/java/org/eclipse/jetty/util/MultiPartInputStream.java750
-rw-r--r--jetty-util/src/test/java/org/eclipse/jetty/util/MultiPartInputStreamTest.java328
-rw-r--r--jetty-util/src/test/java/org/eclipse/jetty/util/resource/ResourceTest.java14
-rw-r--r--jetty-util/src/test/java/org/eclipse/jetty/util/thread/TimeoutTest.java5
-rw-r--r--jetty-webapp/pom.xml7
-rw-r--r--jetty-webapp/src/main/java/org/eclipse/jetty/webapp/DiscoveredAnnotation.java15
-rw-r--r--jetty-webapp/src/main/java/org/eclipse/jetty/webapp/FragmentDescriptor.java2
-rw-r--r--jetty-webapp/src/main/java/org/eclipse/jetty/webapp/JettyWebXmlConfiguration.java12
-rw-r--r--jetty-webapp/src/main/java/org/eclipse/jetty/webapp/MetaData.java58
-rw-r--r--jetty-webapp/src/main/java/org/eclipse/jetty/webapp/MetaInfConfiguration.java11
-rw-r--r--jetty-webapp/src/main/java/org/eclipse/jetty/webapp/Ordering.java11
-rw-r--r--jetty-webapp/src/main/java/org/eclipse/jetty/webapp/Origin.java2
-rw-r--r--jetty-webapp/src/main/java/org/eclipse/jetty/webapp/StandardDescriptorProcessor.java535
-rw-r--r--jetty-webapp/src/main/java/org/eclipse/jetty/webapp/WebAppClassLoader.java1
-rw-r--r--jetty-webapp/src/main/java/org/eclipse/jetty/webapp/WebAppContext.java91
-rw-r--r--jetty-webapp/src/main/java/org/eclipse/jetty/webapp/WebXmlConfiguration.java2
-rw-r--r--jetty-webapp/src/test/java/org/eclipse/jetty/webapp/OrderingTest.java38
-rw-r--r--jetty-websocket/pom.xml8
-rw-r--r--jetty-websocket/src/test/java/org/eclipse/jetty/websocket/WebSocketParserD06Test.java3
-rw-r--r--jetty-xml/pom.xml2
-rw-r--r--pom.xml16
-rwxr-xr-xsettings.xml21
-rw-r--r--test-continuation-jetty6/pom.xml20
-rw-r--r--test-continuation-jetty6/src/test/java/org/eclipse/jetty/continuation/ContinuationBase.java428
-rw-r--r--test-continuation-jetty6/src/test/java/org/eclipse/jetty/continuation/FauxContinuationTest.java83
-rw-r--r--test-continuation/pom.xml2
-rw-r--r--test-continuation/src/test/java/org/eclipse/jetty/continuation/ContinuationTest.java2
-rw-r--r--test-continuation/src/test/java/org/eclipse/jetty/continuation/FauxContinuationTest.java5
-rw-r--r--test-jetty-nested/pom.xml2
-rw-r--r--test-jetty-servlet/pom.xml2
-rw-r--r--test-jetty-servlet/src/main/java/org/eclipse/jetty/testing/HttpTester.java2
-rw-r--r--test-jetty-servlet/src/main/java/org/eclipse/jetty/testing/ServletTester.java7
-rw-r--r--test-jetty-webapp/pom.xml7
-rw-r--r--test-jetty-webapp/src/main/config/contexts/test.d/override-web.xml9
-rw-r--r--test-jetty-webapp/src/main/java/com/acme/Dump.java12
-rw-r--r--test-jetty-webapp/src/main/java/com/acme/LoginServlet.java92
-rw-r--r--test-jetty-webapp/src/main/java/com/acme/RegTest.java194
-rw-r--r--test-jetty-webapp/src/main/java/com/acme/TestListener.java36
-rw-r--r--test-jetty-webapp/src/main/webapp/META-INF/MANIFEST.MF4
-rw-r--r--test-jetty-webapp/src/main/webapp/WEB-INF/web.xml49
-rw-r--r--test-jetty-webapp/src/main/webapp/auth.html6
-rw-r--r--test-jetty-webapp/src/main/webapp/index.html4
-rw-r--r--tests/pom.xml2
-rw-r--r--tests/test-integration/pom.xml2
-rw-r--r--tests/test-loginservice/pom.xml2
-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-mongodb-sessions/pom.xml2
-rw-r--r--tests/test-sessions/test-sessions-common/pom.xml2
-rw-r--r--tests/test-webapps/pom.xml2
-rw-r--r--tests/test-webapps/test-webapp-rfc2616/pom.xml2
270 files changed, 11703 insertions, 5355 deletions
diff --git a/.gitignore b/.gitignore
index 12ab1b6945..815d296305 100644
--- a/.gitignore
+++ b/.gitignore
@@ -38,3 +38,4 @@ target/
#maven
*.versionsBackup
+*.releaseBackup
diff --git a/VERSION.txt b/VERSION.txt
index 7f2af82283..447dfa37a0 100644
--- a/VERSION.txt
+++ b/VERSION.txt
@@ -1,10 +1,10 @@
-jetty-7.6.8-SNAPSHOT
+jetty-8.1.8-SNAPSHOT
-jetty-7.6.7.v20120910 - 10 September 2012
+jetty-8.1.7.v20120910 - 10 September 2012
+ 388895 Update dependencies for jetty-jndi
+ fix busy logging statement re: sessions
-jetty-7.6.6.v20120903 - 03 September 2012
+jetty-8.1.6.v20120903 - 03 September 2012
+ 347130 Empty getResourcePaths due to ZipFileClosedException
+ 367591 Support Env variables in XmlConfiguration.
+ 377055 Prevent webapp classloader leaks
@@ -37,7 +37,7 @@ jetty-7.6.6.v20120903 - 03 September 2012
+ 385925: make SslContextFactory.setProtocols and
SslContextFactory.setCipherSuites preserve the order of the given parameters
-jetty-7.6.5.v20120716 - 16 July 2012
+jetty-8.1.5.v20120716 - 16 June 2012
+ 376717 Balancer Servlet with round robin support, contribution, added
missing license
+ 379250 Server is added to shutdown hook twice
@@ -55,15 +55,20 @@ jetty-7.6.5.v20120716 - 16 July 2012
+ 383251 500 for SocketExceptions
+ 383881 WebSocketHandler sets request as handled
+ 384254 revert change to writable when not dispatched
+ + 384280 Implement preliminary ServletRegistrations
+ 384847 CrossOriginFilter is not working.
+ 384896 JDBCSessionManager fails to load existing sessions on oracle when
contextPath is /
+ 384980 Jetty client unable to recover from Time outs when connection count
per address hits max.
+ + 385138 add getter for session path and max cookie age that seemed to
+ disappear in a merge long ago
+ + JETTY-1523 It is imposible to map servlet to "/" using
+ WebApplicationInitializer
+ JETTY-1525 Show handle status in response debug message
+ JETTY-1530 refine search control on ldap login module
-jetty-7.6.4.v20120524 - 24 May 2012
+jetty-8.1.4.v20120524 - 24 May 2012
+ 367608 ignore the aysncrequestreadtest as it is known to fail and is waiting
for a fix
+ 371853 Support bundleentry: protocol for webapp embedded as directory in
@@ -72,9 +77,10 @@ jetty-7.6.4.v20120524 - 24 May 2012
jetty-osgi-boot-logback bundle
+ 376152 apply context resources recursively
+ 376801 Make JAAS login modules useable without jetty infrastructure
+ + 377323 Request#getParts() throws ServletException when it should be throwing
+ IllegalStateException
+ 377391 Manifest updates to jetty-osgi-boot-logback
- + 377492 NPE when deploying a Web Application Bundle with unresolved
- Require-TldBundle
+ + 377492 NPE if jsp taglibs bundle not deployed
+ 377550 set charset when content type is set
+ 377587 ConnectHandler write will block on partial write
+ 377610 New session not timed out if an old session is invalidated in scope
@@ -95,14 +101,18 @@ jetty-7.6.4.v20120524 - 24 May 2012
+ 380212 Clear buffer if parsing fails due to full buffer
+ 380222 JettyPolicyRuntimeTest failure
-jetty-7.6.3.v20120416 - 16 April 2012
+jetty-8.1.3.v20120416 - 16 April 2012
+ + 349110 MultiPartFilter records the content-type in request params
+ 367172 Remove detection for slf4j NOPLogger
+ + 372678 Embedded Examples need updates for new LoginService requirement
+ 373269 Make ServletHandler.notFound() method impl do nothing - override to
send back 404.
+ 373421 address potential race condition related to the nonce queue removing
the same nonce twice
+ 373952 bind called too frequently on refresh
+ 374018 correctly handle requestperminuted underflow
+ + 374152 jetty-all-server MANIFEST contains wrong import:
+ javax.servlet.annotation;version="[2.6,3)"
+ 374252 SslConnection.onClose() does not forward to nested connection.
+ 374258 SPDY leaks SSLEngines. Made the test more reliable.
+ 374367 NPE in QueuedThreadPool.dump() with early java6 jvms
@@ -121,13 +131,19 @@ jetty-7.6.3.v20120416 - 16 April 2012
+ 375594 fixed SSL tests so they are not order dependent
+ 375709 Ensure resolveTempDirectory failure does not deadlock; improve error
message
+ + 375906 Part.getHeader method not case insensitive
+ 375970 HttpServletRequest.getRemoteAddr() returns null when HTTP is over
SPDY.
+ 376201 HalfClosed state not handled properly. Addendum to restore previous
behavior, where a closed stream was also half closed.
+ + 376324 <max-file-size> is not respected in <multipart-config>
+ + JETTY-1495 Ensure dynamic servlet addition does not cause servlets to be
+ inited.
+ + JETTY-1500 form parameters from multipart request not available via
+ request.getParameter
+ JETTY-1504 HttpServletResponseWrapper ignored when using asyncContext?
-jetty-7.6.2.v20120308 - 08 March 2012
+jetty-8.1.2.v20120308 - 08 March 2012
+ 370387 SafariWebsocketDraft0Test failure during build.
+ 371168 Update ClientCrossContextSessionTest
+ 372093 handle quotes in Require-Bundle manifest string
@@ -144,11 +160,12 @@ jetty-7.6.2.v20120308 - 08 March 2012
+ 373306 Set default user agent extraction pattern for UserAgentFilter
+ 373567 cert validation issue with ocsp and crldp always being enabled when
validating turned on fixed
+ + 373603 NullPointer in WebServletAnnotation
+ JETTY-1409 GzipFilter will double-compress application/x-gzip content
+ JETTY-1489 WebAppProvider attempts to deploy .svn folder
+ JETTY-1494 .
-jetty-7.6.1.v20120215 - 15 February 2012
+jetty-8.1.1.v20120215 - 15 February 2012
+ 369121 simplified test
+ 370120 jvm arguments added via start.ini and --exec are missing spaces
+ 370137 SslContextFactory does not respect order for
@@ -162,12 +179,98 @@ jetty-7.6.1.v20120215 - 15 February 2012
+ JETTY-1484 Add option for HashSessionManager to delete session files if it
can't restore them
-jetty-7.6.0.v20120127 - 27 January 2012
+jetty-8.1.0.v20120127 - 27 January 2012
+ 368773 allow authentication to be set by non securityHandler handlers
+ 368992 avoid update key while flushing during a write
+ 369216 turned off the shared resource cache
+ 369349 replace quotes with a space escape method
+jetty-8.1.0.RC5 - 20 January 2012
+ + 359329 Prevent reinvocation of LoginModule.login with jaspi for already
+ authed user
+ + 368632 Remove superfluous removal of org.apache.catalina.jsp_file
+ + 368633 fixed configure.dtd resource mappings
+ + 368635 moved lifecycle state reporting from toString to dump
+ + 368773 process data constraints without realm
+ + 368787 always set token view to new header buffers in httpparser
+ + 368821 improved test harness
+ + 368920 JettyAwareLogger always formats the arguments.
+ + 368948 POM for jetty-jndi references unknown version for javax.activation.
+ + 368992 NPE in HttpGenerator.prepareBuffers() test case.
+ + JETTY-1475 made output state fields volatile to provide memory barrier for
+ non dispatched thread IO
+
+jetty-8.1.0.RC4 - 13 January 2012
+ + 365048 jetty Http client does not send proxy authentication when requesting
+ a Https-resource through a web-proxy.
+ + 366774 removed XSS vulnerbility
+ + 367099 Upgrade jetty-websocket for RFC 6455 - Addendum.
+ + 367433 added tests to investigate
+ + 367435 improved D00 test harness
+ + 367485 HttpExchange canceled before response do not release connection.
+ + 367502 WebSocket connections should be closed when application context is
+ stopped.
+ + 367548 jetty-osgi-boot must not import the nested package twice
+ + 367591 corrected configuration.xml version to 7.6
+ + 367635 Added support for start.d directory
+ + 367716 simplified maxIdleTime logic
+ + 368035 WebSocketClientFactory does not invoke super.doStop().
+ + 368060 do not encode sendRedirect URLs
+ + 368112 NPE on <jsp-config><taglib> element parsing web.xml
+ + 368113 Support servlet mapping to ""
+ + 368114 Protect against non-Strings in System properties for Log
+ + 368189 WebSocketClientFactory should not manage external thread pool. 368240
+ - Improve AggregateLifeCycle handling of shared lifecycles
+ + 368215 Remove debug from jaspi
+ + 368240 Better handling of locally created ThreadPool. Forgot to null out
+ field.
+ + 368291 Change warning to info for NoSuchFieldException on
+ BeanELResolver.properties
+ + 367638 limit number of form parameters to avoid DOS
+ + JETTY-1467 close half closed when idle
+
+jetty-8.1.0.RC2 - 22 December 2011
+ + 359329 jetty-jaspi must exports its packages. jetty-plus must import
+ javax.security
+ + 364638 HttpParser closes if data received while seeking EOF. Tests fixed to
+ cope
+ + 364921 Made test less time sensitive
+ + 364936 use Resource for opening URL streams
+ + 365267 NullPointerException in bad Address
+ + 365375 ResourceHandler should be a HandlerWrapper
+ + 365750 Support WebSocket over SSL, aka wss://
+ + 365932 Produce jetty-websocket aggregate jar for android use
+ + 365947 Set headers for Auth failure and retry in http-spi
+ + 366316 Superfluous printStackTrace on 404
+ + 366342 Dont persist DosFilter trackers in http session
+ + 366730 pass the time idle to onIdleExpire
+ + 367048 test harness for guard on suspended requests
+ + 367175 SSL 100% CPU spin in case of blocked write and RST.
+ + 367219 WebSocketClient.open() fails when URI uses default ports.
+ + 367383 jsp-config element must be returned for
+ ServletContext.getJspConfigDescriptor
+ + JETTY-1460 suppress PrintWriter exceptions
+ + JETTY-1463 websocket D0 parser should return progress even if no fill done
+ + JETTY-1465 NPE in ContextHandler.toString
+
+jetty-8.1.0.RC1 - 06 December 2011
+ + 360245 The version of the javax.servlet packages to import is 2.6 instead of
+ 3.0
+ + 365370 ServletHandler can fall through to nested handler
+
+jetty-8.1.0.RC0 - 30 November 2011
+ + 352565 cookie httponly flag ignored
+ + 353285 ServletSecurity annotation ignored
+ + 357163 jetty 8 ought to proxy jetty8 javadocs
+ + 357209 JSP tag listeners not called
+ + 360051 SocketConnectionTest.testServerClosedConnection is excluded.
+ + 361135 Allow session cookies to NEVER be marked as secure, even on HTTPS
+ requests.
+ + 362249 update shell scripts to jetty8
+ + 363878 Add ecj compiler to jetty-8 for jsp
+ + 364283 can't parse the servlet multipart-config for the web.xml
+ + 364430 Support web.xml enabled state for servlets
+
jetty-7.6.0.RC5 - 20 January 2012
+ 359329 Prevent reinvocation of LoginModule.login with jaspi for already
authed user
@@ -274,6 +377,22 @@ jetty-7.6.0.RC0 - 29 November 2011
+ 364657 Support HTTP only cookies from standard API
+ JETTY-1442 add _hostHeader setter for ProxyRule
+jetty-8.0.4.v20111024 - 24 October 2011
+ + 358263 JDBCSessionIdManager add setDatasource(DataSource) method
+ + 358649 Replace existing StdErrLog system properties for DEBUG/IGNORED with
+ LEVEL instead.
+ + 360836 Accept parameters with bad UTF-8. Use replacement character
+ + 360912 CrossOriginFilter does not send Access-Control-Allow-Origin on
+ responses. 355103 Make allowCredentials default to true in
+ CrossOriginFilter.
+ + 360938 Connections closed after a while.
+ + 361135 secure cookies for sessions
+ + 361319 Log initialization does not catch correct exceptions on all jvms
+ + 361325 359292 Allow KeyStore to be set
+ + 361456 release timer task on connection failed
+ + 361655 ExecutorThreadPool.isLowOnThreads() returns wrong value.
+ + JETTY-1444 start threadpool before selector manager
+
jetty-7.5.4.v20111024 - 24 October 2011
+ 358263 JDBCSessionIdManager add setDatasource(DataSource) method
+ 358649 Replace existing StdErrLog system properties for DEBUG/IGNORED with
@@ -289,6 +408,62 @@ jetty-7.5.4.v20111024 - 24 October 2011
+ 361655 ExecutorThreadPool.isLowOnThreads() returns wrong value.
+ JETTY-1444 start threadpool before selector manager
+jetty-8.0.3.v20111011 - 11 October 2011
+ + 348978 migrate jetty-http-spi
+ + 358649 StdErrLog system properties for package/class logging LEVEL.
+
+jetty-8.0.2.v20111006 - 06 October 2011
+ + 336443 add missing comma in DigestAuthenticator string
+ + 342161 ScannerTest fails intermittently on Mac OS X
+ + 346419 testing HttpClient FDs
+ + 353267 Request._parameters initialization bug
+ + 353509 jetty-client unit tests are running too long
+ + 353627 Basic Auth checks that Basic method has been send
+ + 356144 Allow SelectorManager thread priority to be set
+ + 356274 Start SSL socket factory in call to open()
+ + 357163 jetty 8 ought to proxy jetty8 javadocs
+ + 357178 websockets draft 14 support
+ + 357188 Send content buffer directly
+ + 357209 JSP tag listeners not called
+ + 357216 Logging via Log4J does not expand braces in format strings
+ + 357240 more half close refinements
+ + 357338 remove debug
+ + 357672 resolve issue with serializing pojos with mongodb session manager,
+ thanks to john simone for the discovery and fix
+ + 357959 Include javadoc in distribution
+ + 358027 NullPointerException in ResourceHandler with jetty-stylesheet.css
+ + 358035 idle time only active if > 0
+ + 358147 Add catch for UnknownHostException to fix leaky file descriptor in
+ client
+ + 358164 Dispatch from servlet to handler
+ + 358263 add method for osgi users to register a driver as Class.forName does
+ not work for them
+ + 358649 StdErrLog system properties for package/class logging LEVEL.
+ + 358674 Still allows sslv3 for now
+ + 358687 Updated jsp does not scan for system tlds Fixed pattern.
+ + 358784 JSP broken on Java 1.5
+ + 358925 bit more javadoc on usage
+ + 358959 File descriptor leak with UnresolvedAddressException
+ + 359309 adjust previous test for servletPath to include pathInfo
+ + 359673 updated websocket version handling
+ + 359675 Principal != String, fix for issue in property file login manager
+ + 360051 SocketConnectionTest.testServerClosedConnection is excluded.
+ + 360066 jsps referenced in web.xml <jsp-file> elements do not compile
+ + JETTY-1130 Access Sessions from HashSessionIdManager
+ + JETTY-1277 Fixed sendRedirect encoding of relative locations
+ + JETTY-1322 idle sweeper checks for closed endp
+ + JETTY-1377 extra logging for busy selector
+ + JETTY-1378 new sys property for the latest jsp-impl to force the use of the
+ JDTCompiler when running in OSGi.
+ + JETTY-1414 applied to PropertyUserStore
+ + JETTY-1415 Start/Stop Server and Client only once in test, code format
+ + JETTY-1420 Set Host header for new request in RedirectListener
+ + JETTY-1421 Implement RedirectListener.onException,onConnectionFailed
+ + JETTY-1423 force connection to be closed returned
+ + JETTY-1430 local JNDI contexts don't carry environment
+ + JETTY-1434 Add a jsp that exercises jstl.
+ + JETTY-1439 space in directory installation path causes classloader problem
+
jetty-7.5.3.v20111011 - 11 October 2011
+ 348978 migrate jetty-http-spi
+ 358649 StdErrLog system properties for package/class logging LEVEL.
@@ -304,6 +479,7 @@ jetty-7.5.2.v20111006 - 06 October 2011
+ 356274 Start SSL socket factory in call to open()
+ 357178 websockets draft 14 support
+ 357188 Send content buffer directly
+ + 357209 JSP tag listeners not called
+ 357216 Logging via Log4J does not expand braces in format strings
+ 357240 more half close refinements
+ 357338 remove debug
@@ -343,6 +519,18 @@ jetty-7.5.2.v20111006 - 06 October 2011
+ JETTY-1434 Add a jsp that exercises jstl.
+ JETTY-1439 space in directory installation path causes classloader problem
+jetty-8.0.1.v20110908 - 08 September 2011
+ + 350634 Added Resource.newResource(File)
+ + 356190 fix monodb tests for changed test api
+ + 356428 removed timed waits from test
+ + 356693 reduce visibility to webapp of websocket implementations
+ + 356695 jetty server jars are provided for websockets
+ + 356726 Instead of the sessionDestroyed called sessionCreated after
+ invalidate session
+ + 356751 Add null protection to ServletContextHandler.doStop
+ + 356823 correctly decode close codes. Send not utf-8 close code.
+ + 357058 Acceptor thread blocking
+
jetty-7.5.1.v20110908 - 08 September 2011
+ 350634 Added Resource.newResource(File)
+ 356190 fix monodb tests for changed test api
@@ -355,6 +543,12 @@ jetty-7.5.1.v20110908 - 08 September 2011
+ 356823 correctly decode close codes. Send not utf-8 close code.
+ 357058 Acceptor thread blocking
+jetty-8.0.0.v20110901 - 01 September 2011
+ + 352565 cookie httponly flag ignored
+ + 353073 better warnings
+ + 353285 ServletSecurity annotation ignored
+ + 356421 Upgraded websocket to draft 13 support
+
jetty-7.5.0.v20110901 - 01 September 2011
+ 356421 Upgraded websocket to draft 13 support
+ 353073 better warnings
@@ -389,6 +583,19 @@ jetty-7.5.0.RC1 - 19 August 2011
+ JETTY-1414 HashLoginService doesn't refresh realm if specified config
filename is not an absolute platform specific value
+jetty-8.0.0.RC0 - 16 August 2011
+ + Merge from jetty-7.4.3
+ + Enable annotations by default
+ + 352565 cookie httponly flag ignored
+ + 353285 ServletSecurity annotation ignored
+
+jetty-8.0.0.M3 - 27 May 2011
+ + 324505 Implement API login
+ + 335500 request.getParts() throws a NullPointerException
+ + 343472 isUserInRole does not prevent subsequent login call.
+ + 346180 jsp-2.2 support
+ + Updated to jetty-7.4.2.v20110526
+
jetty-7.5.0.RC0 - 15 August 2011
+ 298502 Handle 200 Connect responses with no content-length
+ 347484 / - > ${/} in some paths in grant codebases
@@ -571,6 +778,26 @@ jetty-7.4.0.RC0
+ Ensure generated fragment names are unique
+ Added extra session removal test
+jetty-8.0.0.M2 - 16 November 2010
+ + 320073 Reconsile configuration mechanism
+ + 321068 JSF2 fails to initialize
+ + 324493 Registration init parameter handling null check, setInitParameters
+ additive
+ + 324505 Request.login method must throw ServletException if it cant login
+ + 324872 allow disabling listener restriction from using *Registration
+ interfaces
+ + 327416 Change meaning of @HandlesTypes in line with latest interpretation by
+ JSR315
+ + 327489 Change meaning of @MultipartConfig to match servlet spec 3.0
+ maintenance release 3.0a
+ + 328008 Handle update to Servlet Spec 3 Section 8.2.3.h.ii
+ + 330188 Reject web-fragment.xml with same <name> as another already loaded
+ one
+ + 330208 Support new wording on servlet-mapping and filter-mapping merging
+ from servlet3.0a
+ + 330292 request.getParts() returns only one part when the name is the same
+ + Update to jetty-7.2.1.v20101111
+
jetty-7.3.1.v20110307 - 07 March 2011
+ 316382 Support a more strict SSL option with certificates
+ 333481 Handle UCS-4 codepoints in decode and encode
@@ -596,9 +823,7 @@ jetty-7.3.1.v20110307 - 07 March 2011
+ 338068 Leaking ConstraintMappings on redeploy
+ 338092 ProxyServlet leaks memory
+ 338607 Removed managed attributes when context is stopped
- + 338880 Fixed failing buffer range checks
- + 338920 Handle non existent real path directories
- + 338961 AJP packet size
+ + 338819 Externally control Deployment Manager application lifecycle
+ JETTY-1304 Allow quoted boundaries in Multipart filter
+ JETTY-1317 More elegent handling of bad URIs in requests
+ JETTY-1331 Allow alternate XML configuration processors (eg spring)
@@ -784,7 +1009,6 @@ jetty-7.2.0.RC0 - 01 October 2010
+ JETTY-1245 Do not use direct buffers with NIO SSL
+ JETTY-1249 Apply max idle time to all connectors
+ JETTY-1250 Parallel start of HandlerCollection
- + JETTY-1252 Handle more multipart transfer encodings
+ JETTY-1256 annotation and jta jars from Orbit
+ JETTY-1259 NullPointerException in JDBCSessionIdManager when invalidating
session
@@ -812,6 +1036,15 @@ jetty-7.1.6.v20100715
+ JETTY-1249 Apply max idle time to all connectors
+ JETTY-1251 Replace then close selector for JVM bugs
+jetty-8.0.0.M1 - 12 July 2010
+ + 306350 Ensure jars excluded by ordering are not scanned for annotations
+ + JETTY-1224 Change jetty-8 merge rules for fragment descriptors and
+ annotations
+ + Ensure <absolute-ordering> in web.xml overrides relative <ordering> in
+ fragments
+ + Ensure empty <absolute-ordering> implies exclusion of all fragments
+ + Ensure servlet-api jar class inheritance hierarchy is scanned
+
jetty-7.1.5.v20100705
+ Update ecj to 3.6 Helios release drop
+ 288194 Add blacklist/whitelist to ProxyServlet and ProxyHandler
@@ -975,6 +1208,9 @@ jetty-7.1.0.RC0 - 27 April 2010
+ Fix jetty-plus.xml reference to addLifeCycle
+ JETTY-1200 SSL NIO Endpoint wraps non NIO buffers
+ JETTY-1202 Use platform default algorithm for SecureRandom
+ + Merged 7.0.2.v20100331
+ + Add NPE protection to ContainerInitializerConfiguration
+ + Temporarily remove jetty-osgi module to clarify jsp version compatibility
+ JETTY-1212 handle long content lengths
+ JETTY-1214 avoid ISE when scavenging invalid session
+ JETTY-903 Stop both caches
@@ -1123,6 +1359,11 @@ jetty-7.0.2.RC0
+ 305997 Coalesce buffers in ChannelEndPoint.flush()
+ 306028 Enable TCP_NODELAY by default in client connectors
+jetty-8.0.0.M0 - 28 February 2010
+ + Updated servlet 3.0 spec 20100224
+ + Merged 7.0.1.v20091116
+ + Updated to cometd 1.0.1
+
jetty-7.0.1.v20091125 - 25 November 2009
+ 274251 DefaultServlet supports exact match mode.
+ 288401 HttpExchange.cancel() Method Unimplemented
diff --git a/example-async-rest/async-rest-jar/pom.xml b/example-async-rest/async-rest-jar/pom.xml
new file mode 100644
index 0000000000..19ebc74c58
--- /dev/null
+++ b/example-async-rest/async-rest-jar/pom.xml
@@ -0,0 +1,24 @@
+<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</groupId>
+ <artifactId>example-async-rest</artifactId>
+ <version>8.1.8-SNAPSHOT</version>
+ </parent>
+ <modelVersion>4.0.0</modelVersion>
+ <groupId>org.eclipse.jetty.example-async-rest</groupId>
+ <artifactId>example-async-rest-jar</artifactId>
+ <packaging>jar</packaging>
+ <name>Example Async Rest :: Jar</name>
+ <dependencies>
+ <dependency>
+ <groupId>org.eclipse.jetty</groupId>
+ <artifactId>jetty-client</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.eclipse.jetty.orbit</groupId>
+ <artifactId>javax.servlet</artifactId>
+ <scope>provided</scope>
+ </dependency>
+ </dependencies>
+</project>
diff --git a/example-async-rest/async-rest-jar/src/main/java/org/eclipse/jetty/example/asyncrest/AbstractRestServlet.java b/example-async-rest/async-rest-jar/src/main/java/org/eclipse/jetty/example/asyncrest/AbstractRestServlet.java
new file mode 100644
index 0000000000..75ee3f0dfd
--- /dev/null
+++ b/example-async-rest/async-rest-jar/src/main/java/org/eclipse/jetty/example/asyncrest/AbstractRestServlet.java
@@ -0,0 +1,120 @@
+//
+// ========================================================================
+// Copyright (c) 1995-2012 Mort Bay Consulting Pty. Ltd.
+// ------------------------------------------------------------------------
+// All rights reserved. This program and the accompanying materials
+// are made available under the terms of the Eclipse Public License v1.0
+// and Apache License v2.0 which accompanies this distribution.
+//
+// The Eclipse Public License is available at
+// http://www.eclipse.org/legal/epl-v10.html
+//
+// The Apache License v2.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.example.asyncrest;
+
+import java.io.IOException;
+import java.math.BigDecimal;
+import java.math.RoundingMode;
+import java.net.URLEncoder;
+import java.util.Map;
+import java.util.Queue;
+
+import javax.servlet.ServletConfig;
+import javax.servlet.ServletException;
+import javax.servlet.http.HttpServlet;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+/**
+ * Abstract Servlet implementation class AsyncRESTServlet.
+ * Enquires ebay REST service for auctions by key word.
+ * May be configured with init parameters: <dl>
+ * <dt>appid</dt><dd>The eBay application ID to use</dd>
+ * </dl>
+ * Each request examines the following request parameters:<dl>
+ * <dt>items</dt><dd>The keyword to search for</dd>
+ * </dl>
+ */
+public class AbstractRestServlet extends HttpServlet
+{
+ protected final static String __DEFAULT_APPID = "Webtide81-adf4-4f0a-ad58-d91e41bbe85";
+ protected final static String STYLE =
+ "<style type='text/css'>"+
+ " img.thumb:hover {height:50px}"+
+ " img.thumb {vertical-align:text-top}"+
+ " span.red {color: #ff0000}"+
+ " span.green {color: #00ff00}"+
+ " iframe {border: 0px}"+
+ "</style>";
+
+ protected final static String ITEMS_PARAM = "items";
+ protected final static String APPID_PARAM = "appid";
+
+ protected String _appid;
+
+ public void init(ServletConfig servletConfig) throws ServletException
+ {
+ if (servletConfig.getInitParameter(APPID_PARAM) == null)
+ _appid = __DEFAULT_APPID;
+ else
+ _appid = servletConfig.getInitParameter(APPID_PARAM);
+ }
+
+ protected String restURL(String item)
+ {
+ try
+ {
+ return ("http://open.api.ebay.com/shopping?MaxEntries=3&appid=" + _appid +
+ "&version=573&siteid=0&callname=FindItems&responseencoding=JSON&QueryKeywords=" +
+ URLEncoder.encode(item,"UTF-8"));
+ }
+ catch(Exception e)
+ {
+ throw new RuntimeException(e);
+ }
+ }
+
+ protected String generateThumbs(Queue<Map<String,String>> results)
+ {
+ StringBuilder thumbs = new StringBuilder();
+ for (Map<String, String> m : results)
+ {
+ if (!m.containsKey("GalleryURL"))
+ continue;
+
+ thumbs.append("<a href=\""+m.get("ViewItemURLForNaturalSearch")+"\">");
+ thumbs.append("<img class='thumb' border='1px' height='25px'"+
+ " src='"+m.get("GalleryURL")+"'"+
+ " title='"+m.get("Title")+"'"+
+ "/>");
+ thumbs.append("</a>&nbsp;");
+ }
+ return thumbs.toString();
+ }
+
+ protected String ms(long nano)
+ {
+ BigDecimal dec = new BigDecimal(nano);
+ return dec.divide(new BigDecimal(1000000L)).setScale(1,RoundingMode.UP).toString();
+ }
+
+ protected int width(long nano)
+ {
+ int w=(int)((nano+999999L)/5000000L);
+ if (w==0)
+ w=2;
+ return w;
+ }
+
+ protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException
+ {
+ doGet(request, response);
+ }
+
+}
diff --git a/example-async-rest/async-rest-jar/src/main/java/org/eclipse/jetty/example/asyncrest/AsyncRestServlet.java b/example-async-rest/async-rest-jar/src/main/java/org/eclipse/jetty/example/asyncrest/AsyncRestServlet.java
new file mode 100644
index 0000000000..0b16297c15
--- /dev/null
+++ b/example-async-rest/async-rest-jar/src/main/java/org/eclipse/jetty/example/asyncrest/AsyncRestServlet.java
@@ -0,0 +1,211 @@
+//
+// ========================================================================
+// Copyright (c) 1995-2012 Mort Bay Consulting Pty. Ltd.
+// ------------------------------------------------------------------------
+// All rights reserved. This program and the accompanying materials
+// are made available under the terms of the Eclipse Public License v1.0
+// and Apache License v2.0 which accompanies this distribution.
+//
+// The Eclipse Public License is available at
+// http://www.eclipse.org/legal/epl-v10.html
+//
+// The Apache License v2.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.example.asyncrest;
+
+import java.io.IOException;
+import java.io.PrintWriter;
+import java.util.Map;
+import java.util.Queue;
+import java.util.concurrent.ConcurrentLinkedQueue;
+import java.util.concurrent.atomic.AtomicInteger;
+
+import javax.servlet.AsyncContext;
+import javax.servlet.ServletConfig;
+import javax.servlet.ServletException;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import org.eclipse.jetty.client.ContentExchange;
+import org.eclipse.jetty.client.HttpClient;
+import org.eclipse.jetty.util.ajax.JSON;
+
+/**
+ * Servlet implementation class AsyncRESTServlet.
+ * Enquires ebay REST service for auctions by key word.
+ * May be configured with init parameters: <dl>
+ * <dt>appid</dt><dd>The eBay application ID to use</dd>
+ * </dl>
+ * Each request examines the following request parameters:<dl>
+ * <dt>items</dt><dd>The keyword to search for</dd>
+ * </dl>
+ */
+public class AsyncRestServlet extends AbstractRestServlet
+{
+ final static String RESULTS_ATTR = "org.eclipse.jetty.demo.client";
+ final static String DURATION_ATTR = "org.eclipse.jetty.demo.duration";
+ final static String START_ATTR = "org.eclispe.jetty.demo.start";
+
+ HttpClient _client;
+
+ public void init(ServletConfig servletConfig) throws ServletException
+ {
+ super.init(servletConfig);
+
+ _client = new HttpClient();
+ _client.setConnectorType(HttpClient.CONNECTOR_SELECT_CHANNEL);
+
+ try
+ {
+ _client.start();
+ }
+ catch (Exception e)
+ {
+ throw new ServletException(e);
+ }
+ }
+
+ protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException
+ {
+ Long start=System.nanoTime();
+
+ // Do we have results yet?
+ Queue<Map<String, String>> results = (Queue<Map<String, String>>) request.getAttribute(RESULTS_ATTR);
+
+ // If no results, this must be the first dispatch, so send the REST request(s)
+ if (results==null)
+ {
+ // define results data structures
+ final Queue<Map<String, String>> resultsQueue = new ConcurrentLinkedQueue<Map<String,String>>();
+ request.setAttribute(RESULTS_ATTR, results=resultsQueue);
+
+ // suspend the request
+ // This is done before scheduling async handling to avoid race of
+ // dispatch before startAsync!
+ final AsyncContext async = request.startAsync();
+ async.setTimeout(30000);
+
+ // extract keywords to search for
+ String[] keywords=request.getParameter(ITEMS_PARAM).split(",");
+ final AtomicInteger outstanding=new AtomicInteger(keywords.length);
+
+ // Send request each keyword
+ for (final String item:keywords)
+ {
+ _client.send(
+ new AsyncRestRequest(item)
+ {
+ void onAuctionFound(Map<String,String> auction)
+ {
+ resultsQueue.add(auction);
+ }
+ void onComplete()
+ {
+ if (outstanding.decrementAndGet()<=0)
+ async.dispatch();
+ }
+ });
+ }
+
+ // save timing info and return
+ request.setAttribute(START_ATTR, start);
+ request.setAttribute(DURATION_ATTR, new Long(System.nanoTime() - start));
+
+ return;
+ }
+
+ // We have results!
+
+ // Generate the response
+ String thumbs = generateThumbs(results);
+
+ response.setContentType("text/html");
+ PrintWriter out = response.getWriter();
+ out.println("<html><head>");
+ out.println(STYLE);
+ out.println("</head><body><small>");
+
+ long initial = (Long) request.getAttribute(DURATION_ATTR);
+ long start0 = (Long) request.getAttribute(START_ATTR);
+
+ long now = System.nanoTime();
+ long total=now-start0;
+ long generate=now-start;
+ long thread=initial+generate;
+
+ out.print("<b>Asynchronous: "+request.getParameter(ITEMS_PARAM)+"</b><br/>");
+ out.print("Total Time: "+ms(total)+"ms<br/>");
+
+ out.print("Thread held (<span class='red'>red</span>): "+ms(thread)+"ms (" + ms(initial) + " initial + " + ms(generate) + " generate )<br/>");
+ out.print("Async wait (<span class='green'>green</span>): "+ms(total-thread)+"ms<br/>");
+
+ out.println("<img border='0px' src='asyncrest/red.png' height='20px' width='"+width(initial)+"px'>"+
+ "<img border='0px' src='asyncrest/green.png' height='20px' width='"+width(total-thread)+"px'>"+
+ "<img border='0px' src='asyncrest/red.png' height='20px' width='"+width(generate)+"px'>");
+
+ out.println("<hr />");
+ out.println(thumbs);
+ out.println("</small>");
+ out.println("</body></html>");
+ out.close();
+ }
+
+ private abstract class AsyncRestRequest extends ContentExchange
+ {
+ AsyncRestRequest(final String item)
+ {
+ // send the exchange
+ setMethod("GET");
+ setURL(restURL(item));
+ }
+
+ abstract void onAuctionFound(Map<String,String> details);
+ abstract void onComplete();
+
+ protected void onResponseComplete() throws IOException
+ {
+ // extract auctions from the results
+ Map<String,?> query = (Map<String,?>) JSON.parse(this.getResponseContent());
+ Object[] auctions = (Object[]) query.get("Item");
+ if (auctions != null)
+ {
+ for (Object o : auctions)
+ onAuctionFound((Map<String,String>)o);
+ }
+
+ onComplete();
+ }
+
+ /* ------------------------------------------------------------ */
+ protected void onConnectionFailed(Throwable ex)
+ {
+ getServletContext().log("onConnectionFailed: ",ex);
+ onComplete();
+ }
+
+ /* ------------------------------------------------------------ */
+ protected void onException(Throwable ex)
+ {
+ getServletContext().log("onConnectionFailed: ",ex);
+ onComplete();
+ }
+
+ /* ------------------------------------------------------------ */
+ protected void onExpire()
+ {
+ getServletContext().log("onConnectionFailed: expired");
+ onComplete();
+ }
+ }
+
+ protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException
+ {
+ doGet(request, response);
+ }
+
+}
diff --git a/example-async-rest/async-rest-jar/src/main/java/org/eclipse/jetty/example/asyncrest/SerialRestServlet.java b/example-async-rest/async-rest-jar/src/main/java/org/eclipse/jetty/example/asyncrest/SerialRestServlet.java
new file mode 100644
index 0000000000..8097ef02ad
--- /dev/null
+++ b/example-async-rest/async-rest-jar/src/main/java/org/eclipse/jetty/example/asyncrest/SerialRestServlet.java
@@ -0,0 +1,106 @@
+//
+// ========================================================================
+// Copyright (c) 1995-2012 Mort Bay Consulting Pty. Ltd.
+// ------------------------------------------------------------------------
+// All rights reserved. This program and the accompanying materials
+// are made available under the terms of the Eclipse Public License v1.0
+// and Apache License v2.0 which accompanies this distribution.
+//
+// The Eclipse Public License is available at
+// http://www.eclipse.org/legal/epl-v10.html
+//
+// The Apache License v2.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.example.asyncrest;
+
+import java.io.BufferedReader;
+import java.io.IOException;
+import java.io.InputStreamReader;
+import java.io.PrintWriter;
+import java.net.HttpURLConnection;
+import java.net.URL;
+import java.util.LinkedList;
+import java.util.Map;
+import java.util.Queue;
+
+import javax.servlet.ServletException;
+import javax.servlet.http.HttpServlet;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import org.eclipse.jetty.util.ajax.JSON;
+
+/**
+ * Servlet implementation class SerialRestServlet
+ */
+public class SerialRestServlet extends AbstractRestServlet
+{
+ protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException
+ {
+ long start = System.nanoTime();
+
+
+ String[] keywords=request.getParameter(ITEMS_PARAM).split(",");
+ Queue<Map<String,String>> results = new LinkedList<Map<String,String>>();
+
+ // make all requests serially
+ for (String itemName : keywords)
+ {
+ URL url = new URL(restURL(itemName));
+
+ HttpURLConnection connection = (HttpURLConnection)url.openConnection();
+ connection.setRequestMethod("GET");
+
+ Map query = (Map)JSON.parse(new BufferedReader(new InputStreamReader(connection.getInputStream())));
+ Object[] auctions = (Object[]) query.get("Item");
+ if (auctions != null)
+ {
+ for (Object o : auctions)
+ results.add((Map) o);
+ }
+ }
+
+
+ // Generate the response
+ String thumbs=generateThumbs(results);
+
+ response.setContentType("text/html");
+ PrintWriter out = response.getWriter();
+ out.println("<html><head>");
+ out.println(STYLE);
+ out.println("</head><body><small>");
+
+ long now = System.nanoTime();
+ long total=now-start;
+
+ out.print("<b>Blocking: "+request.getParameter(ITEMS_PARAM)+"</b><br/>");
+ out.print("Total Time: "+ms(total)+"ms<br/>");
+ out.print("Thread held (<span class='red'>red</span>): "+ms(total)+"ms<br/>");
+
+ out.println("<img border='0px' src='asyncrest/red.png' height='20px' width='"+width(total)+"px'>");
+
+ out.println("<hr />");
+ out.println(thumbs);
+ out.println("</small>");
+ out.println("</body></html>");
+ out.close();
+
+
+
+ }
+
+ /**
+ * @see HttpServlet#doPost(HttpServletRequest request, HttpServletResponse
+ * response)
+ */
+ protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException
+ {
+ doGet(request, response);
+ }
+
+}
diff --git a/example-async-rest/async-rest-jar/src/main/resources/META-INF/resources/asyncrest.html b/example-async-rest/async-rest-jar/src/main/resources/META-INF/resources/asyncrest.html
new file mode 100644
index 0000000000..f92f7f661d
--- /dev/null
+++ b/example-async-rest/async-rest-jar/src/main/resources/META-INF/resources/asyncrest.html
@@ -0,0 +1,38 @@
+<html>
+ <head>
+ <style type='text/css'>
+ iframe {border: 0px}
+ table, tr, td {border: 0px}
+ </style>
+</head>
+<body>
+<h1>Blocking vs Asynchronous REST</h1>
+<p>
+This demo calls the EBay WS API both synchronously and asynchronously,
+to obtain items matching each of the keywords passed on the query
+string. The time the request thread is head is displayed for both.
+</p>
+
+<table width='100%'>
+
+<tr>
+<td>
+ <iframe id="f1" width='100%' height='175px' src="testSerial?items=kayak"></iframe>
+</td>
+<td>
+ <iframe id="f3" width='100%' height='175px' src="testSerial?items=mouse,beer,gnome"></iframe>
+</td>
+</tr>
+
+<tr>
+<td>
+ <iframe id="f2" width='100%' height='175px' src="testAsync?items=kayak"/></iframe>
+</td>
+<td>
+ <iframe id="f4" width='100%' height='175px' src="testAsync?items=mouse,beer,gnome"/></iframe>
+</td>
+</tr>
+
+</table>
+</body>
+</html>
diff --git a/example-async-rest/async-rest-jar/src/main/resources/META-INF/resources/asyncrest/green.png b/example-async-rest/async-rest-jar/src/main/resources/META-INF/resources/asyncrest/green.png
new file mode 100644
index 0000000000..d0fb8420c5
--- /dev/null
+++ b/example-async-rest/async-rest-jar/src/main/resources/META-INF/resources/asyncrest/green.png
Binary files differ
diff --git a/example-async-rest/async-rest-jar/src/main/resources/META-INF/resources/asyncrest/red.png b/example-async-rest/async-rest-jar/src/main/resources/META-INF/resources/asyncrest/red.png
new file mode 100644
index 0000000000..f2a79a07fb
--- /dev/null
+++ b/example-async-rest/async-rest-jar/src/main/resources/META-INF/resources/asyncrest/red.png
Binary files differ
diff --git a/example-async-rest/async-rest-jar/src/main/resources/META-INF/web-fragment.xml b/example-async-rest/async-rest-jar/src/main/resources/META-INF/web-fragment.xml
new file mode 100644
index 0000000000..9876d9983b
--- /dev/null
+++ b/example-async-rest/async-rest-jar/src/main/resources/META-INF/web-fragment.xml
@@ -0,0 +1,22 @@
+<web-fragment>
+ <servlet>
+ <display-name>SerialRestServlet</display-name>
+ <servlet-name>SerialRestServlet</servlet-name>
+ <servlet-class>org.eclipse.jetty.example.asyncrest.SerialRestServlet</servlet-class>
+ </servlet>
+ <servlet-mapping>
+ <servlet-name>SerialRestServlet</servlet-name>
+ <url-pattern>/testSerial</url-pattern>
+ </servlet-mapping>
+
+ <servlet>
+ <display-name>AsyncRestServlet</display-name>
+ <servlet-name>AsyncRestServlet</servlet-name>
+ <servlet-class>org.eclipse.jetty.example.asyncrest.AsyncRestServlet</servlet-class>
+ <async-supported>true</async-supported>
+ </servlet>
+ <servlet-mapping>
+ <servlet-name>AsyncRestServlet</servlet-name>
+ <url-pattern>/testAsync</url-pattern>
+ </servlet-mapping>
+</web-fragment> \ No newline at end of file
diff --git a/example-async-rest/async-rest-webapp/pom.xml b/example-async-rest/async-rest-webapp/pom.xml
new file mode 100644
index 0000000000..44fd96742d
--- /dev/null
+++ b/example-async-rest/async-rest-webapp/pom.xml
@@ -0,0 +1,33 @@
+<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</groupId>
+ <artifactId>example-async-rest</artifactId>
+ <version>8.1.8-SNAPSHOT</version>
+ </parent>
+ <modelVersion>4.0.0</modelVersion>
+ <groupId>org.eclipse.jetty.example-async-rest</groupId>
+ <artifactId>example-async-rest-webapp</artifactId>
+ <packaging>war</packaging>
+ <name>Example Async Rest :: Webapp</name>
+ <build>
+ <finalName>async-rest</finalName>
+ </build>
+ <dependencies>
+ <dependency>
+ <groupId>org.eclipse.jetty.example-async-rest</groupId>
+ <artifactId>example-async-rest-jar</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.eclipse.jetty</groupId>
+ <artifactId>jetty-webapp</artifactId>
+ <version>${project.version}</version>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.eclipse.jetty.orbit</groupId>
+ <artifactId>javax.servlet</artifactId>
+ <scope>provided</scope>
+ </dependency>
+ </dependencies>
+</project>
diff --git a/example-async-rest/async-rest-webapp/src/main/webapp/META-INF/MANIFEST.MF b/example-async-rest/async-rest-webapp/src/main/webapp/META-INF/MANIFEST.MF
new file mode 100644
index 0000000000..5e9495128c
--- /dev/null
+++ b/example-async-rest/async-rest-webapp/src/main/webapp/META-INF/MANIFEST.MF
@@ -0,0 +1,3 @@
+Manifest-Version: 1.0
+Class-Path:
+
diff --git a/example-async-rest/async-rest-webapp/src/main/webapp/WEB-INF/web.xml b/example-async-rest/async-rest-webapp/src/main/webapp/WEB-INF/web.xml
new file mode 100644
index 0000000000..8916bdb6af
--- /dev/null
+++ b/example-async-rest/async-rest-webapp/src/main/webapp/WEB-INF/web.xml
@@ -0,0 +1,9 @@
+<?xml version="1.0"?>
+<web-app xmlns="http://java.sun.com/xml/ns/javaee"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"
+ version="3.0">
+
+ <display-name>Async REST Webservice Example</display-name>
+
+</web-app>
diff --git a/example-async-rest/async-rest-webapp/src/main/webapp/index.html b/example-async-rest/async-rest-webapp/src/main/webapp/index.html
new file mode 100644
index 0000000000..f92f7f661d
--- /dev/null
+++ b/example-async-rest/async-rest-webapp/src/main/webapp/index.html
@@ -0,0 +1,38 @@
+<html>
+ <head>
+ <style type='text/css'>
+ iframe {border: 0px}
+ table, tr, td {border: 0px}
+ </style>
+</head>
+<body>
+<h1>Blocking vs Asynchronous REST</h1>
+<p>
+This demo calls the EBay WS API both synchronously and asynchronously,
+to obtain items matching each of the keywords passed on the query
+string. The time the request thread is head is displayed for both.
+</p>
+
+<table width='100%'>
+
+<tr>
+<td>
+ <iframe id="f1" width='100%' height='175px' src="testSerial?items=kayak"></iframe>
+</td>
+<td>
+ <iframe id="f3" width='100%' height='175px' src="testSerial?items=mouse,beer,gnome"></iframe>
+</td>
+</tr>
+
+<tr>
+<td>
+ <iframe id="f2" width='100%' height='175px' src="testAsync?items=kayak"/></iframe>
+</td>
+<td>
+ <iframe id="f4" width='100%' height='175px' src="testAsync?items=mouse,beer,gnome"/></iframe>
+</td>
+</tr>
+
+</table>
+</body>
+</html>
diff --git a/example-async-rest/async-rest-webapp/src/test/java/org/eclipse/jetty/example/asyncrest/DemoServer.java b/example-async-rest/async-rest-webapp/src/test/java/org/eclipse/jetty/example/asyncrest/DemoServer.java
new file mode 100644
index 0000000000..667c14568d
--- /dev/null
+++ b/example-async-rest/async-rest-webapp/src/test/java/org/eclipse/jetty/example/asyncrest/DemoServer.java
@@ -0,0 +1,48 @@
+//
+// ========================================================================
+// Copyright (c) 1995-2012 Mort Bay Consulting Pty. Ltd.
+// ------------------------------------------------------------------------
+// All rights reserved. This program and the accompanying materials
+// are made available under the terms of the Eclipse Public License v1.0
+// and Apache License v2.0 which accompanies this distribution.
+//
+// The Eclipse Public License is available at
+// http://www.eclipse.org/legal/epl-v10.html
+//
+// The Apache License v2.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.example.asyncrest;
+
+import org.eclipse.jetty.server.Connector;
+import org.eclipse.jetty.server.Server;
+import org.eclipse.jetty.server.nio.SelectChannelConnector;
+import org.eclipse.jetty.webapp.WebAppContext;
+
+public class DemoServer
+{
+ public static void main(String[] args)
+ throws Exception
+ {
+ String jetty_home = System.getProperty("jetty.home",".");
+
+ Server server = new Server();
+
+ Connector connector=new SelectChannelConnector();
+ connector.setPort(Integer.getInteger("jetty.port",8080).intValue());
+ server.setConnectors(new Connector[]{connector});
+
+ WebAppContext webapp = new WebAppContext();
+ webapp.setContextPath("/");
+ webapp.setWar(jetty_home+"/target/example-async-rest-webapp-8.0.0.M0-SNAPSHOT");
+
+ server.setHandler(webapp);
+
+ server.start();
+ server.join();
+ }
+}
diff --git a/example-async-rest/pom.xml b/example-async-rest/pom.xml
new file mode 100644
index 0000000000..55c66e364c
--- /dev/null
+++ b/example-async-rest/pom.xml
@@ -0,0 +1,16 @@
+<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</groupId>
+ <artifactId>jetty-project</artifactId>
+ <version>8.1.8-SNAPSHOT</version>
+ </parent>
+ <modelVersion>4.0.0</modelVersion>
+ <groupId>org.eclipse.jetty</groupId>
+ <artifactId>example-async-rest</artifactId>
+ <packaging>pom</packaging>
+ <name>Example Async Rest</name>
+ <modules>
+ <module>async-rest-jar</module>
+ <module>async-rest-webapp</module>
+ </modules>
+</project>
diff --git a/example-jetty-embedded/pom.xml b/example-jetty-embedded/pom.xml
index 2ea9a89d38..f2530604b9 100644
--- a/example-jetty-embedded/pom.xml
+++ b/example-jetty-embedded/pom.xml
@@ -2,7 +2,7 @@
<parent>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-project</artifactId>
- <version>7.6.8-SNAPSHOT</version>
+ <version>8.1.8-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>example-jetty-embedded</artifactId>
diff --git a/example-jetty-embedded/src/main/java/org/eclipse/jetty/embedded/LikeJettyXml.java b/example-jetty-embedded/src/main/java/org/eclipse/jetty/embedded/LikeJettyXml.java
index 2848784896..f0c4019c23 100644
--- a/example-jetty-embedded/src/main/java/org/eclipse/jetty/embedded/LikeJettyXml.java
+++ b/example-jetty-embedded/src/main/java/org/eclipse/jetty/embedded/LikeJettyXml.java
@@ -148,7 +148,7 @@ public class LikeJettyXml
webapp_provider.setDefaultsDescriptor(jetty_home + "/etc/webdefault.xml");
webapp_provider.setContextXmlDir(jetty_home + "/contexts");
deployer.addAppProvider(webapp_provider);
-
+
HashLoginService login = new HashLoginService();
login.setName("Test Realm");
login.setConfig(jetty_home + "/etc/realm.properties");
diff --git a/example-jetty-embedded/src/main/java/org/eclipse/jetty/embedded/ManyContexts.java b/example-jetty-embedded/src/main/java/org/eclipse/jetty/embedded/ManyContexts.java
index 50272a8ac8..6b85c73082 100644
--- a/example-jetty-embedded/src/main/java/org/eclipse/jetty/embedded/ManyContexts.java
+++ b/example-jetty-embedded/src/main/java/org/eclipse/jetty/embedded/ManyContexts.java
@@ -74,5 +74,4 @@ public class ManyContexts
System.err.println(server.dump());
server.join();
}
-
}
diff --git a/example-jetty-embedded/src/main/java/org/eclipse/jetty/embedded/OneWebApp.java b/example-jetty-embedded/src/main/java/org/eclipse/jetty/embedded/OneWebApp.java
index 7fd8f444a6..5f793eaea6 100644
--- a/example-jetty-embedded/src/main/java/org/eclipse/jetty/embedded/OneWebApp.java
+++ b/example-jetty-embedded/src/main/java/org/eclipse/jetty/embedded/OneWebApp.java
@@ -34,7 +34,11 @@ public class OneWebApp
server.setConnectors(new Connector[]
{ connector });
- String war = args.length > 0?args[0]: "../test-jetty-webapp/target/test-jetty-webapp-" + Server.getVersion();
+
+ //If you're running this from inside Eclipse, then Server.getVersion will not provide
+ //the correct number as there is no manifest. Use the command line instead to provide the path to the
+ //test webapp
+ String war = args.length > 0?args[0]: "../test-jetty-webapp/target/test-jetty-webapp-"+Server.getVersion();
String path = args.length > 1?args[1]:"/";
System.err.println(war + " " + path);
@@ -42,6 +46,15 @@ public class OneWebApp
WebAppContext webapp = new WebAppContext();
webapp.setContextPath(path);
webapp.setWar(war);
+
+ //If the webapp contains security constraints, you will need to configure a LoginService
+ if (war.contains("test-jetty-webapp"))
+ {
+ org.eclipse.jetty.security.HashLoginService loginService = new org.eclipse.jetty.security.HashLoginService();
+ loginService.setName("Test Realm");
+ loginService.setConfig("src/test/resources/realm.properties");
+ webapp.getSecurityHandler().setLoginService(loginService);
+ }
server.setHandler(webapp);
diff --git a/jetty-aggregate/jetty-all-server/pom.xml b/jetty-aggregate/jetty-all-server/pom.xml
index ab289a0a5a..1e2b5e5abd 100644
--- a/jetty-aggregate/jetty-all-server/pom.xml
+++ b/jetty-aggregate/jetty-all-server/pom.xml
@@ -1,9 +1,8 @@
-<?xml version="1.0"?>
<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.aggregate</groupId>
<artifactId>jetty-aggregate-project</artifactId>
- <version>7.6.8-SNAPSHOT</version>
+ <version>8.1.8-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>jetty-all-server</artifactId>
@@ -78,10 +77,11 @@
<instructions>
<Import-Package>
!org.eclipse.jetty*,
- com.sun.org.apache.commons.logging;version="[2.1,3)";split="glassfish";resolution:=optional,
javax.annotation;version="1.0.0";resolution:=optional,
- javax.servlet;version="2.5.0",
- javax.servlet.http;version="2.5.0",
+ javax.servlet;version="2.6.0",
+ javax.servlet.annotation;version="2.6.0",
+ javax.servlet.descriptor;version="2.6.0",
+ javax.servlet.http;version="2.6.0",
javax.mail;version="1.4.0";resolution:=optional,
javax.mail.event;version="1.4.0";resolution:=optional,
javax.mail.internet;version="1.4.0";resolution:=optional,
diff --git a/jetty-aggregate/jetty-all/pom.xml b/jetty-aggregate/jetty-all/pom.xml
index 9235332dfb..956c31c263 100644
--- a/jetty-aggregate/jetty-all/pom.xml
+++ b/jetty-aggregate/jetty-all/pom.xml
@@ -1,9 +1,8 @@
-<?xml version="1.0" encoding="UTF-8"?>
<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.aggregate</groupId>
<artifactId>jetty-aggregate-project</artifactId>
- <version>7.6.8-SNAPSHOT</version>
+ <version>8.1.8-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>jetty-all</artifactId>
diff --git a/jetty-aggregate/jetty-client/pom.xml b/jetty-aggregate/jetty-client/pom.xml
index 1be391592e..7a03132240 100644
--- a/jetty-aggregate/jetty-client/pom.xml
+++ b/jetty-aggregate/jetty-client/pom.xml
@@ -2,7 +2,7 @@
<parent>
<groupId>org.eclipse.jetty.aggregate</groupId>
<artifactId>jetty-aggregate-project</artifactId>
- <version>7.6.8-SNAPSHOT</version>
+ <version>8.1.8-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>jetty-client</artifactId>
diff --git a/jetty-aggregate/jetty-plus/pom.xml b/jetty-aggregate/jetty-plus/pom.xml
index 4d3af29430..39c5b6c9da 100644
--- a/jetty-aggregate/jetty-plus/pom.xml
+++ b/jetty-aggregate/jetty-plus/pom.xml
@@ -2,7 +2,7 @@
<parent>
<groupId>org.eclipse.jetty.aggregate</groupId>
<artifactId>jetty-aggregate-project</artifactId>
- <version>7.6.8-SNAPSHOT</version>
+ <version>8.1.8-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>jetty-plus</artifactId>
diff --git a/jetty-aggregate/jetty-server/pom.xml b/jetty-aggregate/jetty-server/pom.xml
index 4464aff513..56dac6528a 100644
--- a/jetty-aggregate/jetty-server/pom.xml
+++ b/jetty-aggregate/jetty-server/pom.xml
@@ -2,7 +2,7 @@
<parent>
<groupId>org.eclipse.jetty.aggregate</groupId>
<artifactId>jetty-aggregate-project</artifactId>
- <version>7.6.8-SNAPSHOT</version>
+ <version>8.1.8-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>jetty-server</artifactId>
diff --git a/jetty-aggregate/jetty-servlet/pom.xml b/jetty-aggregate/jetty-servlet/pom.xml
index 47f24feeed..ce290ac18c 100644
--- a/jetty-aggregate/jetty-servlet/pom.xml
+++ b/jetty-aggregate/jetty-servlet/pom.xml
@@ -2,7 +2,7 @@
<parent>
<groupId>org.eclipse.jetty.aggregate</groupId>
<artifactId>jetty-aggregate-project</artifactId>
- <version>7.6.8-SNAPSHOT</version>
+ <version>8.1.8-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>jetty-servlet</artifactId>
diff --git a/jetty-aggregate/jetty-webapp/pom.xml b/jetty-aggregate/jetty-webapp/pom.xml
index c8d6cb0fa6..3f1f0c9d2a 100644
--- a/jetty-aggregate/jetty-webapp/pom.xml
+++ b/jetty-aggregate/jetty-webapp/pom.xml
@@ -2,7 +2,7 @@
<parent>
<groupId>org.eclipse.jetty.aggregate</groupId>
<artifactId>jetty-aggregate-project</artifactId>
- <version>7.6.8-SNAPSHOT</version>
+ <version>8.1.8-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>jetty-webapp</artifactId>
diff --git a/jetty-aggregate/jetty-websocket/pom.xml b/jetty-aggregate/jetty-websocket/pom.xml
index 2cb09de092..8b64c1d502 100644
--- a/jetty-aggregate/jetty-websocket/pom.xml
+++ b/jetty-aggregate/jetty-websocket/pom.xml
@@ -2,7 +2,7 @@
<parent>
<groupId>org.eclipse.jetty.aggregate</groupId>
<artifactId>jetty-aggregate-project</artifactId>
- <version>7.6.8-SNAPSHOT</version>
+ <version>8.1.8-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>jetty-websocket</artifactId>
diff --git a/jetty-aggregate/pom.xml b/jetty-aggregate/pom.xml
index c52f3100a4..33c7f898da 100644
--- a/jetty-aggregate/pom.xml
+++ b/jetty-aggregate/pom.xml
@@ -4,7 +4,7 @@
<parent>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-project</artifactId>
- <version>7.6.8-SNAPSHOT</version>
+ <version>8.1.8-SNAPSHOT</version>
</parent>
<groupId>org.eclipse.jetty.aggregate</groupId>
<artifactId>jetty-aggregate-project</artifactId>
diff --git a/jetty-ajp/pom.xml b/jetty-ajp/pom.xml
index d7d35e4a08..de7f32bb3e 100644
--- a/jetty-ajp/pom.xml
+++ b/jetty-ajp/pom.xml
@@ -2,7 +2,7 @@
<parent>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-project</artifactId>
- <version>7.6.8-SNAPSHOT</version>
+ <version>8.1.8-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>jetty-ajp</artifactId>
@@ -21,6 +21,11 @@
<goals>
<goal>manifest</goal>
</goals>
+ <configuration>
+ <instructions>
+ <Import-Package>javax.servlet.*;version="2.6.0",*</Import-Package>
+ </instructions>
+ </configuration>
</execution>
</executions>
</plugin>
diff --git a/jetty-annotations/pom.xml b/jetty-annotations/pom.xml
index c21cf4a9e0..baa1b0b774 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>7.6.8-SNAPSHOT</version>
+ <version>8.1.8-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>jetty-annotations</artifactId>
@@ -14,6 +14,23 @@
<build>
<plugins>
<plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-assembly-plugin</artifactId>
+ <executions>
+ <execution>
+ <phase>package</phase>
+ <goals>
+ <goal>single</goal>
+ </goals>
+ <configuration>
+ <descriptorRefs>
+ <descriptorRef>config</descriptorRef>
+ </descriptorRefs>
+ </configuration>
+ </execution>
+ </executions>
+ </plugin>
+ <plugin>
<groupId>org.apache.felix</groupId>
<artifactId>maven-bundle-plugin</artifactId>
<extensions>true</extensions>
@@ -25,7 +42,7 @@
</goals>
<configuration>
<instructions>
- <Import-Package>javax.servlet.*;version="[2.5,3.0)",*</Import-Package>
+ <Import-Package>javax.servlet.*;version="2.6.0",*</Import-Package>
</instructions>
</configuration>
</execution>
diff --git a/jetty-annotations/src/main/config/etc/jetty-annotations.xml b/jetty-annotations/src/main/config/etc/jetty-annotations.xml
new file mode 100644
index 0000000000..7aa719d7ca
--- /dev/null
+++ b/jetty-annotations/src/main/config/etc/jetty-annotations.xml
@@ -0,0 +1,23 @@
+<?xml version="1.0"?>
+<!DOCTYPE Configure PUBLIC "-//Jetty//Configure//EN" "http://www.eclipse.org/jetty/configure.dtd">
+
+<Configure id="Server" class="org.eclipse.jetty.server.Server">
+
+ <!-- ================================================================= -->
+ <!-- Enable annotations - configure deployment steps for every web app -->
+ <!-- ================================================================= -->
+ <Call name="setAttribute">
+ <Arg>org.eclipse.jetty.webapp.configuration</Arg>
+ <Arg>
+ <Array type="java.lang.String">
+ <Item>org.eclipse.jetty.webapp.WebInfConfiguration</Item>
+ <Item>org.eclipse.jetty.webapp.WebXmlConfiguration</Item>
+ <Item>org.eclipse.jetty.webapp.MetaInfConfiguration</Item>
+ <Item>org.eclipse.jetty.webapp.FragmentConfiguration</Item>
+ <Item>org.eclipse.jetty.annotations.AnnotationConfiguration</Item>
+ <Item>org.eclipse.jetty.webapp.JettyWebXmlConfiguration</Item>
+ </Array>
+ </Arg>
+ </Call>
+
+</Configure>
diff --git a/jetty-annotations/src/main/java/org/eclipse/jetty/annotations/AbstractDiscoverableAnnotationHandler.java b/jetty-annotations/src/main/java/org/eclipse/jetty/annotations/AbstractDiscoverableAnnotationHandler.java
index 2367709243..95c5b4145d 100644
--- a/jetty-annotations/src/main/java/org/eclipse/jetty/annotations/AbstractDiscoverableAnnotationHandler.java
+++ b/jetty-annotations/src/main/java/org/eclipse/jetty/annotations/AbstractDiscoverableAnnotationHandler.java
@@ -22,7 +22,7 @@ import java.util.ArrayList;
import java.util.List;
import org.eclipse.jetty.annotations.AnnotationParser.DiscoverableAnnotationHandler;
-import org.eclipse.jetty.annotations.AnnotationParser.Value;
+import org.eclipse.jetty.util.resource.Resource;
import org.eclipse.jetty.webapp.DiscoveredAnnotation;
import org.eclipse.jetty.webapp.WebAppContext;
@@ -34,13 +34,32 @@ import org.eclipse.jetty.webapp.WebAppContext;
public abstract class AbstractDiscoverableAnnotationHandler implements DiscoverableAnnotationHandler
{
protected WebAppContext _context;
- protected List<DiscoveredAnnotation> _annotations = new ArrayList<DiscoveredAnnotation>();
+ protected List<DiscoveredAnnotation> _annotations;
+ protected Resource _resource;
public AbstractDiscoverableAnnotationHandler(WebAppContext context)
{
+ this(context, null);
+ }
+
+ public AbstractDiscoverableAnnotationHandler(WebAppContext context, List<DiscoveredAnnotation> list)
+ {
_context = context;
+ if (list == null)
+ _annotations = new ArrayList<DiscoveredAnnotation>();
+ else
+ _annotations = list;
}
+ public Resource getResource()
+ {
+ return _resource;
+ }
+
+ public void setResource(Resource resource)
+ {
+ _resource = resource;
+ }
public List<DiscoveredAnnotation> getAnnotationList ()
{
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 042fe21a12..e927dd0294 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
@@ -18,8 +18,33 @@
package org.eclipse.jetty.annotations;
+import java.net.URI;
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+import java.util.ServiceLoader;
+import java.util.Set;
+
+import javax.servlet.ServletContainerInitializer;
+import javax.servlet.ServletContext;
+import javax.servlet.ServletException;
+import javax.servlet.annotation.HandlesTypes;
+
+
+import org.eclipse.jetty.annotations.AnnotationParser.DiscoverableAnnotationHandler;
+import org.eclipse.jetty.plus.annotation.ContainerInitializer;
+import org.eclipse.jetty.util.MultiMap;
+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.Configuration;
import org.eclipse.jetty.webapp.AbstractConfiguration;
+import org.eclipse.jetty.webapp.Descriptor;
+import org.eclipse.jetty.webapp.DiscoveredAnnotation;
+import org.eclipse.jetty.webapp.FragmentDescriptor;
+import org.eclipse.jetty.webapp.MetaDataComplete;
import org.eclipse.jetty.webapp.WebAppContext;
+import org.eclipse.jetty.webapp.WebDescriptor;
/**
* Configuration for Annotations
@@ -28,15 +53,461 @@ import org.eclipse.jetty.webapp.WebAppContext;
*/
public class AnnotationConfiguration extends AbstractConfiguration
{
+ private static final Logger LOG = Log.getLogger(AnnotationConfiguration.class);
+ public static final String CLASS_INHERITANCE_MAP = "org.eclipse.jetty.classInheritanceMap";
+ public static final String CONTAINER_INITIALIZERS = "org.eclipse.jetty.containerInitializers";
+
+
+ protected List<DiscoverableAnnotationHandler> _discoverableAnnotationHandlers = new ArrayList<DiscoverableAnnotationHandler>();
+ protected ClassInheritanceHandler _classInheritanceHandler;
+ protected List<ContainerInitializerAnnotationHandler> _containerInitializerAnnotationHandlers = new ArrayList<ContainerInitializerAnnotationHandler>();
+
+
+ public void preConfigure(final WebAppContext context) throws Exception
+ {
+ }
+
+
+
+ /**
+ * @see org.eclipse.jetty.webapp.AbstractConfiguration#configure(org.eclipse.jetty.webapp.WebAppContext)
+ */
@Override
public void configure(WebAppContext context) throws Exception
- {
+ {
+ boolean metadataComplete = context.getMetaData().isMetaDataComplete();
context.addDecorator(new AnnotationDecorator(context));
+
+
+ //Even if metadata is complete, we still need to scan for ServletContainerInitializers - if there are any
+ AnnotationParser parser = null;
+ if (!metadataComplete)
+ {
+ //If metadata isn't complete, if this is a servlet 3 webapp or isConfigDiscovered is true, we need to search for annotations
+ if (context.getServletContext().getEffectiveMajorVersion() >= 3 || context.isConfigurationDiscovered())
+ {
+ _discoverableAnnotationHandlers.add(new WebServletAnnotationHandler(context));
+ _discoverableAnnotationHandlers.add(new WebFilterAnnotationHandler(context));
+ _discoverableAnnotationHandlers.add(new WebListenerAnnotationHandler(context));
+ }
+ }
+ else
+ if (LOG.isDebugEnabled()) LOG.debug("Metadata-complete==true, not processing discoverable servlet annotations for context "+context);
+
+
+
+ //Regardless of metadata, if there are any ServletContainerInitializers with @HandlesTypes, then we need to scan all the
+ //classes so we can call their onStartup() methods correctly
+ createServletContainerInitializerAnnotationHandlers(context, getNonExcludedInitializers(context));
+
+ if (!_discoverableAnnotationHandlers.isEmpty() || _classInheritanceHandler != null || !_containerInitializerAnnotationHandlers.isEmpty())
+ {
+ parser = createAnnotationParser();
+ if (LOG.isDebugEnabled()) LOG.debug("Scanning all classses for annotations: webxmlVersion="+context.getServletContext().getEffectiveMajorVersion()+" configurationDiscovered="+context.isConfigurationDiscovered());
+ parseContainerPath(context, parser);
+ //email from Rajiv Mordani jsrs 315 7 April 2010
+ // If there is a <others/> then the ordering should be
+ // WEB-INF/classes the order of the declared elements + others.
+ // In case there is no others then it is
+ // WEB-INF/classes + order of the elements.
+ parseWebInfClasses(context, parser);
+ parseWebInfLib (context, parser);
+
+ for (DiscoverableAnnotationHandler h:_discoverableAnnotationHandlers)
+ context.getMetaData().addDiscoveredAnnotations(((AbstractDiscoverableAnnotationHandler)h).getAnnotationList());
+ }
+ }
+
+
+
+ /**
+ * @see org.eclipse.jetty.webapp.AbstractConfiguration#postConfigure(org.eclipse.jetty.webapp.WebAppContext)
+ */
+ @Override
+ public void postConfigure(WebAppContext context) throws Exception
+ {
+ MultiMap map = (MultiMap)context.getAttribute(CLASS_INHERITANCE_MAP);
+ if (map != null)
+ map.clear();
+
+ context.removeAttribute(CLASS_INHERITANCE_MAP);
+
+ List<ContainerInitializer> initializers = (List<ContainerInitializer>)context.getAttribute(CONTAINER_INITIALIZERS);
+ if (initializers != null)
+ initializers.clear();
+ if (_discoverableAnnotationHandlers != null)
+ _discoverableAnnotationHandlers.clear();
+
+ _classInheritanceHandler = null;
+ if (_containerInitializerAnnotationHandlers != null)
+ _containerInitializerAnnotationHandlers.clear();
+
+ super.postConfigure(context);
}
+ /**
+ * @return a new AnnotationParser. This method can be overridden to use a different impleemntation of
+ * the AnnotationParser. Note that this is considered internal API.
+ */
+ protected AnnotationParser createAnnotationParser()
+ {
+ return new AnnotationParser();
+ }
+
+ /**
+ * @see org.eclipse.jetty.webapp.AbstractConfiguration#cloneConfigure(org.eclipse.jetty.webapp.WebAppContext, org.eclipse.jetty.webapp.WebAppContext)
+ */
@Override
public void cloneConfigure(WebAppContext template, WebAppContext context) throws Exception
{
context.addDecorator(new AnnotationDecorator(context));
}
+
+
+
+ /**
+ * @param context
+ * @param scis
+ * @throws Exception
+ */
+ public void createServletContainerInitializerAnnotationHandlers (WebAppContext context, List<ServletContainerInitializer> scis)
+ throws Exception
+ {
+
+ if (scis == null || scis.isEmpty())
+ return; // nothing to do
+
+
+ List<ContainerInitializer> initializers = new ArrayList<ContainerInitializer>();
+ context.setAttribute(CONTAINER_INITIALIZERS, initializers);
+
+ for (ServletContainerInitializer service : scis)
+ {
+ HandlesTypes annotation = service.getClass().getAnnotation(HandlesTypes.class);
+ ContainerInitializer initializer = new ContainerInitializer();
+ initializer.setTarget(service);
+ initializers.add(initializer);
+ if (annotation != null)
+ {
+ //There is a HandlesTypes annotation on the on the ServletContainerInitializer
+ Class[] classes = annotation.value();
+ if (classes != null)
+ {
+ initializer.setInterestedTypes(classes);
+
+ //If we haven't already done so, we need to register a handler that will
+ //process the whole class hierarchy to satisfy the ServletContainerInitializer
+ if (context.getAttribute(CLASS_INHERITANCE_MAP) == null)
+ {
+ MultiMap map = new MultiMap();
+ context.setAttribute(CLASS_INHERITANCE_MAP, map);
+ _classInheritanceHandler = new ClassInheritanceHandler(map);
+ }
+
+ for (Class c: classes)
+ {
+ //The value of one of the HandlesTypes classes is actually an Annotation itself so
+ //register a handler for it
+ if (c.isAnnotation())
+ {
+ if (LOG.isDebugEnabled()) LOG.debug("Registering annotation handler for "+c.getName());
+
+ _containerInitializerAnnotationHandlers.add(new ContainerInitializerAnnotationHandler(initializer, c));
+ }
+ }
+ }
+ else
+ if (LOG.isDebugEnabled()) LOG.debug("No classes in HandlesTypes on initializer "+service.getClass());
+ }
+ else
+ if (LOG.isDebugEnabled()) LOG.debug("No annotation on initializer "+service.getClass());
+ }
+
+
+ //add a listener which will call the servletcontainerinitializers when appropriate
+ ServletContainerInitializerListener listener = new ServletContainerInitializerListener();
+ listener.setWebAppContext(context);
+ context.addEventListener(listener);
+ }
+
+
+
+ /**
+ * Check to see if the ServletContainerIntializer loaded via the ServiceLoader came
+ * from a jar that is excluded by the fragment ordering. See ServletSpec 3.0 p.85.
+ * @param orderedJars
+ * @param service
+ * @return
+ */
+ public boolean isFromExcludedJar (WebAppContext context, ServletContainerInitializer service)
+ throws Exception
+ {
+ List<Resource> orderedJars = context.getMetaData().getOrderedWebInfJars();
+
+ //If no ordering, nothing is excluded
+ if (context.getMetaData().getOrdering() == null)
+ return false;
+
+ //there is an ordering, but there are no jars resulting from the ordering, everything excluded
+ if (orderedJars.isEmpty())
+ return true;
+
+ String loadingJarName = Thread.currentThread().getContextClassLoader().getResource(service.getClass().getName().replace('.','/')+".class").toString();
+
+ int i = loadingJarName.indexOf(".jar");
+ if (i < 0)
+ return false; //not from a jar therefore not from WEB-INF so not excludable
+
+ loadingJarName = loadingJarName.substring(0,i+4);
+ loadingJarName = (loadingJarName.startsWith("jar:")?loadingJarName.substring(4):loadingJarName);
+ URI loadingJarURI = Resource.newResource(loadingJarName).getURI();
+ boolean found = false;
+ Iterator<Resource> itor = orderedJars.iterator();
+ while (!found && itor.hasNext())
+ {
+ Resource r = itor.next();
+ found = r.getURI().equals(loadingJarURI);
+ }
+
+ return !found;
+ }
+
+
+
+ /**
+ * @param context
+ * @return
+ * @throws Exception
+ */
+ public List<ServletContainerInitializer> getNonExcludedInitializers (WebAppContext context)
+ throws Exception
+ {
+ List<ServletContainerInitializer> nonExcludedInitializers = new ArrayList<ServletContainerInitializer>();
+
+ //We use the ServiceLoader mechanism to find the ServletContainerInitializer classes to inspect
+ ServiceLoader<ServletContainerInitializer> loadedInitializers = ServiceLoader.load(ServletContainerInitializer.class, context.getClassLoader());
+
+ if (loadedInitializers != null)
+ {
+ for (ServletContainerInitializer service : loadedInitializers)
+ {
+ if (!isFromExcludedJar(context, service))
+ nonExcludedInitializers.add(service);
+ }
+ }
+ return nonExcludedInitializers;
+ }
+
+
+
+
+ /**
+ * Scan jars on container path.
+ *
+ * @param context
+ * @param parser
+ * @throws Exception
+ */
+ public void parseContainerPath (final WebAppContext context, final AnnotationParser parser)
+ throws Exception
+ {
+ //if no pattern for the container path is defined, then by default scan NOTHING
+ LOG.debug("Scanning container jars");
+
+ //always parse for discoverable annotations as well as class hierarchy and servletcontainerinitializer related annotations
+ parser.clearHandlers();
+ for (DiscoverableAnnotationHandler h:_discoverableAnnotationHandlers)
+ {
+ if (h instanceof AbstractDiscoverableAnnotationHandler)
+ ((AbstractDiscoverableAnnotationHandler)h).setResource(null); //
+ }
+ parser.registerHandlers(_discoverableAnnotationHandlers);
+ parser.registerHandler(_classInheritanceHandler);
+ parser.registerHandlers(_containerInitializerAnnotationHandlers);
+
+ //Convert from Resource to URI
+ ArrayList<URI> containerUris = new ArrayList<URI>();
+ for (Resource r : context.getMetaData().getOrderedContainerJars())
+ {
+ URI uri = r.getURI();
+ containerUris.add(uri);
+ }
+
+ parser.parse (containerUris.toArray(new URI[containerUris.size()]),
+ new ClassNameResolver ()
+ {
+ public boolean isExcluded (String name)
+ {
+ if (context.isSystemClass(name)) return false;
+ if (context.isServerClass(name)) return true;
+ return false;
+ }
+
+ public boolean shouldOverride (String name)
+ {
+ //looking at system classpath
+ if (context.isParentLoaderPriority())
+ return true;
+ return false;
+ }
+ });
+
+
+ }
+
+
+ /**
+ * Scan jars in WEB-INF/lib
+ *
+ * @param context
+ * @param parser
+ * @throws Exception
+ */
+ public void parseWebInfLib (final WebAppContext context, final AnnotationParser parser)
+ throws Exception
+ {
+ List<FragmentDescriptor> frags = context.getMetaData().getFragments();
+
+ //email from Rajiv Mordani jsrs 315 7 April 2010
+ //jars that do not have a web-fragment.xml are still considered fragments
+ //they have to participate in the ordering
+ ArrayList<URI> webInfUris = new ArrayList<URI>();
+
+ List<Resource> jars = context.getMetaData().getOrderedWebInfJars();
+
+ //No ordering just use the jars in any order
+ if (jars == null || jars.isEmpty())
+ jars = context.getMetaData().getWebInfJars();
+
+ for (Resource r : jars)
+ {
+ //for each jar, we decide which set of annotations we need to parse for
+ parser.clearHandlers();
+ URI uri = r.getURI();
+ FragmentDescriptor f = getFragmentFromJar(r, frags);
+
+ //if its from a fragment jar that is metadata complete, we should skip scanning for @webservlet etc
+ // but yet we still need to do the scanning for the classes on behalf of the servletcontainerinitializers
+ //if a jar has no web-fragment.xml we scan it (because it is not excluded by the ordering)
+ //or if it has a fragment we scan it if it is not metadata complete
+ if (f == null || !isMetaDataComplete(f) || _classInheritanceHandler != null || !_containerInitializerAnnotationHandlers.isEmpty())
+ {
+ //register the classinheritance handler if there is one
+ parser.registerHandler(_classInheritanceHandler);
+
+ //register the handlers for the @HandlesTypes values that are themselves annotations if there are any
+ parser.registerHandlers(_containerInitializerAnnotationHandlers);
+
+ //only register the discoverable annotation handlers if this fragment is not metadata complete, or has no fragment descriptor
+ if (f == null || !isMetaDataComplete(f))
+ {
+ for (DiscoverableAnnotationHandler h:_discoverableAnnotationHandlers)
+ {
+ if (h instanceof AbstractDiscoverableAnnotationHandler)
+ ((AbstractDiscoverableAnnotationHandler)h).setResource(r);
+ }
+ parser.registerHandlers(_discoverableAnnotationHandlers);
+ }
+
+ parser.parse(uri,
+ new ClassNameResolver()
+ {
+ public boolean isExcluded (String name)
+ {
+ if (context.isSystemClass(name)) return true;
+ if (context.isServerClass(name)) return false;
+ return false;
+ }
+
+ public boolean shouldOverride (String name)
+ {
+ //looking at webapp classpath, found already-parsed class of same name - did it come from system or duplicate in webapp?
+ if (context.isParentLoaderPriority())
+ return false;
+ return true;
+ }
+ });
+ }
+ }
+ }
+
+ /**
+ * Scan classes in WEB-INF/classes
+ *
+ * @param context
+ * @param parser
+ * @throws Exception
+ */
+ public void parseWebInfClasses (final WebAppContext context, final AnnotationParser parser)
+ throws Exception
+ {
+ LOG.debug("Scanning classes in WEB-INF/classes");
+ if (context.getWebInf() != null)
+ {
+ Resource classesDir = context.getWebInf().addPath("classes/");
+ if (classesDir.exists())
+ {
+ parser.clearHandlers();
+ for (DiscoverableAnnotationHandler h:_discoverableAnnotationHandlers)
+ {
+ if (h instanceof AbstractDiscoverableAnnotationHandler)
+ ((AbstractDiscoverableAnnotationHandler)h).setResource(null); //
+ }
+ parser.registerHandlers(_discoverableAnnotationHandlers);
+ parser.registerHandler(_classInheritanceHandler);
+ parser.registerHandlers(_containerInitializerAnnotationHandlers);
+
+ parser.parse(classesDir,
+ new ClassNameResolver()
+ {
+ public boolean isExcluded (String name)
+ {
+ if (context.isSystemClass(name)) return true;
+ if (context.isServerClass(name)) return false;
+ return false;
+ }
+
+ public boolean shouldOverride (String name)
+ {
+ //looking at webapp classpath, found already-parsed class of same name - did it come from system or duplicate in webapp?
+ if (context.isParentLoaderPriority())
+ return false;
+ return true;
+ }
+ });
+ }
+ }
+ }
+
+
+
+ /**
+ * Get the web-fragment.xml from a jar
+ *
+ * @param jar
+ * @param frags
+ * @return
+ * @throws Exception
+ */
+ public FragmentDescriptor getFragmentFromJar (Resource jar, List<FragmentDescriptor> frags)
+ throws Exception
+ {
+ //check if the jar has a web-fragment.xml
+ FragmentDescriptor d = null;
+ for (FragmentDescriptor frag: frags)
+ {
+ Resource fragResource = frag.getResource(); //eg jar:file:///a/b/c/foo.jar!/META-INF/web-fragment.xml
+ if (Resource.isContainedIn(fragResource,jar))
+ {
+ d = frag;
+ break;
+ }
+ }
+ return d;
+ }
+
+ public boolean isMetaDataComplete (WebDescriptor d)
+ {
+ return (d!=null && d.getMetaDataComplete() == MetaDataComplete.True);
+ }
}
diff --git a/jetty-annotations/src/main/java/org/eclipse/jetty/annotations/AnnotationDecorator.java b/jetty-annotations/src/main/java/org/eclipse/jetty/annotations/AnnotationDecorator.java
index 70df00e1cf..9a4d63eb28 100644
--- a/jetty-annotations/src/main/java/org/eclipse/jetty/annotations/AnnotationDecorator.java
+++ b/jetty-annotations/src/main/java/org/eclipse/jetty/annotations/AnnotationDecorator.java
@@ -50,6 +50,8 @@ public class AnnotationDecorator implements Decorator
_introspector.registerHandler(new PostConstructAnnotationHandler(context));
_introspector.registerHandler(new PreDestroyAnnotationHandler(context));
_introspector.registerHandler(new DeclareRolesAnnotationHandler(context));
+ _introspector.registerHandler(new MultiPartConfigAnnotationHandler(context));
+ _introspector.registerHandler(new ServletSecurityAnnotationHandler(context));
}
/* ------------------------------------------------------------ */
diff --git a/jetty-annotations/src/main/java/org/eclipse/jetty/annotations/AnnotationParser.java b/jetty-annotations/src/main/java/org/eclipse/jetty/annotations/AnnotationParser.java
index bd362f033c..537638778d 100644
--- a/jetty-annotations/src/main/java/org/eclipse/jetty/annotations/AnnotationParser.java
+++ b/jetty-annotations/src/main/java/org/eclipse/jetty/annotations/AnnotationParser.java
@@ -54,11 +54,8 @@ public class AnnotationParser
{
private static final Logger LOG = Log.getLogger(AnnotationParser.class);
- protected List<String> _parsedClassNames = new ArrayList<String>();
- protected Map<String, List<DiscoverableAnnotationHandler>> _annotationHandlers = new HashMap<String, List<DiscoverableAnnotationHandler>>();
- protected List<ClassHandler> _classHandlers = new ArrayList<ClassHandler>();
- protected List<MethodHandler> _methodHandlers = new ArrayList<MethodHandler>();
- protected List<FieldHandler> _fieldHandlers = new ArrayList<FieldHandler>();
+ protected List<String> _parsedClassNames = new ArrayList<String>();
+ protected List<Handler> _handlers = new ArrayList<Handler>();
public static String normalize (String name)
{
@@ -169,37 +166,122 @@ public class AnnotationParser
- public interface DiscoverableAnnotationHandler
+ /**
+ * Handler
+ *
+ * Signature for all handlers that respond to parsing class files.
+ */
+ public interface Handler
+ {
+
+ }
+
+
+
+ /**
+ * DiscoverableAnnotationHandler
+ *
+ * Processes an annotation when it is discovered on a class.
+ */
+ public interface DiscoverableAnnotationHandler extends Handler
{
+ /**
+ * Process an annotation that was discovered on a class
+ * @param className
+ * @param version
+ * @param access
+ * @param signature
+ * @param superName
+ * @param interfaces
+ * @param annotation
+ * @param values
+ */
public void handleClass (String className, int version, int access,
String signature, String superName, String[] interfaces,
String annotation, List<Value>values);
+ /**
+ * Process an annotation that was discovered on a method
+ * @param className
+ * @param methodName
+ * @param access
+ * @param desc
+ * @param signature
+ * @param exceptions
+ * @param annotation
+ * @param values
+ */
public void handleMethod (String className, String methodName, int access,
String desc, String signature,String[] exceptions,
String annotation, List<Value>values);
+
+ /**
+ * Process an annotation that was discovered on a field
+ * @param className
+ * @param fieldName
+ * @param access
+ * @param fieldType
+ * @param signature
+ * @param value
+ * @param annotation
+ * @param values
+ */
public void handleField (String className, String fieldName, int access,
String fieldType, String signature, Object value,
String annotation, List<Value>values);
+
+
+ /**
+ * Get the name of the annotation processed by this handler. Can be null
+ *
+ * @return
+ */
+ public String getAnnotationName();
}
- public interface ClassHandler
+
+ /**
+ * ClassHandler
+ *
+ * Responds to finding a Class
+ */
+ public interface ClassHandler extends Handler
{
public void handle (String className, int version, int access, String signature, String superName, String[] interfaces);
}
- public interface MethodHandler
+
+
+ /**
+ * MethodHandler
+ *
+ * Responds to finding a Method
+ */
+ public interface MethodHandler extends Handler
{
public void handle (String className, String methodName, int access, String desc, String signature,String[] exceptions);
}
- public interface FieldHandler
+
+ /**
+ * FieldHandler
+ *
+ * Responds to finding a Field
+ */
+ public interface FieldHandler extends Handler
{
public void handle (String className, String fieldName, int access, String fieldType, String signature, Object value);
}
+
+
+ /**
+ * MyAnnotationVisitor
+ *
+ * ASM Visitor for Annotations
+ */
public class MyAnnotationVisitor implements AnnotationVisitor
{
List<Value> _annotationValues;
@@ -308,10 +390,13 @@ public class AnnotationParser
for (String s : interfaces)
normalizedInterfaces[i++] = normalize(s);
}
-
- for (ClassHandler h : AnnotationParser.this._classHandlers)
+
+ for (Handler h : AnnotationParser.this._handlers)
{
- h.handle(_className, _version, _access, _signature, normalize(_superName), normalizedInterfaces);
+ if (h instanceof ClassHandler)
+ {
+ ((ClassHandler)h).handle(_className, _version, _access, _signature, normalize(_superName), normalizedInterfaces);
+ }
}
}
@@ -324,12 +409,13 @@ public class AnnotationParser
super.visitEnd();
//call all AnnotationHandlers with classname, annotation name + values
- List<DiscoverableAnnotationHandler> handlers = AnnotationParser.this._annotationHandlers.get(_annotationName);
- if (handlers != null)
+ for (Handler h : AnnotationParser.this._handlers)
{
- for (DiscoverableAnnotationHandler h:handlers)
+ if (h instanceof DiscoverableAnnotationHandler)
{
- h.handleClass(_className, _version, _access, _signature, _superName, _interfaces, _annotationName, _annotationValues);
+ DiscoverableAnnotationHandler dah = (DiscoverableAnnotationHandler)h;
+ if (_annotationName.equalsIgnoreCase(dah.getAnnotationName()))
+ dah.handleClass(_className, _version, _access, _signature, _superName, _interfaces, _annotationName, _annotationValues);
}
}
}
@@ -355,12 +441,13 @@ public class AnnotationParser
{
super.visitEnd();
//call all AnnotationHandlers with classname, method, annotation name + values
- List<DiscoverableAnnotationHandler> handlers = AnnotationParser.this._annotationHandlers.get(_annotationName);
- if (handlers != null)
+ for (Handler h : AnnotationParser.this._handlers)
{
- for (DiscoverableAnnotationHandler h:handlers)
+ if (h instanceof DiscoverableAnnotationHandler)
{
- h.handleMethod(_className, name, access, methodDesc, signature, exceptions, _annotationName, _annotationValues);
+ DiscoverableAnnotationHandler dah = (DiscoverableAnnotationHandler)h;
+ if (_annotationName.equalsIgnoreCase(dah.getAnnotationName()))
+ dah.handleMethod(_className, name, access, methodDesc, signature, exceptions, _annotationName, _annotationValues);
}
}
}
@@ -387,12 +474,13 @@ public class AnnotationParser
public void visitEnd()
{
super.visitEnd();
- List<DiscoverableAnnotationHandler> handlers = AnnotationParser.this._annotationHandlers.get(_annotationName);
- if (handlers != null)
+ for (Handler h : AnnotationParser.this._handlers)
{
- for (DiscoverableAnnotationHandler h:handlers)
+ if (h instanceof DiscoverableAnnotationHandler)
{
- h.handleField(_className, fieldName, access, fieldType, signature, value, _annotationName, _annotationValues);
+ DiscoverableAnnotationHandler dah = (DiscoverableAnnotationHandler)h;
+ if (_annotationName.equalsIgnoreCase(dah.getAnnotationName()))
+ dah.handleField(_className, fieldName, access, fieldType, signature, value, _annotationName, _annotationValues);
}
}
}
@@ -408,46 +496,130 @@ public class AnnotationParser
* Register a handler that will be called back when the named annotation is
* encountered on a class.
*
+ * @deprecated see registerHandler(Handler)
* @param annotationName
* @param handler
*/
public void registerAnnotationHandler (String annotationName, DiscoverableAnnotationHandler handler)
{
- List<DiscoverableAnnotationHandler> handlers = _annotationHandlers.get(annotationName);
- if (handlers == null)
- {
- handlers = new ArrayList<DiscoverableAnnotationHandler>();
- _annotationHandlers.put(annotationName, handlers);
- }
- handlers.add(handler);
+ _handlers.add(handler);
}
+
+ /**
+ * @deprecated
+ * @param annotationName
+ * @return
+ */
public List<DiscoverableAnnotationHandler> getAnnotationHandlers(String annotationName)
{
- List<DiscoverableAnnotationHandler> handlers = _annotationHandlers.get(annotationName);
- if (handlers == null)
- return Collections.emptyList();
- return new ArrayList<DiscoverableAnnotationHandler>(handlers);
+ List<DiscoverableAnnotationHandler> handlers = new ArrayList<DiscoverableAnnotationHandler>();
+ for (Handler h:_handlers)
+ {
+ if (h instanceof DiscoverableAnnotationHandler)
+ {
+ DiscoverableAnnotationHandler dah = (DiscoverableAnnotationHandler)h;
+ if (annotationName.equals(dah.getAnnotationName()))
+ handlers.add(dah);
+ }
+ }
+
+ return handlers;
}
+ /**
+ * @deprecated
+ * @return
+ */
public List<DiscoverableAnnotationHandler> getAnnotationHandlers()
{
- List<DiscoverableAnnotationHandler> allHandlers = new ArrayList<DiscoverableAnnotationHandler>();
- for (List<DiscoverableAnnotationHandler> list:_annotationHandlers.values())
- allHandlers.addAll(list);
- return allHandlers;
+ List<DiscoverableAnnotationHandler> allAnnotationHandlers = new ArrayList<DiscoverableAnnotationHandler>();
+ for (Handler h:_handlers)
+ {
+ if (h instanceof DiscoverableAnnotationHandler)
+ allAnnotationHandlers.add((DiscoverableAnnotationHandler)h);
+ }
+ return allAnnotationHandlers;
}
+ /**
+ * @deprecated see registerHandler(Handler)
+ * @param handler
+ */
public void registerClassHandler (ClassHandler handler)
{
- _classHandlers.add(handler);
+ _handlers.add(handler);
+ }
+
+
+
+ /**
+ * Add a particular handler
+ *
+ * @param h
+ */
+ public void registerHandler(Handler h)
+ {
+ if (h == null)
+ return;
+
+ _handlers.add(h);
}
+
+
+ /**
+ * Add a list of handlers
+ *
+ * @param handlers
+ */
+ public void registerHandlers(List<? extends Handler> handlers)
+ {
+ if (handlers == null)
+ return;
+ _handlers.addAll(handlers);
+ }
+
+
+ /**
+ * Remove a particular handler
+ *
+ * @param h
+ * @return
+ */
+ public boolean deregisterHandler(Handler h)
+ {
+ return _handlers.remove(h);
+ }
+
+
+ /**
+ * Remove all registered handlers
+ */
+ public void clearHandlers()
+ {
+ _handlers.clear();
+ }
+
+ /**
+ * True if the class has already been processed, false otherwise
+ * @param className
+ * @return
+ */
public boolean isParsed (String className)
{
return _parsedClassNames.contains(className);
}
+
+
+ /**
+ * Parse a given class
+ *
+ * @param className
+ * @param resolver
+ * @throws Exception
+ */
public void parse (String className, ClassNameResolver resolver)
throws Exception
{
@@ -469,6 +641,16 @@ public class AnnotationParser
}
}
+
+
+ /**
+ * Parse the given class, optionally walking its inheritance hierarchy
+ *
+ * @param clazz
+ * @param resolver
+ * @param visitSuperClasses
+ * @throws Exception
+ */
public void parse (Class clazz, ClassNameResolver resolver, boolean visitSuperClasses)
throws Exception
{
@@ -495,6 +677,15 @@ public class AnnotationParser
}
}
+
+
+ /**
+ * Parse the given classes
+ *
+ * @param classNames
+ * @param resolver
+ * @throws Exception
+ */
public void parse (String[] classNames, ClassNameResolver resolver)
throws Exception
{
@@ -504,6 +695,14 @@ public class AnnotationParser
parse(Arrays.asList(classNames), resolver);
}
+
+ /**
+ * Parse the given classes
+ *
+ * @param classNames
+ * @param resolver
+ * @throws Exception
+ */
public void parse (List<String> classNames, ClassNameResolver resolver)
throws Exception
{
@@ -522,6 +721,14 @@ public class AnnotationParser
}
}
+
+ /**
+ * Parse all classes in a directory
+ *
+ * @param dir
+ * @param resolver
+ * @throws Exception
+ */
public void parse (Resource dir, ClassNameResolver resolver)
throws Exception
{
@@ -557,8 +764,9 @@ public class AnnotationParser
/**
- * Find annotations on classes in the supplied classloader.
+ * Parse classes in the supplied classloader.
* Only class files in jar files will be scanned.
+ *
* @param loader
* @param visitParents
* @param nullInclusive
@@ -607,7 +815,8 @@ public class AnnotationParser
/**
- * Find annotations in classes in the supplied url of jar files.
+ * Parse classes in the supplied url of jar files.
+ *
* @param uris
* @param resolver
* @throws Exception
@@ -649,6 +858,12 @@ public class AnnotationParser
scanner.scan(null, uris, true);
}
+ /**
+ * Parse a particular resource
+ * @param uri
+ * @param resolver
+ * @throws Exception
+ */
public void parse (URI uri, final ClassNameResolver resolver)
throws Exception
{
@@ -658,10 +873,19 @@ public class AnnotationParser
parse(uris, resolver);
}
- private void scanClass (InputStream is)
+
+
+ /**
+ * Use ASM on a class
+ *
+ * @param is
+ * @throws IOException
+ */
+ protected void scanClass (InputStream is)
throws IOException
{
ClassReader reader = new ClassReader(is);
reader.accept(new MyClassVisitor(), ClassReader.SKIP_CODE|ClassReader.SKIP_DEBUG|ClassReader.SKIP_FRAMES);
}
}
+
diff --git a/jetty-annotations/src/main/java/org/eclipse/jetty/annotations/ClassInheritanceHandler.java b/jetty-annotations/src/main/java/org/eclipse/jetty/annotations/ClassInheritanceHandler.java
index 79f111a0ab..8242b08d74 100644
--- a/jetty-annotations/src/main/java/org/eclipse/jetty/annotations/ClassInheritanceHandler.java
+++ b/jetty-annotations/src/main/java/org/eclipse/jetty/annotations/ClassInheritanceHandler.java
@@ -35,10 +35,16 @@ public class ClassInheritanceHandler implements ClassHandler
private static final Logger LOG = Log.getLogger(ClassInheritanceHandler.class);
- MultiMap _inheritanceMap = new MultiMap();
+ MultiMap _inheritanceMap;
public ClassInheritanceHandler()
{
+ _inheritanceMap = new MultiMap();
+ }
+
+ public ClassInheritanceHandler(MultiMap map)
+ {
+ _inheritanceMap = map;
}
public void handle(String className, int version, int access, String signature, String superName, String[] interfaces)
diff --git a/jetty-annotations/src/main/java/org/eclipse/jetty/annotations/ContainerInitializerAnnotationHandler.java b/jetty-annotations/src/main/java/org/eclipse/jetty/annotations/ContainerInitializerAnnotationHandler.java
new file mode 100644
index 0000000000..e84188e640
--- /dev/null
+++ b/jetty-annotations/src/main/java/org/eclipse/jetty/annotations/ContainerInitializerAnnotationHandler.java
@@ -0,0 +1,83 @@
+//
+// ========================================================================
+// Copyright (c) 1995-2012 Mort Bay Consulting Pty. Ltd.
+// ------------------------------------------------------------------------
+// All rights reserved. This program and the accompanying materials
+// are made available under the terms of the Eclipse Public License v1.0
+// and Apache License v2.0 which accompanies this distribution.
+//
+// The Eclipse Public License is available at
+// http://www.eclipse.org/legal/epl-v10.html
+//
+// The Apache License v2.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.annotations;
+
+import java.util.List;
+
+import javax.servlet.annotation.HandlesTypes;
+
+import org.eclipse.jetty.annotations.AnnotationParser.DiscoverableAnnotationHandler;
+import org.eclipse.jetty.annotations.AnnotationParser.Value;
+import org.eclipse.jetty.plus.annotation.ContainerInitializer;
+import org.eclipse.jetty.util.Loader;
+import org.eclipse.jetty.util.log.Log;
+
+/**
+ * ContainerInitializerAnnotationHandler
+ *
+ * Discovers classes that contain the specified annotation, either at class or
+ * method level. The specified annotation is derived from an @HandlesTypes on
+ * a ServletContainerInitializer class.
+ */
+public class ContainerInitializerAnnotationHandler implements DiscoverableAnnotationHandler
+{
+ ContainerInitializer _initializer;
+ Class _annotation;
+
+ public ContainerInitializerAnnotationHandler (ContainerInitializer initializer, Class annotation)
+ {
+ _initializer = initializer;
+ _annotation = annotation;
+ }
+
+ /**
+ * Handle finding a class that is annotated with the annotation we were constructed with.
+ * @see org.eclipse.jetty.annotations.AnnotationParser.DiscoverableAnnotationHandler#handleClass(java.lang.String, int, int, java.lang.String, java.lang.String, java.lang.String[], java.lang.String, java.util.List)
+ */
+ public void handleClass(String className, int version, int access, String signature, String superName, String[] interfaces, String annotationName,
+ List<Value> values)
+ {
+ _initializer.addAnnotatedTypeName(className);
+ }
+
+ public void handleField(String className, String fieldName, int access, String fieldType, String signature, Object value, String annotation,
+ List<Value> values)
+ {
+ _initializer.addAnnotatedTypeName(className);
+ }
+
+ public void handleMethod(String className, String methodName, int access, String params, String signature, String[] exceptions, String annotation,
+ List<Value> values)
+ {
+ _initializer.addAnnotatedTypeName(className);
+ }
+
+ @Override
+ public String getAnnotationName()
+ {
+ return _annotation.getName();
+ }
+
+ public ContainerInitializer getContainerInitializer()
+ {
+ return _initializer;
+ }
+
+}
diff --git a/jetty-annotations/src/main/java/org/eclipse/jetty/annotations/MultiPartConfigAnnotationHandler.java b/jetty-annotations/src/main/java/org/eclipse/jetty/annotations/MultiPartConfigAnnotationHandler.java
new file mode 100644
index 0000000000..c3abf5138f
--- /dev/null
+++ b/jetty-annotations/src/main/java/org/eclipse/jetty/annotations/MultiPartConfigAnnotationHandler.java
@@ -0,0 +1,95 @@
+//
+// ========================================================================
+// Copyright (c) 1995-2012 Mort Bay Consulting Pty. Ltd.
+// ------------------------------------------------------------------------
+// All rights reserved. This program and the accompanying materials
+// are made available under the terms of the Eclipse Public License v1.0
+// and Apache License v2.0 which accompanies this distribution.
+//
+// The Eclipse Public License is available at
+// http://www.eclipse.org/legal/epl-v10.html
+//
+// The Apache License v2.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.annotations;
+
+import javax.servlet.MultipartConfigElement;
+import javax.servlet.Servlet;
+import javax.servlet.annotation.MultipartConfig;
+
+import org.eclipse.jetty.annotations.AnnotationIntrospector.AbstractIntrospectableAnnotationHandler;
+import org.eclipse.jetty.servlet.ServletHolder;
+import org.eclipse.jetty.webapp.Descriptor;
+import org.eclipse.jetty.webapp.MetaData;
+import org.eclipse.jetty.webapp.WebAppContext;
+
+/**
+ * MultiPartConfigAnnotationHandler
+ *
+ *
+ */
+public class MultiPartConfigAnnotationHandler extends AbstractIntrospectableAnnotationHandler
+{
+ protected WebAppContext _context;
+
+ public MultiPartConfigAnnotationHandler(WebAppContext context)
+ {
+ //TODO verify that MultipartConfig is not inheritable
+ super(false);
+ _context = context;
+ }
+ /**
+ * @see org.eclipse.jetty.annotations.AnnotationIntrospector.AbstractIntrospectableAnnotationHandler#doHandle(java.lang.Class)
+ */
+ public void doHandle(Class clazz)
+ {
+ if (!Servlet.class.isAssignableFrom(clazz))
+ return;
+
+ MultipartConfig multi = (MultipartConfig) clazz.getAnnotation(MultipartConfig.class);
+ if (multi == null)
+ return;
+
+ MetaData metaData = _context.getMetaData();
+
+ //TODO: The MultipartConfigElement needs to be set on the ServletHolder's Registration.
+ //How to identify the correct Servlet? If the Servlet has no WebServlet annotation on it, does it mean that this MultipartConfig
+ //annotation applies to all declared instances in web.xml/programmatically?
+ //Assuming TRUE for now.
+
+ ServletHolder holder = getServletHolderForClass(clazz);
+ if (holder != null)
+ {
+ Descriptor d = metaData.getOriginDescriptor(holder.getName()+".servlet.multipart-config");
+ //if a descriptor has already set the value for multipart config, do not
+ //let the annotation override it
+ if (d == null)
+ {
+ metaData.setOrigin(holder.getName()+".servlet.multipart-config");
+ holder.getRegistration().setMultipartConfig(new MultipartConfigElement(multi));
+ }
+ }
+ }
+
+ private ServletHolder getServletHolderForClass (Class clazz)
+ {
+ ServletHolder holder = null;
+ ServletHolder[] holders = _context.getServletHandler().getServlets();
+ if (holders != null)
+ {
+ for (ServletHolder h : holders)
+ {
+ if (h.getClassName() != null && h.getClassName().equals(clazz.getName()))
+ {
+ holder = h;
+ }
+ }
+ }
+ return holder;
+ }
+}
diff --git a/jetty-annotations/src/main/java/org/eclipse/jetty/annotations/RunAsAnnotationHandler.java b/jetty-annotations/src/main/java/org/eclipse/jetty/annotations/RunAsAnnotationHandler.java
index ada84129c0..898ac4c86a 100644
--- a/jetty-annotations/src/main/java/org/eclipse/jetty/annotations/RunAsAnnotationHandler.java
+++ b/jetty-annotations/src/main/java/org/eclipse/jetty/annotations/RunAsAnnotationHandler.java
@@ -107,7 +107,7 @@ public class RunAsAnnotationHandler extends AbstractIntrospectableAnnotationHand
{
for (ServletHolder h : holders)
{
- if (h.getClassName().equals(clazz.getName()))
+ if (h.getClassName() != null && h.getClassName().equals(clazz.getName()))
{
holder = h;
}
diff --git a/jetty-annotations/src/main/java/org/eclipse/jetty/annotations/ServletContainerInitializerListener.java b/jetty-annotations/src/main/java/org/eclipse/jetty/annotations/ServletContainerInitializerListener.java
new file mode 100644
index 0000000000..641859a521
--- /dev/null
+++ b/jetty-annotations/src/main/java/org/eclipse/jetty/annotations/ServletContainerInitializerListener.java
@@ -0,0 +1,142 @@
+//
+// ========================================================================
+// Copyright (c) 1995-2012 Mort Bay Consulting Pty. Ltd.
+// ------------------------------------------------------------------------
+// All rights reserved. This program and the accompanying materials
+// are made available under the terms of the Eclipse Public License v1.0
+// and Apache License v2.0 which accompanies this distribution.
+//
+// The Eclipse Public License is available at
+// http://www.eclipse.org/legal/epl-v10.html
+//
+// The Apache License v2.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.annotations;
+
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+
+import javax.servlet.ServletContextEvent;
+import javax.servlet.ServletContextListener;
+
+import org.eclipse.jetty.annotations.AnnotationConfiguration;
+import org.eclipse.jetty.plus.annotation.ContainerInitializer;
+import org.eclipse.jetty.util.MultiMap;
+import org.eclipse.jetty.util.log.Log;
+import org.eclipse.jetty.util.log.Logger;
+import org.eclipse.jetty.webapp.WebAppContext;
+
+/**
+ * ServletContainerInitializerListener
+ *
+ *
+ */
+public class ServletContainerInitializerListener implements ServletContextListener
+{
+ private static final Logger LOG = Log.getLogger(ServletContainerInitializerListener.class);
+ protected WebAppContext _context = null;
+
+
+ public void setWebAppContext (WebAppContext context)
+ {
+ _context = context;
+ }
+
+ /**
+ * @see javax.servlet.ServletContextListener#contextInitialized(javax.servlet.ServletContextEvent)
+ */
+ public void contextInitialized(ServletContextEvent sce)
+ {
+ List<ContainerInitializer> initializers = (List<ContainerInitializer>)_context.getAttribute(AnnotationConfiguration.CONTAINER_INITIALIZERS);
+ MultiMap classMap = (MultiMap)_context.getAttribute(AnnotationConfiguration.CLASS_INHERITANCE_MAP);
+
+ if (initializers != null)
+ {
+ for (ContainerInitializer i : initializers)
+ {
+ //We have already found the classes that directly have an annotation that was in the HandlesTypes
+ //annotation of the ServletContainerInitializer. For each of those classes, walk the inheritance
+ //hierarchy to find classes that extend or implement them.
+ if (i.getAnnotatedTypeNames() != null)
+ {
+ Set<String> annotatedClassNames = new HashSet<String>(i.getAnnotatedTypeNames());
+ for (String name : annotatedClassNames)
+ {
+ //add the class with the annotation
+ i.addApplicableTypeName(name);
+ //add the classes that inherit the annotation
+ if (classMap != null)
+ {
+ List<String> implementsOrExtends = (List<String>)classMap.getValues(name);
+ if (implementsOrExtends != null && !implementsOrExtends.isEmpty())
+ addInheritedTypes(classMap, i, implementsOrExtends);
+ }
+ }
+ }
+
+
+ //Now we need to look at the HandlesTypes classes that were not annotations. We need to
+ //find all classes that extend or implement them.
+ if (i.getInterestedTypes() != null)
+ {
+ for (Class c : i.getInterestedTypes())
+ {
+ if (!c.isAnnotation())
+ {
+ //add the classes that implement or extend the class.
+ //TODO but not including the class itself?
+ if (classMap != null)
+ {
+ List<String> implementsOrExtends = (List<String>)classMap.getValues(c.getName());
+ if (implementsOrExtends != null && !implementsOrExtends.isEmpty())
+ addInheritedTypes(classMap, i, implementsOrExtends);
+ }
+ }
+ }
+ }
+
+ //instantiate ServletContainerInitializers, call doStart
+ try
+ {
+ i.callStartup(_context);
+ }
+ catch (Exception e)
+ {
+ LOG.warn(e);
+ throw new RuntimeException(e);
+ }
+ }
+ }
+ }
+
+
+ void addInheritedTypes (MultiMap classMap, ContainerInitializer initializer, List<String> applicableTypes)
+ {
+ for (String s : applicableTypes)
+ {
+ //add the name of the class that extends or implements
+ initializer.addApplicableTypeName(s);
+
+ //walk the hierarchy and find all types that extend or implement it
+ List<String> implementsOrExtends = (List<String>)classMap.getValues(s);
+ if (implementsOrExtends != null && !implementsOrExtends.isEmpty())
+ addInheritedTypes (classMap, initializer, implementsOrExtends);
+ }
+ }
+
+
+ /**
+ * @see javax.servlet.ServletContextListener#contextDestroyed(javax.servlet.ServletContextEvent)
+ */
+ public void contextDestroyed(ServletContextEvent sce)
+ {
+
+ }
+
+}
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
new file mode 100644
index 0000000000..bfbef9bf9c
--- /dev/null
+++ b/jetty-annotations/src/main/java/org/eclipse/jetty/annotations/ServletSecurityAnnotationHandler.java
@@ -0,0 +1,196 @@
+//
+// ========================================================================
+// Copyright (c) 1995-2012 Mort Bay Consulting Pty. Ltd.
+// ------------------------------------------------------------------------
+// All rights reserved. This program and the accompanying materials
+// are made available under the terms of the Eclipse Public License v1.0
+// and Apache License v2.0 which accompanies this distribution.
+//
+// The Eclipse Public License is available at
+// http://www.eclipse.org/legal/epl-v10.html
+//
+// The Apache License v2.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.annotations;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import javax.servlet.ServletSecurityElement;
+import javax.servlet.annotation.HttpConstraint;
+import javax.servlet.annotation.HttpMethodConstraint;
+import javax.servlet.annotation.ServletSecurity;
+import javax.servlet.annotation.ServletSecurity.EmptyRoleSemantic;
+import javax.servlet.annotation.ServletSecurity.TransportGuarantee;
+
+import org.eclipse.jetty.annotations.AnnotationIntrospector.AbstractIntrospectableAnnotationHandler;
+import org.eclipse.jetty.security.ConstraintAware;
+import org.eclipse.jetty.security.ConstraintMapping;
+import org.eclipse.jetty.security.ConstraintSecurityHandler;
+import org.eclipse.jetty.servlet.ServletHolder;
+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;
+
+/**
+ * ServletSecurityAnnotationHandler
+ *
+ * Inspect a class to see if it has an @ServletSecurity annotation on it,
+ * setting up the <security-constraint>s.
+ *
+ * A servlet can be defined in:
+ * <ul>
+ * <li>web.xml
+ * <li>web-fragment.xml
+ * <li>@WebServlet annotation discovered
+ * <li>ServletContext.createServlet
+ * </ul>
+ *
+ * The ServletSecurity annotation for a servlet should only be processed
+ * iff metadata-complete == false.
+ */
+public class ServletSecurityAnnotationHandler extends AbstractIntrospectableAnnotationHandler
+{
+ private static final Logger LOG = Log.getLogger(ServletSecurityAnnotationHandler.class);
+
+ private WebAppContext _context;
+
+ public ServletSecurityAnnotationHandler(WebAppContext wac)
+ {
+ super(false);
+ _context = wac;
+ }
+
+ /**
+ * @see org.eclipse.jetty.annotations.AnnotationIntrospector.IntrospectableAnnotationHandler#handle(java.lang.Class)
+ */
+ public void doHandle(Class clazz)
+ {
+ if (!(_context.getSecurityHandler() instanceof ConstraintAware))
+ {
+ LOG.warn("SecurityHandler not ConstraintAware, skipping security annotation processing");
+ return;
+ }
+
+ ServletSecurity servletSecurity = (ServletSecurity)clazz.getAnnotation(ServletSecurity.class);
+ if (servletSecurity == null)
+ return;
+
+ //If there are already constraints defined (ie from web.xml) that match any
+ //of the url patterns defined for this servlet, then skip the security annotation.
+
+ List<ServletMapping> servletMappings = getServletMappings(clazz.getCanonicalName());
+ List<ConstraintMapping> constraintMappings = ((ConstraintAware)_context.getSecurityHandler()).getConstraintMappings();
+
+ if (constraintsExist(servletMappings, constraintMappings))
+ {
+ LOG.warn("Constraints already defined for "+clazz.getName()+", skipping ServletSecurity annotation");
+ return;
+ }
+
+ //Make a fresh list
+ constraintMappings = new ArrayList<ConstraintMapping>();
+
+ ServletSecurityElement securityElement = new ServletSecurityElement(servletSecurity);
+ for (ServletMapping sm : servletMappings)
+ {
+ for (String url : sm.getPathSpecs())
+ {
+ _context.getMetaData().setOrigin("constraint.url."+url, Origin.Annotation);
+ constraintMappings.addAll(ConstraintSecurityHandler.createConstraintsWithMappingsForPath(clazz.getName(), url, securityElement));
+ }
+ }
+
+ //set up the security constraints produced by the annotation
+ ConstraintAware securityHandler = (ConstraintAware)_context.getSecurityHandler();
+
+ for (ConstraintMapping m:constraintMappings)
+ securityHandler.addConstraintMapping(m);
+ }
+
+
+
+ /**
+ * Make a jetty Constraint object, which represents the <auth-constraint> and
+ * <user-data-constraint> elements, based on the security annotation.
+ * @param servlet
+ * @param rolesAllowed
+ * @param permitOrDeny
+ * @param transport
+ * @return
+ */
+ protected Constraint makeConstraint (Class servlet, String[] rolesAllowed, EmptyRoleSemantic permitOrDeny, TransportGuarantee transport)
+ {
+ return ConstraintSecurityHandler.createConstraint(servlet.getName(), rolesAllowed, permitOrDeny, transport);
+ }
+
+
+
+ /**
+ * Get the ServletMappings for the servlet's class.
+ * @param className
+ * @return
+ */
+ protected List<ServletMapping> getServletMappings(String className)
+ {
+ List<ServletMapping> results = new ArrayList<ServletMapping>();
+ ServletMapping[] mappings = _context.getServletHandler().getServletMappings();
+ for (ServletMapping mapping : mappings)
+ {
+ //Check the name of the servlet that this mapping applies to, and then find the ServletHolder for it to find it's class
+ ServletHolder holder = _context.getServletHandler().getServlet(mapping.getServletName());
+ if (holder.getClassName() != null && holder.getClassName().equals(className))
+ results.add(mapping);
+ }
+ return results;
+ }
+
+
+
+ /**
+ * Check if there are already <security-constraint> elements defined that match the url-patterns for
+ * the servlet.
+ * @param servletMappings
+ * @return
+ */
+ protected boolean constraintsExist (List<ServletMapping> servletMappings, List<ConstraintMapping> constraintMappings)
+ {
+ boolean exists = false;
+
+ //Check to see if the path spec on each constraint mapping matches a pathSpec in the servlet mappings.
+ //If it does, then we should ignore the security annotations.
+ for (ServletMapping mapping : servletMappings)
+ {
+ //Get its url mappings
+ String[] pathSpecs = mapping.getPathSpecs();
+ if (pathSpecs == null)
+ continue;
+
+ //Check through the constraints to see if there are any whose pathSpecs (url mappings)
+ //match the servlet. If so, then we already have constraints defined for this servlet,
+ //and we will not be processing the annotation (ie web.xml or programmatic override).
+ for (int i=0; constraintMappings != null && i < constraintMappings.size() && !exists; i++)
+ {
+ for (int j=0; j < pathSpecs.length; j++)
+ {
+ //TODO decide if we need to check the origin
+ if (pathSpecs[j].equals(constraintMappings.get(i).getPathSpec()))
+ {
+ exists = true;
+ break;
+ }
+ }
+ }
+ }
+ return exists;
+ }
+
+}
diff --git a/jetty-annotations/src/main/java/org/eclipse/jetty/annotations/Util.java b/jetty-annotations/src/main/java/org/eclipse/jetty/annotations/Util.java
index 40ae236c7b..e89ed6d15b 100644
--- a/jetty-annotations/src/main/java/org/eclipse/jetty/annotations/Util.java
+++ b/jetty-annotations/src/main/java/org/eclipse/jetty/annotations/Util.java
@@ -61,7 +61,8 @@ public class Util
javax.servlet.ServletRequestListener.class.isAssignableFrom(c) ||
javax.servlet.ServletRequestAttributeListener.class.isAssignableFrom(c) ||
javax.servlet.http.HttpSessionListener.class.isAssignableFrom(c) ||
- javax.servlet.http.HttpSessionAttributeListener.class.isAssignableFrom(c))
+ javax.servlet.http.HttpSessionAttributeListener.class.isAssignableFrom(c) ||
+ javax.servlet.AsyncListener.class.isAssignableFrom(c))
isServlet=true;
diff --git a/jetty-annotations/src/main/java/org/eclipse/jetty/annotations/WebFilterAnnotation.java b/jetty-annotations/src/main/java/org/eclipse/jetty/annotations/WebFilterAnnotation.java
new file mode 100644
index 0000000000..f3824a9025
--- /dev/null
+++ b/jetty-annotations/src/main/java/org/eclipse/jetty/annotations/WebFilterAnnotation.java
@@ -0,0 +1,223 @@
+//
+// ========================================================================
+// Copyright (c) 1995-2012 Mort Bay Consulting Pty. Ltd.
+// ------------------------------------------------------------------------
+// All rights reserved. This program and the accompanying materials
+// are made available under the terms of the Eclipse Public License v1.0
+// and Apache License v2.0 which accompanies this distribution.
+//
+// The Eclipse Public License is available at
+// http://www.eclipse.org/legal/epl-v10.html
+//
+// The Apache License v2.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.annotations;
+
+import java.util.ArrayList;
+import java.util.EnumSet;
+
+import javax.servlet.DispatcherType;
+import javax.servlet.Filter;
+import javax.servlet.annotation.WebFilter;
+import javax.servlet.annotation.WebInitParam;
+
+import org.eclipse.jetty.servlet.FilterHolder;
+import org.eclipse.jetty.servlet.FilterMapping;
+import org.eclipse.jetty.servlet.Holder;
+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.DiscoveredAnnotation;
+import org.eclipse.jetty.webapp.MetaData;
+import org.eclipse.jetty.webapp.WebAppContext;
+import org.eclipse.jetty.webapp.Origin;
+
+/**
+ * WebFilterAnnotation
+ *
+ *
+ */
+public class WebFilterAnnotation extends DiscoveredAnnotation
+{
+ private static final Logger LOG = Log.getLogger(WebFilterAnnotation.class);
+
+ /**
+ * @param context
+ * @param className
+ */
+ public WebFilterAnnotation(WebAppContext context, String className)
+ {
+ super(context, className);
+ }
+
+ public WebFilterAnnotation(WebAppContext context, String className, Resource resource)
+ {
+ super(context, className, resource);
+ }
+
+ /**
+ * @see org.eclipse.jetty.annotations.ClassAnnotation#apply()
+ */
+ public void apply()
+ {
+ // TODO verify against rules for annotation v descriptor
+
+ Class clazz = getTargetClass();
+ if (clazz == null)
+ {
+ LOG.warn(_className+" cannot be loaded");
+ return;
+ }
+
+
+ //Servlet Spec 8.1.2
+ if (!Filter.class.isAssignableFrom(clazz))
+ {
+ LOG.warn(clazz.getName()+" is not assignable from javax.servlet.Filter");
+ return;
+ }
+ MetaData metaData = _context.getMetaData();
+
+ WebFilter filterAnnotation = (WebFilter)clazz.getAnnotation(WebFilter.class);
+
+ if (filterAnnotation.value().length > 0 && filterAnnotation.urlPatterns().length > 0)
+ {
+ LOG.warn(clazz.getName()+" defines both @WebFilter.value and @WebFilter.urlPatterns");
+ return;
+ }
+
+ String name = (filterAnnotation.filterName().equals("")?clazz.getName():filterAnnotation.filterName());
+ String[] urlPatterns = filterAnnotation.value();
+ if (urlPatterns.length == 0)
+ urlPatterns = filterAnnotation.urlPatterns();
+
+ FilterHolder holder = _context.getServletHandler().getFilter(name);
+ if (holder == null)
+ {
+ //Filter with this name does not already exist, so add it
+ holder = _context.getServletHandler().newFilterHolder(Holder.Source.ANNOTATION);
+ holder.setName(name);
+
+ holder.setHeldClass(clazz);
+ metaData.setOrigin(name+".filter.filter-class");
+
+ holder.setDisplayName(filterAnnotation.displayName());
+ metaData.setOrigin(name+".filter.display-name");
+
+ for (WebInitParam ip: filterAnnotation.initParams())
+ {
+ holder.setInitParameter(ip.name(), ip.value());
+ metaData.setOrigin(name+".filter.init-param."+ip.name());
+ }
+
+ FilterMapping mapping = new FilterMapping();
+ mapping.setFilterName(holder.getName());
+
+ if (urlPatterns.length > 0)
+ {
+ ArrayList paths = new ArrayList();
+ for (String s:urlPatterns)
+ {
+ paths.add(Util.normalizePattern(s));
+ }
+ mapping.setPathSpecs((String[])paths.toArray(new String[paths.size()]));
+ }
+
+ if (filterAnnotation.servletNames().length > 0)
+ {
+ ArrayList<String> names = new ArrayList<String>();
+ for (String s : filterAnnotation.servletNames())
+ {
+ names.add(s);
+ }
+ mapping.setServletNames((String[])names.toArray(new String[names.size()]));
+ }
+
+ EnumSet<DispatcherType> dispatcherSet = EnumSet.noneOf(DispatcherType.class);
+ for (DispatcherType d : filterAnnotation.dispatcherTypes())
+ {
+ dispatcherSet.add(d);
+ }
+ mapping.setDispatcherTypes(dispatcherSet);
+ metaData.setOrigin(name+".filter.mappings");
+
+ holder.setAsyncSupported(filterAnnotation.asyncSupported());
+ metaData.setOrigin(name+".filter.async-supported");
+
+ _context.getServletHandler().addFilter(holder);
+ _context.getServletHandler().addFilterMapping(mapping);
+ }
+ else
+ {
+ //A Filter definition for the same name already exists from web.xml
+ //ServletSpec 3.0 p81 if the Filter is already defined and has mappings,
+ //they override the annotation. If it already has DispatcherType set, that
+ //also overrides the annotation. Init-params are additive, but web.xml overrides
+ //init-params of the same name.
+ for (WebInitParam ip: filterAnnotation.initParams())
+ {
+ //if (holder.getInitParameter(ip.name()) == null)
+ if (metaData.getOrigin(name+".filter.init-param."+ip.name())==Origin.NotSet)
+ {
+ holder.setInitParameter(ip.name(), ip.value());
+ metaData.setOrigin(name+".filter.init-param."+ip.name());
+ }
+ }
+
+ FilterMapping[] mappings = _context.getServletHandler().getFilterMappings();
+ boolean mappingExists = false;
+ if (mappings != null)
+ {
+ for (FilterMapping m:mappings)
+ {
+ if (m.getFilterName().equals(name))
+ {
+ mappingExists = true;
+ break;
+ }
+ }
+ }
+ //if a descriptor didn't specify at least one mapping, use the mappings from the annotation and the DispatcherTypes
+ //from the annotation
+ if (!mappingExists)
+ {
+ FilterMapping mapping = new FilterMapping();
+ mapping.setFilterName(holder.getName());
+
+ if (urlPatterns.length > 0)
+ {
+ ArrayList paths = new ArrayList();
+ for (String s:urlPatterns)
+ {
+ paths.add(Util.normalizePattern(s));
+ }
+ mapping.setPathSpecs((String[])paths.toArray(new String[paths.size()]));
+ }
+ if (filterAnnotation.servletNames().length > 0)
+ {
+ ArrayList<String> names = new ArrayList<String>();
+ for (String s : filterAnnotation.servletNames())
+ {
+ names.add(s);
+ }
+ mapping.setServletNames((String[])names.toArray(new String[names.size()]));
+ }
+
+ EnumSet<DispatcherType> dispatcherSet = EnumSet.noneOf(DispatcherType.class);
+ for (DispatcherType d : filterAnnotation.dispatcherTypes())
+ {
+ dispatcherSet.add(d);
+ }
+ mapping.setDispatcherTypes(dispatcherSet);
+ _context.getServletHandler().addFilterMapping(mapping);
+ metaData.setOrigin(name+".filter.mappings");
+ }
+ }
+ }
+
+}
diff --git a/jetty-annotations/src/main/java/org/eclipse/jetty/annotations/WebFilterAnnotationHandler.java b/jetty-annotations/src/main/java/org/eclipse/jetty/annotations/WebFilterAnnotationHandler.java
new file mode 100644
index 0000000000..1be7b2c9ec
--- /dev/null
+++ b/jetty-annotations/src/main/java/org/eclipse/jetty/annotations/WebFilterAnnotationHandler.java
@@ -0,0 +1,74 @@
+//
+// ========================================================================
+// Copyright (c) 1995-2012 Mort Bay Consulting Pty. Ltd.
+// ------------------------------------------------------------------------
+// All rights reserved. This program and the accompanying materials
+// are made available under the terms of the Eclipse Public License v1.0
+// and Apache License v2.0 which accompanies this distribution.
+//
+// The Eclipse Public License is available at
+// http://www.eclipse.org/legal/epl-v10.html
+//
+// The Apache License v2.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.annotations;
+
+import java.util.List;
+
+import org.eclipse.jetty.annotations.AnnotationParser.DiscoverableAnnotationHandler;
+import org.eclipse.jetty.annotations.AnnotationParser.Value;
+import org.eclipse.jetty.util.log.Log;
+import org.eclipse.jetty.util.log.Logger;
+import org.eclipse.jetty.webapp.DiscoveredAnnotation;
+import org.eclipse.jetty.webapp.WebAppContext;
+
+/**
+ * WebFilterAnnotationHandler
+ *
+ *
+ */
+public class WebFilterAnnotationHandler extends AbstractDiscoverableAnnotationHandler
+{
+ private static final Logger LOG = Log.getLogger(WebFilterAnnotationHandler.class);
+
+ public WebFilterAnnotationHandler (WebAppContext context)
+ {
+ super(context);
+ }
+
+ public WebFilterAnnotationHandler (WebAppContext context, List<DiscoveredAnnotation> list)
+ {
+ super(context, list);
+ }
+
+ public void handleClass(String className, int version, int access, String signature, String superName, String[] interfaces, String annotation,
+ List<Value> values)
+ {
+ WebFilterAnnotation wfAnnotation = new WebFilterAnnotation(_context, className, _resource);
+ addAnnotation(wfAnnotation);
+ }
+
+ public void handleField(String className, String fieldName, int access, String fieldType, String signature, Object value, String annotation,
+ List<Value> values)
+ {
+ LOG.warn ("@WebFilter not applicable for fields: "+className+"."+fieldName);
+ }
+
+ public void handleMethod(String className, String methodName, int access, String params, String signature, String[] exceptions, String annotation,
+ List<Value> values)
+ {
+ LOG.warn ("@WebFilter not applicable for methods: "+className+"."+methodName+" "+signature);
+ }
+
+ @Override
+ public String getAnnotationName()
+ {
+ return "javax.servlet.annotation.WebFilter";
+ }
+
+}
diff --git a/jetty-annotations/src/main/java/org/eclipse/jetty/annotations/WebListenerAnnotation.java b/jetty-annotations/src/main/java/org/eclipse/jetty/annotations/WebListenerAnnotation.java
new file mode 100644
index 0000000000..cb48ba4629
--- /dev/null
+++ b/jetty-annotations/src/main/java/org/eclipse/jetty/annotations/WebListenerAnnotation.java
@@ -0,0 +1,96 @@
+//
+// ========================================================================
+// Copyright (c) 1995-2012 Mort Bay Consulting Pty. Ltd.
+// ------------------------------------------------------------------------
+// All rights reserved. This program and the accompanying materials
+// are made available under the terms of the Eclipse Public License v1.0
+// and Apache License v2.0 which accompanies this distribution.
+//
+// The Eclipse Public License is available at
+// http://www.eclipse.org/legal/epl-v10.html
+//
+// The Apache License v2.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.annotations;
+
+import javax.servlet.ServletContextAttributeListener;
+import javax.servlet.ServletContextListener;
+import javax.servlet.ServletRequestAttributeListener;
+import javax.servlet.ServletRequestListener;
+import javax.servlet.http.HttpSessionAttributeListener;
+import javax.servlet.http.HttpSessionListener;
+
+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.DiscoveredAnnotation;
+import org.eclipse.jetty.webapp.MetaData;
+import org.eclipse.jetty.webapp.WebAppContext;
+import org.eclipse.jetty.webapp.Origin;
+
+/**
+ * WebListenerAnnotation
+ *
+ *
+ */
+public class WebListenerAnnotation extends DiscoveredAnnotation
+{
+ private static final Logger LOG = Log.getLogger(WebListenerAnnotation.class);
+
+ /**
+ * @param context
+ * @param className
+ */
+ public WebListenerAnnotation(WebAppContext context, String className)
+ {
+ super(context, className);
+ }
+
+ public WebListenerAnnotation(WebAppContext context, String className, Resource resource)
+ {
+ super(context, className, resource);
+ }
+
+ /**
+ * @see org.eclipse.jetty.annotations.ClassAnnotation#apply()
+ */
+ public void apply()
+ {
+ // TODO check algorithm against ordering rules for descriptors v annotations
+
+ Class clazz = getTargetClass();
+
+ if (clazz == null)
+ {
+ LOG.warn(_className+" cannot be loaded");
+ return;
+ }
+
+ try
+ {
+ if (ServletContextListener.class.isAssignableFrom(clazz) ||
+ ServletContextAttributeListener.class.isAssignableFrom(clazz) ||
+ ServletRequestListener.class.isAssignableFrom(clazz) ||
+ ServletRequestAttributeListener.class.isAssignableFrom(clazz) ||
+ HttpSessionListener.class.isAssignableFrom(clazz) ||
+ HttpSessionAttributeListener.class.isAssignableFrom(clazz))
+ {
+ java.util.EventListener listener = (java.util.EventListener)clazz.newInstance();
+ MetaData metaData = _context.getMetaData();
+ if (metaData.getOrigin(clazz.getName()+".listener") == Origin.NotSet)
+ _context.addEventListener(listener);
+ }
+ else
+ LOG.warn(clazz.getName()+" does not implement one of the servlet listener interfaces");
+ }
+ catch (Exception e)
+ {
+ LOG.warn(e);
+ }
+ }
+}
diff --git a/jetty-annotations/src/main/java/org/eclipse/jetty/annotations/WebListenerAnnotationHandler.java b/jetty-annotations/src/main/java/org/eclipse/jetty/annotations/WebListenerAnnotationHandler.java
new file mode 100644
index 0000000000..2dd1c16bd1
--- /dev/null
+++ b/jetty-annotations/src/main/java/org/eclipse/jetty/annotations/WebListenerAnnotationHandler.java
@@ -0,0 +1,71 @@
+//
+// ========================================================================
+// Copyright (c) 1995-2012 Mort Bay Consulting Pty. Ltd.
+// ------------------------------------------------------------------------
+// All rights reserved. This program and the accompanying materials
+// are made available under the terms of the Eclipse Public License v1.0
+// and Apache License v2.0 which accompanies this distribution.
+//
+// The Eclipse Public License is available at
+// http://www.eclipse.org/legal/epl-v10.html
+//
+// The Apache License v2.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.annotations;
+
+import java.util.List;
+
+import org.eclipse.jetty.annotations.AnnotationParser.Value;
+import org.eclipse.jetty.util.log.Log;
+import org.eclipse.jetty.util.log.Logger;
+import org.eclipse.jetty.webapp.DiscoveredAnnotation;
+import org.eclipse.jetty.webapp.WebAppContext;
+
+public class WebListenerAnnotationHandler extends AbstractDiscoverableAnnotationHandler
+{
+ private static final Logger LOG = Log.getLogger(WebListenerAnnotationHandler.class);
+
+ public WebListenerAnnotationHandler (WebAppContext context)
+ {
+ super(context);
+ }
+
+ public WebListenerAnnotationHandler (WebAppContext context, List<DiscoveredAnnotation> list)
+ {
+ super(context, list);
+ }
+
+ /**
+ * @see org.eclipse.jetty.annotations.AnnotationParser.DiscoverableAnnotationHandler#handleClass(java.lang.String, int, int, java.lang.String, java.lang.String, java.lang.String[], java.lang.String, java.util.List)
+ */
+ public void handleClass(String className, int version, int access, String signature, String superName, String[] interfaces, String annotation,
+ List<Value> values)
+ {
+ WebListenerAnnotation wlAnnotation = new WebListenerAnnotation(_context, className, _resource);
+ addAnnotation(wlAnnotation);
+ }
+
+ public void handleField(String className, String fieldName, int access, String fieldType, String signature, Object value, String annotation,
+ List<Value> values)
+ {
+ LOG.warn ("@WebListener is not applicable to fields: "+className+"."+fieldName);
+ }
+
+ public void handleMethod(String className, String methodName, int access, String params, String signature, String[] exceptions, String annotation,
+ List<Value> values)
+ {
+ LOG.warn ("@WebListener is not applicable to methods: "+className+"."+methodName+" "+signature);
+ }
+
+ @Override
+ public String getAnnotationName()
+ {
+ return "javax.servlet.annotation.WebListener";
+ }
+
+}
diff --git a/jetty-annotations/src/main/java/org/eclipse/jetty/annotations/WebServletAnnotation.java b/jetty-annotations/src/main/java/org/eclipse/jetty/annotations/WebServletAnnotation.java
new file mode 100644
index 0000000000..62965baeed
--- /dev/null
+++ b/jetty-annotations/src/main/java/org/eclipse/jetty/annotations/WebServletAnnotation.java
@@ -0,0 +1,227 @@
+//
+// ========================================================================
+// Copyright (c) 1995-2012 Mort Bay Consulting Pty. Ltd.
+// ------------------------------------------------------------------------
+// All rights reserved. This program and the accompanying materials
+// are made available under the terms of the Eclipse Public License v1.0
+// and Apache License v2.0 which accompanies this distribution.
+//
+// The Eclipse Public License is available at
+// http://www.eclipse.org/legal/epl-v10.html
+//
+// The Apache License v2.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.annotations;
+
+import java.util.ArrayList;
+
+import javax.servlet.annotation.WebInitParam;
+import javax.servlet.annotation.WebServlet;
+import javax.servlet.http.HttpServlet;
+
+import org.eclipse.jetty.servlet.Holder;
+import org.eclipse.jetty.servlet.ServletHolder;
+import org.eclipse.jetty.servlet.ServletMapping;
+import org.eclipse.jetty.util.LazyList;
+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.DiscoveredAnnotation;
+import org.eclipse.jetty.webapp.MetaData;
+import org.eclipse.jetty.webapp.WebAppContext;
+import org.eclipse.jetty.webapp.Origin;
+
+/**
+ * WebServletAnnotation
+ *
+ *
+ */
+public class WebServletAnnotation extends DiscoveredAnnotation
+{
+ private static final Logger LOG = Log.getLogger(WebServletAnnotation.class);
+
+ public WebServletAnnotation (WebAppContext context, String className)
+ {
+ super(context, className);
+ }
+
+
+ public WebServletAnnotation (WebAppContext context, String className, Resource resource)
+ {
+ super(context, className, resource);
+ }
+
+ /**
+ * @see org.eclipse.jetty.annotations.ClassAnnotation#apply()
+ */
+ public void apply()
+ {
+ //TODO check this algorithm with new rules for applying descriptors and annotations in order
+ Class clazz = getTargetClass();
+
+ if (clazz == null)
+ {
+ LOG.warn(_className+" cannot be loaded");
+ return;
+ }
+
+ //Servlet Spec 8.1.1
+ if (!HttpServlet.class.isAssignableFrom(clazz))
+ {
+ LOG.warn(clazz.getName()+" is not assignable from javax.servlet.http.HttpServlet");
+ return;
+ }
+
+ WebServlet annotation = (WebServlet)clazz.getAnnotation(WebServlet.class);
+
+ if (annotation.urlPatterns().length > 0 && annotation.value().length > 0)
+ {
+ LOG.warn(clazz.getName()+ " defines both @WebServlet.value and @WebServlet.urlPatterns");
+ return;
+ }
+
+ String[] urlPatterns = annotation.value();
+ if (urlPatterns.length == 0)
+ urlPatterns = annotation.urlPatterns();
+
+ if (urlPatterns.length == 0)
+ {
+ LOG.warn(clazz.getName()+ " defines neither @WebServlet.value nor @WebServlet.urlPatterns");
+ return;
+ }
+
+ //canonicalize the patterns
+ ArrayList<String> urlPatternList = new ArrayList<String>();
+ for (String p : urlPatterns)
+ urlPatternList.add(Util.normalizePattern(p));
+
+ String servletName = (annotation.name().equals("")?clazz.getName():annotation.name());
+
+ MetaData metaData = _context.getMetaData();
+
+ //Find out if a <servlet> already exists with this name
+ ServletHolder[] holders = _context.getServletHandler().getServlets();
+ boolean isNew = true;
+ ServletHolder holder = null;
+ if (holders != null)
+ {
+ for (ServletHolder h : holders)
+ {
+ if (h.getName() != null && servletName.equals(h.getName()))
+ {
+ holder = h;
+ isNew = false;
+ break;
+ }
+ }
+ }
+
+ if (isNew)
+ {
+ //No servlet of this name has already been defined, either by a descriptor
+ //or another annotation (which would be impossible).
+ holder = _context.getServletHandler().newServletHolder(Holder.Source.ANNOTATION);
+ holder.setHeldClass(clazz);
+ metaData.setOrigin(servletName+".servlet.servlet-class");
+
+ holder.setName(servletName);
+ holder.setDisplayName(annotation.displayName());
+ metaData.setOrigin(servletName+".servlet.display-name");
+
+ holder.setInitOrder(annotation.loadOnStartup());
+ metaData.setOrigin(servletName+".servlet.load-on-startup");
+
+ holder.setAsyncSupported(annotation.asyncSupported());
+ metaData.setOrigin(servletName+".servlet.async-supported");
+
+ for (WebInitParam ip:annotation.initParams())
+ {
+ holder.setInitParameter(ip.name(), ip.value());
+ metaData.setOrigin(servletName+".servlet.init-param."+ip.name());
+ }
+
+ _context.getServletHandler().addServlet(holder);
+ ServletMapping mapping = new ServletMapping();
+ mapping.setServletName(holder.getName());
+ mapping.setPathSpecs( LazyList.toStringArray(urlPatternList));
+ _context.getServletHandler().addServletMapping(mapping);
+ metaData.setOrigin(servletName+".servlet.mappings");
+ }
+ else
+ {
+ //set the class according to the servlet that is annotated, if it wasn't already
+ //NOTE: this may be considered as "completing" an incomplete servlet registration, and it is
+ //not clear from servlet 3.0 spec whether this is intended, or if only a ServletContext.addServlet() call
+ //can complete it, see http://java.net/jira/browse/SERVLET_SPEC-42
+ if (holder.getClassName() == null)
+ holder.setClassName(clazz.getName());
+ if (holder.getHeldClass() == null)
+ holder.setHeldClass(clazz);
+
+ //check if the existing servlet has each init-param from the annotation
+ //if not, add it
+ for (WebInitParam ip:annotation.initParams())
+ {
+ if (metaData.getOrigin(servletName+".servlet.init-param"+ip.name())==Origin.NotSet)
+ {
+ holder.setInitParameter(ip.name(), ip.value());
+ metaData.setOrigin(servletName+".servlet.init-param."+ip.name());
+ }
+ }
+
+ //check the url-patterns
+ //ServletSpec 3.0 p81 If a servlet already has url mappings from a
+ //webxml or fragment descriptor the annotation is ignored. However, we want to be able to
+ //replace mappings that were given in webdefault.xml
+ boolean mappingsExist = false;
+ boolean anyNonDefaults = false;
+ ServletMapping[] allMappings = _context.getServletHandler().getServletMappings();
+ if (allMappings != null)
+ {
+ for (ServletMapping m:allMappings)
+ {
+ if (m.getServletName() != null && servletName.equals(m.getServletName()))
+ {
+ mappingsExist = true;
+ if (!m.isDefault())
+ {
+ anyNonDefaults = true;
+ break;
+ }
+ }
+ }
+ }
+
+ if (anyNonDefaults)
+ return; //if any mappings already set by a descriptor that is not webdefault.xml, we're done
+
+ boolean clash = false;
+ if (mappingsExist)
+ {
+ for (String p:urlPatternList)
+ {
+ ServletMapping m = _context.getServletHandler().getServletMapping(p);
+ if (m != null && !m.isDefault())
+ {
+ //trying to override a servlet-mapping that was added not by webdefault.xml
+ clash = true;
+ break;
+ }
+ }
+ }
+
+ if (!mappingsExist || !clash)
+ {
+ ServletMapping m = new ServletMapping();
+ m.setServletName(servletName);
+ m.setPathSpecs(LazyList.toStringArray(urlPatternList));
+ _context.getServletHandler().addServletMapping(m);
+ }
+ }
+ }
+}
diff --git a/jetty-annotations/src/main/java/org/eclipse/jetty/annotations/WebServletAnnotationHandler.java b/jetty-annotations/src/main/java/org/eclipse/jetty/annotations/WebServletAnnotationHandler.java
new file mode 100644
index 0000000000..0f74eb906f
--- /dev/null
+++ b/jetty-annotations/src/main/java/org/eclipse/jetty/annotations/WebServletAnnotationHandler.java
@@ -0,0 +1,85 @@
+//
+// ========================================================================
+// Copyright (c) 1995-2012 Mort Bay Consulting Pty. Ltd.
+// ------------------------------------------------------------------------
+// All rights reserved. This program and the accompanying materials
+// are made available under the terms of the Eclipse Public License v1.0
+// and Apache License v2.0 which accompanies this distribution.
+//
+// The Eclipse Public License is available at
+// http://www.eclipse.org/legal/epl-v10.html
+//
+// The Apache License v2.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.annotations;
+
+import java.util.List;
+
+import org.eclipse.jetty.annotations.AnnotationParser.DiscoverableAnnotationHandler;
+import org.eclipse.jetty.annotations.AnnotationParser.Value;
+import org.eclipse.jetty.util.log.Log;
+import org.eclipse.jetty.util.log.Logger;
+import org.eclipse.jetty.webapp.DiscoveredAnnotation;
+import org.eclipse.jetty.webapp.WebAppContext;
+
+/**
+ * WebServletAnnotationHandler
+ *
+ * Process a WebServlet annotation on a class.
+ *
+ */
+public class WebServletAnnotationHandler extends AbstractDiscoverableAnnotationHandler
+{
+ private static final Logger LOG = Log.getLogger(WebServletAnnotationHandler.class);
+
+ public WebServletAnnotationHandler (WebAppContext context)
+ {
+ super(context);
+ }
+
+ public WebServletAnnotationHandler (WebAppContext context, List<DiscoveredAnnotation> list)
+ {
+ super(context, list);
+ }
+
+
+ /**
+ * Handle discovering a WebServlet annotation.
+ *
+ *
+ * @see org.eclipse.jetty.annotations.AnnotationParser.DiscoverableAnnotationHandler#handleClass(java.lang.String, int, int, java.lang.String, java.lang.String, java.lang.String[], java.lang.String, java.util.List)
+ */
+ public void handleClass(String className, int version, int access, String signature, String superName, String[] interfaces, String annotationName,
+ List<Value> values)
+ {
+ if (!"javax.servlet.annotation.WebServlet".equals(annotationName))
+ return;
+
+ WebServletAnnotation annotation = new WebServletAnnotation (_context, className, _resource);
+ addAnnotation(annotation);
+ }
+
+ public void handleField(String className, String fieldName, int access, String fieldType, String signature, Object value, String annotation,
+ List<Value> values)
+ {
+ LOG.warn ("@WebServlet annotation not supported for fields");
+ }
+
+ public void handleMethod(String className, String methodName, int access, String params, String signature, String[] exceptions, String annotation,
+ List<Value> values)
+ {
+ LOG.warn ("@WebServlet annotation not supported for methods");
+ }
+
+
+ @Override
+ public String getAnnotationName()
+ {
+ return "javax.servlet.annotation.WebServlet";
+ }
+}
diff --git a/jetty-annotations/src/test/java/org/eclipse/jetty/annotations/FilterC.java b/jetty-annotations/src/test/java/org/eclipse/jetty/annotations/FilterC.java
index 08397c2861..3268c46c57 100644
--- a/jetty-annotations/src/test/java/org/eclipse/jetty/annotations/FilterC.java
+++ b/jetty-annotations/src/test/java/org/eclipse/jetty/annotations/FilterC.java
@@ -24,16 +24,20 @@ import javax.annotation.PostConstruct;
import javax.annotation.PreDestroy;
import javax.annotation.Resource;
import javax.annotation.security.RunAs;
+import javax.servlet.DispatcherType;
import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
+import javax.servlet.annotation.WebFilter;
+import javax.servlet.annotation.WebInitParam;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
+@WebFilter(filterName="CFilter", dispatcherTypes={DispatcherType.REQUEST}, urlPatterns = {"/*"}, initParams={@WebInitParam(name="a", value="99")}, asyncSupported=false)
@RunAs("admin")
public class FilterC implements Filter
{
diff --git a/jetty-annotations/src/test/java/org/eclipse/jetty/annotations/ListenerC.java b/jetty-annotations/src/test/java/org/eclipse/jetty/annotations/ListenerC.java
index 23fbf78d17..097e6c40ec 100644
--- a/jetty-annotations/src/test/java/org/eclipse/jetty/annotations/ListenerC.java
+++ b/jetty-annotations/src/test/java/org/eclipse/jetty/annotations/ListenerC.java
@@ -20,7 +20,9 @@ package org.eclipse.jetty.annotations;
import javax.servlet.ServletContextEvent;
import javax.servlet.ServletContextListener;
+import javax.servlet.annotation.WebListener;
+@WebListener
public class ListenerC implements ServletContextListener
{
diff --git a/jetty-annotations/src/test/java/org/eclipse/jetty/annotations/ServletC.java b/jetty-annotations/src/test/java/org/eclipse/jetty/annotations/ServletC.java
index 86e6d03ab3..f607b25ac3 100644
--- a/jetty-annotations/src/test/java/org/eclipse/jetty/annotations/ServletC.java
+++ b/jetty-annotations/src/test/java/org/eclipse/jetty/annotations/ServletC.java
@@ -26,12 +26,21 @@ import javax.annotation.Resource;
import javax.annotation.security.DeclareRoles;
import javax.annotation.security.RunAs;
import javax.servlet.ServletException;
+import javax.servlet.annotation.HttpConstraint;
+import javax.servlet.annotation.HttpMethodConstraint;
+import javax.servlet.annotation.MultipartConfig;
+import javax.servlet.annotation.ServletSecurity;
+import javax.servlet.annotation.WebInitParam;
+import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
@DeclareRoles({"alice"})
+@WebServlet(urlPatterns = { "/foo/*", "/bah/*" }, name="CServlet", initParams={@WebInitParam(name="x", value="y")}, loadOnStartup=2, asyncSupported=false)
+@MultipartConfig(fileSizeThreshold=1000, maxFileSize=2000, maxRequestSize=3000)
@RunAs("admin")
+@ServletSecurity(value=@HttpConstraint(rolesAllowed={"fred", "bill", "dorothy"}), httpMethodConstraints={@HttpMethodConstraint(value="GET", rolesAllowed={"bob", "carol", "ted"})})
public class ServletC extends HttpServlet
{
@Resource (mappedName="foo", type=Double.class)
diff --git a/jetty-annotations/src/test/java/org/eclipse/jetty/annotations/TestAnnotationConfiguration.java b/jetty-annotations/src/test/java/org/eclipse/jetty/annotations/TestAnnotationConfiguration.java
new file mode 100644
index 0000000000..dd0e2e9cb9
--- /dev/null
+++ b/jetty-annotations/src/test/java/org/eclipse/jetty/annotations/TestAnnotationConfiguration.java
@@ -0,0 +1,58 @@
+//
+// ========================================================================
+// Copyright (c) 1995-2012 Mort Bay Consulting Pty. Ltd.
+// ------------------------------------------------------------------------
+// All rights reserved. This program and the accompanying materials
+// are made available under the terms of the Eclipse Public License v1.0
+// and Apache License v2.0 which accompanies this distribution.
+//
+// The Eclipse Public License is available at
+// http://www.eclipse.org/legal/epl-v10.html
+//
+// The Apache License v2.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.annotations;
+
+import java.io.File;
+import java.net.URL;
+import java.util.ArrayList;
+import java.util.List;
+
+import junit.framework.TestCase;
+
+import org.eclipse.jetty.util.resource.Resource;
+import org.eclipse.jetty.webapp.FragmentDescriptor;
+import org.eclipse.jetty.webapp.WebAppContext;
+
+/**
+ * TestAnnotationConfiguration
+ *
+ *
+ */
+public class TestAnnotationConfiguration extends TestCase
+{
+ public void testGetFragmentFromJar ()
+ throws Exception
+ {
+ String dir = System.getProperty("basedir", ".");
+ File file = new File(dir);
+ file=new File(file.getCanonicalPath());
+ URL url=file.toURL();
+
+ Resource jar1 = Resource.newResource(url+"file.jar");
+
+ AnnotationConfiguration config = new AnnotationConfiguration();
+ WebAppContext wac = new WebAppContext();
+
+ List<FragmentDescriptor> frags = new ArrayList<FragmentDescriptor>();
+ frags.add(new FragmentDescriptor(Resource.newResource("jar:"+url+"file.jar!/fooa.props")));
+ frags.add(new FragmentDescriptor(Resource.newResource("jar:"+url+"file2.jar!/foob.props")));
+
+ assertNotNull(config.getFragmentFromJar(jar1, frags));
+ }
+}
diff --git a/jetty-annotations/src/test/java/org/eclipse/jetty/annotations/TestAnnotationInheritance.java b/jetty-annotations/src/test/java/org/eclipse/jetty/annotations/TestAnnotationInheritance.java
index b5928edecd..4deb5408f5 100644
--- a/jetty-annotations/src/test/java/org/eclipse/jetty/annotations/TestAnnotationInheritance.java
+++ b/jetty-annotations/src/test/java/org/eclipse/jetty/annotations/TestAnnotationInheritance.java
@@ -18,20 +18,23 @@
package org.eclipse.jetty.annotations;
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertTrue;
-
import java.util.ArrayList;
import java.util.List;
-
+import java.util.Map;
import javax.naming.Context;
import javax.naming.InitialContext;
import org.eclipse.jetty.annotations.AnnotationParser.DiscoverableAnnotationHandler;
import org.eclipse.jetty.annotations.AnnotationParser.Value;
+import org.eclipse.jetty.util.MultiMap;
import org.junit.After;
import org.junit.Test;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertTrue;
+
/**
*
*/
@@ -63,6 +66,12 @@ public class TestAnnotationInheritance
{
annotatedMethods.add(className+"."+methodName);
}
+
+ @Override
+ public String getAnnotationName()
+ {
+ return "org.eclipse.jetty.annotations.Sample";
+ }
}
@After
@@ -82,7 +91,7 @@ public class TestAnnotationInheritance
SampleHandler handler = new SampleHandler();
AnnotationParser parser = new AnnotationParser();
- parser.registerAnnotationHandler("org.eclipse.jetty.annotations.Sample", handler);
+ parser.registerHandler(handler);
parser.parse(classNames, new ClassNameResolver ()
{
public boolean isExcluded(String name)
@@ -191,4 +200,40 @@ public class TestAnnotationInheritance
});
assertEquals (1, handler.annotatedClassNames.size());
}
+
+ @Test
+ public void testTypeInheritanceHandling() throws Exception
+ {
+ AnnotationParser parser = new AnnotationParser();
+ ClassInheritanceHandler handler = new ClassInheritanceHandler();
+ parser.registerClassHandler(handler);
+
+ class Foo implements InterfaceD
+ {
+ }
+
+ classNames.clear();
+ classNames.add(ClassA.class.getName());
+ classNames.add(ClassB.class.getName());
+ classNames.add(InterfaceD.class.getName());
+ classNames.add(Foo.class.getName());
+
+ parser.parse(classNames, null);
+
+ MultiMap map = handler.getMap();
+ assertNotNull(map);
+ assertFalse(map.isEmpty());
+ assertEquals(2, map.size());
+ Map stringArrayMap = map.toStringArrayMap();
+ assertTrue (stringArrayMap.keySet().contains("org.eclipse.jetty.annotations.ClassA"));
+ assertTrue (stringArrayMap.keySet().contains("org.eclipse.jetty.annotations.InterfaceD"));
+ String[] classes = (String[])stringArrayMap.get("org.eclipse.jetty.annotations.ClassA");
+ assertEquals(1, classes.length);
+ assertEquals ("org.eclipse.jetty.annotations.ClassB", classes[0]);
+
+ classes = (String[])stringArrayMap.get("org.eclipse.jetty.annotations.InterfaceD");
+ assertEquals(2, classes.length);
+ assertEquals ("org.eclipse.jetty.annotations.ClassB", classes[0]);
+ assertEquals(Foo.class.getName(), classes[1]);
+ }
}
diff --git a/jetty-annotations/src/test/java/org/eclipse/jetty/annotations/TestAnnotationParser.java b/jetty-annotations/src/test/java/org/eclipse/jetty/annotations/TestAnnotationParser.java
index ec74005170..ec00c9b905 100644
--- a/jetty-annotations/src/test/java/org/eclipse/jetty/annotations/TestAnnotationParser.java
+++ b/jetty-annotations/src/test/java/org/eclipse/jetty/annotations/TestAnnotationParser.java
@@ -41,6 +41,9 @@ public class TestAnnotationParser
{
private List<String> methods = Arrays.asList("a", "b", "c", "d", "l");
+
+
+
public void handleClass(String className, int version, int access, String signature, String superName, String[] interfaces, String annotation,
List<Value> values)
{
@@ -81,9 +84,15 @@ public class TestAnnotationParser
assertTrue(methods.contains(methodName));
assertEquals("org.eclipse.jetty.annotations.Sample", annotation);
}
+
+ @Override
+ public String getAnnotationName()
+ {
+ return "org.eclipse.jetty.annotations.Sample";
+ }
}
- parser.registerAnnotationHandler("org.eclipse.jetty.annotations.Sample", new SampleAnnotationHandler());
+ parser.registerHandler(new SampleAnnotationHandler());
long start = System.currentTimeMillis();
parser.parse(classNames, new ClassNameResolver ()
@@ -140,9 +149,17 @@ public class TestAnnotationParser
System.err.println(anv.toString());
}
}
+
+ @Override
+ public String getAnnotationName()
+ {
+ return "org.eclipse.jetty.annotations.Multi";
+ }
+
+
}
- parser.registerAnnotationHandler("org.eclipse.jetty.annotations.Multi", new MultiAnnotationHandler());
+ parser.registerHandler(new MultiAnnotationHandler());
parser.parse(classNames, null);
}
}
diff --git a/jetty-annotations/src/test/java/org/eclipse/jetty/annotations/TestSecurityAnnotationConversions.java b/jetty-annotations/src/test/java/org/eclipse/jetty/annotations/TestSecurityAnnotationConversions.java
new file mode 100644
index 0000000000..42111880d7
--- /dev/null
+++ b/jetty-annotations/src/test/java/org/eclipse/jetty/annotations/TestSecurityAnnotationConversions.java
@@ -0,0 +1,334 @@
+//
+// ========================================================================
+// Copyright (c) 1995-2012 Mort Bay Consulting Pty. Ltd.
+// ------------------------------------------------------------------------
+// All rights reserved. This program and the accompanying materials
+// are made available under the terms of the Eclipse Public License v1.0
+// and Apache License v2.0 which accompanies this distribution.
+//
+// The Eclipse Public License is available at
+// http://www.eclipse.org/legal/epl-v10.html
+//
+// The Apache License v2.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.annotations;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import javax.servlet.annotation.ServletSecurity;
+import javax.servlet.annotation.HttpConstraint;
+import javax.servlet.annotation.HttpMethodConstraint;
+import javax.servlet.annotation.ServletSecurity.TransportGuarantee;
+import javax.servlet.annotation.ServletSecurity.EmptyRoleSemantic;
+import javax.servlet.http.HttpServlet;
+
+import org.eclipse.jetty.security.ConstraintAware;
+import org.eclipse.jetty.security.ConstraintMapping;
+import org.eclipse.jetty.servlet.Holder;
+import org.eclipse.jetty.security.ConstraintSecurityHandler;
+import org.eclipse.jetty.servlet.ServletHolder;
+import org.eclipse.jetty.servlet.ServletMapping;
+import org.eclipse.jetty.util.LazyList;
+import org.eclipse.jetty.util.security.Constraint;
+import org.eclipse.jetty.webapp.WebAppContext;
+
+import junit.framework.TestCase;
+
+public class TestSecurityAnnotationConversions extends TestCase
+{
+ @ServletSecurity(value=@HttpConstraint(value=EmptyRoleSemantic.DENY))
+ public static class DenyServlet extends HttpServlet
+ {}
+
+ @ServletSecurity
+ public static class PermitServlet extends HttpServlet
+ {}
+
+ @ServletSecurity(value=@HttpConstraint(value=EmptyRoleSemantic.PERMIT, transportGuarantee=TransportGuarantee.CONFIDENTIAL, rolesAllowed={"tom", "dick", "harry"}))
+ public static class RolesServlet extends HttpServlet
+ {}
+
+ @ServletSecurity(value=@HttpConstraint(value=EmptyRoleSemantic.PERMIT, transportGuarantee=TransportGuarantee.CONFIDENTIAL, rolesAllowed={"tom", "dick", "harry"}),
+ httpMethodConstraints={@HttpMethodConstraint(value="GET")})
+ public static class Method1Servlet extends HttpServlet
+ {}
+
+ @ServletSecurity(value=@HttpConstraint(value=EmptyRoleSemantic.PERMIT, transportGuarantee=TransportGuarantee.CONFIDENTIAL, rolesAllowed={"tom", "dick", "harry"}),
+ httpMethodConstraints={@HttpMethodConstraint(value="GET", transportGuarantee=TransportGuarantee.CONFIDENTIAL)})
+ public static class Method2Servlet extends HttpServlet
+ {}
+
+
+ public void setUp()
+ {
+ }
+
+ public void testDenyAllOnClass ()
+ throws Exception
+ {
+
+ WebAppContext wac = makeWebAppContext(DenyServlet.class.getCanonicalName(), "denyServlet", new String[]{"/foo/*", "*.foo"});
+
+ //Assume we found 1 servlet with a @HttpConstraint with value=EmptyRoleSemantic.DENY security annotation
+ ServletSecurityAnnotationHandler annotationHandler = new ServletSecurityAnnotationHandler(wac);
+ AnnotationIntrospector introspector = new AnnotationIntrospector();
+ introspector.registerHandler(annotationHandler);
+
+ //set up the expected outcomes:
+ //1 ConstraintMapping per ServletMapping pathSpec
+ Constraint expectedConstraint = new Constraint();
+ expectedConstraint.setAuthenticate(true);
+ expectedConstraint.setDataConstraint(Constraint.DC_NONE);
+
+ ConstraintMapping[] expectedMappings = new ConstraintMapping[2];
+
+ expectedMappings[0] = new ConstraintMapping();
+ expectedMappings[0].setConstraint(expectedConstraint);
+ expectedMappings[0].setPathSpec("/foo/*");
+
+ expectedMappings[1] = new ConstraintMapping();
+ expectedMappings[1].setConstraint(expectedConstraint);
+ expectedMappings[1].setPathSpec("*.foo");
+
+ introspector.introspect(DenyServlet.class);
+
+ compareResults(expectedMappings, ((ConstraintAware)wac.getSecurityHandler()).getConstraintMappings());
+ }
+
+
+ public void testPermitAll()
+ throws Exception
+ {
+ //Assume we found 1 servlet with a @ServletSecurity security annotation
+ WebAppContext wac = makeWebAppContext(PermitServlet.class.getCanonicalName(), "permitServlet", new String[]{"/foo/*", "*.foo"});
+
+ ServletSecurityAnnotationHandler annotationHandler = new ServletSecurityAnnotationHandler(wac);
+ AnnotationIntrospector introspector = new AnnotationIntrospector();
+ introspector.registerHandler(annotationHandler);
+
+
+ //set up the expected outcomes:
+ //1 ConstraintMapping per ServletMapping pathSpec
+ Constraint expectedConstraint = new Constraint();
+ expectedConstraint.setAuthenticate(false);
+ expectedConstraint.setDataConstraint(Constraint.DC_NONE);
+
+ ConstraintMapping[] expectedMappings = new ConstraintMapping[2];
+ expectedMappings[0] = new ConstraintMapping();
+ expectedMappings[0].setConstraint(expectedConstraint);
+ expectedMappings[0].setPathSpec("/foo/*");
+
+ expectedMappings[1] = new ConstraintMapping();
+ expectedMappings[1].setConstraint(expectedConstraint);
+ expectedMappings[1].setPathSpec("*.foo");
+
+ introspector.introspect(PermitServlet.class);
+
+ compareResults (expectedMappings, ((ConstraintAware)wac.getSecurityHandler()).getConstraintMappings());
+ }
+
+ public void testRolesAllowedWithTransportGuarantee ()
+ throws Exception
+ {
+ //Assume we found 1 servlet with annotation with roles defined and
+ //and a TransportGuarantee
+
+ WebAppContext wac = makeWebAppContext(RolesServlet.class.getCanonicalName(), "rolesServlet", new String[]{"/foo/*", "*.foo"});
+
+ ServletSecurityAnnotationHandler annotationHandler = new ServletSecurityAnnotationHandler(wac);
+ AnnotationIntrospector introspector = new AnnotationIntrospector();
+ introspector.registerHandler(annotationHandler);
+
+ //set up the expected outcomes:compareResults
+ //1 ConstraintMapping per ServletMapping
+ Constraint expectedConstraint = new Constraint();
+ expectedConstraint.setAuthenticate(true);
+ expectedConstraint.setRoles(new String[]{"tom", "dick", "harry"});
+ expectedConstraint.setDataConstraint(Constraint.DC_CONFIDENTIAL);
+
+ ConstraintMapping[] expectedMappings = new ConstraintMapping[2];
+ expectedMappings[0] = new ConstraintMapping();
+ expectedMappings[0].setConstraint(expectedConstraint);
+ expectedMappings[0].setPathSpec("/foo/*");
+
+ expectedMappings[1] = new ConstraintMapping();
+ expectedMappings[1].setConstraint(expectedConstraint);
+ expectedMappings[1].setPathSpec("*.foo");
+
+ introspector.introspect(RolesServlet.class);
+ compareResults (expectedMappings, ((ConstraintAware)wac.getSecurityHandler()).getConstraintMappings());
+ }
+
+
+ public void testMethodAnnotation ()
+ throws Exception
+ {
+ //ServletSecurity annotation with HttpConstraint of TransportGuarantee.CONFIDENTIAL, and a list of rolesAllowed, and
+ //a HttpMethodConstraint for GET method that permits all and has TransportGuarantee.NONE (ie is default)
+
+ WebAppContext wac = makeWebAppContext(Method1Servlet.class.getCanonicalName(), "method1Servlet", new String[]{"/foo/*", "*.foo"});
+
+ //set up the expected outcomes: - a Constraint for the RolesAllowed on the class
+ //with userdata constraint of DC_CONFIDENTIAL
+ //and mappings for each of the pathSpecs
+ Constraint expectedConstraint1 = new Constraint();
+ expectedConstraint1.setAuthenticate(true);
+ expectedConstraint1.setRoles(new String[]{"tom", "dick", "harry"});
+ expectedConstraint1.setDataConstraint(Constraint.DC_CONFIDENTIAL);
+
+ //a Constraint for the PermitAll on the doGet method with a userdata
+ //constraint of DC_CONFIDENTIAL inherited from the class
+ Constraint expectedConstraint2 = new Constraint();
+ expectedConstraint2.setDataConstraint(Constraint.DC_NONE);
+
+ ConstraintMapping[] expectedMappings = new ConstraintMapping[4];
+ expectedMappings[0] = new ConstraintMapping();
+ expectedMappings[0].setConstraint(expectedConstraint1);
+ expectedMappings[0].setPathSpec("/foo/*");
+ expectedMappings[0].setMethodOmissions(new String[]{"GET"});
+ expectedMappings[1] = new ConstraintMapping();
+ expectedMappings[1].setConstraint(expectedConstraint1);
+ expectedMappings[1].setPathSpec("*.foo");
+ expectedMappings[1].setMethodOmissions(new String[]{"GET"});
+
+ expectedMappings[2] = new ConstraintMapping();
+ expectedMappings[2].setConstraint(expectedConstraint2);
+ expectedMappings[2].setPathSpec("/foo/*");
+ expectedMappings[2].setMethod("GET");
+ expectedMappings[3] = new ConstraintMapping();
+ expectedMappings[3].setConstraint(expectedConstraint2);
+ expectedMappings[3].setPathSpec("*.foo");
+ expectedMappings[3].setMethod("GET");
+
+ AnnotationIntrospector introspector = new AnnotationIntrospector();
+ ServletSecurityAnnotationHandler annotationHandler = new ServletSecurityAnnotationHandler(wac);
+ introspector.registerHandler(annotationHandler);
+ introspector.introspect(Method1Servlet.class);
+ compareResults (expectedMappings, ((ConstraintAware)wac.getSecurityHandler()).getConstraintMappings());
+ }
+
+ public void testMethodAnnotation2 ()
+ throws Exception
+ {
+ //A ServletSecurity annotation that has HttpConstraint of CONFIDENTIAL with defined roles, but a
+ //HttpMethodConstraint for GET that permits all, but also requires CONFIDENTIAL
+ WebAppContext wac = makeWebAppContext(Method2Servlet.class.getCanonicalName(), "method2Servlet", new String[]{"/foo/*", "*.foo"});
+
+ AnnotationIntrospector introspector = new AnnotationIntrospector();
+ ServletSecurityAnnotationHandler annotationHandler = new ServletSecurityAnnotationHandler(wac);
+ introspector.registerHandler(annotationHandler);
+
+ //set up the expected outcomes: - a Constraint for the RolesAllowed on the class
+ //with userdata constraint of DC_CONFIDENTIAL
+ //and mappings for each of the pathSpecs
+ Constraint expectedConstraint1 = new Constraint();
+ expectedConstraint1.setAuthenticate(true);
+ expectedConstraint1.setRoles(new String[]{"tom", "dick", "harry"});
+ expectedConstraint1.setDataConstraint(Constraint.DC_CONFIDENTIAL);
+
+ //a Constraint for the Permit on the GET method with a userdata
+ //constraint of DC_CONFIDENTIAL
+ Constraint expectedConstraint2 = new Constraint();
+ expectedConstraint2.setDataConstraint(Constraint.DC_CONFIDENTIAL);
+
+ ConstraintMapping[] expectedMappings = new ConstraintMapping[4];
+ expectedMappings[0] = new ConstraintMapping();
+ expectedMappings[0].setConstraint(expectedConstraint1);
+ expectedMappings[0].setPathSpec("/foo/*");
+ expectedMappings[0].setMethodOmissions(new String[]{"GET"});
+ expectedMappings[1] = new ConstraintMapping();
+ expectedMappings[1].setConstraint(expectedConstraint1);
+ expectedMappings[1].setPathSpec("*.foo");
+ expectedMappings[1].setMethodOmissions(new String[]{"GET"});
+
+ expectedMappings[2] = new ConstraintMapping();
+ expectedMappings[2].setConstraint(expectedConstraint2);
+ expectedMappings[2].setPathSpec("/foo/*");
+ expectedMappings[2].setMethod("GET");
+ expectedMappings[3] = new ConstraintMapping();
+ expectedMappings[3].setConstraint(expectedConstraint2);
+ expectedMappings[3].setPathSpec("*.foo");
+ expectedMappings[3].setMethod("GET");
+
+ introspector.introspect(Method2Servlet.class);
+ compareResults (expectedMappings, ((ConstraintAware)wac.getSecurityHandler()).getConstraintMappings());
+ }
+
+ private void compareResults (ConstraintMapping[] expectedMappings, List<ConstraintMapping> actualMappings)
+ {
+ assertNotNull(actualMappings);
+ assertEquals(expectedMappings.length, actualMappings.size());
+
+ for (int k=0; k < actualMappings.size(); k++)
+ {
+ ConstraintMapping am = actualMappings.get(k);
+ boolean matched = false;
+
+ for (int i=0; i< expectedMappings.length && !matched; i++)
+ {
+ ConstraintMapping em = expectedMappings[i];
+ if (em.getPathSpec().equals(am.getPathSpec()))
+ {
+ if ((em.getMethod()==null && am.getMethod() == null) || em.getMethod() != null && em.getMethod().equals(am.getMethod()))
+ {
+ matched = true;
+
+ assertEquals(em.getConstraint().getAuthenticate(), am.getConstraint().getAuthenticate());
+ assertEquals(em.getConstraint().getDataConstraint(), am.getConstraint().getDataConstraint());
+ if (em.getMethodOmissions() == null)
+ {
+ assertNull(am.getMethodOmissions());
+ }
+ else
+ {
+ assertTrue(Arrays.equals(am.getMethodOmissions(), em.getMethodOmissions()));
+ }
+
+ if (em.getConstraint().getRoles() == null)
+ {
+ assertNull(am.getConstraint().getRoles());
+ }
+ else
+ {
+ assertTrue(Arrays.equals(em.getConstraint().getRoles(), am.getConstraint().getRoles()));
+ }
+ }
+ }
+ }
+
+ if (!matched)
+ fail("No expected ConstraintMapping matching method:"+am.getMethod()+" pathSpec: "+am.getPathSpec());
+ }
+ }
+
+
+ private WebAppContext makeWebAppContext (String className, String servletName, String[] paths)
+ {
+ WebAppContext wac = new WebAppContext();
+
+ ServletHolder[] holders = new ServletHolder[1];
+ holders[0] = new ServletHolder();
+ holders[0].setClassName(className);
+ holders[0].setName(servletName);
+ holders[0].setServletHandler(wac.getServletHandler());
+ wac.getServletHandler().setServlets(holders);
+ wac.setSecurityHandler(new ConstraintSecurityHandler());
+
+ ServletMapping[] servletMappings = new ServletMapping[1];
+ servletMappings[0] = new ServletMapping();
+
+ servletMappings[0].setPathSpecs(paths);
+ servletMappings[0].setServletName(servletName);
+ wac.getServletHandler().setServletMappings(servletMappings);
+ return wac;
+ }
+}
diff --git a/jetty-annotations/src/test/java/org/eclipse/jetty/annotations/TestServletAnnotations.java b/jetty-annotations/src/test/java/org/eclipse/jetty/annotations/TestServletAnnotations.java
index 2222cb3dd8..6915448835 100644
--- a/jetty-annotations/src/test/java/org/eclipse/jetty/annotations/TestServletAnnotations.java
+++ b/jetty-annotations/src/test/java/org/eclipse/jetty/annotations/TestServletAnnotations.java
@@ -18,12 +18,19 @@
package org.eclipse.jetty.annotations;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertTrue;
+import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashSet;
+import java.util.List;
import org.eclipse.jetty.security.ConstraintSecurityHandler;
+import org.eclipse.jetty.servlet.ServletHolder;
+import org.eclipse.jetty.servlet.ServletMapping;
import org.eclipse.jetty.webapp.WebAppContext;
import org.junit.Test;
@@ -34,8 +41,50 @@ import org.junit.Test;
*/
public class TestServletAnnotations
{
-
@Test
+ public void testServletAnnotation() throws Exception
+ {
+ List<String> classes = new ArrayList<String>();
+ classes.add("org.eclipse.jetty.annotations.ServletC");
+ AnnotationParser parser = new AnnotationParser();
+
+ WebAppContext wac = new WebAppContext();
+ WebServletAnnotationHandler handler = new WebServletAnnotationHandler(wac);
+ parser.registerAnnotationHandler("javax.servlet.annotation.WebServlet", handler);
+
+ parser.parse(classes, new ClassNameResolver ()
+ {
+ public boolean isExcluded(String name)
+ {
+ return false;
+ }
+
+ public boolean shouldOverride(String name)
+ {
+ return false;
+ }
+ });
+
+ assertEquals(1, handler.getAnnotationList().size());
+ assertTrue(handler.getAnnotationList().get(0) instanceof WebServletAnnotation);
+
+ handler.getAnnotationList().get(0).apply();
+
+ ServletHolder[] holders = wac.getServletHandler().getServlets();
+ assertNotNull(holders);
+ assertEquals(1, holders.length);
+ assertEquals("CServlet", holders[0].getName());
+ ServletMapping[] mappings = wac.getServletHandler().getServletMappings();
+ assertNotNull(mappings);
+ assertEquals(1, mappings.length);
+ String[] paths = mappings[0].getPathSpecs();
+ assertNotNull(paths);
+ assertEquals(2, paths.length);
+ assertEquals("y", holders[0].getInitParameter("x"));
+ assertEquals(2,holders[0].getInitOrder());
+ assertFalse(holders[0].isAsyncSupported());
+ }
+
public void testDeclareRoles ()
throws Exception
{
diff --git a/jetty-client/pom.xml b/jetty-client/pom.xml
index dbbf90f26e..34091b1ac9 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>7.6.8-SNAPSHOT</version>
+ <version>8.1.8-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
diff --git a/jetty-continuation/pom.xml b/jetty-continuation/pom.xml
index b5ad693666..dcaada141d 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>7.6.8-SNAPSHOT</version>
+ <version>8.1.8-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>jetty-continuation</artifactId>
@@ -24,7 +24,7 @@
</goals>
<configuration>
<instructions>
- <Import-Package>javax.servlet.*;version="[2.5,3.1)",org.mortbay.log.*;version="[6.1,7)";resolution:=optional,org.mortbay.util.ajax.*;version="[6.1,7)";resolution:=optional,*</Import-Package>
+ <Import-Package>javax.servlet.*;version="2.6.0",org.mortbay.log.*;version="[6.1,7)";resolution:=optional,org.mortbay.util.ajax.*;version="[6.1,7)";resolution:=optional,*</Import-Package>
</instructions>
</configuration>
</execution>
diff --git a/jetty-continuation/src/main/java/org/eclipse/jetty/continuation/ContinuationSupport.java b/jetty-continuation/src/main/java/org/eclipse/jetty/continuation/ContinuationSupport.java
index 314c6c84b8..fa1a549fc5 100644
--- a/jetty-continuation/src/main/java/org/eclipse/jetty/continuation/ContinuationSupport.java
+++ b/jetty-continuation/src/main/java/org/eclipse/jetty/continuation/ContinuationSupport.java
@@ -19,7 +19,6 @@
package org.eclipse.jetty.continuation;
import java.lang.reflect.Constructor;
-
import javax.servlet.ServletRequest;
import javax.servlet.ServletRequestWrapper;
import javax.servlet.ServletResponse;
@@ -59,7 +58,7 @@ public class ContinuationSupport
__servlet3=servlet3Support;
__newServlet3Continuation=s3cc;
}
-
+
boolean jetty6Support=false;
Constructor<? extends Continuation>j6cc=null;
try
@@ -80,7 +79,7 @@ public class ContinuationSupport
__jetty6=jetty6Support;
__newJetty6Continuation=j6cc;
}
-
+
Class<?> waiting=null;
try
{
@@ -98,12 +97,12 @@ public class ContinuationSupport
/* ------------------------------------------------------------ */
/**
* Get a Continuation. The type of the Continuation returned may
- * vary depending on the container in which the application is
+ * vary depending on the container in which the application is
* deployed. It may be an implementation native to the container (eg
* org.eclipse.jetty.server.AsyncContinuation) or one of the utility
* implementations provided such as an internal <code>FauxContinuation</code>
* or a real implementation like {@link org.eclipse.jetty.continuation.Servlet3Continuation}.
- * @param request The request
+ * @param request The request
* @return a Continuation instance
*/
public static Continuation getContinuation(ServletRequest request)
@@ -111,10 +110,10 @@ public class ContinuationSupport
Continuation continuation = (Continuation) request.getAttribute(Continuation.ATTRIBUTE);
if (continuation!=null)
return continuation;
-
+
while (request instanceof ServletRequestWrapper)
request=((ServletRequestWrapper)request).getRequest();
-
+
if (__servlet3 )
{
try
diff --git a/jetty-continuation/src/main/java/org/eclipse/jetty/continuation/FauxContinuation.java b/jetty-continuation/src/main/java/org/eclipse/jetty/continuation/FauxContinuation.java
index 72fef5fb36..3c8dc73aa8 100644
--- a/jetty-continuation/src/main/java/org/eclipse/jetty/continuation/FauxContinuation.java
+++ b/jetty-continuation/src/main/java/org/eclipse/jetty/continuation/FauxContinuation.java
@@ -505,4 +505,4 @@ class FauxContinuation implements FilteredContinuation
throw new IllegalStateException("!suspended");
}
-} \ No newline at end of file
+}
diff --git a/jetty-continuation/src/main/java/org/eclipse/jetty/continuation/Servlet3Continuation.java b/jetty-continuation/src/main/java/org/eclipse/jetty/continuation/Servlet3Continuation.java
index 76fcb445e1..f30eb24bd7 100644
--- a/jetty-continuation/src/main/java/org/eclipse/jetty/continuation/Servlet3Continuation.java
+++ b/jetty-continuation/src/main/java/org/eclipse/jetty/continuation/Servlet3Continuation.java
@@ -21,7 +21,6 @@ package org.eclipse.jetty.continuation;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
-
import javax.servlet.AsyncContext;
import javax.servlet.AsyncEvent;
import javax.servlet.AsyncListener;
@@ -34,7 +33,7 @@ import javax.servlet.ServletResponseWrapper;
/* ------------------------------------------------------------ */
/**
* This implementation of Continuation is used by {@link ContinuationSupport}
- * when it detects that the application has been deployed in a non-jetty Servlet 3
+ * when it detects that the application has been deployed in a non-jetty Servlet 3
* server.
*/
public class Servlet3Continuation implements Continuation
@@ -42,11 +41,11 @@ public class Servlet3Continuation implements Continuation
// Exception reused for all continuations
// Turn on debug in ContinuationFilter to see real stack trace.
private final static ContinuationThrowable __exception = new ContinuationThrowable();
-
+
private final ServletRequest _request;
private ServletResponse _response;
private AsyncContext _context;
- private List<AsyncListener> _listeners=new ArrayList<AsyncListener>();
+ private List<AsyncListener> _listeners=new ArrayList<AsyncListener>();
private volatile boolean _initial=true;
private volatile boolean _resumed=false;
private volatile boolean _expired=false;
@@ -108,7 +107,7 @@ public class Servlet3Continuation implements Continuation
listener.onTimeout(Servlet3Continuation.this);
}
};
-
+
if (_context!=null)
_context.addListener(wrapped);
else
@@ -188,7 +187,7 @@ public class Servlet3Continuation implements Continuation
_expired=false;
_context=_request.startAsync();
_context.setTimeout(_timeoutMs);
-
+
for (AsyncListener listener:_listeners)
_context.addListener(listener);
_listeners.clear();
@@ -201,7 +200,7 @@ public class Servlet3Continuation implements Continuation
_expired=false;
_context=_request.startAsync();
_context.setTimeout(_timeoutMs);
-
+
for (AsyncListener listener:_listeners)
_context.addListener(listener);
_listeners.clear();
diff --git a/jetty-deploy/pom.xml b/jetty-deploy/pom.xml
index 880e2f2881..ba9f7d88c6 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>7.6.8-SNAPSHOT</version>
+ <version>8.1.8-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>jetty-deploy</artifactId>
@@ -24,7 +24,7 @@
</goals>
<configuration>
<instructions>
- <Import-Package>org.eclipse.jetty.jmx.*;version="[7.3,8)";resolution:=optional,*</Import-Package>
+ <Import-Package>org.eclipse.jetty.jmx.*;version="8.0";resolution:=optional,*</Import-Package>
</instructions>
</configuration>
</execution>
diff --git a/jetty-deploy/src/main/config/etc/jetty-deploy.xml b/jetty-deploy/src/main/config/etc/jetty-deploy.xml
index dd25f7ff34..1b3fd66dcd 100644
--- a/jetty-deploy/src/main/config/etc/jetty-deploy.xml
+++ b/jetty-deploy/src/main/config/etc/jetty-deploy.xml
@@ -22,7 +22,7 @@
</Set>
<Call name="setContextAttribute">
<Arg>org.eclipse.jetty.server.webapp.ContainerIncludeJarPattern</Arg>
- <Arg>.*/.*jsp-api-[^/]*\.jar$|.*/.*jsp-[^/]*\.jar$|.*/.*taglibs[^/]*\.jar$</Arg>
+ <Arg>.*/servlet-api-[^/]*\.jar$</Arg>
</Call>
diff --git a/jetty-distribution/pom.xml b/jetty-distribution/pom.xml
index c8f77aab33..a64f2f1e24 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>7.6.8-SNAPSHOT</version>
+ <version>8.1.8-SNAPSHOT</version>
</parent>
<artifactId>jetty-distribution</artifactId>
<name>Jetty :: Distribution Assemblies</name>
@@ -144,7 +144,7 @@
<version>${orbit-servlet-api-version}</version>
<overWrite>true</overWrite>
<outputDirectory>${assembly-directory}/lib</outputDirectory>
- <destFileName>servlet-api-2.5.jar</destFileName>
+ <destFileName>servlet-api-3.0.jar</destFileName>
</artifactItem>
</artifactItems>
</configuration>
diff --git a/jetty-distribution/src/main/resources/bin/jetty-cygwin.sh b/jetty-distribution/src/main/resources/bin/jetty-cygwin.sh
index 550390edce..16371bea30 100755
--- a/jetty-distribution/src/main/resources/bin/jetty-cygwin.sh
+++ b/jetty-distribution/src/main/resources/bin/jetty-cygwin.sh
@@ -5,7 +5,7 @@
# To get the service to restart correctly on reboot, uncomment below (3 lines):
# ========================
# chkconfig: 3 99 99
-# description: Jetty 7 webserver
+# description: Jetty 8 webserver
# processname: jetty
# ========================
@@ -134,8 +134,8 @@ NO_START=0
##################################################
# See if there's a default configuration file
##################################################
-if [ -f /etc/default/jetty7 ] ; then
- . /etc/default/jetty7
+if [ -f /etc/default/jetty8 ] ; then
+ . /etc/default/jetty8
elif [ -f /etc/default/jetty ] ; then
. /etc/default/jetty
fi
@@ -196,13 +196,13 @@ if [ "$JETTY_HOME" = "" ] ; then
/home \
"
JETTY_DIR_NAMES=" \
- jetty-7 \
- jetty7 \
- jetty-7.* \
+ jetty-8 \
+ jetty8 \
+ jetty-8.* \
jetty \
- Jetty-7 \
- Jetty7 \
- Jetty-7.* \
+ Jetty-8 \
+ Jetty8 \
+ Jetty-8.* \
Jetty \
"
@@ -511,7 +511,7 @@ case "$ACTION" in
echo -n "Starting Jetty: "
if [ "$NO_START" = "1" ]; then
- echo "Not starting jetty - NO_START=1 in /etc/default/jetty7";
+ echo "Not starting jetty - NO_START=1 in /etc/default/jetty8";
exit 0;
fi
diff --git a/jetty-distribution/src/main/resources/bin/jetty.sh b/jetty-distribution/src/main/resources/bin/jetty.sh
index 7f6b549463..5442d2fe14 100755
--- a/jetty-distribution/src/main/resources/bin/jetty.sh
+++ b/jetty-distribution/src/main/resources/bin/jetty.sh
@@ -5,7 +5,7 @@
# To get the service to restart correctly on reboot, uncomment below (3 lines):
# ========================
# chkconfig: 3 99 99
-# description: Jetty 7 webserver
+# description: Jetty 8 webserver
# processname: jetty
# ========================
@@ -136,7 +136,7 @@ shift
##################################################
# Read any configuration files
##################################################
-for CONFIG in /etc/default/jetty{,7} $HOME/.jettyrc; do
+for CONFIG in /etc/default/jetty{,8} $HOME/.jettyrc; do
if [ -f "$CONFIG" ] ; then
readConfig "$CONFIG"
fi
@@ -192,13 +192,13 @@ if [ -z "$JETTY_HOME" ] ; then
"/home"
)
JETTY_DIR_NAMES=(
- "jetty-7"
- "jetty7"
- "jetty-7.*"
+ "jetty-8"
+ "jetty8"
+ "jetty-8.*"
"jetty"
- "Jetty-7"
- "Jetty7"
- "Jetty-7.*"
+ "Jetty-8"
+ "Jetty8"
+ "Jetty-8.*"
"Jetty"
)
diff --git a/jetty-distribution/src/main/resources/start.ini b/jetty-distribution/src/main/resources/start.ini
index 0ada4c0205..dfc2783db5 100644
--- a/jetty-distribution/src/main/resources/start.ini
+++ b/jetty-distribution/src/main/resources/start.ini
@@ -46,7 +46,7 @@
# for a full listing do
# java -jar start.jar --list-options
#-----------------------------------------------------------
-OPTIONS=Server,jsp,jmx,resources,websocket,ext
+OPTIONS=Server,jsp,jmx,resources,websocket,ext,plus,annotations
#-----------------------------------------------------------
@@ -57,6 +57,7 @@ OPTIONS=Server,jsp,jmx,resources,websocket,ext
#-----------------------------------------------------------
#etc/jetty-jmx.xml
etc/jetty.xml
+etc/jetty-annotations.xml
# etc/jetty-ssl.xml
# etc/jetty-requestlog.xml
etc/jetty-deploy.xml
diff --git a/jetty-http-spi/pom.xml b/jetty-http-spi/pom.xml
index 29a49593b6..ca4c37bbae 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>7.6.8-SNAPSHOT</version>
+ <version>8.1.8-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>jetty-http-spi</artifactId>
diff --git a/jetty-http/pom.xml b/jetty-http/pom.xml
index bf838f1b91..0853013f59 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>7.6.8-SNAPSHOT</version>
+ <version>8.1.8-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>jetty-http</artifactId>
@@ -41,7 +41,7 @@
</goals>
<configuration>
<instructions>
- <Import-Package>javax.net.*,*</Import-Package>
+ <Import-Package>javax.servlet.*;version="2.6.0",javax.net.*,*</Import-Package>
</instructions>
</configuration>
</execution>
diff --git a/jetty-http/src/main/java/org/eclipse/jetty/http/HttpFields.java b/jetty-http/src/main/java/org/eclipse/jetty/http/HttpFields.java
index a0a117c661..a4f88ff3ea 100644
--- a/jetty-http/src/main/java/org/eclipse/jetty/http/HttpFields.java
+++ b/jetty-http/src/main/java/org/eclipse/jetty/http/HttpFields.java
@@ -24,10 +24,12 @@ import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Collections;
+import java.util.Collection;
import java.util.Date;
import java.util.Enumeration;
import java.util.GregorianCalendar;
import java.util.HashMap;
+import java.util.Iterator;
import java.util.List;
import java.util.Locale;
import java.util.Map;
@@ -341,6 +343,22 @@ public class HttpFields
/* -------------------------------------------------------------- */
/**
+ * Get Collection of header names.
+ */
+ public Collection<String> getFieldNamesCollection()
+ {
+ final List<String> list = new ArrayList<String>(_fields.size());
+
+ for (Field f : _fields)
+ {
+ if (f!=null)
+ list.add(BufferUtil.to8859_1_String(f._name));
+ }
+ return list;
+ }
+
+ /* -------------------------------------------------------------- */
+ /**
* Get enumeration of header _names. Returns an enumeration of strings representing the header
* _names for this request.
*/
@@ -371,7 +389,7 @@ public class HttpFields
/**
* Get a Field by index.
* @return A Field value or null if the Field value has not been set
- * for this revision of the fields.
+ *
*/
public Field getField(int i)
{
@@ -438,6 +456,30 @@ public class HttpFields
return field==null?null:field._value;
}
+
+ /* -------------------------------------------------------------- */
+ /**
+ * Get multi headers
+ *
+ * @return Enumeration of the values, or null if no such header.
+ * @param name the case-insensitive field name
+ */
+ public Collection<String> getValuesCollection(String name)
+ {
+ Field field = getField(name);
+ if (field==null)
+ return null;
+
+ final List<String> list = new ArrayList<String>();
+
+ while(field!=null)
+ {
+ list.add(field.getValue());
+ field=field._next;
+ }
+ return list;
+ }
+
/* -------------------------------------------------------------- */
/**
* Get multi headers
@@ -1361,5 +1403,4 @@ public class HttpFields
return ("[" + getName() + "=" + _value + (_next == null ? "" : "->") + "]");
}
}
-
}
diff --git a/jetty-http/src/main/java/org/eclipse/jetty/http/PathMap.java b/jetty-http/src/main/java/org/eclipse/jetty/http/PathMap.java
index 72c5ad298f..3324ddfeee 100644
--- a/jetty-http/src/main/java/org/eclipse/jetty/http/PathMap.java
+++ b/jetty-http/src/main/java/org/eclipse/jetty/http/PathMap.java
@@ -151,7 +151,16 @@ public class PathMap extends HashMap implements Externalizable
@Override
public Object put(Object pathSpec, Object object)
{
- StringTokenizer tok = new StringTokenizer(pathSpec.toString(),__pathSpecSeparators);
+ String str = pathSpec.toString();
+ if ("".equals(str.trim()))
+ {
+ Entry entry = new Entry("",object);
+ entry.setMapped("");
+ _exactMap.put("", entry);
+ return super.put("", object);
+ }
+
+ StringTokenizer tok = new StringTokenizer(str,__pathSpecSeparators);
Object old =null;
while (tok.hasMoreTokens())
@@ -223,13 +232,21 @@ public class PathMap extends HashMap implements Externalizable
*/
public Entry getMatch(String path)
{
- Map.Entry entry;
+ Map.Entry entry=null;
if (path==null)
return null;
int l=path.length();
-
+
+ //special case
+ if (l == 1 && path.charAt(0)=='/')
+ {
+ entry = (Map.Entry)_exactMap.get("");
+ if (entry != null)
+ return (Entry)entry;
+ }
+
// try exact match
entry=_exactMap.getEntry(path,0,l);
if (entry!=null)
@@ -460,6 +477,9 @@ public class PathMap extends HashMap implements Externalizable
*/
public static String pathInfo(String pathSpec, String path)
{
+ if ("".equals(pathSpec))
+ return path; //servlet 3 spec sec 12.2 will be '/'
+
char c = pathSpec.charAt(0);
if (c=='/')
diff --git a/jetty-http/src/test/java/org/eclipse/jetty/http/HttpGeneratorClientTest.java b/jetty-http/src/test/java/org/eclipse/jetty/http/HttpGeneratorClientTest.java
index ff361ac80a..f9f27d186d 100644
--- a/jetty-http/src/test/java/org/eclipse/jetty/http/HttpGeneratorClientTest.java
+++ b/jetty-http/src/test/java/org/eclipse/jetty/http/HttpGeneratorClientTest.java
@@ -18,9 +18,6 @@
package org.eclipse.jetty.http;
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertTrue;
-
import java.io.IOException;
import java.util.concurrent.atomic.AtomicInteger;
@@ -33,6 +30,9 @@ import org.eclipse.jetty.io.SimpleBuffers;
import org.eclipse.jetty.io.View;
import org.junit.Test;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
+
public class HttpGeneratorClientTest
{
public final static String CONTENT="The quick brown fox jumped over the lazy dog.\nNow is the time for all good men to come to the aid of the party\nThe moon is blue to a fish in love.\n";
@@ -125,7 +125,7 @@ public class HttpGeneratorClientTest
* screw up the chunking by leaving out the second chunk header.
*/
@Test
- public void testChunkedWithBackPressure() throws Exception
+ public void testChunkedWithBackPressure() throws Exception
{
final AtomicInteger availableChannelBytes = new AtomicInteger(500);
ByteArrayEndPoint endp = new ByteArrayEndPoint(new byte[0],4096)
diff --git a/jetty-http/src/test/java/org/eclipse/jetty/http/PathMapTest.java b/jetty-http/src/test/java/org/eclipse/jetty/http/PathMapTest.java
index 193c25df98..8587389be2 100644
--- a/jetty-http/src/test/java/org/eclipse/jetty/http/PathMapTest.java
+++ b/jetty-http/src/test/java/org/eclipse/jetty/http/PathMapTest.java
@@ -41,6 +41,7 @@ public class PathMapTest extends TestCase
p.put("*.gz", "7");
p.put("/", "8");
p.put("/XXX:/YYY", "9");
+ p.put("", "10");
String[][] tests = {
{ "/abs/path", "1"},
@@ -73,7 +74,7 @@ public class PathMapTest extends TestCase
assertEquals("Dir matches", "[/animal/fish/*=4, /animal/*=5, /=8]", p.getMatches("/animal/fish/").toString());
assertEquals("Dir matches", "[/animal/fish/*=4, /animal/*=5, /=8]", p.getMatches("/animal/fish").toString());
assertEquals("Dir matches", "[/=8]", p.getMatches("/").toString());
- assertEquals("Dir matches", "[/=8]", p.getMatches("").toString());
+ assertEquals("Dir matches", "[=10, /=8]", p.getMatches("").toString());
assertEquals("pathMatch exact", "/Foo/bar", PathMap.pathMatch("/Foo/bar", "/Foo/bar"));
assertEquals("pathMatch prefix", "/Foo", PathMap.pathMatch("/Foo/*", "/Foo/bar"));
@@ -130,6 +131,8 @@ public class PathMapTest extends TestCase
assertTrue("!match /foo/*", !PathMap.match("/foo/*", "/bar/anything"));
assertTrue("match *.foo", PathMap.match("*.foo", "anything.foo"));
assertTrue("!match *.foo", !PathMap.match("*.foo", "anything.bar"));
+
+ assertEquals("match / with ''", "10", p.getMatch("/").getValue());
}
/**
diff --git a/jetty-io/pom.xml b/jetty-io/pom.xml
index c08d403fba..3bc51cf05a 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>7.6.8-SNAPSHOT</version>
+ <version>8.1.8-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>jetty-io</artifactId>
diff --git a/jetty-io/src/main/java/org/eclipse/jetty/io/AbstractBuffer.java b/jetty-io/src/main/java/org/eclipse/jetty/io/AbstractBuffer.java
index 24dac02c4b..748016a634 100644
--- a/jetty-io/src/main/java/org/eclipse/jetty/io/AbstractBuffer.java
+++ b/jetty-io/src/main/java/org/eclipse/jetty/io/AbstractBuffer.java
@@ -21,6 +21,7 @@ package org.eclipse.jetty.io;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
+import java.nio.charset.Charset;
import org.eclipse.jetty.util.TypeUtil;
import org.eclipse.jetty.util.log.Log;
@@ -505,43 +506,37 @@ public abstract class AbstractBuffer implements Buffer
public void setGetIndex(int getIndex)
{
- /* bounds checking */
- if (__boundsChecking)
- {
- if (isImmutable())
- throw new IllegalStateException(__IMMUTABLE);
- if (getIndex < 0)
- throw new IllegalArgumentException("getIndex<0: " + getIndex + "<0");
- if (getIndex > putIndex())
- throw new IllegalArgumentException("getIndex>putIndex: " + getIndex + ">" + putIndex());
- }
-
+ /* bounds checking
+ if (isImmutable())
+ throw new IllegalStateException(__IMMUTABLE);
+ if (getIndex < 0)
+ throw new IllegalArgumentException("getIndex<0: " + getIndex + "<0");
+ if (getIndex > putIndex())
+ throw new IllegalArgumentException("getIndex>putIndex: " + getIndex + ">" + putIndex());
+ */
_get = getIndex;
_hash=0;
}
public void setMarkIndex(int index)
{
-
+ /*
if (index>=0 && isImmutable())
throw new IllegalStateException(__IMMUTABLE);
-
+ */
_mark = index;
}
public void setPutIndex(int putIndex)
{
- if (__boundsChecking)
- {
- /* bounds checking */
- if (isImmutable())
- throw new IllegalStateException(__IMMUTABLE);
- if (putIndex > capacity())
+ /* bounds checking
+ if (isImmutable())
+ throw new IllegalStateException(__IMMUTABLE);
+ if (putIndex > capacity())
throw new IllegalArgumentException("putIndex>capacity: " + putIndex + ">" + capacity());
- if (getIndex() > putIndex)
+ if (getIndex() > putIndex)
throw new IllegalArgumentException("getIndex>putIndex: " + getIndex() + ">" + putIndex);
- }
-
+ */
_put = putIndex;
_hash=0;
}
@@ -651,6 +646,23 @@ public abstract class AbstractBuffer implements Buffer
}
/* ------------------------------------------------------------ */
+ public String toString(Charset charset)
+ {
+ try
+ {
+ byte[] bytes=array();
+ if (bytes!=null)
+ return new String(bytes,getIndex(),length(),charset);
+ return new String(asArray(), 0, length(),charset);
+ }
+ catch(Exception e)
+ {
+ LOG.warn(e);
+ return new String(asArray(), 0, length());
+ }
+ }
+
+ /* ------------------------------------------------------------ */
public String toDebugString()
{
return getClass()+"@"+super.hashCode();
diff --git a/jetty-io/src/main/java/org/eclipse/jetty/io/Buffer.java b/jetty-io/src/main/java/org/eclipse/jetty/io/Buffer.java
index c6ff99ee7c..ec6d23d77f 100644
--- a/jetty-io/src/main/java/org/eclipse/jetty/io/Buffer.java
+++ b/jetty-io/src/main/java/org/eclipse/jetty/io/Buffer.java
@@ -21,6 +21,7 @@ package org.eclipse.jetty.io;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
+import java.nio.charset.Charset;
/**
@@ -365,7 +366,10 @@ public interface Buffer extends Cloneable
/* ------------------------------------------------------------ */
String toString(String charset);
- /*
+ /* ------------------------------------------------------------ */
+ String toString(Charset charset);
+
+ /*
* Buffers implementing this interface should be compared with case insensitive equals
*
*/
diff --git a/jetty-io/src/main/java/org/eclipse/jetty/io/BufferUtil.java b/jetty-io/src/main/java/org/eclipse/jetty/io/BufferUtil.java
index 8c03634788..c24723dc90 100644
--- a/jetty-io/src/main/java/org/eclipse/jetty/io/BufferUtil.java
+++ b/jetty-io/src/main/java/org/eclipse/jetty/io/BufferUtil.java
@@ -354,6 +354,6 @@ public class BufferUtil
{
if (buffer instanceof CachedBuffer)
return buffer.toString();
- return buffer.toString(StringUtil.__ISO_8859_1);
+ return buffer.toString(StringUtil.__ISO_8859_1_CHARSET);
}
}
diff --git a/jetty-servlet/src/main/java/org/eclipse/jetty/servlet/api/ServletRegistration.java b/jetty-io/src/main/java/org/eclipse/jetty/io/UncheckedIOException.java
index c378c7ddf0..0731111ef1 100644
--- a/jetty-servlet/src/main/java/org/eclipse/jetty/servlet/api/ServletRegistration.java
+++ b/jetty-io/src/main/java/org/eclipse/jetty/io/UncheckedIOException.java
@@ -16,24 +16,33 @@
// ========================================================================
//
-package org.eclipse.jetty.servlet.api;
-import java.util.Collection;
-import java.util.Set;
+package org.eclipse.jetty.io;
-public interface ServletRegistration
+/* ------------------------------------------------------------ */
+/**
+ * Subclass of {@link java.lang.RuntimeException} used to signal that there
+ * was an {@link java.io.IOException} thrown by underlying {@link UncheckedPrintWriter}
+ */
+public class UncheckedIOException extends RuntimeException
{
- public Set<String> addMapping(String... urlPatterns);
-
- public Collection<String> getMappings();
-
- public String getRunAsRole();
+ public UncheckedIOException()
+ {
+ super();
+ }
- interface Dynamic extends ServletRegistration, Registration.Dynamic
+ public UncheckedIOException(String message)
{
- public void setLoadOnStartup(int loadOnStartup);
+ super(message);
+ }
- public void setRunAsRole(String roleName);
+ public UncheckedIOException(Throwable cause)
+ {
+ super(cause);
}
+ public UncheckedIOException(String message, Throwable cause)
+ {
+ super(message,cause);
+ }
}
diff --git a/jetty-jaspi/pom.xml b/jetty-jaspi/pom.xml
index c1a3a3cd0a..df5480889d 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>7.6.8-SNAPSHOT</version>
+ <version>8.1.8-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>jetty-jaspi</artifactId>
@@ -22,6 +22,12 @@
<goals>
<goal>manifest</goal>
</goals>
+ <configuration>
+ <instructions>
+ <Import-Package>javax.servlet.*;version="2.6.0",*</Import-Package>
+ <Export-Package>org.eclipse.jetty.security.jaspi.*;version="${parsedVersion.osgiVersion}"</Export-Package>
+ </instructions>
+ </configuration>
</execution>
</executions>
</plugin>
diff --git a/jetty-jaspi/src/main/java/org/eclipse/jetty/security/jaspi/JaspiAuthenticator.java b/jetty-jaspi/src/main/java/org/eclipse/jetty/security/jaspi/JaspiAuthenticator.java
index c93bafa770..e28d4a17cc 100644
--- a/jetty-jaspi/src/main/java/org/eclipse/jetty/security/jaspi/JaspiAuthenticator.java
+++ b/jetty-jaspi/src/main/java/org/eclipse/jetty/security/jaspi/JaspiAuthenticator.java
@@ -31,6 +31,8 @@ import javax.security.auth.message.config.ServerAuthConfig;
import javax.security.auth.message.config.ServerAuthContext;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpSession;
import org.eclipse.jetty.security.Authenticator;
import org.eclipse.jetty.security.IdentityService;
@@ -38,15 +40,21 @@ import org.eclipse.jetty.security.ServerAuthException;
import org.eclipse.jetty.security.UserAuthentication;
import org.eclipse.jetty.security.authentication.DeferredAuthentication;
import org.eclipse.jetty.security.authentication.LoginAuthenticator;
+import org.eclipse.jetty.security.authentication.SessionAuthentication;
+import org.eclipse.jetty.security.jaspi.modules.BaseAuthModule;
import org.eclipse.jetty.server.Authentication;
import org.eclipse.jetty.server.UserIdentity;
import org.eclipse.jetty.server.Authentication.User;
+import org.eclipse.jetty.util.log.Log;
+import org.eclipse.jetty.util.log.Logger;
/**
* @version $Rev: 4793 $ $Date: 2009-03-19 00:00:01 +0100 (Thu, 19 Mar 2009) $
*/
public class JaspiAuthenticator extends LoginAuthenticator
{
+ private static final Logger LOG = Log.getLogger(JaspiAuthenticator.class.getName());
+
private final ServerAuthConfig _authConfig;
private final Map _authProperties;
@@ -107,6 +115,28 @@ public class JaspiAuthenticator extends LoginAuthenticator
}
+ /**
+ * @see org.eclipse.jetty.security.authentication.LoginAuthenticator#login(java.lang.String, java.lang.Object, javax.servlet.ServletRequest)
+ */
+ @Override
+ public UserIdentity login(String username, Object password, ServletRequest request)
+ {
+ UserIdentity user = _loginService.login(username, password);
+ if (user != null)
+ {
+ renewSession((HttpServletRequest)request, null);
+ HttpSession session = ((HttpServletRequest)request).getSession(true);
+ if (session != null)
+ {
+ SessionAuthentication sessionAuth = new SessionAuthentication(getAuthMethod(), user, password);
+ session.setAttribute(SessionAuthentication.__J_AUTHENTICATED, sessionAuth);
+ }
+ }
+ return user;
+ }
+
+
+
public Authentication validateRequest(JaspiMessageInfo messageInfo) throws ServerAuthException
{
try
@@ -151,6 +181,12 @@ public class JaspiAuthenticator extends LoginAuthenticator
String[] groups = groupPrincipalCallback == null ? null : groupPrincipalCallback.getGroups();
userIdentity = _identityService.newUserIdentity(clientSubject, principal, groups);
}
+
+ HttpSession session = ((HttpServletRequest)messageInfo.getRequestMessage()).getSession(false);
+ Authentication cached = (session == null?null:(SessionAuthentication)session.getAttribute(SessionAuthentication.__J_AUTHENTICATED));
+ if (cached != null)
+ return cached;
+
return new UserAuthentication(getAuthMethod(), userIdentity);
}
if (authStatus == AuthStatus.SEND_SUCCESS)
diff --git a/jetty-jaspi/src/main/java/org/eclipse/jetty/security/jaspi/SimpleAuthConfig.java b/jetty-jaspi/src/main/java/org/eclipse/jetty/security/jaspi/SimpleAuthConfig.java
index f25203d741..832a2aab33 100644
--- a/jetty-jaspi/src/main/java/org/eclipse/jetty/security/jaspi/SimpleAuthConfig.java
+++ b/jetty-jaspi/src/main/java/org/eclipse/jetty/security/jaspi/SimpleAuthConfig.java
@@ -70,7 +70,7 @@ public class SimpleAuthConfig implements ServerAuthConfig
return true;
}
- public void refresh()
+ public void refresh()
{
}
}
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 6c6270280b..9bea1c5063 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
@@ -43,7 +43,10 @@ import org.eclipse.jetty.util.security.Password;
import org.eclipse.jetty.security.CrossContextPsuedoSession;
import org.eclipse.jetty.security.authentication.DeferredAuthentication;
import org.eclipse.jetty.security.authentication.LoginCallbackImpl;
+import org.eclipse.jetty.security.authentication.SessionAuthentication;
+import org.eclipse.jetty.security.jaspi.callback.CredentialValidationCallback;
import org.eclipse.jetty.server.Authentication;
+import org.eclipse.jetty.server.UserIdentity;
import org.eclipse.jetty.util.StringUtil;
import org.eclipse.jetty.util.URIUtil;
import org.eclipse.jetty.util.log.Log;
@@ -214,21 +217,22 @@ public class FormAuthModule extends BaseAuthModule
// Check if the session is already authenticated.
- FormCredential form_cred = (FormCredential) session.getAttribute(__J_AUTHENTICATED);
- if (form_cred != null)
+ SessionAuthentication sessionAuth = (SessionAuthentication)session.getAttribute(SessionAuthentication.__J_AUTHENTICATED);
+ if (sessionAuth != null)
{
//TODO: ideally we would like the form auth module to be able to invoke the
//loginservice.validate() method to check the previously authed user, but it is not visible
//to FormAuthModule
- if (form_cred._subject == null)
+ if (sessionAuth.getUserIdentity().getSubject() == null)
return AuthStatus.SEND_FAILURE;
- Set<Object> credentials = form_cred._subject.getPrivateCredentials();
+
+ Set<Object> credentials = sessionAuth.getUserIdentity().getSubject().getPrivateCredentials();
if (credentials == null || credentials.isEmpty())
return AuthStatus.SEND_FAILURE; //if no private credentials, assume it cannot be authenticated
clientSubject.getPrivateCredentials().addAll(credentials);
+ clientSubject.getPrivateCredentials().add(sessionAuth.getUserIdentity());
- //boolean success = tryLogin(messageInfo, clientSubject, response, session, form_cred._jUserName, new Password(new String(form_cred._jPassword)));
return AuthStatus.SUCCESS;
}
else if (ssoSource != null)
@@ -300,8 +304,14 @@ public class FormAuthModule extends BaseAuthModule
if (!loginCallbacks.isEmpty())
{
LoginCallbackImpl loginCallback = loginCallbacks.iterator().next();
- FormCredential form_cred = new FormCredential(username, pwdChars, loginCallback.getUserPrincipal(), loginCallback.getSubject());
- session.setAttribute(__J_AUTHENTICATED, form_cred);
+ Set<UserIdentity> userIdentities = clientSubject.getPrivateCredentials(UserIdentity.class);
+ if (!userIdentities.isEmpty())
+ {
+ UserIdentity userIdentity = userIdentities.iterator().next();
+
+ SessionAuthentication sessionAuth = new SessionAuthentication(Constraint.__FORM_AUTH, userIdentity, password);
+ session.setAttribute(SessionAuthentication.__J_AUTHENTICATED, sessionAuth);
+ }
}
// Sign-on to SSO mechanism
@@ -320,61 +330,4 @@ public class FormAuthModule extends BaseAuthModule
return pathInContext != null && (pathInContext.equals(_formErrorPath) || pathInContext.equals(_formLoginPath));
}
- /* ------------------------------------------------------------ */
- /**
- * FORM Authentication credential holder.
- */
- private static class FormCredential implements Serializable, HttpSessionBindingListener
- {
- String _jUserName;
-
- char[] _jPassword;
-
- transient Principal _userPrincipal;
-
- transient Subject _subject;
-
- private FormCredential(String _jUserName, char[] _jPassword, Principal _userPrincipal, Subject subject)
- {
- this._jUserName = _jUserName;
- this._jPassword = _jPassword;
- this._userPrincipal = _userPrincipal;
- this._subject = subject;
- }
-
- public void valueBound(HttpSessionBindingEvent event)
- {
- }
-
- public void valueUnbound(HttpSessionBindingEvent event)
- {
- if (LOG.isDebugEnabled()) LOG.debug("Logout " + _jUserName);
-
- // TODO jaspi call cleanSubject()
- // if (_realm instanceof SSORealm)
- // ((SSORealm) _realm).clearSingleSignOn(_jUserName);
- //
- // if (_realm != null && _userPrincipal != null)
- // _realm.logout(_userPrincipal);
- }
-
- public int hashCode()
- {
- return _jUserName.hashCode() + _jPassword.hashCode();
- }
-
- public boolean equals(Object o)
- {
- if (!(o instanceof FormCredential)) return false;
- FormCredential fc = (FormCredential) o;
- return _jUserName.equals(fc._jUserName) && Arrays.equals(_jPassword, fc._jPassword);
- }
-
- public String toString()
- {
- return "Cred[" + _jUserName + "]";
- }
-
- }
-
}
diff --git a/jetty-jmx/pom.xml b/jetty-jmx/pom.xml
index 726fca4c09..71c4fbc3e2 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>7.6.8-SNAPSHOT</version>
+ <version>8.1.8-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>jetty-jmx</artifactId>
diff --git a/jetty-jndi/pom.xml b/jetty-jndi/pom.xml
index fea782ecc6..fc4276c442 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>7.6.8-SNAPSHOT</version>
+ <version>8.1.8-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>jetty-jndi</artifactId>
diff --git a/jetty-jsp/pom.xml b/jetty-jsp/pom.xml
index c422892319..c540b6617c 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>7.6.8-SNAPSHOT</version>
+ <version>8.1.8-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>jetty-jsp</artifactId>
@@ -16,13 +16,13 @@
<dependency>
<groupId>org.eclipse.jetty.orbit</groupId>
<artifactId>javax.servlet.jsp</artifactId>
- <version>2.1.0.v201105211820</version>
+ <version>2.2.0.v201112011158</version>
</dependency>
<!-- JSP Impl -->
<dependency>
<groupId>org.eclipse.jetty.orbit</groupId>
<artifactId>org.apache.jasper.glassfish</artifactId>
- <version>2.1.0.v201110031002</version>
+ <version>2.2.2.v201112011158</version>
</dependency>
<!-- JSTL Api -->
<dependency>
@@ -40,13 +40,13 @@
<dependency>
<groupId>org.eclipse.jetty.orbit</groupId>
<artifactId>javax.el</artifactId>
- <version>2.1.0.v201105211819</version>
+ <version>2.2.0.v201108011116</version>
</dependency>
<!-- EL Impl -->
<dependency>
<groupId>org.eclipse.jetty.orbit</groupId>
<artifactId>com.sun.el</artifactId>
- <version>1.0.0.v201105211818</version>
+ <version>2.2.0.v201108011116</version>
</dependency>
<!-- Eclipse Java Compiler (for JSP Compilation) -->
<dependency>
diff --git a/jetty-monitor/pom.xml b/jetty-monitor/pom.xml
index 1eea5ee00b..0cac1c02fd 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>7.6.8-SNAPSHOT</version>
+ <version>8.1.8-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>jetty-monitor</artifactId>
diff --git a/jetty-nested/pom.xml b/jetty-nested/pom.xml
index a043d69617..e86fc13d03 100644
--- a/jetty-nested/pom.xml
+++ b/jetty-nested/pom.xml
@@ -4,7 +4,7 @@
<parent>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-project</artifactId>
- <version>7.6.8-SNAPSHOT</version>
+ <version>8.1.8-SNAPSHOT</version>
</parent>
<artifactId>jetty-nested</artifactId>
<name>Jetty :: Nested</name>
@@ -26,7 +26,7 @@
</goals>
<configuration>
<instructions>
- <Import-Package>javax.servlet*;version="2.5.0",*</Import-Package>
+ <Import-Package>javax.servlet.*;version="2.6.0",*</Import-Package>
</instructions>
</configuration>
</execution>
diff --git a/jetty-nested/src/main/java/org/eclipse/jetty/nested/NestedConnection.java b/jetty-nested/src/main/java/org/eclipse/jetty/nested/NestedConnection.java
index 4367d68330..9d32f0e643 100644
--- a/jetty-nested/src/main/java/org/eclipse/jetty/nested/NestedConnection.java
+++ b/jetty-nested/src/main/java/org/eclipse/jetty/nested/NestedConnection.java
@@ -21,6 +21,7 @@ package org.eclipse.jetty.nested;
import java.io.IOException;
import java.util.Enumeration;
+import javax.servlet.DispatcherType;
import javax.servlet.ServletException;
import javax.servlet.ServletInputStream;
import javax.servlet.http.HttpServletRequest;
@@ -30,7 +31,6 @@ import org.eclipse.jetty.http.HttpFields;
import org.eclipse.jetty.http.HttpURI;
import org.eclipse.jetty.io.Connection;
import org.eclipse.jetty.server.AbstractHttpConnection;
-import org.eclipse.jetty.server.DispatcherType;
public class NestedConnection extends AbstractHttpConnection
diff --git a/jetty-nosql/pom.xml b/jetty-nosql/pom.xml
index fb50c9d260..694049d0d0 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>7.6.8-SNAPSHOT</version>
+ <version>8.1.8-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>jetty-nosql</artifactId>
@@ -28,7 +28,7 @@
<artifactId>maven-bundle-plugin</artifactId>
<configuration>
<instructions>
- <Import-Package>javax.servlet.*;version="[2.5,3.0)",org.eclipse.jetty.server.session.jmx;version="[7.5,8)";resolution:=optional,,org.eclipse.jetty.*;version="[7.5,8)",*</Import-Package>
+ <Import-Package>javax.servlet.*;version="2.6.0",org.eclipse.jetty.server.session.jmx;version="8.0.0";resolution:=optional,,org.eclipse.jetty.*;version="8.0.0",*</Import-Package>
</instructions>
</configuration>
<extensions>true</extensions>
diff --git a/jetty-osgi/jetty-osgi-boot-jsp/pom.xml b/jetty-osgi/jetty-osgi-boot-jsp/pom.xml
index 95a03e1cad..e2afe90046 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>7.6.8-SNAPSHOT</version>
+ <version>8.1.8-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>
<modelVersion>4.0.0</modelVersion>
@@ -93,28 +93,27 @@
com.sun.el.lang;resolution:=optional,
com.sun.el.parser;resolution:=optional,
com.sun.el.util;resolution:=optional,
- com.sun.org.apache.commons.logging;split=glassfish;version="[2.1,3)";resolution:=optional,
- javax.el;version="1.0.0";resolution:=optional,
- javax.servlet;version="2.5.0",
- javax.servlet.jsp;version="2.1.0",
- javax.servlet.jsp.el;version="2.1.0",
+ javax.el;version="2.2.0";resolution:=optional,
+ javax.servlet;version="2.6.0",
+ javax.servlet.jsp;version="2.2.0",
+ javax.servlet.jsp.el;version="2.2.0",
javax.servlet.jsp.jstl.core;version="1.2.0";resolution:=optional,
javax.servlet.jsp.jstl.fmt;version="1.2.0";resolution:=optional,
javax.servlet.jsp.jstl.sql;version="1.2.0";resolution:=optional,
javax.servlet.jsp.jstl.tlv;version="1.2.0";resolution:=optional,
- javax.servlet.jsp.resources;version="2.1.0",
- javax.servlet.jsp.tagext;version="2.1.0",
- javax.servlet.resources;version="2.5.0",
- org.apache.jasper;version="6.0.0";resolution:=optional,
- org.apache.jasper.compiler;version="6.0.0";resolution:=optional,
- org.apache.jasper.compiler.tagplugin;version="6.0.0";resolution:=optional,
- org.apache.jasper.runtime;version="6.0.0";resolution:=optional,
- org.apache.jasper.security;version="6.0.0";resolution:=optional,
- org.apache.jasper.servlet;version="6.0.0";resolution:=optional,
- org.apache.jasper.tagplugins.jstl;version="6.0.0";resolution:=optional,
- org.apache.jasper.util;version="6.0.0";resolution:=optional,
- org.apache.jasper.xmlparser;version="6.0.0";resolution:=optional,
- org.glassfish.jsp.api;version="2.1.3";resolution:=optional,
+ javax.servlet.jsp.resources;version="2.2.0",
+ javax.servlet.jsp.tagext;version="2.2.0",
+ javax.servlet.resources;version="2.6.0",
+ org.apache.jasper;version="2.2.2";resolution:=optional,
+ org.apache.jasper.compiler;version="2.2.2";resolution:=optional,
+ org.apache.jasper.compiler.tagplugin;version="2.2.2";resolution:=optional,
+ org.apache.jasper.runtime;version="2.2.2";resolution:=optional,
+ org.apache.jasper.security;version="2.2.2";resolution:=optional,
+ org.apache.jasper.servlet;version="2.2.2";resolution:=optional,
+ org.apache.jasper.tagplugins.jstl;version="2.2.2";resolution:=optional,
+ org.apache.jasper.util;version="2.2.2";resolution:=optional,
+ org.apache.jasper.xmlparser;version="2.2.2";resolution:=optional,
+ org.glassfish.jsp.api;version="2.2.2";resolution:=optional,
org.apache.taglibs.standard;version="1.2.0";resolution:=optional,
org.apache.taglibs.standard.extra.spath;version="1.2.0";resolution:=optional,
org.apache.taglibs.standard.functions;version="1.2.0";resolution:=optional,
@@ -138,13 +137,13 @@
org.apache.taglibs.standard.tag.rt.xml;version="1.2.0";resolution:=optional,
org.apache.taglibs.standard.tei;version="1.2.0";resolution:=optional,
org.apache.taglibs.standard.tlv;version="1.2.0";resolution:=optional,
- org.eclipse.jetty.jsp;version="[7.0,8.0)";resolution:=optional,
!org.osgi.*,
!org.xml.*,
!org.eclipse.jetty.*,
*
</Import-Package>
<_nouses>true</_nouses>
+ <!-- DynamicImport-Package>org.apache.jasper.*;version="2.2.2"</DynamicImport-Package -->
</instructions>
</configuration>
</plugin>
diff --git a/jetty-osgi/jetty-osgi-boot-logback/META-INF/readme.txt b/jetty-osgi/jetty-osgi-boot-logback/META-INF/readme.txt
deleted file mode 100644
index 20960b4bd4..0000000000
--- a/jetty-osgi/jetty-osgi-boot-logback/META-INF/readme.txt
+++ /dev/null
@@ -1,12 +0,0 @@
-This bundle is made to inject the logback dependencies along with the slf4j dependencies to support log4j and commons-logging.
-It will read the configuration in the jettyhome/resources/logback-test.xml or jettyhome/resources/logback.xml folder.
-
-
-It was tested with these bundles:
-#this provides lg4j and commons-logging via slf4j
-SLF4J = group("com.springsource.slf4j.api", "com.springsource.slf4j.org.apache.log4j", "com.springsource.slf4j.org.apache.commons.logging",
- :under=>"org.slf4j", :version=>"1.5.6")
-
-#logback is not exporting enough packages for us to be able to configure logback classic programatically.. on the springsource version they are fine...
-LOGBACK = group("com.springsource.ch.qos.logback.core", "com.springsource.ch.qos.logback.classic",
- :under=>"ch.qos.logback", :version=>"0.9.15") \ No newline at end of file
diff --git a/jetty-osgi/jetty-osgi-boot-logback/build.properties b/jetty-osgi/jetty-osgi-boot-logback/build.properties
deleted file mode 100644
index 6d10c98886..0000000000
--- a/jetty-osgi/jetty-osgi-boot-logback/build.properties
+++ /dev/null
@@ -1,5 +0,0 @@
-source.. = src/main/java/
-output.. = target/classes/
-bin.includes = META-INF/,\
- .
-src.includes = META-INF/
diff --git a/jetty-osgi/jetty-osgi-boot-logback/pom.xml b/jetty-osgi/jetty-osgi-boot-logback/pom.xml
deleted file mode 100644
index b2061220f0..0000000000
--- a/jetty-osgi/jetty-osgi-boot-logback/pom.xml
+++ /dev/null
@@ -1,126 +0,0 @@
-<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.osgi</groupId>
- <artifactId>jetty-osgi-project</artifactId>
- <version>7.6.8-SNAPSHOT</version>
- <relativePath>../pom.xml</relativePath>
- </parent>
- <modelVersion>4.0.0</modelVersion>
- <artifactId>jetty-osgi-boot-logback</artifactId>
- <name>Jetty :: OSGi :: Boot Logback</name>
- <description>Jetty OSGi Boot Logback bundle</description>
- <properties>
- <bundle-symbolic-name>${project.groupId}.boot.logback</bundle-symbolic-name>
- </properties>
- <dependencies>
- <dependency>
- <groupId>org.eclipse.jetty.osgi</groupId>
- <artifactId>jetty-osgi-boot</artifactId>
- <version>${project.version}</version>
- <scope>provided</scope>
- </dependency>
- <dependency>
- <groupId>org.eclipse.osgi</groupId>
- <artifactId>org.eclipse.osgi</artifactId>
- </dependency>
- <dependency>
- <groupId>org.eclipse.jetty</groupId>
- <artifactId>jetty-webapp</artifactId>
- </dependency>
- <dependency>
- <groupId>org.eclipse.osgi</groupId>
- <artifactId>org.eclipse.osgi.services</artifactId>
- </dependency>
- <dependency>
- <groupId>org.slf4j</groupId>
- <artifactId>slf4j-api</artifactId>
- </dependency>
- <dependency>
- <groupId>org.slf4j</groupId>
- <artifactId>jcl-over-slf4j</artifactId>
- </dependency>
- <dependency>
- <groupId>org.slf4j</groupId>
- <artifactId>log4j-over-slf4j</artifactId>
- </dependency>
- <dependency>
- <groupId>ch.qos.logback</groupId>
- <artifactId>logback-core</artifactId>
- </dependency>
- <dependency>
- <groupId>ch.qos.logback</groupId>
- <artifactId>logback-classic</artifactId>
- </dependency>
- </dependencies>
-
- <build>
- <plugins>
- <plugin>
- <groupId>org.apache.maven.plugins</groupId>
- <artifactId>maven-jar-plugin</artifactId>
- <executions>
- <execution>
- <id>artifact-jar</id>
- <goals>
- <goal>jar</goal>
- </goals>
- </execution>
- <execution>
- <id>test-jar</id>
- <goals>
- <goal>test-jar</goal>
- </goals>
- </execution>
- </executions>
- <configuration>
- <archive>
- <manifestFile>target/classes/META-INF/MANIFEST.MF</manifestFile>
- </archive>
- </configuration>
- </plugin>
- <plugin>
- <groupId>org.apache.felix</groupId>
- <artifactId>maven-bundle-plugin</artifactId>
- <extensions>true</extensions>
- <executions>
- <execution>
- <id>bundle-manifest</id>
- <phase>process-classes</phase>
- <goals>
- <goal>manifest</goal>
- </goals>
- </execution>
- </executions>
- <configuration>
- <instructions>
- <Bundle-SymbolicName>org.eclipse.jetty.osgi.boot.logback;singleton:=true</Bundle-SymbolicName>
- <Bundle-Name>Jetty-OSGi-Logback Integration</Bundle-Name>
- <Fragment-Host>org.eclipse.jetty.osgi.boot</Fragment-Host>
- <Import-Package>
-ch.qos.logback.access.jetty;version="[0.9,1.1)";resolution:=optional,
-ch.qos.logback.access.jetty.v7;version="[0.9,1.1)";resolution:=optional,
-ch.qos.logback.*;version="[0.9,1.1)",
-org.osgi.framework.*,
-org.slf4j.*,
-*;resolution:=optional
- </Import-Package>
- <Export-Package>
-!org.eclipse.jetty.osgi.boot.logback.internal.*,
-org.eclipse.jetty.osgi.boot.logback.*;version="${parsedVersion.osgiVersion}"
- </Export-Package>
- <_nouses>true</_nouses>
- </instructions>
- </configuration>
- </plugin>
- <plugin>
- <groupId>org.codehaus.mojo</groupId>
- <artifactId>findbugs-maven-plugin</artifactId>
- <configuration>
- <onlyAnalyze>org.eclipse.jetty.osgi.boot.logback.*</onlyAnalyze>
- </configuration>
- </plugin>
- </plugins>
- </build>
-
-
-</project>
diff --git a/jetty-osgi/jetty-osgi-boot-logback/src/main/java/org/eclipse/jetty/osgi/boot/logback/FragmentActivator.java b/jetty-osgi/jetty-osgi-boot-logback/src/main/java/org/eclipse/jetty/osgi/boot/logback/FragmentActivator.java
deleted file mode 100644
index 49a57bc58c..0000000000
--- a/jetty-osgi/jetty-osgi-boot-logback/src/main/java/org/eclipse/jetty/osgi/boot/logback/FragmentActivator.java
+++ /dev/null
@@ -1,92 +0,0 @@
-//
-// ========================================================================
-// Copyright (c) 1995-2012 Mort Bay Consulting Pty. Ltd.
-// ------------------------------------------------------------------------
-// All rights reserved. This program and the accompanying materials
-// are made available under the terms of the Eclipse Public License v1.0
-// and Apache License v2.0 which accompanies this distribution.
-//
-// The Eclipse Public License is available at
-// http://www.eclipse.org/legal/epl-v10.html
-//
-// The Apache License v2.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.logback;
-
-import java.io.File;
-import java.util.Map;
-
-import org.eclipse.jetty.osgi.boot.internal.webapp.LibExtClassLoaderHelper;
-import org.eclipse.jetty.osgi.boot.internal.webapp.OSGiWebappClassLoader;
-import org.eclipse.jetty.osgi.boot.internal.webapp.LibExtClassLoaderHelper.IFilesInJettyHomeResourcesProcessor;
-import org.eclipse.jetty.osgi.boot.logback.internal.LogbackInitializer;
-import org.osgi.framework.BundleActivator;
-import org.osgi.framework.BundleContext;
-
-
-/**
- * Pseudo fragment activator.
- * Called by the main org.eclipse.jetty.osgi.boot bundle.
- * Please note: this is not a real BundleActivator. Simply something called back by
- * the host bundle.
- * The fragment is in charge of placing a hook to configure logback
- * when the files inside jettyhome/resources are parsed.
- */
-public class FragmentActivator implements BundleActivator, IFilesInJettyHomeResourcesProcessor
-{
- /**
- *
- */
- public void start(BundleContext context) throws Exception
- {
- LibExtClassLoaderHelper.registeredFilesInJettyHomeResourcesProcessors.add(this);
-
- //now let's make sure no log4j, no slf4j and no commons.logging
- //get inserted as a library that is not an osgi library
- OSGiWebappClassLoader.addClassThatIdentifiesAJarThatMustBeRejected("org.apache.commons.logging.Log");
- OSGiWebappClassLoader.addClassThatIdentifiesAJarThatMustBeRejected("org.apache.log4j.Logger");
- OSGiWebappClassLoader.addClassThatIdentifiesAJarThatMustBeRejected("org.slf4j.Logger");
- //OSGiWebappClassLoader.addClassThatIdentifiesAJarThatMustBeRejected(java.util.logging.Logger.class);
-
- }
-
- /**
- * Called when this bundle is stopped so the Framework can perform the
- * bundle-specific activities necessary to stop the bundle. In general, this
- * method should undo the work that the <code>BundleActivator.start</code>
- * method started. There should be no active threads that were started by
- * this bundle when this bundle returns. A stopped bundle must not call any
- * Framework objects.
- *
- * <p>
- * This method must complete and return to its caller in a timely manner.
- *
- * @param context The execution context of the bundle being stopped.
- * @throws Exception If this method throws an exception, the
- * bundle is still marked as stopped, and the Framework will remove
- * the bundle's listeners, unregister all services registered by the
- * bundle, and release all services used by the bundle.
- */
- public void stop(BundleContext context) throws Exception
- {
- LibExtClassLoaderHelper.registeredFilesInJettyHomeResourcesProcessors.remove(this);
- }
-
- public void processFilesInResourcesFolder(File jettyHome, Map<String,File> files)
- {
- try
- {
- LogbackInitializer.processFilesInResourcesFolder(jettyHome, files);
- }
- catch (Throwable t)
- {
- t.printStackTrace();
- }
- }
-
-}
diff --git a/jetty-osgi/jetty-osgi-boot-logback/src/main/java/org/eclipse/jetty/osgi/boot/logback/internal/LogbackInitializer.java b/jetty-osgi/jetty-osgi-boot-logback/src/main/java/org/eclipse/jetty/osgi/boot/logback/internal/LogbackInitializer.java
deleted file mode 100644
index bbab7c413d..0000000000
--- a/jetty-osgi/jetty-osgi-boot-logback/src/main/java/org/eclipse/jetty/osgi/boot/logback/internal/LogbackInitializer.java
+++ /dev/null
@@ -1,102 +0,0 @@
-//
-// ========================================================================
-// Copyright (c) 1995-2012 Mort Bay Consulting Pty. Ltd.
-// ------------------------------------------------------------------------
-// All rights reserved. This program and the accompanying materials
-// are made available under the terms of the Eclipse Public License v1.0
-// and Apache License v2.0 which accompanies this distribution.
-//
-// The Eclipse Public License is available at
-// http://www.eclipse.org/legal/epl-v10.html
-//
-// The Apache License v2.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.logback.internal;
-
-import java.io.File;
-import java.util.Map;
-
-import org.slf4j.LoggerFactory;
-
-import ch.qos.logback.classic.LoggerContext;
-import ch.qos.logback.classic.joran.JoranConfigurator;
-import ch.qos.logback.core.joran.JoranConfiguratorBase;
-import ch.qos.logback.core.joran.spi.JoranException;
-import ch.qos.logback.core.util.StatusPrinter;
-
-/**
- * Setup logback eventually located in the config file inside jettyhome/resources
- * All logback related code is done in this separate class for better debug
- * and isolation when it does not load.
- */
-public class LogbackInitializer {
-
- /**
- * @return true when we are currently being run by the pde in development mode.
- */
- private static boolean isPDEDevelopment()
- {
- String eclipseCommands = System.getProperty("eclipse.commands");
- // detect if we are being run from the pde: ie during development.
- return eclipseCommands != null && eclipseCommands.indexOf("-dev") != -1
- && (eclipseCommands.indexOf("-dev\n") != -1
- || eclipseCommands.indexOf("-dev\r") != -1
- || eclipseCommands.indexOf("-dev ") != -1);
- }
-
-
- /**
- * Follow the configuration for logback.
- * unless the system propery was set in which case it
- * was assume it was already setup.
- */
- public static void processFilesInResourcesFolder(File jettyHome, Map<String,File> files)
- {
- String logbackConf = System.getProperty("logback.configurationFile");
- if (logbackConf != null)
- {
- File confFile = new File(logbackConf);
- if (confFile.exists())
- {
- //assume logback was configured by this one?
- return;
- }
- }
-
- File logConf = isPDEDevelopment() ? files.get("logback-dev.xml") : null;
- if (logConf == null)
- {
- logConf = files.get("logback-test.xml");
- }
- if (logConf == null)
- {
- logConf = files.get("logback.xml");
- }
- if (logConf == null)
- {
- return;
- }
- // assume SLF4J is bound to logback in the current environment
- LoggerContext lc = (LoggerContext) LoggerFactory.getILoggerFactory();
-
- try
- {
- JoranConfiguratorBase configurator = new JoranConfigurator();
- configurator.setContext(lc);
- lc.reset();
- configurator.doConfigure(logConf.getAbsoluteFile().getAbsolutePath());
- }
- catch (JoranException je)
- {
- je.printStackTrace();
- }
- StatusPrinter.printIfErrorsOccured(lc);
-
- }
-
-}
diff --git a/jetty-osgi/jetty-osgi-boot-warurl/pom.xml b/jetty-osgi/jetty-osgi-boot-warurl/pom.xml
index 8ca64e39f2..92d97eb3aa 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>7.6.8-SNAPSHOT</version>
+ <version>8.1.8-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>
<modelVersion>4.0.0</modelVersion>
@@ -79,6 +79,4 @@
</plugin>
</plugins>
</build>
-
-
</project>
diff --git a/jetty-osgi/jetty-osgi-boot-warurl/pom.xml.tycho b/jetty-osgi/jetty-osgi-boot-warurl/pom.xml.tycho
deleted file mode 100644
index b30ae7a464..0000000000
--- a/jetty-osgi/jetty-osgi-boot-warurl/pom.xml.tycho
+++ /dev/null
@@ -1,14 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<project xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd" xmlns="http://maven.apache.org/POM/4.0.0"
- xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
- <modelVersion>4.0.0</modelVersion>
- <parent>
- <artifactId>jetty-osgi</artifactId>
- <version>7.0.1-SNAPSHOT</version>
- <groupId>org.eclipse.jetty.osgi</groupId>
- </parent>
- <groupId>org.eclipse.jetty.osgi</groupId>
- <artifactId>org.eclipse.jetty.osgi.boot.warurl</artifactId>
- <version>7.0.1.qualifier</version>
- <packaging>eclipse-plugin</packaging>
-</project>
diff --git a/jetty-osgi/jetty-osgi-boot/pom.xml b/jetty-osgi/jetty-osgi-boot/pom.xml
index 849d308bc5..16e586b59a 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>7.6.8-SNAPSHOT</version>
+ <version>8.1.8-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>
<modelVersion>4.0.0</modelVersion>
@@ -13,6 +13,10 @@
<bundle-symbolic-name>${project.groupId}.boot</bundle-symbolic-name>
</properties>
<dependencies>
+ <dependency>
+ <groupId>org.eclipse.jetty</groupId>
+ <artifactId>jetty-annotations</artifactId>
+ </dependency>
<dependency>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-webapp</artifactId>
@@ -114,10 +118,12 @@
javax.mail.internet;version="1.4.0";resolution:=optional,
javax.mail.search;version="1.4.0";resolution:=optional,
javax.mail.util;version="1.4.0";resolution:=optional,
- javax.servlet;version="2.5.0",
- javax.servlet.http;version="2.5.0",
+ javax.servlet;version="2.6.0",
+ javax.servlet.http;version="2.6.0",
javax.transaction;version="1.1.0";resolution:=optional,
javax.transaction.xa;version="1.1.0";resolution:=optional,
+ org.eclipse.jetty.nested;version="[8.1,9)";resolution:=optional,
+ org.eclipse.jetty.annotations;version="[8.1,9)";resolution:=optional,
org.osgi.framework,
org.osgi.service.cm;version="1.2.0",
org.osgi.service.packageadmin,
@@ -129,12 +135,11 @@
org.slf4j.helpers;resolution:=optional,
org.xml.sax,
org.xml.sax.helpers,
- org.eclipse.jetty.nested;resolution:=optional,
*
</Import-Package>
- <DynamicImport-Package>org.eclipse.jetty.*;version="[7.6,8)"</DynamicImport-Package>
+ <DynamicImport-Package>org.eclipse.jetty.*;version="[8.1,9)"</DynamicImport-Package>
<!--Require-Bundle/-->
- <!-- Bundle-RequiredExecutionEnvironment>J2SE-1.5</Bundle-RequiredExecutionEnvironment -->
+ <!-- Bundle-RequiredExecutionEnvironment>JavaSE-1.6</Bundle-RequiredExecutionEnvironment-->
</instructions>
</configuration>
</plugin>
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
new file mode 100644
index 0000000000..4005f9a397
--- /dev/null
+++ b/jetty-osgi/jetty-osgi-boot/src/main/java/org/eclipse/jetty/osgi/annotations/AnnotationConfiguration.java
@@ -0,0 +1,210 @@
+//
+// ========================================================================
+// Copyright (c) 1995-2012 Mort Bay Consulting Pty. Ltd.
+// ------------------------------------------------------------------------
+// All rights reserved. This program and the accompanying materials
+// are made available under the terms of the Eclipse Public License v1.0
+// and Apache License v2.0 which accompanies this distribution.
+//
+// The Eclipse Public License is available at
+// http://www.eclipse.org/legal/epl-v10.html
+//
+// The Apache License v2.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.annotations;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.eclipse.jetty.annotations.AbstractDiscoverableAnnotationHandler;
+import org.eclipse.jetty.annotations.AnnotationParser.DiscoverableAnnotationHandler;
+import org.eclipse.jetty.annotations.ClassNameResolver;
+import org.eclipse.jetty.osgi.boot.OSGiWebappConstants;
+import org.eclipse.jetty.osgi.boot.utils.internal.PackageAdminServiceTracker;
+import org.eclipse.jetty.util.resource.Resource;
+import org.eclipse.jetty.webapp.DiscoveredAnnotation;
+import org.eclipse.jetty.webapp.WebAppContext;
+import org.osgi.framework.Bundle;
+import org.osgi.framework.Constants;
+
+/**
+ * Extend the AnnotationConfiguration to support OSGi:
+ * Look for annotations inside WEB-INF/lib and also in the fragments and required bundles.
+ * Discover them using a scanner adapted to OSGi instead of the jarscanner.
+ */
+public class AnnotationConfiguration extends org.eclipse.jetty.annotations.AnnotationConfiguration
+{
+
+ /**
+ * This parser scans the bundles using the OSGi APIs instead of assuming a jar.
+ */
+ @Override
+ protected org.eclipse.jetty.annotations.AnnotationParser createAnnotationParser()
+ {
+ return new AnnotationParser();
+ }
+
+ /**
+ * Here is the order in which jars and osgi artifacts are scanned for discoverable annotations.
+ * <ol>
+ * <li>The container jars are scanned.</li>
+ * <li>The WEB-INF/classes are scanned</li>
+ * <li>The osgi fragment to the web bundle are parsed.</li>
+ * <li>The WEB-INF/lib are scanned</li>
+ * <li>The required bundles are parsed</li>
+ * </ol>
+ */
+ @Override
+ public void parseWebInfLib (WebAppContext context, org.eclipse.jetty.annotations.AnnotationParser parser)
+ throws Exception
+ {
+ AnnotationParser oparser = (AnnotationParser)parser;
+
+ Bundle webbundle = (Bundle) context.getAttribute(OSGiWebappConstants.JETTY_OSGI_BUNDLE);
+ Bundle[] fragAndRequiredBundles = PackageAdminServiceTracker.INSTANCE.getFragmentsAndRequiredBundles(webbundle);
+ if (fragAndRequiredBundles != null)
+ {
+ //index:
+ for (Bundle bundle : fragAndRequiredBundles)
+ {
+ Resource bundleRes = oparser.indexBundle(bundle);
+ if (!context.getMetaData().getWebInfJars().contains(bundleRes))
+ {
+ context.getMetaData().addWebInfJar(bundleRes);
+ }
+ }
+
+ //scan the fragments
+ for (Bundle fragmentBundle : fragAndRequiredBundles)
+ {
+ if (fragmentBundle.getHeaders().get(Constants.FRAGMENT_HOST) != null)
+ {
+ //a fragment indeed:
+ parseFragmentBundle(context,oparser,webbundle,fragmentBundle);
+ }
+ }
+ }
+ //scan ourselves
+ parseWebBundle(context,oparser,webbundle);
+
+ //scan the WEB-INF/lib
+ super.parseWebInfLib(context,parser);
+ if (fragAndRequiredBundles != null)
+ {
+ //scan the required bundles
+ for (Bundle requiredBundle : fragAndRequiredBundles)
+ {
+ if (requiredBundle.getHeaders().get(Constants.FRAGMENT_HOST) == null)
+ {
+ //a bundle indeed:
+ parseRequiredBundle(context,oparser,webbundle,requiredBundle);
+ }
+ }
+ }
+ }
+
+ /**
+ * Scan a fragment bundle for servlet annotations
+ * @param context The webapp context
+ * @param parser The parser
+ * @param webbundle The current webbundle
+ * @param fragmentBundle The OSGi fragment bundle to scan
+ * @throws Exception
+ */
+ protected void parseFragmentBundle(WebAppContext context, AnnotationParser parser,
+ Bundle webbundle, Bundle fragmentBundle) throws Exception
+ {
+ parseBundle(context,parser,webbundle,fragmentBundle);
+ }
+
+ /**
+ * Scan a bundle required by the webbundle for servlet annotations
+ * @param context The webapp context
+ * @param parser The parser
+ * @param webbundle The current webbundle
+ * @param fragmentBundle The OSGi required bundle to scan
+ * @throws Exception
+ */
+ protected void parseWebBundle(WebAppContext context, AnnotationParser parser, Bundle webbundle)
+ throws Exception
+ {
+ parseBundle(context,parser,webbundle,webbundle);
+ }
+
+ /**
+ * Scan a bundle required by the webbundle for servlet annotations
+ * @param context The webapp context
+ * @param parser The parser
+ * @param webbundle The current webbundle
+ * @param fragmentBundle The OSGi required bundle to scan
+ * @throws Exception
+ */
+ protected void parseRequiredBundle(WebAppContext context, AnnotationParser parser,
+ Bundle webbundle, Bundle requiredBundle) throws Exception
+ {
+ parseBundle(context,parser,webbundle,requiredBundle);
+ }
+
+ protected void parseBundle(WebAppContext context, AnnotationParser parser,
+ Bundle webbundle, Bundle bundle) throws Exception
+ {
+
+ Resource bundleRes = parser.getResource(bundle);
+
+ parser.clearHandlers();
+ for (DiscoverableAnnotationHandler h:_discoverableAnnotationHandlers)
+ {
+ if (h instanceof AbstractDiscoverableAnnotationHandler)
+ {
+ if (webbundle == bundle)
+ ((AbstractDiscoverableAnnotationHandler)h).setResource(null);
+ else
+ ((AbstractDiscoverableAnnotationHandler)h).setResource(bundleRes);
+ }
+ }
+ parser.registerHandlers(_discoverableAnnotationHandlers);
+ parser.registerHandler(_classInheritanceHandler);
+ parser.registerHandlers(_containerInitializerAnnotationHandlers);
+
+ parser.parse(bundle,createClassNameResolver(context));
+ }
+
+ /**
+ * Returns the same classname resolver than for the webInfjar scanner
+ * @param context
+ * @return
+ */
+ protected ClassNameResolver createClassNameResolver(final WebAppContext context)
+ {
+ return createClassNameResolver(context,true,false,false,false);
+ }
+
+ protected ClassNameResolver createClassNameResolver(final WebAppContext context,
+ final boolean excludeSysClass, final boolean excludeServerClass, final boolean excludeEverythingElse,
+ final boolean overrideIsParenLoaderIsPriority)
+ {
+ return new ClassNameResolver ()
+ {
+ public boolean isExcluded (String name)
+ {
+ if (context.isSystemClass(name)) return excludeSysClass;
+ if (context.isServerClass(name)) return excludeServerClass;
+ return excludeEverythingElse;
+ }
+
+ public boolean shouldOverride (String name)
+ {
+ //looking at system classpath
+ if (context.isParentLoaderPriority())
+ return overrideIsParenLoaderIsPriority;
+ return !overrideIsParenLoaderIsPriority;
+ }
+ };
+ }
+
+}
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
new file mode 100644
index 0000000000..2142253dc1
--- /dev/null
+++ b/jetty-osgi/jetty-osgi-boot/src/main/java/org/eclipse/jetty/osgi/annotations/AnnotationParser.java
@@ -0,0 +1,197 @@
+//
+// ========================================================================
+// Copyright (c) 1995-2012 Mort Bay Consulting Pty. Ltd.
+// ------------------------------------------------------------------------
+// All rights reserved. This program and the accompanying materials
+// are made available under the terms of the Eclipse Public License v1.0
+// and Apache License v2.0 which accompanies this distribution.
+//
+// The Eclipse Public License is available at
+// http://www.eclipse.org/legal/epl-v10.html
+//
+// The Apache License v2.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.annotations;
+
+import java.io.File;
+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;
+
+import org.eclipse.jetty.annotations.ClassNameResolver;
+import org.eclipse.jetty.osgi.boot.utils.BundleFileLocatorHelper;
+import org.eclipse.jetty.util.resource.Resource;
+import org.osgi.framework.Bundle;
+import org.osgi.framework.Constants;
+
+/**
+ *
+ */
+public class AnnotationParser extends org.eclipse.jetty.annotations.AnnotationParser
+{
+ private Set<URI> _alreadyParsed = new HashSet<URI>();
+
+ private Map<URI,Bundle> _uriToBundle = new HashMap<URI, Bundle>();
+ private Map<Bundle,Resource> _resourceToBundle = new HashMap<Bundle,Resource>();
+ private Map<Bundle,URI> _bundleToUri = new HashMap<Bundle, URI>();
+
+ /**
+ * Keep track of a jetty URI Resource and its associated OSGi bundle.
+ * @param uri
+ * @param bundle
+ * @throws Exception
+ */
+ protected Resource indexBundle(Bundle bundle) throws Exception
+ {
+ File bundleFile = BundleFileLocatorHelper.DEFAULT.getBundleInstallLocation(bundle);
+ Resource resource = Resource.newResource(bundleFile.toURI());
+ URI uri = resource.getURI();
+ _uriToBundle.put(uri,bundle);
+ _bundleToUri.put(bundle,uri);
+ _resourceToBundle.put(bundle,resource);
+ return resource;
+ }
+ protected URI getURI(Bundle bundle)
+ {
+ return _bundleToUri.get(bundle);
+ }
+ protected Resource getResource(Bundle bundle)
+ {
+ return _resourceToBundle.get(bundle);
+ }
+ /**
+ *
+ */
+ @Override
+ public void parse (URI[] uris, ClassNameResolver resolver)
+ throws Exception
+ {
+ for (URI uri : uris)
+ {
+ Bundle associatedBundle = _uriToBundle.get(uri);
+ if (associatedBundle == null)
+ {
+ if (!_alreadyParsed.add(uri))
+ {
+ continue;
+ }
+ //a jar in WEB-INF/lib or the WEB-INF/classes
+ //use the behavior of the super class for a standard jar.
+ super.parse(new URI[] {uri},resolver);
+ }
+ else
+ {
+ parse(associatedBundle,resolver);
+ }
+ }
+ }
+
+ protected void parse(Bundle bundle, ClassNameResolver resolver)
+ throws Exception
+ {
+ URI uri = _bundleToUri.get(bundle);
+ if (!_alreadyParsed.add(uri))
+ {
+ return;
+ }
+
+ String bundleClasspath = (String)bundle.getHeaders().get(Constants.BUNDLE_CLASSPATH);
+ if (bundleClasspath == null)
+ {
+ bundleClasspath = ".";
+ }
+ //order the paths first by the number of tokens in the path second alphabetically.
+ TreeSet<String> paths = new TreeSet<String>(
+ new Comparator<String>()
+ {
+ public int compare(String o1, String o2)
+ {
+ int paths1 = new StringTokenizer(o1,"/",false).countTokens();
+ int paths2 = new StringTokenizer(o2,"/",false).countTokens();
+ if (paths1 == paths2)
+ {
+ return o1.compareTo(o2);
+ }
+ return paths2 - paths1;
+ }
+ });
+ boolean hasDotPath = false;
+ StringTokenizer tokenizer = new StringTokenizer(bundleClasspath, ",;", false);
+ while (tokenizer.hasMoreTokens())
+ {
+ String token = tokenizer.nextToken().trim();
+ if (!token.startsWith("/"))
+ {
+ token = "/" + token;
+ }
+ if (token.equals("/."))
+ {
+ hasDotPath = true;
+ }
+ else if (!token.endsWith(".jar") && !token.endsWith("/"))
+ {
+ paths.add(token+"/");
+ }
+ else
+ {
+ paths.add(token);
+ }
+ }
+ //support the development environment: maybe the classes are inside bin or target/classes
+ //this is certainly not useful in production.
+ //however it makes our life so much easier during development.
+ if (bundle.getEntry("/.classpath") != null)
+ {
+ if (bundle.getEntry("/bin/") != null)
+ {
+ paths.add("/bin/");
+ }
+ else if (bundle.getEntry("/target/classes/") != null)
+ {
+ paths.add("/target/classes/");
+ }
+ }
+ Enumeration classes = bundle.findEntries("/","*.class",true);
+ if (classes == null)
+ {
+ return;
+ }
+ while (classes.hasMoreElements())
+ {
+ URL classUrl = (URL) classes.nextElement();
+ String path = classUrl.getPath();
+ //remove the longest path possible:
+ String name = null;
+ for (String prefixPath : paths)
+ {
+ if (path.startsWith(prefixPath))
+ {
+ name = path.substring(prefixPath.length());
+ break;
+ }
+ }
+ if (name == null && hasDotPath)
+ {
+ //remove the starting '/'
+ name = path.substring(1);
+ }
+ //transform into a classname to pass to the resolver
+ String shortName = name.replace('/', '.').substring(0,name.length()-6);
+ if ((resolver == null)|| (!resolver.isExcluded(shortName) && (!isParsed(shortName) || resolver.shouldOverride(shortName))))
+ scanClass(classUrl.openStream());
+ }
+ }
+
+}
diff --git a/jetty-osgi/jetty-osgi-boot/src/main/java/org/eclipse/jetty/osgi/boot/internal/jsp/TldLocatableURLClassloader.java b/jetty-osgi/jetty-osgi-boot/src/main/java/org/eclipse/jetty/osgi/boot/internal/jsp/TldLocatableURLClassloader.java
index ad23673df3..7f6c6288ac 100644
--- a/jetty-osgi/jetty-osgi-boot/src/main/java/org/eclipse/jetty/osgi/boot/internal/jsp/TldLocatableURLClassloader.java
+++ b/jetty-osgi/jetty-osgi-boot/src/main/java/org/eclipse/jetty/osgi/boot/internal/jsp/TldLocatableURLClassloader.java
@@ -48,4 +48,18 @@ public class TldLocatableURLClassloader extends URLClassLoader
{
return _jarsWithTldsInside;
}
+
+ public String toString()
+ {
+ StringBuilder builder = new StringBuilder();
+
+ if (_jarsWithTldsInside != null)
+ {
+ for (URL u:_jarsWithTldsInside)
+ builder.append(" "+u.toString());
+ return builder.toString();
+ }
+ else
+ return super.toString();
+ }
}
diff --git a/jetty-osgi/jetty-osgi-boot/src/main/java/org/eclipse/jetty/osgi/boot/utils/internal/PackageAdminServiceTracker.java b/jetty-osgi/jetty-osgi-boot/src/main/java/org/eclipse/jetty/osgi/boot/utils/internal/PackageAdminServiceTracker.java
index c386626441..7b5b86cc8d 100644
--- a/jetty-osgi/jetty-osgi-boot/src/main/java/org/eclipse/jetty/osgi/boot/utils/internal/PackageAdminServiceTracker.java
+++ b/jetty-osgi/jetty-osgi-boot/src/main/java/org/eclipse/jetty/osgi/boot/utils/internal/PackageAdminServiceTracker.java
@@ -380,3 +380,4 @@ public class PackageAdminServiceTracker implements ServiceListener
}
}
+
diff --git a/jetty-osgi/jetty-osgi-equinoxtools/build.properties b/jetty-osgi/jetty-osgi-equinoxtools/build.properties
deleted file mode 100644
index 05786b032b..0000000000
--- a/jetty-osgi/jetty-osgi-equinoxtools/build.properties
+++ /dev/null
@@ -1,5 +0,0 @@
-source.. = src/
-output.. = bin/
-bin.includes = META-INF/,\
- equinoxconsole/,\
- .
diff --git a/jetty-osgi/jetty-osgi-equinoxtools/equinoxconsole/index.html b/jetty-osgi/jetty-osgi-equinoxtools/equinoxconsole/index.html
deleted file mode 100644
index 4deba32c28..0000000000
--- a/jetty-osgi/jetty-osgi-equinoxtools/equinoxconsole/index.html
+++ /dev/null
@@ -1,85 +0,0 @@
-<html><head>
- <title>Async Equinox Console</title>
- <script type='text/javascript'>
- function $() { return document.getElementById(arguments[0]); }
- function $F() { return document.getElementById(arguments[0]).value; }
- function getKeyCode(ev) { if (window.event) return window.event.keyCode; return ev.keyCode; }
- function xhr(method,uri,body,handler) {
- var req=(window.XMLHttpRequest)?new XMLHttpRequest():new ActiveXObject('Microsoft.XMLHTTP');
- req.onreadystatechange=function() { if (req.readyState==4 && handler) { eval('var o='+req.responseText);handler(o);} }
- req.open(method,uri,true);
- req.setRequestHeader('Content-Type','application/x-www-form-urlencoded');
- req.send(body);
- };
- function send(action,user,message,handler){
- if (message) message=message.replace('%','%25').replace('&','%26').replace('=','%3D');
- if (user) user=user.replace('%','%25').replace('&','%26').replace('=','%3D');
- xhr('POST','chat','action='+action+'&user='+user+'&message='+message,handler);
- };
-
- var room = {
- join: function(name) {
- this._username=name;
- $('join').className='hidden';
- $('joined').className='';
- $('phrase').focus();
- send('join', room._username,null);
- send('chat', room._username,'has joined!');
- send('poll', room._username,null, room._poll);
- },
- chat: function(text) {
- if (text != null && text.length>0 )
- send('chat',room._username,text);
- },
- _poll: function(m) {
- //console.debug(m);
- if (m.chat){
- var chat=document.getElementById('chat');
- var spanFrom = document.createElement('span');
- spanFrom.className='from';
- spanFrom.innerHTML=m.from+'&nbsp;';
- var spanText = document.createElement('span');
- spanText.className='text';
- spanText.innerHTML=m.chat;
- var lineBreak = document.createElement('br');
- chat.appendChild(spanFrom);
- chat.appendChild(spanText);
- chat.appendChild(lineBreak);
- chat.scrollTop = chat.scrollHeight - chat.clientHeight;
- }
- if (m.action=='poll')
- send('poll', room._username,null, room._poll);
- },
- _end:''
- };
- </script>
- <style type='text/css'>
- div { border: 0px solid black; }
- div#chat { clear: both; width: 40em; height: 20ex; overflow: auto; background-color: #f0f0f0; padding: 4px; border: 1px solid black; }
- div#input { clear: both; width: 40em; padding: 4px; background-color: #e0e0e0; border: 1px solid black; border-top: 0px }
- input#phrase { width:30em; background-color: #e0f0f0; }
- input#username { width:14em; background-color: #e0f0f0; }
- div.hidden { display: none; }
- span.from { font-weight: bold; }
- span.alert { font-style: italic; }
- </style>
-</head><body>
-<div id='chat'></div>
-<div id='input'>
- <div id='join' >
- Username:&nbsp;<input id='username' type='text'/><input id='joinB' class='button' type='submit' name='join' value='Join'/>
- </div>
- <div id='joined' class='hidden'>
- OSGi:&nbsp;<input id='phrase' type='text'/>
- <input id='sendB' class='button' type='submit' name='join' value='Send'/>
- </div>
-</div>
-<script type='text/javascript'>
-$('username').setAttribute('autocomplete','OFF');
-$('username').onkeyup = function(ev) { var keyc=getKeyCode(ev); if (keyc==13 || keyc==10) { room.join($F('username')); return false; } return true; } ;
-$('joinB').onclick = function(event) { room.join($F('username')); return false; };
-$('phrase').setAttribute('autocomplete','OFF');
-$('phrase').onkeyup = function(ev) { var keyc=getKeyCode(ev); if (keyc==13 || keyc==10) { room.chat($F('phrase')); $('phrase').value=''; return false; } return true; };
-$('sendB').onclick = function(event) { room.chat($F('phrase')); $('phrase').value=''; return false; };
-</script>
-</body></html>
diff --git a/jetty-osgi/jetty-osgi-equinoxtools/equinoxconsole/ws/index.html b/jetty-osgi/jetty-osgi-equinoxtools/equinoxconsole/ws/index.html
deleted file mode 100644
index 4d5acc96d7..0000000000
--- a/jetty-osgi/jetty-osgi-equinoxtools/equinoxconsole/ws/index.html
+++ /dev/null
@@ -1,109 +0,0 @@
-<html><head>
- <title>Equinox Console (WebSocket)</title>
- <script type='text/javascript'>
-
- if (!window.WebSocket)
- alert("WebSocket not supported by this browser");
-
- function $() { return document.getElementById(arguments[0]); }
- function $F() { return document.getElementById(arguments[0]).value; }
-
- function getKeyCode(ev) { if (window.event) return window.event.keyCode; return ev.keyCode; }
-
- var room = {
- join: function(name) {
- this._username=name;
- var location = document.location.toString().replace('http://','ws://').replace('https://','wss://').replace('/index.html','');
- this._ws=new WebSocket(location);
- this._ws.onopen=this._onopen;
- this._ws.onmessage=this._onmessage;
- this._ws.onclose=this._onclose;
- },
-
- _onopen: function(){
- $('join').className='hidden';
- $('joined').className='';
- $('phrase').focus();
- room._send(room._username,'has joined!');
- },
-
- _send: function(user,message){
- user=user.replace(':','_');
- if (this._ws)
- this._ws.send(user+':'+message);
- },
-
- chat: function(text) {
- if (text != null && text.length>0 )
- room._send(room._username,text);
- },
-
- _onmessage: function(m) {
- if (m.data){
- var c=m.data.indexOf(':');
- var from=m.data.substring(0,c).replace('<','&lt;').replace('>','&gt;');
- var text=m.data.substring(c+1).replace('<','&lt;').replace('>','&gt;');
-
- var chat=$('chat');
- var spanFrom = document.createElement('span');
- spanFrom.className='from';
- spanFrom.innerHTML=from+':&nbsp;';
- var spanText = document.createElement('span');
- spanText.className='text';
- spanText.innerHTML=text;
- var lineBreak = document.createElement('br');
- chat.appendChild(spanFrom);
- chat.appendChild(spanText);
- chat.appendChild(lineBreak);
- chat.scrollTop = chat.scrollHeight - chat.clientHeight;
- }
- },
-
- _onclose: function(m) {
- this._ws=null;
- $('join').className='';
- $('joined').className='hidden';
- $('username').focus();
- $('chat').innerHTML='';
- }
-
- };
-
- </script>
- <style type='text/css'>
- div { border: 0px solid black; }
- div#chat { clear: both; width: 40em; height: 20ex; overflow: auto; background-color: #f0f0f0; padding: 4px; border: 1px solid black; }
- div#input { clear: both; width: 40em; padding: 4px; background-color: #e0e0e0; border: 1px solid black; border-top: 0px }
- input#phrase { width:30em; background-color: #e0f0f0; }
- input#username { width:14em; background-color: #e0f0f0; }
- div.hidden { display: none; }
- span.from { font-weight: bold; }
- span.alert { font-style: italic; }
- </style>
-</head><body>
-<div id='chat'></div>
-<div id='input'>
- <div id='join' >
- Username:&nbsp;<input id='username' type='text'/><input id='joinB' class='button' type='submit' name='join' value='Join'/>
- </div>
- <div id='joined' class='hidden'>
- Chat:&nbsp;<input id='phrase' type='text'/>
- <input id='sendB' class='button' type='submit' name='join' value='Send'/>
- </div>
-</div>
-<script type='text/javascript'>
-$('username').setAttribute('autocomplete','OFF');
-$('username').onkeyup = function(ev) { var keyc=getKeyCode(ev); if (keyc==13 || keyc==10) { room.join($F('username')); return false; } return true; } ;
-$('joinB').onclick = function(event) { room.join($F('username')); return false; };
-$('phrase').setAttribute('autocomplete','OFF');
-$('phrase').onkeyup = function(ev) { var keyc=getKeyCode(ev); if (keyc==13 || keyc==10) { room.chat($F('phrase')); $('phrase').value=''; return false; } return true; };
-$('sendB').onclick = function(event) { room.chat($F('phrase')); $('phrase').value=''; return false; };
-</script>
-
-<p>
-This is a demonstration of the Jetty websocket server.
-</p>
-</body></html>
-
-
-
diff --git a/jetty-osgi/jetty-osgi-equinoxtools/pom.xml b/jetty-osgi/jetty-osgi-equinoxtools/pom.xml
deleted file mode 100644
index 84e8bf683d..0000000000
--- a/jetty-osgi/jetty-osgi-equinoxtools/pom.xml
+++ /dev/null
@@ -1,120 +0,0 @@
-<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.osgi</groupId>
- <artifactId>jetty-osgi-project</artifactId>
- <version>7.6.8-SNAPSHOT</version>
- <relativePath>../pom.xml</relativePath>
- </parent>
- <modelVersion>4.0.0</modelVersion>
- <artifactId>jetty-osgi-equinoxtools</artifactId>
- <name>Jetty :: OSGi :: Example Equinox Tools</name>
- <description>Jetty OSGi Example Equinox Tools</description>
- <properties>
- <bundle-symbolic-name>${project.groupId}.equinoxtools</bundle-symbolic-name>
- </properties>
- <dependencies>
- <dependency>
- <groupId>org.eclipse.jetty</groupId>
- <artifactId>jetty-webapp</artifactId>
- </dependency>
- <dependency>
- <groupId>org.eclipse.jetty</groupId>
- <artifactId>jetty-continuation</artifactId>
- </dependency>
- <dependency>
- <groupId>org.eclipse.jetty</groupId>
- <artifactId>jetty-websocket</artifactId>
- </dependency>
- <dependency>
- <groupId>org.eclipse.jetty</groupId>
- <artifactId>jetty-servlet</artifactId>
- </dependency>
- <dependency>
- <groupId>org.eclipse.osgi</groupId>
- <artifactId>org.eclipse.osgi</artifactId>
- </dependency>
- <dependency>
- <groupId>org.eclipse.osgi</groupId>
- <artifactId>org.eclipse.osgi.services</artifactId>
- </dependency>
- </dependencies>
-
- <build>
- <plugins>
- <plugin>
- <artifactId>maven-antrun-plugin</artifactId>
- <executions>
- <execution>
- <phase>process-resources</phase>
- <configuration>
- <tasks>
- <copy todir="target/classes/equinoxconsole">
- <fileset dir="equinoxconsole" />
- </copy>
- </tasks>
- </configuration>
- <goals>
- <goal>run</goal>
- </goals>
- </execution>
- </executions>
- </plugin>
- <plugin>
- <groupId>org.apache.maven.plugins</groupId>
- <artifactId>maven-jar-plugin</artifactId>
- <executions>
- <execution>
- <id>artifact-jar</id>
- <goals>
- <goal>jar</goal>
- </goals>
- </execution>
- <execution>
- <id>test-jar</id>
- <goals>
- <goal>test-jar</goal>
- </goals>
- </execution>
- </executions>
- <configuration>
- <archive>
- <manifestFile>target/classes/META-INF/MANIFEST.MF</manifestFile>
- </archive>
- </configuration>
- </plugin>
- <plugin>
- <groupId>org.apache.felix</groupId>
- <artifactId>maven-bundle-plugin</artifactId>
- <extensions>true</extensions>
- <executions>
- <execution>
- <id>bundle-manifest</id>
- <phase>process-classes</phase>
- <goals>
- <goal>manifest</goal>
- </goals>
- </execution>
- </executions>
- <configuration>
- <instructions>
- <Bundle-SymbolicName>org.eclipse.jetty.osgi.equinoxtools</Bundle-SymbolicName>
- <Bundle-Name>Console</Bundle-Name>
- <Bundle-Activator>org.eclipse.jetty.osgi.equinoxtools.WebEquinoxToolsActivator</Bundle-Activator>
- <Export-Package>org.eclipse.jetty.osgi.equinoxtools;x-internal:=true;version="${parsedVersion.osgiVersion}",
- org.eclipse.jetty.osgi.equinoxtools.console;x-internal:=true;version="${parsedVersion.osgiVersion}"
- </Export-Package>
- <_nouses>true</_nouses>
- </instructions>
- </configuration>
- </plugin>
- <plugin>
- <groupId>org.codehaus.mojo</groupId>
- <artifactId>findbugs-maven-plugin</artifactId>
- <configuration>
- <onlyAnalyze>org.eclipse.jetty.osgi.equinoxtools.*</onlyAnalyze>
- </configuration>
- </plugin>
- </plugins>
- </build>
-
-</project>
diff --git a/jetty-osgi/jetty-osgi-equinoxtools/src/main/java/org/eclipse/jetty/osgi/equinoxtools/WebEquinoxToolsActivator.java b/jetty-osgi/jetty-osgi-equinoxtools/src/main/java/org/eclipse/jetty/osgi/equinoxtools/WebEquinoxToolsActivator.java
deleted file mode 100644
index d4bc6d7013..0000000000
--- a/jetty-osgi/jetty-osgi-equinoxtools/src/main/java/org/eclipse/jetty/osgi/equinoxtools/WebEquinoxToolsActivator.java
+++ /dev/null
@@ -1,133 +0,0 @@
-//
-// ========================================================================
-// Copyright (c) 1995-2012 Mort Bay Consulting Pty. Ltd.
-// ------------------------------------------------------------------------
-// All rights reserved. This program and the accompanying materials
-// are made available under the terms of the Eclipse Public License v1.0
-// and Apache License v2.0 which accompanies this distribution.
-//
-// The Eclipse Public License is available at
-// http://www.eclipse.org/legal/epl-v10.html
-//
-// The Apache License v2.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.equinoxtools;
-
-import javax.servlet.ServletException;
-
-import org.eclipse.jetty.osgi.equinoxtools.console.EquinoxChattingSupport;
-import org.eclipse.jetty.osgi.equinoxtools.console.EquinoxConsoleContinuationServlet;
-import org.eclipse.jetty.osgi.equinoxtools.console.EquinoxConsoleSyncServlet;
-import org.eclipse.jetty.osgi.equinoxtools.console.EquinoxConsoleWebSocketServlet;
-import org.eclipse.jetty.osgi.equinoxtools.console.WebConsoleSession;
-import org.eclipse.jetty.util.log.Log;
-import org.eclipse.jetty.util.log.Logger;
-import org.eclipse.osgi.framework.console.ConsoleSession;
-import org.osgi.framework.BundleActivator;
-import org.osgi.framework.BundleContext;
-import org.osgi.framework.ServiceReference;
-import org.osgi.service.http.HttpService;
-import org.osgi.service.http.NamespaceException;
-import org.osgi.util.tracker.ServiceTracker;
-import org.osgi.util.tracker.ServiceTrackerCustomizer;
-
-/**
- * When started will register on the HttpService 3 servlets for 3 different styles of equinox consoles.
- */
-public class WebEquinoxToolsActivator implements BundleActivator
-{
- private static final Logger LOG = Log.getLogger(WebEquinoxToolsActivator.class);
-
-
- private static BundleContext context;
- public static BundleContext getContext()
- {
- return context;
- }
-
- private HttpService _httpService;
- private ServiceTracker _tracker;
- private EquinoxChattingSupport _equinoxChattingSupport;
-
-
- /*
- * (non-Javadoc)
- *
- * @see org.osgi.framework.BundleActivator#start(org.osgi.framework.BundleContext)
- */
- public void start(BundleContext bundleContext) throws Exception
- {
- WebEquinoxToolsActivator.context = bundleContext;
-
- ServiceTrackerCustomizer httpServiceTrackerCustomizer = new ServiceTrackerCustomizer()
- {
- public void removedService(ServiceReference reference, Object service)
- {
- _httpService = null;
- }
-
- public void modifiedService(ServiceReference reference, Object service)
- {
- _httpService = (HttpService)context.getService(reference);
- }
-
- public Object addingService(ServiceReference reference)
- {
- _httpService = (HttpService)context.getService(reference);
- try
- {
- //TODO; some effort to use the same console session on the 2 async console servlets?
-
- //websocket:
-// WebConsoleSession wsSession = new WebConsoleSession();
-// WebEquinoxConsoleActivator.context.registerService(ConsoleSession.class.getName(), wsSession, null);
-// EquinoxChattingSupport wsEquinoxChattingSupport = new EquinoxChattingSupport(wsSession);
- _httpService.registerResources("/equinoxconsole/ws/index.html","/equinoxconsole/ws/index.html",null);
- _httpService.registerServlet("/equinoxconsole/ws",new EquinoxConsoleWebSocketServlet(/*wsSession, wsEquinoxChattingSupport*/),null,null);
-
- //continuations:
-// WebConsoleSession contSession = new WebConsoleSession();
-// WebEquinoxConsoleActivator.context.registerService(ConsoleSession.class.getName(), contSession, null);
-// EquinoxChattingSupport contEquinoxChattingSupport = new EquinoxChattingSupport(contSession);
- _httpService.registerResources("/equinoxconsole/index.html","/equinoxconsole/index.html",null);
- _httpService.registerServlet("/equinoxconsole",new EquinoxConsoleContinuationServlet(/*contSession, contEquinoxChattingSupport*/),null,null);
-
- //legacy synchroneous; keep it in a separate console session.
- WebConsoleSession syncSession = new WebConsoleSession();
- WebEquinoxToolsActivator.context.registerService(ConsoleSession.class.getName(), syncSession, null);
- _httpService.registerServlet("/equinoxconsole/sync",new EquinoxConsoleSyncServlet(syncSession),null,null);
- }
- catch (ServletException e)
- {
- LOG.warn(e);
- }
- catch (NamespaceException e)
- {
- LOG.warn(e);
- }
- return _httpService;
- }
- };
-
- _tracker = new ServiceTracker(context,HttpService.class.getName(),httpServiceTrackerCustomizer);
- _tracker.open();
- }
-
- /*
- * (non-Javadoc)
- *
- * @see org.osgi.framework.BundleActivator#stop(org.osgi.framework.BundleContext)
- */
- public void stop(BundleContext bundleContext) throws Exception
- {
- _tracker.close();
- WebEquinoxToolsActivator.context = null;
- }
-
-
-}
diff --git a/jetty-osgi/jetty-osgi-equinoxtools/src/main/java/org/eclipse/jetty/osgi/equinoxtools/console/EquinoxChattingSupport.java b/jetty-osgi/jetty-osgi-equinoxtools/src/main/java/org/eclipse/jetty/osgi/equinoxtools/console/EquinoxChattingSupport.java
deleted file mode 100644
index 4211243555..0000000000
--- a/jetty-osgi/jetty-osgi-equinoxtools/src/main/java/org/eclipse/jetty/osgi/equinoxtools/console/EquinoxChattingSupport.java
+++ /dev/null
@@ -1,156 +0,0 @@
-//
-// ========================================================================
-// Copyright (c) 1995-2012 Mort Bay Consulting Pty. Ltd.
-// ------------------------------------------------------------------------
-// All rights reserved. This program and the accompanying materials
-// are made available under the terms of the Eclipse Public License v1.0
-// and Apache License v2.0 which accompanies this distribution.
-//
-// The Eclipse Public License is available at
-// http://www.eclipse.org/legal/epl-v10.html
-//
-// The Apache License v2.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.equinoxtools.console;
-
-import java.util.LinkedList;
-import java.util.Queue;
-
-import org.eclipse.jetty.osgi.equinoxtools.console.WebConsoleWriterOutputStream.OnFlushListener;
-
-/**
- * Processing of the messages to be received and sent to the chat servlets.
- * Made to be extended for filtering of the messages and commands.
- */
-public class EquinoxChattingSupport
-{
-
- private WebConsoleSession _consoleSession;
-
- public EquinoxChattingSupport(WebConsoleSession consoleSession)
- {
- _consoleSession = consoleSession;
- }
-
- /**
- * Split the output into multiple lines.
- * Format them for the json messages sent to the chat.
- * Empties the console output from what is already displayed in the chat.
- * @return The lines to add to the message queue of each client.
- */
- protected Queue<String> processConsoleOutput(boolean escape, OnFlushListener onflush)
- {
- Queue<String> result = new LinkedList<String>();
- String toDisplay = _consoleSession.getOutputAsWriter().getBuffer().toString();
- //the last listener to be called is in charge of clearing the console.
- boolean clearConsole = _consoleSession.getOnFlushListeners().indexOf(onflush) == _consoleSession.getOnFlushListeners().size();
- if (clearConsole)
- {
- _consoleSession.clearOutput();
- }
- boolean lastLineIsComplete = toDisplay.endsWith("\n") || toDisplay.endsWith("\r");
- String[] lines = toDisplay.split("\n");
- String lastLine = lastLineIsComplete ? null : lines[lines.length-1];
- if (clearConsole)
- {
- _consoleSession.getOutputAsWriter().append(lastLine);
- }
- for (int lnNb = 0; lnNb < (lastLineIsComplete ? lines.length : lines.length-1); lnNb++)
- {
- String line = lines[lnNb];
- while (line.trim().startsWith("null"))
- {//hum..
- line = line.trim().substring("null".length()).trim();
- }
- if (line.startsWith("osgi>"))
- {
- result.add("osgi>");
- result.add(escape ? jsonEscapeString(line.substring("osgi>".length())) : line.substring("osgi>".length()));
- }
- else
- {
- result.add("&#10;");
- result.add(escape ? jsonEscapeString(line) : line);
- }
- }
- return result;
- }
-
- /**
- * http://www.ietf.org/rfc/rfc4627.txt
- * @param str
- * @return The same string escaped according to the JSON RFC.
- */
- public static String jsonEscapeString(String str)
- {
- StringBuilder sb = new StringBuilder();
- char[] asChars = str.toCharArray();
- for (char ch : asChars)
- {
- switch (ch)
- {
- //the reserved characters
- case '"':
- sb.append("\\\"");
- break;
- case '\\':
- sb.append("\\\\");
- break;
- case '\b':
- sb.append("\\b");
- break;
- case '\f':
- sb.append("\\f");
- break;
- case '\n':
- sb.append("\\n");
- break;
- case '\r':
- sb.append("\\r");
- break;
- case '\t':
- sb.append("\\t");
- break;
- case '/':
- sb.append("\\/");
- break;
- default:
- //The non reserved characters
- if (ch >= '\u0000' && ch <= '\u001F')
- {
- //escape as a unicode number when out of range.
- String ss = Integer.toHexString(ch);
- sb.append("\\u");
- for (int i = 0; i < 4 - ss.length(); i++)
- {
- //padding
- sb.append('0');
- }
- sb.append(ss.toUpperCase());
- }
- else
- {
- sb.append(ch);
- }
- }
- }
- return sb.toString();
- }
-
- public void broadcast(OnFlushListener source)
- {
- for (OnFlushListener onflush : _consoleSession.getOnFlushListeners())
- {
- if (onflush != source)
- {
- onflush.onFlush();
- }
- }
- }
-
-}
diff --git a/jetty-osgi/jetty-osgi-equinoxtools/src/main/java/org/eclipse/jetty/osgi/equinoxtools/console/EquinoxConsoleContinuationServlet.java b/jetty-osgi/jetty-osgi-equinoxtools/src/main/java/org/eclipse/jetty/osgi/equinoxtools/console/EquinoxConsoleContinuationServlet.java
deleted file mode 100644
index ab08af70fc..0000000000
--- a/jetty-osgi/jetty-osgi-equinoxtools/src/main/java/org/eclipse/jetty/osgi/equinoxtools/console/EquinoxConsoleContinuationServlet.java
+++ /dev/null
@@ -1,253 +0,0 @@
-//
-// ========================================================================
-// Copyright (c) 1995-2012 Mort Bay Consulting Pty. Ltd.
-// ------------------------------------------------------------------------
-// All rights reserved. This program and the accompanying materials
-// are made available under the terms of the Eclipse Public License v1.0
-// and Apache License v2.0 which accompanies this distribution.
-//
-// The Eclipse Public License is available at
-// http://www.eclipse.org/legal/epl-v10.html
-//
-// The Apache License v2.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.equinoxtools.console;
-
-import java.io.IOException;
-import java.io.PrintWriter;
-import java.util.HashMap;
-import java.util.LinkedList;
-import java.util.Map;
-import java.util.Queue;
-
-import javax.servlet.ServletException;
-import javax.servlet.http.HttpServlet;
-import javax.servlet.http.HttpServletRequest;
-import javax.servlet.http.HttpServletResponse;
-
-import org.eclipse.jetty.continuation.Continuation;
-import org.eclipse.jetty.continuation.ContinuationSupport;
-import org.eclipse.jetty.osgi.equinoxtools.WebEquinoxToolsActivator;
-import org.eclipse.jetty.osgi.equinoxtools.console.WebConsoleWriterOutputStream.OnFlushListener;
-import org.eclipse.osgi.framework.console.ConsoleSession;
-
-/**
- * Async servlet with jetty continuations to interact with the equinox console.
- * Ported from jetty's example 'ChatServlet'
- */
-public class EquinoxConsoleContinuationServlet extends HttpServlet implements OnFlushListener
-{
-
- private static final long serialVersionUID = 1L;
- private Map<String,ConsoleUser> _consoleUsers = new HashMap<String, ConsoleUser>();
- private WebConsoleSession _consoleSession;
- private EquinoxChattingSupport _support;
-
- /**
- * @param consoleSession
- */
- public EquinoxConsoleContinuationServlet()
- {
-
- }
- /**
- * @param consoleSession
- */
- public EquinoxConsoleContinuationServlet(WebConsoleSession consoleSession, EquinoxChattingSupport support)
- {
- _consoleSession = consoleSession;
- _support = support;
- }
- @Override
- public void init() throws ServletException
- {
- if (_consoleSession == null)
- {
- _consoleSession = new WebConsoleSession();
- WebEquinoxToolsActivator.getContext().registerService(ConsoleSession.class.getName(), _consoleSession, null);
- }
- if (_support == null)
- {
- _support = new EquinoxChattingSupport(_consoleSession);
- }
- _consoleSession.addOnFlushListener(this);
- }
- @Override
- public void destroy()
- {
- _consoleSession.removeOnFlushListener(this);
- }
-
- // Serve the HTML with embedded CSS and Javascript.
- // This should be static content and should use real JS libraries.
- @Override
- protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException
- {
- if (request.getParameter("action")!=null)
- doPost(request,response);
- else
- response.sendRedirect(request.getContextPath() + request.getServletPath()
- + (request.getPathInfo() != null ? request.getPathInfo() : "") + "/index.html");
- }
-
- // Handle Ajax calls from browser
- @Override
- protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException
- {
- // Ajax calls are form encoded
- String action = request.getParameter("action");
- String message = request.getParameter("message");
- String username = request.getParameter("user");
-
- if (action.equals("join"))
- join(request,response,username);
- else if (action.equals("poll"))
- poll(request,response,username);
- else if (action.equals("chat"))
- chat(request,response,username,message);
- }
-
- private synchronized void join(HttpServletRequest request,HttpServletResponse response,String username)
- throws IOException
- {
- ConsoleUser member = new ConsoleUser(username);
- _consoleUsers.put(username,member);
- response.setContentType("text/json;charset=utf-8");
- PrintWriter out=response.getWriter();
- out.print("{action:\"join\"}");
- }
-
- private synchronized void poll(HttpServletRequest request,HttpServletResponse response,String username)
- throws IOException
- {
- ConsoleUser member = _consoleUsers.get(username);
- if (member==null)
- {
- response.sendError(503);
- return;
- }
-
- synchronized(member)
- {
- if (member.getMessageQueue().size()>0)
- {
- // Send one chat message
- response.setContentType("text/json;charset=utf-8");
- StringBuilder buf=new StringBuilder();
-
- buf.append("{\"action\":\"poll\",");
- buf.append("\"from\":\"");
- buf.append(member.getMessageQueue().poll());
- buf.append("\",");
-
- String message = member.getMessageQueue().poll();
- int quote=message.indexOf('"');
- while (quote>=0)
- {
- message=message.substring(0,quote)+'\\'+message.substring(quote);
- quote=message.indexOf('"',quote+2);
- }
- buf.append("\"chat\":\"");
- buf.append(message);
- buf.append("\"}");
- byte[] bytes = buf.toString().getBytes("utf-8");
- response.setContentLength(bytes.length);
- response.getOutputStream().write(bytes);
- }
- else
- {
- Continuation continuation = ContinuationSupport.getContinuation(request);
- if (continuation.isInitial())
- {
- // No chat in queue, so suspend and wait for timeout or chat
- continuation.setTimeout(20000);
- continuation.suspend();
- member.setContinuation(continuation);
- }
- else
- {
- // Timeout so send empty response
- response.setContentType("text/json;charset=utf-8");
- PrintWriter out=response.getWriter();
- out.print("{action:\"poll\"}");
- }
- }
- }
- }
-
- private synchronized void chat(HttpServletRequest request,HttpServletResponse response,String username,String message)
- throws IOException
- {
- if (!message.endsWith("has joined!"))
- {
- _consoleSession.processCommand(message, false);
- }
- // Post chat to all members
- onFlush();
-
- response.setContentType("text/json;charset=utf-8");
- PrintWriter out=response.getWriter();
- out.print("{action:\"chat\"}");
- }
-
- /**
- * Called right after the flush method on the output stream has been executed.
- */
- public void onFlush()
- {
- Queue<String> pendingConsoleOutputMessages = _support.processConsoleOutput(true, this);
- for (ConsoleUser m:_consoleUsers.values())
- {
- synchronized (m)
- {
-// m.getMessageQueue().add("osgi>"); // from
-// m.getMessageQueue().add("something was printed"); // chat
- m.getMessageQueue().addAll(pendingConsoleOutputMessages);
-
- // wakeup member if polling
- if (m.getContinuation()!=null)
- {
- m.getContinuation().resume();
- m.setContinuation(null);
- }
- }
- }
- }
-
- class ConsoleUser
- {
- private String _name;
- private Continuation _continuation;
- private Queue<String> _queue = new LinkedList<String>();
-
- public ConsoleUser(String name)
- {
- _name = name;
- }
-
- public String getName()
- {
- return _name;
- }
-
- public void setContinuation(Continuation continuation)
- {
- _continuation = continuation;
- }
-
- public Continuation getContinuation()
- {
- return _continuation;
- }
- public Queue<String> getMessageQueue()
- {
- return _queue;
- }
-
- }
-}
diff --git a/jetty-osgi/jetty-osgi-equinoxtools/src/main/java/org/eclipse/jetty/osgi/equinoxtools/console/EquinoxConsoleSyncServlet.java b/jetty-osgi/jetty-osgi-equinoxtools/src/main/java/org/eclipse/jetty/osgi/equinoxtools/console/EquinoxConsoleSyncServlet.java
deleted file mode 100644
index 33f0b38087..0000000000
--- a/jetty-osgi/jetty-osgi-equinoxtools/src/main/java/org/eclipse/jetty/osgi/equinoxtools/console/EquinoxConsoleSyncServlet.java
+++ /dev/null
@@ -1,82 +0,0 @@
-//
-// ========================================================================
-// Copyright (c) 1995-2012 Mort Bay Consulting Pty. Ltd.
-// ------------------------------------------------------------------------
-// All rights reserved. This program and the accompanying materials
-// are made available under the terms of the Eclipse Public License v1.0
-// and Apache License v2.0 which accompanies this distribution.
-//
-// The Eclipse Public License is available at
-// http://www.eclipse.org/legal/epl-v10.html
-//
-// The Apache License v2.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.equinoxtools.console;
-
-import java.io.IOException;
-import java.io.PrintWriter;
-
-import javax.servlet.ServletException;
-import javax.servlet.http.HttpServlet;
-import javax.servlet.http.HttpServletRequest;
-import javax.servlet.http.HttpServletResponse;
-
-
-/**
- * Take the example ChatServlet and use it to make an Equinox Console on the web.
- */
-public class EquinoxConsoleSyncServlet extends HttpServlet
-{
-
- private static final long serialVersionUID = 1L;
-
- private WebConsoleSession _consoleSession;
-
- public EquinoxConsoleSyncServlet(WebConsoleSession consoleSession)
- {
- _consoleSession = consoleSession;
- }
-
- @Override
- protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException
- {
- String cmd = request.getParameter("cmd");
- String Action = request.getParameter("Action");
- if (Action != null && Action.toLowerCase().indexOf("clear") != -1)
- {
- _consoleSession.clearOutput();
- }
- if (cmd != null)
- {
- _consoleSession.processCommand(cmd, true);
- }
-
- response.setContentType("text/html;charset=utf-8");
- PrintWriter p = response.getWriter();
- p.println("<html><head><title>Equinox Console (Synchroneous)</title></head><body>");
- p.println("<textarea rows=\"30\" cols=\"110\">");
- p.println(_consoleSession.getOutputAsWriter().toString());
- p.println("</textarea>");
- p.println("<form method=\"GET\" action=\""+response.encodeURL(getURI(request))+"\">");
- p.println("osgi>&nbsp;<input type=\"text\" name=\"cmd\" value=\"\"/><br/>\n");
- p.println("<input type=\"submit\" name=\"Action\" value=\"Submit or Refresh\"><br/>");
- p.println("<input type=\"submit\" name=\"Action\" value=\"Clear and Submit\"><br/>");
- p.println("</form>");
- p.println("<br/>");
- }
-
-
- private String getURI(HttpServletRequest request)
- {
- String uri= (String)request.getAttribute("javax.servlet.forward.request_uri");
- if (uri == null)
- uri= request.getRequestURI();
- return uri;
- }
-
-}
diff --git a/jetty-osgi/jetty-osgi-equinoxtools/src/main/java/org/eclipse/jetty/osgi/equinoxtools/console/EquinoxConsoleWebSocketServlet.java b/jetty-osgi/jetty-osgi-equinoxtools/src/main/java/org/eclipse/jetty/osgi/equinoxtools/console/EquinoxConsoleWebSocketServlet.java
deleted file mode 100644
index 55c8e23ff5..0000000000
--- a/jetty-osgi/jetty-osgi-equinoxtools/src/main/java/org/eclipse/jetty/osgi/equinoxtools/console/EquinoxConsoleWebSocketServlet.java
+++ /dev/null
@@ -1,182 +0,0 @@
-//
-// ========================================================================
-// Copyright (c) 1995-2012 Mort Bay Consulting Pty. Ltd.
-// ------------------------------------------------------------------------
-// All rights reserved. This program and the accompanying materials
-// are made available under the terms of the Eclipse Public License v1.0
-// and Apache License v2.0 which accompanies this distribution.
-//
-// The Eclipse Public License is available at
-// http://www.eclipse.org/legal/epl-v10.html
-//
-// The Apache License v2.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.equinoxtools.console;
-
-import java.io.IOException;
-import java.util.Queue;
-import java.util.Set;
-import java.util.concurrent.CopyOnWriteArraySet;
-
-import javax.servlet.ServletException;
-import javax.servlet.http.HttpServletRequest;
-import javax.servlet.http.HttpServletResponse;
-
-import org.eclipse.jetty.osgi.equinoxtools.WebEquinoxToolsActivator;
-import org.eclipse.jetty.osgi.equinoxtools.console.WebConsoleWriterOutputStream.OnFlushListener;
-import org.eclipse.jetty.util.log.Log;
-import org.eclipse.jetty.util.log.Logger;
-import org.eclipse.jetty.websocket.WebSocket;
-import org.eclipse.jetty.websocket.WebSocketServlet;
-import org.eclipse.osgi.framework.console.ConsoleSession;
-
-/**
- * Websocket version of the Chat with equinox.
- * Ported from jetty's example 'WebSocketChatServlet'
- */
-public class EquinoxConsoleWebSocketServlet extends WebSocketServlet implements OnFlushListener
-{
- private static final Logger LOG = Log.getLogger(EquinoxConsoleWebSocketServlet.class);
-
- private final Set<ChatWebSocket> _members = new CopyOnWriteArraySet<ChatWebSocket>();
- private static final long serialVersionUID = 1L;
- private WebConsoleSession _consoleSession;
- private EquinoxChattingSupport _support;
-
- public EquinoxConsoleWebSocketServlet()
- {
-
- }
- public EquinoxConsoleWebSocketServlet(WebConsoleSession consoleSession, EquinoxChattingSupport support)
- {
- _consoleSession = consoleSession;
- _support = support;
- }
- @Override
- public void init() throws ServletException
- {
- if (_consoleSession == null)
- {
- _consoleSession = new WebConsoleSession();
- WebEquinoxToolsActivator.getContext().registerService(ConsoleSession.class.getName(), _consoleSession, null);
- }
- if (_support == null)
- {
- _support = new EquinoxChattingSupport(_consoleSession);
- }
- super.init();
- _consoleSession.addOnFlushListener(this);
- }
-
- @Override
- public void destroy()
- {
- _consoleSession.removeOnFlushListener(this);
- }
-
-
- protected void doGet(HttpServletRequest request, HttpServletResponse response)
- throws javax.servlet.ServletException ,IOException
- {
- //getServletContext().getNamedDispatcher("default").forward(request,response);
- response.sendRedirect(request.getContextPath() + request.getServletPath()
- + (request.getPathInfo() != null ? request.getPathInfo() : "") + "/index.html");
- };
-
- public WebSocket doWebSocketConnect(HttpServletRequest request, String protocol)
- {
- return new ChatWebSocket();
- }
-
- /* ------------------------------------------------------------ */
- /* ------------------------------------------------------------ */
- class ChatWebSocket implements WebSocket.OnTextMessage
- {
- Connection _connection;
- String _username;
-
- public void onOpen(Connection connection)
- {
- // LOG.info(this+" onConnect");
- _connection=connection;
- _members.add(this);
- }
-
- public void onMessage(byte frame, byte[] data,int offset, int length)
- {
- // LOG.info(this+" onMessage: "+TypeUtil.toHexString(data,offset,length));
- }
-
- public void onMessage(String data)
- {
- LOG.info("onMessage: {}",data);
- if (data.indexOf("disconnect")>=0)
- _connection.disconnect();
- else
- {
- if (!data.endsWith(":has joined!"))
- {
- if (_username != null)
- {
- if (data.startsWith(_username + ":"))
- {
- data = data.substring(_username.length()+1);
- }
- else
- {
- //we should not be here?
- }
- }
- _consoleSession.processCommand(data, false);
- }
- else
- {
- _username = data.substring(0, data.length()-":has joined!".length());
- }
- // LOG.info(this+" onMessage: "+data);
- onFlush();
- }
- }
-
- public void onClose(int code, String message)
- {
- // LOG.info(this+" onDisconnect");
- _members.remove(this);
- }
-
- public void onError(String message, Throwable ex)
- {
-
- }
-
- }
-
-
- /**
- * Called right after the flush method on the output stream has been executed.
- */
- public void onFlush()
- {
- Queue<String> pendingConsoleOutputMessages = _support.processConsoleOutput(false, this);
- for (ChatWebSocket member : _members)
- {
- try
- {
- for (String line : pendingConsoleOutputMessages)
- {
- member._connection.sendMessage(line);
- }
- }
- catch(IOException e)
- {
- LOG.warn(e);
- }
- }
- }
-
-}
diff --git a/jetty-osgi/jetty-osgi-equinoxtools/src/main/java/org/eclipse/jetty/osgi/equinoxtools/console/WebConsoleSession.java b/jetty-osgi/jetty-osgi-equinoxtools/src/main/java/org/eclipse/jetty/osgi/equinoxtools/console/WebConsoleSession.java
deleted file mode 100644
index b867934247..0000000000
--- a/jetty-osgi/jetty-osgi-equinoxtools/src/main/java/org/eclipse/jetty/osgi/equinoxtools/console/WebConsoleSession.java
+++ /dev/null
@@ -1,189 +0,0 @@
-//
-// ========================================================================
-// Copyright (c) 1995-2012 Mort Bay Consulting Pty. Ltd.
-// ------------------------------------------------------------------------
-// All rights reserved. This program and the accompanying materials
-// are made available under the terms of the Eclipse Public License v1.0
-// and Apache License v2.0 which accompanies this distribution.
-//
-// The Eclipse Public License is available at
-// http://www.eclipse.org/legal/epl-v10.html
-//
-// The Apache License v2.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.equinoxtools.console;
-
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.OutputStream;
-import java.io.PipedInputStream;
-import java.io.PipedOutputStream;
-import java.io.PrintStream;
-import java.io.StringWriter;
-import java.util.List;
-
-import org.eclipse.jetty.osgi.equinoxtools.console.WebConsoleWriterOutputStream.OnFlushListener;
-import org.eclipse.osgi.framework.console.ConsoleSession;
-
-/**
- * A simple console session for equinox.
- *
- * @author hmalphettes
- */
-public class WebConsoleSession extends ConsoleSession
-{
-
- private OutputStream _out;
- private StringWriter _outWriter;
- private PrintStream _source;
- private InputStream _in;
-
- public WebConsoleSession()
- {
- _outWriter = new StringWriter();
- _out = new WebConsoleWriterOutputStream(_outWriter,"UTF-8");
- try
- {
- PipedOutputStream source = new PipedOutputStream();
- PipedInputStream sink = new PipedInputStream(source);
- _in = sink;
- _source = new PrintStream(source);
- }
- catch (IOException e)
- {
- //this never happens?
- e.printStackTrace();
- }
- }
-
- @Override
- protected void doClose()
- {
- if (_out != null) try { _out.close(); } catch (IOException e) {}
- if (_in != null) try { _in.close(); } catch (IOException ioe) {}
- }
-
- @Override
- public InputStream getInput()
- {
- return _in;
- }
-
- @Override
- public OutputStream getOutput()
- {
- return _out;
- }
-
- /**
- * For the output we are using a string writer in fact.
- * @return
- */
- public StringWriter getOutputAsWriter()
- {
- return _outWriter;
- }
-
- /**
- * @return The print stream where commands can be written.
- */
- public PrintStream getSource()
- {
- return _source;
- }
-
- /**
- * Issue a command on the console.
- * @param cmd
- */
- public void issueCommand(String cmd)
- {
- if (cmd != null)
- {
- getSource().println(cmd);
- }
- }
-
- /**
- * @param flushListener Object that is called back when the outputstream is flushed.
- */
- public void addOnFlushListener(OnFlushListener flushListener)
- {
- ((WebConsoleWriterOutputStream)_out).addOnFlushListener(flushListener);
- }
- /**
- * @param flushListener Object that is called back when the outputstream is flushed.
- */
- public boolean removeOnFlushListener(OnFlushListener flushListener)
- {
- return ((WebConsoleWriterOutputStream)_out).removeOnFlushListener(flushListener);
- }
-
- /**
- * Process command comming from a web UI
- * @param cmd
- */
- public void processCommand(String cmd, boolean wait)
- {
- cmd = cmd.trim();
- while (cmd.startsWith("osgi>"))
- {
- cmd = cmd.substring("osgi>".length()).trim();
- }
- if (cmd.equals("clear"))
- {
- clearOutput();
- }
- else
- {
- getOutputAsWriter().append(cmd + "\n");
- int originalOutputLength = getOutputAsWriter().getBuffer().length();
- issueCommand(cmd);
-
- if (wait)
- {
- //it does not get uglier than this:
- //give a little time to equinox to interpret the command so we see the response
- //we could do a lot better, but we might as well use the async servlets anyways.
- int waitLoopNumber = 0;
- int lastWaitOutputLength = -1;
- while (waitLoopNumber < 10)
- {
- waitLoopNumber++;
- try
- {
- Thread.sleep(100);
- }
- catch (InterruptedException e)
- {
- break;
- }
- int newOutputLength = getOutputAsWriter().getBuffer().length();
- if (newOutputLength > originalOutputLength && newOutputLength == lastWaitOutputLength)
- {
- break;
- }
- lastWaitOutputLength = newOutputLength;
- }
- }
- }
-
- }
-
- public void clearOutput()
- {
- StringBuffer buf = getOutputAsWriter().getBuffer();
- if (buf.length() > 0) buf.delete(0,buf.length()-1);
- }
-
- public List<OnFlushListener> getOnFlushListeners()
- {
- return ((WebConsoleWriterOutputStream)_out).getOnFlushListeners();
- }
-
-}
diff --git a/jetty-osgi/jetty-osgi-equinoxtools/src/main/java/org/eclipse/jetty/osgi/equinoxtools/console/WebConsoleWriterOutputStream.java b/jetty-osgi/jetty-osgi-equinoxtools/src/main/java/org/eclipse/jetty/osgi/equinoxtools/console/WebConsoleWriterOutputStream.java
deleted file mode 100644
index c60b3e5f49..0000000000
--- a/jetty-osgi/jetty-osgi-equinoxtools/src/main/java/org/eclipse/jetty/osgi/equinoxtools/console/WebConsoleWriterOutputStream.java
+++ /dev/null
@@ -1,93 +0,0 @@
-//
-// ========================================================================
-// Copyright (c) 1995-2012 Mort Bay Consulting Pty. Ltd.
-// ------------------------------------------------------------------------
-// All rights reserved. This program and the accompanying materials
-// are made available under the terms of the Eclipse Public License v1.0
-// and Apache License v2.0 which accompanies this distribution.
-//
-// The Eclipse Public License is available at
-// http://www.eclipse.org/legal/epl-v10.html
-//
-// The Apache License v2.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.equinoxtools.console;
-
-import java.io.IOException;
-import java.io.Writer;
-import java.util.ArrayList;
-import java.util.List;
-
-/**
- * Can be set with a listener that is called back right after the flush method is called.
- */
-public class WebConsoleWriterOutputStream extends org.eclipse.jetty.io.WriterOutputStream
-{
-
- /**
- * Interface called back after the outputstream is flushed.
- */
- public interface OnFlushListener
- {
- /**
- * Called right after the flush method on the output stream has been executed.
- */
- public void onFlush();
-
- }
-
- public interface MessageBroadcaster
- {
- public void broadcast();
- }
-
- private List<OnFlushListener> _callBacks;
-
- public WebConsoleWriterOutputStream(Writer writer, String encoding)
- {
- super(writer, encoding);
- }
-
- @Override
- public synchronized void flush() throws IOException
- {
- super.flush();
- if (_callBacks != null)
- {
- for (OnFlushListener listener : _callBacks)
- {
- listener.onFlush();
- }
- }
- }
-
- public synchronized void addOnFlushListener(OnFlushListener callback)
- {
- if (_callBacks == null)
- {
- _callBacks = new ArrayList<WebConsoleWriterOutputStream.OnFlushListener>();
- }
- if (!_callBacks.contains(callback))
- {
- _callBacks.add(callback);
- }
- }
- public synchronized boolean removeOnFlushListener(OnFlushListener callback)
- {
- if (_callBacks != null)
- {
- return _callBacks.remove(callback);
- }
- return false;
- }
- public synchronized List<OnFlushListener> getOnFlushListeners()
- {
- return _callBacks;
- }
-
-}
diff --git a/jetty-osgi/jetty-osgi-httpservice/contexts/httpservice.xml b/jetty-osgi/jetty-osgi-httpservice/contexts/httpservice.xml
index 95757f6c80..211a8e8ce2 100644
--- a/jetty-osgi/jetty-osgi-httpservice/contexts/httpservice.xml
+++ b/jetty-osgi/jetty-osgi-httpservice/contexts/httpservice.xml
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="ISO-8859-1"?>
<!DOCTYPE Configure PUBLIC "-//Jetty//Configure//EN" "http://www.eclipse.org/jetty/configure.dtd">
<!--
- Copyright (c) 2009 Intalio, Inc.
+ Copyright (c) 2009-2011 Intalio, Inc.
All rights reserved. This program and the accompanying materials
are made available under the terms of the Eclipse Public License v1.0
@@ -29,4 +29,4 @@
<Set name="ErrorHandler">
<New class="org.eclipse.jetty.osgi.httpservice.HttpServiceErrorPageErrorHandler"/>
</Set>
-</Configure> \ No newline at end of file
+</Configure>
diff --git a/jetty-osgi/jetty-osgi-httpservice/pom.xml b/jetty-osgi/jetty-osgi-httpservice/pom.xml
index 26246ac4dc..4b4e3a9b74 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>7.6.8-SNAPSHOT</version>
+ <version>8.1.8-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>
<modelVersion>4.0.0</modelVersion>
@@ -96,8 +96,8 @@
<Bundle-SymbolicName>org.eclipse.jetty.osgi.httpservice</Bundle-SymbolicName>
<Bundle-Name>OSGi HttpService</Bundle-Name>
<Jetty-ContextFilePath>contexts/httpservice.xml</Jetty-ContextFilePath>
- <Import-Package>org.eclipse.jetty.server.handler;version="[7.6,8)",
-org.eclipse.jetty.util.component;version="[7.6,8)",
+ <Import-Package>org.eclipse.jetty.server.handler;version="[8.1,9)",
+org.eclipse.jetty.util.component;version="[8.1,9)",
org.eclipse.equinox.http.servlet,
*
</Import-Package>
@@ -114,6 +114,4 @@ org.eclipse.equinox.http.servlet,
</plugin>
</plugins>
</build>
-
-
</project>
diff --git a/jetty-osgi/jetty-osgi-httpservice/pom.xml.tycho b/jetty-osgi/jetty-osgi-httpservice/pom.xml.tycho
deleted file mode 100644
index c6efbeb50f..0000000000
--- a/jetty-osgi/jetty-osgi-httpservice/pom.xml.tycho
+++ /dev/null
@@ -1,12 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<project xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd" xmlns="http://maven.apache.org/POM/4.0.0"
- xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
- <modelVersion>4.0.0</modelVersion>
- <parent>
- <artifactId>jetty-osgi</artifactId>
- <groupId>org.eclipse.jetty.osgi</groupId>
- <version>7.0.1-SNAPSHOT</version>
- </parent>
- <artifactId>org.eclipse.jetty.osgi.httpservice</artifactId>
- <packaging>eclipse-plugin</packaging>
-</project>
diff --git a/jetty-osgi/jetty-osgi-servletbridge/pom.xml b/jetty-osgi/jetty-osgi-servletbridge/pom.xml
deleted file mode 100644
index db10d11a57..0000000000
--- a/jetty-osgi/jetty-osgi-servletbridge/pom.xml
+++ /dev/null
@@ -1,53 +0,0 @@
-<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.osgi</groupId>
- <artifactId>jetty-osgi-project</artifactId>
- <version>7.6.5-SNAPSHOT</version>
- <relativePath>../pom.xml</relativePath>
- </parent>
- <modelVersion>4.0.0</modelVersion>
- <groupId>org.eclipse.jetty.osgi</groupId>
- <artifactId>jetty-osgi-servletbridge</artifactId>
- <name>Jetty :: OSGi :: Servletbridge</name>
- <description>Jetty OSGi Servletbridge webapp</description>
- <packaging>war</packaging>
- <properties><eclipse.pde>false</eclipse.pde></properties>
- <dependencies>
- <dependency>
- <groupId>org.eclipse.equinox</groupId>
- <artifactId>org.eclipse.equinox.servletbridge</artifactId>
- <version>1.2.0.v20100503</version>
- </dependency>
- <dependency>
- <groupId>javax.servlet</groupId>
- <artifactId>servlet-api</artifactId>
- <version>2.5</version>
- <scope>provided</scope>
- </dependency>
- <dependency>
- <groupId>org.eclipse.osgi</groupId>
- <artifactId>org.eclipse.osgi</artifactId>
- <version>3.6.0.v20100517</version>
- <scope>provided</scope>
- </dependency>
- </dependencies>
- <repositories>
- <!-- can't find equinox servlet bridge jar on maven central.
- uploaded it to intalio.org for now. -->
- <repository>
- <id>intalio-org</id>
- <url>http://intalio.org/public/maven2</url>
- </repository>
- </repositories>
-
- <build>
- <plugins><plugin>
- <groupId>org.apache.maven.plugins</groupId>
- <artifactId>maven-eclipse-plugin</artifactId>
- <configuration>
- <pde>false</pde>
- </configuration>
- </plugin></plugins>
- </build>
-
-</project>
diff --git a/jetty-osgi/jetty-osgi-servletbridge/src/main/java/org/eclipse/jetty/nested/Dump.java b/jetty-osgi/jetty-osgi-servletbridge/src/main/java/org/eclipse/jetty/nested/Dump.java
deleted file mode 100644
index 50236caaff..0000000000
--- a/jetty-osgi/jetty-osgi-servletbridge/src/main/java/org/eclipse/jetty/nested/Dump.java
+++ /dev/null
@@ -1,1017 +0,0 @@
-//
-// ========================================================================
-// Copyright (c) 1995-2012 Mort Bay Consulting Pty. Ltd.
-// ------------------------------------------------------------------------
-// All rights reserved. This program and the accompanying materials
-// are made available under the terms of the Eclipse Public License v1.0
-// and Apache License v2.0 which accompanies this distribution.
-//
-// The Eclipse Public License is available at
-// http://www.eclipse.org/legal/epl-v10.html
-//
-// The Apache License v2.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.nested;
-
-import java.io.BufferedWriter;
-import java.io.File;
-import java.io.IOException;
-import java.io.OutputStream;
-import java.io.OutputStreamWriter;
-import java.io.PrintWriter;
-import java.io.Reader;
-import java.lang.reflect.Array;
-import java.lang.reflect.Field;
-import java.sql.Connection;
-import java.sql.DriverManager;
-import java.sql.Statement;
-import java.util.Date;
-import java.util.Enumeration;
-import java.util.Locale;
-import java.util.Map.Entry;
-
-import javax.servlet.ServletConfig;
-import javax.servlet.ServletContext;
-import javax.servlet.ServletException;
-import javax.servlet.ServletRequest;
-import javax.servlet.ServletRequestWrapper;
-import javax.servlet.ServletResponse;
-import javax.servlet.ServletResponseWrapper;
-import javax.servlet.UnavailableException;
-import javax.servlet.http.Cookie;
-import javax.servlet.http.HttpServlet;
-import javax.servlet.http.HttpServletRequest;
-import javax.servlet.http.HttpServletRequestWrapper;
-import javax.servlet.http.HttpServletResponse;
-import javax.servlet.http.HttpServletResponseWrapper;
-import javax.sql.DataSource;
-
-/* ------------------------------------------------------------ */
-/**
- * Dump Servlet Request.
- *
- * Copied from test-jetty-webapp's Dump servlet.
- */
-public class Dump extends HttpServlet
-{
- boolean fixed;
-
- /* ------------------------------------------------------------ */
- @Override
- public void init(ServletConfig config) throws ServletException
- {
- super.init(config);
-
- if (config.getInitParameter("unavailable") != null && !fixed)
- {
-
- fixed = true;
- throw new UnavailableException("Unavailable test", Integer.parseInt(config.getInitParameter("unavailable")));
- }
- }
-
- /* ------------------------------------------------------------ */
- @Override
- public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException
- {
- doGet(request, response);
- }
-
- /* ------------------------------------------------------------ */
- @Override
- public void doGet(final HttpServletRequest request, final HttpServletResponse response) throws ServletException, IOException
- {
- // Handle a dump of data
- final String data = request.getParameter("data");
- final String chars = request.getParameter("chars");
- final String block = request.getParameter("block");
- final String dribble = request.getParameter("dribble");
- final boolean flush = request.getParameter("flush") != null ? Boolean.parseBoolean(request.getParameter("flush")) : false;
-
- if (request.getPathInfo() != null && request.getPathInfo().toLowerCase().indexOf("script") != -1)
- {
- response.sendRedirect(response.encodeRedirectURL(getServletContext().getContextPath() + "/dump/info"));
- return;
- }
-
- request.setCharacterEncoding("UTF-8");
-
- if (request.getParameter("empty") != null)
- {
- response.setStatus(200);
- response.flushBuffer();
- return;
- }
-
- request.setAttribute("Dump", this);
- getServletContext().setAttribute("Dump", this);
-
- // Force a content length response
- String length = request.getParameter("length");
- if (length != null && length.length() > 0)
- {
- response.setContentLength(Integer.parseInt(length));
- }
-
- // Handle a dump of data
- if (dump(response, data, chars, block, dribble, flush)) return;
-
- // handle an exception
- String info = request.getPathInfo();
- if (info != null && info.endsWith("Exception"))
- {
- try
- {
- throw (Throwable) Thread.currentThread().getContextClassLoader().loadClass(info.substring(1)).newInstance();
- }
- catch (Throwable th)
- {
- throw new ServletException(th);
- }
- }
-
- // test a reset
- String reset = request.getParameter("reset");
- if (reset != null && reset.length() > 0)
- {
- response.getOutputStream().println("THIS SHOULD NOT BE SEEN!");
- response.setHeader("SHOULD_NOT", "BE SEEN");
- response.reset();
- }
-
- // handle an redirect
- String redirect = request.getParameter("redirect");
- if (redirect != null && redirect.length() > 0)
- {
- response.getOutputStream().println("THIS SHOULD NOT BE SEEN!");
- response.sendRedirect(response.encodeRedirectURL(redirect));
- try
- {
- response.getOutputStream().println("THIS SHOULD NOT BE SEEN!");
- }
- catch (IOException e)
- {
- // ignored as stream is closed.
- }
- return;
- }
-
- // handle an error
- String error = request.getParameter("error");
- if (error != null && error.length() > 0 && request.getAttribute("javax.servlet.error.status_code") == null)
- {
- response.getOutputStream().println("THIS SHOULD NOT BE SEEN!");
- response.sendError(Integer.parseInt(error));
- try
- {
- response.getOutputStream().println("THIS SHOULD NOT BE SEEN!");
- }
- catch (IllegalStateException e)
- {
- try
- {
- response.getWriter().println("NOR THIS!!");
- }
- catch (IOException e2)
- {
- }
- }
- catch (IOException e)
- {
- }
- return;
- }
-
- // Handle a extra headers
- String headers = request.getParameter("headers");
- if (headers != null && headers.length() > 0)
- {
- long h = Long.parseLong(headers);
- for (int i = 0; i < h; i++)
- response.addHeader("Header" + i, "Value" + i);
- }
-
- String buffer = request.getParameter("buffer");
- if (buffer != null && buffer.length() > 0) response.setBufferSize(Integer.parseInt(buffer));
-
- String charset = request.getParameter("charset");
- if (charset == null) charset = "UTF-8";
- response.setCharacterEncoding(charset);
- response.setContentType("text/html");
-
- if (info != null && info.indexOf("Locale/") >= 0)
- {
- try
- {
- String locale_name = info.substring(info.indexOf("Locale/") + 7);
- Field f = java.util.Locale.class.getField(locale_name);
- response.setLocale((Locale) f.get(null));
- }
- catch (Exception e)
- {
- e.printStackTrace();
- response.setLocale(Locale.getDefault());
- }
- }
-
- String cn = request.getParameter("cookie");
- String cv = request.getParameter("cookiev");
- if (cn != null && cv != null)
- {
- Cookie cookie = new Cookie(cn, cv);
- if (request.getParameter("version") != null) cookie.setVersion(Integer.parseInt(request.getParameter("version")));
- cookie.setComment("Cookie from dump servlet");
- response.addCookie(cookie);
- }
-
- String pi = request.getPathInfo();
- if (pi != null && pi.startsWith("/ex"))
- {
- OutputStream out = response.getOutputStream();
- out.write("</H1>This text should be reset</H1>".getBytes());
- if ("/ex0".equals(pi))
- throw new ServletException("test ex0", new Throwable());
- else if ("/ex1".equals(pi))
- throw new IOException("test ex1");
- else if ("/ex2".equals(pi))
- throw new UnavailableException("test ex2");
- else if (pi.startsWith("/ex3/")) throw new UnavailableException("test ex3", Integer.parseInt(pi.substring(5)));
- throw new RuntimeException("test");
- }
-
- if ("true".equals(request.getParameter("close"))) response.setHeader("Connection", "close");
-
- String buffered = request.getParameter("buffered");
-
- PrintWriter pout = null;
-
- try
- {
- pout = response.getWriter();
- }
- catch (IllegalStateException e)
- {
- pout = new PrintWriter(new OutputStreamWriter(response.getOutputStream(), charset));
- }
- if (buffered != null) pout = new PrintWriter(new BufferedWriter(pout, Integer.parseInt(buffered)));
-
- try
- {
- pout.write("<html>\n<body>\n");
- pout.write("<h1>Dump Servlet</h1>\n");
- pout.write("<table width=\"95%\">");
- pout.write("<tr>\n");
- pout.write("<th align=\"right\">getMethod:&nbsp;</th>");
- pout.write("<td>" + notag(request.getMethod()) + "</td>");
- pout.write("</tr><tr>\n");
- pout.write("<th align=\"right\">getContentLength:&nbsp;</th>");
- pout.write("<td>" + Integer.toString(request.getContentLength()) + "</td>");
- pout.write("</tr><tr>\n");
- pout.write("<th align=\"right\">getContentType:&nbsp;</th>");
- pout.write("<td>" + notag(request.getContentType()) + "</td>");
- pout.write("</tr><tr>\n");
- pout.write("<th align=\"right\">getRequestURI:&nbsp;</th>");
- pout.write("<td>" + notag(request.getRequestURI()) + "</td>");
- pout.write("</tr><tr>\n");
- pout.write("<th align=\"right\">getRequestURL:&nbsp;</th>");
- pout.write("<td>" + notag(request.getRequestURL().toString()) + "</td>");
- pout.write("</tr><tr>\n");
- pout.write("<th align=\"right\">getContextPath:&nbsp;</th>");
- pout.write("<td>" + request.getContextPath() + "</td>");
- pout.write("</tr><tr>\n");
- pout.write("<th align=\"right\">getServletPath:&nbsp;</th>");
- pout.write("<td>" + notag(request.getServletPath()) + "</td>");
- pout.write("</tr><tr>\n");
- pout.write("<th align=\"right\">getPathInfo:&nbsp;</th>");
- pout.write("<td>" + notag(request.getPathInfo()) + "</td>");
- pout.write("</tr><tr>\n");
- pout.write("<th align=\"right\">getPathTranslated:&nbsp;</th>");
- pout.write("<td>" + notag(request.getPathTranslated()) + "</td>");
- pout.write("</tr><tr>\n");
- pout.write("<th align=\"right\">getQueryString:&nbsp;</th>");
- pout.write("<td>" + notag(request.getQueryString()) + "</td>");
- pout.write("</tr><tr>\n");
-
- pout.write("<th align=\"right\">getProtocol:&nbsp;</th>");
- pout.write("<td>" + request.getProtocol() + "</td>");
- pout.write("</tr><tr>\n");
- pout.write("<th align=\"right\">getScheme:&nbsp;</th>");
- pout.write("<td>" + request.getScheme() + "</td>");
- pout.write("</tr><tr>\n");
- pout.write("<th align=\"right\">getServerName:&nbsp;</th>");
- pout.write("<td>" + notag(request.getServerName()) + "</td>");
- pout.write("</tr><tr>\n");
- pout.write("<th align=\"right\">getServerPort:&nbsp;</th>");
- pout.write("<td>" + Integer.toString(request.getServerPort()) + "</td>");
- pout.write("</tr><tr>\n");
- pout.write("<th align=\"right\">getLocalName:&nbsp;</th>");
- pout.write("<td>" + request.getLocalName() + "</td>");
- pout.write("</tr><tr>\n");
- pout.write("<th align=\"right\">getLocalAddr:&nbsp;</th>");
- pout.write("<td>" + request.getLocalAddr() + "</td>");
- pout.write("</tr><tr>\n");
- pout.write("<th align=\"right\">getLocalPort:&nbsp;</th>");
- pout.write("<td>" + Integer.toString(request.getLocalPort()) + "</td>");
- pout.write("</tr><tr>\n");
- pout.write("<th align=\"right\">getRemoteUser:&nbsp;</th>");
- pout.write("<td>" + request.getRemoteUser() + "</td>");
- pout.write("</tr><tr>\n");
- pout.write("<th align=\"right\">getUserPrincipal:&nbsp;</th>");
- pout.write("<td>" + request.getUserPrincipal() + "</td>");
- pout.write("</tr><tr>\n");
- pout.write("<th align=\"right\">getRemoteAddr:&nbsp;</th>");
- pout.write("<td>" + request.getRemoteAddr() + "</td>");
- pout.write("</tr><tr>\n");
- pout.write("<th align=\"right\">getRemoteHost:&nbsp;</th>");
- pout.write("<td>" + request.getRemoteHost() + "</td>");
- pout.write("</tr><tr>\n");
- pout.write("<th align=\"right\">getRemotePort:&nbsp;</th>");
- pout.write("<td>" + request.getRemotePort() + "</td>");
- pout.write("</tr><tr>\n");
- pout.write("<th align=\"right\">getRequestedSessionId:&nbsp;</th>");
- pout.write("<td>" + request.getRequestedSessionId() + "</td>");
- pout.write("</tr><tr>\n");
- pout.write("<th align=\"right\">isSecure():&nbsp;</th>");
- pout.write("<td>" + request.isSecure() + "</td>");
-
- pout.write("</tr><tr>\n");
- pout.write("<th align=\"right\">isUserInRole(admin):&nbsp;</th>");
- pout.write("<td>" + request.isUserInRole("admin") + "</td>");
-
- pout.write("</tr><tr>\n");
- pout.write("<th align=\"right\">getLocale:&nbsp;</th>");
- pout.write("<td>" + request.getLocale() + "</td>");
-
- Enumeration locales = request.getLocales();
- while (locales.hasMoreElements())
- {
- pout.write("</tr><tr>\n");
- pout.write("<th align=\"right\">getLocales:&nbsp;</th>");
- pout.write("<td>" + locales.nextElement() + "</td>");
- }
- pout.write("</tr><tr>\n");
-
- pout.write("<th align=\"left\" colspan=\"2\"><big><br/>Other HTTP Headers:</big></th>");
- Enumeration h = request.getHeaderNames();
- String name;
- while (h.hasMoreElements())
- {
- name = (String) h.nextElement();
-
- Enumeration h2 = request.getHeaders(name);
- while (h2.hasMoreElements())
- {
- String hv = (String) h2.nextElement();
- pout.write("</tr><tr>\n");
- pout.write("<th align=\"right\">" + notag(name) + ":&nbsp;</th>");
- pout.write("<td>" + notag(hv) + "</td>");
- }
- }
-
- // Test the system properties
- if ("true".equals(request.getParameter("env")))
- {
- pout.write("</tr><tr>\n");
- pout.write("<th align=\"left\" colspan=\"2\"><big><br/>Environment:&nbsp;</big></th>");
- for (Entry e : System.getenv().entrySet())
- {
- pout.write("</tr><tr>\n");
- pout.write("<th align=\"right\">" + notag(String.valueOf(e.getKey())) + ":&nbsp;</th>");
- pout.write("<td>" + notag(String.valueOf(e.getValue())) + "</td>");
- }
-
- pout.write("</tr><tr>\n");
- pout.write("<th align=\"left\" colspan=\"2\"><big><br/>System-Properties:&nbsp;</big></th>");
-
- for (Entry<Object, Object> e : System.getProperties().entrySet())
- {
- pout.write("</tr><tr>\n");
- pout.write("<th align=\"right\">" + notag(String.valueOf(e.getKey())) + ":&nbsp;</th>");
- pout.write("<td>" + notag(String.valueOf(e.getValue())) + "</td>");
- }
- }
-
- // handle testing jdbc connections:
- String jdbcUrl = request.getParameter("jdbc-url");
- String jdbcDriver = request.getParameter("jdbc-driver");
- if (jdbcUrl != null)
- {
- Connection con = null;
- try
- {
- String user = request.getParameter("jdbc-user");
- String pass = request.getParameter("jdbc-pass");
- String query = request.getParameter("jdbc-query");
- if (user.length() == 0) user = null;
- if (pass.length() == 0) pass = null;
- if (query == null || query.length() == 0) query = "show tables;";
- pout.write("</tr><tr>\n");
- pout.write("<th align=\"left\" colspan=\"2\"><big><br/>JDBC test:&nbsp;</big></th>");
-
- Class driver = Thread.currentThread().getContextClassLoader().loadClass(jdbcDriver);
-
- pout.write("</tr><tr>\n");
- pout.write("<th align=\"right\">Driver class:&nbsp;</th>");
- pout.write("<td>" + driver.getName() + " loaded by " + driver.getClassLoader() + "</td>");
- pout.write("</tr><tr>\n");
- pout.write("<th align=\"right\">Connection url:&nbsp;</th>");
- pout.write("<td>" + jdbcUrl + "</td>");
- pout.write("</tr><tr>\n");
- pout.write("<th align=\"right\">User (optional):&nbsp;</th>");
- pout.write("<td>" + user + "</td>");
- pout.write("</tr><tr>\n");
- pout.write("<th align=\"right\">Is there a password (optional):&nbsp;</th>");
- pout.write("<td>" + (pass != null ? "yes" : "no") + "</td>");
-
- con = user != null ? DriverManager.getConnection(jdbcUrl, user, pass) : DriverManager.getConnection(jdbcUrl);
-
- Statement statement = con.createStatement();
- boolean success = statement.execute(query);
- pout.write("</tr><tr>\n");
- pout.write("<th align=\"right\">Query:&nbsp;</th>");
- pout.write("<td>" + query + "</td>");
- pout.write("</tr><tr>\n");
- pout.write("<th align=\"right\">Successful query:&nbsp;</th>");
- pout.write("<td>" + success + "</td>");
-
- }
- catch (Throwable t)
- {
- pout.write("</tr><tr>\n");
- pout.write("<th align=\"right\">JDBC test error:&nbsp;</th>");
- pout.write("<td>" + t + "</td>");
- }
- finally
- {
- if (con != null)
- {
- try
- {
- con.close();
- }
- catch (Throwable ee)
- {
- }
- }
- }
- }
-
- pout.write("</tr><tr>\n");
- pout.write("<th align=\"left\" colspan=\"2\"><big><br/>Request Parameters:</big></th>");
- h = request.getParameterNames();
- while (h.hasMoreElements())
- {
- name = (String) h.nextElement();
- pout.write("</tr><tr>\n");
- pout.write("<th align=\"right\">" + notag(name) + ":&nbsp;</th>");
- pout.write("<td>" + notag(request.getParameter(name)) + "</td>");
- String[] values = request.getParameterValues(name);
- if (values == null)
- {
- pout.write("</tr><tr>\n");
- pout.write("<th align=\"right\">" + notag(name) + " Values:&nbsp;</th>");
- pout.write("<td>" + "NULL!" + "</td>");
- }
- else if (values.length > 1)
- {
- for (int i = 0; i < values.length; i++)
- {
- pout.write("</tr><tr>\n");
- pout.write("<th align=\"right\">" + notag(name) + "[" + i + "]:&nbsp;</th>");
- pout.write("<td>" + notag(values[i]) + "</td>");
- }
- }
- }
-
- pout.write("</tr><tr>\n");
- pout.write("<th align=\"left\" colspan=\"2\"><big><br/>Cookies:</big></th>");
- Cookie[] cookies = request.getCookies();
- for (int i = 0; cookies != null && i < cookies.length; i++)
- {
- Cookie cookie = cookies[i];
-
- pout.write("</tr><tr>\n");
- pout.write("<th align=\"right\">" + notag(cookie.getName()) + ":&nbsp;</th>");
- pout.write("<td>" + notag(cookie.getValue()) + "</td>");
- }
-
- String content_type = request.getContentType();
- if (content_type != null && !content_type.startsWith("application/x-www-form-urlencoded") && !content_type.startsWith("multipart/form-data"))
- {
- pout.write("</tr><tr>\n");
- pout.write("<th align=\"left\" valign=\"top\" colspan=\"2\"><big><br/>Content:</big></th>");
- pout.write("</tr><tr>\n");
- pout.write("<td><pre>");
- char[] content = new char[4096];
- int len;
- try
- {
- Reader in = request.getReader();
-
- while ((len = in.read(content)) >= 0)
- pout.write(notag(new String(content, 0, len)));
- }
- catch (IOException e)
- {
- pout.write(e.toString());
- }
-
- pout.write("</pre></td>");
- }
-
- pout.write("</tr><tr>\n");
- pout.write("<th align=\"left\" colspan=\"2\"><big><br/>Request Attributes:</big></th>");
- Enumeration a = request.getAttributeNames();
- while (a.hasMoreElements())
- {
- name = (String) a.nextElement();
- pout.write("</tr><tr>\n");
- pout.write("<th align=\"right\" valign=\"top\">" + name.replace(".", " .") + ":&nbsp;</th>");
- Object value = request.getAttribute(name);
- if (value instanceof File)
- {
- File file = (File) value;
- pout.write("<td>" + "<pre>" + file.getName() + " (" + file.length() + " " + new Date(file.lastModified()) + ")</pre>" + "</td>");
- }
- else
- pout.write("<td>" + "<pre>" + toString(request.getAttribute(name)) + "</pre>" + "</td>");
- }
- request.setAttribute("org.eclipse.jetty.servlet.MultiPartFilter.files", null);
-
- pout.write("</tr><tr>\n");
- pout.write("<th align=\"left\" colspan=\"2\"><big><br/>Servlet InitParameters:</big></th>");
- a = getInitParameterNames();
- while (a.hasMoreElements())
- {
- name = (String) a.nextElement();
- pout.write("</tr><tr>\n");
- pout.write("<th align=\"right\">" + name + ":&nbsp;</th>");
- pout.write("<td>" + toString(getInitParameter(name)) + "</td>");
- }
-
- pout.write("</tr><tr>\n");
- pout.write("<th align=\"left\" colspan=\"2\"><big><br/>ServletContext Misc:</big></th>");
- pout.write("</tr><tr>\n");
- pout.write("<th align=\"right\" valign=\"top\">" + "servletContext.getContextPath()" + ":&nbsp;</th>");
- pout.write("<td>" + getServletContext().getContextPath() + "</td>");
- pout.write("</tr><tr>\n");
- pout.write("<th align=\"right\" valign=\"top\">" + "getServletContext().getRealPath(\"/WEB-INF/\")" + ":&nbsp;</th>");
- pout.write("<td>" + getServletContext().getRealPath("/WEB-INF/") + "</td>");
-
- String webinfRealPath = getServletContext().getRealPath("/WEB-INF/");
- if (webinfRealPath != null)
- {
- try
- {
- File webInfRealPathFile = new File(webinfRealPath);
- pout.write("</tr><tr>\n");
- pout.write("<th align=\"right\" valign=\"top\">" + "new File(getServletContext().getRealPath(\"/WEB-INF/\"))" + ":&nbsp;</th>");
- pout.write("<td>exists()=" + webInfRealPathFile.exists()
- + "; isFile()="
- + webInfRealPathFile.isFile()
- + "; isDirectory()="
- + webInfRealPathFile.isDirectory()
- + "; isAbsolute()="
- + webInfRealPathFile.isAbsolute()
- + "; canRead()="
- + webInfRealPathFile.canRead()
- + "; canWrite()="
- + webInfRealPathFile.canWrite()
- + "</td>");
- if (webInfRealPathFile.exists() && webInfRealPathFile.isDirectory())
- {
- File webxml = new File(webInfRealPathFile, "web.xml");
- pout.write("</tr><tr>\n");
- pout.write("<th align=\"right\" valign=\"top\">" + "new File(getServletContext().getRealPath(\"/WEB-INF/web.xml\"))" + ":&nbsp;</th>");
- pout.write("<td>exists()=" + webxml.exists()
- + "; isFile()="
- + webxml.isFile()
- + "; isDirectory()="
- + webxml.isDirectory()
- + "; isAbsolute()="
- + webxml.isAbsolute()
- + "; canRead()="
- + webxml.canRead()
- + "; canWrite()="
- + webxml.canWrite()
- + "</td>");
- }
- }
- catch (Throwable t)
- {
- pout.write("<th align=\"right\" valign=\"top\">" + "Error probing the java.io.File(getServletContext().getRealPath(\"/WEB-INF/\"))"
- + ":&nbsp;</th>");
- pout.write("<td>" + t + "</td>");
- }
- }
-
- pout.write("</tr><tr>\n");
- pout.write("<th align=\"right\" valign=\"top\">" + "getServletContext().getServerInfo()" + ":&nbsp;</th>");
- pout.write("<td>" + getServletContext().getServerInfo() + "</td>");
- pout.write("</tr><tr>\n");
- pout.write("<th align=\"right\" valign=\"top\">" + "getServletContext().getServletContextName()" + ":&nbsp;</th>");
- pout.write("<td>" + getServletContext().getServletContextName() + "</td>");
-
- pout.write("</tr><tr>\n");
- pout.write("<th align=\"left\" colspan=\"2\"><big><br/>Context InitParameters:</big></th>");
- a = getServletContext().getInitParameterNames();
- while (a.hasMoreElements())
- {
- name = (String) a.nextElement();
- pout.write("</tr><tr>\n");
- pout.write("<th align=\"right\" valign=\"top\">" + name.replace(".", " .") + ":&nbsp;</th>");
- pout.write("<td>" + toString(getServletContext().getInitParameter(name)) + "</td>");
- }
-
- pout.write("</tr><tr>\n");
- pout.write("<th align=\"left\" colspan=\"2\"><big><br/>Context Attributes:</big></th>");
- a = getServletContext().getAttributeNames();
- while (a.hasMoreElements())
- {
- name = (String) a.nextElement();
- pout.write("</tr><tr>\n");
- pout.write("<th align=\"right\" valign=\"top\">" + name.replace(".", " .") + ":&nbsp;</th>");
- pout.write("<td>" + "<pre>" + toString(getServletContext().getAttribute(name)) + "</pre>" + "</td>");
- }
-
- String res = request.getParameter("resource");
- if (res != null && res.length() > 0)
- {
- pout.write("</tr><tr>\n");
- pout.write("<th align=\"left\" colspan=\"2\"><big><br/>Get Resource: \"" + res + "\"</big></th>");
-
- pout.write("</tr><tr>\n");
- pout.write("<th align=\"right\">getServletContext().getContext(...):&nbsp;</th>");
-
- ServletContext context = getServletContext().getContext(res);
- pout.write("<td>" + context + "</td>");
-
- if (context != null)
- {
- String cp = context.getContextPath();
- if (cp == null || "/".equals(cp)) cp = "";
- pout.write("</tr><tr>\n");
- pout.write("<th align=\"right\">getServletContext().getContext(...),getRequestDispatcher(...):&nbsp;</th>");
- pout.write("<td>" + getServletContext().getContext(res).getRequestDispatcher(res.substring(cp.length())) + "</td>");
- }
-
- pout.write("</tr><tr>\n");
- pout.write("<th align=\"right\">this.getClass().getResource(...):&nbsp;</th>");
- pout.write("<td>" + this.getClass().getResource(res) + "</td>");
-
- pout.write("</tr><tr>\n");
- pout.write("<th align=\"right\">this.getClass().getClassLoader().getResource(...):&nbsp;</th>");
- pout.write("<td>" + this.getClass().getClassLoader().getResource(res) + "</td>");
-
- pout.write("</tr><tr>\n");
- pout.write("<th align=\"right\">Thread.currentThread().getContextClassLoader().getResource(...):&nbsp;</th>");
- pout.write("<td>" + Thread.currentThread().getContextClassLoader().getResource(res) + "</td>");
-
- pout.write("</tr><tr>\n");
- pout.write("<th align=\"right\">getServletContext().getResource(...):&nbsp;</th>");
- try
- {
- pout.write("<td>" + getServletContext().getResource(res) + "</td>");
- }
- catch (Exception e)
- {
- pout.write("<td>" + "" + e + "</td>");
- }
- }
-
- pout.write("</tr></table>\n");
-
- /* ------------------------------------------------------------ */
- pout.write("<h2>Request Wrappers</h2>\n");
- ServletRequest rw = request;
- int w = 0;
- while (rw != null)
- {
- pout.write((w++) + ": " + rw.getClass().getName() + "<br/>");
- if (rw instanceof HttpServletRequestWrapper)
- rw = ((HttpServletRequestWrapper) rw).getRequest();
- else if (rw instanceof ServletRequestWrapper)
- rw = ((ServletRequestWrapper) rw).getRequest();
- else
- rw = null;
- }
-
- /* ------------------------------------------------------------ */
- pout.write("<h2>Response Wrappers</h2>\n");
- ServletResponse rsw = response;
- w = 0;
- while (rsw != null)
- {
- pout.write((w++) + ": " + rsw.getClass().getName() + "<br/>");
- if (rsw instanceof HttpServletResponseWrapper)
- rsw = ((HttpServletResponseWrapper) rsw).getResponse();
- else if (rsw instanceof ServletResponseWrapper)
- rsw = ((ServletResponseWrapper) rsw).getResponse();
- else
- rsw = null;
- }
-
- pout.write("<br/>");
- pout.write("<h2>International Characters (UTF-8)</h2>");
- pout.write("LATIN LETTER SMALL CAPITAL AE<br/>\n");
- pout.write("Directly uni encoded(\\u1d01): \u1d01<br/>");
- pout.write("HTML reference (&amp;AElig;): &AElig;<br/>");
- pout.write("Decimal (&amp;#7425;): &#7425;<br/>");
- pout.write("Javascript unicode (\\u1d01) : <script language='javascript'>document.write(\"\u1d01\");</script><br/>");
- pout.write("<br/>");
- pout.write("<h2>Form to generate GET content</h2>");
- pout.write("<form method=\"GET\" action=\"" + response.encodeURL(getURI(request)) + "\">");
- pout.write("TextField: <input type=\"text\" name=\"TextField\" value=\"value\"/><br/>\n");
- pout.write("<input type=\"submit\" name=\"Action\" value=\"Submit\">");
- pout.write("</form>");
-
- pout.write("<br/>");
-
- pout.write("<h2>Form to generate POST content</h2>");
- pout.write("<form method=\"POST\" accept-charset=\"utf-8\" action=\"" + response.encodeURL(getURI(request)) + "\">");
- pout.write("TextField: <input type=\"text\" name=\"TextField\" value=\"value\"/><br/>\n");
- pout.write("Select: <select multiple name=\"Select\">\n");
- pout.write("<option>ValueA</option>");
- pout.write("<option>ValueB1,ValueB2</option>");
- pout.write("<option>ValueC</option>");
- pout.write("</select><br/>");
- pout.write("<input type=\"submit\" name=\"Action\" value=\"Submit\"><br/>");
- pout.write("</form>");
- pout.write("<br/>");
-
- pout.write("<h2>Form to generate UPLOAD content</h2>");
- pout.write("<form method=\"POST\" enctype=\"multipart/form-data\" accept-charset=\"utf-8\" action=\"" + response.encodeURL(getURI(request))
- + (request.getQueryString() == null ? "" : ("?" + request.getQueryString()))
- + "\">");
- pout.write("TextField: <input type=\"text\" name=\"TextField\" value=\"comment\"/><br/>\n");
- pout.write("File 1: <input type=\"file\" name=\"file1\" /><br/>\n");
- pout.write("File 2: <input type=\"file\" name=\"file2\" /><br/>\n");
- pout.write("<input type=\"submit\" name=\"Action\" value=\"Submit\"><br/>");
- pout.write("</form>");
-
- pout.write("<h2>Form to set Cookie</h2>");
- pout.write("<form method=\"POST\" action=\"" + response.encodeURL(getURI(request)) + "\">");
- pout.write("cookie: <input type=\"text\" name=\"cookie\" /><br/>\n");
- pout.write("value: <input type=\"text\" name=\"cookiev\" /><br/>\n");
- pout.write("<input type=\"submit\" name=\"Action\" value=\"setCookie\">");
- pout.write("</form>\n");
-
- pout.write("<h2>Form to get Resource</h2>");
- pout.write("<form method=\"POST\" action=\"" + response.encodeURL(getURI(request)) + "\">");
- pout.write("resource: <input type=\"text\" name=\"resource\" /><br/>\n");
- pout.write("<input type=\"submit\" name=\"Action\" value=\"getResource\">");
- pout.write("</form>\n");
-
- pout.write("<h2>Form to test a JDBC connection URL</h2>");
- String jdbcUser = request.getParameter("jdbc-user");
- if (jdbcUser == null || jdbcUser.length() == 0) jdbcUser = "root";
- String jdbcPass = request.getParameter("jdbc-pass");
- if (jdbcPass == null) jdbcPass = "";
- String jdbcDriverr = request.getParameter("jdbc-driver");
- if (jdbcDriverr == null || jdbcDriverr.length() == 0) jdbcDriverr = "com.mysql.jdbc.Driver";
- String jdbcQuery = request.getParameter("jdbc-query");
- if (jdbcQuery == null || jdbcQuery.length() == 0) jdbcQuery = "show tables;";
- String jdbcUrll = request.getParameter("jdbc-url");
- if (jdbcUrll == null || jdbcUrll.length() == 0) jdbcUrll = "jdbc:mysql://127.0.0.1:3306/example";
- pout.write("<form method=\"POST\" accept-charset=\"utf-8\" action=\"" + response.encodeURL(getURI(request)) + "\">");
- pout.write("JDBC Driver class: <input type=\"text\" name=\"jdbc-driver\" value=\"" + jdbcDriverr + "\"/><br/>\n");
- pout.write("JDBC URL: <input type=\"text\" name=\"jdbc-url\" value=\"" + jdbcUrll + "\"/><br/>\n");
- pout.write("JDBC Username: <input type=\"text\" name=\"jdbc-user\" value=\"" + jdbcUser + "\"/><br/>\n");
- pout.write("JDBC Password: <input type=\"text\" name=\"jdbc-pass\" value=\"" + jdbcPass + "\"/><br/>\n");
- pout.write("JDBC Query: <input type=\"text\" name=\"jdbc-query\" value=\"" + jdbcQuery + "\"/><br/>\n");
- pout.write("<input type=\"submit\" name=\"Action\" value=\"Submit\"><br/>");
- pout.write("</form>");
- pout.write("<br/>");
-
- }
- catch (Exception e)
- {
- getServletContext().log("dump", e);
- }
-
- String lines = request.getParameter("lines");
- if (lines != null)
- {
- char[] line = "<span>A line of characters. Blah blah blah blah. blooble blooble</span></br>\n".toCharArray();
- for (int l = Integer.parseInt(lines); l-- > 0;)
- {
- pout.write("<span>" + l + " </span>");
- pout.write(line);
- }
- }
-
- pout.write("</body>\n</html>\n");
-
- pout.close();
-
- if (pi != null)
- {
- if ("/ex4".equals(pi)) throw new ServletException("test ex4", new Throwable());
- if ("/ex5".equals(pi)) throw new IOException("test ex5");
- if ("/ex6".equals(pi)) throw new UnavailableException("test ex6");
- }
-
- }
-
- /* ------------------------------------------------------------ */
- @Override
- public String getServletInfo()
- {
- return "Dump Servlet";
- }
-
- /* ------------------------------------------------------------ */
- @Override
- public synchronized void destroy()
- {
- }
-
- /* ------------------------------------------------------------ */
- private String getURI(HttpServletRequest request)
- {
- String uri = (String) request.getAttribute("javax.servlet.forward.request_uri");
- if (uri == null) uri = request.getRequestURI();
- return uri;
- }
-
- /* ------------------------------------------------------------ */
- private static String toString(Object o)
- {
- if (o == null) return null;
-
- try
- {
- if (o.getClass().isArray())
- {
- StringBuffer sb = new StringBuffer();
- if (!o.getClass().getComponentType().isPrimitive())
- {
- Object[] array = (Object[]) o;
- for (int i = 0; i < array.length; i++)
- {
- if (i > 0) sb.append("\n");
- sb.append(array.getClass().getComponentType().getName());
- sb.append("[");
- sb.append(i);
- sb.append("]=");
- sb.append(toString(array[i]));
- }
- return sb.toString();
- }
- else
- {
- int length = Array.getLength(o);
- for (int i = 0; i < length; i++)
- {
- if (i > 0) sb.append("\n");
- sb.append(o.getClass().getComponentType().getName());
- sb.append("[");
- sb.append(i);
- sb.append("]=");
- sb.append(toString(Array.get(o, i)));
- }
- return sb.toString();
- }
- }
- else
- return o.toString();
- }
- catch (Exception e)
- {
- return e.toString();
- }
- }
-
- private boolean dump(HttpServletResponse response, String data, String chars, String block, String dribble, boolean flush) throws IOException
- {
- if (data != null && data.length() > 0)
- {
- long d = Long.parseLong(data);
- int b = (block != null && block.length() > 0) ? Integer.parseInt(block) : 50;
- byte[] buf = new byte[b];
- for (int i = 0; i < b; i++)
- {
-
- buf[i] = (byte) ('0' + (i % 10));
- if (i % 10 == 9) buf[i] = (byte) '\n';
- }
- buf[0] = 'o';
- OutputStream out = response.getOutputStream();
- response.setContentType("text/plain");
- while (d > 0)
- {
- if (b == 1)
- {
- out.write(d % 80 == 0 ? '\n' : '.');
- d--;
- }
- else if (d >= b)
- {
- out.write(buf);
- d = d - b;
- }
- else
- {
- out.write(buf, 0, (int) d);
- d = 0;
- }
-
- if (dribble != null)
- {
- out.flush();
- try
- {
- Thread.sleep(Long.parseLong(dribble));
- }
- catch (Exception e)
- {
- e.printStackTrace();
- break;
- }
- }
-
- }
-
- if (flush) out.flush();
-
- return true;
- }
-
- // Handle a dump of data
- if (chars != null && chars.length() > 0)
- {
- long d = Long.parseLong(chars);
- int b = (block != null && block.length() > 0) ? Integer.parseInt(block) : 50;
- char[] buf = new char[b];
- for (int i = 0; i < b; i++)
- {
- buf[i] = (char) ('0' + (i % 10));
- if (i % 10 == 9) buf[i] = '\n';
- }
- buf[0] = 'o';
- response.setContentType("text/plain");
- PrintWriter out = response.getWriter();
- while (d > 0 && !out.checkError())
- {
- if (b == 1)
- {
- out.write(d % 80 == 0 ? '\n' : '.');
- d--;
- }
- else if (d >= b)
- {
- out.write(buf);
- d = d - b;
- }
- else
- {
- out.write(buf, 0, (int) d);
- d = 0;
- }
- }
- return true;
- }
- return false;
- }
-
- private String notag(String s)
- {
- if (s == null) return "null";
- s = replace(s, "&", "&amp;");
- s = replace(s, "<", "&lt;");
- s = replace(s, ">", "&gt;");
- return s;
- }
-
- /**
- * replace substrings within string.
- */
- public static String replace(String s, String sub, String with)
- {
- int c = 0;
- int i = s.indexOf(sub, c);
- if (i == -1) return s;
-
- StringBuffer buf = new StringBuffer(s.length() + with.length());
-
- synchronized (buf)
- {
- do
- {
- buf.append(s.substring(c, i));
- buf.append(with);
- c = i + sub.length();
- }
- while ((i = s.indexOf(sub, c)) != -1);
-
- if (c < s.length()) buf.append(s.substring(c, s.length()));
-
- return buf.toString();
- }
- }
-}
diff --git a/jetty-osgi/jetty-osgi-servletbridge/src/main/java/org/eclipse/jetty/osgi/servletbridge/BridgeServletExtended.java b/jetty-osgi/jetty-osgi-servletbridge/src/main/java/org/eclipse/jetty/osgi/servletbridge/BridgeServletExtended.java
deleted file mode 100644
index 499b687d8a..0000000000
--- a/jetty-osgi/jetty-osgi-servletbridge/src/main/java/org/eclipse/jetty/osgi/servletbridge/BridgeServletExtended.java
+++ /dev/null
@@ -1,56 +0,0 @@
-//
-// ========================================================================
-// Copyright (c) 1995-2012 Mort Bay Consulting Pty. Ltd.
-// ------------------------------------------------------------------------
-// All rights reserved. This program and the accompanying materials
-// are made available under the terms of the Eclipse Public License v1.0
-// and Apache License v2.0 which accompanies this distribution.
-//
-// The Eclipse Public License is available at
-// http://www.eclipse.org/legal/epl-v10.html
-//
-// The Apache License v2.0 is available at
-// http://www.opensource.org/licenses/apache2.0.php
-//
-// You may elect to redistribute this code under either of these licenses.
-// ========================================================================
-//
-
-import java.io.IOException;
-
-import javax.servlet.ServletException;
-import javax.servlet.http.HttpServletRequest;
-import javax.servlet.http.HttpServletResponse;
-
-import org.eclipse.equinox.servletbridge.BridgeServlet;
-
-/**
- * Override the BridgeServlet to report on whether equinox is actually started
- * or not in case it is started asynchronously.
- *
- * @author hmalphettes
- */
-public class BridgeServletExtended extends BridgeServlet
-{
-
- @Override
- protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException
- {
- if (FrameworkLauncherExtended.ASYNCH_START_IN_PROGRESS != null && req.getMethod().equals("GET"))
- {
- if (FrameworkLauncherExtended.ASYNCH_START_IN_PROGRESS)
- {
- resp.getWriter().append("Equinox is currently starting...\n");
- return;
- }
- else if (FrameworkLauncherExtended.ASYNCH_START_FAILURE != null)
- {
- resp.getWriter().append("Equinox failed to start:\n");
- FrameworkLauncherExtended.ASYNCH_START_FAILURE.printStackTrace(resp.getWriter());
- return;
- }
- }
- super.service(req, resp);
- }
-
-}
diff --git a/jetty-osgi/jetty-osgi-servletbridge/src/main/java/org/eclipse/jetty/osgi/servletbridge/FrameworkLauncherExtended.java b/jetty-osgi/jetty-osgi-servletbridge/src/main/java/org/eclipse/jetty/osgi/servletbridge/FrameworkLauncherExtended.java
deleted file mode 100644
index e4470e60dd..0000000000
--- a/jetty-osgi/jetty-osgi-servletbridge/src/main/java/org/eclipse/jetty/osgi/servletbridge/FrameworkLauncherExtended.java
+++ /dev/null
@@ -1,716 +0,0 @@
-//
-// ========================================================================
-// Copyright (c) 1995-2012 Mort Bay Consulting Pty. Ltd.
-// ------------------------------------------------------------------------
-// All rights reserved. This program and the accompanying materials
-// are made available under the terms of the Eclipse Public License v1.0
-// and Apache License v2.0 which accompanies this distribution.
-//
-// The Eclipse Public License is available at
-// http://www.eclipse.org/legal/epl-v10.html
-//
-// The Apache License v2.0 is available at
-// http://www.opensource.org/licenses/apache2.0.php
-//
-// You may elect to redistribute this code under either of these licenses.
-// ========================================================================
-//
-
-import java.io.BufferedReader;
-import java.io.File;
-import java.io.FileFilter;
-import java.io.FileInputStream;
-import java.io.FileOutputStream;
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.InputStreamReader;
-import java.lang.reflect.Field;
-import java.lang.reflect.Method;
-import java.net.MalformedURLException;
-import java.net.URL;
-import java.util.Properties;
-import java.util.TreeMap;
-import java.util.jar.Attributes;
-import java.util.jar.JarOutputStream;
-import java.util.jar.Manifest;
-import java.util.zip.ZipEntry;
-
-import org.eclipse.equinox.servletbridge.FrameworkLauncher;
-
-/**
- * Extend the servletbridge FrameworkLauncher to support launching an equinox
- * installation made by p2director.
- */
-public class FrameworkLauncherExtended extends FrameworkLauncher
-{
-
- /**
- * if the OSGI_INSTALL_AREA installed area is specified as a sytem property
- * and matches a Folder on the file system, we don't copy the whole eclipse
- * installation instead we use that folder as it is
- */
- private static final String DEPLOY_IN_PLACE_WHEN_INSTALL_AREA_IS_FOLDER = "org.eclipse.equinox.servletbridge.deployinplace"; //$NON-NLS-1$
-
- public static final String FRAMEWORK_BOOTDELEGATION = "org.osgi.framework.bootdelegation";
-
- private boolean deployedInPlace = false;
-
- private URL resourceBaseAsURL = null;
-
- protected static Boolean ASYNCH_START_IN_PROGRESS;
-
- protected static Throwable ASYNCH_START_FAILURE = null;
-
- /**
- * If the start is asynch we do it in a different thread and return
- * immediately.
- */
- @Override
- public synchronized void start()
- {
- if (ASYNCH_START_IN_PROGRESS == null && "true".equals(super.config.getInitParameter("asyncStart")))
- {
- final ClassLoader webappCl = Thread.currentThread().getContextClassLoader();
- Thread th = new Thread()
- {
- public void run()
- {
- Thread.currentThread().setContextClassLoader(webappCl);
- System.out.println("Jetty-Nested: Starting equinox asynchronously.");
- FrameworkLauncherExtended.this.start();
- System.out.println("Jetty-Nested: Finished starting equinox asynchronously.");
- }
- };
- ASYNCH_START_IN_PROGRESS = true;
- try
- {
- th.start();
- }
- catch (Throwable t)
- {
- ASYNCH_START_FAILURE = t;
- if (t instanceof RuntimeException)
- {
- throw (RuntimeException) t;
- }
- else
- {
- throw new RuntimeException("Equinox failed to start", t);
- }
- }
- finally
- {
- ASYNCH_START_IN_PROGRESS = false;
- }
- }
- else
- {
- System.out.println("Jetty-Nested: Starting equinox synchronously.");
- super.start();
- System.out.println("Jetty-Nested: Finished starting equinox synchronously.");
- }
- }
-
- /**
- * try to find the resource base for this webapp by looking for the launcher
- * initialization file.
- */
- protected void initResourceBase()
- {
- try
- {
- String resourceBaseStr = System.getProperty(OSGI_INSTALL_AREA);
- if (resourceBaseStr == null || resourceBaseStr.length() == 0)
- {
- resourceBaseStr = config.getInitParameter(OSGI_INSTALL_AREA);
- }
- if (resourceBaseStr != null && resourceBaseStr.length() != 0)
- {
- // If the path starts with a reference to a system property,
- // resolve it.
- resourceBaseStr = resolveSystemProperty(resourceBaseStr);
- if (resourceBaseStr.startsWith("/WEB-INF/"))
- {
- String rpath = context.getRealPath(resourceBaseStr);
- if (rpath != null)
- {
- File rpathFile = new File(rpath);
- if (rpathFile.exists() && rpathFile.isDirectory() && rpathFile.canWrite())
- {
- resourceBaseStr = rpath;
- }
- }
- }
-
- if (resourceBaseStr.startsWith("file://"))
- {
- resourceBaseAsURL = new URL(resourceBaseStr.replace(" ", "%20")); //$NON-NLS-1$ //$NON-NLS-2$
- }
- else if (new File(resourceBaseStr).exists())
- {
- resourceBaseAsURL = new URL("file://" + new File(resourceBaseStr).getCanonicalPath().replace(" ", "%20")); //$NON-NLS-1$ //$NON-NLS-2$
- }
- else
- {
- resourceBaseAsURL = context.getResource(resourceBaseStr);
- }
- }
- else
- {
- if (context.getResource(RESOURCE_BASE + ECLIPSE) != null)
- {
- resourceBase = RESOURCE_BASE + ECLIPSE;
- }
- else
- {
- super.initResourceBase();
- }
- resourceBaseAsURL = context.getResource(resourceBase);
- }
- }
- catch (MalformedURLException e)
- {
- // ignore
- }
- catch (IOException e)
- {
- // ignore
- }
- if (resourceBaseAsURL != null && resourceBaseAsURL.getProtocol().equals("file"))
- {
- File resBase = new File(resourceBaseAsURL.getPath());
- if (resBase.exists() && resBase.isDirectory()
- && !Boolean.FALSE.toString().equalsIgnoreCase(System.getProperty(DEPLOY_IN_PLACE_WHEN_INSTALL_AREA_IS_FOLDER)))
- {
- __setPlatformDirectory(resBase);
- deployedInPlace = true;
- }
- }
- }
-
- /**
- * Override this method to be able to set default system properties computed
- * on the fly depending on the environment where equinox and jetty-osgi are
- * deployed.
- *
- * @param resource - The target to read properties from
- * @return the properties
- */
- protected Properties loadProperties(String resource)
- {
- Properties props = super.loadProperties(resource);
- if (resource.equals(resourceBase + LAUNCH_INI) && deployedInPlace)
- {
- String osgiInstall = props.getProperty(OSGI_INSTALL_AREA);
- if (osgiInstall == null)
- {
- // compute the osgi install dynamically.
- props.put(OSGI_INSTALL_AREA, getPlatformDirectory().getAbsolutePath());
- }
- String osgiFramework = props.getProperty(OSGI_FRAMEWORK);
- File pluginsFolder = null;
- if (osgiFramework == null && getPlatformDirectory() != null)
- {
- File osgiFrameworkF = findOsgiFramework(getPlatformDirectory());
- pluginsFolder = osgiFrameworkF.getParentFile();
- props.put(OSGI_FRAMEWORK, osgiFrameworkF.getAbsoluteFile().getAbsolutePath());
- }
- String osgiFrameworkExtensions = props.getProperty(OSGI_FRAMEWORK_EXTENSIONS);
- if (osgiFrameworkExtensions == null)
- {
- // this bundle will make the javax.servlet and
- // javax.servlet.http packages passed from
- // the bootstrap classloader into equinox
- osgiFrameworkExtensions = "org.eclipse.equinox.servletbridge.extensionbundle";
- }
- File configIni = new File(getPlatformDirectory(), "configuration/config.ini");
- Properties configIniProps = new Properties();
- if (configIni.exists())
- {
- System.out.println("Got the " + configIni.getAbsolutePath());
- InputStream configIniStream = null;
- try
- {
- configIniStream = new FileInputStream(configIni);
- configIniProps.load(configIniStream);
- }
- catch (IOException ioe)
- {
-
- }
- finally
- {
- try
- {
- configIniStream.close();
- }
- catch (IOException ioe2)
- {
- }
- }
- String confIniFrameworkExt = configIniProps.getProperty(OSGI_FRAMEWORK_EXTENSIONS);
- if (confIniFrameworkExt != null)
- {
- osgiFrameworkExtensions = osgiFrameworkExtensions + "," + confIniFrameworkExt;
- }
- }
- else
- {
- System.out.println("Unable to locate the " + configIni.getAbsolutePath());
- }
- props.setProperty(OSGI_FRAMEWORK_EXTENSIONS, osgiFrameworkExtensions);
- // __deployExtensionBundle(pluginsFolder);
- deployExtensionBundle(pluginsFolder, true);
-
- String bootDeleg = props.getProperty(FRAMEWORK_BOOTDELEGATION);
- if (bootDeleg == null)
- {
- bootDeleg = configIniProps.getProperty(FRAMEWORK_BOOTDELEGATION);
- }
- if (bootDeleg == null || bootDeleg.indexOf("javax.servlet.http") == -1)
- {
- String add = "javax.servlet,javax.servlet.http,javax.servlet.resources";
- if (bootDeleg != null)
- {
- bootDeleg += add;
- }
- else
- {
- bootDeleg = add;
- }
- props.setProperty(FRAMEWORK_BOOTDELEGATION, bootDeleg);
- }
-
- String jettyHome = System.getProperty("jetty.home");
- if (jettyHome == null)
- {
- jettyHome = getPlatformDirectory().getAbsolutePath();
- System.setProperty("jetty.home", jettyHome);
- props.setProperty("jetty.home", jettyHome);
- }
- else
- {
- jettyHome = resolveSystemProperty(jettyHome);
- }
- String etcJettyXml = System.getProperty("jetty.etc.config.urls");
- if (etcJettyXml == null)
- {
- etcJettyXml = "etc/jetty.xml";
- if (new File(jettyHome, "etc/jetty-nested.xml").exists())
- {
- etcJettyXml += ",etc/jetty-nested.xml";
- }
- System.setProperty("jetty.etc.config.urls", etcJettyXml);
- props.setProperty("jetty.etc.config.urls", etcJettyXml);
- }
- String startLevel = System.getProperty("osgi.startLevel");
- if (startLevel == null)
- {
- startLevel = props.getProperty("osgi.startLevel");
- if (startLevel == null)
- {
- startLevel = configIniProps.getProperty("osgi.startLevel");
- }
- if (startLevel != null)
- {
- props.setProperty("osgi.startLevel", startLevel);
- System.setProperty("osgi.startLevel", startLevel);
- }
- }
- String logback = System.getProperty("logback.configurationFile");
- if (logback == null)
- {
- File etcLogback = new File(jettyHome, "etc/logback-nested.xml");
- if (!etcLogback.exists())
- {
- etcLogback = new File(jettyHome, "etc/logback.xml");
- }
- if (etcLogback.exists())
- {
- System.setProperty("logback.configurationFile", etcLogback.getAbsolutePath());
- props.setProperty("logback.configurationFile", etcLogback.getAbsolutePath());
- }
- }
- else
- {
- logback = resolveSystemProperty(logback);
- }
- System.out.println("sysout: logback.configurationFile=" + System.getProperty("logback.configurationFile"));
- }
- return props;
- }
-
- /**
- * Look for the eclipse.ini file. or any *.ini Search for the argument
- * -startup The next line is a relative path to the launcher osgi bundle:
- * ../bundlepool/plugins/org.eclipse.equinox.launcher_1.1.0.v20100507.jar
- * Get that file, get the parent folder. This is where the plugins are
- * located. In that folder look for the
- *
- * @param installFolder
- * @return The osgi framework bundle.
- */
- private File findOsgiFramework(File installFolder)
- {
- File[] fs = installFolder.listFiles();
- for (int i = 0; i < fs.length; i++)
- {
- File f = fs[i];
- if (f.isFile() && f.getName().endsWith(".ini") && !f.getName().equals(LAUNCH_INI))
- {
- BufferedReader br = null;
- try
- {
- br = new BufferedReader(new InputStreamReader(new FileInputStream(f)));
- String line = null;
- String pathToLauncherJar = null;
- boolean gotStartArg = false;
- while ((line = br.readLine()) != null)
- {
- if (gotStartArg)
- {
- pathToLauncherJar = line.trim();
- if (pathToLauncherJar.length() == 0)
- {
- continue;
- }
- break;
- }
- else if (line.trim().equals("-startup"))
- {
- gotStartArg = true;
- }
- }
- if (pathToLauncherJar != null)
- {
- File currFolder = getPlatformDirectory();
- String oriStartup = pathToLauncherJar;
- while (pathToLauncherJar.startsWith("../"))
- {
- currFolder = currFolder.getParentFile();
- pathToLauncherJar = pathToLauncherJar.substring(3);
- }
- File pluginsfolder = new File(currFolder, pathToLauncherJar).getParentFile();
- // System.err.println("Got the pluginsfolder " +
- // pluginsfolder);
- if (!pluginsfolder.exists()) { throw new IllegalStateException("The -startup argument in " + f.getPath()
- + " is "
- + oriStartup
- + ". It points to "
- + pluginsfolder.getPath()
- + " plugins directory that does not exists."); }
- TreeMap osgis = new TreeMap();
- File[] plugins = pluginsfolder.listFiles();
- for (int j = 0; j < plugins.length; j++)
- {
- File b = plugins[j];
- if (b.isFile() && b.getName().startsWith(FRAMEWORK_BUNDLE_NAME + "_") && b.getName().endsWith(".jar"))
- {
- osgis.put(b.getName(), b);
- }
- }
- if (osgis.isEmpty()) { throw new IllegalStateException("The -startup argument in " + f.getPath()
- + " is "
- + oriStartup
- + ". It points to "
- + pluginsfolder.getPath()
- + " plugins directory but there is no org.eclipse.osgi.*.jar files there."); }
- File osgiFramework = (File) osgis.values().iterator().next();
- String path = osgiFramework.getPath();
- System.err.println("Using " + path + " for the osgi framework.");
- return osgiFramework;
- }
- }
- catch (IOException ioe)
- {
- //
- }
- finally
- {
- if (br != null) try
- {
- br.close();
- }
- catch (IOException ii)
- {
- }
- }
-
- }
- }
- return null;
- }
-
- /**
- * recursively substitute the ${sysprop} by their actual system property.
- * ${sysprop,defaultvalue} will use 'defaultvalue' as the value if no
- * sysprop is defined. Not the most efficient code but we are shooting for
- * simplicity and speed of development here.
- *
- * @param value
- * @return
- */
- public static String resolveSystemProperty(String value)
- {
- int ind = value.indexOf("${");
- if (ind == -1) { return value; }
- int ind2 = value.indexOf('}', ind);
- if (ind2 == -1) { return value; }
- String sysprop = value.substring(ind + 2, ind2);
- String defaultValue = null;
- int comma = sysprop.indexOf(',');
- if (comma != -1 && comma + 1 != sysprop.length())
- {
- defaultValue = sysprop.substring(comma + 1);
- defaultValue = resolveSystemProperty(defaultValue);
- sysprop = sysprop.substring(0, comma);
- }
- else
- {
- defaultValue = "${" + sysprop + "}";
- }
-
- String v = System.getProperty(sysprop);
-
- String reminder = value.length() > ind2 + 1 ? value.substring(ind2 + 1) : "";
- reminder = resolveSystemProperty(reminder);
- if (v != null)
- {
- return value.substring(0, ind) + v + reminder;
- }
- else
- {
- return value.substring(0, ind) + defaultValue + reminder;
- }
- }
-
- // introspection trick to be able to set the private field platformDirectory
- private static Field _field;
-
- void __setPlatformDirectory(File platformDirectory)
- {
- try
- {
- if (_field == null)
- {
- _field = org.eclipse.equinox.servletbridge.FrameworkLauncher.class.getDeclaredField("platformDirectory");
- _field.setAccessible(true);
- }
- _field.set(this, platformDirectory);
- }
- catch (SecurityException e)
- {
- e.printStackTrace();
- }
- catch (NoSuchFieldException e)
- {
- e.printStackTrace();
- }
- catch (IllegalArgumentException e)
- {
- e.printStackTrace();
- }
- catch (IllegalAccessException e)
- {
- e.printStackTrace();
- }
- }
-
- // introspection trick to invoke the generateExtensionBundle method
- private static Method _deployExtensionBundleMethod;
-
- private void __deployExtensionBundle(File plugins)
- {
- // look for the extensionbundle
- // if it is already there no need to do something:
- for (String file : plugins.list())
- {
- if (file.startsWith("org.eclipse.equinox.servletbridge.extensionbundle"))// EXTENSIONBUNDLE_DEFAULT_BSN
- { return; }
- }
-
- try
- {
- // invoke deployExtensionBundle(File plugins)
- if (_deployExtensionBundleMethod == null)
- {
- _deployExtensionBundleMethod = FrameworkLauncher.class.getDeclaredMethod("deployExtensionBundle", File.class);
- _deployExtensionBundleMethod.setAccessible(true);
- }
- _deployExtensionBundleMethod.invoke(this, plugins);
- }
- catch (Throwable t)
- {
- t.printStackTrace();
- }
- }
-
- // --end of introspection to invoke deployExtensionBundle
-
- // from Framework with support for the equinox hook
- private static final String EXTENSIONBUNDLE_DEFAULT_BSN = "org.eclipse.equinox.servletbridge.extensionbundle"; //$NON-NLS-1$
-
- private static final String EXTENSIONBUNDLE_DEFAULT_VERSION = "1.2.0"; //$NON-NLS-1$
-
- private static final String MANIFEST_VERSION = "Manifest-Version"; //$NON-NLS-1$
-
- private static final String BUNDLE_MANIFEST_VERSION = "Bundle-ManifestVersion"; //$NON-NLS-1$
-
- private static final String BUNDLE_NAME = "Bundle-Name"; //$NON-NLS-1$
-
- private static final String BUNDLE_SYMBOLIC_NAME = "Bundle-SymbolicName"; //$NON-NLS-1$
-
- private static final String BUNDLE_VERSION = "Bundle-Version"; //$NON-NLS-1$
-
- private static final String FRAGMENT_HOST = "Fragment-Host"; //$NON-NLS-1$
-
- private static final String EXPORT_PACKAGE = "Export-Package"; //$NON-NLS-1$
-
- private static final String CONFIG_EXTENDED_FRAMEWORK_EXPORTS = "extendedFrameworkExports"; //$NON-NLS-1$
-
- private void deployExtensionBundle(File plugins, boolean configureEquinoxHook)
- {
- // we might want to parameterize the extension bundle BSN in the future
- final String extensionBundleBSN = EXTENSIONBUNDLE_DEFAULT_BSN;
- File extensionBundleFile = findExtensionBundleFile(plugins, extensionBundleBSN);
-
- if (extensionBundleFile == null)
- generateExtensionBundle(plugins, extensionBundleBSN, EXTENSIONBUNDLE_DEFAULT_VERSION, configureEquinoxHook);
- else
- /*
- * if (Boolean.valueOf(config.getInitParameter(
- * CONFIG_OVERRIDE_AND_REPLACE_EXTENSION_BUNDLE)).booleanValue())
- */{
- String extensionBundleVersion = findExtensionBundleVersion(extensionBundleFile, extensionBundleBSN);
- if (extensionBundleFile.isDirectory())
- {
- deleteDirectory(extensionBundleFile);
- }
- else
- {
- extensionBundleFile.delete();
- }
- generateExtensionBundle(plugins, extensionBundleBSN, extensionBundleVersion, true);
- // } else {
- // processExtensionBundle(extensionBundleFile);
- }
- }
-
- private File findExtensionBundleFile(File plugins, final String extensionBundleBSN)
- {
- FileFilter extensionBundleFilter = new FileFilter()
- {
- public boolean accept(File candidate)
- {
- return candidate.getName().startsWith(extensionBundleBSN + "_"); //$NON-NLS-1$
- }
- };
- File[] extensionBundles = plugins.listFiles(extensionBundleFilter);
- if (extensionBundles.length == 0) return null;
-
- if (extensionBundles.length > 1)
- {
- for (int i = 1; i < extensionBundles.length; i++)
- {
- if (extensionBundles[i].isDirectory())
- {
- deleteDirectory(extensionBundles[i]);
- }
- else
- {
- extensionBundles[i].delete();
- }
- }
- }
- return extensionBundles[0];
- }
-
- private String findExtensionBundleVersion(File extensionBundleFile, String extensionBundleBSN)
- {
- String fileName = extensionBundleFile.getName();
- if (fileName.endsWith(".jar")) { return fileName.substring(extensionBundleBSN.length() + 1, fileName.length() - ".jar".length()); }
- return fileName.substring(extensionBundleBSN.length() + 1);
- }
-
- private void generateExtensionBundle(File plugins, String extensionBundleBSN, String extensionBundleVersion, boolean configureEquinoxHook)
- {
- Manifest mf = new Manifest();
- Attributes attribs = mf.getMainAttributes();
- attribs.putValue(MANIFEST_VERSION, "1.0"); //$NON-NLS-1$
- attribs.putValue(BUNDLE_MANIFEST_VERSION, "2"); //$NON-NLS-1$
- attribs.putValue(BUNDLE_NAME, "Servletbridge Extension Bundle"); //$NON-NLS-1$
- attribs.putValue(BUNDLE_SYMBOLIC_NAME, extensionBundleBSN);
- attribs.putValue(BUNDLE_VERSION, extensionBundleVersion);
- attribs.putValue(FRAGMENT_HOST, "system.bundle; extension:=framework"); //$NON-NLS-1$
-
- String servletVersion = context.getMajorVersion() + "." + context.getMinorVersion(); //$NON-NLS-1$
- String packageExports = "org.eclipse.equinox.servletbridge; version=1.1"
- + ", javax.servlet; version="
- + servletVersion
- + ", javax.servlet.http; version="
- + servletVersion
- + ", javax.servlet.resources; version="
- + servletVersion;
-
- String extendedExports = config.getInitParameter(CONFIG_EXTENDED_FRAMEWORK_EXPORTS);
- if (extendedExports != null && extendedExports.trim().length() != 0) packageExports += ", " + extendedExports; //$NON-NLS-1$
-
- attribs.putValue(EXPORT_PACKAGE, packageExports);
- writeJarFile(new File(plugins, extensionBundleBSN + "_" + extensionBundleVersion + ".jar"), mf, configureEquinoxHook); //$NON-NLS-1$
- }
-
- private void writeJarFile(File jarFile, Manifest mf, boolean configureEquinoxHook)
- {
- try
- {
- JarOutputStream jos = null;
- try
- {
- jos = new JarOutputStream(new FileOutputStream(jarFile), mf);
-
- if (configureEquinoxHook)
- {
- // hook configurator properties:
- ZipEntry e = new ZipEntry("hookconfigurators.properties");
- jos.putNextEntry(e);
- Properties props = new Properties();
- props.put("hook.configurators", "org.eclipse.jetty.osgi.servletbridge.hook.ServletBridgeClassLoaderDelegateHook");
- props.store(jos, "");
- jos.closeEntry();
-
- // the hook class
- e = new ZipEntry("org/eclipse/jetty/osgi/servletbridge/hook/ServletBridgeClassLoaderDelegateHook.class");
- jos.putNextEntry(e);
- InputStream in = getClass().getResourceAsStream("/org/eclipse/jetty/osgi/servletbridge/hook/ServletBridgeClassLoaderDelegateHook.class");
-
- byte[] buffer = new byte[512];
- try
- {
- int n;
- while ((n = in.read(buffer)) != -1)
- {
- jos.write(buffer, 0, n);
- }
- }
- finally
- {
- in.close();
- }
- jos.closeEntry();
- }
-
- jos.finish();
- }
- finally
- {
- if (jos != null) jos.close();
- }
- }
- catch (IOException e)
- {
- context.log("Error writing extension bundle", e); //$NON-NLS-1$
- }
- }
- // --from Framework with support for the equinox hook
-
-}
diff --git a/jetty-osgi/jetty-osgi-servletbridge/src/main/java/org/eclipse/jetty/osgi/servletbridge/hook/ServletBridgeClassLoaderDelegateHook.java b/jetty-osgi/jetty-osgi-servletbridge/src/main/java/org/eclipse/jetty/osgi/servletbridge/hook/ServletBridgeClassLoaderDelegateHook.java
deleted file mode 100644
index d6d6e63596..0000000000
--- a/jetty-osgi/jetty-osgi-servletbridge/src/main/java/org/eclipse/jetty/osgi/servletbridge/hook/ServletBridgeClassLoaderDelegateHook.java
+++ /dev/null
@@ -1,97 +0,0 @@
-//
-// ========================================================================
-// Copyright (c) 1995-2012 Mort Bay Consulting Pty. Ltd.
-// ------------------------------------------------------------------------
-// All rights reserved. This program and the accompanying materials
-// are made available under the terms of the Eclipse Public License v1.0
-// and Apache License v2.0 which accompanies this distribution.
-//
-// The Eclipse Public License is available at
-// http://www.eclipse.org/legal/epl-v10.html
-//
-// The Apache License v2.0 is available at
-// http://www.opensource.org/licenses/apache2.0.php
-//
-// You may elect to redistribute this code under either of these licenses.
-// ========================================================================
-//
-
-import java.io.FileNotFoundException;
-import java.net.URL;
-import java.util.Enumeration;
-import java.util.HashSet;
-import java.util.Set;
-
-import org.eclipse.core.runtime.adaptor.EclipseStarter;
-import org.eclipse.osgi.baseadaptor.HookConfigurator;
-import org.eclipse.osgi.baseadaptor.HookRegistry;
-import org.eclipse.osgi.framework.adaptor.BundleClassLoader;
-import org.eclipse.osgi.framework.adaptor.BundleData;
-import org.eclipse.osgi.framework.adaptor.ClassLoaderDelegateHook;
-import org.eclipse.osgi.internal.loader.BundleLoader;
-
-/**
- * With some complex osgi products, experience shows that using a system bundle
- * extension to pass certain packages from the bootstrapping server to equinox
- * fails. The bundles keep loading javax.servlet.http from the javax.servlet
- * bundle. This class is in fact copied into the servletbridge.extensionbundle;
- * it is not loaded by the webapp.
- */
-public class ServletBridgeClassLoaderDelegateHook implements ClassLoaderDelegateHook, HookConfigurator
-{
-
- private static Set<String> packagesInBootstrapClassLoader = new HashSet<String>();
- static
- {
- packagesInBootstrapClassLoader.add("javax.servlet");
- packagesInBootstrapClassLoader.add("javax.servlet.http");
- }
-
- public void addHooks(HookRegistry hookRegistry)
- {
- hookRegistry.addClassLoaderDelegateHook(this);
- }
-
- public Class preFindClass(String name, BundleClassLoader classLoader, BundleData data) throws ClassNotFoundException
- {
- String pkgName = BundleLoader.getPackageName(name);
- if (packagesInBootstrapClassLoader.contains(pkgName)) { return EclipseStarter.class.getClassLoader().loadClass(name); }
- return null;
- }
-
- public Class postFindClass(String name, BundleClassLoader classLoader, BundleData data) throws ClassNotFoundException
- {
- return null;
- }
-
- public URL preFindResource(String name, BundleClassLoader classLoader, BundleData data) throws FileNotFoundException
- {
- return null;
- }
-
- public URL postFindResource(String name, BundleClassLoader classLoader, BundleData data) throws FileNotFoundException
- {
- return null;
- }
-
- public Enumeration preFindResources(String name, BundleClassLoader classLoader, BundleData data) throws FileNotFoundException
- {
- return null;
- }
-
- public Enumeration postFindResources(String name, BundleClassLoader classLoader, BundleData data) throws FileNotFoundException
- {
- return null;
- }
-
- public String preFindLibrary(String name, BundleClassLoader classLoader, BundleData data) throws FileNotFoundException
- {
- return null;
- }
-
- public String postFindLibrary(String name, BundleClassLoader classLoader, BundleData data)
- {
- return null;
- }
-
-}
diff --git a/jetty-osgi/jetty-osgi-servletbridge/src/main/webapp/WEB-INF/web.xml b/jetty-osgi/jetty-osgi-servletbridge/src/main/webapp/WEB-INF/web.xml
deleted file mode 100644
index c61dee582d..0000000000
--- a/jetty-osgi/jetty-osgi-servletbridge/src/main/webapp/WEB-INF/web.xml
+++ /dev/null
@@ -1,67 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://java.sun.com/xml/ns/javaee" xmlns:web="http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" id="WebApp_ID" version="2.5">
- <display-name>jettyservletbridge</display-name>
- <servlet id="proxy">
- <servlet-name>proxy</servlet-name>
- <display-name>Transparent Proxy Servlet and Equinox Framework Controller</display-name>
- <description>Transparent Proxy Servlet and Equinox Framework Controller</description>
- <servlet-class>org.eclipse.jetty.osgi.servletbridge.BridgeServletExtended</servlet-class>
- <!-- Point to a folder where an equinox installation exists.
- When this parameter is defined, that equinox installation is launched in place.
- The parameter can also be passed as a system property. -->
- <init-param>
- <param-name>osgi.install.area</param-name>
- <param-value>/WEB-INF/eclipse</param-value>
- </init-param>
- <!-- Start equinox in a different thread and display a simple
- a simple status message until it is started. -->
- <init-param>
- <param-name>asyncStart</param-name>
- <param-value>true</param-value>
- </init-param>
- <init-param>
- <param-name>commandline</param-name>
- <param-value>-console</param-value>
- </init-param>
- <init-param>
- <param-name>enableFrameworkControls</param-name>
- <param-value>true</param-value>
- </init-param>
- <!--
- org.eclipse.equinox.servletbridge and the Servlet API are exported automatically to the underlying OSGi framework.
- The extendedFrameworkExports parameter allows the specification of additional java package exports.
- The format is a comma separated list of exports as specified by the "Export-Package" bundle manifest header.
- For example: com.mycompany.exports; version=1.0.0, com.mycompany.otherexports; version=1.0.0
- -->
- <init-param>
- <param-name>extendedFrameworkExports</param-name>
- <param-value></param-value>
- </init-param>
-
- <!--
- You can specify your own framework launcher here.
- The default is: org.eclipse.equinox.servletbridge.FrameworkLauncher -->
- <init-param>
- <param-name>frameworkLauncherClass</param-name>
- <param-value>org.eclipse.jetty.osgi.servletbridge.FrameworkLauncherExtended</param-value>
- <!--param-value>org.eclipse.equinox.servletbridge.FrameworkLauncher</param-value-->
- </init-param>
- <load-on-startup>1</load-on-startup>
- </servlet>
-
- <servlet>
- <servlet-name>dump</servlet-name>
- <servlet-class>org.eclipse.jetty.nested.Dump</servlet-class>
- <load-on-startup>1</load-on-startup>
- </servlet>
-
- <servlet-mapping>
- <servlet-name>dump</servlet-name>
- <url-pattern>/dump/*</url-pattern>
- </servlet-mapping>
- <servlet-mapping>
- <servlet-name>proxy</servlet-name>
- <url-pattern>/*</url-pattern>
- </servlet-mapping>
-
-</web-app> \ No newline at end of file
diff --git a/jetty-osgi/pom.xml b/jetty-osgi/pom.xml
index 63b9bd055c..7c61e8e3e0 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>7.6.8-SNAPSHOT</version>
+ <version>8.1.8-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>
<groupId>org.eclipse.jetty.osgi</groupId>
@@ -21,10 +21,8 @@
<modules>
<module>jetty-osgi-boot</module>
<module>jetty-osgi-boot-jsp</module>
- <module>jetty-osgi-boot-logback</module>
<module>jetty-osgi-boot-warurl</module>
<module>jetty-osgi-httpservice</module>
- <module>jetty-osgi-equinoxtools</module>
<module>test-jetty-osgi-webapp</module>
<module>test-jetty-osgi-context</module>
<module>test-jetty-osgi</module>
@@ -76,7 +74,7 @@
<dependencies>
<dependency>
<groupId>org.eclipse.jetty</groupId>
- <artifactId>jetty-server</artifactId>
+ <artifactId>jetty-annotations</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
@@ -144,6 +142,23 @@
<artifactId>servletbridge</artifactId>
<version>${equinox-servletbridge-version}</version>
</dependency-->
+ <!-- not ready <dependency>
+ <groupId>org.mortbay.jetty</groupId>
+ <artifactId>jsp-impl</artifactId>
+ <version>${jsp-impl-2.2-glassfish-version}</version>
+ </dependency-->
+<!--
+ <dependency>
+ <groupId>org.mortbay.jetty</groupId>
+ <artifactId>jsp-2.1-glassfish</artifactId>
+ <version>${jsp-2.1-glassfish-version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.mortbay.jetty</groupId>
+ <artifactId>jsp-api-2.1-glassfish</artifactId>
+ <version>${jsp-2.1-glassfish-version}</version>
+ </dependency>
+-->
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
diff --git a/jetty-osgi/test-jetty-osgi-context/pom.xml b/jetty-osgi/test-jetty-osgi-context/pom.xml
index 5b65bc00f1..48ca540fd9 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>7.6.8-SNAPSHOT</version>
+ <version>8.1.8-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>
<modelVersion>4.0.0</modelVersion>
@@ -16,6 +16,7 @@
<dependency>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-server</artifactId>
+ <version>${project.version}</version>
</dependency>
<dependency>
<groupId>org.eclipse.osgi</groupId>
@@ -120,7 +121,7 @@
org.xml.sax.helpers,
*
</Import-Package>
- <DynamicImport-Package>org.eclipse.jetty.*;version="[7.6,8)"</DynamicImport-Package>
+ <DynamicImport-Package>org.eclipse.jetty.*;version="[8.1,9)"</DynamicImport-Package>
<!--Require-Bundle/-->
<!-- Bundle-RequiredExecutionEnvironment>J2SE-1.5</Bundle-RequiredExecutionEnvironment -->
</instructions>
diff --git a/jetty-osgi/test-jetty-osgi-webapp/pom.xml b/jetty-osgi/test-jetty-osgi-webapp/pom.xml
index 3e4d27d4e2..f08fd1ad7f 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>7.6.8-SNAPSHOT</version>
+ <version>8.1.8-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>
<modelVersion>4.0.0</modelVersion>
@@ -117,7 +117,7 @@
org.xml.sax.helpers,
*
</Import-Package>
- <DynamicImport-Package>org.eclipse.jetty.*;version="[7.6,8)"</DynamicImport-Package>
+ <DynamicImport-Package>org.eclipse.jetty.*;version="[8.1,9)"</DynamicImport-Package>
<!--Require-Bundle/-->
<!-- Bundle-RequiredExecutionEnvironment>J2SE-1.5</Bundle-RequiredExecutionEnvironment -->
</instructions>
diff --git a/jetty-osgi/test-jetty-osgi/pom.xml b/jetty-osgi/test-jetty-osgi/pom.xml
index 5e321f0b9b..e11095f5d1 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>7.6.8-SNAPSHOT</version>
+ <version>8.1.8-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>
<modelVersion>4.0.0</modelVersion>
@@ -11,6 +11,7 @@
<description>Jetty OSGi Integration test</description>
<properties>
<bundle-symbolic-name>${project.groupId}.boot.test</bundle-symbolic-name>
+ <jetty-orbit-url>http://download.eclipse.org/jetty/orbit/</jetty-orbit-url>
<assembly-directory>target/distribution</assembly-directory>
<paxexam-version>1.2.0</paxexam-version>
</properties>
@@ -223,7 +224,7 @@
<version>${orbit-servlet-api-version}</version>
<overWrite>true</overWrite>
<outputDirectory>${assembly-directory}/lib</outputDirectory>
- <destFileName>servlet-api-2.5.jar</destFileName>
+ <destFileName>servlet-api-3.0.jar</destFileName>
</artifactItem>
</artifactItems>
</configuration>
diff --git a/jetty-osgi/test-jetty-osgi/src/test/java/org/eclipse/jetty/osgi/boot/TestJettyOSGiBootWebAppAsService.java b/jetty-osgi/test-jetty-osgi/src/test/java/org/eclipse/jetty/osgi/boot/TestJettyOSGiBootWebAppAsService.java
index ff82304b34..bbaeefb088 100644
--- a/jetty-osgi/test-jetty-osgi/src/test/java/org/eclipse/jetty/osgi/boot/TestJettyOSGiBootWebAppAsService.java
+++ b/jetty-osgi/test-jetty-osgi/src/test/java/org/eclipse/jetty/osgi/boot/TestJettyOSGiBootWebAppAsService.java
@@ -128,6 +128,7 @@ public class TestJettyOSGiBootWebAppAsService
* plus your testcase, wrapped into a bundle called pax-exam-probe
*/
@Test
+ @Ignore
public void listBundles() throws Exception
{
Map<String,Bundle> bundlesIndexedBySymbolicName = new HashMap<String, Bundle>();
diff --git a/jetty-osgi/test-jetty-osgi/src/test/java/org/eclipse/jetty/osgi/boot/TestJettyOSGiBootWithJsp.java b/jetty-osgi/test-jetty-osgi/src/test/java/org/eclipse/jetty/osgi/boot/TestJettyOSGiBootWithJsp.java
index 24eaa3b270..87adbddf8c 100644
--- a/jetty-osgi/test-jetty-osgi/src/test/java/org/eclipse/jetty/osgi/boot/TestJettyOSGiBootWithJsp.java
+++ b/jetty-osgi/test-jetty-osgi/src/test/java/org/eclipse/jetty/osgi/boot/TestJettyOSGiBootWithJsp.java
@@ -132,14 +132,14 @@ public class TestJettyOSGiBootWithJsp
* plus your testcase, wrapped into a bundle called pax-exam-probe
*/
@Test
-
+ @Ignore
public void listBundles() throws Exception
{
Map<String,Bundle> bundlesIndexedBySymbolicName = new HashMap<String, Bundle>();
for( Bundle b : bundleContext.getBundles() )
{
bundlesIndexedBySymbolicName.put(b.getSymbolicName(), b);
- System.err.println("Got " + b.getSymbolicName() + " " + b.getVersion().toString() + " " + b.getState());
+ System.err.println("Got " + b.getSymbolicName());
}
Bundle osgiBoot = bundlesIndexedBySymbolicName.get("org.eclipse.jetty.osgi.boot");
@@ -148,11 +148,11 @@ public class TestJettyOSGiBootWithJsp
Bundle osgiBootJsp = bundlesIndexedBySymbolicName.get("org.eclipse.jetty.osgi.boot.jsp");
Assert.assertNotNull("Could not find the org.eclipse.jetty.osgi.boot.jsp bundle", osgiBootJsp);
- Assert.assertTrue("The fragment jsp is not correctly resolved " + osgiBootJsp.getState(), osgiBootJsp.getState() == Bundle.RESOLVED);
+ Assert.assertTrue("The fragment jsp is not correctly resolved", osgiBootJsp.getState() == Bundle.RESOLVED);
Bundle testWebBundle = bundlesIndexedBySymbolicName.get("org.eclipse.jetty.test-jetty-webapp");
- Assert.assertNotNull("Could not find the org.eclipse.jetty.test-jetty-webapp bundle", osgiBootJsp);
- Assert.assertTrue("The bundle org.eclipse.jetty.test-jetty-webapp is not correctly resolved", testWebBundle.getState() == Bundle.ACTIVE);
+ Assert.assertNotNull("Could not find the test-jetty-webapp bundle", testWebBundle);
+ Assert.assertTrue("The test-jetty-webapp bundle is not correctly resolved", testWebBundle.getState() == Bundle.ACTIVE);
//now test the jsp/dump.jsp
HttpClient client = new HttpClient();
diff --git a/jetty-overlay-deployer/pom.xml b/jetty-overlay-deployer/pom.xml
index 5a11c02a89..c0b85bdbb6 100644
--- a/jetty-overlay-deployer/pom.xml
+++ b/jetty-overlay-deployer/pom.xml
@@ -2,7 +2,7 @@
<parent>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-project</artifactId>
- <version>7.6.8-SNAPSHOT</version>
+ <version>8.1.8-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>jetty-overlay-deployer</artifactId>
diff --git a/jetty-plus/pom.xml b/jetty-plus/pom.xml
index d5615a005d..c9abc52f92 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>7.6.8-SNAPSHOT</version>
+ <version>8.1.8-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>jetty-plus</artifactId>
@@ -28,7 +28,7 @@
<configuration>
<instructions>
<_versionpolicy> </_versionpolicy>
- <Import-Package>javax.sql.*,javax.security.*,javax.naming.*,javax.servlet.*;version="[2.5,3.0)",javax.transaction.*;version="[1.1,1.2)",*</Import-Package>
+ <Import-Package>javax.sql.*,javax.security.*,javax.naming.*,javax.servlet.*;version="2.6.0",javax.transaction.*;version="[1.1,1.2)",*</Import-Package>
</instructions>
</configuration>
</execution>
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
new file mode 100644
index 0000000000..9ba3dfc1b2
--- /dev/null
+++ b/jetty-plus/src/main/java/org/eclipse/jetty/plus/annotation/ContainerInitializer.java
@@ -0,0 +1,114 @@
+//
+// ========================================================================
+// Copyright (c) 1995-2012 Mort Bay Consulting Pty. Ltd.
+// ------------------------------------------------------------------------
+// All rights reserved. This program and the accompanying materials
+// are made available under the terms of the Eclipse Public License v1.0
+// and Apache License v2.0 which accompanies this distribution.
+//
+// The Eclipse Public License is available at
+// http://www.eclipse.org/legal/epl-v10.html
+//
+// The Apache License v2.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.plus.annotation;
+
+import java.util.HashSet;
+import java.util.Set;
+
+import javax.servlet.ServletContainerInitializer;
+import javax.servlet.ServletContext;
+
+import org.eclipse.jetty.util.Loader;
+import org.eclipse.jetty.webapp.WebAppContext;
+
+public class ContainerInitializer
+{
+ protected ServletContainerInitializer _target;
+ protected Class[] _interestedTypes;
+ protected Set<String> _applicableTypeNames;
+ protected Set<String> _annotatedTypeNames;
+
+
+ public void setTarget (ServletContainerInitializer target)
+ {
+ _target = target;
+ }
+
+ public ServletContainerInitializer getTarget ()
+ {
+ return _target;
+ }
+
+ public Class[] getInterestedTypes ()
+ {
+ return _interestedTypes;
+ }
+
+ public void setInterestedTypes (Class[] interestedTypes)
+ {
+ _interestedTypes = interestedTypes;
+ }
+
+ /**
+ * A class has been found that has an annotation of interest
+ * to this initializer.
+ * @param className
+ */
+ public void addAnnotatedTypeName (String className)
+ {
+ if (_annotatedTypeNames == null)
+ _annotatedTypeNames = new HashSet<String>();
+ _annotatedTypeNames.add(className);
+ }
+
+ public Set<String> getAnnotatedTypeNames ()
+ {
+ return _annotatedTypeNames;
+ }
+
+ public void addApplicableTypeName (String className)
+ {
+ if (_applicableTypeNames == null)
+ _applicableTypeNames = new HashSet<String>();
+ _applicableTypeNames.add(className);
+ }
+
+ public Set<String> getApplicableTypeNames ()
+ {
+ return _applicableTypeNames;
+ }
+
+
+ public void callStartup(WebAppContext context)
+ throws Exception
+ {
+ if (_target != null)
+ {
+ Set<Class<?>> classes = new HashSet<Class<?>>();
+
+ ClassLoader oldLoader = Thread.currentThread().getContextClassLoader();
+ Thread.currentThread().setContextClassLoader(context.getClassLoader());
+
+ try
+ {
+ if (_applicableTypeNames != null)
+ {
+ for (String s : _applicableTypeNames)
+ classes.add(Loader.loadClass(context.getClass(), s));
+ }
+
+ _target.onStartup(classes, context.getServletContext());
+ }
+ finally
+ {
+ Thread.currentThread().setContextClassLoader(oldLoader);
+ }
+ }
+ }
+}
diff --git a/jetty-plus/src/test/java/org/eclipse/jetty/plus/webapp/PlusDescriptorProcessorTest.java b/jetty-plus/src/test/java/org/eclipse/jetty/plus/webapp/PlusDescriptorProcessorTest.java
new file mode 100644
index 0000000000..9528b79d6f
--- /dev/null
+++ b/jetty-plus/src/test/java/org/eclipse/jetty/plus/webapp/PlusDescriptorProcessorTest.java
@@ -0,0 +1,176 @@
+//
+// ========================================================================
+// Copyright (c) 1995-2012 Mort Bay Consulting Pty. Ltd.
+// ------------------------------------------------------------------------
+// All rights reserved. This program and the accompanying materials
+// are made available under the terms of the Eclipse Public License v1.0
+// and Apache License v2.0 which accompanies this distribution.
+//
+// The Eclipse Public License is available at
+// http://www.eclipse.org/legal/epl-v10.html
+//
+// The Apache License v2.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.plus.webapp;
+
+
+
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
+
+import java.net.URL;
+
+import javax.naming.Context;
+import javax.naming.InitialContext;
+
+import org.eclipse.jetty.webapp.Descriptor;
+import org.eclipse.jetty.webapp.FragmentDescriptor;
+import org.eclipse.jetty.webapp.Origin;
+import org.eclipse.jetty.webapp.WebAppClassLoader;
+import org.eclipse.jetty.webapp.WebAppContext;
+import org.eclipse.jetty.webapp.WebDescriptor;
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+
+/**
+ * PlusDescriptorProcessorTest
+ *
+ *
+ */
+public class PlusDescriptorProcessorTest
+{
+ protected WebDescriptor webDescriptor;
+ protected FragmentDescriptor fragDescriptor1;
+ protected FragmentDescriptor fragDescriptor2;
+ protected FragmentDescriptor fragDescriptor3;
+ protected WebAppContext context;
+ /**
+ * @throws java.lang.Exception
+ */
+ @Before
+ public void setUp() throws Exception
+ {
+ context = new WebAppContext();
+ context.setClassLoader(new WebAppClassLoader(Thread.currentThread().getContextClassLoader(), context));
+ ClassLoader oldLoader = Thread.currentThread().getContextClassLoader();
+ Thread.currentThread().setContextClassLoader(context.getClassLoader());
+ Context icontext = new InitialContext();
+ Context compCtx = (Context)icontext.lookup ("java:comp");
+ compCtx.createSubcontext("env");
+ Thread.currentThread().setContextClassLoader(oldLoader);
+
+ org.eclipse.jetty.plus.jndi.Resource ds = new org.eclipse.jetty.plus.jndi.Resource (context, "jdbc/mydatasource", new Object());
+
+ URL webXml = Thread.currentThread().getContextClassLoader().getResource("web.xml");
+ webDescriptor = new WebDescriptor(org.eclipse.jetty.util.resource.Resource.newResource(webXml));
+ webDescriptor.parse();
+
+ URL frag1Xml = Thread.currentThread().getContextClassLoader().getResource("web-fragment-1.xml");
+ fragDescriptor1 = new FragmentDescriptor(org.eclipse.jetty.util.resource.Resource.newResource(frag1Xml));
+ fragDescriptor1.parse();
+ URL frag2Xml = Thread.currentThread().getContextClassLoader().getResource("web-fragment-2.xml");
+ fragDescriptor2 = new FragmentDescriptor(org.eclipse.jetty.util.resource.Resource.newResource(frag2Xml));
+ fragDescriptor2.parse();
+ URL frag3Xml = Thread.currentThread().getContextClassLoader().getResource("web-fragment-3.xml");
+ fragDescriptor3 = new FragmentDescriptor(org.eclipse.jetty.util.resource.Resource.newResource(frag3Xml));
+ fragDescriptor3.parse();
+ }
+
+ @After
+ public void tearDown() throws Exception
+ {
+ ClassLoader oldLoader = Thread.currentThread().getContextClassLoader();
+ Thread.currentThread().setContextClassLoader(context.getClassLoader());
+ Context ic = new InitialContext();
+ Context compCtx = (Context)ic.lookup ("java:comp");
+ compCtx.destroySubcontext("env");
+ Thread.currentThread().setContextClassLoader(oldLoader);
+ }
+
+ @Test
+ public void testWebXmlResourceDeclarations()
+ throws Exception
+ {
+ //if declared in web.xml, fragment declarations ignored
+ ClassLoader oldLoader = Thread.currentThread().getContextClassLoader();
+ Thread.currentThread().setContextClassLoader(context.getClassLoader());
+ try
+ {
+ PlusDescriptorProcessor pdp = new PlusDescriptorProcessor();
+ pdp.process(context, webDescriptor);
+ Descriptor d = context.getMetaData().getOriginDescriptor("resource-ref.jdbc/mydatasource");
+ assertNotNull(d);
+ assertTrue(d == webDescriptor);
+
+ pdp.process(context, fragDescriptor1);
+ pdp.process(context, fragDescriptor2);
+ }
+ finally
+ {
+ Thread.currentThread().setContextClassLoader(oldLoader);
+ }
+ }
+
+
+ @Test
+ public void testMismatchedFragmentResourceDeclarations ()
+ throws Exception
+ {
+ //if declared in more than 1 fragment, declarations must be the same
+ ClassLoader oldLoader = Thread.currentThread().getContextClassLoader();
+ Thread.currentThread().setContextClassLoader(context.getClassLoader());
+ try
+ {
+ PlusDescriptorProcessor pdp = new PlusDescriptorProcessor();
+ pdp.process(context, fragDescriptor1);
+ Descriptor d = context.getMetaData().getOriginDescriptor("resource-ref.jdbc/mydatasource");
+ assertNotNull(d);
+ assertTrue(d == fragDescriptor1);
+ assertEquals(Origin.WebFragment, context.getMetaData().getOrigin("resource-ref.jdbc/mydatasource"));
+
+ pdp.process(context, fragDescriptor2);
+ fail("Expected conflicting resource-ref declaration");
+ }
+ catch (Exception e)
+ {
+ //expected
+ }
+ finally
+ {
+ Thread.currentThread().setContextClassLoader(oldLoader);
+ }
+ }
+
+ @Test
+ public void testMatchingFragmentResourceDeclarations ()
+ throws Exception
+ {
+ //if declared in more than 1 fragment, declarations must be the same
+ ClassLoader oldLoader = Thread.currentThread().getContextClassLoader();
+ Thread.currentThread().setContextClassLoader(context.getClassLoader());
+ try
+ {
+ PlusDescriptorProcessor pdp = new PlusDescriptorProcessor();
+ pdp.process(context, fragDescriptor1);
+ Descriptor d = context.getMetaData().getOriginDescriptor("resource-ref.jdbc/mydatasource");
+ assertNotNull(d);
+ assertTrue(d == fragDescriptor1);
+ assertEquals(Origin.WebFragment, context.getMetaData().getOrigin("resource-ref.jdbc/mydatasource"));
+ pdp.process(context, fragDescriptor3);
+ }
+
+ finally
+ {
+ Thread.currentThread().setContextClassLoader(oldLoader);
+ }
+ }
+}
diff --git a/jetty-plus/src/test/resources/web-fragment-1.xml b/jetty-plus/src/test/resources/web-fragment-1.xml
new file mode 100644
index 0000000000..b213172ef0
--- /dev/null
+++ b/jetty-plus/src/test/resources/web-fragment-1.xml
@@ -0,0 +1,27 @@
+<?xml version="1.0" encoding="ISO-8859-1"?>
+
+<web-fragment
+ xmlns="http://java.sun.com/xml/ns/javaee"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-fragment_3_0.xsd"
+ version="3.0">
+
+ <name>Fragment1</name>
+
+ <ordering>
+ <after>others</after>
+ </ordering>
+
+ <resource-ref>
+ <res-ref-name>jdbc/mydatasource</res-ref-name>
+ <res-type>javax.sql.DataSource</res-type>
+ <res-auth>Container</res-auth>
+<!--
+ <injection-target>
+ <injection-target-class>com.acme.Bar</injection-target-class>
+ <injection-target-name>myDatasource</injection-target-name>
+ </injection-target>
+-->
+ </resource-ref>
+
+</web-fragment>
diff --git a/jetty-plus/src/test/resources/web-fragment-2.xml b/jetty-plus/src/test/resources/web-fragment-2.xml
new file mode 100644
index 0000000000..e2fff6786f
--- /dev/null
+++ b/jetty-plus/src/test/resources/web-fragment-2.xml
@@ -0,0 +1,27 @@
+<?xml version="1.0" encoding="ISO-8859-1"?>
+
+<web-fragment
+ xmlns="http://java.sun.com/xml/ns/javaee"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-fragment_3_0.xsd"
+ version="3.0">
+
+ <name>Fragment2</name>
+
+ <ordering>
+ <after>others</after>
+ </ordering>
+
+ <resource-ref>
+ <res-ref-name>jdbc/mydatasource</res-ref-name>
+ <res-type>javax.sql.DataSource</res-type>
+ <res-auth>User</res-auth>
+<!--
+ <injection-target>
+ <injection-target-class>com.acme.Bar</injection-target-class>
+ <injection-target-name>myDatasource</injection-target-name>
+ </injection-target>
+-->
+ </resource-ref>
+
+</web-fragment>
diff --git a/jetty-plus/src/test/resources/web-fragment-3.xml b/jetty-plus/src/test/resources/web-fragment-3.xml
new file mode 100644
index 0000000000..da1f3d5add
--- /dev/null
+++ b/jetty-plus/src/test/resources/web-fragment-3.xml
@@ -0,0 +1,27 @@
+<?xml version="1.0" encoding="ISO-8859-1"?>
+
+<web-fragment
+ xmlns="http://java.sun.com/xml/ns/javaee"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-fragment_3_0.xsd"
+ version="3.0">
+
+ <name>Fragment3</name>
+
+ <ordering>
+ <after>others</after>
+ </ordering>
+
+ <resource-ref>
+ <res-ref-name>jdbc/mydatasource</res-ref-name>
+ <res-type>javax.sql.DataSource</res-type>
+ <res-auth>Container</res-auth>
+<!--
+ <injection-target>
+ <injection-target-class>com.acme.Bar</injection-target-class>
+ <injection-target-name>myDatasource</injection-target-name>
+ </injection-target>
+-->
+ </resource-ref>
+
+</web-fragment>
diff --git a/jetty-plus/src/test/resources/web.xml b/jetty-plus/src/test/resources/web.xml
new file mode 100644
index 0000000000..aa40eb3fba
--- /dev/null
+++ b/jetty-plus/src/test/resources/web.xml
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="ISO-8859-1"?>
+<web-app
+ xmlns="http://java.sun.com/xml/ns/javaee"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"
+ metadata-complete="false"
+ version="3.0">
+
+ <display-name>Test WebApp</display-name>
+
+ <resource-ref>
+ <res-ref-name>jdbc/mydatasource</res-ref-name>
+ <res-type>javax.sql.DataSource</res-type>
+ <res-auth>Container</res-auth>
+<!--
+ <injection-target>
+ <injection-target-class>com.acme.JNDITest</injection-target-class>
+ <injection-target-name>myDatasource</injection-target-name>
+ </injection-target>
+-->
+ </resource-ref>
+
+</web-app>
diff --git a/jetty-policy/pom.xml b/jetty-policy/pom.xml
index 51b8f4c951..bd3681de84 100644
--- a/jetty-policy/pom.xml
+++ b/jetty-policy/pom.xml
@@ -3,7 +3,7 @@
<parent>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-project</artifactId>
- <version>7.6.8-SNAPSHOT</version>
+ <version>8.1.8-SNAPSHOT</version>
</parent>
<artifactId>jetty-policy</artifactId>
<name>Jetty :: Policy Tool</name>
diff --git a/jetty-rewrite/pom.xml b/jetty-rewrite/pom.xml
index 5de6184e31..dfe1c7811d 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>7.6.8-SNAPSHOT</version>
+ <version>8.1.8-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>jetty-rewrite</artifactId>
@@ -22,6 +22,11 @@
<goals>
<goal>manifest</goal>
</goals>
+ <configuration>
+ <instructions>
+ <Import-Package>javax.servlet.*;version="2.6.0",*</Import-Package>
+ </instructions>
+ </configuration>
</execution>
</executions>
</plugin>
diff --git a/jetty-rewrite/src/test/java/org/eclipse/jetty/rewrite/handler/HeaderPatternRuleTest.java b/jetty-rewrite/src/test/java/org/eclipse/jetty/rewrite/handler/HeaderPatternRuleTest.java
index c52c6fd2eb..4df73613a7 100644
--- a/jetty-rewrite/src/test/java/org/eclipse/jetty/rewrite/handler/HeaderPatternRuleTest.java
+++ b/jetty-rewrite/src/test/java/org/eclipse/jetty/rewrite/handler/HeaderPatternRuleTest.java
@@ -19,7 +19,7 @@
package org.eclipse.jetty.rewrite.handler;
import java.io.IOException;
-import java.util.Enumeration;
+import java.util.Iterator;
import org.junit.Before;
import org.junit.Test;
@@ -86,11 +86,11 @@ public class HeaderPatternRuleTest extends AbstractRuleTestCase
};
assertHeaders(headers);
- Enumeration e = _response.getHeaders("size");
+ Iterator<String> e = _response.getHeaders("size").iterator();
int count = 0;
- while (e.hasMoreElements())
+ while (e.hasNext())
{
- e.nextElement();
+ e.next();
count++;
}
diff --git a/jetty-security/pom.xml b/jetty-security/pom.xml
index e25b2299d7..3af63a46a3 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>7.6.8-SNAPSHOT</version>
+ <version>8.1.8-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>jetty-security</artifactId>
@@ -24,7 +24,7 @@
</goals>
<configuration>
<instructions>
- <Import-Package>javax.servlet.*;version="[2.5,3.0)",javax.security.cert,*</Import-Package>
+ <Import-Package>javax.servlet.*;version="2.6.0",javax.security.cert,*</Import-Package>
</instructions>
</configuration>
diff --git a/jetty-security/src/main/java/org/eclipse/jetty/security/ConstraintMapping.java b/jetty-security/src/main/java/org/eclipse/jetty/security/ConstraintMapping.java
index 16be420e8d..fee3836bbf 100644
--- a/jetty-security/src/main/java/org/eclipse/jetty/security/ConstraintMapping.java
+++ b/jetty-security/src/main/java/org/eclipse/jetty/security/ConstraintMapping.java
@@ -23,6 +23,7 @@ import org.eclipse.jetty.util.security.Constraint;
public class ConstraintMapping
{
String _method;
+ String[] _methodOmissions;
String _pathSpec;
@@ -81,4 +82,19 @@ public class ConstraintMapping
{
this._pathSpec = pathSpec;
}
+
+ /* ------------------------------------------------------------ */
+ /**
+ * @param omissions The http-method-omission
+ */
+ public void setMethodOmissions(String[] omissions)
+ {
+ _methodOmissions = omissions;
+ }
+
+ /* ------------------------------------------------------------ */
+ public String[] getMethodOmissions()
+ {
+ return _methodOmissions;
+ }
}
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 0ca83b1962..5712c1df92 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
@@ -19,16 +19,24 @@
package org.eclipse.jetty.security;
import java.io.IOException;
+import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
+import java.util.Map.Entry;
import java.util.Set;
import java.util.concurrent.CopyOnWriteArrayList;
import java.util.concurrent.CopyOnWriteArraySet;
+import javax.servlet.HttpConstraintElement;
+import javax.servlet.HttpMethodConstraintElement;
+import javax.servlet.ServletSecurityElement;
+import javax.servlet.annotation.ServletSecurity.EmptyRoleSemantic;
+import javax.servlet.annotation.ServletSecurity.TransportGuarantee;
+
import org.eclipse.jetty.http.PathMap;
import org.eclipse.jetty.server.AbstractHttpConnection;
import org.eclipse.jetty.server.Connector;
@@ -42,17 +50,225 @@ import org.eclipse.jetty.util.security.Constraint;
/* ------------------------------------------------------------ */
/**
* Handler to enforce SecurityConstraints. This implementation is servlet spec
- * 2.4 compliant and precomputes the constraint combinations for runtime
+ * 3.0 compliant and precomputes the constraint combinations for runtime
* efficiency.
*
*/
public class ConstraintSecurityHandler extends SecurityHandler implements ConstraintAware
{
+ private static final String OMISSION_SUFFIX = ".omission";
+
private final List<ConstraintMapping> _constraintMappings= new CopyOnWriteArrayList<ConstraintMapping>();
private final Set<String> _roles = new CopyOnWriteArraySet<String>();
private final PathMap _constraintMap = new PathMap();
private boolean _strict = true;
+
+
+ /* ------------------------------------------------------------ */
+ /**
+ * @return
+ */
+ public static Constraint createConstraint()
+ {
+ return new Constraint();
+ }
+
+ /* ------------------------------------------------------------ */
+ /**
+ * @param constraint
+ * @return
+ */
+ public static Constraint createConstraint(Constraint constraint)
+ {
+ try
+ {
+ return (Constraint)constraint.clone();
+ }
+ catch (CloneNotSupportedException e)
+ {
+ throw new IllegalStateException (e);
+ }
+ }
+
+ /* ------------------------------------------------------------ */
+ /**
+ * Create a security constraint
+ *
+ * @param name
+ * @param authenticate
+ * @param roles
+ * @param dataConstraint
+ * @return
+ */
+ public static Constraint createConstraint (String name, boolean authenticate, String[] roles, int dataConstraint)
+ {
+ Constraint constraint = createConstraint();
+ if (name != null)
+ constraint.setName(name);
+ constraint.setAuthenticate(authenticate);
+ constraint.setRoles(roles);
+ constraint.setDataConstraint(dataConstraint);
+ return constraint;
+ }
+
+
+ /* ------------------------------------------------------------ */
+ /**
+ * @param name
+ * @param element
+ * @return
+ */
+ public static Constraint createConstraint (String name, HttpConstraintElement element)
+ {
+ return createConstraint(name, element.getRolesAllowed(), element.getEmptyRoleSemantic(), element.getTransportGuarantee());
+ }
+
+
+ /* ------------------------------------------------------------ */
+ /**
+ * @param name
+ * @param rolesAllowed
+ * @param permitOrDeny
+ * @param transport
+ * @return
+ */
+ public static Constraint createConstraint (String name, String[] rolesAllowed, EmptyRoleSemantic permitOrDeny, TransportGuarantee transport)
+ {
+ Constraint constraint = createConstraint();
+
+ if (rolesAllowed == null || rolesAllowed.length==0)
+ {
+ if (permitOrDeny.equals(EmptyRoleSemantic.DENY))
+ {
+ //Equivalent to <auth-constraint> with no roles
+ constraint.setName(name+"-Deny");
+ constraint.setAuthenticate(true);
+ }
+ else
+ {
+ //Equivalent to no <auth-constraint>
+ constraint.setName(name+"-Permit");
+ constraint.setAuthenticate(false);
+ }
+ }
+ else
+ {
+ //Equivalent to <auth-constraint> with list of <security-role-name>s
+ constraint.setAuthenticate(true);
+ constraint.setRoles(rolesAllowed);
+ constraint.setName(name+"-RolesAllowed");
+ }
+
+ //Equivalent to //<user-data-constraint><transport-guarantee>CONFIDENTIAL</transport-guarantee></user-data-constraint>
+ constraint.setDataConstraint((transport.equals(TransportGuarantee.CONFIDENTIAL)?Constraint.DC_CONFIDENTIAL:Constraint.DC_NONE));
+ return constraint;
+ }
+
+
+
+ /* ------------------------------------------------------------ */
+ /**
+ * @param pathSpec
+ * @param constraintMappings
+ * @return
+ */
+ public static List<ConstraintMapping> getConstraintMappingsForPath(String pathSpec, List<ConstraintMapping> constraintMappings)
+ {
+ if (pathSpec == null || "".equals(pathSpec.trim()) || constraintMappings == null || constraintMappings.size() == 0)
+ return Collections.emptyList();
+
+ List<ConstraintMapping> mappings = new ArrayList<ConstraintMapping>();
+ for (ConstraintMapping mapping:constraintMappings)
+ {
+ if (pathSpec.equals(mapping.getPathSpec()))
+ {
+ mappings.add(mapping);
+ }
+ }
+ return mappings;
+ }
+
+
+ /* ------------------------------------------------------------ */
+ /** Take out of the constraint mappings those that match the
+ * given path.
+ *
+ * @param pathSpec
+ * @param constraintMappings a new list minus the matching constraints
+ * @return
+ */
+ public static List<ConstraintMapping> removeConstraintMappingsForPath(String pathSpec, List<ConstraintMapping> constraintMappings)
+ {
+ if (pathSpec == null || "".equals(pathSpec.trim()) || constraintMappings == null || constraintMappings.size() == 0)
+ return Collections.emptyList();
+
+ List<ConstraintMapping> mappings = new ArrayList<ConstraintMapping>();
+ for (ConstraintMapping mapping:constraintMappings)
+ {
+ //Remove the matching mappings by only copying in non-matching mappings
+ if (!pathSpec.equals(mapping.getPathSpec()))
+ {
+ mappings.add(mapping);
+ }
+ }
+ return mappings;
+ }
+
+
+
+ /* ------------------------------------------------------------ */
+ /** Generate Constraints and ContraintMappings for the given url pattern and ServletSecurityElement
+ *
+ * @param name
+ * @param pathSpec
+ * @param securityElement
+ * @return
+ */
+ public static List<ConstraintMapping> createConstraintsWithMappingsForPath (String name, String pathSpec, ServletSecurityElement securityElement)
+ {
+ List<ConstraintMapping> mappings = new ArrayList<ConstraintMapping>();
+
+ //Create a constraint that will describe the default case (ie if not overridden by specific HttpMethodConstraints)
+ Constraint constraint = ConstraintSecurityHandler.createConstraint(name, securityElement);
+
+ //Create a mapping for the pathSpec for the default case
+ ConstraintMapping defaultMapping = new ConstraintMapping();
+ defaultMapping.setPathSpec(pathSpec);
+ defaultMapping.setConstraint(constraint);
+ mappings.add(defaultMapping);
+
+
+ //See Spec 13.4.1.2 p127
+ List<String> methodOmissions = new ArrayList<String>();
+
+ //make constraint mappings for this url for each of the HttpMethodConstraintElements
+ Collection<HttpMethodConstraintElement> methodConstraints = securityElement.getHttpMethodConstraints();
+ if (methodConstraints != null)
+ {
+ for (HttpMethodConstraintElement methodConstraint:methodConstraints)
+ {
+ //Make a Constraint that captures the <auth-constraint> and <user-data-constraint> elements supplied for the HttpMethodConstraintElement
+ Constraint mconstraint = ConstraintSecurityHandler.createConstraint(name, methodConstraint);
+ ConstraintMapping mapping = new ConstraintMapping();
+ mapping.setConstraint(mconstraint);
+ mapping.setPathSpec(pathSpec);
+ if (methodConstraint.getMethodName() != null)
+ {
+ mapping.setMethod(methodConstraint.getMethodName());
+ //See spec 13.4.1.2 p127 - add an omission for every method name to the default constraint
+ methodOmissions.add(methodConstraint.getMethodName());
+ }
+ mappings.add(mapping);
+ }
+ }
+ //See spec 13.4.1.2 p127 - add an omission for every method name to the default constraint
+ if (methodOmissions.size() > 0)
+ defaultMapping.setMethodOmissions(methodOmissions.toArray(new String[methodOmissions.size()]));
+ return mappings;
+ }
+
+
/* ------------------------------------------------------------ */
/** Get the strict mode.
* @return true if the security handler is running in strict mode.
@@ -136,8 +352,6 @@ public class ConstraintSecurityHandler extends SecurityHandler implements Constr
*/
public void setConstraintMappings(List<ConstraintMapping> constraintMappings, Set<String> roles)
{
- if (isStarted())
- throw new IllegalStateException("Started");
_constraintMappings.clear();
_constraintMappings.addAll(constraintMappings);
@@ -156,6 +370,14 @@ public class ConstraintSecurityHandler extends SecurityHandler implements Constr
}
}
setRoles(roles);
+
+ if (isStarted())
+ {
+ for (ConstraintMapping mapping : _constraintMappings)
+ {
+ processConstraintMapping(mapping);
+ }
+ }
}
/* ------------------------------------------------------------ */
@@ -168,9 +390,6 @@ public class ConstraintSecurityHandler extends SecurityHandler implements Constr
*/
public void setRoles(Set<String> roles)
{
- if (isStarted())
- throw new IllegalStateException("Started");
-
_roles.clear();
_roles.addAll(roles);
}
@@ -232,7 +451,9 @@ public class ConstraintSecurityHandler extends SecurityHandler implements Constr
}
super.doStart();
}
-
+
+
+ /* ------------------------------------------------------------ */
@Override
protected void doStop() throws Exception
{
@@ -241,7 +462,15 @@ public class ConstraintSecurityHandler extends SecurityHandler implements Constr
_roles.clear();
super.doStop();
}
-
+
+
+ /* ------------------------------------------------------------ */
+ /**
+ * Create and combine the constraint with the existing processed
+ * constraints.
+ *
+ * @param mapping
+ */
protected void processConstraintMapping(ConstraintMapping mapping)
{
Map<String, RoleInfo> mappings = (Map<String, RoleInfo>)_constraintMap.get(mapping.getPathSpec());
@@ -253,8 +482,15 @@ public class ConstraintSecurityHandler extends SecurityHandler implements Constr
RoleInfo allMethodsRoleInfo = mappings.get(null);
if (allMethodsRoleInfo != null && allMethodsRoleInfo.isForbidden())
return;
+
+ if (mapping.getMethodOmissions() != null && mapping.getMethodOmissions().length > 0)
+ {
+
+ processConstraintMappingWithMethodOmissions(mapping, mappings);
+ return;
+ }
- String httpMethod = mapping.getMethod();
+ String httpMethod = mapping.getMethod();
RoleInfo roleInfo = mappings.get(httpMethod);
if (roleInfo == null)
{
@@ -268,10 +504,10 @@ public class ConstraintSecurityHandler extends SecurityHandler implements Constr
if (roleInfo.isForbidden())
return;
- Constraint constraint = mapping.getConstraint();
- boolean forbidden = constraint.isForbidden();
- roleInfo.setForbidden(forbidden);
- if (forbidden)
+ //add in info from the constraint
+ configureRoleInfo(roleInfo, mapping);
+
+ if (roleInfo.isForbidden())
{
if (httpMethod == null)
{
@@ -281,50 +517,120 @@ public class ConstraintSecurityHandler extends SecurityHandler implements Constr
}
else
{
- UserDataConstraint userDataConstraint = UserDataConstraint.get(constraint.getDataConstraint());
- roleInfo.setUserDataConstraint(userDataConstraint);
+ //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);
+ }
+ }
+ }
+ }
+ }
+
+ /* ------------------------------------------------------------ */
+ /** Constraints that name method omissions are dealt with differently.
+ * We create an entry in the mappings with key "method.omission". This entry
+ * is only ever combined with other omissions for the same method to produce a
+ * consolidated RoleInfo. Then, when we wish to find the relevant constraints for
+ * a given Request (in prepareConstraintInfo()), we consult 3 types of entries in
+ * the mappings: an entry that names the method of the Request specifically, an
+ * entry that names constraints that apply to all methods, entries of the form
+ * method.omission, where the method of the Request is not named in the omission.
+ * @param mapping
+ * @param mappings
+ */
+ protected void processConstraintMappingWithMethodOmissions (ConstraintMapping mapping, Map<String, RoleInfo> mappings)
+ {
+ String[] omissions = mapping.getMethodOmissions();
- boolean checked = constraint.getAuthenticate();
- roleInfo.setChecked(checked);
- if (roleInfo.isChecked())
+ for (String omission:omissions)
+ {
+ //for each method omission, see if there is already a RoleInfo for it in mappings
+ RoleInfo ri = mappings.get(omission+OMISSION_SUFFIX);
+ if (ri == null)
{
- if (constraint.isAnyRole())
+ //if not, make one
+ ri = new RoleInfo();
+ mappings.put(omission+OMISSION_SUFFIX, ri);
+ }
+
+ //initialize RoleInfo or combine from ConstraintMapping
+ configureRoleInfo(ri, mapping);
+ }
+ }
+
+
+ /* ------------------------------------------------------------ */
+ /**
+ * Initialize or update the RoleInfo from the constraint
+ * @param ri
+ * @param mapping
+ */
+ protected void configureRoleInfo (RoleInfo ri, ConstraintMapping mapping)
+ {
+ Constraint constraint = mapping.getConstraint();
+ boolean forbidden = constraint.isForbidden();
+ ri.setForbidden(forbidden);
+
+ //set up the data constraint (NOTE: must be done after setForbidden, as it nulls out the data constraint
+ //which we need in order to do combining of omissions in prepareConstraintInfo
+ UserDataConstraint userDataConstraint = UserDataConstraint.get(mapping.getConstraint().getDataConstraint());
+ ri.setUserDataConstraint(userDataConstraint);
+
+
+ //if forbidden, no point setting up roles
+ if (!ri.isForbidden())
+ {
+ //add in the roles
+ boolean checked = mapping.getConstraint().getAuthenticate();
+ ri.setChecked(checked);
+ if (ri.isChecked())
+ {
+ if (mapping.getConstraint().isAnyRole())
{
if (_strict)
{
// * means "all defined roles"
for (String role : _roles)
- roleInfo.addRole(role);
+ ri.addRole(role);
}
else
// * means any role
- roleInfo.setAnyRole(true);
+ ri.setAnyRole(true);
}
else
{
- String[] newRoles = constraint.getRoles();
+ String[] newRoles = mapping.getConstraint().getRoles();
for (String role : newRoles)
{
if (_strict &&!_roles.contains(role))
throw new IllegalArgumentException("Attempt to use undeclared role: " + role + ", known roles: " + _roles);
- roleInfo.addRole(role);
- }
- }
- }
- if (httpMethod == null)
- {
- for (Map.Entry<String, RoleInfo> entry : mappings.entrySet())
- {
- if (entry.getKey() != null)
- {
- RoleInfo specific = entry.getValue();
- specific.combine(roleInfo);
+ ri.addRole(role);
}
}
}
}
}
-
+
+
+ /* ------------------------------------------------------------ */
+ /**
+ * Find constraints that apply to the given path.
+ * In order to do this, we consult 3 different types of information stored in the mappings for each path - each mapping
+ * represents a merged set of user data constraints, roles etc -:
+ * <ol>
+ * <li>A mapping of an exact method name </li>
+ * <li>A mapping will null key that matches every method name</li>
+ * <li>Mappings with keys of the form "method.omission" that indicates it will match every method name EXCEPT that given</li>
+ * </ol>
+ *
+ * @see org.eclipse.jetty.security.SecurityHandler#prepareConstraintInfo(java.lang.String, org.eclipse.jetty.server.Request)
+ */
protected Object prepareConstraintInfo(String pathInContext, Request request)
{
Map<String, RoleInfo> mappings = (Map<String, RoleInfo>)_constraintMap.match(pathInContext);
@@ -334,13 +640,46 @@ public class ConstraintSecurityHandler extends SecurityHandler implements Constr
String httpMethod = request.getMethod();
RoleInfo roleInfo = mappings.get(httpMethod);
if (roleInfo == null)
- roleInfo = mappings.get(null);
+ {
+ //No specific http-method names matched
+ List<RoleInfo> applicableConstraints = new ArrayList<RoleInfo>();
+
+ //Get info for constraint that matches all methods if it exists
+ RoleInfo all = mappings.get(null);
+ if (all != null)
+ applicableConstraints.add(all);
+
+
+ //Get info for constraints that name method omissions where target method name is not omitted
+ //(ie matches because target method is not omitted, hence considered covered by the constraint)
+ for (Entry<String, RoleInfo> entry: mappings.entrySet())
+ {
+ if (entry.getKey() != null && entry.getKey().contains(OMISSION_SUFFIX) && !(httpMethod+OMISSION_SUFFIX).equals(entry.getKey()))
+ applicableConstraints.add(entry.getValue());
+ }
+
+ if (applicableConstraints.size() == 1)
+ roleInfo = applicableConstraints.get(0);
+ else
+ {
+ roleInfo = new RoleInfo();
+ roleInfo.setUserDataConstraint(UserDataConstraint.None);
+
+ for (RoleInfo r:applicableConstraints)
+ roleInfo.combine(r);
+ }
+
+ }
return roleInfo;
}
-
return null;
}
-
+
+
+ /* ------------------------------------------------------------ */
+ /**
+ * @see org.eclipse.jetty.security.SecurityHandler#checkUserDataPermissions(java.lang.String, org.eclipse.jetty.server.Request, org.eclipse.jetty.server.Response, java.lang.Object)
+ */
protected boolean checkUserDataPermissions(String pathInContext, Request request, Response response, Object constraintInfo) throws IOException
{
if (constraintInfo == null)
@@ -404,7 +743,11 @@ public class ConstraintSecurityHandler extends SecurityHandler implements Constr
}
}
-
+
+ /* ------------------------------------------------------------ */
+ /**
+ * @see org.eclipse.jetty.security.SecurityHandler#isAuthMandatory(org.eclipse.jetty.server.Request, org.eclipse.jetty.server.Response, java.lang.Object)
+ */
protected boolean isAuthMandatory(Request baseRequest, Response base_response, Object constraintInfo)
{
if (constraintInfo == null)
@@ -413,7 +756,12 @@ public class ConstraintSecurityHandler extends SecurityHandler implements Constr
}
return ((RoleInfo)constraintInfo).isChecked();
}
-
+
+
+ /* ------------------------------------------------------------ */
+ /**
+ * @see org.eclipse.jetty.security.SecurityHandler#checkWebResourcePermissions(java.lang.String, org.eclipse.jetty.server.Request, org.eclipse.jetty.server.Response, java.lang.Object, org.eclipse.jetty.server.UserIdentity)
+ */
@Override
protected boolean checkWebResourcePermissions(String pathInContext, Request request, Response response, Object constraintInfo, UserIdentity userIdentity)
throws IOException
@@ -454,4 +802,5 @@ public class ConstraintSecurityHandler extends SecurityHandler implements Constr
getBeans(),
TypeUtil.asList(getHandlers()));
}
+
}
diff --git a/jetty-security/src/main/java/org/eclipse/jetty/security/authentication/BasicAuthenticator.java b/jetty-security/src/main/java/org/eclipse/jetty/security/authentication/BasicAuthenticator.java
index ec2fb04b0d..3ae194f3fa 100644
--- a/jetty-security/src/main/java/org/eclipse/jetty/security/authentication/BasicAuthenticator.java
+++ b/jetty-security/src/main/java/org/eclipse/jetty/security/authentication/BasicAuthenticator.java
@@ -54,6 +54,8 @@ public class BasicAuthenticator extends LoginAuthenticator
return Constraint.__BASIC_AUTH;
}
+
+
/* ------------------------------------------------------------ */
/**
* @see org.eclipse.jetty.security.Authenticator#validateRequest(javax.servlet.ServletRequest, javax.servlet.ServletResponse, boolean)
@@ -85,10 +87,9 @@ public class BasicAuthenticator extends LoginAuthenticator
String username = credentials.substring(0,i);
String password = credentials.substring(i+1);
- UserIdentity user = _loginService.login(username,password);
+ UserIdentity user = login (username, password, request);
if (user!=null)
{
- renewSession(request,response);
return new UserAuthentication(getAuthMethod(),user);
}
}
diff --git a/jetty-security/src/main/java/org/eclipse/jetty/security/authentication/ClientCertAuthenticator.java b/jetty-security/src/main/java/org/eclipse/jetty/security/authentication/ClientCertAuthenticator.java
index a4bef236a3..f34ccf3a0a 100644
--- a/jetty-security/src/main/java/org/eclipse/jetty/security/authentication/ClientCertAuthenticator.java
+++ b/jetty-security/src/main/java/org/eclipse/jetty/security/authentication/ClientCertAuthenticator.java
@@ -81,6 +81,8 @@ public class ClientCertAuthenticator extends LoginAuthenticator
return Constraint.__CERT_AUTH;
}
+
+
/**
* @return Authentication for request
* @throws ServerAuthException
@@ -121,10 +123,9 @@ public class ClientCertAuthenticator extends LoginAuthenticator
final char[] credential = B64Code.encode(cert.getSignature());
- UserIdentity user = _loginService.login(username,credential);
+ UserIdentity user = login(username, credential, req);
if (user!=null)
{
- renewSession(request,response);
return new UserAuthentication(getAuthMethod(),user);
}
}
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 158058c94f..68f3192dfd 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
@@ -21,12 +21,15 @@ package org.eclipse.jetty.security.authentication;
import java.io.IOException;
import java.io.PrintWriter;
+import java.util.Collection;
+import java.util.Collections;
import java.util.Locale;
import javax.servlet.ServletOutputStream;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.Cookie;
+import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.eclipse.jetty.security.Authenticator;
@@ -71,6 +74,7 @@ public class DeferredAuthentication implements Authentication.Deferred
if (identity_service!=null)
_previousAssociation=identity_service.associate(((Authentication.User)authentication).getUserIdentity());
+
return authentication;
}
}
@@ -78,7 +82,8 @@ public class DeferredAuthentication implements Authentication.Deferred
{
LOG.debug(e);
}
- return Authentication.UNAUTHENTICATED;
+
+ return this;
}
/* ------------------------------------------------------------ */
@@ -101,28 +106,23 @@ public class DeferredAuthentication implements Authentication.Deferred
{
LOG.debug(e);
}
- return Authentication.UNAUTHENTICATED;
+ return this;
}
/* ------------------------------------------------------------ */
/**
* @see org.eclipse.jetty.server.Authentication.Deferred#login(java.lang.String, java.lang.String)
*/
- public Authentication login(String username, String password)
+ public Authentication login(String username, Object password, ServletRequest request)
{
- LoginService login_service= _authenticator.getLoginService();
- IdentityService identity_service=login_service.getIdentityService();
-
- if (login_service!=null)
+ UserIdentity identity = _authenticator.login(username, password, request);
+ if (identity != null)
{
- UserIdentity user = login_service.login(username,password);
- if (user!=null)
- {
- UserAuthentication authentication = new UserAuthentication("API",user);
- if (identity_service!=null)
- _previousAssociation=identity_service.associate(user);
- return authentication;
- }
+ IdentityService identity_service = _authenticator.getLoginService().getIdentityService();
+ UserAuthentication authentication = new UserAuthentication("API",identity);
+ if (identity_service != null)
+ _previousAssociation=identity_service.associate(identity);
+ return authentication;
}
return null;
}
@@ -288,6 +288,29 @@ public class DeferredAuthentication implements Authentication.Deferred
{
}
+ public Collection<String> getHeaderNames()
+ {
+ return Collections.emptyList();
+ }
+
+ @Override
+ public String getHeader(String arg0)
+ {
+ return null;
+ }
+
+ @Override
+ public Collection<String> getHeaders(String arg0)
+ {
+ return Collections.emptyList();
+ }
+
+ @Override
+ public int getStatus()
+ {
+ return 0;
+ }
+
};
/* ------------------------------------------------------------ */
@@ -309,4 +332,4 @@ public class DeferredAuthentication implements Authentication.Deferred
};
-} \ No newline at end of file
+}
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 c42c26c871..1e5a417f29 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
@@ -116,6 +116,8 @@ public class DigestAuthenticator extends LoginAuthenticator
{
return true;
}
+
+
/* ------------------------------------------------------------ */
public Authentication validateRequest(ServletRequest req, ServletResponse res, boolean mandatory) throws ServerAuthException
@@ -185,10 +187,10 @@ public class DigestAuthenticator extends LoginAuthenticator
if (n > 0)
{
- UserIdentity user = _loginService.login(digest.username,digest);
+ //UserIdentity user = _loginService.login(digest.username,digest);
+ UserIdentity user = login(digest.username, digest, req);
if (user!=null)
{
- renewSession(request,response);
return new UserAuthentication(getAuthMethod(),user);
}
}
diff --git a/jetty-security/src/main/java/org/eclipse/jetty/security/authentication/FormAuthenticator.java b/jetty-security/src/main/java/org/eclipse/jetty/security/authentication/FormAuthenticator.java
index 26a080dbdb..504b59c355 100644
--- a/jetty-security/src/main/java/org/eclipse/jetty/security/authentication/FormAuthenticator.java
+++ b/jetty-security/src/main/java/org/eclipse/jetty/security/authentication/FormAuthenticator.java
@@ -180,6 +180,22 @@ public class FormAuthenticator extends LoginAuthenticator
_formErrorPath = _formErrorPath.substring(0, _formErrorPath.indexOf('?'));
}
}
+
+
+ /* ------------------------------------------------------------ */
+ @Override
+ public UserIdentity login(String username, Object password, ServletRequest request)
+ {
+
+ UserIdentity user = super.login(username,password,request);
+ if (user!=null)
+ {
+ HttpSession session = ((HttpServletRequest)request).getSession(true);
+ Authentication cached=new SessionAuthentication(getAuthMethod(),user,password);
+ session.setAttribute(SessionAuthentication.__J_AUTHENTICATED, cached);
+ }
+ return user;
+ }
/* ------------------------------------------------------------ */
public Authentication validateRequest(ServletRequest req, ServletResponse res, boolean mandatory) throws ServerAuthException
@@ -207,11 +223,10 @@ public class FormAuthenticator extends LoginAuthenticator
final String username = request.getParameter(__J_USERNAME);
final String password = request.getParameter(__J_PASSWORD);
- UserIdentity user = _loginService.login(username,password);
+ UserIdentity user = login(username, password, request);
+ session = request.getSession(true);
if (user!=null)
- {
- session=renewSession(request,response);
-
+ {
// Redirect to original request
String nuri;
synchronized(session)
@@ -224,9 +239,6 @@ public class FormAuthenticator extends LoginAuthenticator
if (nuri.length() == 0)
nuri = URIUtil.SLASH;
}
-
- Authentication cached=new SessionAuthentication(getAuthMethod(),user,password);
- session.setAttribute(SessionAuthentication.__J_AUTHENTICATED, cached);
}
response.setContentLength(0);
response.sendRedirect(response.encodeRedirectURL(nuri));
diff --git a/jetty-security/src/main/java/org/eclipse/jetty/security/authentication/LoginAuthenticator.java b/jetty-security/src/main/java/org/eclipse/jetty/security/authentication/LoginAuthenticator.java
index 17e86574b6..322b17c95e 100644
--- a/jetty-security/src/main/java/org/eclipse/jetty/security/authentication/LoginAuthenticator.java
+++ b/jetty-security/src/main/java/org/eclipse/jetty/security/authentication/LoginAuthenticator.java
@@ -18,6 +18,7 @@
package org.eclipse.jetty.security.authentication;
+import javax.servlet.ServletRequest;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
@@ -25,6 +26,8 @@ import javax.servlet.http.HttpSession;
import org.eclipse.jetty.security.Authenticator;
import org.eclipse.jetty.security.IdentityService;
import org.eclipse.jetty.security.LoginService;
+import org.eclipse.jetty.server.Authentication;
+import org.eclipse.jetty.server.UserIdentity;
import org.eclipse.jetty.server.session.AbstractSessionManager;
public abstract class LoginAuthenticator implements Authenticator
@@ -37,6 +40,20 @@ public abstract class LoginAuthenticator implements Authenticator
{
}
+
+ /* ------------------------------------------------------------ */
+ public UserIdentity login(String username, Object password, ServletRequest request)
+ {
+ UserIdentity user = _loginService.login(username,password);
+ if (user!=null)
+ {
+ renewSession((HttpServletRequest)request, null);
+ return user;
+ }
+ return null;
+ }
+
+
public void setConfiguration(AuthConfiguration configuration)
{
_loginService=configuration.getLoginService();
diff --git a/jetty-security/src/main/java/org/eclipse/jetty/security/authentication/SessionAuthentication.java b/jetty-security/src/main/java/org/eclipse/jetty/security/authentication/SessionAuthentication.java
index 260d5ddd3f..7c0a56c1ac 100644
--- a/jetty-security/src/main/java/org/eclipse/jetty/security/authentication/SessionAuthentication.java
+++ b/jetty-security/src/main/java/org/eclipse/jetty/security/authentication/SessionAuthentication.java
@@ -98,8 +98,8 @@ public class SessionAuthentication implements Authentication.User, Serializable,
{
if (_session!=null && _session.getAttribute(__J_AUTHENTICATED)!=null)
_session.removeAttribute(__J_AUTHENTICATED);
- else
- doLogout();
+
+ doLogout();
}
private void doLogout()
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 ca5563f4e5..303d2f7e30 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
@@ -60,6 +60,8 @@ public class SpnegoAuthenticator extends LoginAuthenticator
return _authMethod;
}
+
+
public Authentication validateRequest(ServletRequest request, ServletResponse response, boolean mandatory) throws ServerAuthException
{
HttpServletRequest req = (HttpServletRequest)request;
@@ -96,7 +98,7 @@ public class SpnegoAuthenticator extends LoginAuthenticator
{
String spnegoToken = header.substring(10);
- UserIdentity user = _loginService.login(null,spnegoToken);
+ UserIdentity user = login(null,spnegoToken, request);
if ( user != null )
{
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 a400db3a93..cab25b10e5 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
@@ -22,9 +22,11 @@ import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
import java.io.IOException;
+import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.HashSet;
+import java.util.List;
import java.util.Map;
import java.util.Set;
@@ -76,6 +78,8 @@ public class ConstraintTest
_loginService.putUser("user",new Password("password"));
_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");
_server.setHandler(_context);
@@ -189,17 +193,59 @@ public class ConstraintTest
@Test
public void testBasic() throws Exception
{
+
+ List<ConstraintMapping> list = new ArrayList<ConstraintMapping>(_security.getConstraintMappings());
+
+ Constraint constraint6 = new Constraint();
+ constraint6.setAuthenticate(true);
+ constraint6.setName("omit POST and GET");
+ constraint6.setRoles(new String[]{"user"});
+ ConstraintMapping mapping6 = new ConstraintMapping();
+ mapping6.setPathSpec("/omit/*");
+ mapping6.setConstraint(constraint6);
+ mapping6.setMethodOmissions(new String[]{"GET", "HEAD"}); //requests for every method except GET and HEAD must be in role "user"
+ list.add(mapping6);
+
+ Constraint constraint7 = new Constraint();
+ constraint7.setAuthenticate(true);
+ constraint7.setName("non-omitted GET");
+ constraint7.setRoles(new String[]{"administrator"});
+ ConstraintMapping mapping7 = new ConstraintMapping();
+ mapping7.setPathSpec("/omit/*");
+ mapping7.setConstraint(constraint7);
+ mapping7.setMethod("GET"); //requests for GET must be in role "admin"
+ list.add(mapping7);
+
+ Constraint constraint8 = new Constraint();
+ constraint8.setAuthenticate(true);
+ constraint8.setName("non specific");
+ constraint8.setRoles(new String[]{"foo"});
+ ConstraintMapping mapping8 = new ConstraintMapping();
+ mapping8.setPathSpec("/omit/*");
+ mapping8.setConstraint(constraint8);//requests for all methods must be in role "foo"
+ list.add(mapping8);
+
+ Set<String> knownRoles=new HashSet<String>();
+ knownRoles.add("user");
+ knownRoles.add("administrator");
+ knownRoles.add("foo");
+
+ _security.setConstraintMappings(list, knownRoles);
+
+
_security.setAuthenticator(new BasicAuthenticator());
_security.setStrict(false);
_server.start();
String response;
+ /*
response = _connector.getResponses("GET /ctx/noauth/info HTTP/1.0\r\n\r\n");
assertTrue(response.startsWith("HTTP/1.1 200 OK"));
-
+*/
+
response = _connector.getResponses("GET /ctx/forbid/info HTTP/1.0\r\n\r\n");
assertTrue(response.startsWith("HTTP/1.1 403 Forbidden"));
-
+ /*
response = _connector.getResponses("GET /ctx/auth/info HTTP/1.0\r\n\r\n");
assertTrue(response.startsWith("HTTP/1.1 401 Unauthorized"));
assertTrue(response.indexOf("WWW-Authenticate: basic realm=\"TestRealm\"") > 0);
@@ -214,8 +260,8 @@ public class ConstraintTest
"Authorization: Basic " + B64Code.encode("user:password") + "\r\n" +
"\r\n");
assertTrue(response.startsWith("HTTP/1.1 200 OK"));
-
-
+*/
+/*
// test admin
response = _connector.getResponses("GET /ctx/admin/info HTTP/1.0\r\n\r\n");
assertTrue(response.startsWith("HTTP/1.1 401 Unauthorized"));
@@ -241,7 +287,33 @@ public class ConstraintTest
response = _connector.getResponses("GET /ctx/admin/relax/info HTTP/1.0\r\n\r\n");
assertTrue(response.startsWith("HTTP/1.1 200 OK"));
+
+ //check GET is in role administrator
+ response = _connector.getResponses("GET /ctx/omit/x HTTP/1.0\r\n" +
+ "Authorization: Basic " + B64Code.encode("admin:password") + "\r\n" +
+ "\r\n");
+ assertTrue(response.startsWith("HTTP/1.1 200 OK"));
+
+ //check POST is in role user
+ response = _connector.getResponses("POST /ctx/omit/x HTTP/1.0\r\n" +
+ "Authorization: Basic " + B64Code.encode("user2:password") + "\r\n" +
+ "\r\n");
+ assertTrue(response.startsWith("HTTP/1.1 200 OK"));
+
+ //check POST can be in role foo too
+ response = _connector.getResponses("POST /ctx/omit/x HTTP/1.0\r\n" +
+ "Authorization: Basic " + B64Code.encode("user3:password") + "\r\n" +
+ "\r\n");
+ assertTrue(response.startsWith("HTTP/1.1 200 OK"));
+
+ //check HEAD cannot be in role user
+ response = _connector.getResponses("HEAD /ctx/omit/x HTTP/1.0\r\n" +
+ "Authorization: Basic " + B64Code.encode("user2:password") + "\r\n" +
+ "\r\n");
+ assertTrue(response.startsWith("HTTP/1.1 200 OK"));*/
}
+
+
@Test
public void testFormDispatch() throws Exception
@@ -847,7 +919,7 @@ public class ConstraintTest
public void handle(String target, Request baseRequest, HttpServletRequest request, HttpServletResponse response ) throws IOException, ServletException
{
baseRequest.setHandled(true);
- if (request.getAuthType()==null || "user".equals(request.getRemoteUser()) || request.isUserInRole("user"))
+ if (request.getAuthType()==null || "user".equals(request.getRemoteUser()) || request.isUserInRole("user") || request.isUserInRole("foo"))
{
response.setStatus(200);
response.setContentType("text/plain; charset=UTF-8");
diff --git a/jetty-security/src/test/java/org/eclipse/jetty/security/SpecExampleConstraintTest.java b/jetty-security/src/test/java/org/eclipse/jetty/security/SpecExampleConstraintTest.java
new file mode 100644
index 0000000000..743effaddd
--- /dev/null
+++ b/jetty-security/src/test/java/org/eclipse/jetty/security/SpecExampleConstraintTest.java
@@ -0,0 +1,311 @@
+//
+// ========================================================================
+// Copyright (c) 1995-2012 Mort Bay Consulting Pty. Ltd.
+// ------------------------------------------------------------------------
+// All rights reserved. This program and the accompanying materials
+// are made available under the terms of the Eclipse Public License v1.0
+// and Apache License v2.0 which accompanies this distribution.
+//
+// The Eclipse Public License is available at
+// http://www.eclipse.org/legal/epl-v10.html
+//
+// The Apache License v2.0 is available at
+// http://www.opensource.org/licenses/apache2.0.php
+//
+// You may elect to redistribute this code under either of these licenses.
+// ========================================================================
+//
+
+package org.eclipse.jetty.security;
+
+import static org.junit.Assert.assertTrue;
+
+import java.io.IOException;
+import java.util.Arrays;
+import java.util.HashSet;
+import java.util.Set;
+
+import javax.servlet.ServletException;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import org.eclipse.jetty.security.authentication.BasicAuthenticator;
+import org.eclipse.jetty.server.Connector;
+import org.eclipse.jetty.server.LocalConnector;
+import org.eclipse.jetty.server.Request;
+import org.eclipse.jetty.server.Server;
+import org.eclipse.jetty.server.handler.AbstractHandler;
+import org.eclipse.jetty.server.handler.ContextHandler;
+import org.eclipse.jetty.server.session.SessionHandler;
+import org.eclipse.jetty.util.B64Code;
+import org.eclipse.jetty.util.security.Constraint;
+import org.eclipse.jetty.util.security.Password;
+import org.junit.After;
+import org.junit.Before;
+import org.junit.BeforeClass;
+import org.junit.Test;
+
+/**
+ * @version $Revision: 1441 $ $Date: 2010-04-02 12:28:17 +0200 (Fri, 02 Apr 2010) $
+ */
+public class SpecExampleConstraintTest
+{
+ private static final String TEST_REALM = "TestRealm";
+ private static Server _server;
+ private static LocalConnector _connector;
+ private static SessionHandler _session;
+ private ConstraintSecurityHandler _security;
+
+ @BeforeClass
+ public static void startServer()
+ {
+ _server = new Server();
+ _connector = new LocalConnector();
+ _server.setConnectors(new Connector[]{_connector});
+
+ ContextHandler _context = new ContextHandler();
+ _session = new SessionHandler();
+
+ HashLoginService _loginService = new HashLoginService(TEST_REALM);
+ _loginService.putUser("fred",new Password("password"));
+ _loginService.putUser("harry",new Password("password"), new String[] {"HOMEOWNER"});
+ _loginService.putUser("chris",new Password("password"), new String[] {"CONTRACTOR"});
+ _loginService.putUser("steven", new Password("password"), new String[] {"SALESCLERK"});
+
+
+ _context.setContextPath("/ctx");
+ _server.setHandler(_context);
+ _context.setHandler(_session);
+
+ _server.addBean(_loginService);
+ }
+
+ @Before
+ public void setupSecurity()
+ {
+ _security = new ConstraintSecurityHandler();
+ _session.setHandler(_security);
+ RequestHandler _handler = new RequestHandler();
+ _security.setHandler(_handler);
+
+
+ /*
+
+ <security-constraint>
+ <web-resource-collection>
+ <web-resource-name>precluded methods</web-resource-name>
+ <url-pattern>/*</url-pattern>
+ <url-pattern>/acme/wholesale/*</url-pattern>
+ <url-pattern>/acme/retail/*</url-pattern>
+ <http-method-exception>GET</http-method-exception>
+ <http-method-exception>POST</http-method-exception>
+ </web-resource-collection>
+ <auth-constraint/>
+ </security-constraint>
+ */
+
+ Constraint constraint0 = new Constraint();
+ constraint0.setAuthenticate(true);
+ constraint0.setName("precluded methods");
+ ConstraintMapping mapping0 = new ConstraintMapping();
+ mapping0.setPathSpec("/*");
+ mapping0.setConstraint(constraint0);
+ mapping0.setMethodOmissions(new String[]{"GET", "POST"});
+
+ ConstraintMapping mapping1 = new ConstraintMapping();
+ mapping1.setPathSpec("/acme/wholesale/*");
+ mapping1.setConstraint(constraint0);
+ mapping1.setMethodOmissions(new String[]{"GET", "POST"});
+
+ ConstraintMapping mapping2 = new ConstraintMapping();
+ mapping2.setPathSpec("/acme/retail/*");
+ mapping2.setConstraint(constraint0);
+ mapping2.setMethodOmissions(new String[]{"GET", "POST"});
+
+ /*
+
+ <security-constraint>
+ <web-resource-collection>
+ <web-resource-name>wholesale</web-resource-name>
+ <url-pattern>/acme/wholesale/*</url-pattern>
+ <http-method>GET</http-method>
+ <http-method>PUT</http-method>
+ </web-resource-collection>
+ <auth-constraint>
+ <role-name>SALESCLERK</role-name>
+ </auth-constraint>
+ </security-constraint>
+ */
+ Constraint constraint1 = new Constraint();
+ constraint1.setAuthenticate(true);
+ constraint1.setName("wholesale");
+ constraint1.setRoles(new String[]{"SALESCLERK"});
+ ConstraintMapping mapping3 = new ConstraintMapping();
+ mapping3.setPathSpec("/acme/wholesale/*");
+ mapping3.setConstraint(constraint1);
+ mapping3.setMethod("GET");
+ ConstraintMapping mapping4 = new ConstraintMapping();
+ mapping4.setPathSpec("/acme/wholesale/*");
+ mapping4.setConstraint(constraint1);
+ mapping4.setMethod("PUT");
+
+ /*
+ <security-constraint>
+ <web-resource-collection>
+ <web-resource-name>wholesale 2</web-resource-name>
+ <url-pattern>/acme/wholesale/*</url-pattern>
+ <http-method>GET</http-method>
+ <http-method>POST</http-method>
+ </web-resource-collection>
+ <auth-constraint>
+ <role-name>CONTRACTOR</role-name>
+ </auth-constraint>
+ <user-data-constraint>
+ <transport-guarantee>CONFIDENTIAL</transport-guarantee>
+ </user-data-constraint>
+ </security-constraint>
+ */
+ Constraint constraint2 = new Constraint();
+ constraint2.setAuthenticate(true);
+ constraint2.setName("wholesale 2");
+ constraint2.setRoles(new String[]{"CONTRACTOR"});
+ constraint2.setDataConstraint(Constraint.DC_CONFIDENTIAL);
+ ConstraintMapping mapping5 = new ConstraintMapping();
+ mapping5.setPathSpec("/acme/wholesale/*");
+ mapping5.setMethod("GET");
+ mapping5.setConstraint(constraint2);
+ ConstraintMapping mapping6 = new ConstraintMapping();
+ mapping6.setPathSpec("/acme/wholesale/*");
+ mapping6.setMethod("POST");
+ mapping6.setConstraint(constraint2);
+
+ /*
+<security-constraint>
+<web-resource-collection>
+<web-resource-name>retail</web-resource-name>
+<url-pattern>/acme/retail/*</url-pattern>
+<http-method>GET</http-method>
+<http-method>POST</http-method>
+</web-resource-collection>
+<auth-constraint>
+<role-name>CONTRACTOR</role-name>
+<role-name>HOMEOWNER</role-name>
+</auth-constraint>
+</security-constraint>
+*/
+ Constraint constraint4 = new Constraint();
+ constraint4.setName("retail");
+ constraint4.setAuthenticate(true);
+ constraint4.setRoles(new String[]{"CONTRACTOR", "HOMEOWNER"});
+ ConstraintMapping mapping7 = new ConstraintMapping();
+ mapping7.setPathSpec("/acme/retail/*");
+ mapping7.setMethod("GET");
+ mapping7.setConstraint(constraint4);
+ ConstraintMapping mapping8 = new ConstraintMapping();
+ mapping8.setPathSpec("/acme/retail/*");
+ mapping8.setMethod("POST");
+ mapping8.setConstraint(constraint4);
+
+
+
+
+ Set<String> knownRoles=new HashSet<String>();
+ knownRoles.add("CONTRACTOR");
+ knownRoles.add("HOMEOWNER");
+ knownRoles.add("SALESCLERK");
+
+ _security.setConstraintMappings(Arrays.asList(new ConstraintMapping[]
+ {
+ mapping0, mapping1, mapping2, mapping3, mapping4, mapping5, mapping6, mapping7, mapping8
+ }), knownRoles);
+ }
+
+ @After
+ public void stopServer() throws Exception
+ {
+ if (_server.isRunning())
+ {
+ _server.stop();
+ _server.join();
+ }
+ }
+
+
+
+ @Test
+ public void testBasic() throws Exception
+ {
+
+ _security.setAuthenticator(new BasicAuthenticator());
+ _security.setStrict(false);
+ _server.start();
+
+ String response;
+ /*
+ /star all methods except GET/POST forbidden
+ /acme/wholesale/star all methods except GET/POST forbidden
+ /acme/retail/star all methods except GET/POST forbidden
+ /acme/wholesale/star GET must be in role CONTRACTOR or SALESCLERK
+ /acme/wholesale/star POST must be in role CONTRACTOR and confidential transport
+ /acme/retail/star GET must be in role CONTRACTOR or HOMEOWNER
+ /acme/retail/star POST must be in role CONTRACTOR or HOMEOWNER
+ */
+
+ //a user in role HOMEOWNER is forbidden HEAD request
+ response = _connector.getResponses("HEAD /ctx/index.html HTTP/1.0\r\n\r\n");
+ assertTrue(response.startsWith("HTTP/1.1 403 Forbidden"));
+
+ response = _connector.getResponses("HEAD /ctx/index.html HTTP/1.0\r\n" +
+ "Authorization: Basic " + B64Code.encode("harry:password") + "\r\n" +
+ "\r\n");
+ assertTrue(response.startsWith("HTTP/1.1 403 Forbidden"));
+
+ response = _connector.getResponses("HEAD /ctx/acme/wholesale/index.html HTTP/1.0\r\n" +
+ "Authorization: Basic " + B64Code.encode("harry:password") + "\r\n" +
+ "\r\n");
+ assertTrue(response.startsWith("HTTP/1.1 403 Forbidden"));
+
+ response = _connector.getResponses("HEAD /ctx/acme/retail/index.html HTTP/1.0\r\n" +
+ "Authorization: Basic " + B64Code.encode("harry:password") + "\r\n" +
+ "\r\n");
+ assertTrue(response.startsWith("HTTP/1.1 403 Forbidden"));
+
+ //a user in role CONTRACTOR can do a GET
+ response = _connector.getResponses("GET /ctx/acme/wholesale/index.html HTTP/1.0\r\n" +
+ "Authorization: Basic " + B64Code.encode("chris:password") + "\r\n" +
+ "\r\n");
+
+ assertTrue(response.startsWith("HTTP/1.1 200 OK"));
+
+ //a user in role CONTRACTOR can only do a post if confidential
+ response = _connector.getResponses("POST /ctx/acme/wholesale/index.html HTTP/1.0\r\n" +
+ "Authorization: Basic " + B64Code.encode("chris:password") + "\r\n" +
+ "\r\n");
+ assertTrue(response.startsWith("HTTP/1.1 403 !Confidential"));
+
+
+ //a user in role HOMEOWNER can do a GET
+ response = _connector.getResponses("GET /ctx/acme/retail/index.html HTTP/1.0\r\n" +
+ "Authorization: Basic " + B64Code.encode("harry:password") + "\r\n" +
+ "\r\n");
+ assertTrue(response.startsWith("HTTP/1.1 200 OK"));
+ }
+
+
+ private class RequestHandler extends AbstractHandler
+ {
+ public void handle(String target, Request baseRequest, HttpServletRequest request, HttpServletResponse response ) throws IOException, ServletException
+ {
+ baseRequest.setHandled(true);
+
+ response.setStatus(200);
+ response.setContentType("text/plain; charset=UTF-8");
+ response.getWriter().println("URI="+request.getRequestURI());
+ String user = request.getRemoteUser();
+ response.getWriter().println("user="+user);
+ if (request.getParameter("test_parameter")!=null)
+ response.getWriter().println(request.getParameter("test_parameter"));
+ }
+ }
+
+}
diff --git a/jetty-server/pom.xml b/jetty-server/pom.xml
index 169cde2117..35dbdd5959 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>7.6.8-SNAPSHOT</version>
+ <version>8.1.8-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>jetty-server</artifactId>
@@ -25,7 +25,7 @@
</goals>
<configuration>
<instructions>
- <Import-Package>javax.servlet.*;version="[2.5,3.0)",org.eclipse.jetty.jmx.*;version="[7.3,8)";resolution:=optional,*</Import-Package>
+ <Import-Package>javax.servlet.*;version="2.6.0",org.eclipse.jetty.jmx.*;version="8.0";resolution:=optional,*</Import-Package>
</instructions>
</configuration>
</execution>
diff --git a/jetty-server/src/main/java/org/eclipse/jetty/server/AbstractHttpConnection.java b/jetty-server/src/main/java/org/eclipse/jetty/server/AbstractHttpConnection.java
index 49fe8ca094..a160bfa18d 100644
--- a/jetty-server/src/main/java/org/eclipse/jetty/server/AbstractHttpConnection.java
+++ b/jetty-server/src/main/java/org/eclipse/jetty/server/AbstractHttpConnection.java
@@ -21,6 +21,7 @@ package org.eclipse.jetty.server;
import java.io.IOException;
import java.io.InputStream;
import java.io.PrintWriter;
+import javax.servlet.DispatcherType;
import javax.servlet.ServletInputStream;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletResponse;
@@ -423,6 +424,7 @@ public abstract class AbstractHttpConnection extends AbstractConnection
boolean error = false;
String threadName=null;
+ Throwable async_exception=null;
try
{
if (LOG.isDebugEnabled())
@@ -494,6 +496,7 @@ public abstract class AbstractHttpConnection extends AbstractConnection
}
catch (EofException e)
{
+ async_exception=e;
LOG.debug(e);
error=true;
_request.setHandled(true);
@@ -502,6 +505,7 @@ public abstract class AbstractHttpConnection extends AbstractConnection
}
catch (RuntimeIOException e)
{
+ async_exception=e;
LOG.debug(e);
error=true;
_request.setHandled(true);
@@ -515,6 +519,7 @@ public abstract class AbstractHttpConnection extends AbstractConnection
}
catch (Throwable e)
{
+ async_exception=e;
LOG.warn(String.valueOf(_uri),e);
error=true;
_request.setHandled(true);
@@ -533,7 +538,8 @@ public abstract class AbstractHttpConnection extends AbstractConnection
if (_request._async.isUncompleted())
{
- _request._async.doComplete();
+
+ _request._async.doComplete(async_exception);
if (_expect100Continue)
{
diff --git a/jetty-server/src/main/java/org/eclipse/jetty/server/AsyncContext.java b/jetty-server/src/main/java/org/eclipse/jetty/server/AsyncContext.java
deleted file mode 100644
index 90c6503225..0000000000
--- a/jetty-server/src/main/java/org/eclipse/jetty/server/AsyncContext.java
+++ /dev/null
@@ -1,48 +0,0 @@
-//
-// ========================================================================
-// Copyright (c) 1995-2012 Mort Bay Consulting Pty. Ltd.
-// ------------------------------------------------------------------------
-// All rights reserved. This program and the accompanying materials
-// are made available under the terms of the Eclipse Public License v1.0
-// and Apache License v2.0 which accompanies this distribution.
-//
-// The Eclipse Public License is available at
-// http://www.eclipse.org/legal/epl-v10.html
-//
-// The Apache License v2.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 javax.servlet.ServletContext;
-import javax.servlet.ServletRequest;
-import javax.servlet.ServletResponse;
-
-import org.eclipse.jetty.continuation.ContinuationListener;
-
-/* temporary interface in anticipation of servlet 3.0 */
-public interface AsyncContext
-{
- static final String ASYNC_REQUEST_URI = "javax.servlet.async.request_uri";
- static final String ASYNC_CONTEXT_PATH = "javax.servlet.async.context_path";
- static final String ASYNC_PATH_INFO = "javax.servlet.async.path_info";
- static final String ASYNC_SERVLET_PATH = "javax.servlet.async.servlet_path";
- static final String ASYNC_QUERY_STRING = "javax.servlet.async.query_string";
-
- public ServletRequest getRequest();
- public ServletResponse getResponse();
- public boolean hasOriginalRequestAndResponse();
- public void dispatch();
- public void dispatch(String path);
- public void dispatch(ServletContext context, String path);
- public void complete();
- public void start(Runnable run);
- public void setTimeout(long ms);
- public void addContinuationListener(ContinuationListener listener);
-}
-
-
diff --git a/jetty-server/src/main/java/org/eclipse/jetty/server/AsyncContinuation.java b/jetty-server/src/main/java/org/eclipse/jetty/server/AsyncContinuation.java
index 7bf4999278..8bf27dd29c 100644
--- a/jetty-server/src/main/java/org/eclipse/jetty/server/AsyncContinuation.java
+++ b/jetty-server/src/main/java/org/eclipse/jetty/server/AsyncContinuation.java
@@ -18,6 +18,12 @@
package org.eclipse.jetty.server;
+import javax.servlet.AsyncContext;
+import javax.servlet.AsyncEvent;
+import javax.servlet.AsyncListener;
+import javax.servlet.ServletResponseWrapper;
+import javax.servlet.ServletException;
+
import java.util.ArrayList;
import java.util.List;
@@ -27,8 +33,8 @@ import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import org.eclipse.jetty.continuation.Continuation;
-import org.eclipse.jetty.continuation.ContinuationListener;
import org.eclipse.jetty.continuation.ContinuationThrowable;
+import org.eclipse.jetty.continuation.ContinuationListener;
import org.eclipse.jetty.io.AsyncEndPoint;
import org.eclipse.jetty.io.EndPoint;
import org.eclipse.jetty.server.handler.ContextHandler;
@@ -39,7 +45,7 @@ import org.eclipse.jetty.util.log.Logger;
import org.eclipse.jetty.util.thread.Timeout;
/* ------------------------------------------------------------ */
-/** Implementation of Continuation and AsyncContext interfaces.
+/** Implementation of Continuation and AsyncContext interfaces
*
*/
public class AsyncContinuation implements AsyncContext, Continuation
@@ -74,9 +80,10 @@ public class AsyncContinuation implements AsyncContext, Continuation
private static final int __UNCOMPLETED=8; // Request is completable
private static final int __COMPLETED=9; // Request is complete
-
/* ------------------------------------------------------------ */
protected AbstractHttpConnection _connection;
+ private List<AsyncListener> _lastAsyncListeners;
+ private List<AsyncListener> _asyncListeners;
private List<ContinuationListener> _continuationListeners;
/* ------------------------------------------------------------ */
@@ -87,7 +94,8 @@ public class AsyncContinuation implements AsyncContext, Continuation
private volatile boolean _responseWrapped;
private long _timeoutMs=DEFAULT_TIMEOUT;
private AsyncEventState _event;
- private volatile long _expireAt;
+ private volatile long _expireAt;
+ private volatile boolean _continuation;
/* ------------------------------------------------------------ */
protected AsyncContinuation()
@@ -106,6 +114,29 @@ public class AsyncContinuation implements AsyncContext, Continuation
}
/* ------------------------------------------------------------ */
+ public void addListener(AsyncListener listener)
+ {
+ synchronized(this)
+ {
+ if (_asyncListeners==null)
+ _asyncListeners=new ArrayList<AsyncListener>();
+ _asyncListeners.add(listener);
+ }
+ }
+
+ /* ------------------------------------------------------------ */
+ public void addListener(AsyncListener listener,ServletRequest request, ServletResponse response)
+ {
+ synchronized(this)
+ {
+ // TODO handle the request/response ???
+ if (_asyncListeners==null)
+ _asyncListeners=new ArrayList<AsyncListener>();
+ _asyncListeners.add(listener);
+ }
+ }
+
+ /* ------------------------------------------------------------ */
public void addContinuationListener(ContinuationListener listener)
{
synchronized(this)
@@ -268,6 +299,7 @@ public class AsyncContinuation implements AsyncContext, Continuation
{
synchronized (this)
{
+ _continuation=false;
_responseWrapped=false;
switch(_state)
@@ -275,6 +307,15 @@ public class AsyncContinuation implements AsyncContext, Continuation
case __IDLE:
_initial=true;
_state=__DISPATCHED;
+ if (_lastAsyncListeners!=null)
+ _lastAsyncListeners.clear();
+ if (_asyncListeners!=null)
+ _asyncListeners.clear();
+ else
+ {
+ _asyncListeners=_lastAsyncListeners;
+ _lastAsyncListeners=null;
+ }
return true;
case __COMPLETING:
@@ -311,7 +352,7 @@ public class AsyncContinuation implements AsyncContext, Continuation
_resumed=false;
_expired=false;
- if (_event==null || request!=_event.getRequest() || response != _event.getResponse() || context != _event.getServletContext())
+ if (_event==null || request!=_event.getSuppliedRequest() || response != _event.getSuppliedResponse() || context != _event.getServletContext())
_event=new AsyncEventState(context,request,response);
else
{
@@ -319,12 +360,32 @@ public class AsyncContinuation implements AsyncContext, Continuation
_event._pathInContext=null;
}
_state=__ASYNCSTARTED;
+ List<AsyncListener> recycle=_lastAsyncListeners;
+ _lastAsyncListeners=_asyncListeners;
+ _asyncListeners=recycle;
+ if (_asyncListeners!=null)
+ _asyncListeners.clear();
break;
default:
throw new IllegalStateException(this.getStatusString());
}
}
+
+ if (_lastAsyncListeners!=null)
+ {
+ for (AsyncListener listener : _lastAsyncListeners)
+ {
+ try
+ {
+ listener.onStartAsync(_event);
+ }
+ catch(Exception e)
+ {
+ LOG.warn(e);
+ }
+ }
+ }
}
/* ------------------------------------------------------------ */
@@ -339,8 +400,6 @@ public class AsyncContinuation implements AsyncContext, Continuation
{
synchronized (this)
{
- List<ContinuationListener> listeners=_continuationListeners;
-
switch(_state)
{
case __REDISPATCHED:
@@ -361,7 +420,7 @@ public class AsyncContinuation implements AsyncContext, Continuation
{
_state=__UNCOMPLETED;
return true;
- }
+ }
_initial=false;
_state=__REDISPATCHED;
return false;
@@ -419,27 +478,43 @@ public class AsyncContinuation implements AsyncContext, Continuation
/* ------------------------------------------------------------ */
protected void expired()
{
- final List<ContinuationListener> listeners;
+ final List<ContinuationListener> cListeners;
+ final List<AsyncListener> aListeners;
synchronized (this)
{
switch(_state)
{
case __ASYNCSTARTED:
case __ASYNCWAIT:
- listeners=_continuationListeners;
+ cListeners=_continuationListeners;
+ aListeners=_asyncListeners;
break;
default:
- listeners=null;
+ cListeners=null;
+ aListeners=null;
return;
}
_expired=true;
}
- if (listeners!=null)
+ if (aListeners!=null)
+ {
+ for (AsyncListener listener : aListeners)
+ {
+ try
+ {
+ listener.onTimeout(_event);
+ }
+ catch(Exception e)
+ {
+ LOG.warn(e);
+ }
+ }
+ }
+ if (cListeners!=null)
{
- for (int i=0;i<listeners.size();i++)
+ for (ContinuationListener listener : cListeners)
{
- ContinuationListener listener=listeners.get(i);
try
{
listener.onTimeout(this);
@@ -450,6 +525,8 @@ public class AsyncContinuation implements AsyncContext, Continuation
}
}
}
+
+
synchronized (this)
{
@@ -457,7 +534,11 @@ public class AsyncContinuation implements AsyncContext, Continuation
{
case __ASYNCSTARTED:
case __ASYNCWAIT:
- dispatch();
+ if (_continuation)
+ dispatch();
+ else
+ // TODO maybe error dispatch?
+ complete();
}
}
@@ -501,36 +582,75 @@ public class AsyncContinuation implements AsyncContext, Continuation
}
}
-
+ /* ------------------------------------------------------------ */
+ @Override
+ public <T extends AsyncListener> T createListener(Class<T> clazz) throws ServletException
+ {
+ try
+ {
+ // TODO inject
+ return clazz.newInstance();
+ }
+ catch(Exception e)
+ {
+ throw new ServletException(e);
+ }
+ }
+
+
/* ------------------------------------------------------------ */
/* (non-Javadoc)
* @see javax.servlet.ServletRequest#complete()
*/
- protected void doComplete()
+ protected void doComplete(Throwable ex)
{
- final List<ContinuationListener> listeners;
+ final List<ContinuationListener> cListeners;
+ final List<AsyncListener> aListeners;
synchronized (this)
{
switch(_state)
{
case __UNCOMPLETED:
_state=__COMPLETED;
- listeners=_continuationListeners;
+ cListeners=_continuationListeners;
+ aListeners=_asyncListeners;
break;
default:
- listeners=null;
+ cListeners=null;
+ aListeners=null;
throw new IllegalStateException(this.getStatusString());
}
}
- if (listeners!=null)
+ if (aListeners!=null)
+ {
+ for (AsyncListener listener : aListeners)
+ {
+ try
+ {
+ if (ex!=null)
+ {
+ _event.getSuppliedRequest().setAttribute(Dispatcher.ERROR_EXCEPTION,ex);
+ _event.getSuppliedRequest().setAttribute(Dispatcher.ERROR_MESSAGE,ex.getMessage());
+ listener.onError(_event);
+ }
+ else
+ listener.onComplete(_event);
+ }
+ catch(Exception e)
+ {
+ LOG.warn(e);
+ }
+ }
+ }
+ if (cListeners!=null)
{
- for(int i=0;i<listeners.size();i++)
+ for (ContinuationListener listener : cListeners)
{
try
{
- listeners.get(i).onComplete(this);
+ listener.onComplete(this);
}
catch(Exception e)
{
@@ -545,7 +665,6 @@ public class AsyncContinuation implements AsyncContext, Continuation
{
synchronized (this)
{
-// _history.append("r\n");
switch(_state)
{
case __DISPATCHED:
@@ -617,7 +736,7 @@ public class AsyncContinuation implements AsyncContext, Continuation
}
else
{
- ((AsyncEndPoint)endp).scheduleTimeout(_event,_timeoutMs);
+ ((AsyncEndPoint)endp).scheduleTimeout(_event._timeout,_timeoutMs);
}
}
}
@@ -639,7 +758,7 @@ public class AsyncContinuation implements AsyncContext, Continuation
final AsyncEventState event=_event;
if (event!=null)
{
- ((AsyncEndPoint)endp).cancelTimeout(event);
+ ((AsyncEndPoint)endp).cancelTimeout(event._timeout);
}
}
}
@@ -736,15 +855,15 @@ public class AsyncContinuation implements AsyncContext, Continuation
public ServletRequest getRequest()
{
if (_event!=null)
- return _event.getRequest();
+ return _event.getSuppliedRequest();
return _connection.getRequest();
}
/* ------------------------------------------------------------ */
public ServletResponse getResponse()
{
- if (_event!=null)
- return _event.getResponse();
+ if (_responseWrapped && _event!=null && _event.getSuppliedResponse()!=null)
+ return _event.getSuppliedResponse();
return _connection.getResponse();
}
@@ -769,7 +888,7 @@ public class AsyncContinuation implements AsyncContext, Continuation
{
synchronized (this)
{
- return (_event!=null && _event.getRequest()==_connection._request && _event.getResponse()==_connection._response);
+ return (_event!=null && _event.getSuppliedRequest()==_connection._request && _event.getSuppliedResponse()==_connection._response);
}
}
@@ -840,6 +959,7 @@ public class AsyncContinuation implements AsyncContext, Continuation
*/
public void suspend(ServletResponse response)
{
+ _continuation=true;
_responseWrapped=!(response instanceof Response);
doSuspend(_connection.getRequest().getServletContext(),_connection.getRequest(),response);
}
@@ -851,6 +971,7 @@ public class AsyncContinuation implements AsyncContext, Continuation
public void suspend()
{
_responseWrapped=false;
+ _continuation=true;
doSuspend(_connection.getRequest().getServletContext(),_connection.getRequest(),_connection.getResponse());
}
@@ -860,8 +981,8 @@ public class AsyncContinuation implements AsyncContext, Continuation
*/
public ServletResponse getServletResponse()
{
- if (_responseWrapped && _event!=null && _event.getResponse()!=null)
- return _event.getResponse();
+ if (_responseWrapped && _event!=null && _event.getSuppliedResponse()!=null)
+ return _event.getSuppliedResponse();
return _connection.getResponse();
}
@@ -910,21 +1031,34 @@ public class AsyncContinuation implements AsyncContext, Continuation
/* ------------------------------------------------------------ */
/* ------------------------------------------------------------ */
- public class AsyncEventState extends Timeout.Task implements Runnable
+ public class AsyncTimeout extends Timeout.Task implements Runnable
+ {
+ @Override
+ public void expired()
+ {
+ AsyncContinuation.this.expired();
+ }
+
+ @Override
+ public void run()
+ {
+ AsyncContinuation.this.expired();
+ }
+ }
+
+ /* ------------------------------------------------------------ */
+ /* ------------------------------------------------------------ */
+ public class AsyncEventState extends AsyncEvent
{
private final ServletContext _suspendedContext;
- private final ServletRequest _request;
- private final ServletResponse _response;
private ServletContext _dispatchContext;
private String _pathInContext;
+ private Timeout.Task _timeout= new AsyncTimeout();
public AsyncEventState(ServletContext context, ServletRequest request, ServletResponse response)
{
+ super(AsyncContinuation.this, request,response);
_suspendedContext=context;
- _request=request;
- _response=response;
-
-
// Get the base request So we can remember the initial paths
Request r=_connection.getRequest();
@@ -969,16 +1103,6 @@ public class AsyncContinuation implements AsyncContext, Continuation
{
return _dispatchContext==null?_suspendedContext:_dispatchContext;
}
-
- public ServletRequest getRequest()
- {
- return _request;
- }
-
- public ServletResponse getResponse()
- {
- return _response;
- }
/* ------------------------------------------------------------ */
/**
@@ -988,16 +1112,5 @@ public class AsyncContinuation implements AsyncContext, Continuation
{
return _pathInContext;
}
-
- @Override
- public void expired()
- {
- AsyncContinuation.this.expired();
- }
-
- public void run()
- {
- AsyncContinuation.this.expired();
- }
}
}
diff --git a/jetty-server/src/main/java/org/eclipse/jetty/server/Authentication.java b/jetty-server/src/main/java/org/eclipse/jetty/server/Authentication.java
index 1c63baf764..ff281f6d03 100644
--- a/jetty-server/src/main/java/org/eclipse/jetty/server/Authentication.java
+++ b/jetty-server/src/main/java/org/eclipse/jetty/server/Authentication.java
@@ -85,7 +85,7 @@ public interface Authentication
* @param password
* @return The new Authentication state
*/
- Authentication login(String username,String password);
+ Authentication login(String username,Object password,ServletRequest request);
}
diff --git a/jetty-server/src/main/java/org/eclipse/jetty/server/Dispatcher.java b/jetty-server/src/main/java/org/eclipse/jetty/server/Dispatcher.java
index 7448e297da..e5353cc1d4 100644
--- a/jetty-server/src/main/java/org/eclipse/jetty/server/Dispatcher.java
+++ b/jetty-server/src/main/java/org/eclipse/jetty/server/Dispatcher.java
@@ -25,6 +25,7 @@ import java.util.HashSet;
import java.util.Iterator;
import java.util.Map;
+import javax.servlet.DispatcherType;
import javax.servlet.RequestDispatcher;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
@@ -45,24 +46,6 @@ import org.eclipse.jetty.util.UrlEncoded;
*/
public class Dispatcher implements RequestDispatcher
{
- public static final String FORWARD_REQUEST_URI = "javax.servlet.forward.request_uri";
- public static final String FORWARD_CONTEXT_PATH = "javax.servlet.forward.context_path";
- public static final String FORWARD_PATH_INFO = "javax.servlet.forward.path_info";
- public static final String FORWARD_SERVLET_PATH = "javax.servlet.forward.servlet_path";
- public static final String FORWARD_QUERY_STRING = "javax.servlet.forward.query_string";
- public static final String INCLUDE_REQUEST_URI = "javax.servlet.include.request_uri";
- public static final String INCLUDE_CONTEXT_PATH = "javax.servlet.include.context_path";
- public static final String INCLUDE_PATH_INFO = "javax.servlet.include.path_info";
- public static final String INCLUDE_SERVLET_PATH = "javax.servlet.include.servlet_path";
- public static final String INCLUDE_QUERY_STRING = "javax.servlet.include.query_string";
-
- public static final String ERROR_EXCEPTION = "javax.servlet.error.exception";
- public static final String ERROR_EXCEPTION_TYPE = "javax.servlet.error.exception_type";
- public static final String ERROR_MESSAGE = "javax.servlet.error.message";
- public static final String ERROR_REQUEST_URI = "javax.servlet.error.request_uri";
- public static final String ERROR_SERVLET_NAME = "javax.servlet.error.servlet_name";
- public static final String ERROR_STATUS_CODE = "javax.servlet.error.status_code";
-
/** Dispatch include attribute names */
public final static String __INCLUDE_PREFIX="javax.servlet.include.";
diff --git a/jetty-server/src/main/java/org/eclipse/jetty/server/DispatcherType.java b/jetty-server/src/main/java/org/eclipse/jetty/server/DispatcherType.java
deleted file mode 100644
index dc5307372d..0000000000
--- a/jetty-server/src/main/java/org/eclipse/jetty/server/DispatcherType.java
+++ /dev/null
@@ -1,28 +0,0 @@
-//
-// ========================================================================
-// Copyright (c) 1995-2012 Mort Bay Consulting Pty. Ltd.
-// ------------------------------------------------------------------------
-// All rights reserved. This program and the accompanying materials
-// are made available under the terms of the Eclipse Public License v1.0
-// and Apache License v2.0 which accompanies this distribution.
-//
-// The Eclipse Public License is available at
-// http://www.eclipse.org/legal/epl-v10.html
-//
-// The Apache License v2.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;
-
-public enum DispatcherType
-{
- FORWARD,
- INCLUDE,
- REQUEST,
- ASYNC,
- ERROR
-}
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 4d927bc317..62dc7ab3b1 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
@@ -19,6 +19,7 @@
package org.eclipse.jetty.server;
import java.io.BufferedReader;
+import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
@@ -37,16 +38,26 @@ import java.util.Locale;
import java.util.Map;
import java.util.Map.Entry;
+import javax.servlet.AsyncContext;
+import javax.servlet.AsyncEvent;
+import javax.servlet.AsyncListener;
+import javax.servlet.DispatcherType;
+import javax.servlet.MultipartConfigElement;
import javax.servlet.RequestDispatcher;
import javax.servlet.ServletContext;
+import javax.servlet.ServletException;
import javax.servlet.ServletInputStream;
import javax.servlet.ServletRequest;
import javax.servlet.ServletRequestAttributeEvent;
import javax.servlet.ServletRequestAttributeListener;
+import javax.servlet.ServletRequestEvent;
+import javax.servlet.ServletRequestListener;
import javax.servlet.ServletResponse;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
+import javax.servlet.http.Part;
import org.eclipse.jetty.continuation.Continuation;
import org.eclipse.jetty.continuation.ContinuationListener;
@@ -61,6 +72,7 @@ import org.eclipse.jetty.http.HttpVersions;
import org.eclipse.jetty.http.MimeTypes;
import org.eclipse.jetty.io.Buffer;
import org.eclipse.jetty.io.BufferUtil;
+import org.eclipse.jetty.io.ByteArrayBuffer;
import org.eclipse.jetty.io.EndPoint;
import org.eclipse.jetty.io.nio.DirectNIOBuffer;
import org.eclipse.jetty.io.nio.IndirectNIOBuffer;
@@ -70,7 +82,9 @@ import org.eclipse.jetty.server.handler.ContextHandler.Context;
import org.eclipse.jetty.util.Attributes;
import org.eclipse.jetty.util.AttributesMap;
import org.eclipse.jetty.util.LazyList;
+import org.eclipse.jetty.util.MultiException;
import org.eclipse.jetty.util.MultiMap;
+import org.eclipse.jetty.util.MultiPartInputStream;
import org.eclipse.jetty.util.StringUtil;
import org.eclipse.jetty.util.URIUtil;
import org.eclipse.jetty.util.UrlEncoded;
@@ -111,12 +125,51 @@ import org.eclipse.jetty.util.log.Logger;
*/
public class Request implements HttpServletRequest
{
+ public static final String __MULTIPART_CONFIG_ELEMENT = "org.eclipse.multipartConfig";
+ public static final String __MULTIPART_INPUT_STREAM = "org.eclipse.multiPartInputStream";
+ public static final String __MULTIPART_CONTEXT = "org.eclipse.multiPartContext";
private static final Logger LOG = Log.getLogger(Request.class);
private static final String __ASYNC_FWD = "org.eclipse.asyncfwd";
private static final Collection __defaultLocale = Collections.singleton(Locale.getDefault());
private static final int __NONE = 0, _STREAM = 1, __READER = 2;
+ public static class MultiPartCleanerListener implements ServletRequestListener
+ {
+
+ @Override
+ public void requestDestroyed(ServletRequestEvent sre)
+ {
+ //Clean up any tmp files created by MultiPartInputStream
+ MultiPartInputStream mpis = (MultiPartInputStream)sre.getServletRequest().getAttribute(__MULTIPART_INPUT_STREAM);
+ if (mpis != null)
+ {
+ ContextHandler.Context context = (ContextHandler.Context)sre.getServletRequest().getAttribute(__MULTIPART_CONTEXT);
+
+ //Only do the cleanup if we are exiting from the context in which a servlet parsed the multipart files
+ if (context == sre.getServletContext())
+ {
+ try
+ {
+ mpis.deleteParts();
+ }
+ catch (MultiException e)
+ {
+ sre.getServletContext().log("Errors deleting multipart tmp files", e);
+ }
+ }
+ }
+ }
+
+ @Override
+ public void requestInitialized(ServletRequestEvent sre)
+ {
+ //nothing to do, multipart config set up by ServletHolder.handle()
+ }
+
+ }
+
+
/* ------------------------------------------------------------ */
public static Request getRequest(HttpServletRequest request)
{
@@ -170,7 +223,9 @@ public class Request implements HttpServletRequest
private Buffer _timeStampBuffer;
private HttpURI _uri;
-
+
+ private MultiPartInputStream _multiPartInputStream; //if the request is a multi-part mime
+
/* ------------------------------------------------------------ */
public Request()
{
@@ -188,7 +243,9 @@ public class Request implements HttpServletRequest
if (listener instanceof ServletRequestAttributeListener)
_requestAttributeListeners = LazyList.add(_requestAttributeListeners,listener);
if (listener instanceof ContinuationListener)
- throw new IllegalArgumentException();
+ throw new IllegalArgumentException(listener.getClass().toString());
+ if (listener instanceof AsyncListener)
+ throw new IllegalArgumentException(listener.getClass().toString());
}
/* ------------------------------------------------------------ */
@@ -321,7 +378,7 @@ public class Request implements HttpServletRequest
{
return _async;
}
-
+
/* ------------------------------------------------------------ */
/*
* @see javax.servlet.ServletRequest#getAttribute(java.lang.String)
@@ -377,8 +434,8 @@ public class Request implements HttpServletRequest
public String getAuthType()
{
if (_authentication instanceof Authentication.Deferred)
- _authentication = ((Authentication.Deferred)_authentication).authenticate(this);
-
+ setAuthentication(((Authentication.Deferred)_authentication).authenticate(this));
+
if (_authentication instanceof Authentication.User)
return ((Authentication.User)_authentication).getAuthMethod();
return null;
@@ -1255,6 +1312,7 @@ public class Request implements HttpServletRequest
UserIdentity user = ((Authentication.User)_authentication).getUserIdentity();
return user.getUserPrincipal();
}
+
return null;
}
@@ -1275,6 +1333,12 @@ public class Request implements HttpServletRequest
return _handled;
}
+ public boolean isAsyncStarted()
+ {
+ return _async.isAsyncStarted();
+ }
+
+
/* ------------------------------------------------------------ */
public boolean isAsyncSupported()
{
@@ -1410,7 +1474,8 @@ public class Request implements HttpServletRequest
if (_savedNewSessions != null)
_savedNewSessions.clear();
- _savedNewSessions = null;
+ _savedNewSessions=null;
+ _multiPartInputStream = null;
}
/* ------------------------------------------------------------ */
@@ -1912,6 +1977,118 @@ public class Request implements HttpServletRequest
}
/* ------------------------------------------------------------ */
+ public boolean authenticate(HttpServletResponse response) throws IOException, ServletException
+ {
+ if (_authentication instanceof Authentication.Deferred)
+ {
+ setAuthentication(((Authentication.Deferred)_authentication).authenticate(this,response));
+ return !(_authentication instanceof Authentication.ResponseSent);
+ }
+ response.sendError(HttpStatus.UNAUTHORIZED_401);
+ return false;
+ }
+
+ /* ------------------------------------------------------------ */
+ public Part getPart(String name) throws IOException, ServletException
+ {
+ if (getContentType() == null || !getContentType().startsWith("multipart/form-data"))
+ throw new ServletException("Content-Type != multipart/form-data");
+
+ if (_multiPartInputStream == null)
+ {
+ MultipartConfigElement config = (MultipartConfigElement)getAttribute(__MULTIPART_CONFIG_ELEMENT);
+
+ if (config == null)
+ throw new IllegalStateException("No multipart config for servlet");
+
+ _multiPartInputStream = new MultiPartInputStream(getInputStream(),
+ getContentType(),config,
+ (_context != null?(File)_context.getAttribute("javax.servlet.context.tempdir"):null));
+ setAttribute(__MULTIPART_INPUT_STREAM, _multiPartInputStream);
+ setAttribute(__MULTIPART_CONTEXT, _context);
+ Collection<Part> parts = _multiPartInputStream.getParts(); //causes parsing
+ for (Part p:parts)
+ {
+ MultiPartInputStream.MultiPart mp = (MultiPartInputStream.MultiPart)p;
+ if (mp.getContentDispositionFilename() == null && mp.getFile() == null)
+ {
+ //Servlet Spec 3.0 pg 23, parts without filenames must be put into init params
+ String charset = null;
+ if (mp.getContentType() != null)
+ charset = MimeTypes.getCharsetFromContentType(new ByteArrayBuffer(mp.getContentType()));
+
+ String content=new String(mp.getBytes(),charset==null?StringUtil.__UTF8:charset);
+ getParameter(""); //cause params to be evaluated
+ getParameters().add(mp.getName(), content);
+ }
+ }
+ }
+ return _multiPartInputStream.getPart(name);
+ }
+
+ /* ------------------------------------------------------------ */
+ public Collection<Part> getParts() throws IOException, ServletException
+ {
+ if (getContentType() == null || !getContentType().startsWith("multipart/form-data"))
+ throw new ServletException("Content-Type != multipart/form-data");
+
+ if (_multiPartInputStream == null)
+ {
+ MultipartConfigElement config = (MultipartConfigElement)getAttribute(__MULTIPART_CONFIG_ELEMENT);
+
+ if (config == null)
+ throw new IllegalStateException("No multipart config for servlet");
+
+ _multiPartInputStream = new MultiPartInputStream(getInputStream(),
+ getContentType(), config,
+ (_context != null?(File)_context.getAttribute("javax.servlet.context.tempdir"):null));
+
+ setAttribute(__MULTIPART_INPUT_STREAM, _multiPartInputStream);
+ setAttribute(__MULTIPART_CONTEXT, _context);
+ Collection<Part> parts = _multiPartInputStream.getParts(); //causes parsing
+ for (Part p:parts)
+ {
+ MultiPartInputStream.MultiPart mp = (MultiPartInputStream.MultiPart)p;
+ if (mp.getContentDispositionFilename() == null && mp.getFile() == null)
+ {
+ //Servlet Spec 3.0 pg 23, parts without filenames must be put into init params
+ String charset = null;
+ if (mp.getContentType() != null)
+ charset = MimeTypes.getCharsetFromContentType(new ByteArrayBuffer(mp.getContentType()));
+
+ String content=new String(mp.getBytes(),charset==null?StringUtil.__UTF8:charset);
+ getParameter(""); //cause params to be evaluated
+ getParameters().add(mp.getName(), content);
+ }
+ }
+ }
+ return _multiPartInputStream.getParts();
+ }
+
+ /* ------------------------------------------------------------ */
+ public void login(String username, String password) throws ServletException
+ {
+ if (_authentication instanceof Authentication.Deferred)
+ {
+ _authentication=((Authentication.Deferred)_authentication).login(username,password,this);
+ if (_authentication == null)
+ throw new ServletException();
+ }
+ else
+ {
+ throw new ServletException("Authenticated as "+_authentication);
+ }
+ }
+
+ /* ------------------------------------------------------------ */
+ public void logout() throws ServletException
+ {
+ if (_authentication instanceof Authentication.User)
+ ((Authentication.User)_authentication).logout();
+ _authentication=Authentication.UNAUTHENTICATED;
+ }
+
+ /* ------------------------------------------------------------ */
/**
* Merge in a new query string. The query string is merged with the existing parameters and {@link #setParameters(MultiMap)} and
* {@link #setQueryString(String)} are called with the result. The merge is according to the rules of the servlet dispatch forward method.
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 49f6d1551d..b8f9ccb9a7 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
@@ -20,6 +20,7 @@ package org.eclipse.jetty.server;
import java.io.IOException;
import java.io.PrintWriter;
+import java.util.Collection;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Enumeration;
@@ -164,7 +165,7 @@ public class Response implements HttpServletResponse
cookie.getMaxAge(),
comment,
cookie.getSecure(),
- http_only,// || cookie.isHttpOnly(),
+ http_only || cookie.isHttpOnly(),
cookie.getVersion());
}
@@ -537,6 +538,14 @@ public class Response implements HttpServletResponse
}
}
+
+ /* ------------------------------------------------------------ */
+ public Collection<String> getHeaderNames()
+ {
+ final HttpFields fields=_connection.getResponseFields();
+ return fields.getFieldNamesCollection();
+ }
+
/* ------------------------------------------------------------ */
/*
*/
@@ -548,12 +557,13 @@ public class Response implements HttpServletResponse
/* ------------------------------------------------------------ */
/*
*/
- public Enumeration getHeaders(String name)
+ public Collection<String> getHeaders(String name)
{
- Enumeration e = _connection.getResponseFields().getValues(name);
- if (e==null)
- return Collections.enumeration(Collections.EMPTY_LIST);
- return e;
+ final HttpFields fields=_connection.getResponseFields();
+ Collection<String> i = fields.getValuesCollection(name);
+ if (i==null)
+ return Collections.EMPTY_LIST;
+ return i;
}
/* ------------------------------------------------------------ */
@@ -1091,7 +1101,7 @@ public class Response implements HttpServletResponse
HttpFields response_fields=_connection.getResponseFields();
ArrayList<String> cookieValues = new ArrayList<String>(5);
- Enumeration vals = response_fields.getValues(HttpHeaders.SET_COOKIE);
+ Enumeration<String> vals = response_fields.getValues(HttpHeaders.SET_COOKIE);
while (vals.hasMoreElements())
cookieValues.add((String)vals.nextElement());
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 c891d63066..6699c67448 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
@@ -21,6 +21,8 @@ package org.eclipse.jetty.server;
import java.io.IOException;
import java.net.InetSocketAddress;
import java.util.Enumeration;
+
+import javax.servlet.AsyncContext;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
@@ -65,7 +67,7 @@ public class Server extends HandlerWrapper implements Attributes
Server.class.getPackage().getImplementationVersion()!=null)
__version=Server.class.getPackage().getImplementationVersion();
else
- __version=System.getProperty("jetty.version","7.x.y-SNAPSHOT");
+ __version=System.getProperty("jetty.version","8.y.z-SNAPSHOT");
}
private final Container _container=new Container();
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 cdcbed1837..463e57cf3c 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
@@ -19,14 +19,19 @@
package org.eclipse.jetty.server;
+import java.io.IOException;
import java.security.Principal;
+import java.util.Collection;
import java.util.Enumeration;
+import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletRequestWrapper;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
+import javax.servlet.http.Part;
/* ------------------------------------------------------------ */
/** Class to tunnel a ServletRequest via a HttpServletRequest
@@ -163,5 +168,45 @@ public class ServletRequestHttpWrapper extends ServletRequestWrapper implements
return false;
}
+ /**
+ * @see javax.servlet.http.HttpServletRequest#authenticate(javax.servlet.http.HttpServletResponse)
+ */
+ public boolean authenticate(HttpServletResponse response) throws IOException, ServletException
+ {
+ return false;
+ }
+
+ /**
+ * @see javax.servlet.http.HttpServletRequest#getPart(java.lang.String)
+ */
+ public Part getPart(String name) throws IOException, ServletException
+ {
+ return null;
+ }
+
+ /**
+ * @see javax.servlet.http.HttpServletRequest#getParts()
+ */
+ public Collection<Part> getParts() throws IOException, ServletException
+ {
+ return null;
+ }
+
+ /**
+ * @see javax.servlet.http.HttpServletRequest#login(java.lang.String, java.lang.String)
+ */
+ public void login(String username, String password) throws ServletException
+ {
+
+ }
+
+ /**
+ * @see javax.servlet.http.HttpServletRequest#logout()
+ */
+ public void logout() throws ServletException
+ {
+
+ }
+
} \ No newline at end of file
diff --git a/jetty-server/src/main/java/org/eclipse/jetty/server/ServletResponseHttpWrapper.java b/jetty-server/src/main/java/org/eclipse/jetty/server/ServletResponseHttpWrapper.java
index 48514a24f6..4b62f0809d 100644
--- a/jetty-server/src/main/java/org/eclipse/jetty/server/ServletResponseHttpWrapper.java
+++ b/jetty-server/src/main/java/org/eclipse/jetty/server/ServletResponseHttpWrapper.java
@@ -19,6 +19,7 @@
package org.eclipse.jetty.server;
import java.io.IOException;
+import java.util.Collection;
import javax.servlet.ServletResponse;
import javax.servlet.ServletResponseWrapper;
@@ -109,4 +110,36 @@ public class ServletResponseHttpWrapper extends ServletResponseWrapper implement
{
}
+ /**
+ * @see javax.servlet.http.HttpServletResponse#getHeader(java.lang.String)
+ */
+ public String getHeader(String name)
+ {
+ return null;
+ }
+
+ /**
+ * @see javax.servlet.http.HttpServletResponse#getHeaderNames()
+ */
+ public Collection<String> getHeaderNames()
+ {
+ return null;
+ }
+
+ /**
+ * @see javax.servlet.http.HttpServletResponse#getHeaders(java.lang.String)
+ */
+ public Collection<String> getHeaders(String name)
+ {
+ return null;
+ }
+
+ /**
+ * @see javax.servlet.http.HttpServletResponse#getStatus()
+ */
+ public int getStatus()
+ {
+ return 0;
+ }
+
}
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 67e0ae2ac0..43c8947d89 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
@@ -19,7 +19,10 @@
package org.eclipse.jetty.server;
import java.util.EventListener;
+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;
@@ -109,11 +112,6 @@ public interface SessionManager extends LifeCycle
*/
public HttpSession newHttpSession(HttpServletRequest request);
- /* ------------------------------------------------------------ */
- /**
- * @return true if session cookies should be secure
- */
- public boolean getSecureCookies();
/* ------------------------------------------------------------ */
/**
@@ -258,19 +256,6 @@ public interface SessionManager extends LifeCycle
public void complete(HttpSession session);
/**
- * Sets the session cookie name.
- * @param cookieName the session cookie name
- * @see #getSessionCookie()
- */
- public void setSessionCookie(String cookieName);
-
- /**
- * @return the session cookie name, by default "JSESSIONID".
- * @see #setSessionCookie(String)
- */
- public String getSessionCookie();
-
- /**
* Sets the session id URL path parameter name.
*
* @param parameterName the URL path parameter name for session id URL rewriting (null or "none" for no rewriting).
@@ -293,48 +278,22 @@ public interface SessionManager extends LifeCycle
public String getSessionIdPathParameterNamePrefix();
/**
- * Sets the domain to set on the session cookie
- * @param domain the domain to set on the session cookie
- * @see #getSessionDomain()
- */
- public void setSessionDomain(String domain);
-
- /**
- * @return the domain to set on the session cookie
- * @see #setSessionDomain(String)
+ * @return whether the session management is handled via cookies.
*/
- public String getSessionDomain();
-
+ public boolean isUsingCookies();
+
/**
- * Sets the path to set on the session cookie
- * @param path the path to set on the session cookie
- * @see #getSessionPath()
+ * @return whether the session management is handled via URLs.
*/
- public void setSessionPath(String path);
+ public boolean isUsingURLs();
- /**
- * @return the path to set on the session cookie
- * @see #setSessionPath(String)
- */
- public String getSessionPath();
+ public Set<SessionTrackingMode> getDefaultSessionTrackingModes();
- /**
- * Sets the max age to set on the session cookie, in seconds
- * @param maxCookieAge the max age to set on the session cookie, in seconds
- * @see #getMaxCookieAge()
- */
- public void setMaxCookieAge(int maxCookieAge);
+ public Set<SessionTrackingMode> getEffectiveSessionTrackingModes();
- /**
- * @return the max age to set on the session cookie, in seconds
- * @see #setMaxCookieAge(int)
- */
- public int getMaxCookieAge();
+ public void setSessionTrackingModes(Set<SessionTrackingMode> sessionTrackingModes);
- /**
- * @return whether the session management is handled via cookies.
- */
- public boolean isUsingCookies();
+ public SessionCookieConfig getSessionCookieConfig();
/**
* @return True if absolute URLs are check for remoteness before being session encoded.
@@ -345,5 +304,4 @@ public interface SessionManager extends LifeCycle
* @param remote True if absolute URLs are check for remoteness before being session encoded.
*/
public void setCheckingRemoteSessionIdEncoding(boolean remote);
-
}
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 60b1f24ff1..ec4f6af5c1 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
@@ -24,6 +24,7 @@ import java.io.InputStream;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLClassLoader;
+import java.security.AccessController;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
@@ -35,6 +36,9 @@ import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.Set;
+import java.util.EnumSet;
+
+import javax.servlet.DispatcherType;
import javax.servlet.RequestDispatcher;
import javax.servlet.Servlet;
import javax.servlet.ServletContext;
@@ -43,9 +47,16 @@ import javax.servlet.ServletContextAttributeListener;
import javax.servlet.ServletContextEvent;
import javax.servlet.ServletContextListener;
import javax.servlet.ServletException;
+import javax.servlet.ServletRegistration;
import javax.servlet.ServletRequestAttributeListener;
import javax.servlet.ServletRequestEvent;
import javax.servlet.ServletRequestListener;
+import javax.servlet.SessionCookieConfig;
+import javax.servlet.SessionTrackingMode;
+import javax.servlet.Filter;
+import javax.servlet.FilterRegistration;
+import javax.servlet.FilterRegistration.Dynamic;
+import javax.servlet.descriptor.JspConfigDescriptor;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
@@ -54,7 +65,6 @@ import org.eclipse.jetty.http.MimeTypes;
import org.eclipse.jetty.io.Buffer;
import org.eclipse.jetty.server.AbstractHttpConnection;
import org.eclipse.jetty.server.Dispatcher;
-import org.eclipse.jetty.server.DispatcherType;
import org.eclipse.jetty.server.Handler;
import org.eclipse.jetty.server.HandlerContainer;
import org.eclipse.jetty.server.Request;
@@ -579,6 +589,19 @@ public class ContextHandler extends ScopedHandler implements Attributes, Server.
{
setEventListeners((EventListener[])LazyList.addToArray(getEventListeners(),listener,EventListener.class));
}
+
+
+ /**
+ * Apply any necessary restrictions on a programmatically added
+ * listener.
+ *
+ * Superclasses should implement.
+ *
+ * @param listener
+ */
+ public void restrictEventListener (EventListener listener)
+ {
+ }
/* ------------------------------------------------------------ */
/**
@@ -737,14 +760,25 @@ public class ContextHandler extends ScopedHandler implements Attributes, Server.
ServletContextEvent event = new ServletContextEvent(_scontext);
for (int i = 0; i < LazyList.size(_contextListeners); i++)
{
- ((ServletContextListener)LazyList.get(_contextListeners,i)).contextInitialized(event);
+ callContextInitialized(((ServletContextListener)LazyList.get(_contextListeners, i)), event);
}
}
+ }
+ /* ------------------------------------------------------------ */
+ public void callContextInitialized (ServletContextListener l, ServletContextEvent e)
+ {
+ l.contextInitialized(e);
LOG.info("started {}",this);
}
/* ------------------------------------------------------------ */
+ public void callContextDestroyed (ServletContextListener l, ServletContextEvent e)
+ {
+ l.contextDestroyed(e);
+ }
+
+ /* ------------------------------------------------------------ */
/*
* @see org.eclipse.thread.AbstractLifeCycle#doStop()
*/
@@ -1488,6 +1522,7 @@ public class ContextHandler extends ScopedHandler implements Attributes, Server.
_localeEncodingMap.put(locale,encoding);
}
+ /* ------------------------------------------------------------ */
public String getLocaleEncoding(String locale)
{
if (_localeEncodingMap == null)
@@ -1631,6 +1666,10 @@ public class ContextHandler extends ScopedHandler implements Attributes, Server.
*/
public class Context implements ServletContext
{
+ protected int _majorVersion = 3;
+ protected int _minorVersion = 0;
+ protected boolean _enabled = true; //whether or not the dynamic API is enabled for callers
+
/* ------------------------------------------------------------ */
protected Context()
{
@@ -1647,6 +1686,7 @@ public class ContextHandler extends ScopedHandler implements Attributes, Server.
/*
* @see javax.servlet.ServletContext#getContext(java.lang.String)
*/
+ @Override
public ServletContext getContext(String uripath)
{
List<ContextHandler> contexts = new ArrayList<ContextHandler>();
@@ -1732,15 +1772,18 @@ public class ContextHandler extends ScopedHandler implements Attributes, Server.
/*
* @see javax.servlet.ServletContext#getMajorVersion()
*/
+ @Override
public int getMajorVersion()
{
- return 2;
+ return 3;
}
+
/* ------------------------------------------------------------ */
/*
* @see javax.servlet.ServletContext#getMimeType(java.lang.String)
*/
+ @Override
public String getMimeType(String file)
{
if (_mimeTypes == null)
@@ -1755,15 +1798,17 @@ public class ContextHandler extends ScopedHandler implements Attributes, Server.
/*
* @see javax.servlet.ServletContext#getMinorVersion()
*/
+ @Override
public int getMinorVersion()
{
- return 5;
+ return 0;
}
/* ------------------------------------------------------------ */
/*
* @see javax.servlet.ServletContext#getNamedDispatcher(java.lang.String)
*/
+ @Override
public RequestDispatcher getNamedDispatcher(String name)
{
return null;
@@ -1773,6 +1818,7 @@ public class ContextHandler extends ScopedHandler implements Attributes, Server.
/*
* @see javax.servlet.ServletContext#getRequestDispatcher(java.lang.String)
*/
+ @Override
public RequestDispatcher getRequestDispatcher(String uriInContext)
{
if (uriInContext == null)
@@ -1809,6 +1855,7 @@ public class ContextHandler extends ScopedHandler implements Attributes, Server.
/*
* @see javax.servlet.ServletContext#getRealPath(java.lang.String)
*/
+ @Override
public String getRealPath(String path)
{
if (path == null)
@@ -1837,6 +1884,7 @@ public class ContextHandler extends ScopedHandler implements Attributes, Server.
}
/* ------------------------------------------------------------ */
+ @Override
public URL getResource(String path) throws MalformedURLException
{
Resource resource = ContextHandler.this.getResource(path);
@@ -1849,6 +1897,7 @@ public class ContextHandler extends ScopedHandler implements Attributes, Server.
/*
* @see javax.servlet.ServletContext#getResourceAsStream(java.lang.String)
*/
+ @Override
public InputStream getResourceAsStream(String path)
{
try
@@ -1870,6 +1919,7 @@ public class ContextHandler extends ScopedHandler implements Attributes, Server.
/*
* @see javax.servlet.ServletContext#getResourcePaths(java.lang.String)
*/
+ @Override
public Set getResourcePaths(String path)
{
return ContextHandler.this.getResourcePaths(path);
@@ -1879,6 +1929,7 @@ public class ContextHandler extends ScopedHandler implements Attributes, Server.
/*
* @see javax.servlet.ServletContext#getServerInfo()
*/
+ @Override
public String getServerInfo()
{
return "jetty/" + Server.getVersion();
@@ -1888,6 +1939,8 @@ public class ContextHandler extends ScopedHandler implements Attributes, Server.
/*
* @see javax.servlet.ServletContext#getServlet(java.lang.String)
*/
+ @Override
+ @Deprecated
public Servlet getServlet(String name) throws ServletException
{
return null;
@@ -1898,6 +1951,8 @@ public class ContextHandler extends ScopedHandler implements Attributes, Server.
* @see javax.servlet.ServletContext#getServletNames()
*/
@SuppressWarnings("unchecked")
+ @Override
+ @Deprecated
public Enumeration getServletNames()
{
return Collections.enumeration(Collections.EMPTY_LIST);
@@ -1908,6 +1963,8 @@ public class ContextHandler extends ScopedHandler implements Attributes, Server.
* @see javax.servlet.ServletContext#getServlets()
*/
@SuppressWarnings("unchecked")
+ @Override
+ @Deprecated
public Enumeration getServlets()
{
return Collections.enumeration(Collections.EMPTY_LIST);
@@ -1917,6 +1974,7 @@ public class ContextHandler extends ScopedHandler implements Attributes, Server.
/*
* @see javax.servlet.ServletContext#log(java.lang.Exception, java.lang.String)
*/
+ @Override
public void log(Exception exception, String msg)
{
_logger.warn(msg,exception);
@@ -1926,6 +1984,7 @@ public class ContextHandler extends ScopedHandler implements Attributes, Server.
/*
* @see javax.servlet.ServletContext#log(java.lang.String)
*/
+ @Override
public void log(String msg)
{
_logger.info(msg);
@@ -1935,6 +1994,7 @@ public class ContextHandler extends ScopedHandler implements Attributes, Server.
/*
* @see javax.servlet.ServletContext#log(java.lang.String, java.lang.Throwable)
*/
+ @Override
public void log(String message, Throwable throwable)
{
_logger.warn(message,throwable);
@@ -1944,6 +2004,7 @@ public class ContextHandler extends ScopedHandler implements Attributes, Server.
/*
* @see javax.servlet.ServletContext#getInitParameter(java.lang.String)
*/
+ @Override
public String getInitParameter(String name)
{
return ContextHandler.this.getInitParameter(name);
@@ -1954,6 +2015,7 @@ public class ContextHandler extends ScopedHandler implements Attributes, Server.
* @see javax.servlet.ServletContext#getInitParameterNames()
*/
@SuppressWarnings("unchecked")
+ @Override
public Enumeration getInitParameterNames()
{
return ContextHandler.this.getInitParameterNames();
@@ -1963,6 +2025,7 @@ public class ContextHandler extends ScopedHandler implements Attributes, Server.
/*
* @see javax.servlet.ServletContext#getAttribute(java.lang.String)
*/
+ @Override
public synchronized Object getAttribute(String name)
{
Object o = ContextHandler.this.getAttribute(name);
@@ -1976,6 +2039,7 @@ public class ContextHandler extends ScopedHandler implements Attributes, Server.
* @see javax.servlet.ServletContext#getAttributeNames()
*/
@SuppressWarnings("unchecked")
+ @Override
public synchronized Enumeration getAttributeNames()
{
HashSet<String> set = new HashSet<String>();
@@ -1996,6 +2060,7 @@ public class ContextHandler extends ScopedHandler implements Attributes, Server.
/*
* @see javax.servlet.ServletContext#setAttribute(java.lang.String, java.lang.Object)
*/
+ @Override
public synchronized void setAttribute(String name, Object value)
{
checkManagedAttribute(name,value);
@@ -2028,6 +2093,7 @@ public class ContextHandler extends ScopedHandler implements Attributes, Server.
/*
* @see javax.servlet.ServletContext#removeAttribute(java.lang.String)
*/
+ @Override
public synchronized void removeAttribute(String name)
{
checkManagedAttribute(name,null);
@@ -2057,6 +2123,7 @@ public class ContextHandler extends ScopedHandler implements Attributes, Server.
/*
* @see javax.servlet.ServletContext#getServletContextName()
*/
+ @Override
public String getServletContextName()
{
String name = ContextHandler.this.getDisplayName();
@@ -2066,6 +2133,7 @@ public class ContextHandler extends ScopedHandler implements Attributes, Server.
}
/* ------------------------------------------------------------ */
+ @Override
public String getContextPath()
{
if ((_contextPath != null) && _contextPath.equals(URIUtil.SLASH))
@@ -2082,6 +2150,7 @@ public class ContextHandler extends ScopedHandler implements Attributes, Server.
}
/* ------------------------------------------------------------ */
+ @Override
public boolean setInitParameter(String name, String value)
{
if (ContextHandler.this.getInitParameter(name) != null)
@@ -2090,6 +2159,242 @@ public class ContextHandler extends ScopedHandler implements Attributes, Server.
return true;
}
+ /* ------------------------------------------------------------ */
+ final private static String __unimplmented="Unimplemented - use org.eclipse.jetty.servlet.ServletContextHandler";
+
+ @Override
+ public Dynamic addFilter(String filterName, Class<? extends Filter> filterClass)
+ {
+ LOG.warn(__unimplmented);
+ return null;
+ }
+
+ @Override
+ public Dynamic addFilter(String filterName, Filter filter)
+ {
+ LOG.warn(__unimplmented);
+ return null;
+ }
+
+ @Override
+ public Dynamic addFilter(String filterName, String className)
+ {
+ LOG.warn(__unimplmented);
+ return null;
+ }
+
+ @Override
+ public javax.servlet.ServletRegistration.Dynamic addServlet(String servletName, Class<? extends Servlet> servletClass)
+ {
+ LOG.warn(__unimplmented);
+ return null;
+ }
+
+ @Override
+ public javax.servlet.ServletRegistration.Dynamic addServlet(String servletName, Servlet servlet)
+ {
+ LOG.warn(__unimplmented);
+ return null;
+ }
+
+ @Override
+ public javax.servlet.ServletRegistration.Dynamic addServlet(String servletName, String className)
+ {
+ LOG.warn(__unimplmented);
+ return null;
+ }
+
+ @Override
+ public <T extends Filter> T createFilter(Class<T> c) throws ServletException
+ {
+ LOG.warn(__unimplmented);
+ return null;
+ }
+
+ @Override
+ public <T extends Servlet> T createServlet(Class<T> c) throws ServletException
+ {
+ LOG.warn(__unimplmented);
+ return null;
+ }
+
+ @Override
+ public Set<SessionTrackingMode> getDefaultSessionTrackingModes()
+ {
+ LOG.warn(__unimplmented);
+ return null;
+ }
+
+ @Override
+ public Set<SessionTrackingMode> getEffectiveSessionTrackingModes()
+ {
+ LOG.warn(__unimplmented);
+ return null;
+ }
+
+ @Override
+ public FilterRegistration getFilterRegistration(String filterName)
+ {
+ LOG.warn(__unimplmented);
+ return null;
+ }
+
+ @Override
+ public Map<String, ? extends FilterRegistration> getFilterRegistrations()
+ {
+ LOG.warn(__unimplmented);
+ return null;
+ }
+
+ @Override
+ public ServletRegistration getServletRegistration(String servletName)
+ {
+ LOG.warn(__unimplmented);
+ return null;
+ }
+
+ @Override
+ public Map<String, ? extends ServletRegistration> getServletRegistrations()
+ {
+ LOG.warn(__unimplmented);
+ return null;
+ }
+
+ @Override
+ public SessionCookieConfig getSessionCookieConfig()
+ {
+ LOG.warn(__unimplmented);
+ return null;
+ }
+
+ @Override
+ public void setSessionTrackingModes(Set<SessionTrackingMode> sessionTrackingModes)
+ {
+ LOG.warn(__unimplmented);
+ }
+
+ @Override
+ public void addListener(String className)
+ {
+ if (!_enabled)
+ throw new UnsupportedOperationException();
+
+ try
+ {
+ Class<? extends EventListener> clazz = _classLoader==null?Loader.loadClass(ContextHandler.class,className):_classLoader.loadClass(className);
+ addListener(clazz);
+ }
+ catch (ClassNotFoundException e)
+ {
+ throw new IllegalArgumentException(e);
+ }
+ }
+
+ @Override
+ public <T extends EventListener> void addListener(T t)
+ {
+ if (!_enabled)
+ throw new UnsupportedOperationException();
+ ContextHandler.this.addEventListener(t);
+ }
+
+ @Override
+ public void addListener(Class<? extends EventListener> listenerClass)
+ {
+ if (!_enabled)
+ throw new UnsupportedOperationException();
+
+ try
+ {
+ EventListener e = createListener(listenerClass);
+ ContextHandler.this.addEventListener(e);
+ ContextHandler.this.restrictEventListener(e);
+ }
+ catch (ServletException e)
+ {
+ throw new IllegalArgumentException(e);
+ }
+ }
+
+ @Override
+ public <T extends EventListener> T createListener(Class<T> clazz) throws ServletException
+ {
+ try
+ {
+ return clazz.newInstance();
+ }
+ catch (InstantiationException e)
+ {
+ throw new ServletException(e);
+ }
+ catch (IllegalAccessException e)
+ {
+ throw new ServletException(e);
+ }
+ }
+
+ @Override
+ public ClassLoader getClassLoader()
+ {
+ AccessController.checkPermission(new RuntimePermission("getClassLoader"));
+ return _classLoader;
+ }
+
+ @Override
+ public int getEffectiveMajorVersion()
+ {
+ return _majorVersion;
+ }
+
+ @Override
+ public int getEffectiveMinorVersion()
+ {
+ return _minorVersion;
+ }
+
+ public void setEffectiveMajorVersion (int v)
+ {
+ _majorVersion = v;
+ }
+
+ public void setEffectiveMinorVersion (int v)
+ {
+ _minorVersion = v;
+ }
+
+ @Override
+ public JspConfigDescriptor getJspConfigDescriptor()
+ {
+ LOG.warn(__unimplmented);
+ return null;
+ }
+
+ public void setJspConfigDescriptor(JspConfigDescriptor d)
+ {
+
+ }
+
+ @Override
+ public void declareRoles(String... roleNames)
+ {
+ if (!isStarting())
+ throw new IllegalStateException ();
+ if (!_enabled)
+ throw new UnsupportedOperationException();
+
+ // TODO Auto-generated method stub
+
+ }
+
+ public void setEnabled(boolean enabled)
+ {
+ _enabled = enabled;
+ }
+
+ public boolean isEnabled()
+ {
+ return _enabled;
+ }
}
private static class CLDump implements Dumpable
diff --git a/jetty-server/src/main/java/org/eclipse/jetty/server/handler/IPAccessHandler.java b/jetty-server/src/main/java/org/eclipse/jetty/server/handler/IPAccessHandler.java
index c6e9e80ac1..b4642ece91 100644
--- a/jetty-server/src/main/java/org/eclipse/jetty/server/handler/IPAccessHandler.java
+++ b/jetty-server/src/main/java/org/eclipse/jetty/server/handler/IPAccessHandler.java
@@ -242,7 +242,7 @@ public class IPAccessHandler extends HandlerWrapper
pathMap = new PathMap(true);
patternMap.put(addr,pathMap);
}
- if (path != null)
+ if (path != null && !"".equals(path))
pathMap.put(path,path);
if (deprecated)
diff --git a/jetty-server/src/main/java/org/eclipse/jetty/server/handler/RequestLogHandler.java b/jetty-server/src/main/java/org/eclipse/jetty/server/handler/RequestLogHandler.java
index bef865cf9d..b5bc248f3a 100644
--- a/jetty-server/src/main/java/org/eclipse/jetty/server/handler/RequestLogHandler.java
+++ b/jetty-server/src/main/java/org/eclipse/jetty/server/handler/RequestLogHandler.java
@@ -20,12 +20,12 @@ package org.eclipse.jetty.server.handler;
import java.io.IOException;
+import javax.servlet.DispatcherType;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.eclipse.jetty.server.AsyncContinuation;
-import org.eclipse.jetty.server.DispatcherType;
import org.eclipse.jetty.server.Request;
import org.eclipse.jetty.server.RequestLog;
import org.eclipse.jetty.server.Response;
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 2211d394c4..9b72c1dccb 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
@@ -20,15 +20,20 @@ package org.eclipse.jetty.server.session;
import static java.lang.Math.round;
+import java.util.Arrays;
import java.util.Collections;
import java.util.Enumeration;
import java.util.EventListener;
+import java.util.HashSet;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
+import java.util.Set;
import java.util.concurrent.CopyOnWriteArrayList;
import javax.servlet.ServletRequest;
+import javax.servlet.SessionCookieConfig;
+import javax.servlet.SessionTrackingMode;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;
import javax.servlet.http.HttpSessionAttributeListener;
@@ -63,6 +68,12 @@ import org.eclipse.jetty.util.statistic.SampleStatistic;
public abstract class AbstractSessionManager extends AbstractLifeCycle implements SessionManager
{
final static Logger __log = SessionHandler.LOG;
+
+ public Set<SessionTrackingMode> __defaultSessionTrackingModes =
+ Collections.unmodifiableSet(
+ new HashSet<SessionTrackingMode>(
+ Arrays.asList(new SessionTrackingMode[]{SessionTrackingMode.COOKIE,SessionTrackingMode.URL})));
+
public final static String SESSION_KNOWN_ONLY_TO_AUTHENTICATED="org.eclipse.jetty.security.sessionKnownOnlytoAuthenticated";
/* ------------------------------------------------------------ */
@@ -92,6 +103,8 @@ public abstract class AbstractSessionManager extends AbstractLifeCycle implement
protected boolean _httpOnly=false;
protected SessionIdManager _sessionIdManager;
protected boolean _secureCookies=false;
+ protected boolean _secureRequestOnly=true;
+
protected final List<HttpSessionAttributeListener> _sessionAttributeListeners = new CopyOnWriteArrayList<HttpSessionAttributeListener>();
protected final List<HttpSessionListener> _sessionListeners= new CopyOnWriteArrayList<HttpSessionListener>();
@@ -106,7 +119,12 @@ public abstract class AbstractSessionManager extends AbstractLifeCycle implement
protected int _refreshCookieAge;
protected boolean _nodeIdInSessionId;
protected boolean _checkingRemoteSessionIdEncoding;
+ protected String _sessionComment;
+ public Set<SessionTrackingMode> _sessionTrackingModes;
+
+ private boolean _usingURLs;
+
protected final CounterStatistic _sessionsStats = new CounterStatistic();
protected final SampleStatistic _sessionTimeStats = new SampleStatistic();
@@ -135,6 +153,7 @@ public abstract class AbstractSessionManager extends AbstractLifeCycle implement
/* ------------------------------------------------------------ */
public AbstractSessionManager()
{
+ setSessionTrackingModes(__defaultSessionTrackingModes);
}
/* ------------------------------------------------------------ */
@@ -149,6 +168,16 @@ public abstract class AbstractSessionManager extends AbstractLifeCycle implement
return _context.getContextHandler();
}
+ public String getSessionPath()
+ {
+ return _sessionPath;
+ }
+
+ public int getMaxCookieAge()
+ {
+ return _maxCookieAge;
+ }
+
/* ------------------------------------------------------------ */
public HttpCookie access(HttpSession session,boolean secure)
{
@@ -156,14 +185,14 @@ public abstract class AbstractSessionManager extends AbstractLifeCycle implement
AbstractSession s = ((SessionIf)session).getSession();
- if (s.access(now))
- {
+ if (s.access(now))
+ {
// Do we need to refresh the cookie?
if (isUsingCookies() &&
- (s.isIdChanged() ||
- (getMaxCookieAge()>0 && getRefreshCookieAge()>0 && ((now-s.getCookieSetTime())/1000>getRefreshCookieAge()))
- )
- )
+ (s.isIdChanged() ||
+ (getSessionCookieConfig().getMaxAge()>0 && getRefreshCookieAge()>0 && ((now-s.getCookieSetTime())/1000>getRefreshCookieAge()))
+ )
+ )
{
HttpCookie cookie=getSessionCookie(session,_context==null?"/":(_context.getContextPath()),secure);
s.cookieSet();
@@ -305,16 +334,12 @@ public abstract class AbstractSessionManager extends AbstractLifeCycle implement
return _sessionIdManager;
}
- /* ------------------------------------------------------------ */
- public int getMaxCookieAge()
- {
- return _maxCookieAge;
- }
/* ------------------------------------------------------------ */
/**
* @return seconds
*/
+ @Override
public int getMaxInactiveInterval()
{
return _dftMaxIdleSecs;
@@ -377,13 +402,38 @@ public abstract class AbstractSessionManager extends AbstractLifeCycle implement
/* ------------------------------------------------------------ */
/**
- * @return Returns the secureCookies.
+ * @return same as SessionCookieConfig.getSecure(). If true, session
+ * cookies are ALWAYS marked as secure. If false, a session cookie is
+ * ONLY marked as secure if _secureRequestOnly == true and it is a HTTPS request.
*/
public boolean getSecureCookies()
{
return _secureCookies;
}
+
+ /* ------------------------------------------------------------ */
+ /**
+ * @return true if session cookie is to be marked as secure only on HTTPS requests
+ */
+ public boolean isSecureRequestOnly()
+ {
+ return _secureRequestOnly;
+ }
+
+
+ /* ------------------------------------------------------------ */
+ /**
+ * @return if true, session cookie will be marked as secure only iff
+ * HTTPS request. Can be overridden by setting SessionCookieConfig.setSecure(true),
+ * in which case the session cookie will be marked as secure on both HTTPS and HTTP.
+ */
+ public void setSecureRequestOnly(boolean secureRequestOnly)
+ {
+ _secureRequestOnly = secureRequestOnly;
+ }
+
+
/* ------------------------------------------------------------ */
public String getSessionCookie()
{
@@ -391,6 +441,31 @@ public abstract class AbstractSessionManager extends AbstractLifeCycle implement
}
/* ------------------------------------------------------------ */
+ /**
+ * A sessioncookie is marked as secure IFF any of the following conditions are true:
+ * <ol>
+ * <li>SessionCookieConfig.setSecure == true</li>
+ * <li>SessionCookieConfig.setSecure == false && _secureRequestOnly==true && request is HTTPS</li>
+ * </ol>
+ * According to SessionCookieConfig javadoc, case 1 can be used when:
+ * "... even though the request that initiated the session came over HTTP,
+ * is to support a topology where the web container is front-ended by an
+ * SSL offloading load balancer. In this case, the traffic between the client
+ * and the load balancer will be over HTTPS, whereas the traffic between the
+ * load balancer and the web container will be over HTTP."
+ *
+ * For case 2, you can use _secureRequestOnly to determine if you want the
+ * Servlet Spec 3.0 default behaviour when SessionCookieConfig.setSecure==false,
+ * which is:
+ * "they shall be marked as secure only if the request that initiated the
+ * corresponding session was also secure"
+ *
+ * The default for _secureRequestOnly is true, which gives the above behaviour. If
+ * you set it to false, then a session cookie is NEVER marked as secure, even if
+ * the initiating request was secure.
+ *
+ * @see org.eclipse.jetty.server.SessionManager#getSessionCookie(javax.servlet.http.HttpSession, java.lang.String, boolean)
+ */
public HttpCookie getSessionCookie(HttpSession session, String contextPath, boolean requestIsSecure)
{
if (isUsingCookies())
@@ -398,15 +473,32 @@ public abstract class AbstractSessionManager extends AbstractLifeCycle implement
String sessionPath = (_sessionPath==null) ? contextPath : _sessionPath;
sessionPath = (sessionPath==null||sessionPath.length()==0) ? "/" : sessionPath;
String id = getNodeId(session);
- HttpCookie cookie=new HttpCookie(
- _sessionCookie,
- id,
- _sessionDomain,
- sessionPath,
- getMaxCookieAge(),
- getHttpOnly(),
- requestIsSecure&&getSecureCookies());
-
+ HttpCookie cookie = null;
+ if (_sessionComment == null)
+ {
+ cookie = new HttpCookie(
+ _sessionCookie,
+ id,
+ _sessionDomain,
+ sessionPath,
+ _cookieConfig.getMaxAge(),
+ _cookieConfig.isHttpOnly(),
+ _cookieConfig.isSecure() || (isSecureRequestOnly() && requestIsSecure));
+ }
+ else
+ {
+ cookie = new HttpCookie(
+ _sessionCookie,
+ id,
+ _sessionDomain,
+ sessionPath,
+ _cookieConfig.getMaxAge(),
+ _cookieConfig.isHttpOnly(),
+ _cookieConfig.isSecure() || (isSecureRequestOnly() && requestIsSecure),
+ _sessionComment,
+ 1);
+ }
+
return cookie;
}
return null;
@@ -436,11 +528,7 @@ public abstract class AbstractSessionManager extends AbstractLifeCycle implement
throw new UnsupportedOperationException();
}
- /* ------------------------------------------------------------ */
- public String getSessionPath()
- {
- return _sessionPath;
- }
+
/* ------------------------------------------------------------ */
public int getSessions()
@@ -560,15 +648,7 @@ public abstract class AbstractSessionManager extends AbstractLifeCycle implement
_sessionIdManager=metaManager;
}
- /* ------------------------------------------------------------ */
- public void setMaxCookieAge(int maxCookieAgeInSeconds)
- {
- _maxCookieAge=maxCookieAgeInSeconds;
- if (_maxCookieAge>0 && _refreshCookieAge==0)
- _refreshCookieAge=_maxCookieAge/3;
-
- }
/* ------------------------------------------------------------ */
/**
@@ -579,15 +659,6 @@ public abstract class AbstractSessionManager extends AbstractLifeCycle implement
_dftMaxIdleSecs=seconds;
}
- /* ------------------------------------------------------------ */
- /**
- * @deprecated use {@link #setSessionIdManager(SessionIdManager)}
- */
- @Deprecated
- public void setMetaManager(SessionIdManager metaManager)
- {
- setSessionIdManager(metaManager);
- }
/* ------------------------------------------------------------ */
public void setRefreshCookieAge(int ageInSeconds)
@@ -596,34 +667,13 @@ public abstract class AbstractSessionManager extends AbstractLifeCycle implement
}
- /* ------------------------------------------------------------ */
- /**
- * Set if the session manager should use SecureCookies.
- * A secure cookie will only be sent by a browser on a secure (https) connection to
- * avoid the concern of cookies being intercepted on non secure channels.
- * For the cookie to be issued as secure, the {@link ServletRequest#isSecure()} method must return true.
- * If SSL offload is used, then the {@link AbstractConnector#customize(org.eclipse.jetty.io.EndPoint, Request)}
- * method can be used to force the request to be https, or the {@link AbstractConnector#setForwarded(boolean)}
- * can be set to true, so that the X-Forwarded-Proto header is respected.
- * <p>
- * If secure session cookies are used, then a session may not be shared between http and https requests.
- *
- * @param secureCookies If true, use secure cookies.
- */
- public void setSecureCookies(boolean secureCookies)
- {
- _secureCookies=secureCookies;
- }
public void setSessionCookie(String cookieName)
{
_sessionCookie=cookieName;
}
- public void setSessionDomain(String domain)
- {
- _sessionDomain=domain;
- }
+
/* ------------------------------------------------------------ */
/**
@@ -635,15 +685,7 @@ public abstract class AbstractSessionManager extends AbstractLifeCycle implement
_sessionHandler=sessionHandler;
}
- /* ------------------------------------------------------------ */
- /**
- * @see org.eclipse.jetty.server.SessionManager#setSessionPath(java.lang.String)
- */
- public void setSessionPath(String path)
- {
- _sessionPath=path;
- }
-
+
/* ------------------------------------------------------------ */
public void setSessionIdPathParameterName(String param)
{
@@ -781,6 +823,132 @@ public abstract class AbstractSessionManager extends AbstractLifeCycle implement
}
/* ------------------------------------------------------------ */
+ public Set<SessionTrackingMode> getDefaultSessionTrackingModes()
+ {
+ return __defaultSessionTrackingModes;
+ }
+
+ /* ------------------------------------------------------------ */
+ public Set<SessionTrackingMode> getEffectiveSessionTrackingModes()
+ {
+ return Collections.unmodifiableSet(_sessionTrackingModes);
+ }
+
+ /* ------------------------------------------------------------ */
+ @Override
+ public void setSessionTrackingModes(Set<SessionTrackingMode> sessionTrackingModes)
+ {
+ _sessionTrackingModes=new HashSet<SessionTrackingMode>(sessionTrackingModes);
+ _usingCookies=_sessionTrackingModes.contains(SessionTrackingMode.COOKIE);
+ _usingURLs=_sessionTrackingModes.contains(SessionTrackingMode.URL);
+ }
+
+ /* ------------------------------------------------------------ */
+ @Override
+ public boolean isUsingURLs()
+ {
+ return _usingURLs;
+ }
+
+
+ /* ------------------------------------------------------------ */
+ public SessionCookieConfig getSessionCookieConfig()
+ {
+ return _cookieConfig;
+ }
+
+ /* ------------------------------------------------------------ */
+ private SessionCookieConfig _cookieConfig =
+ new SessionCookieConfig()
+ {
+ @Override
+ public String getComment()
+ {
+ return _sessionComment;
+ }
+
+ @Override
+ public String getDomain()
+ {
+ return _sessionDomain;
+ }
+
+ @Override
+ public int getMaxAge()
+ {
+ return _maxCookieAge;
+ }
+
+ @Override
+ public String getName()
+ {
+ return _sessionCookie;
+ }
+
+ @Override
+ public String getPath()
+ {
+ return _sessionPath;
+ }
+
+ @Override
+ public boolean isHttpOnly()
+ {
+ return _httpOnly;
+ }
+
+ @Override
+ public boolean isSecure()
+ {
+ return _secureCookies;
+ }
+
+ @Override
+ public void setComment(String comment)
+ {
+ _sessionComment = comment;
+ }
+
+ @Override
+ public void setDomain(String domain)
+ {
+ _sessionDomain=domain;
+ }
+
+ @Override
+ public void setHttpOnly(boolean httpOnly)
+ {
+ _httpOnly=httpOnly;
+ }
+
+ @Override
+ public void setMaxAge(int maxAge)
+ {
+ _maxCookieAge=maxAge;
+ }
+
+ @Override
+ public void setName(String name)
+ {
+ _sessionCookie=name;
+ }
+
+ @Override
+ public void setPath(String path)
+ {
+ _sessionPath=path;
+ }
+
+ @Override
+ public void setSecure(boolean secure)
+ {
+ _secureCookies=secure;
+ }
+
+ };
+
+
+ /* ------------------------------------------------------------ */
/**
* @return total amount of time all sessions remained valid
*/
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 7f888a99d7..19ee760a51 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
@@ -27,6 +27,7 @@ import java.io.ObjectInputStream;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.Map;
+import java.util.Set;
import java.util.Timer;
import java.util.TimerTask;
import java.util.concurrent.ConcurrentHashMap;
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 e63704793a..d37b4eba0c 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
@@ -34,9 +34,11 @@ import java.util.HashMap;
import java.util.List;
import java.util.ListIterator;
import java.util.Map;
+import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.atomic.AtomicReference;
+import javax.servlet.SessionTrackingMode;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSessionEvent;
import javax.servlet.http.HttpSessionListener;
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 818dc10bf4..1034efed97 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
@@ -19,15 +19,17 @@
package org.eclipse.jetty.server.session;
import java.io.IOException;
+import java.util.EnumSet;
import java.util.EventListener;
+import javax.servlet.DispatcherType;
import javax.servlet.ServletException;
+import javax.servlet.SessionTrackingMode;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import org.eclipse.jetty.http.HttpCookie;
-import org.eclipse.jetty.server.DispatcherType;
import org.eclipse.jetty.server.Request;
import org.eclipse.jetty.server.Server;
import org.eclipse.jetty.server.SessionManager;
@@ -43,6 +45,8 @@ 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);
+
/* -------------------------------------------------------------- */
private SessionManager _sessionManager;
@@ -260,9 +264,10 @@ public class SessionHandler extends ScopedHandler
Cookie[] cookies = request.getCookies();
if (cookies != null && cookies.length > 0)
{
+ final String sessionCookie=sessionManager.getSessionCookieConfig().getName();
for (int i = 0; i < cookies.length; i++)
{
- if (sessionManager.getSessionCookie().equalsIgnoreCase(cookies[i].getName()))
+ if (sessionCookie.equalsIgnoreCase(cookies[i].getName()))
{
requested_session_id = cookies[i].getValue();
requested_session_id_from_cookie = true;
diff --git a/jetty-server/src/test/java/org/eclipse/jetty/server/AsyncStressTest.java b/jetty-server/src/test/java/org/eclipse/jetty/server/AsyncStressTest.java
index 7eaa152400..ea04fc2f44 100644
--- a/jetty-server/src/test/java/org/eclipse/jetty/server/AsyncStressTest.java
+++ b/jetty-server/src/test/java/org/eclipse/jetty/server/AsyncStressTest.java
@@ -27,7 +27,10 @@ import java.net.Socket;
import java.util.Random;
import java.util.Timer;
import java.util.TimerTask;
-
+import javax.servlet.AsyncContext;
+import javax.servlet.AsyncEvent;
+import javax.servlet.AsyncListener;
+import javax.servlet.DispatcherType;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
@@ -226,10 +229,9 @@ public class AsyncStressTest
if (suspend_for>=0)
{
final AsyncContext asyncContext = baseRequest.startAsync();
- asyncContext.addContinuationListener(__asyncListener);
+ asyncContext.addListener(__asyncListener);
if (suspend_for>0)
asyncContext.setTimeout(suspend_for);
-
if (complete_after>0)
{
TimerTask complete = new TimerTask()
@@ -325,18 +327,31 @@ public class AsyncStressTest
}
}
}
+
+
+ private static AsyncListener __asyncListener = new AsyncListener()
+ {
+ @Override
+ public void onComplete(AsyncEvent event) throws IOException
+ {
+ }
+ @Override
+ public void onTimeout(AsyncEvent event) throws IOException
+ {
+ event.getSuppliedRequest().setAttribute("TIMEOUT",Boolean.TRUE);
+ event.getSuppliedRequest().getAsyncContext().dispatch();
+ }
- private static ContinuationListener __asyncListener = new ContinuationListener()
- {
- public void onComplete(Continuation continuation)
+ @Override
+ public void onError(AsyncEvent event) throws IOException
{
+
}
- public void onTimeout(Continuation continuation)
+ @Override
+ public void onStartAsync(AsyncEvent event) throws IOException
{
- continuation.setAttribute("TIMEOUT",Boolean.TRUE);
- continuation.resume();
}
};
}
diff --git a/jetty-server/src/test/java/org/eclipse/jetty/server/LocalAsyncContextTest.java b/jetty-server/src/test/java/org/eclipse/jetty/server/LocalAsyncContextTest.java
index 1680c9b2fd..01b270bb68 100644
--- a/jetty-server/src/test/java/org/eclipse/jetty/server/LocalAsyncContextTest.java
+++ b/jetty-server/src/test/java/org/eclipse/jetty/server/LocalAsyncContextTest.java
@@ -18,18 +18,26 @@
package org.eclipse.jetty.server;
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertTrue;
-
-
-
-import org.eclipse.jetty.continuation.Continuation;
-import org.eclipse.jetty.continuation.ContinuationListener;
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.concurrent.atomic.AtomicInteger;
+import javax.servlet.AsyncContext;
+import javax.servlet.AsyncEvent;
+import javax.servlet.AsyncListener;
+import javax.servlet.DispatcherType;
+import javax.servlet.ServletException;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import org.eclipse.jetty.server.handler.HandlerWrapper;
import org.eclipse.jetty.server.session.SessionHandler;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
+
public class LocalAsyncContextTest
{
protected Server _server = new Server();
@@ -48,7 +56,7 @@ public class LocalAsyncContextTest
_server.setHandler(session);
_server.start();
}
-
+
protected Connector initConnector()
{
return new LocalConnector();
@@ -64,76 +72,123 @@ public class LocalAsyncContextTest
@Test
public void testSuspendResume() throws Exception
{
+ String response;
+ __completed.set(0);
+ __completed1.set(0);
_handler.setRead(0);
_handler.setSuspendFor(1000);
_handler.setResumeAfter(-1);
_handler.setCompleteAfter(-1);
- check("TIMEOUT",process(null));
+ response=process(null);
+ check(response,"TIMEOUT");
+ assertEquals(1,__completed.get());
+ assertEquals(1,__completed1.get());
_handler.setSuspendFor(10000);
_handler.setResumeAfter(0);
_handler.setCompleteAfter(-1);
- check("RESUMED",process(null));
+ response=process(null);
+ check(response,"DISPATCHED");
_handler.setResumeAfter(100);
_handler.setCompleteAfter(-1);
- check("RESUMED",process(null));
+ response=process(null);
+ check(response,"DISPATCHED");
_handler.setResumeAfter(-1);
_handler.setCompleteAfter(0);
- check("COMPLETED",process(null));
+ response=process(null);
+ check(response,"COMPLETED");
_handler.setResumeAfter(-1);
_handler.setCompleteAfter(200);
- check("COMPLETED",process(null));
+ response=process(null);
+ check(response,"COMPLETED");
_handler.setRead(-1);
_handler.setResumeAfter(0);
_handler.setCompleteAfter(-1);
- check("RESUMED",process("wibble"));
+ response=process("wibble");
+ check(response,"DISPATCHED");
_handler.setResumeAfter(100);
_handler.setCompleteAfter(-1);
- check("RESUMED",process("wibble"));
+ response=process("wibble");
+ check(response,"DISPATCHED");
_handler.setResumeAfter(-1);
_handler.setCompleteAfter(0);
- check("COMPLETED",process("wibble"));
+ response=process("wibble");
+ check(response,"COMPLETED");
_handler.setResumeAfter(-1);
_handler.setCompleteAfter(100);
- check("COMPLETED",process("wibble"));
+ response=process("wibble");
+ check(response,"COMPLETED");
_handler.setRead(6);
_handler.setResumeAfter(0);
_handler.setCompleteAfter(-1);
- check("RESUMED",process("wibble"));
+ response=process("wibble");
+ check(response,"DISPATCHED");
_handler.setResumeAfter(100);
_handler.setCompleteAfter(-1);
- check("RESUMED",process("wibble"));
+ response=process("wibble");
+ check(response,"DISPATCHED");
_handler.setResumeAfter(-1);
_handler.setCompleteAfter(0);
- check("COMPLETED",process("wibble"));
+ response=process("wibble");
+ check(response,"COMPLETED");
_handler.setResumeAfter(-1);
_handler.setCompleteAfter(100);
- check("COMPLETED",process("wibble"));
+ response=process("wibble");
+ check(response,"COMPLETED");
}
- protected void check(String content,String response)
+ @Test
+ public void testTwoCycles() throws Exception
+ {
+ String response;
+
+ __completed.set(0);
+ __completed1.set(0);
+
+ _handler.setRead(0);
+ _handler.setSuspendFor(1000);
+ _handler.setResumeAfter(100);
+ _handler.setCompleteAfter(-1);
+ _handler.setSuspendFor2(1000);
+ _handler.setResumeAfter2(200);
+ _handler.setCompleteAfter2(-1);
+ response=process(null);
+ check(response,"STARTASYNC","DISPATCHED","startasync","STARTASYNC","DISPATCHED");
+ assertEquals(1,__completed.get());
+ assertEquals(0,__completed1.get());
+
+ }
+
+ protected void check(String response,String... content)
{
assertEquals("HTTP/1.1 200 OK",response.substring(0,15));
- assertTrue(response.contains(content));
+ int i=0;
+ for (String m:content)
+ {
+ i=response.indexOf(m,i);
+ assertTrue(i>=0);
+ i+=m.length();
+ }
+
}
private synchronized String process(String content) throws Exception
{
- String request = "GET / HTTP/1.1\r\n" +
+ String request = "GET / HTTP/1.1\r\n" +
"Host: localhost\r\n"+
"Connection: close\r\n";
@@ -144,23 +199,346 @@ public class LocalAsyncContextTest
return getResponse(request);
}
-
+
protected String getResponse(String request) throws Exception
{
return ((LocalConnector)_connector).getResponses(request);
}
-
- static ContinuationListener __asyncListener = new ContinuationListener()
+ private static class SuspendHandler extends HandlerWrapper
+ {
+ private int _read;
+ private long _suspendFor=-1;
+ private long _resumeAfter=-1;
+ private long _completeAfter=-1;
+ private long _suspendFor2=-1;
+ private long _resumeAfter2=-1;
+ private long _completeAfter2=-1;
+
+ public SuspendHandler()
+ {
+ }
+
+ public int getRead()
+ {
+ return _read;
+ }
+
+ public void setRead(int read)
+ {
+ _read = read;
+ }
+
+ public long getSuspendFor()
+ {
+ return _suspendFor;
+ }
+
+ public void setSuspendFor(long suspendFor)
+ {
+ _suspendFor = suspendFor;
+ }
+
+ public long getResumeAfter()
+ {
+ return _resumeAfter;
+ }
+
+ public void setResumeAfter(long resumeAfter)
+ {
+ _resumeAfter = resumeAfter;
+ }
+
+ public long getCompleteAfter()
+ {
+ return _completeAfter;
+ }
+
+ public void setCompleteAfter(long completeAfter)
+ {
+ _completeAfter = completeAfter;
+ }
+
+
+
+ /* ------------------------------------------------------------ */
+ /** Get the suspendFor2.
+ * @return the suspendFor2
+ */
+ public long getSuspendFor2()
+ {
+ return _suspendFor2;
+ }
+
+
+ /* ------------------------------------------------------------ */
+ /** Set the suspendFor2.
+ * @param suspendFor2 the suspendFor2 to set
+ */
+ public void setSuspendFor2(long suspendFor2)
+ {
+ _suspendFor2 = suspendFor2;
+ }
+
+
+ /* ------------------------------------------------------------ */
+ /** Get the resumeAfter2.
+ * @return the resumeAfter2
+ */
+ public long getResumeAfter2()
+ {
+ return _resumeAfter2;
+ }
+
+
+ /* ------------------------------------------------------------ */
+ /** Set the resumeAfter2.
+ * @param resumeAfter2 the resumeAfter2 to set
+ */
+ public void setResumeAfter2(long resumeAfter2)
+ {
+ _resumeAfter2 = resumeAfter2;
+ }
+
+
+ /* ------------------------------------------------------------ */
+ /** Get the completeAfter2.
+ * @return the completeAfter2
+ */
+ public long getCompleteAfter2()
+ {
+ return _completeAfter2;
+ }
+
+
+ /* ------------------------------------------------------------ */
+ /** Set the completeAfter2.
+ * @param completeAfter2 the completeAfter2 to set
+ */
+ public void setCompleteAfter2(long completeAfter2)
+ {
+ _completeAfter2 = completeAfter2;
+ }
+
+
+ @Override
+ public void handle(String target, final Request baseRequest, final HttpServletRequest request, final HttpServletResponse response) throws IOException, ServletException
+ {
+ try
+ {
+ if (DispatcherType.REQUEST.equals(baseRequest.getDispatcherType()))
+ {
+ if (_read>0)
+ {
+ byte[] buf=new byte[_read];
+ request.getInputStream().read(buf);
+ }
+ else if (_read<0)
+ {
+ InputStream in = request.getInputStream();
+ int b=in.read();
+ while(b!=-1)
+ b=in.read();
+ }
+
+
+ final AsyncContext asyncContext = baseRequest.startAsync();
+ response.getOutputStream().println("STARTASYNC");
+ asyncContext.addListener(__asyncListener);
+ asyncContext.addListener(__asyncListener1);
+ if (_suspendFor>0)
+ asyncContext.setTimeout(_suspendFor);
+
+
+ if (_completeAfter>0)
+ {
+ new Thread() {
+ @Override
+ public void run()
+ {
+ try
+ {
+ Thread.sleep(_completeAfter);
+ response.getOutputStream().println("COMPLETED");
+ response.setStatus(200);
+ baseRequest.setHandled(true);
+ asyncContext.complete();
+ }
+ catch(Exception e)
+ {
+ e.printStackTrace();
+ }
+ }
+ }.start();
+ }
+ else if (_completeAfter==0)
+ {
+ response.getOutputStream().println("COMPLETED");
+ response.setStatus(200);
+ baseRequest.setHandled(true);
+ asyncContext.complete();
+ }
+
+ if (_resumeAfter>0)
+ {
+ new Thread() {
+ @Override
+ public void run()
+ {
+ try
+ {
+ Thread.sleep(_resumeAfter);
+ if(((HttpServletRequest)asyncContext.getRequest()).getSession(true).getId()!=null)
+ asyncContext.dispatch();
+ }
+ catch(Exception e)
+ {
+ e.printStackTrace();
+ }
+ }
+ }.start();
+ }
+ else if (_resumeAfter==0)
+ {
+ asyncContext.dispatch();
+ }
+ }
+ else
+ {
+ if (request.getAttribute("TIMEOUT")!=null)
+ response.getOutputStream().println("TIMEOUT");
+ else
+ response.getOutputStream().println("DISPATCHED");
+
+ if (_suspendFor2>=0)
+ {
+ final AsyncContext asyncContext = baseRequest.startAsync();
+ response.getOutputStream().println("STARTASYNC2");
+ if (_suspendFor2>0)
+ asyncContext.setTimeout(_suspendFor2);
+ _suspendFor2=-1;
+
+ if (_completeAfter2>0)
+ {
+ new Thread() {
+ @Override
+ public void run()
+ {
+ try
+ {
+ Thread.sleep(_completeAfter2);
+ response.getOutputStream().println("COMPLETED2");
+ response.setStatus(200);
+ baseRequest.setHandled(true);
+ asyncContext.complete();
+ }
+ catch(Exception e)
+ {
+ e.printStackTrace();
+ }
+ }
+ }.start();
+ }
+ else if (_completeAfter2==0)
+ {
+ response.getOutputStream().println("COMPLETED2");
+ response.setStatus(200);
+ baseRequest.setHandled(true);
+ asyncContext.complete();
+ }
+
+ if (_resumeAfter2>0)
+ {
+ new Thread() {
+ @Override
+ public void run()
+ {
+ try
+ {
+ Thread.sleep(_resumeAfter2);
+ asyncContext.dispatch();
+ }
+ catch(Exception e)
+ {
+ e.printStackTrace();
+ }
+ }
+ }.start();
+ }
+ else if (_resumeAfter2==0)
+ {
+ asyncContext.dispatch();
+ }
+ }
+ else
+ {
+ response.setStatus(200);
+ baseRequest.setHandled(true);
+ }
+ }
+ }
+ finally
+ {
+ }
+ }
+ }
+
+ static AtomicInteger __completed = new AtomicInteger();
+ static AtomicInteger __completed1 = new AtomicInteger();
+
+ private static AsyncListener __asyncListener = new AsyncListener()
+ {
+
+ @Override
+ public void onComplete(AsyncEvent event) throws IOException
+ {
+ __completed.incrementAndGet();
+ }
+
+ @Override
+ public void onError(AsyncEvent event) throws IOException
+ {
+ __completed.incrementAndGet();
+ }
+
+ @Override
+ public void onStartAsync(AsyncEvent event) throws IOException
+ {
+ event.getSuppliedResponse().getOutputStream().println("startasync");
+ event.getAsyncContext().addListener(this);
+ }
+
+ @Override
+ public void onTimeout(AsyncEvent event) throws IOException
+ {
+ event.getSuppliedRequest().setAttribute("TIMEOUT",Boolean.TRUE);
+ event.getAsyncContext().dispatch();
+ }
+
+ };
+
+ private static AsyncListener __asyncListener1 = new AsyncListener()
{
- public void onComplete(Continuation continuation)
+
+ @Override
+ public void onComplete(AsyncEvent event) throws IOException
{
+ __completed1.incrementAndGet();
}
- public void onTimeout(Continuation continuation)
+ @Override
+ public void onError(AsyncEvent event) throws IOException
{
- continuation.setAttribute("TIMEOUT",Boolean.TRUE);
- continuation.resume();
}
+ @Override
+ public void onStartAsync(AsyncEvent event) throws IOException
+ {
+ }
+
+ @Override
+ public void onTimeout(AsyncEvent event) throws IOException
+ {
+ }
+
};
}
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 766031bd72..408feefa62 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
@@ -23,6 +23,7 @@ import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotSame;
import static org.junit.Assert.assertSame;
import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.assertNotNull;
import java.io.BufferedReader;
import java.io.File;
@@ -36,10 +37,13 @@ import java.util.Enumeration;
import java.util.HashMap;
import java.util.Map;
+import javax.servlet.MultipartConfigElement;
import javax.servlet.ServletException;
+import javax.servlet.ServletRequestEvent;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
+import javax.servlet.http.Part;
import junit.framework.Assert;
@@ -47,6 +51,7 @@ import org.eclipse.jetty.http.MimeTypes;
import org.eclipse.jetty.server.handler.AbstractHandler;
import org.eclipse.jetty.server.handler.ContextHandler;
import org.eclipse.jetty.util.IO;
+import org.eclipse.jetty.util.MultiPartInputStream;
import org.eclipse.jetty.util.StringUtil;
import org.eclipse.jetty.util.log.Log;
import org.junit.After;
@@ -127,6 +132,113 @@ public class RequestTest
assertTrue(responses.startsWith("HTTP/1.1 200"));
}
+
+ @Test
+ public void testMultiPartNoConfig() throws Exception
+ {
+ _handler._checker = new RequestTester()
+ {
+ public boolean check(HttpServletRequest request,HttpServletResponse response)
+ {
+ try
+ {
+ Part foo = request.getPart("stuff");
+ return false;
+ }
+ catch (IllegalStateException e)
+ {
+ //expected exception because no multipart config is set up
+ assertTrue(e.getMessage().startsWith("No multipart config"));
+ return true;
+ }
+ catch (Exception e)
+ {
+ return false;
+ }
+ }
+ };
+
+ String multipart = "--AaB03x\r\n"+
+ "content-disposition: form-data; name=\"field1\"\r\n"+
+ "\r\n"+
+ "Joe Blow\r\n"+
+ "--AaB03x\r\n"+
+ "content-disposition: form-data; name=\"stuff\"\r\n"+
+ "Content-Type: text/plain;charset=ISO-8859-1\r\n"+
+ "\r\n"+
+ "000000000000000000000000000000000000000000000000000\r\n"+
+ "--AaB03x--\r\n";
+
+ String request="GET / HTTP/1.1\r\n"+
+ "Host: whatever\r\n"+
+ "Content-Type: multipart/form-data; boundary=\"AaB03x\"\r\n"+
+ "Content-Length: "+multipart.getBytes().length+"\r\n"+
+ "\r\n"+
+ multipart;
+
+ String responses=_connector.getResponses(request);
+ assertTrue(responses.startsWith("HTTP/1.1 200"));
+ }
+
+
+ @Test
+ public void testMultiPart() throws Exception
+ {
+ final File tmpDir = new File (System.getProperty("java.io.tmpdir"));
+ final File testTmpDir = new File (tmpDir, "reqtest");
+ testTmpDir.deleteOnExit();
+ assertTrue(testTmpDir.mkdirs());
+ assertTrue(testTmpDir.list().length == 0);
+
+ ContextHandler contextHandler = new ContextHandler();
+ contextHandler.setContextPath("/foo");
+ contextHandler.setResourceBase(".");
+ contextHandler.setHandler(new MultiPartRequestHandler(testTmpDir));
+ contextHandler.addEventListener(new Request.MultiPartCleanerListener()
+ {
+
+ @Override
+ public void requestDestroyed(ServletRequestEvent sre)
+ {
+ MultiPartInputStream m = (MultiPartInputStream)sre.getServletRequest().getAttribute(Request.__MULTIPART_INPUT_STREAM);
+ ContextHandler.Context c = (ContextHandler.Context)sre.getServletRequest().getAttribute(Request.__MULTIPART_CONTEXT);
+ assertNotNull (m);
+ assertNotNull (c);
+ assertTrue(c == sre.getServletContext());
+ assertTrue(!m.getParsedParts().isEmpty());
+ assertTrue(testTmpDir.list().length == 2);
+ super.requestDestroyed(sre);
+ String[] files = testTmpDir.list();
+ assertTrue(files.length == 0);
+ }
+
+ });
+ _server.stop();
+ _server.setHandler(contextHandler);
+ _server.start();
+
+ String multipart = "--AaB03x\r\n"+
+ "content-disposition: form-data; name=\"field1\"\r\n"+
+ "\r\n"+
+ "Joe Blow\r\n"+
+ "--AaB03x\r\n"+
+ "content-disposition: form-data; name=\"stuff\"; filename=\"foo.upload\"\r\n"+
+ "Content-Type: text/plain;charset=ISO-8859-1\r\n"+
+ "\r\n"+
+ "000000000000000000000000000000000000000000000000000\r\n"+
+ "--AaB03x--\r\n";
+
+ String request="GET /foo/x.html HTTP/1.1\r\n"+
+ "Host: whatever\r\n"+
+ "Content-Type: multipart/form-data; boundary=\"AaB03x\"\r\n"+
+ "Content-Length: "+multipart.getBytes().length+"\r\n"+
+ "\r\n"+
+ multipart;
+
+ String responses=_connector.getResponses(request);
+ System.err.println(responses);
+ assertTrue(responses.startsWith("HTTP/1.1 200"));
+ }
@Test
public void testBadUtf8ParamExtraction() throws Exception
@@ -670,10 +782,12 @@ public class RequestTest
assertNotSame(cookies.get(1), cookies.get(3));
cookies.clear();
+//NOTE: the javax.servlet.http.Cookie class sets the system property org.glassfish.web.rfc2109_cookie_names_enforced
+//to TRUE by default, and rejects all cookie names containing punctuation.Therefore this test cannot use "name2".
response=_connector.getResponses(
"POST / HTTP/1.1\r\n"+
"Host: whatever\r\n"+
- "Cookie: name0=value0; name1 = value1 ; \"\\\"name2\\\"\" = \"\\\"value2\\\"\" \n" +
+ "Cookie: name0=value0; name1 = value1 ; \"name2\" = \"\\\"value2\\\"\" \n" +
"Cookie: $Version=2; name3=value3=value3;$path=/path;$domain=acme.com;$port=8080; name4=; name5 = ; name6\n" +
"Cookie: name7=value7;\n" +
"Connection: close\r\n"+
@@ -683,7 +797,7 @@ public class RequestTest
assertEquals("value0", cookies.get(0).getValue());
assertEquals("name1", cookies.get(1).getName());
assertEquals("value1", cookies.get(1).getValue());
- assertEquals("\"name2\"", cookies.get(2).getName());
+ assertEquals("name2", cookies.get(2).getName());
assertEquals("\"value2\"", cookies.get(2).getValue());
assertEquals("name3", cookies.get(3).getName());
assertEquals("value3=value3", cookies.get(3).getValue());
@@ -850,7 +964,9 @@ public class RequestTest
{
((Request)request).setHandled(true);
- if (request.getContentLength()>0 && !MimeTypes.FORM_ENCODED.equals(request.getContentType()))
+ if (request.getContentLength()>0
+ && !MimeTypes.FORM_ENCODED.equals(request.getContentType())
+ && !request.getContentType().startsWith("multipart/form-data"))
_content=IO.toString(request.getInputStream());
if (_checker!=null && _checker.check(request,response))
@@ -861,4 +977,43 @@ public class RequestTest
}
}
+
+ private class MultiPartRequestHandler extends AbstractHandler
+ {
+ File tmpDir;
+
+ public MultiPartRequestHandler(File tmpDir)
+ {
+ this.tmpDir = tmpDir;
+ }
+
+
+ @Override
+ public void handle(String target, Request baseRequest, HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException
+ {
+ ((Request)request).setHandled(true);
+ try
+ {
+
+ MultipartConfigElement mpce = new MultipartConfigElement(tmpDir.getAbsolutePath(),-1, -1, 2);
+ request.setAttribute(Request.__MULTIPART_CONFIG_ELEMENT, mpce);
+
+ Part foo = request.getPart("stuff");
+ assertNotNull(foo);
+ assertTrue(foo.getSize() > 0);
+
+ response.setStatus(200);
+ }
+ catch (IllegalStateException e)
+ {
+ //expected exception because no multipart config is set up
+ assertTrue(e.getMessage().startsWith("No multipart config"));
+ response.setStatus(200);
+ }
+ catch (Exception e)
+ {
+ response.sendError(500);
+ }
+ }
+ }
}
diff --git a/jetty-server/src/test/java/org/eclipse/jetty/server/ResponseTest.java b/jetty-server/src/test/java/org/eclipse/jetty/server/ResponseTest.java
index 0c205b0bfc..ece7e2e964 100644
--- a/jetty-server/src/test/java/org/eclipse/jetty/server/ResponseTest.java
+++ b/jetty-server/src/test/java/org/eclipse/jetty/server/ResponseTest.java
@@ -32,6 +32,7 @@ import java.net.Socket;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Enumeration;
+import java.util.Iterator;
import java.util.Locale;
import java.util.Map;
@@ -104,14 +105,15 @@ public class ResponseTest
response.setContentType("foo2/bar2");
assertEquals("foo2/bar2;charset=ISO-8859-1",response.getContentType());
response.setHeader("name","foo");
- Enumeration<?> en=response.getHeaders("name");
- assertEquals("foo",en.nextElement());
- assertFalse(en.hasMoreElements());
+
+ Iterator<String> en = response.getHeaders("name").iterator();
+ assertEquals("foo",en.next());
+ assertFalse(en.hasNext());
response.addHeader("name","bar");
- en=response.getHeaders("name");
- assertEquals("foo",en.nextElement());
- assertEquals("bar",en.nextElement());
- assertFalse(en.hasMoreElements());
+ en=response.getHeaders("name").iterator();
+ assertEquals("foo",en.next());
+ assertEquals("bar",en.next());
+ assertFalse(en.hasNext());
response.recycle();
diff --git a/jetty-server/src/test/java/org/eclipse/jetty/server/SelectChannelTimeoutTest.java b/jetty-server/src/test/java/org/eclipse/jetty/server/SelectChannelTimeoutTest.java
index e44b9cdaf3..8419806862 100644
--- a/jetty-server/src/test/java/org/eclipse/jetty/server/SelectChannelTimeoutTest.java
+++ b/jetty-server/src/test/java/org/eclipse/jetty/server/SelectChannelTimeoutTest.java
@@ -18,8 +18,6 @@
package org.eclipse.jetty.server;
-import static org.junit.Assert.assertTrue;
-
import java.io.IOException;
import java.io.InputStream;
import java.io.UnsupportedEncodingException;
@@ -32,6 +30,8 @@ import org.eclipse.jetty.util.IO;
import org.junit.BeforeClass;
import org.junit.Test;
+import static org.junit.Assert.assertTrue;
+
public class SelectChannelTimeoutTest extends ConnectorTimeoutTest
{
diff --git a/jetty-server/src/test/java/org/eclipse/jetty/server/SuspendHandler.java b/jetty-server/src/test/java/org/eclipse/jetty/server/SuspendHandler.java
index 78dff1721e..aafaef02ff 100644
--- a/jetty-server/src/test/java/org/eclipse/jetty/server/SuspendHandler.java
+++ b/jetty-server/src/test/java/org/eclipse/jetty/server/SuspendHandler.java
@@ -20,14 +20,17 @@ package org.eclipse.jetty.server;
import java.io.IOException;
import java.io.InputStream;
-
+import javax.servlet.AsyncContext;
+import javax.servlet.AsyncEvent;
+import javax.servlet.AsyncListener;
+import javax.servlet.DispatcherType;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.eclipse.jetty.server.handler.HandlerWrapper;
-class SuspendHandler extends HandlerWrapper
+class SuspendHandler extends HandlerWrapper implements AsyncListener
{
private int _read;
private long _suspendFor=-1;
@@ -77,7 +80,7 @@ class SuspendHandler extends HandlerWrapper
{
_completeAfter = completeAfter;
}
-
+
@Override
public void handle(String target, final Request baseRequest, final HttpServletRequest request, final HttpServletResponse response) throws IOException, ServletException
{
@@ -97,7 +100,7 @@ class SuspendHandler extends HandlerWrapper
}
final AsyncContext asyncContext = baseRequest.startAsync();
- asyncContext.addContinuationListener(LocalAsyncContextTest.__asyncListener);
+ asyncContext.addListener(this);
if (_suspendFor>0)
asyncContext.setTimeout(_suspendFor);
@@ -110,7 +113,7 @@ class SuspendHandler extends HandlerWrapper
try
{
Thread.sleep(_completeAfter);
- response.getOutputStream().print("COMPLETED");
+ response.getOutputStream().println("COMPLETED");
response.setStatus(200);
baseRequest.setHandled(true);
asyncContext.complete();
@@ -124,7 +127,7 @@ class SuspendHandler extends HandlerWrapper
}
else if (_completeAfter==0)
{
- response.getOutputStream().print("COMPLETED");
+ response.getOutputStream().println("COMPLETED");
response.setStatus(200);
baseRequest.setHandled(true);
asyncContext.complete();
@@ -167,4 +170,25 @@ class SuspendHandler extends HandlerWrapper
}
}
-} \ No newline at end of file
+ @Override
+ public void onComplete(AsyncEvent asyncEvent) throws IOException
+ {
+ }
+
+ @Override
+ public void onTimeout(AsyncEvent asyncEvent) throws IOException
+ {
+ asyncEvent.getSuppliedRequest().setAttribute("TIMEOUT",Boolean.TRUE);
+ asyncEvent.getAsyncContext().dispatch();
+ }
+
+ @Override
+ public void onError(AsyncEvent asyncEvent) throws IOException
+ {
+ }
+
+ @Override
+ public void onStartAsync(AsyncEvent asyncEvent) throws IOException
+ {
+ }
+}
diff --git a/jetty-server/src/test/java/org/eclipse/jetty/server/session/SessionCookieTest.java b/jetty-server/src/test/java/org/eclipse/jetty/server/session/SessionCookieTest.java
new file mode 100644
index 0000000000..6792eff573
--- /dev/null
+++ b/jetty-server/src/test/java/org/eclipse/jetty/server/session/SessionCookieTest.java
@@ -0,0 +1,199 @@
+//
+// ========================================================================
+// Copyright (c) 1995-2012 Mort Bay Consulting Pty. Ltd.
+// ------------------------------------------------------------------------
+// All rights reserved. This program and the accompanying materials
+// are made available under the terms of the Eclipse Public License v1.0
+// and Apache License v2.0 which accompanies this distribution.
+//
+// The Eclipse Public License is available at
+// http://www.eclipse.org/legal/epl-v10.html
+//
+// The Apache License v2.0 is available at
+// http://www.opensource.org/licenses/apache2.0.php
+//
+// You may elect to redistribute this code under either of these licenses.
+// ========================================================================
+//
+
+package org.eclipse.jetty.server.session;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+
+import javax.servlet.SessionCookieConfig;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpSession;
+
+import org.eclipse.jetty.http.HttpCookie;
+import org.junit.Test;
+/**
+ * SessionCookieTest
+ *
+ *
+ */
+public class SessionCookieTest
+{
+
+ public class MockSession extends AbstractSession
+ {
+
+
+ /**
+ * @param abstractSessionManager
+ * @param created
+ * @param accessed
+ * @param clusterId
+ */
+ protected MockSession(AbstractSessionManager abstractSessionManager, long created, long accessed, String clusterId)
+ {
+ super(abstractSessionManager, created, accessed, clusterId);
+ }
+
+ }
+
+ public class MockSessionIdManager extends AbstractSessionIdManager
+ {
+
+ /**
+ * @see org.eclipse.jetty.server.SessionIdManager#idInUse(java.lang.String)
+ */
+ public boolean idInUse(String id)
+ {
+ return false;
+ }
+
+ /**
+ * @see org.eclipse.jetty.server.SessionIdManager#addSession(javax.servlet.http.HttpSession)
+ */
+ public void addSession(HttpSession session)
+ {
+
+ }
+
+ /**
+ * @see org.eclipse.jetty.server.SessionIdManager#removeSession(javax.servlet.http.HttpSession)
+ */
+ public void removeSession(HttpSession session)
+ {
+
+ }
+
+ /**
+ * @see org.eclipse.jetty.server.SessionIdManager#invalidateAll(java.lang.String)
+ */
+ public void invalidateAll(String id)
+ {
+
+ }
+
+ /**
+ * @see org.eclipse.jetty.server.SessionIdManager#getClusterId(java.lang.String)
+ */
+ public String getClusterId(String nodeId)
+ {
+ int dot=nodeId.lastIndexOf('.');
+ return (dot>0)?nodeId.substring(0,dot):nodeId;
+ }
+
+ /**
+ * @see org.eclipse.jetty.server.SessionIdManager#getNodeId(java.lang.String, javax.servlet.http.HttpServletRequest)
+ */
+ public String getNodeId(String clusterId, HttpServletRequest request)
+ {
+ return clusterId+'.'+_workerName;
+ }
+
+ }
+
+ public class MockSessionManager extends AbstractSessionManager
+ {
+
+ /**
+ * @see org.eclipse.jetty.server.session.AbstractSessionManager#addSession(org.eclipse.jetty.server.session.AbstractSession)
+ */
+ protected void addSession(AbstractSession session)
+ {
+
+ }
+
+ /**
+ * @see org.eclipse.jetty.server.session.AbstractSessionManager#getSession(java.lang.String)
+ */
+ public AbstractSession getSession(String idInCluster)
+ {
+ return null;
+ }
+
+ /**
+ * @see org.eclipse.jetty.server.session.AbstractSessionManager#invalidateSessions()
+ */
+ protected void invalidateSessions() throws Exception
+ {
+
+ }
+
+ /**
+ * @see org.eclipse.jetty.server.session.AbstractSessionManager#newSession(javax.servlet.http.HttpServletRequest)
+ */
+ protected AbstractSession newSession(HttpServletRequest request)
+ {
+ return null;
+ }
+
+ /**
+ * @see org.eclipse.jetty.server.session.AbstractSessionManager#removeSession(java.lang.String)
+ */
+ protected boolean removeSession(String idInCluster)
+ {
+ return false;
+ }
+
+ }
+
+ @Test
+ public void testSecureSessionCookie () throws Exception
+ {
+ MockSessionIdManager idMgr = new MockSessionIdManager();
+ idMgr.setWorkerName("node1");
+ MockSessionManager mgr = new MockSessionManager();
+ mgr.setSessionIdManager(idMgr);
+ MockSession session = new MockSession(mgr, System.currentTimeMillis(), System.currentTimeMillis(), "node1123"); //clusterId
+
+ SessionCookieConfig sessionCookieConfig = mgr.getSessionCookieConfig();
+ sessionCookieConfig.setSecure(true);
+
+ //sessionCookieConfig.secure == true, always mark cookie as secure, irrespective of if requestIsSecure
+ HttpCookie cookie = mgr.getSessionCookie(session, "/foo", true);
+ assertTrue(cookie.isSecure());
+ //sessionCookieConfig.secure == true, always mark cookie as secure, irrespective of if requestIsSecure
+ cookie = mgr.getSessionCookie(session, "/foo", false);
+ assertTrue(cookie.isSecure());
+
+ //sessionCookieConfig.secure==false, setSecureRequestOnly==true, requestIsSecure==true
+ //cookie should be secure: see SessionCookieConfig.setSecure() javadoc
+ sessionCookieConfig.setSecure(false);
+ cookie = mgr.getSessionCookie(session, "/foo", true);
+ assertTrue(cookie.isSecure());
+
+ //sessionCookieConfig.secure=false, setSecureRequestOnly==true, requestIsSecure==false
+ //cookie is not secure: see SessionCookieConfig.setSecure() javadoc
+ cookie = mgr.getSessionCookie(session, "/foo", false);
+ assertFalse(cookie.isSecure());
+
+ //sessionCookieConfig.secure=false, setSecureRequestOnly==false, requestIsSecure==false
+ //cookie is not secure: not a secure request
+ mgr.setSecureRequestOnly(false);
+ cookie = mgr.getSessionCookie(session, "/foo", false);
+ assertFalse(cookie.isSecure());
+
+ //sessionCookieConfig.secure=false, setSecureRequestOnly==false, requestIsSecure==true
+ //cookie is not secure: not on secured requests and request is secure
+ cookie = mgr.getSessionCookie(session, "/foo", true);
+ assertFalse(cookie.isSecure());
+
+
+ }
+
+}
diff --git a/jetty-server/src/test/java/org/eclipse/jetty/server/session/SessionHandlerTest.java b/jetty-server/src/test/java/org/eclipse/jetty/server/session/SessionHandlerTest.java
index 8ad58a7726..28c57e0e38 100644
--- a/jetty-server/src/test/java/org/eclipse/jetty/server/session/SessionHandlerTest.java
+++ b/jetty-server/src/test/java/org/eclipse/jetty/server/session/SessionHandlerTest.java
@@ -26,20 +26,29 @@ import java.io.BufferedReader;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.security.Principal;
+import java.util.Collection;
import java.util.Enumeration;
import java.util.EventListener;
import java.util.Locale;
import java.util.Map;
-
+import java.util.Set;
+import javax.servlet.AsyncContext;
import javax.servlet.RequestDispatcher;
+import javax.servlet.ServletContext;
+import javax.servlet.ServletException;
import javax.servlet.ServletInputStream;
+import javax.servlet.ServletRequest;
+import javax.servlet.ServletResponse;
+import javax.servlet.SessionCookieConfig;
+import javax.servlet.SessionTrackingMode;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
+import javax.servlet.http.Part;
+import javax.servlet.DispatcherType;
import org.eclipse.jetty.http.HttpCookie;
-import org.eclipse.jetty.server.DispatcherType;
import org.eclipse.jetty.server.Request;
import org.eclipse.jetty.server.SessionIdManager;
import org.eclipse.jetty.server.SessionManager;
@@ -68,6 +77,98 @@ public class SessionHandlerTest
SessionHandler sessionHandler = new SessionHandler();
sessionHandler.setSessionManager(new MockSessionManager()
{
+
+
+ public SessionCookieConfig getSessionCookieConfig()
+ {
+ return new SessionCookieConfig()
+ {
+
+ public String getComment()
+ {
+ // TODO Auto-generated method stub
+ return null;
+ }
+
+ public String getDomain()
+ {
+ // TODO Auto-generated method stub
+ return null;
+ }
+
+ public int getMaxAge()
+ {
+ // TODO Auto-generated method stub
+ return 0;
+ }
+
+ public String getName()
+ {
+ return cookieName;
+ }
+
+ public String getPath()
+ {
+ // TODO Auto-generated method stub
+ return null;
+ }
+
+ public boolean isHttpOnly()
+ {
+ // TODO Auto-generated method stub
+ return false;
+ }
+
+ public boolean isSecure()
+ {
+ // TODO Auto-generated method stub
+ return false;
+ }
+
+ public void setComment(String comment)
+ {
+ // TODO Auto-generated method stub
+
+ }
+
+ public void setDomain(String domain)
+ {
+ // TODO Auto-generated method stub
+
+ }
+
+ public void setHttpOnly(boolean httpOnly)
+ {
+ // TODO Auto-generated method stub
+
+ }
+
+ public void setMaxAge(int maxAge)
+ {
+ // TODO Auto-generated method stub
+
+ }
+
+ public void setName(String name)
+ {
+ // TODO Auto-generated method stub
+
+ }
+
+ public void setPath(String path)
+ {
+ // TODO Auto-generated method stub
+
+ }
+
+ public void setSecure(boolean secure)
+ {
+ // TODO Auto-generated method stub
+
+ }
+
+ };
+ }
public boolean isUsingCookies()
{
return true;
@@ -104,7 +205,8 @@ public class SessionHandlerTest
SessionHandler sessionHandler = new SessionHandler();
sessionHandler.setSessionManager(new MockSessionManager()
- {
+ {
+
@Override
public String getSessionIdPathParameterName()
{
@@ -396,6 +498,114 @@ public class SessionHandlerTest
public void setCharacterEncoding(String env) throws UnsupportedEncodingException
{
}
+
+ /**
+ * @see javax.servlet.http.HttpServletRequest#authenticate(javax.servlet.http.HttpServletResponse)
+ */
+ public boolean authenticate(HttpServletResponse response) throws IOException, ServletException
+ {
+ // TODO Auto-generated method stub
+ return false;
+ }
+
+ /**
+ * @see javax.servlet.http.HttpServletRequest#getPart(java.lang.String)
+ */
+ public Part getPart(String name) throws IOException, ServletException
+ {
+ // TODO Auto-generated method stub
+ return null;
+ }
+
+ /**
+ * @see javax.servlet.http.HttpServletRequest#getParts()
+ */
+ public Collection<Part> getParts() throws IOException, ServletException
+ {
+ // TODO Auto-generated method stub
+ return null;
+ }
+
+ /**
+ * @see javax.servlet.http.HttpServletRequest#login(java.lang.String, java.lang.String)
+ */
+ public void login(String username, String password) throws ServletException
+ {
+ // TODO Auto-generated method stub
+
+ }
+
+ /**
+ * @see javax.servlet.http.HttpServletRequest#logout()
+ */
+ public void logout() throws ServletException
+ {
+ // TODO Auto-generated method stub
+
+ }
+
+ /**
+ * @see javax.servlet.ServletRequest#getAsyncContext()
+ */
+ public AsyncContext getAsyncContext()
+ {
+ // TODO Auto-generated method stub
+ return null;
+ }
+
+ /**
+ * @see javax.servlet.ServletRequest#getDispatcherType()
+ */
+ public DispatcherType getDispatcherType()
+ {
+ // TODO Auto-generated method stub
+ return null;
+ }
+
+ /**
+ * @see javax.servlet.ServletRequest#getServletContext()
+ */
+ public ServletContext getServletContext()
+ {
+ // TODO Auto-generated method stub
+ return null;
+ }
+
+ /**
+ * @see javax.servlet.ServletRequest#isAsyncStarted()
+ */
+ public boolean isAsyncStarted()
+ {
+ // TODO Auto-generated method stub
+ return false;
+ }
+
+ /**
+ * @see javax.servlet.ServletRequest#isAsyncSupported()
+ */
+ public boolean isAsyncSupported()
+ {
+ // TODO Auto-generated method stub
+ return false;
+ }
+
+ /**
+ * @see javax.servlet.ServletRequest#startAsync()
+ */
+ public AsyncContext startAsync() throws IllegalStateException
+ {
+ // TODO Auto-generated method stub
+ return null;
+ }
+
+ /**
+ * @see javax.servlet.ServletRequest#startAsync(javax.servlet.ServletRequest, javax.servlet.ServletResponse)
+ */
+ public AsyncContext startAsync(ServletRequest servletRequest, ServletResponse servletResponse) throws IllegalStateException
+ {
+ // TODO Auto-generated method stub
+ return null;
+ }
}
/**
@@ -592,6 +802,50 @@ public class SessionHandlerTest
{
}
+ /**
+ * @see org.eclipse.jetty.server.SessionManager#getDefaultSessionTrackingModes()
+ */
+ public Set<SessionTrackingMode> getDefaultSessionTrackingModes()
+ {
+ // TODO Auto-generated method stub
+ return null;
+ }
+
+ /**
+ * @see org.eclipse.jetty.server.SessionManager#getEffectiveSessionTrackingModes()
+ */
+ public Set<SessionTrackingMode> getEffectiveSessionTrackingModes()
+ {
+ // TODO Auto-generated method stub
+ return null;
+ }
+
+ /**
+ * @see org.eclipse.jetty.server.SessionManager#getSessionCookieConfig()
+ */
+ public SessionCookieConfig getSessionCookieConfig()
+ {
+ return null;
+ }
+
+ /**
+ * @see org.eclipse.jetty.server.SessionManager#isUsingURLs()
+ */
+ public boolean isUsingURLs()
+ {
+ // TODO Auto-generated method stub
+ return false;
+ }
+
+ /**
+ * @see org.eclipse.jetty.server.SessionManager#setSessionTrackingModes(java.util.Set)
+ */
+ public void setSessionTrackingModes(Set<SessionTrackingMode> sessionTrackingModes)
+ {
+ // TODO Auto-generated method stub
+
+ }
+
private boolean _checkRemote=false;
public boolean isCheckingRemoteSessionIdEncoding()
diff --git a/jetty-servlet/pom.xml b/jetty-servlet/pom.xml
index cb80ecefd8..7b6c31b5b1 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>7.6.8-SNAPSHOT</version>
+ <version>8.1.8-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>jetty-servlet</artifactId>
@@ -25,7 +25,7 @@
</goals>
<configuration>
<instructions>
- <Import-Package>org.eclipse.jetty.jmx.*;version="[7.3,8)";resolution:=optional,*</Import-Package>
+ <Import-Package>javax.servlet.*;version="2.6.0",org.eclipse.jetty.jmx.*;version="8.0";resolution:=optional,*</Import-Package>
</instructions>
</configuration>
</execution>
diff --git a/jetty-servlet/src/main/java/org/eclipse/jetty/servlet/FilterHolder.java b/jetty-servlet/src/main/java/org/eclipse/jetty/servlet/FilterHolder.java
index 4078898e67..e5ef8c2301 100644
--- a/jetty-servlet/src/main/java/org/eclipse/jetty/servlet/FilterHolder.java
+++ b/jetty-servlet/src/main/java/org/eclipse/jetty/servlet/FilterHolder.java
@@ -24,12 +24,13 @@ import java.util.Collection;
import java.util.EnumSet;
import java.util.List;
+import javax.servlet.DispatcherType;
import javax.servlet.Filter;
import javax.servlet.FilterConfig;
+import javax.servlet.FilterRegistration;
import javax.servlet.ServletException;
-import org.eclipse.jetty.server.DispatcherType;
-import org.eclipse.jetty.servlet.api.FilterRegistration;
+import org.eclipse.jetty.servlet.Holder.Source;
import org.eclipse.jetty.util.TypeUtil;
import org.eclipse.jetty.util.log.Log;
import org.eclipse.jetty.util.log.Logger;
@@ -52,14 +53,24 @@ public class FilterHolder extends Holder<Filter>
*/
public FilterHolder()
{
+ super (Source.EMBEDDED);
}
/* ---------------------------------------------------------------- */
/** Constructor
*/
+ public FilterHolder(Holder.Source source)
+ {
+ super (source);
+ }
+
+ /* ---------------------------------------------------------------- */
+ /** Constructor
+ */
public FilterHolder(Class<? extends Filter> filter)
{
+ super (Source.EMBEDDED);
setHeldClass(filter);
}
@@ -68,6 +79,7 @@ public class FilterHolder extends Holder<Filter>
*/
public FilterHolder(Filter filter)
{
+ super (Source.EMBEDDED);
setFilter(filter);
}
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 fb98819592..195e5d6b09 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
@@ -21,8 +21,8 @@ package org.eclipse.jetty.servlet;
import java.io.IOException;
import java.util.EnumSet;
+import javax.servlet.DispatcherType;
import org.eclipse.jetty.http.PathMap;
-import org.eclipse.jetty.server.DispatcherType;
import org.eclipse.jetty.server.Handler;
import org.eclipse.jetty.util.TypeUtil;
import org.eclipse.jetty.util.component.AggregateLifeCycle;
@@ -172,8 +172,6 @@ public class FilterMapping implements Dumpable
}
}
-
-
/* ------------------------------------------------------------ */
/**
* @param dispatches The dispatches to set.
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 dc080d5d28..2bef5dfea0 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
@@ -26,11 +26,11 @@ import java.util.HashSet;
import java.util.Map;
import java.util.Set;
+import javax.servlet.Registration;
import javax.servlet.ServletContext;
import javax.servlet.UnavailableException;
import org.eclipse.jetty.server.handler.ContextHandler;
-import org.eclipse.jetty.servlet.api.Registration;
import org.eclipse.jetty.util.Loader;
import org.eclipse.jetty.util.component.AbstractLifeCycle;
import org.eclipse.jetty.util.component.AggregateLifeCycle;
@@ -45,6 +45,8 @@ import org.eclipse.jetty.util.log.Logger;
*/
public class Holder<T> extends AbstractLifeCycle implements Dumpable
{
+ public enum Source { EMBEDDED, JAVAX_API, DESCRIPTOR, ANNOTATION };
+ final private Source _source;
private static final Logger LOG = Log.getLogger(Holder.class);
protected transient Class<? extends T> _class;
@@ -59,10 +61,16 @@ public class Holder<T> extends AbstractLifeCycle implements Dumpable
protected ServletHandler _servletHandler;
/* ---------------------------------------------------------------- */
- protected Holder()
+ protected Holder(Source source)
{
+ _source=source;
}
-
+
+ public Source getSource()
+ {
+ return _source;
+ }
+
/* ------------------------------------------------------------ */
/**
* @return True if this holder was created for a specific instance.
@@ -79,7 +87,7 @@ public class Holder<T> extends AbstractLifeCycle implements Dumpable
{
//if no class already loaded and no classname, make servlet permanently unavailable
if (_class==null && (_className==null || _className.equals("")))
- throw new UnavailableException("No class for Servlet or Filter", -1);
+ throw new UnavailableException("No class for Servlet or Filter for "+_name, -1);
//try to load class
if (_class==null)
@@ -341,6 +349,12 @@ public class Holder<T> extends AbstractLifeCycle implements Dumpable
public boolean setInitParameter(String name, String value)
{
illegalStateIfContextStarted();
+ if (name == null) {
+ throw new IllegalArgumentException("init parameter name required");
+ }
+ if (value == null) {
+ throw new IllegalArgumentException("non-null value required for init parameter " + name);
+ }
if (Holder.this.getInitParameter(name)!=null)
return false;
Holder.this.setInitParameter(name,value);
@@ -351,20 +365,28 @@ public class Holder<T> extends AbstractLifeCycle implements Dumpable
{
illegalStateIfContextStarted();
Set<String> clash=null;
- for (String name : initParameters.keySet())
+ for (Map.Entry<String, String> entry : initParameters.entrySet())
{
- if (Holder.this.getInitParameter(name)!=null)
+ if (entry.getKey() == null) {
+ throw new IllegalArgumentException("init parameter name required");
+ }
+ if (entry.getValue() == null) {
+ throw new IllegalArgumentException("non-null value required for init parameter " + entry.getKey());
+ }
+ if (Holder.this.getInitParameter(entry.getKey())!=null)
{
if (clash==null)
clash=new HashSet<String>();
- clash.add(name);
+ clash.add(entry.getKey());
}
}
if (clash!=null)
return clash;
- Holder.this.setInitParameters(initParameters);
+ Holder.this.getInitParameters().putAll(initParameters);
return Collections.emptySet();
- };
+ }
+
+
}
}
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 c8ec32a2b9..055060ae91 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
@@ -20,6 +20,7 @@ package org.eclipse.jetty.servlet;
import java.util.ArrayList;
import java.util.Arrays;
+import java.util.Collection;
import java.util.Collections;
import java.util.EnumSet;
import java.util.EventListener;
@@ -29,19 +30,28 @@ import java.util.List;
import java.util.Map;
import java.util.Set;
+import javax.servlet.DispatcherType;
import javax.servlet.Filter;
+import javax.servlet.FilterRegistration;
import javax.servlet.RequestDispatcher;
import javax.servlet.Servlet;
import javax.servlet.ServletContext;
import javax.servlet.ServletContextEvent;
import javax.servlet.ServletContextListener;
import javax.servlet.ServletException;
+import javax.servlet.ServletRegistration;
+import javax.servlet.ServletSecurityElement;
+import javax.servlet.SessionCookieConfig;
+import javax.servlet.SessionTrackingMode;
+import javax.servlet.descriptor.JspConfigDescriptor;
+import javax.servlet.descriptor.JspPropertyGroupDescriptor;
+import javax.servlet.descriptor.TaglibDescriptor;
import org.eclipse.jetty.security.ConstraintAware;
+import org.eclipse.jetty.security.ConstraintMapping;
import org.eclipse.jetty.security.ConstraintSecurityHandler;
import org.eclipse.jetty.security.SecurityHandler;
import org.eclipse.jetty.server.Dispatcher;
-import org.eclipse.jetty.server.DispatcherType;
import org.eclipse.jetty.server.Handler;
import org.eclipse.jetty.server.HandlerContainer;
import org.eclipse.jetty.server.handler.ContextHandler;
@@ -49,9 +59,8 @@ import org.eclipse.jetty.server.handler.ErrorHandler;
import org.eclipse.jetty.server.handler.HandlerCollection;
import org.eclipse.jetty.server.handler.HandlerWrapper;
import org.eclipse.jetty.server.session.SessionHandler;
-import org.eclipse.jetty.servlet.api.FilterRegistration;
-import org.eclipse.jetty.servlet.api.ServletRegistration;
-import org.eclipse.jetty.util.Loader;
+import org.eclipse.jetty.util.LazyList;
+import org.eclipse.jetty.util.security.Constraint;
/* ------------------------------------------------------------ */
@@ -79,8 +88,10 @@ public class ServletContextHandler extends ContextHandler
protected ServletHandler _servletHandler;
protected HandlerWrapper _wrapper;
protected int _options;
+ protected JspConfigDescriptor _jspConfig;
protected Object _restrictedContextListeners;
-
+ private boolean _restrictListeners = true;
+
/* ------------------------------------------------------------ */
public ServletContextHandler()
{
@@ -336,46 +347,96 @@ public class ServletContextHandler extends ContextHandler
{
return getServletHandler().addFilterWithMapping(filterClass,pathSpec,dispatches);
}
-
- /* ------------------------------------------------------------ */
- /** conveniance method to add a filter
+ /**
+ * notification that a ServletRegistration has been created so we can track the annotations
+ * @param holder new holder created through the api.
+ * @return the ServletRegistration.Dynamic
*/
- public void addFilter(FilterHolder holder,String pathSpec,int dispatches)
- {
- getServletHandler().addFilterWithMapping(holder,pathSpec,dispatches);
+ protected ServletRegistration.Dynamic dynamicHolderAdded(ServletHolder holder) {
+ return holder.getRegistration();
}
- /* ------------------------------------------------------------ */
- /** convenience method to add a filter
+ /**
+ * delegate for ServletContext.declareRole method
+ * @param roleNames role names to add
*/
- public FilterHolder addFilter(Class<? extends Filter> filterClass,String pathSpec,int dispatches)
- {
- return getServletHandler().addFilterWithMapping(filterClass,pathSpec,dispatches);
+ protected void addRoles(String... roleNames) {
+ //Get a reference to the SecurityHandler, which must be ConstraintAware
+ if (_securityHandler != null && _securityHandler instanceof ConstraintAware)
+ {
+ HashSet<String> union = new HashSet<String>();
+ Set<String> existing = ((ConstraintAware)_securityHandler).getRoles();
+ if (existing != null)
+ union.addAll(existing);
+ union.addAll(Arrays.asList(roleNames));
+ ((ConstraintSecurityHandler)_securityHandler).setRoles(union);
+ }
}
- /* ------------------------------------------------------------ */
- /** convenience method to add a filter
+ /**
+ * Delegate for ServletRegistration.Dynamic.setServletSecurity method
+ * @param registration ServletRegistration.Dynamic instance that setServletSecurity was called on
+ * @param servletSecurityElement new security info
+ * @return the set of exact URL mappings currently associated with the registration that are also present in the web.xml
+ * security constraints and thus will be unaffected by this call.
*/
- public FilterHolder addFilter(String filterClass,String pathSpec,int dispatches)
+ public Set<String> setServletSecurity(ServletRegistration.Dynamic registration, ServletSecurityElement servletSecurityElement)
{
- return getServletHandler().addFilterWithMapping(filterClass,pathSpec,dispatches);
+ //Default implementation is to just accept them all. If using a webapp, then this behaviour is overridden in WebAppContext.setServletSecurity
+ Collection<String> pathSpecs = registration.getMappings();
+ if (pathSpecs != null)
+ {
+ for (String pathSpec:pathSpecs)
+ {
+ List<ConstraintMapping> mappings = ConstraintSecurityHandler.createConstraintsWithMappingsForPath(registration.getName(), pathSpec, servletSecurityElement);
+ for (ConstraintMapping m:mappings)
+ ((ConstraintAware)getSecurityHandler()).addConstraintMapping(m);
+ }
+ }
+ return Collections.emptySet();
}
-
- public void callContextInitialized(ServletContextListener l, ServletContextEvent e)
- {
- l.contextInitialized(e);
+
+ public void restrictEventListener (EventListener e)
+ {
+ if (_restrictListeners && e instanceof ServletContextListener)
+ _restrictedContextListeners = LazyList.add(_restrictedContextListeners, e);
}
+ public boolean isRestrictListeners() {
+ return _restrictListeners;
+ }
- public void callContextDestroyed(ServletContextListener l, ServletContextEvent e)
+ public void setRestrictListeners(boolean restrictListeners) {
+ this._restrictListeners = restrictListeners;
+ }
+
+ public void callContextInitialized(ServletContextListener l, ServletContextEvent e)
{
- l.contextDestroyed(e);
+ try
+ {
+ //toggle state of the dynamic API so that the listener cannot use it
+ if (LazyList.contains(_restrictedContextListeners, l))
+ this.getServletContext().setEnabled(false);
+
+ super.callContextInitialized(l, e);
+ }
+ finally
+ {
+ //untoggle the state of the dynamic API
+ this.getServletContext().setEnabled(true);
+ }
}
+
+ public void callContextDestroyed(ServletContextListener l, ServletContextEvent e)
+ {
+ super.callContextDestroyed(l, e);
+ }
+
/* ------------------------------------------------------------ */
/**
@@ -456,6 +517,290 @@ public class ServletContextHandler extends ContextHandler
}
/* ------------------------------------------------------------ */
+ public static class JspPropertyGroup implements JspPropertyGroupDescriptor
+ {
+ private List<String> _urlPatterns = new ArrayList<String>();
+ private String _elIgnored;
+ private String _pageEncoding;
+ private String _scriptingInvalid;
+ private String _isXml;
+ private List<String> _includePreludes = new ArrayList<String>();
+ private List<String> _includeCodas = new ArrayList<String>();
+ private String _deferredSyntaxAllowedAsLiteral;
+ private String _trimDirectiveWhitespaces;
+ private String _defaultContentType;
+ private String _buffer;
+ private String _errorOnUndeclaredNamespace;
+
+
+
+ /**
+ * @see javax.servlet.descriptor.JspPropertyGroupDescriptor#getUrlPatterns()
+ */
+ public Collection<String> getUrlPatterns()
+ {
+ return new ArrayList<String>(_urlPatterns); // spec says must be a copy
+ }
+
+ public void addUrlPattern (String s)
+ {
+ if (!_urlPatterns.contains(s))
+ _urlPatterns.add(s);
+ }
+
+ /**
+ * @see javax.servlet.descriptor.JspPropertyGroupDescriptor#getElIgnored()
+ */
+ public String getElIgnored()
+ {
+ return _elIgnored;
+ }
+
+ public void setElIgnored (String s)
+ {
+ _elIgnored = s;
+ }
+
+ /**
+ * @see javax.servlet.descriptor.JspPropertyGroupDescriptor#getPageEncoding()
+ */
+ public String getPageEncoding()
+ {
+ return _pageEncoding;
+ }
+
+ public void setPageEncoding(String pageEncoding)
+ {
+ _pageEncoding = pageEncoding;
+ }
+
+ public void setScriptingInvalid(String scriptingInvalid)
+ {
+ _scriptingInvalid = scriptingInvalid;
+ }
+
+ public void setIsXml(String isXml)
+ {
+ _isXml = isXml;
+ }
+
+ public void setDeferredSyntaxAllowedAsLiteral(String deferredSyntaxAllowedAsLiteral)
+ {
+ _deferredSyntaxAllowedAsLiteral = deferredSyntaxAllowedAsLiteral;
+ }
+
+ public void setTrimDirectiveWhitespaces(String trimDirectiveWhitespaces)
+ {
+ _trimDirectiveWhitespaces = trimDirectiveWhitespaces;
+ }
+
+ public void setDefaultContentType(String defaultContentType)
+ {
+ _defaultContentType = defaultContentType;
+ }
+
+ public void setBuffer(String buffer)
+ {
+ _buffer = buffer;
+ }
+
+ public void setErrorOnUndeclaredNamespace(String errorOnUndeclaredNamespace)
+ {
+ _errorOnUndeclaredNamespace = errorOnUndeclaredNamespace;
+ }
+
+ /**
+ * @see javax.servlet.descriptor.JspPropertyGroupDescriptor#getScriptingInvalid()
+ */
+ public String getScriptingInvalid()
+ {
+ return _scriptingInvalid;
+ }
+
+ /**
+ * @see javax.servlet.descriptor.JspPropertyGroupDescriptor#getIsXml()
+ */
+ public String getIsXml()
+ {
+ return _isXml;
+ }
+
+ /**
+ * @see javax.servlet.descriptor.JspPropertyGroupDescriptor#getIncludePreludes()
+ */
+ public Collection<String> getIncludePreludes()
+ {
+ return new ArrayList<String>(_includePreludes); //must be a copy
+ }
+
+ public void addIncludePrelude(String prelude)
+ {
+ if (!_includePreludes.contains(prelude))
+ _includePreludes.add(prelude);
+ }
+
+ /**
+ * @see javax.servlet.descriptor.JspPropertyGroupDescriptor#getIncludeCodas()
+ */
+ public Collection<String> getIncludeCodas()
+ {
+ return new ArrayList<String>(_includeCodas); //must be a copy
+ }
+
+ public void addIncludeCoda (String coda)
+ {
+ if (!_includeCodas.contains(coda))
+ _includeCodas.add(coda);
+ }
+
+ /**
+ * @see javax.servlet.descriptor.JspPropertyGroupDescriptor#getDeferredSyntaxAllowedAsLiteral()
+ */
+ public String getDeferredSyntaxAllowedAsLiteral()
+ {
+ return _deferredSyntaxAllowedAsLiteral;
+ }
+
+ /**
+ * @see javax.servlet.descriptor.JspPropertyGroupDescriptor#getTrimDirectiveWhitespaces()
+ */
+ public String getTrimDirectiveWhitespaces()
+ {
+ return _trimDirectiveWhitespaces;
+ }
+
+ /**
+ * @see javax.servlet.descriptor.JspPropertyGroupDescriptor#getDefaultContentType()
+ */
+ public String getDefaultContentType()
+ {
+ return _defaultContentType;
+ }
+
+ /**
+ * @see javax.servlet.descriptor.JspPropertyGroupDescriptor#getBuffer()
+ */
+ public String getBuffer()
+ {
+ return _buffer;
+ }
+
+ /**
+ * @see javax.servlet.descriptor.JspPropertyGroupDescriptor#getErrorOnUndeclaredNamespace()
+ */
+ public String getErrorOnUndeclaredNamespace()
+ {
+ return _errorOnUndeclaredNamespace;
+ }
+
+ public String toString ()
+ {
+ StringBuffer sb = new StringBuffer();
+ sb.append("JspPropertyGroupDescriptor:");
+ sb.append(" el-ignored="+_elIgnored);
+ sb.append(" is-xml="+_isXml);
+ sb.append(" page-encoding="+_pageEncoding);
+ sb.append(" scripting-invalid="+_scriptingInvalid);
+ sb.append(" deferred-syntax-allowed-as-literal="+_deferredSyntaxAllowedAsLiteral);
+ sb.append(" trim-directive-whitespaces"+_trimDirectiveWhitespaces);
+ sb.append(" default-content-type="+_defaultContentType);
+ sb.append(" buffer="+_buffer);
+ sb.append(" error-on-undeclared-namespace="+_errorOnUndeclaredNamespace);
+ for (String prelude:_includePreludes)
+ sb.append(" include-prelude="+prelude);
+ for (String coda:_includeCodas)
+ sb.append(" include-coda="+coda);
+ return sb.toString();
+ }
+ }
+
+ /* ------------------------------------------------------------ */
+ public static class TagLib implements TaglibDescriptor
+ {
+ private String _uri;
+ private String _location;
+
+ /**
+ * @see javax.servlet.descriptor.TaglibDescriptor#getTaglibURI()
+ */
+ public String getTaglibURI()
+ {
+ return _uri;
+ }
+
+ public void setTaglibURI(String uri)
+ {
+ _uri = uri;
+ }
+
+ /**
+ * @see javax.servlet.descriptor.TaglibDescriptor#getTaglibLocation()
+ */
+ public String getTaglibLocation()
+ {
+ return _location;
+ }
+
+ public void setTaglibLocation(String location)
+ {
+ _location = location;
+ }
+
+ public String toString()
+ {
+ return ("TagLibDescriptor: taglib-uri="+_uri+" location="+_location);
+ }
+ }
+
+
+ /* ------------------------------------------------------------ */
+ public static class JspConfig implements JspConfigDescriptor
+ {
+ private List<TaglibDescriptor> _taglibs = new ArrayList<TaglibDescriptor>();
+ private List<JspPropertyGroupDescriptor> _jspPropertyGroups = new ArrayList<JspPropertyGroupDescriptor>();
+
+ public JspConfig() {}
+
+ /**
+ * @see javax.servlet.descriptor.JspConfigDescriptor#getTaglibs()
+ */
+ public Collection<TaglibDescriptor> getTaglibs()
+ {
+ return new ArrayList<TaglibDescriptor>(_taglibs);
+ }
+
+ public void addTaglibDescriptor (TaglibDescriptor d)
+ {
+ _taglibs.add(d);
+ }
+
+ /**
+ * @see javax.servlet.descriptor.JspConfigDescriptor#getJspPropertyGroups()
+ */
+ public Collection<JspPropertyGroupDescriptor> getJspPropertyGroups()
+ {
+ return new ArrayList<JspPropertyGroupDescriptor>(_jspPropertyGroups);
+ }
+
+ public void addJspPropertyGroup(JspPropertyGroupDescriptor g)
+ {
+ _jspPropertyGroups.add(g);
+ }
+
+ public String toString()
+ {
+ StringBuffer sb = new StringBuffer();
+ sb.append("JspConfigDescriptor: \n");
+ for (TaglibDescriptor taglib:_taglibs)
+ sb.append(taglib+"\n");
+ for (JspPropertyGroupDescriptor jpg:_jspPropertyGroups)
+ sb.append(jpg+"\n");
+ return sb.toString();
+ }
+ }
+
+
+ /* ------------------------------------------------------------ */
public class Context extends ContextHandler.Context
{
/* ------------------------------------------------------------ */
@@ -466,7 +811,10 @@ public class ServletContextHandler extends ContextHandler
public RequestDispatcher getNamedDispatcher(String name)
{
ContextHandler context=org.eclipse.jetty.servlet.ServletContextHandler.this;
- if (_servletHandler==null || _servletHandler.getServlet(name)==null)
+ if (_servletHandler==null)
+ return null;
+ ServletHolder holder = _servletHandler.getServlet(name);
+ if (holder==null || !holder.isEnabled())
return null;
return new Dispatcher(context, name);
}
@@ -475,34 +823,68 @@ public class ServletContextHandler extends ContextHandler
/**
* @since servlet-api-3.0
*/
+ @Override
public FilterRegistration.Dynamic addFilter(String filterName, Class<? extends Filter> filterClass)
{
if (isStarted())
throw new IllegalStateException();
+
+ if (!_enabled)
+ throw new UnsupportedOperationException();
final ServletHandler handler = ServletContextHandler.this.getServletHandler();
- final FilterHolder holder= handler.newFilterHolder();
- holder.setName(filterName);
- holder.setHeldClass(filterClass);
- handler.addFilter(holder);
- return holder.getRegistration();
+ FilterHolder holder = handler.getFilter(filterName);
+ if (holder == null)
+ {
+ //new filter
+ holder = handler.newFilterHolder(Holder.Source.JAVAX_API);
+ holder.setName(filterName);
+ holder.setHeldClass(filterClass);
+ handler.addFilter(holder);
+ return holder.getRegistration();
+ }
+ if (holder.getClassName()==null && holder.getHeldClass()==null)
+ {
+ //preliminary filter registration completion
+ holder.setHeldClass(filterClass);
+ return holder.getRegistration();
+ }
+ else
+ return null; //existing filter
}
/* ------------------------------------------------------------ */
/**
* @since servlet-api-3.0
*/
+ @Override
public FilterRegistration.Dynamic addFilter(String filterName, String className)
{
if (isStarted())
throw new IllegalStateException();
+
+ if (!_enabled)
+ throw new UnsupportedOperationException();
final ServletHandler handler = ServletContextHandler.this.getServletHandler();
- final FilterHolder holder= handler.newFilterHolder();
- holder.setName(filterName);
- holder.setClassName(className);
- handler.addFilter(holder);
- return holder.getRegistration();
+ FilterHolder holder = handler.getFilter(filterName);
+ if (holder == null)
+ {
+ //new filter
+ holder = handler.newFilterHolder(Holder.Source.JAVAX_API);
+ holder.setName(filterName);
+ holder.setClassName(className);
+ handler.addFilter(holder);
+ return holder.getRegistration();
+ }
+ if (holder.getClassName()==null && holder.getHeldClass()==null)
+ {
+ //preliminary filter registration completion
+ holder.setClassName(className);
+ return holder.getRegistration();
+ }
+ else
+ return null; //existing filter
}
@@ -510,81 +892,160 @@ public class ServletContextHandler extends ContextHandler
/**
* @since servlet-api-3.0
*/
+ @Override
public FilterRegistration.Dynamic addFilter(String filterName, Filter filter)
{
if (isStarted())
throw new IllegalStateException();
+ if (!_enabled)
+ throw new UnsupportedOperationException();
+
final ServletHandler handler = ServletContextHandler.this.getServletHandler();
- final FilterHolder holder= handler.newFilterHolder();
- holder.setName(filterName);
- holder.setFilter(filter);
- handler.addFilter(holder);
- return holder.getRegistration();
+ FilterHolder holder = handler.getFilter(filterName);
+ if (holder == null)
+ {
+ //new filter
+ holder = handler.newFilterHolder(Holder.Source.JAVAX_API);
+ holder.setName(filterName);
+ holder.setFilter(filter);
+ handler.addFilter(holder);
+ return holder.getRegistration();
+ }
+
+ if (holder.getClassName()==null && holder.getHeldClass()==null)
+ {
+ //preliminary filter registration completion
+ holder.setFilter(filter);
+ return holder.getRegistration();
+ }
+ else
+ return null; //existing filter
}
/* ------------------------------------------------------------ */
/**
* @since servlet-api-3.0
*/
+ @Override
public ServletRegistration.Dynamic addServlet(String servletName, Class<? extends Servlet> servletClass)
{
if (!isStarting())
throw new IllegalStateException();
-
+
+ if (!_enabled)
+ throw new UnsupportedOperationException();
+
final ServletHandler handler = ServletContextHandler.this.getServletHandler();
- final ServletHolder holder= handler.newServletHolder();
- holder.setName(servletName);
- holder.setHeldClass(servletClass);
- handler.addServlet(holder);
- return holder.getRegistration();
+ ServletHolder holder = handler.getServlet(servletName);
+ if (holder == null)
+ {
+ //new servlet
+ holder = handler.newServletHolder(Holder.Source.JAVAX_API);
+ holder.setName(servletName);
+ holder.setHeldClass(servletClass);
+ handler.addServlet(holder);
+ return dynamicHolderAdded(holder);
+ }
+
+ //complete a partial registration
+ if (holder.getClassName()==null && holder.getHeldClass()==null)
+ {
+ holder.setHeldClass(servletClass);
+ return holder.getRegistration();
+ }
+ else
+ return null; //existing completed registration for servlet name
}
/* ------------------------------------------------------------ */
/**
* @since servlet-api-3.0
*/
+ @Override
public ServletRegistration.Dynamic addServlet(String servletName, String className)
{
if (!isStarting())
throw new IllegalStateException();
- final ServletHandler handler = ServletContextHandler.this.getServletHandler();
- final ServletHolder holder= handler.newServletHolder();
- holder.setName(servletName);
- holder.setClassName(className);
- handler.addServlet(holder);
- return holder.getRegistration();
+ if (!_enabled)
+ throw new UnsupportedOperationException();
+
+
+ final ServletHandler handler = ServletContextHandler.this.getServletHandler();
+ ServletHolder holder = handler.getServlet(servletName);
+ if (holder == null)
+ {
+ //new servlet
+ holder = handler.newServletHolder(Holder.Source.JAVAX_API);
+ holder.setName(servletName);
+ holder.setClassName(className);
+ handler.addServlet(holder);
+ return dynamicHolderAdded(holder);
+ }
+
+ //complete a partial registration
+ if (holder.getClassName()==null && holder.getHeldClass()==null)
+ {
+ holder.setClassName(className);
+ return holder.getRegistration();
+ }
+ else
+ return null; //existing completed registration for servlet name
}
/* ------------------------------------------------------------ */
/**
* @since servlet-api-3.0
*/
+ @Override
public ServletRegistration.Dynamic addServlet(String servletName, Servlet servlet)
{
if (!isStarting())
throw new IllegalStateException();
+ if (!_enabled)
+ throw new UnsupportedOperationException();
+
+ //TODO handle partial registrations
+
final ServletHandler handler = ServletContextHandler.this.getServletHandler();
- final ServletHolder holder= handler.newServletHolder();
- holder.setName(servletName);
- holder.setServlet(servlet);
- handler.addServlet(holder);
- return holder.getRegistration();
+ ServletHolder holder = handler.getServlet(servletName);
+ if (holder == null)
+ {
+ holder = handler.newServletHolder(Holder.Source.JAVAX_API);
+ holder.setName(servletName);
+ holder.setServlet(servlet);
+ handler.addServlet(holder);
+ return dynamicHolderAdded(holder);
+ }
+
+ //complete a partial registration
+ if (holder.getClassName()==null && holder.getHeldClass()==null)
+ {
+ holder.setServlet(servlet);
+ return holder.getRegistration();
+ }
+ else
+ return null; //existing completed registration for servlet name
}
/* ------------------------------------------------------------ */
+ @Override
public boolean setInitParameter(String name, String value)
{
// TODO other started conditions
if (!isStarting())
throw new IllegalStateException();
+ if (!_enabled)
+ throw new UnsupportedOperationException();
+
return super.setInitParameter(name,value);
}
/* ------------------------------------------------------------ */
+ @Override
public <T extends Filter> T createFilter(Class<T> c) throws ServletException
{
try
@@ -608,6 +1069,7 @@ public class ServletContextHandler extends ContextHandler
}
/* ------------------------------------------------------------ */
+ @Override
public <T extends Servlet> T createServlet(Class<T> c) throws ServletException
{
try
@@ -629,16 +1091,39 @@ public class ServletContextHandler extends ContextHandler
throw new ServletException(e);
}
}
-
+
+ @Override
+ public Set<SessionTrackingMode> getDefaultSessionTrackingModes()
+ {
+ if (_sessionHandler!=null)
+ return _sessionHandler.getSessionManager().getDefaultSessionTrackingModes();
+ return null;
+ }
+
+ @Override
+ public Set<SessionTrackingMode> getEffectiveSessionTrackingModes()
+ {
+ if (_sessionHandler!=null)
+ return _sessionHandler.getSessionManager().getEffectiveSessionTrackingModes();
+ return null;
+ }
+
+ @Override
public FilterRegistration getFilterRegistration(String filterName)
- {
+ {
+ if (!_enabled)
+ throw new UnsupportedOperationException();
+
final FilterHolder holder=ServletContextHandler.this.getServletHandler().getFilter(filterName);
return (holder==null)?null:holder.getRegistration();
}
-
+ @Override
public Map<String, ? extends FilterRegistration> getFilterRegistrations()
{
+ if (!_enabled)
+ throw new UnsupportedOperationException();
+
HashMap<String, FilterRegistration> registrations = new HashMap<String, FilterRegistration>();
ServletHandler handler=ServletContextHandler.this.getServletHandler();
FilterHolder[] holders=handler.getFilters();
@@ -650,16 +1135,22 @@ public class ServletContextHandler extends ContextHandler
return registrations;
}
-
+ @Override
public ServletRegistration getServletRegistration(String servletName)
- {
+ {
+ if (!_enabled)
+ throw new UnsupportedOperationException();
+
final ServletHolder holder=ServletContextHandler.this.getServletHandler().getServlet(servletName);
return (holder==null)?null:holder.getRegistration();
}
-
+ @Override
public Map<String, ? extends ServletRegistration> getServletRegistrations()
- {
+ {
+ if (!_enabled)
+ throw new UnsupportedOperationException();
+
HashMap<String, ServletRegistration> registrations = new HashMap<String, ServletRegistration>();
ServletHandler handler=ServletContextHandler.this.getServletHandler();
ServletHolder[] holders=handler.getServlets();
@@ -671,67 +1162,71 @@ public class ServletContextHandler extends ContextHandler
return registrations;
}
-
+ @Override
+ public SessionCookieConfig getSessionCookieConfig()
+ {
+ // TODO other started conditions
+ if (!_enabled)
+ throw new UnsupportedOperationException();
+
+ if (_sessionHandler!=null)
+ return _sessionHandler.getSessionManager().getSessionCookieConfig();
+ return null;
+ }
+
+ @Override
+ public void setSessionTrackingModes(Set<SessionTrackingMode> sessionTrackingModes)
+ {
+ // TODO other started conditions
+ if (!isStarting())
+ throw new IllegalStateException();
+ if (!_enabled)
+ throw new UnsupportedOperationException();
+
+
+ if (_sessionHandler!=null)
+ _sessionHandler.getSessionManager().setSessionTrackingModes(sessionTrackingModes);
+ }
+
+ @Override
public void addListener(String className)
{
// TODO other started conditions
if (!isStarting())
throw new IllegalStateException();
- try
- {
- Class<? extends EventListener> clazz = getClassLoader()==null?Loader.loadClass(ContextHandler.class,className):getClassLoader().loadClass(className);
- addListener(clazz);
- }
- catch (ClassNotFoundException e)
- {
- throw new IllegalArgumentException(e);
- }
+ if (!_enabled)
+ throw new UnsupportedOperationException();
+ super.addListener(className);
}
-
+ @Override
public <T extends EventListener> void addListener(T t)
{
+ // TODO other started conditions
if (!isStarting())
throw new IllegalStateException();
-
- ServletContextHandler.this.addEventListener(t);
+ if (!_enabled)
+ throw new UnsupportedOperationException();
+ super.addListener(t);
}
-
+ @Override
public void addListener(Class<? extends EventListener> listenerClass)
{
+ // TODO other started conditions
if (!isStarting())
throw new IllegalStateException();
-
- try
- {
- EventListener l = createListener(listenerClass);
- ServletContextHandler.this.addEventListener(l);
- }
- catch (ServletException e)
- {
- throw new IllegalStateException(e);
- }
+ if (!_enabled)
+ throw new UnsupportedOperationException();
+ super.addListener(listenerClass);
}
-
+ @Override
public <T extends EventListener> T createListener(Class<T> clazz) throws ServletException
{
try
{
- T l = null;
- try
- {
- l = clazz.newInstance();
- }
- catch (InstantiationException e)
- {
- throw new ServletException(e);
- }
- catch (IllegalAccessException e)
- {
- throw new ServletException(e);
- }
+ T l = super.createListener(clazz);
for (int i=_decorators.size()-1; i>=0; i--)
{
@@ -750,26 +1245,36 @@ public class ServletContextHandler extends ContextHandler
}
}
-
+
+ @Override
+ public JspConfigDescriptor getJspConfigDescriptor()
+ {
+ return _jspConfig;
+ }
+
+ @Override
+ public void setJspConfigDescriptor(JspConfigDescriptor d)
+ {
+ _jspConfig = d;
+ }
+
+
+ @Override
public void declareRoles(String... roleNames)
{
if (!isStarting())
throw new IllegalStateException();
-
- //Get a reference to the SecurityHandler, which must be ConstraintAware
- if (_securityHandler != null && _securityHandler instanceof ConstraintAware)
- {
- HashSet<String> union = new HashSet<String>();
- Set<String> existing = ((ConstraintAware)_securityHandler).getRoles();
- if (existing != null)
- union.addAll(existing);
- union.addAll(Arrays.asList(roleNames));
- ((ConstraintSecurityHandler)_securityHandler).setRoles(union);
- }
+ if (!_enabled)
+ throw new UnsupportedOperationException();
+ addRoles(roleNames);
+
+
}
+
}
-
-
+
+
+
/* ------------------------------------------------------------ */
/** Interface to decorate loaded classes.
*/
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 b0812c544b..dfc1d2ae67 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
@@ -21,8 +21,11 @@ package org.eclipse.jetty.servlet;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
+import java.util.Collections;
import java.util.EnumSet;
import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Set;
import java.util.List;
import java.util.Map;
import java.util.Queue;
@@ -30,14 +33,18 @@ import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentLinkedQueue;
import java.util.concurrent.ConcurrentMap;
+import javax.servlet.AsyncContext;
+import javax.servlet.DispatcherType;
import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.RequestDispatcher;
import javax.servlet.Servlet;
import javax.servlet.ServletContext;
import javax.servlet.ServletException;
+import javax.servlet.ServletRegistration;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
+import javax.servlet.ServletSecurityElement;
import javax.servlet.UnavailableException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
@@ -51,7 +58,7 @@ import org.eclipse.jetty.security.IdentityService;
import org.eclipse.jetty.security.SecurityHandler;
import org.eclipse.jetty.server.AbstractHttpConnection;
import org.eclipse.jetty.server.Dispatcher;
-import org.eclipse.jetty.server.DispatcherType;
+import org.eclipse.jetty.server.AbstractHttpConnection;
import org.eclipse.jetty.server.Request;
import org.eclipse.jetty.server.Server;
import org.eclipse.jetty.server.ServletRequestHttpWrapper;
@@ -279,6 +286,7 @@ public class ServletHandler extends ScopedHandler
*/
public ServletMapping getServletMapping(String pattern)
{
+ ServletMapping theMapping = null;
if (_servletMappings!=null)
{
for (ServletMapping m:_servletMappings)
@@ -289,12 +297,12 @@ public class ServletHandler extends ScopedHandler
for (String path:paths)
{
if (pattern.equals(path))
- return m;
+ theMapping = m;
}
}
}
}
- return null;
+ return theMapping;
}
/* ------------------------------------------------------------ */
@@ -336,8 +344,8 @@ public class ServletHandler extends ScopedHandler
String servlet_path_spec=(String)entry.getKey();
String servlet_path=entry.getMapped()!=null?entry.getMapped():PathMap.pathMatch(servlet_path_spec,target);
- String path_info=PathMap.pathInfo(servlet_path_spec,target);
-
+ String path_info=PathMap.pathInfo(servlet_path_spec,target);
+
if (DispatcherType.INCLUDE.equals(type))
{
baseRequest.setAttribute(Dispatcher.INCLUDE_SERVLET_PATH,servlet_path);
@@ -355,7 +363,7 @@ public class ServletHandler extends ScopedHandler
// look for a servlet by name!
servlet_holder=(ServletHolder)_servletNameMap.get(target);
}
-
+
if (LOG.isDebugEnabled())
LOG.debug("servlet {}|{}|{} -> {}",baseRequest.getContextPath(),baseRequest.getServletPath(),baseRequest.getPathInfo(),servlet_holder);
@@ -761,12 +769,13 @@ public class ServletHandler extends ScopedHandler
/**
* see also newServletHolder(Class)
*/
- public ServletHolder newServletHolder()
+ public ServletHolder newServletHolder(Holder.Source source)
{
- return new ServletHolder();
+ return new ServletHolder(source);
}
/* ------------------------------------------------------------ */
+ /** Convenience method to add a servlet Holder.
public ServletHolder newServletHolder(Class<? extends Servlet> servlet)
{
return new ServletHolder(servlet);
@@ -791,7 +800,7 @@ public class ServletHandler extends ScopedHandler
*/
public ServletHolder addServletWithMapping (Class<? extends Servlet> servlet,String pathSpec)
{
- ServletHolder holder = newServletHolder();
+ ServletHolder holder = newServletHolder(Holder.Source.EMBEDDED);
holder.setHeldClass(servlet);
setServlets((ServletHolder[])LazyList.addToArray(getServlets(), holder, ServletHolder.class));
addServletWithMapping(holder,pathSpec);
@@ -846,23 +855,23 @@ public class ServletHandler extends ScopedHandler
{
setServletMappings((ServletMapping[])LazyList.addToArray(getServletMappings(), mapping, ServletMapping.class));
}
-
- /* ------------------------------------------------------------ */
- public FilterHolder newFilterHolder(Class<? extends Filter> filter)
- {
- return new FilterHolder(filter);
+
+ public Set<String> setServletSecurity(ServletRegistration.Dynamic registration, ServletSecurityElement servletSecurityElement) {
+ if (_contextHandler != null) {
+ return _contextHandler.setServletSecurity(registration, servletSecurityElement);
+ }
+ return Collections.emptySet();
}
-
+
/* ------------------------------------------------------------ */
/**
* @see #newFilterHolder(Class)
*/
- public FilterHolder newFilterHolder()
+ public FilterHolder newFilterHolder(Holder.Source source)
{
- return new FilterHolder();
+ return new FilterHolder(source);
}
-
/* ------------------------------------------------------------ */
public FilterHolder getFilter(String name)
{
@@ -879,7 +888,7 @@ public class ServletHandler extends ScopedHandler
*/
public FilterHolder addFilterWithMapping (Class<? extends Filter> filter,String pathSpec,EnumSet<DispatcherType> dispatches)
{
- FilterHolder holder = newFilterHolder();
+ FilterHolder holder = newFilterHolder(Holder.Source.EMBEDDED);
holder.setHeldClass(filter);
addFilterWithMapping(holder,pathSpec,dispatches);
@@ -895,7 +904,7 @@ public class ServletHandler extends ScopedHandler
*/
public FilterHolder addFilterWithMapping (String className,String pathSpec,EnumSet<DispatcherType> dispatches)
{
- FilterHolder holder = newFilterHolder();
+ FilterHolder holder = newFilterHolder(Holder.Source.EMBEDDED);
holder.setName(className+"-"+_filters.length);
holder.setClassName(className);
@@ -938,7 +947,6 @@ public class ServletHandler extends ScopedHandler
}
-
/* ------------------------------------------------------------ */
/** Convenience method to add a filter.
* @param filter class of filter to create
@@ -948,7 +956,8 @@ public class ServletHandler extends ScopedHandler
*/
public FilterHolder addFilterWithMapping (Class<? extends Filter> filter,String pathSpec,int dispatches)
{
- FilterHolder holder = newFilterHolder(filter);
+ FilterHolder holder = newFilterHolder(Holder.Source.EMBEDDED);
+ holder.setHeldClass(filter);
addFilterWithMapping(holder,pathSpec,dispatches);
return holder;
@@ -1006,14 +1015,13 @@ public class ServletHandler extends ScopedHandler
}
-
/* ------------------------------------------------------------ */
/** Convenience method to add a filter with a mapping
* @param className
* @param pathSpec
* @param dispatches
* @return the filter holder created
- * @deprecated use {@link #addFilterWithMapping(Class, String, int)} instead
+ * @deprecated use {@link #addFilterWithMapping(Class, String, EnumSet<DispatcherType>)} instead
*/
public FilterHolder addFilter (String className,String pathSpec,EnumSet<DispatcherType> dispatches)
{
@@ -1152,7 +1160,7 @@ public class ServletHandler extends ScopedHandler
ServletHolder servlet_holder = (ServletHolder)_servletNameMap.get(_servletMappings[i].getServletName());
if (servlet_holder==null)
throw new IllegalStateException("No such servlet: "+_servletMappings[i].getServletName());
- else if (_servletMappings[i].getPathSpecs()!=null)
+ else if (servlet_holder.isEnabled() && _servletMappings[i].getPathSpecs()!=null)
{
String[] pathSpecs = _servletMappings[i].getPathSpecs();
for (int j=0;j<pathSpecs.length;j++)
@@ -1185,7 +1193,7 @@ public class ServletHandler extends ScopedHandler
try
{
- if (isStarted())
+ if (_contextHandler!=null && _contextHandler.isStarted() || _contextHandler==null && isStarted())
initialize();
}
catch (Exception e)
@@ -1262,7 +1270,6 @@ public class ServletHandler extends ScopedHandler
invalidateChainsCache();
}
-
/* ------------------------------------------------------------ */
/* ------------------------------------------------------------ */
private class CachedChain implements FilterChain
diff --git a/jetty-servlet/src/main/java/org/eclipse/jetty/servlet/ServletHolder.java b/jetty-servlet/src/main/java/org/eclipse/jetty/servlet/ServletHolder.java
index 7f2372bcf1..d3499f62c1 100644
--- a/jetty-servlet/src/main/java/org/eclipse/jetty/servlet/ServletHolder.java
+++ b/jetty-servlet/src/main/java/org/eclipse/jetty/servlet/ServletHolder.java
@@ -19,9 +19,6 @@
package org.eclipse.jetty.servlet;
import java.io.IOException;
-import java.io.PrintStream;
-import java.lang.reflect.InvocationTargetException;
-import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
@@ -33,12 +30,15 @@ import java.util.Map;
import java.util.Set;
import java.util.Stack;
+import javax.servlet.MultipartConfigElement;
import javax.servlet.Servlet;
import javax.servlet.ServletConfig;
-import javax.servlet.ServletContext;
import javax.servlet.ServletException;
+import javax.servlet.ServletRegistration;
+import javax.servlet.ServletContext;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
+import javax.servlet.ServletSecurityElement;
import javax.servlet.SingleThreadModel;
import javax.servlet.UnavailableException;
@@ -47,7 +47,6 @@ import org.eclipse.jetty.security.RunAsToken;
import org.eclipse.jetty.server.Request;
import org.eclipse.jetty.server.UserIdentity;
import org.eclipse.jetty.server.handler.ContextHandler;
-import org.eclipse.jetty.servlet.api.ServletRegistration;
import org.eclipse.jetty.util.Loader;
import org.eclipse.jetty.util.log.Log;
import org.eclipse.jetty.util.log.Logger;
@@ -82,6 +81,7 @@ public class ServletHolder extends Holder<Servlet> implements UserIdentity.Scope
private transient Servlet _servlet;
private transient Config _config;
private transient long _unavailable;
+ private transient boolean _enabled = true;
private transient UnavailableException _unavailableEx;
public static final Map<String,String> NO_MAPPED_ROLES = Collections.emptyMap();
@@ -90,32 +90,32 @@ public class ServletHolder extends Holder<Servlet> implements UserIdentity.Scope
*/
public ServletHolder()
{
+ super (Source.EMBEDDED);
}
-
/* ---------------------------------------------------------------- */
- /** Constructor for existing servlet.
+ /** Constructor .
*/
- public ServletHolder(String name,Servlet servlet)
+ public ServletHolder(Holder.Source creator)
{
- setName(name);
- setServlet(servlet);
+ super (creator);
}
-
/* ---------------------------------------------------------------- */
/** Constructor for existing servlet.
*/
public ServletHolder(Servlet servlet)
{
+ super (Source.EMBEDDED);
setServlet(servlet);
}
/* ---------------------------------------------------------------- */
/** Constructor for servlet class.
*/
- public ServletHolder(String name,Class<? extends Servlet> servlet)
+ public ServletHolder(String name, Class<? extends Servlet> servlet)
{
+ super (Source.EMBEDDED);
setName(name);
setHeldClass(servlet);
}
@@ -123,8 +123,19 @@ public class ServletHolder extends Holder<Servlet> implements UserIdentity.Scope
/* ---------------------------------------------------------------- */
/** Constructor for servlet class.
*/
+ public ServletHolder(String name, Servlet servlet)
+ {
+ super (Source.EMBEDDED);
+ setName(name);
+ setServlet(servlet);
+ }
+
+ /* ---------------------------------------------------------------- */
+ /** Constructor for servlet class.
+ */
public ServletHolder(Class<? extends Servlet> servlet)
{
+ super (Source.EMBEDDED);
setHeldClass(servlet);
}
@@ -262,20 +273,47 @@ public class ServletHolder extends Holder<Servlet> implements UserIdentity.Scope
_forcedPath = forcedPath;
}
+ public boolean isEnabled()
+ {
+ return _enabled;
+ }
+
+
+ public void setEnabled(boolean enabled)
+ {
+ _enabled = enabled;
+ }
+
+
/* ------------------------------------------------------------ */
public void doStart()
throws Exception
{
_unavailable=0;
+ if (!_enabled)
+ return;
+ //check servlet has a class (ie is not a preliminary registration). If preliminary, fail startup.
try
{
super.doStart();
+ }
+ catch (UnavailableException ue)
+ {
+ makeUnavailable(ue);
+ throw ue;
+ }
+
+ try
+ {
checkServletType();
}
catch (UnavailableException ue)
{
makeUnavailable(ue);
+ if (!_servletHandler.isStartWithUnavailable())
+ throw ue; //servlet is not an instance of javax.servlet.Servlet
}
+
_identityService = _servletHandler.getIdentityService();
if (_identityService!=null && _runAsRole!=null)
@@ -472,12 +510,13 @@ public class ServletHolder extends Holder<Servlet> implements UserIdentity.Scope
// Handle configuring servlets that implement org.apache.jasper.servlet.JspServlet
if (isJspServlet())
+ {
initJspServlet();
+ }
- _servlet.init(_config);
+ initMultiPart();
- if (isJspServlet())
- postInitJspServlet();
+ _servlet.init(_config);
}
catch (UnavailableException e)
{
@@ -533,52 +572,26 @@ public class ServletHolder extends Holder<Servlet> implements UserIdentity.Scope
}
}
- protected void postInitJspServlet() throws Exception
+ /* ------------------------------------------------------------ */
+ /**
+ * Register a ServletRequestListener that will ensure tmp multipart
+ * files are deleted when the request goes out of scope.
+ *
+ * @throws Exception
+ */
+ protected void initMultiPart () throws Exception
{
- try
+ //if this servlet can handle multipart requests, ensure tmp files will be
+ //cleaned up correctly
+ if (((Registration)getRegistration()).getMultipartConfig() != null)
{
- //Check that jasper's SystemLogHandler class is on the classpath
- Class systemLogHandlerClass = Loader.loadClass(this.getClass(), "org.apache.jasper.util.SystemLogHandler");
- PrintStream rootSystemLogHandler = null;
- while (systemLogHandlerClass.isAssignableFrom(System.err.getClass()))
- {
- rootSystemLogHandler = System.err;
- Method getWrapped = systemLogHandlerClass.getMethod("getWrapped", new Class[]{});
- PrintStream ps = (PrintStream)getWrapped.invoke(System.err, new Object[]{});
- System.setErr(ps);
- }
-
- if (rootSystemLogHandler != null)
- System.setErr(rootSystemLogHandler);
- }
- catch (ClassNotFoundException e)
- {
- //jasper not on classpath, ignore
- }
- catch (NoSuchMethodException e)
- {
- LOG.info("Problem unwrapping SystemLogHandler from System.err", e);
- }
- catch (SecurityException e)
- {
- LOG.warn("Problem unwrapping SystemLogHandler from System.err", e);
- }
- catch (IllegalAccessException e)
- {
- LOG.warn("Problem unwrapping SystemLogHandler from System.err", e);
- }
- catch (IllegalArgumentException e)
- {
- LOG.warn("Problem unwrapping SystemLogHandler from System.err", e);
- }
- catch (InvocationTargetException e)
- {
- LOG.warn("Problem unwrapping SystemLogHandler from System.err", e);
+ //Register a listener to delete tmp files that are created as a result of this
+ //servlet calling Request.getPart() or Request.getParts()
+ ContextHandler ch = ((ContextHandler.Context)getServletHandler().getServletContext()).getContextHandler();
+ ch.addEventListener(new Request.MultiPartCleanerListener());
}
-
}
-
/* ------------------------------------------------------------ */
/**
* @see org.eclipse.jetty.server.UserIdentity.Scope#getContextPath()
@@ -645,10 +658,14 @@ public class ServletHolder extends Holder<Servlet> implements UserIdentity.Scope
// Handle run as
if (_identityService!=null)
old_run_as=_identityService.setRunAs(baseRequest.getResolvedUserIdentity(),_runAsToken);
-
+
if (!isAsyncSupported())
baseRequest.setAsyncSupported(false);
-
+
+ MultipartConfigElement mpce = ((Registration)getRegistration()).getMultipartConfig();
+ if (mpce != null)
+ request.setAttribute(Request.__MULTIPART_CONFIG_ELEMENT, mpce);
+
servlet.service(request,response);
servlet_error=false;
}
@@ -717,24 +734,33 @@ public class ServletHolder extends Holder<Servlet> implements UserIdentity.Scope
/* -------------------------------------------------------- */
/* -------------------------------------------------------- */
public class Registration extends HolderRegistration implements ServletRegistration.Dynamic
- {
+ {
+ protected MultipartConfigElement _multipartConfig;
+
public Set<String> addMapping(String... urlPatterns)
{
illegalStateIfContextStarted();
Set<String> clash=null;
for (String pattern : urlPatterns)
{
- if (_servletHandler.getServletMapping(pattern)!=null)
+ ServletMapping mapping = _servletHandler.getServletMapping(pattern);
+ if (mapping!=null)
{
- if (clash==null)
- clash=new HashSet<String>();
- clash.add(pattern);
+ //if the servlet mapping was from a default descriptor, then allow it to be overridden
+ if (!mapping.isDefault())
+ {
+ if (clash==null)
+ clash=new HashSet<String>();
+ clash.add(pattern);
+ }
}
}
+ //if there were any clashes amongst the urls, return them
if (clash!=null)
return clash;
+ //otherwise apply all of them
ServletMapping mapping = new ServletMapping();
mapping.setServletName(ServletHolder.this.getName());
mapping.setPathSpecs(urlPatterns);
@@ -747,22 +773,27 @@ public class ServletHolder extends Holder<Servlet> implements UserIdentity.Scope
{
ServletMapping[] mappings =_servletHandler.getServletMappings();
List<String> patterns=new ArrayList<String>();
- for (ServletMapping mapping : mappings)
+ if (mappings!=null)
{
- if (!mapping.getServletName().equals(getName()))
- continue;
- String[] specs=mapping.getPathSpecs();
- if (specs!=null && specs.length>0)
- patterns.addAll(Arrays.asList(specs));
+ for (ServletMapping mapping : mappings)
+ {
+ if (!mapping.getServletName().equals(getName()))
+ continue;
+ String[] specs=mapping.getPathSpecs();
+ if (specs!=null && specs.length>0)
+ patterns.addAll(Arrays.asList(specs));
+ }
}
return patterns;
}
+ @Override
public String getRunAsRole()
{
return _runAsRole;
}
+ @Override
public void setLoadOnStartup(int loadOnStartup)
{
illegalStateIfContextStarted();
@@ -773,17 +804,35 @@ public class ServletHolder extends Holder<Servlet> implements UserIdentity.Scope
{
return ServletHolder.this.getInitOrder();
}
-
+
+ @Override
+ public void setMultipartConfig(MultipartConfigElement element)
+ {
+ _multipartConfig = element;
+ }
+
+ public MultipartConfigElement getMultipartConfig()
+ {
+ return _multipartConfig;
+ }
+
+ @Override
public void setRunAsRole(String role)
{
_runAsRole = role;
}
+
+ @Override
+ public Set<String> setServletSecurity(ServletSecurityElement securityElement)
+ {
+ return _servletHandler.setServletSecurity(this, securityElement);
+ }
}
public ServletRegistration.Dynamic getRegistration()
{
if (_registration == null)
- _registration = new Registration();
+ _registration = new Registration();
return _registration;
}
@@ -903,8 +952,3 @@ public class ServletHolder extends Holder<Servlet> implements UserIdentity.Scope
}
}
}
-
-
-
-
-
diff --git a/jetty-servlet/src/main/java/org/eclipse/jetty/servlet/ServletMapping.java b/jetty-servlet/src/main/java/org/eclipse/jetty/servlet/ServletMapping.java
index 03b6ead91f..f25000910c 100644
--- a/jetty-servlet/src/main/java/org/eclipse/jetty/servlet/ServletMapping.java
+++ b/jetty-servlet/src/main/java/org/eclipse/jetty/servlet/ServletMapping.java
@@ -26,6 +26,8 @@ public class ServletMapping
{
private String[] _pathSpecs;
private String _servletName;
+ private boolean _default;
+
/* ------------------------------------------------------------ */
public ServletMapping()
@@ -77,6 +79,25 @@ public class ServletMapping
_servletName = servletName;
}
+
+ /* ------------------------------------------------------------ */
+ /**
+ * @return
+ */
+ public boolean isDefault()
+ {
+ return _default;
+ }
+
+
+ /* ------------------------------------------------------------ */
+ /**
+ * @param default1
+ */
+ public void setDefault(boolean fromDefault)
+ {
+ _default = fromDefault;
+ }
/* ------------------------------------------------------------ */
public String toString()
diff --git a/jetty-servlet/src/main/java/org/eclipse/jetty/servlet/api/FilterRegistration.java b/jetty-servlet/src/main/java/org/eclipse/jetty/servlet/api/FilterRegistration.java
deleted file mode 100644
index d2c95838b1..0000000000
--- a/jetty-servlet/src/main/java/org/eclipse/jetty/servlet/api/FilterRegistration.java
+++ /dev/null
@@ -1,45 +0,0 @@
-//
-// ========================================================================
-// Copyright (c) 1995-2012 Mort Bay Consulting Pty. Ltd.
-// ------------------------------------------------------------------------
-// All rights reserved. This program and the accompanying materials
-// are made available under the terms of the Eclipse Public License v1.0
-// and Apache License v2.0 which accompanies this distribution.
-//
-// The Eclipse Public License is available at
-// http://www.eclipse.org/legal/epl-v10.html
-//
-// The Apache License v2.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.servlet.api;
-
-import java.util.Collection;
-import java.util.EnumSet;
-
-import org.eclipse.jetty.server.DispatcherType;
-
-/**
- * FilterRegistration
- *
- * Mimics the javax.servlet.FilterRegistration class to ease
- * jetty-7/jetty-8 compatibility
- */
-public interface FilterRegistration
-{
- public void addMappingForServletNames(EnumSet<DispatcherType> dispatcherTypes, boolean isMatchAfter, String... servletNames);
-
- public Collection<String> getServletNameMappings();
-
- public void addMappingForUrlPatterns(EnumSet<DispatcherType> dispatcherTypes, boolean isMatchAfter, String... urlPatterns);
-
- public Collection<String> getUrlPatternMappings();
-
- interface Dynamic extends FilterRegistration, Registration.Dynamic
- {
- }
-}
diff --git a/jetty-servlet/src/main/java/org/eclipse/jetty/servlet/api/Registration.java b/jetty-servlet/src/main/java/org/eclipse/jetty/servlet/api/Registration.java
deleted file mode 100644
index dca5eae41c..0000000000
--- a/jetty-servlet/src/main/java/org/eclipse/jetty/servlet/api/Registration.java
+++ /dev/null
@@ -1,43 +0,0 @@
-//
-// ========================================================================
-// Copyright (c) 1995-2012 Mort Bay Consulting Pty. Ltd.
-// ------------------------------------------------------------------------
-// All rights reserved. This program and the accompanying materials
-// are made available under the terms of the Eclipse Public License v1.0
-// and Apache License v2.0 which accompanies this distribution.
-//
-// The Eclipse Public License is available at
-// http://www.eclipse.org/legal/epl-v10.html
-//
-// The Apache License v2.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.servlet.api;
-
-import java.util.Map;
-import java.util.Set;
-
-public interface Registration
-{
-
- public String getName();
-
- public String getClassName();
-
- public boolean setInitParameter(String name, String value);
-
- public String getInitParameter(String name);
-
- public Set<String> setInitParameters(Map<String, String> initParameters);
-
- public Map<String, String> getInitParameters();
-
- interface Dynamic extends Registration
- {
- public void setAsyncSupported(boolean isAsyncSupported);
- }
-}
diff --git a/jetty-servlet/src/test/java/org/eclipse/jetty/servlet/AsyncContextTest.java b/jetty-servlet/src/test/java/org/eclipse/jetty/servlet/AsyncContextTest.java
index 8da745768a..a3707b39a6 100644
--- a/jetty-servlet/src/test/java/org/eclipse/jetty/servlet/AsyncContextTest.java
+++ b/jetty-servlet/src/test/java/org/eclipse/jetty/servlet/AsyncContextTest.java
@@ -27,6 +27,8 @@ import java.io.BufferedReader;
import java.io.IOException;
import java.io.StringReader;
+import javax.servlet.AsyncContext;
+import javax.servlet.DispatcherType;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
@@ -35,11 +37,8 @@ import javax.servlet.http.HttpServletResponseWrapper;
import junit.framework.Assert;
-import org.eclipse.jetty.continuation.ContinuationSupport;
-import org.eclipse.jetty.server.AsyncContext;
import org.eclipse.jetty.server.AsyncContinuation;
import org.eclipse.jetty.server.Connector;
-import org.eclipse.jetty.server.DispatcherType;
import org.eclipse.jetty.server.Handler;
import org.eclipse.jetty.server.LocalConnector;
import org.eclipse.jetty.server.Request;
@@ -89,9 +88,9 @@ public class AsyncContextTest
{
String request = "GET /servletPath HTTP/1.1\r\n" + "Host: localhost\r\n" + "Content-Type: application/x-www-form-urlencoded\r\n"
+ "Connection: close\r\n" + "\r\n";
-
String responseString = _connector.getResponses(request);
+
BufferedReader br = parseHeader(responseString);
Assert.assertEquals("servlet gets right path","doGet:getServletPath:/servletPath",br.readLine());
@@ -294,27 +293,18 @@ public class AsyncContextTest
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException
{
- AsyncContinuation continuation = (AsyncContinuation)ContinuationSupport.getContinuation(request);
-
if (request.getParameter("dispatch") != null)
- {
- continuation.suspend();
- continuation.dispatch("/servletPath2");
- // AsyncContext asyncContext = request.startAsync(request,response);
+ {
+ AsyncContext asyncContext = request.startAsync(request,response);
+ asyncContext.dispatch("/servletPath2");
}
else
{
response.getOutputStream().print("doGet:getServletPath:" + request.getServletPath() + "\n");
+ AsyncContext asyncContext = request.startAsync(request,response);
+ response.getOutputStream().print("doGet:async:getServletPath:" + ((HttpServletRequest)asyncContext.getRequest()).getServletPath() + "\n");
+ asyncContext.start(new AsyncRunnable(asyncContext));
- continuation.suspend();
-
- // AsyncContext asyncContext = request.startAsync(request,response);
-
- response.getOutputStream().print("doGet:async:getServletPath:" + ((HttpServletRequest)continuation.getRequest()).getServletPath() + "\n");
-
- Runnable runable = new AsyncRunnable(continuation);
- new Thread(runable).start();
- // asyncContext.start(new AsyncRunnable(asyncContext));
}
return;
@@ -328,49 +318,41 @@ public class AsyncContextTest
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException
{
- AsyncContinuation continuation = (AsyncContinuation)ContinuationSupport.getContinuation(request);
-
response.getOutputStream().print("doGet:getServletPath:" + request.getServletPath() + "\n");
-
- continuation.suspend();
- // AsyncContext asyncContext = request.startAsync(request, response);
-
- response.getOutputStream().print("doGet:async:getServletPath:" + ((HttpServletRequest)continuation.getRequest()).getServletPath() + "\n");
- Runnable runable = new AsyncRunnable(continuation);
- new Thread(runable).start();
- // asyncContext.start(new AsyncRunnable(asyncContext));
-
+ AsyncContext asyncContext = request.startAsync(request, response);
+ response.getOutputStream().print("doGet:async:getServletPath:" + ((HttpServletRequest)asyncContext.getRequest()).getServletPath() + "\n");
+ asyncContext.start(new AsyncRunnable(asyncContext));
return;
}
}
private class AsyncRunnable implements Runnable
{
- private AsyncContinuation _continuation;
+ private AsyncContext _context;
- public AsyncRunnable(AsyncContinuation continuation)
+ public AsyncRunnable(AsyncContext context)
{
- _continuation = continuation;
+ _context = context;
}
+ @Override
public void run()
{
- HttpServletRequest req = (HttpServletRequest)_continuation.getRequest();
-
+ HttpServletRequest req = (HttpServletRequest)_context.getRequest();
+
try
{
- _continuation.getResponse().getOutputStream().print("async:run:attr:servletPath:" + req.getAttribute(AsyncContext.ASYNC_SERVLET_PATH) + "\n");
- _continuation.getResponse().getOutputStream().print("async:run:attr:pathInfo:" + req.getAttribute(AsyncContext.ASYNC_PATH_INFO) + "\n");
- _continuation.getResponse().getOutputStream().print("async:run:attr:queryString:" + req.getAttribute(AsyncContext.ASYNC_QUERY_STRING) + "\n");
- _continuation.getResponse().getOutputStream().print("async:run:attr:contextPath:" + req.getAttribute(AsyncContext.ASYNC_CONTEXT_PATH) + "\n");
- _continuation.getResponse().getOutputStream().print("async:run:attr:requestURI:" + req.getAttribute(AsyncContext.ASYNC_REQUEST_URI) + "\n");
+ _context.getResponse().getOutputStream().print("async:run:attr:servletPath:" + req.getAttribute(AsyncContext.ASYNC_SERVLET_PATH) + "\n");
+ _context.getResponse().getOutputStream().print("async:run:attr:pathInfo:" + req.getAttribute(AsyncContext.ASYNC_PATH_INFO) + "\n");
+ _context.getResponse().getOutputStream().print("async:run:attr:queryString:" + req.getAttribute(AsyncContext.ASYNC_QUERY_STRING) + "\n");
+ _context.getResponse().getOutputStream().print("async:run:attr:contextPath:" + req.getAttribute(AsyncContext.ASYNC_CONTEXT_PATH) + "\n");
+ _context.getResponse().getOutputStream().print("async:run:attr:requestURI:" + req.getAttribute(AsyncContext.ASYNC_REQUEST_URI) + "\n");
}
catch (IOException e)
{
e.printStackTrace();
}
-
- _continuation.complete();
+ _context.complete();
}
}
diff --git a/jetty-servlet/src/test/java/org/eclipse/jetty/servlet/DefaultServletTest.java b/jetty-servlet/src/test/java/org/eclipse/jetty/servlet/DefaultServletTest.java
index fae6e0bfd1..fc211a0b23 100644
--- a/jetty-servlet/src/test/java/org/eclipse/jetty/servlet/DefaultServletTest.java
+++ b/jetty-servlet/src/test/java/org/eclipse/jetty/servlet/DefaultServletTest.java
@@ -23,7 +23,8 @@ import static org.junit.Assert.assertTrue;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
-
+import java.util.EnumSet;
+import javax.servlet.DispatcherType;
import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
@@ -562,7 +563,7 @@ public class DefaultServletTest
assertResponseContains("Content-Length: 12", response);
assertResponseNotContains("Extra Info", response);
- context.addFilter(OutputFilter.class, "/*", 0);
+ context.addFilter(OutputFilter.class,"/*",EnumSet.of(DispatcherType.REQUEST));
response = connector.getResponses("GET /context/data0.txt HTTP/1.1\r\nHost:localhost:8080\r\n\r\n");
assertResponseContains("Content-Length: 2", response); // 20 something long
assertResponseContains("Extra Info", response);
@@ -571,7 +572,7 @@ public class DefaultServletTest
context.getServletHandler().setFilterMappings(new FilterMapping[]{});
context.getServletHandler().setFilters(new FilterHolder[]{});
- context.addFilter(WriterFilter.class, "/*", 0);
+ context.addFilter(WriterFilter.class,"/*",EnumSet.of(DispatcherType.REQUEST));
response = connector.getResponses("GET /context/data0.txt HTTP/1.1\r\nHost:localhost:8080\r\n\r\n");
assertResponseContains("Content-Length: 2", response); // 20 something long
assertResponseContains("Extra Info", response);
diff --git a/jetty-servlet/src/test/java/org/eclipse/jetty/servlet/DispatcherTest.java b/jetty-servlet/src/test/java/org/eclipse/jetty/servlet/DispatcherTest.java
index d339511442..c14a9da7f5 100644
--- a/jetty-servlet/src/test/java/org/eclipse/jetty/servlet/DispatcherTest.java
+++ b/jetty-servlet/src/test/java/org/eclipse/jetty/servlet/DispatcherTest.java
@@ -24,9 +24,11 @@ import static org.junit.Assert.assertTrue;
import java.io.IOException;
import java.util.Arrays;
import java.util.Collections;
-import java.util.Enumeration;
+import java.util.EnumSet;
+import java.util.HashMap;
import java.util.List;
+import javax.servlet.DispatcherType;
import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
@@ -298,7 +300,7 @@ public class DispatcherTest
_contextHandler.addServlet(RogerThatServlet.class, "/*");
_contextHandler.addServlet(ReserveEchoServlet.class,"/recho/*");
_contextHandler.addServlet(EchoServlet.class, "/echo/*");
- _contextHandler.addFilter(ForwardFilter.class, "/*", FilterMapping.REQUEST);
+ _contextHandler.addFilter(ForwardFilter.class, "/*", EnumSet.of(DispatcherType.REQUEST));
String rogerResponse = _connector.getResponses("GET /context/ HTTP/1.0\n" + "Host: localhost\n\n");
diff --git a/jetty-servlet/src/test/java/org/eclipse/jetty/servlet/HolderTest.java b/jetty-servlet/src/test/java/org/eclipse/jetty/servlet/HolderTest.java
new file mode 100644
index 0000000000..a83882ded0
--- /dev/null
+++ b/jetty-servlet/src/test/java/org/eclipse/jetty/servlet/HolderTest.java
@@ -0,0 +1,95 @@
+//
+// ========================================================================
+// Copyright (c) 1995-2012 Mort Bay Consulting Pty. Ltd.
+// ------------------------------------------------------------------------
+// All rights reserved. This program and the accompanying materials
+// are made available under the terms of the Eclipse Public License v1.0
+// and Apache License v2.0 which accompanies this distribution.
+//
+// The Eclipse Public License is available at
+// http://www.eclipse.org/legal/epl-v10.html
+//
+// The Apache License v2.0 is available at
+// http://www.opensource.org/licenses/apache2.0.php
+//
+// You may elect to redistribute this code under either of these licenses.
+// ========================================================================
+//
+
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+
+package org.eclipse.jetty.servlet;
+
+import java.util.Collections;
+import java.util.Set;
+
+import javax.servlet.Registration;
+import javax.servlet.ServletRegistration;
+import org.junit.Test;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
+
+/**
+ * @version $Rev$ $Date$
+ */
+public class HolderTest {
+
+ @Test
+ public void testInitParams() throws Exception {
+ ServletHolder holder = new ServletHolder(Holder.Source.JAVAX_API);
+ ServletRegistration reg = holder.getRegistration();
+ try {
+ reg.setInitParameter(null, "foo");
+ fail("null name accepted");
+ } catch (IllegalArgumentException e) {
+ }
+ try {
+ reg.setInitParameter("foo", null);
+ fail("null value accepted");
+ } catch (IllegalArgumentException e) {
+ }
+ reg.setInitParameter("foo", "bar");
+ assertFalse(reg.setInitParameter("foo", "foo"));
+
+ Set<String> clash = reg.setInitParameters(Collections.singletonMap("foo", "bax"));
+ assertTrue("should be one clash", clash != null && clash.size() == 1);
+
+ try {
+ reg.setInitParameters(Collections.singletonMap((String)null, "bax"));
+ fail("null name in map accepted");
+ } catch (IllegalArgumentException e) {
+ }
+ try {
+ reg.setInitParameters(Collections.singletonMap("foo", (String)null));
+ fail("null value in map accepted");
+ } catch (IllegalArgumentException e) {
+ }
+
+ Set<String> clash2 = reg.setInitParameters(Collections.singletonMap("FOO", "bax"));
+ assertTrue("should be no clash", clash2.isEmpty());
+ assertEquals("setInitParameters should not replace existing non-clashing init parameters", 2, reg.getInitParameters().size());
+
+ }
+}
diff --git a/jetty-servlets/pom.xml b/jetty-servlets/pom.xml
index c8b365cc47..4495cd233d 100644
--- a/jetty-servlets/pom.xml
+++ b/jetty-servlets/pom.xml
@@ -3,7 +3,7 @@
<parent>
<artifactId>jetty-project</artifactId>
<groupId>org.eclipse.jetty</groupId>
- <version>7.6.8-SNAPSHOT</version>
+ <version>8.1.8-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>jetty-servlets</artifactId>
@@ -23,6 +23,11 @@
<goals>
<goal>manifest</goal>
</goals>
+ <configuration>
+ <instructions>
+ <Import-Package>javax.servlet.*;version="2.6.0",*</Import-Package>
+ </instructions>
+ </configuration>
</execution>
</executions>
</plugin>
diff --git a/jetty-servlets/src/main/java/org/eclipse/jetty/servlets/DoSFilter.java b/jetty-servlets/src/main/java/org/eclipse/jetty/servlets/DoSFilter.java
index 7e38d0f21e..1a7b25ed4f 100644
--- a/jetty-servlets/src/main/java/org/eclipse/jetty/servlets/DoSFilter.java
+++ b/jetty-servlets/src/main/java/org/eclipse/jetty/servlets/DoSFilter.java
@@ -344,17 +344,18 @@ public class DoSFilter implements Filter
// Reject this request
if (_insertHeaders)
((HttpServletResponse)response).addHeader("DoSFilter","unavailable");
+
((HttpServletResponse)response).sendError(HttpServletResponse.SC_SERVICE_UNAVAILABLE);
return;
}
case 0:
{
- // fall through to throttle code
+ // fall through to throttle code
request.setAttribute(__TRACKER,tracker);
break;
}
default:
- {
+ {
// insert a delay before throttling the request
if (_insertHeaders)
((HttpServletResponse)response).addHeader("DoSFilter","delayed");
@@ -362,12 +363,22 @@ public class DoSFilter implements Filter
request.setAttribute(__TRACKER,tracker);
if (_delayMs > 0)
continuation.setTimeout(_delayMs);
+ continuation.addContinuationListener(new ContinuationListener()
+ {
+
+ public void onComplete(Continuation continuation)
+ {
+ }
+
+ public void onTimeout(Continuation continuation)
+ {
+ }
+ });
continuation.suspend();
return;
}
}
}
-
// Throttle the request
boolean accepted = false;
try
@@ -421,6 +432,10 @@ public class DoSFilter implements Filter
_context.log("DoS",e);
((HttpServletResponse)response).sendError(HttpServletResponse.SC_SERVICE_UNAVAILABLE);
}
+ catch (Exception e)
+ {
+ e.printStackTrace();
+ }
finally
{
if (accepted)
diff --git a/jetty-servlets/src/main/java/org/eclipse/jetty/servlets/MultiPartFilter.java b/jetty-servlets/src/main/java/org/eclipse/jetty/servlets/MultiPartFilter.java
index bceb6b5efd..d466de3464 100644
--- a/jetty-servlets/src/main/java/org/eclipse/jetty/servlets/MultiPartFilter.java
+++ b/jetty-servlets/src/main/java/org/eclipse/jetty/servlets/MultiPartFilter.java
@@ -20,17 +20,15 @@ package org.eclipse.jetty.servlets;
import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
-import java.io.BufferedReader;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileOutputStream;
-import java.io.FilterInputStream;
import java.io.IOException;
import java.io.InputStream;
-import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.UnsupportedEncodingException;
import java.util.ArrayList;
+import java.util.Collection;
import java.util.Collections;
import java.util.Enumeration;
import java.util.HashMap;
@@ -42,16 +40,20 @@ import java.util.Map;
import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
+import javax.servlet.MultipartConfigElement;
import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletRequestWrapper;
+import javax.servlet.http.Part;
-import org.eclipse.jetty.util.B64Code;
+
+import org.eclipse.jetty.util.IO;
import org.eclipse.jetty.util.LazyList;
import org.eclipse.jetty.util.MultiMap;
+import org.eclipse.jetty.util.MultiPartInputStream;
import org.eclipse.jetty.util.QuotedStringTokenizer;
import org.eclipse.jetty.util.StringUtil;
import org.eclipse.jetty.util.TypeUtil;
@@ -75,15 +77,21 @@ import org.eclipse.jetty.util.TypeUtil;
* The init parameter deleteFiles controls if uploaded files are automatically deleted after the request
* completes.
*
+ * Use init parameter "maxFileSize" to set the max size file that can be uploaded.
+ *
+ * Use init parameter "maxRequestSize" to limit the size of the multipart request.
+ *
*/
public class MultiPartFilter implements Filter
{
public final static String CONTENT_TYPE_SUFFIX=".org.eclipse.jetty.servlet.contentType";
- private final static String FILES ="org.eclipse.jetty.servlet.MultiPartFilter.files";
+ private final static String MULTIPART = "org.eclipse.jetty.servlet.MultiPartFile.multiPartInputStream";
private File tempdir;
private boolean _deleteFiles;
private ServletContext _context;
private int _fileOutputBuffer = 0;
+ private long _maxFileSize = -1L;
+ private long _maxRequestSize = -1L;
private int _maxFormKeys = Integer.getInteger("org.eclipse.jetty.server.Request.maxFormKeys",1000).intValue();
/* ------------------------------------------------------------------------------- */
@@ -97,6 +105,13 @@ public class MultiPartFilter implements Filter
String fileOutputBuffer = filterConfig.getInitParameter("fileOutputBuffer");
if(fileOutputBuffer!=null)
_fileOutputBuffer = Integer.parseInt(fileOutputBuffer);
+ String maxFileSize = filterConfig.getInitParameter("maxFileSize");
+ if (maxFileSize != null)
+ _maxFileSize = Long.parseLong(maxFileSize.trim());
+ String maxRequestSize = filterConfig.getInitParameter("maxRequestSize");
+ if (maxRequestSize != null)
+ _maxRequestSize = Long.parseLong(maxRequestSize.trim());
+
_context=filterConfig.getServletContext();
String mfks = filterConfig.getInitParameter("maxFormKeys");
if (mfks!=null)
@@ -121,15 +136,11 @@ public class MultiPartFilter implements Filter
InputStream in = new BufferedInputStream(request.getInputStream());
String content_type=srequest.getContentType();
- // TODO - handle encodings
- String boundary="--"+QuotedStringTokenizer.unquote(value(content_type.substring(content_type.indexOf("boundary="))).trim());
-
- byte[] byteBoundary=(boundary+"--").getBytes(StringUtil.__ISO_8859_1);
-
- MultiMap params = new MultiMap();
- for (Iterator i = request.getParameterMap().entrySet().iterator();i.hasNext();)
+ //Get current parameters so we can merge into them
+ MultiMap<String> params = new MultiMap<String>();
+ for (Iterator<Map.Entry<String,String[]>> i = request.getParameterMap().entrySet().iterator();i.hasNext();)
{
- Map.Entry entry=(Map.Entry)i.next();
+ Map.Entry<String,String[]> entry=i.next();
Object value=entry.getValue();
if (value instanceof String[])
params.addValues(entry.getKey(),(String[])value);
@@ -137,231 +148,42 @@ public class MultiPartFilter implements Filter
params.add(entry.getKey(),value);
}
+ MultipartConfigElement config = new MultipartConfigElement(tempdir.getCanonicalPath(), _maxFileSize, _maxRequestSize, _fileOutputBuffer);
+ MultiPartInputStream mpis = new MultiPartInputStream(in, content_type, config, tempdir);
+ mpis.setDeleteOnExit(_deleteFiles);
+ request.setAttribute(MULTIPART, mpis);
+
try
{
- // Get first boundary
- byte[] bytes=TypeUtil.readLine(in);
- String line=bytes==null?null:new String(bytes,"UTF-8");
- if(line==null || !line.equals(boundary))
- {
- throw new IOException("Missing initial multi part boundary");
- }
-
- // Read each part
- boolean lastPart=false;
- String content_disposition=null;
- String content_transfer_encoding=null;
-
-
- outer:while(!lastPart && params.size()<_maxFormKeys)
+ Collection<Part> parts = mpis.getParts();
+ if (parts != null)
{
- String type_content=null;
-
- while(true)
- {
- // read a line
- bytes=TypeUtil.readLine(in);
- if (bytes==null)
- break outer;
-
- // If blank line, end of part headers
- if(bytes.length==0)
- break;
- line=new String(bytes,"UTF-8");
-
- // place part header key and value in map
- int c=line.indexOf(':',0);
- if(c>0)
- {
- String key=line.substring(0,c).trim().toLowerCase(Locale.ENGLISH);
- String value=line.substring(c+1,line.length()).trim();
- if(key.equals("content-disposition"))
- content_disposition=value;
- else if(key.equals("content-transfer-encoding"))
- content_transfer_encoding=value;
- else if (key.equals("content-type"))
- type_content = value;
- }
- }
- // Extract content-disposition
- boolean form_data=false;
- if(content_disposition==null)
- {
- throw new IOException("Missing content-disposition");
- }
-
- QuotedStringTokenizer tok=new QuotedStringTokenizer(content_disposition,";");
- String name=null;
- String filename=null;
- while(tok.hasMoreTokens())
+ Iterator<Part> itor = parts.iterator();
+ while (itor.hasNext() && params.size() < _maxFormKeys)
{
- String t=tok.nextToken().trim();
- String tl=t.toLowerCase();
- if(t.startsWith("form-data"))
- form_data=true;
- else if(tl.startsWith("name="))
- name=value(t);
- else if(tl.startsWith("filename="))
- filename=value(t);
- }
-
- // Check disposition
- if(!form_data)
- {
- continue;
- }
- //It is valid for reset and submit buttons to have an empty name.
- //If no name is supplied, the browser skips sending the info for that field.
- //However, if you supply the empty string as the name, the browser sends the
- //field, with name as the empty string. So, only continue this loop if we
- //have not yet seen a name field.
- if(name==null)
- {
- continue;
- }
-
- OutputStream out=null;
- File file=null;
- try
- {
- if (filename!=null && filename.length()>0)
+ Part p = itor.next();
+ MultiPartInputStream.MultiPart mp = (MultiPartInputStream.MultiPart)p;
+ if (mp.getFile() != null)
{
- file = File.createTempFile("MultiPart", "", tempdir);
- out = new FileOutputStream(file);
- if(_fileOutputBuffer>0)
- out = new BufferedOutputStream(out, _fileOutputBuffer);
- request.setAttribute(name,file);
- params.add(name, filename);
- if (type_content != null)
- params.add(name+CONTENT_TYPE_SUFFIX, type_content);
-
- if (_deleteFiles)
+ request.setAttribute(mp.getName(),mp.getFile());
+ if (mp.getContentDispositionFilename() != null)
{
- file.deleteOnExit();
- ArrayList files = (ArrayList)request.getAttribute(FILES);
- if (files==null)
- {
- files=new ArrayList();
- request.setAttribute(FILES,files);
- }
- files.add(file);
- }
+ params.add(mp.getName(), mp.getContentDispositionFilename());
+ if (mp.getContentType() != null)
+ params.add(mp.getName()+CONTENT_TYPE_SUFFIX, mp.getContentType());
+ }
}
else
{
- out=new ByteArrayOutputStream();
- }
-
-
- if ("base64".equalsIgnoreCase(content_transfer_encoding))
- {
- in = new Base64InputStream(in);
- }
- else if ("quoted-printable".equalsIgnoreCase(content_transfer_encoding))
- {
- in = new FilterInputStream(in)
- {
- @Override
- public int read() throws IOException
- {
- int c = in.read();
- if (c >= 0 && c == '=')
- {
- int hi = in.read();
- int lo = in.read();
- if (hi < 0 || lo < 0)
- {
- throw new IOException("Unexpected end to quoted-printable byte");
- }
- char[] chars = new char[] { (char)hi, (char)lo };
- c = Integer.parseInt(new String(chars),16);
- }
- return c;
- }
- };
- }
-
- int state=-2;
- int c;
- boolean cr=false;
- boolean lf=false;
-
- // loop for all lines`
- while(true)
- {
- int b=0;
- while((c=(state!=-2)?state:in.read())!=-1)
- {
- state=-2;
- // look for CR and/or LF
- if(c==13||c==10)
- {
- if(c==13)
- state=in.read();
- break;
- }
- // look for boundary
- if(b>=0&&b<byteBoundary.length&&c==byteBoundary[b])
- b++;
- else
- {
- // this is not a boundary
- if(cr)
- out.write(13);
- if(lf)
- out.write(10);
- cr=lf=false;
- if(b>0)
- out.write(byteBoundary,0,b);
- b=-1;
- out.write(c);
- }
- }
- // check partial boundary
- if((b>0&&b<byteBoundary.length-2)||(b==byteBoundary.length-1))
- {
- if(cr)
- out.write(13);
- if(lf)
- out.write(10);
- cr=lf=false;
- out.write(byteBoundary,0,b);
- b=-1;
- }
- // boundary match
- if(b>0||c==-1)
- {
- if(b==byteBoundary.length)
- lastPart=true;
- if(state==10)
- state=-2;
- break;
- }
- // handle CR LF
- if(cr)
- out.write(13);
- if(lf)
- out.write(10);
- cr=(c==13);
- lf=(c==10||state==10);
- if(state==10)
- state=-2;
+ ByteArrayOutputStream bytes = new ByteArrayOutputStream();
+ IO.copy(p.getInputStream(), bytes);
+ params.add(p.getName(), bytes.toByteArray());
+ if (p.getContentType() != null)
+ params.add(p.getName()+CONTENT_TYPE_SUFFIX, p.getContentType());
}
}
- finally
- {
- out.close();
- }
-
- if (file==null)
- {
- bytes = ((ByteArrayOutputStream)out).toByteArray();
- params.add(name,bytes);
- if (type_content != null)
- params.add(name+CONTENT_TYPE_SUFFIX, type_content);
- }
}
-
+
// handle request
chain.doFilter(new Wrapper(srequest,params),response);
}
@@ -370,26 +192,27 @@ public class MultiPartFilter implements Filter
deleteFiles(request);
}
}
-
+
+
+ /* ------------------------------------------------------------ */
private void deleteFiles(ServletRequest request)
{
- ArrayList files = (ArrayList)request.getAttribute(FILES);
- if (files!=null)
+ if (!_deleteFiles)
+ return;
+
+ MultiPartInputStream mpis = (MultiPartInputStream)request.getAttribute(MULTIPART);
+ if (mpis != null)
{
- Iterator iter = files.iterator();
- while (iter.hasNext())
+ try
{
- File file=(File)iter.next();
- try
- {
- file.delete();
- }
- catch(Exception e)
- {
- _context.log("failed to delete "+file,e);
- }
+ mpis.deleteParts();
+ }
+ catch (Exception e)
+ {
+ _context.log("Error deleting multipart tmp files", e);
}
}
+ request.removeAttribute(MULTIPART);
}
/* ------------------------------------------------------------ */
@@ -530,37 +353,4 @@ public class MultiPartFilter implements Filter
_encoding=enc;
}
}
-
- private static class Base64InputStream extends InputStream
- {
- BufferedReader _in;
- String _line;
- byte[] _buffer;
- int _pos;
-
- public Base64InputStream (InputStream in)
- {
- _in = new BufferedReader(new InputStreamReader(in));
- }
-
- @Override
- public int read() throws IOException
- {
- if (_buffer==null || _pos>= _buffer.length)
- {
- _line = _in.readLine();
- if (_line==null)
- return -1;
- if (_line.startsWith("--"))
- _buffer=(_line+"\r\n").getBytes();
- else if (_line.length()==0)
- _buffer="\r\n".getBytes();
- else
- _buffer=B64Code.decode(_line);
-
- _pos=0;
- }
- return _buffer[_pos++];
- }
- }
}
diff --git a/jetty-servlets/src/test/java/org/eclipse/jetty/servlets/AbstractDoSFilterTest.java b/jetty-servlets/src/test/java/org/eclipse/jetty/servlets/AbstractDoSFilterTest.java
index 722cd5331d..483cd59034 100644
--- a/jetty-servlets/src/test/java/org/eclipse/jetty/servlets/AbstractDoSFilterTest.java
+++ b/jetty-servlets/src/test/java/org/eclipse/jetty/servlets/AbstractDoSFilterTest.java
@@ -23,7 +23,8 @@ import static org.junit.Assert.assertTrue;
import java.io.IOException;
import java.net.Socket;
-
+import java.util.EnumSet;
+import javax.servlet.DispatcherType;
import javax.servlet.Filter;
import javax.servlet.Servlet;
import javax.servlet.ServletException;
@@ -62,7 +63,7 @@ public abstract class AbstractDoSFilterTest
_tester.setContextPath("/ctx");
_tester.addServlet(TestServlet.class, "/*");
- _dosFilter = _tester.addFilter(filter, "/dos/*", 0);
+ _dosFilter = _tester.addFilter(filter, "/dos/*", EnumSet.allOf(DispatcherType.class));
_dosFilter.setInitParameter("maxRequestsPerSec", "4");
_dosFilter.setInitParameter("delayMs", "200");
_dosFilter.setInitParameter("throttledRequests", "1");
@@ -71,7 +72,7 @@ public abstract class AbstractDoSFilterTest
_dosFilter.setInitParameter("remotePort", "false");
_dosFilter.setInitParameter("insertHeaders", "true");
- _timeoutFilter = _tester.addFilter(filter, "/timeout/*", 0);
+ _timeoutFilter = _tester.addFilter(filter, "/timeout/*", EnumSet.allOf(DispatcherType.class));
_timeoutFilter.setInitParameter("maxRequestsPerSec", "4");
_timeoutFilter.setInitParameter("delayMs", "200");
_timeoutFilter.setInitParameter("throttledRequests", "1");
@@ -209,7 +210,7 @@ public abstract class AbstractDoSFilterTest
String request="GET /ctx/dos/test HTTP/1.1\r\nHost: localhost\r\n\r\n";
String last="GET /ctx/dos/test HTTP/1.1\r\nHost: localhost\r\nConnection: close\r\n\r\n";
String responses = doRequests(request+request+request+request,1,0,0,last);
- //System.out.println("responses are " + responses);
+ System.out.println("responses are " + responses);
assertEquals("200 OK responses", 5,count(responses,"HTTP/1.1 200 OK"));
assertEquals("delayed responses", 1,count(responses,"DoSFilter: delayed"));
assertEquals("throttled responses", 1,count(responses,"DoSFilter: throttled"));
@@ -246,6 +247,8 @@ public abstract class AbstractDoSFilterTest
String last="GET /ctx/dos/test HTTP/1.1\r\nHost: localhost\r\nConnection: close\r\n\r\n";
String responses = doRequests(request+request+request+request,1,0,0,last);
+ System.err.println("RESPONSES: \n"+responses);
+
assertEquals(4,count(responses,"HTTP/1.1 200 OK"));
assertEquals(1,count(responses,"HTTP/1.1 503"));
assertEquals(1,count(responses,"DoSFilter: delayed"));
diff --git a/jetty-servlets/src/test/java/org/eclipse/jetty/servlets/AsyncProxyServer.java b/jetty-servlets/src/test/java/org/eclipse/jetty/servlets/AsyncProxyServer.java
index 56e2cf3527..30ea8865ae 100644
--- a/jetty-servlets/src/test/java/org/eclipse/jetty/servlets/AsyncProxyServer.java
+++ b/jetty-servlets/src/test/java/org/eclipse/jetty/servlets/AsyncProxyServer.java
@@ -18,6 +18,10 @@
package org.eclipse.jetty.servlets;
+import java.util.EnumSet;
+
+import javax.servlet.DispatcherType;
+
import org.eclipse.jetty.server.Connector;
import org.eclipse.jetty.server.Server;
import org.eclipse.jetty.server.nio.SelectChannelConnector;
@@ -37,7 +41,7 @@ public class AsyncProxyServer
ServletHandler handler=new ServletHandler();
server.setHandler(handler);
- //FilterHolder gzip = handler.addFilterWithMapping("org.eclipse.jetty.servlets.GzipFilter","/*",0);
+ //FilterHolder gzip = handler.addFilterWithMapping("org.eclipse.jetty.servlet.GzipFilter","/*",EnumSet.of(DispatcherType.REQUEST,DispatcherType.ASYNC));
//gzip.setAsyncSupported(true);
//gzip.setInitParameter("minGzipSize","256");
ServletHolder proxy = handler.addServletWithMapping("org.eclipse.jetty.servlets.ProxyServlet","/");
diff --git a/jetty-servlets/src/test/java/org/eclipse/jetty/servlets/CloseableDoSFilterTest.java b/jetty-servlets/src/test/java/org/eclipse/jetty/servlets/CloseableDoSFilterTest.java
index 665eb8e9f8..4203e6a91d 100644
--- a/jetty-servlets/src/test/java/org/eclipse/jetty/servlets/CloseableDoSFilterTest.java
+++ b/jetty-servlets/src/test/java/org/eclipse/jetty/servlets/CloseableDoSFilterTest.java
@@ -18,6 +18,7 @@
package org.eclipse.jetty.servlets;
+
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
diff --git a/jetty-servlets/src/test/java/org/eclipse/jetty/servlets/CrossOriginFilterTest.java b/jetty-servlets/src/test/java/org/eclipse/jetty/servlets/CrossOriginFilterTest.java
index 93af56813a..faad9b6146 100644
--- a/jetty-servlets/src/test/java/org/eclipse/jetty/servlets/CrossOriginFilterTest.java
+++ b/jetty-servlets/src/test/java/org/eclipse/jetty/servlets/CrossOriginFilterTest.java
@@ -19,8 +19,11 @@
package org.eclipse.jetty.servlets;
import java.io.IOException;
+import java.util.EnumSet;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;
+
+import javax.servlet.DispatcherType;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
@@ -56,7 +59,7 @@ public class CrossOriginFilterTest
@Test
public void testRequestWithNoOriginArrivesToApplication() throws Exception
{
- tester.getContext().addFilter(CrossOriginFilter.class, "/*", FilterMapping.DEFAULT);
+ tester.getContext().addFilter(CrossOriginFilter.class, "/*", EnumSet.of(DispatcherType.REQUEST));
final CountDownLatch latch = new CountDownLatch(1);
tester.getContext().addServlet(new ServletHolder(new ResourceServlet(latch)), "/*");
@@ -76,7 +79,7 @@ public class CrossOriginFilterTest
FilterHolder filterHolder = new FilterHolder(new CrossOriginFilter());
String origin = "http://localhost";
filterHolder.setInitParameter(CrossOriginFilter.ALLOWED_ORIGINS_PARAM, origin);
- tester.getContext().addFilter(filterHolder, "/*", FilterMapping.DEFAULT);
+ tester.getContext().addFilter(filterHolder, "/*", EnumSet.of(DispatcherType.REQUEST));
CountDownLatch latch = new CountDownLatch(1);
tester.getContext().addServlet(new ServletHolder(new ResourceServlet(latch)), "/*");
@@ -100,7 +103,7 @@ public class CrossOriginFilterTest
FilterHolder filterHolder = new FilterHolder(new CrossOriginFilter());
String origin = "http://subdomain.example.com";
filterHolder.setInitParameter(CrossOriginFilter.ALLOWED_ORIGINS_PARAM, "http://*.example.com");
- tester.getContext().addFilter(filterHolder, "/*", FilterMapping.DEFAULT);
+ tester.getContext().addFilter(filterHolder, "/*", EnumSet.of(DispatcherType.REQUEST));
CountDownLatch latch = new CountDownLatch(1);
tester.getContext().addServlet(new ServletHolder(new ResourceServlet(latch)), "/*");
@@ -123,7 +126,7 @@ public class CrossOriginFilterTest
FilterHolder filterHolder = new FilterHolder(new CrossOriginFilter());
String origin = "http://subdomain.subdomain.example.com";
filterHolder.setInitParameter(CrossOriginFilter.ALLOWED_ORIGINS_PARAM, "http://*.example.com");
- tester.getContext().addFilter(filterHolder, "/*", FilterMapping.DEFAULT);
+ tester.getContext().addFilter(filterHolder, "/*", EnumSet.of(DispatcherType.REQUEST));
CountDownLatch latch = new CountDownLatch(1);
tester.getContext().addServlet(new ServletHolder(new ResourceServlet(latch)), "/*");
@@ -146,7 +149,7 @@ public class CrossOriginFilterTest
FilterHolder filterHolder = new FilterHolder(new CrossOriginFilter());
String origin = "http://localhost";
filterHolder.setInitParameter(CrossOriginFilter.ALLOWED_ORIGINS_PARAM, origin);
- tester.getContext().addFilter(filterHolder, "/*", FilterMapping.DEFAULT);
+ tester.getContext().addFilter(filterHolder, "/*", EnumSet.of(DispatcherType.REQUEST));
CountDownLatch latch = new CountDownLatch(1);
tester.getContext().addServlet(new ServletHolder(new ResourceServlet(latch)), "/*");
@@ -170,7 +173,7 @@ public class CrossOriginFilterTest
String origin = "http://localhost";
String otherOrigin = origin.replace("localhost", "127.0.0.1");
filterHolder.setInitParameter(CrossOriginFilter.ALLOWED_ORIGINS_PARAM, origin + "," + otherOrigin);
- tester.getContext().addFilter(filterHolder, "/*", FilterMapping.DEFAULT);
+ tester.getContext().addFilter(filterHolder, "/*", EnumSet.of(DispatcherType.REQUEST));
CountDownLatch latch = new CountDownLatch(1);
tester.getContext().addServlet(new ServletHolder(new ResourceServlet(latch)), "/*");
@@ -193,7 +196,7 @@ public class CrossOriginFilterTest
{
FilterHolder filterHolder = new FilterHolder(new CrossOriginFilter());
filterHolder.setInitParameter(CrossOriginFilter.ALLOW_CREDENTIALS_PARAM, "false");
- tester.getContext().addFilter(filterHolder, "/*", FilterMapping.DEFAULT);
+ tester.getContext().addFilter(filterHolder, "/*", EnumSet.of(DispatcherType.REQUEST));
CountDownLatch latch = new CountDownLatch(1);
tester.getContext().addServlet(new ServletHolder(new ResourceServlet(latch)), "/*");
@@ -218,7 +221,7 @@ public class CrossOriginFilterTest
// will contain the CORS response headers.
FilterHolder filterHolder = new FilterHolder(new CrossOriginFilter());
- tester.getContext().addFilter(filterHolder, "/*", FilterMapping.DEFAULT);
+ tester.getContext().addFilter(filterHolder, "/*", EnumSet.of(DispatcherType.REQUEST));
CountDownLatch latch = new CountDownLatch(1);
tester.getContext().addServlet(new ServletHolder(new ResourceServlet(latch)), "/*");
@@ -243,7 +246,7 @@ public class CrossOriginFilterTest
// will contain the CORS response headers.
FilterHolder filterHolder = new FilterHolder(new CrossOriginFilter());
- tester.getContext().addFilter(filterHolder, "/*", FilterMapping.DEFAULT);
+ tester.getContext().addFilter(filterHolder, "/*", EnumSet.of(DispatcherType.REQUEST));
CountDownLatch latch = new CountDownLatch(1);
tester.getContext().addServlet(new ServletHolder(new ResourceServlet(latch)), "/*");
@@ -265,7 +268,7 @@ public class CrossOriginFilterTest
{
FilterHolder filterHolder = new FilterHolder(new CrossOriginFilter());
filterHolder.setInitParameter(CrossOriginFilter.ALLOWED_METHODS_PARAM, "PUT");
- tester.getContext().addFilter(filterHolder, "/*", FilterMapping.DEFAULT);
+ tester.getContext().addFilter(filterHolder, "/*", EnumSet.of(DispatcherType.REQUEST));
CountDownLatch latch = new CountDownLatch(1);
tester.getContext().addServlet(new ServletHolder(new ResourceServlet(latch)), "/*");
@@ -304,7 +307,7 @@ public class CrossOriginFilterTest
FilterHolder filterHolder = new FilterHolder(new CrossOriginFilter());
filterHolder.setInitParameter(CrossOriginFilter.ALLOWED_METHODS_PARAM, "GET,HEAD,POST,PUT,DELETE");
filterHolder.setInitParameter(CrossOriginFilter.ALLOWED_HEADERS_PARAM, "X-Requested-With,Content-Type,Accept,Origin,X-Custom");
- tester.getContext().addFilter(filterHolder, "/*", FilterMapping.DEFAULT);
+ tester.getContext().addFilter(filterHolder, "/*",EnumSet.of(DispatcherType.REQUEST));
CountDownLatch latch = new CountDownLatch(1);
tester.getContext().addServlet(new ServletHolder(new ResourceServlet(latch)), "/*");
@@ -345,7 +348,7 @@ public class CrossOriginFilterTest
{
FilterHolder filterHolder = new FilterHolder(new CrossOriginFilter());
filterHolder.setInitParameter(CrossOriginFilter.ALLOWED_METHODS_PARAM, "GET,HEAD,POST,PUT,DELETE");
- tester.getContext().addFilter(filterHolder, "/*", FilterMapping.DEFAULT);
+ tester.getContext().addFilter(filterHolder, "/*", EnumSet.of(DispatcherType.REQUEST));
CountDownLatch latch = new CountDownLatch(1);
tester.getContext().addServlet(new ServletHolder(new ResourceServlet(latch)), "/*");
@@ -370,7 +373,7 @@ public class CrossOriginFilterTest
public void testCrossOriginFilterDisabledForWebSocketUpgrade() throws Exception
{
FilterHolder filterHolder = new FilterHolder(new CrossOriginFilter());
- tester.getContext().addFilter(filterHolder, "/*", FilterMapping.DEFAULT);
+ tester.getContext().addFilter(filterHolder, "/*", EnumSet.of(DispatcherType.REQUEST));
CountDownLatch latch = new CountDownLatch(1);
tester.getContext().addServlet(new ServletHolder(new ResourceServlet(latch)), "/*");
@@ -394,7 +397,7 @@ public class CrossOriginFilterTest
{
FilterHolder filterHolder = new FilterHolder(new CrossOriginFilter());
filterHolder.setInitParameter("exposedHeaders", "Content-Length");
- tester.getContext().addFilter(filterHolder, "/*", FilterMapping.DEFAULT);
+ tester.getContext().addFilter(filterHolder, "/*", EnumSet.of(DispatcherType.REQUEST));
CountDownLatch latch = new CountDownLatch(1);
tester.getContext().addServlet(new ServletHolder(new ResourceServlet(latch)), "/*");
@@ -416,7 +419,7 @@ public class CrossOriginFilterTest
FilterHolder filterHolder = new FilterHolder(new CrossOriginFilter());
filterHolder.setInitParameter(CrossOriginFilter.ALLOWED_METHODS_PARAM, "PUT");
filterHolder.setInitParameter(CrossOriginFilter.CHAIN_PREFLIGHT_PARAM, "false");
- tester.getContext().addFilter(filterHolder, "/*", FilterMapping.DEFAULT);
+ tester.getContext().addFilter(filterHolder, "/*", EnumSet.of(DispatcherType.REQUEST));
CountDownLatch latch = new CountDownLatch(1);
tester.getContext().addServlet(new ServletHolder(new ResourceServlet(latch)), "/*");
diff --git a/jetty-servlets/src/test/java/org/eclipse/jetty/servlets/DoSFilterTest.java b/jetty-servlets/src/test/java/org/eclipse/jetty/servlets/DoSFilterTest.java
index f7aa7e4a9c..9bfb3acadb 100644
--- a/jetty-servlets/src/test/java/org/eclipse/jetty/servlets/DoSFilterTest.java
+++ b/jetty-servlets/src/test/java/org/eclipse/jetty/servlets/DoSFilterTest.java
@@ -45,7 +45,8 @@ public class DoSFilterTest extends AbstractDoSFilterTest
@Override
public void closeConnection(HttpServletRequest request, HttpServletResponse response, Thread thread)
{
- try {
+ try
+ {
response.getWriter().append("DoSFilter: timeout");
super.closeConnection(request,response,thread);
}
diff --git a/jetty-servlets/src/test/java/org/eclipse/jetty/servlets/GzipWithPipeliningTest.java b/jetty-servlets/src/test/java/org/eclipse/jetty/servlets/GzipWithPipeliningTest.java
index dc627730b2..4ce84495e9 100644
--- a/jetty-servlets/src/test/java/org/eclipse/jetty/servlets/GzipWithPipeliningTest.java
+++ b/jetty-servlets/src/test/java/org/eclipse/jetty/servlets/GzipWithPipeliningTest.java
@@ -34,6 +34,7 @@ import java.io.InputStream;
import java.net.URI;
import java.security.DigestOutputStream;
import java.security.MessageDigest;
+import java.util.EnumSet;
import java.util.Arrays;
import java.util.Collection;
import java.util.regex.Matcher;
@@ -42,6 +43,8 @@ import java.util.zip.GZIPInputStream;
import java.util.zip.Inflater;
import java.util.zip.InflaterInputStream;
+import javax.servlet.DispatcherType;
+
import org.eclipse.jetty.server.Connector;
import org.eclipse.jetty.server.Server;
import org.eclipse.jetty.servlet.DefaultServlet;
@@ -109,7 +112,7 @@ public class GzipWithPipeliningTest
holder.setInitParameter("resourceBase",MavenTestingUtils.getTestResourcesDir().getAbsolutePath());
context.addServlet(holder,"/");
- FilterHolder filter = context.addFilter(GzipFilter.class,"/*",0);
+ FilterHolder filter = context.addFilter(GzipFilter.class,"/*", EnumSet.of(DispatcherType.REQUEST));
filter.setInitParameter("mimeTypes","text/plain");
server.setHandler(context);
diff --git a/jetty-servlets/src/test/java/org/eclipse/jetty/servlets/IncludableGzipFilterTest.java b/jetty-servlets/src/test/java/org/eclipse/jetty/servlets/IncludableGzipFilterTest.java
index b319debc32..7a073043b8 100644
--- a/jetty-servlets/src/test/java/org/eclipse/jetty/servlets/IncludableGzipFilterTest.java
+++ b/jetty-servlets/src/test/java/org/eclipse/jetty/servlets/IncludableGzipFilterTest.java
@@ -104,7 +104,7 @@ public class IncludableGzipFilterTest
tester.setContextPath("/context");
tester.setResourceBase(testdir.getDir().getCanonicalPath());
tester.addServlet(org.eclipse.jetty.servlet.DefaultServlet.class, "/");
- FilterHolder holder = tester.addFilter(IncludableGzipFilter.class,"/*",0);
+ FilterHolder holder = tester.addFilter(IncludableGzipFilter.class,"/*",null);
holder.setInitParameter("mimeTypes","text/plain");
tester.start();
}
diff --git a/jetty-servlets/src/test/java/org/eclipse/jetty/servlets/MultipartFilterTest.java b/jetty-servlets/src/test/java/org/eclipse/jetty/servlets/MultipartFilterTest.java
index 97da7c63f2..38e2c8bbdc 100644
--- a/jetty-servlets/src/test/java/org/eclipse/jetty/servlets/MultipartFilterTest.java
+++ b/jetty-servlets/src/test/java/org/eclipse/jetty/servlets/MultipartFilterTest.java
@@ -25,7 +25,13 @@ import static org.junit.Assert.assertNotNull;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
+import java.io.OutputStream;
+import java.net.Socket;
+import java.net.URL;
+import java.util.EnumSet;
+import java.util.Enumeration;
+import javax.servlet.DispatcherType;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
@@ -45,7 +51,7 @@ public class MultipartFilterTest
private File _dir;
private ServletTester tester;
-
+
public static class TestServlet extends DumpServlet
{
@@ -55,7 +61,6 @@ public class MultipartFilterTest
assertNotNull(req.getParameter("fileup"));
assertNotNull(req.getParameter("fileup"+MultiPartFilter.CONTENT_TYPE_SUFFIX));
assertEquals(req.getParameter("fileup"+MultiPartFilter.CONTENT_TYPE_SUFFIX), "application/octet-stream");
-
super.doPost(req, resp);
}
@@ -76,7 +81,8 @@ public class MultipartFilterTest
tester.setContextPath("/context");
tester.setResourceBase(_dir.getCanonicalPath());
tester.addServlet(TestServlet.class, "/");
- FilterHolder multipartFilter = tester.addFilter(MultiPartFilter.class,"/*",FilterMapping.DEFAULT);
+ tester.setAttribute("javax.servlet.context.tempdir", _dir);
+ FilterHolder multipartFilter = tester.addFilter(MultiPartFilter.class,"/*", EnumSet.of(DispatcherType.REQUEST));
multipartFilter.setInitParameter("deleteFiles", "true");
tester.start();
}
@@ -115,7 +121,7 @@ public class MultipartFilterTest
response.parse(tester.getResponses(request.generate()));
assertTrue(response.getMethod()==null);
- assertEquals(HttpServletResponse.SC_OK,response.getStatus());
+ assertEquals(HttpServletResponse.SC_INTERNAL_SERVER_ERROR,response.getStatus());
}
@@ -263,8 +269,7 @@ public class MultipartFilterTest
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException
{
- assertEquals("How now brown cow.", req.getParameterMap().get("strupContent-Type: application/octet-stream"));
-
+ assertEquals("How now brown cow.", req.getParameterMap().get("strupContent-Type:"));
super.doPost(req, resp);
}
diff --git a/jetty-servlets/src/test/java/org/eclipse/jetty/servlets/PutFilterTest.java b/jetty-servlets/src/test/java/org/eclipse/jetty/servlets/PutFilterTest.java
index 300430791f..d4a08b069d 100644
--- a/jetty-servlets/src/test/java/org/eclipse/jetty/servlets/PutFilterTest.java
+++ b/jetty-servlets/src/test/java/org/eclipse/jetty/servlets/PutFilterTest.java
@@ -26,6 +26,8 @@ import java.io.FileInputStream;
import java.io.OutputStream;
import java.net.Socket;
import java.net.URL;
+import java.util.EnumSet;
+import javax.servlet.DispatcherType;
import java.util.Arrays;
import java.util.HashSet;
import java.util.Locale;
@@ -59,7 +61,7 @@ public class PutFilterTest
tester.setContextPath("/context");
tester.setResourceBase(_dir.getCanonicalPath());
tester.addServlet(org.eclipse.jetty.servlet.DefaultServlet.class, "/");
- FilterHolder holder = tester.addFilter(PutFilter.class,"/*",0);
+ FilterHolder holder = tester.addFilter(PutFilter.class,"/*",EnumSet.of(DispatcherType.REQUEST));
holder.setInitParameter("delAllowed","true");
// Bloody Windows does not allow file renaming
if (!System.getProperty("os.name").toLowerCase(Locale.ENGLISH).contains("windows"))
diff --git a/jetty-servlets/src/test/java/org/eclipse/jetty/servlets/QoSFilterTest.java b/jetty-servlets/src/test/java/org/eclipse/jetty/servlets/QoSFilterTest.java
index 826a11a4f0..9997eaeaec 100644
--- a/jetty-servlets/src/test/java/org/eclipse/jetty/servlets/QoSFilterTest.java
+++ b/jetty-servlets/src/test/java/org/eclipse/jetty/servlets/QoSFilterTest.java
@@ -23,9 +23,10 @@ import static org.junit.Assert.assertTrue;
import java.io.IOException;
import java.net.URL;
+import java.util.EnumSet;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;
-
+import javax.servlet.DispatcherType;
import javax.servlet.Servlet;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
@@ -99,7 +100,7 @@ public class QoSFilterTest
FilterHolder holder = new FilterHolder(QoSFilter2.class);
holder.setAsyncSupported(true);
holder.setInitParameter(QoSFilter.MAX_REQUESTS_INIT_PARAM, ""+MAX_QOS);
- _tester.getContext().getServletHandler().addFilterWithMapping(holder,"/*",FilterMapping.DEFAULT);
+ _tester.getContext().getServletHandler().addFilterWithMapping(holder,"/*",EnumSet.of(DispatcherType.REQUEST,DispatcherType.ASYNC));
for(int i = 0; i < NUM_CONNECTIONS; ++i )
{
@@ -117,8 +118,7 @@ public class QoSFilterTest
FilterHolder holder = new FilterHolder(QoSFilter2.class);
holder.setAsyncSupported(true);
holder.setInitParameter(QoSFilter.MAX_REQUESTS_INIT_PARAM, ""+MAX_QOS);
- _tester.getContext().getServletHandler().addFilterWithMapping(holder,"/*",FilterMapping.DEFAULT);
-
+ _tester.getContext().getServletHandler().addFilterWithMapping(holder,"/*",EnumSet.of(DispatcherType.REQUEST,DispatcherType.ASYNC));
for(int i = 0; i < NUM_CONNECTIONS; ++i )
{
new Thread(new Worker2(i)).start();
diff --git a/jetty-servlets/src/test/java/org/eclipse/jetty/servlets/gzip/GzipTester.java b/jetty-servlets/src/test/java/org/eclipse/jetty/servlets/gzip/GzipTester.java
index de3aa98fb3..77f47766af 100644
--- a/jetty-servlets/src/test/java/org/eclipse/jetty/servlets/gzip/GzipTester.java
+++ b/jetty-servlets/src/test/java/org/eclipse/jetty/servlets/gzip/GzipTester.java
@@ -35,11 +35,13 @@ import java.io.InputStream;
import java.io.UnsupportedEncodingException;
import java.security.DigestOutputStream;
import java.security.MessageDigest;
+import java.util.EnumSet;
import java.util.Enumeration;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.zip.GZIPInputStream;
import java.util.zip.Inflater;
+import javax.servlet.DispatcherType;
import java.util.zip.InflaterInputStream;
import javax.servlet.Servlet;
@@ -460,7 +462,7 @@ public class GzipTester
servletTester.setResourceBase(testdir.getDir().getCanonicalPath());
ServletHolder servletHolder = servletTester.addServlet(servletClass,"/");
servletHolder.setInitParameter("baseDir",testdir.getDir().getAbsolutePath());
- FilterHolder holder = servletTester.addFilter(gzipFilterClass,"/*",0);
+ FilterHolder holder = servletTester.addFilter(gzipFilterClass,"/*",EnumSet.allOf(DispatcherType.class));
return holder;
}
diff --git a/jetty-spdy/pom.xml b/jetty-spdy/pom.xml
index ed6cff25b7..1dd3d9e8a1 100644
--- a/jetty-spdy/pom.xml
+++ b/jetty-spdy/pom.xml
@@ -3,7 +3,7 @@
<parent>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-project</artifactId>
- <version>7.6.8-SNAPSHOT</version>
+ <version>8.1.8-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
diff --git a/jetty-spdy/spdy-core/pom.xml b/jetty-spdy/spdy-core/pom.xml
index 953eaffb9a..b4b2f4747c 100644
--- a/jetty-spdy/spdy-core/pom.xml
+++ b/jetty-spdy/spdy-core/pom.xml
@@ -3,7 +3,7 @@
<parent>
<groupId>org.eclipse.jetty.spdy</groupId>
<artifactId>spdy-parent</artifactId>
- <version>7.6.8-SNAPSHOT</version>
+ <version>8.1.8-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
diff --git a/jetty-spdy/spdy-jetty-http-webapp/pom.xml b/jetty-spdy/spdy-jetty-http-webapp/pom.xml
index 295c777f6c..b45b01f58d 100644
--- a/jetty-spdy/spdy-jetty-http-webapp/pom.xml
+++ b/jetty-spdy/spdy-jetty-http-webapp/pom.xml
@@ -3,7 +3,7 @@
<parent>
<groupId>org.eclipse.jetty.spdy</groupId>
<artifactId>spdy-parent</artifactId>
- <version>7.6.8-SNAPSHOT</version>
+ <version>8.1.8-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>spdy-jetty-http-webapp</artifactId>
diff --git a/jetty-spdy/spdy-jetty-http/pom.xml b/jetty-spdy/spdy-jetty-http/pom.xml
index dbbfee3b0b..ddee9a70c7 100644
--- a/jetty-spdy/spdy-jetty-http/pom.xml
+++ b/jetty-spdy/spdy-jetty-http/pom.xml
@@ -3,7 +3,7 @@
<parent>
<groupId>org.eclipse.jetty.spdy</groupId>
<artifactId>spdy-parent</artifactId>
- <version>7.6.8-SNAPSHOT</version>
+ <version>8.1.8-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>spdy-jetty-http</artifactId>
diff --git a/jetty-spdy/spdy-jetty/pom.xml b/jetty-spdy/spdy-jetty/pom.xml
index ca6b17f3b1..4825968f4e 100644
--- a/jetty-spdy/spdy-jetty/pom.xml
+++ b/jetty-spdy/spdy-jetty/pom.xml
@@ -3,7 +3,7 @@
<parent>
<groupId>org.eclipse.jetty.spdy</groupId>
<artifactId>spdy-parent</artifactId>
- <version>7.6.8-SNAPSHOT</version>
+ <version>8.1.8-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>spdy-jetty</artifactId>
diff --git a/jetty-start/pom.xml b/jetty-start/pom.xml
index ef22b94371..5d51f61ca1 100644
--- a/jetty-start/pom.xml
+++ b/jetty-start/pom.xml
@@ -2,7 +2,7 @@
<parent>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-project</artifactId>
- <version>7.6.8-SNAPSHOT</version>
+ <version>8.1.8-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>jetty-start</artifactId>
diff --git a/jetty-start/src/main/resources/org/eclipse/jetty/start/start.config b/jetty-start/src/main/resources/org/eclipse/jetty/start/start.config
index c75ffd022c..23bb426162 100644
--- a/jetty-start/src/main/resources/org/eclipse/jetty/start/start.config
+++ b/jetty-start/src/main/resources/org/eclipse/jetty/start/start.config
@@ -92,7 +92,7 @@ $(jetty.home)/lib/jetty-io-$(version).jar
$(jetty.home)/lib/jetty-xml-$(version).jar ! available org.eclipse.jetty.xml.XmlParser
[Server,All,server,default]
-$(jetty.home)/lib/servlet-api-2.5.jar ! available javax.servlet.ServletContext
+$(jetty.home)/lib/servlet-api-3.0.jar ! available javax.servlet.ServletContext
$(jetty.home)/lib/jetty-http-$(version).jar ! available org.eclipse.jetty.http.HttpParser
$(jetty.home)/lib/jetty-continuation-$(version).jar ! available org.eclipse.jetty.continuation.Continuation
$(jetty.home)/lib/jetty-server-$(version).jar ! available org.eclipse.jetty.server.Server
@@ -101,7 +101,7 @@ $(jetty.home)/lib/jetty-server-$(version).jar
$(jetty.home)/lib/jetty-security-$(version).jar ! available org.eclipse.jetty.security.LoginService
[Server,All,servlet,default]
-$(jetty.home)/lib/servlet-api-2.5.jar ! available javax.servlet.ServletContext
+$(jetty.home)/lib/servlet-api-3.0.jar ! available javax.servlet.ServletContext
$(jetty.home)/lib/jetty-servlet-$(version).jar ! available org.eclipse.jetty.servlet.ServletHandler
[Server,All,webapp,default]
@@ -141,7 +141,7 @@ $(jetty.home)/lib/jetty-policy-$(version).jar
[All,Client,client]
$(jetty.home)/lib/jetty-http-$(version).jar ! available org.eclipse.jetty.http.HttpParser
$(jetty.home)/lib/jetty-client-$(version).jar ! available org.eclipse.jetty.client.HttpClient
-
+
[Client]
$(jetty.home)/lib/jetty-http-$(version).jar ! available org.eclipse.jetty.http.HttpParser
diff --git a/jetty-util/pom.xml b/jetty-util/pom.xml
index 7df9a67d53..74e05d2f33 100644
--- a/jetty-util/pom.xml
+++ b/jetty-util/pom.xml
@@ -2,7 +2,7 @@
<parent>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-project</artifactId>
- <version>7.6.8-SNAPSHOT</version>
+ <version>8.1.8-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>jetty-util</artifactId>
@@ -24,7 +24,7 @@
</goals>
<configuration>
<instructions>
- <Import-Package>org.slf4j;version="[1.5,1.7)";resolution:=optional,org.slf4j.impl;version="[1.5,1.7)";resolution:=optional,*</Import-Package>
+ <Import-Package>javax.servlet.*;version="2.6.0",org.slf4j;version="[1.5,2.0)";resolution:=optional,org.slf4j.impl;version="[1.5,2.0)";resolution:=optional,*</Import-Package>
</instructions>
</configuration>
</execution>
@@ -70,6 +70,11 @@
</build>
<dependencies>
<dependency>
+ <groupId>org.eclipse.jetty.orbit</groupId>
+ <artifactId>javax.servlet</artifactId>
+ <scope>provided</scope>
+ </dependency>
+ <dependency>
<groupId>org.eclipse.jetty.toolchain</groupId>
<artifactId>jetty-test-helper</artifactId>
<scope>test</scope>
diff --git a/jetty-util/src/main/java/org/eclipse/jetty/util/MultiMap.java b/jetty-util/src/main/java/org/eclipse/jetty/util/MultiMap.java
index 85bf6110d0..9220d8151d 100644
--- a/jetty-util/src/main/java/org/eclipse/jetty/util/MultiMap.java
+++ b/jetty-util/src/main/java/org/eclipse/jetty/util/MultiMap.java
@@ -86,7 +86,7 @@ public class MultiMap<K> implements ConcurrentMap<K,Object>, Serializable
* @param name The entry key.
* @return Unmodifieable List of values.
*/
- public List<Object> getValues(Object name)
+ public List getValues(Object name)
{
return LazyList.getList(_map.get(name),true);
}
diff --git a/jetty-util/src/main/java/org/eclipse/jetty/util/MultiPartInputStream.java b/jetty-util/src/main/java/org/eclipse/jetty/util/MultiPartInputStream.java
new file mode 100644
index 0000000000..4077ed2852
--- /dev/null
+++ b/jetty-util/src/main/java/org/eclipse/jetty/util/MultiPartInputStream.java
@@ -0,0 +1,750 @@
+//
+// ========================================================================
+// Copyright (c) 1995-2012 Mort Bay Consulting Pty. Ltd.
+// ------------------------------------------------------------------------
+// All rights reserved. This program and the accompanying materials
+// are made available under the terms of the Eclipse Public License v1.0
+// and Apache License v2.0 which accompanies this distribution.
+//
+// The Eclipse Public License is available at
+// http://www.eclipse.org/legal/epl-v10.html
+//
+// The Apache License v2.0 is available at
+// http://www.opensource.org/licenses/apache2.0.php
+//
+// You may elect to redistribute this code under either of these licenses.
+// ========================================================================
+//
+
+package org.eclipse.jetty.util;
+
+import java.io.BufferedInputStream;
+import java.io.BufferedOutputStream;
+import java.io.BufferedReader;
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileNotFoundException;
+import java.io.FileOutputStream;
+import java.io.FilterInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.io.OutputStream;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.StringTokenizer;
+
+import javax.servlet.MultipartConfigElement;
+import javax.servlet.ServletException;
+import javax.servlet.http.Part;
+
+
+
+/**
+ * MultiPartInputStream
+ *
+ * Handle a MultiPart Mime input stream, breaking it up on the boundary into files and strings.
+ */
+public class MultiPartInputStream
+{
+ public static final MultipartConfigElement __DEFAULT_MULTIPART_CONFIG = new MultipartConfigElement(System.getProperty("java.io.tmpdir"));
+ protected InputStream _in;
+ protected MultipartConfigElement _config;
+ protected String _contentType;
+ protected MultiMap<String> _parts;
+ protected File _tmpDir;
+ protected File _contextTmpDir;
+ protected boolean _deleteOnExit;
+
+
+
+ public class MultiPart implements Part
+ {
+ protected String _name;
+ protected String _filename;
+ protected File _file;
+ protected OutputStream _out;
+ protected ByteArrayOutputStream2 _bout;
+ protected String _contentType;
+ protected MultiMap<String> _headers;
+ protected long _size = 0;
+ protected boolean _temporary = true;
+
+ public MultiPart (String name, String filename)
+ throws IOException
+ {
+ _name = name;
+ _filename = filename;
+ }
+
+ protected void setContentType (String contentType)
+ {
+ _contentType = contentType;
+ }
+
+
+ protected void open()
+ throws IOException
+ {
+ //We will either be writing to a file, if it has a filename on the content-disposition
+ //and otherwise a byte-array-input-stream, OR if we exceed the getFileSizeThreshold, we
+ //will need to change to write to a file.
+ if (_filename != null && _filename.trim().length() > 0)
+ {
+ createFile();
+ }
+ else
+ {
+ //Write to a buffer in memory until we discover we've exceed the
+ //MultipartConfig fileSizeThreshold
+ _out = _bout= new ByteArrayOutputStream2();
+ }
+ }
+
+ protected void close()
+ throws IOException
+ {
+ _out.close();
+ }
+
+
+ protected void write (int b)
+ throws IOException
+ {
+ if (MultiPartInputStream.this._config.getMaxFileSize() > 0 && _size + 1 > MultiPartInputStream.this._config.getMaxFileSize())
+ throw new IllegalStateException ("Multipart Mime part "+_name+" exceeds max filesize");
+
+ if (MultiPartInputStream.this._config.getFileSizeThreshold() > 0 && _size + 1 > MultiPartInputStream.this._config.getFileSizeThreshold() && _file==null)
+ createFile();
+ _out.write(b);
+ _size ++;
+ }
+
+ protected void write (byte[] bytes, int offset, int length)
+ throws IOException
+ {
+ if (MultiPartInputStream.this._config.getMaxFileSize() > 0 && _size + length > MultiPartInputStream.this._config.getMaxFileSize())
+ throw new IllegalStateException ("Multipart Mime part "+_name+" exceeds max filesize");
+
+ if (MultiPartInputStream.this._config.getFileSizeThreshold() > 0 && _size + length > MultiPartInputStream.this._config.getFileSizeThreshold() && _file==null)
+ createFile();
+
+ _out.write(bytes, offset, length);
+ _size += length;
+ }
+
+ protected void createFile ()
+ throws IOException
+ {
+ _file = File.createTempFile("MultiPart", "", MultiPartInputStream.this._tmpDir);
+ if (_deleteOnExit)
+ _file.deleteOnExit();
+ FileOutputStream fos = new FileOutputStream(_file);
+ BufferedOutputStream bos = new BufferedOutputStream(fos);
+
+ if (_size > 0 && _out != null)
+ {
+ //already written some bytes, so need to copy them into the file
+ _out.flush();
+ _bout.writeTo(bos);
+ _out.close();
+ _bout = null;
+ }
+ _out = bos;
+ }
+
+
+
+ protected void setHeaders(MultiMap<String> headers)
+ {
+ _headers = headers;
+ }
+
+ /**
+ * @see javax.servlet.http.Part#getContentType()
+ */
+ public String getContentType()
+ {
+ return _contentType;
+ }
+
+ /**
+ * @see javax.servlet.http.Part#getHeader(java.lang.String)
+ */
+ public String getHeader(String name)
+ {
+ if (name == null)
+ return null;
+ return (String)_headers.getValue(name.toLowerCase(), 0);
+ }
+
+ /**
+ * @see javax.servlet.http.Part#getHeaderNames()
+ */
+ public Collection<String> getHeaderNames()
+ {
+ return _headers.keySet();
+ }
+
+ /**
+ * @see javax.servlet.http.Part#getHeaders(java.lang.String)
+ */
+ public Collection<String> getHeaders(String name)
+ {
+ return _headers.getValues(name);
+ }
+
+ /**
+ * @see javax.servlet.http.Part#getInputStream()
+ */
+ public InputStream getInputStream() throws IOException
+ {
+ if (_file != null)
+ {
+ //written to a file, whether temporary or not
+ return new BufferedInputStream (new FileInputStream(_file));
+ }
+ else
+ {
+ //part content is in memory
+ return new ByteArrayInputStream(_bout.getBuf(),0,_bout.size());
+ }
+ }
+
+ public byte[] getBytes()
+ {
+ if (_bout!=null)
+ return _bout.toByteArray();
+ return null;
+ }
+
+ /**
+ * @see javax.servlet.http.Part#getName()
+ */
+ public String getName()
+ {
+ return _name;
+ }
+
+ /**
+ * @see javax.servlet.http.Part#getSize()
+ */
+ public long getSize()
+ {
+ return _size;
+ }
+
+ /**
+ * @see javax.servlet.http.Part#write(java.lang.String)
+ */
+ public void write(String fileName) throws IOException
+ {
+ if (_file == null)
+ {
+ _temporary = false;
+
+ //part data is only in the ByteArrayOutputStream and never been written to disk
+ _file = new File (_tmpDir, fileName);
+
+ BufferedOutputStream bos = null;
+ try
+ {
+ bos = new BufferedOutputStream(new FileOutputStream(_file));
+ _bout.writeTo(bos);
+ bos.flush();
+ }
+ finally
+ {
+ if (bos != null)
+ bos.close();
+ _bout = null;
+ }
+ }
+ else
+ {
+ //the part data is already written to a temporary file, just rename it
+ _temporary = false;
+
+ File f = new File(_tmpDir, fileName);
+ if (_file.renameTo(f))
+ _file = f;
+ }
+ }
+
+ /**
+ * Remove the file, whether or not Part.write() was called on it
+ * (ie no longer temporary)
+ * @see javax.servlet.http.Part#delete()
+ */
+ public void delete() throws IOException
+ {
+ if (_file != null && _file.exists())
+ _file.delete();
+ }
+
+ /**
+ * Only remove tmp files.
+ *
+ * @throws IOException
+ */
+ public void cleanUp() throws IOException
+ {
+ if (_temporary && _file != null && _file.exists())
+ _file.delete();
+ }
+
+
+ /**
+ * Get the file, if any, the data has been written to.
+ * @return
+ */
+ public File getFile ()
+ {
+ return _file;
+ }
+
+
+ /**
+ * Get the filename from the content-disposition.
+ * @return null or the filename
+ */
+ public String getContentDispositionFilename ()
+ {
+ return _filename;
+ }
+ }
+
+
+
+
+ /**
+ * @param in Request input stream
+ * @param contentType Content-Type header
+ * @param config MultipartConfigElement
+ * @param contextTmpDir javax.servlet.context.tempdir
+ */
+ public MultiPartInputStream (InputStream in, String contentType, MultipartConfigElement config, File contextTmpDir)
+ {
+ _in = new BufferedInputStream(in);
+ _contentType = contentType;
+ _config = config;
+ _contextTmpDir = contextTmpDir;
+ if (_contextTmpDir == null)
+ _contextTmpDir = new File (System.getProperty("java.io.tmpdir"));
+
+ if (_config == null)
+ _config = new MultipartConfigElement(_contextTmpDir.getAbsolutePath());
+ }
+
+ /**
+ * Get the already parsed parts.
+ *
+ * @return
+ */
+ public Collection<Part> getParsedParts()
+ {
+ if (_parts == null)
+ return Collections.emptyList();
+
+ Collection<Object> values = _parts.values();
+ List<Part> parts = new ArrayList<Part>();
+ for (Object o: values)
+ {
+ List<Part> asList = LazyList.getList(o, false);
+ parts.addAll(asList);
+ }
+ return parts;
+ }
+
+ /**
+ * Delete any tmp storage for parts, and clear out the parts list.
+ *
+ * @throws MultiException
+ */
+ public void deleteParts ()
+ throws MultiException
+ {
+ Collection<Part> parts = getParsedParts();
+ MultiException err = new MultiException();
+ for (Part p:parts)
+ {
+ try
+ {
+ ((MultiPartInputStream.MultiPart)p).cleanUp();
+ }
+ catch(Exception e)
+ {
+ err.add(e);
+ }
+ }
+ _parts.clear();
+
+ err.ifExceptionThrowMulti();
+ }
+
+
+ /**
+ * Parse, if necessary, the multipart data and return the list of Parts.
+ *
+ * @return
+ * @throws IOException
+ * @throws ServletException
+ */
+ public Collection<Part> getParts()
+ throws IOException, ServletException
+ {
+ parse();
+ Collection<Object> values = _parts.values();
+ List<Part> parts = new ArrayList<Part>();
+ for (Object o: values)
+ {
+ List<Part> asList = LazyList.getList(o, false);
+ parts.addAll(asList);
+ }
+ return parts;
+ }
+
+
+ /**
+ * Get the named Part.
+ *
+ * @param name
+ * @return
+ * @throws IOException
+ * @throws ServletException
+ */
+ public Part getPart(String name)
+ throws IOException, ServletException
+ {
+ parse();
+ return (Part)_parts.getValue(name, 0);
+ }
+
+
+ /**
+ * Parse, if necessary, the multipart stream.
+ *
+ * @throws IOException
+ * @throws ServletException
+ */
+ protected void parse ()
+ throws IOException, ServletException
+ {
+ //have we already parsed the input?
+ if (_parts != null)
+ return;
+
+ //initialize
+ long total = 0; //keep running total of size of bytes read from input and throw an exception if exceeds MultipartConfigElement._maxRequestSize
+ _parts = new MultiMap<String>();
+
+ //if its not a multipart request, don't parse it
+ if (_contentType == null || !_contentType.startsWith("multipart/form-data"))
+ return;
+
+ //sort out the location to which to write the files
+
+ if (_config.getLocation() == null)
+ _tmpDir = _contextTmpDir;
+ else if ("".equals(_config.getLocation()))
+ _tmpDir = _contextTmpDir;
+ else
+ {
+ File f = new File (_config.getLocation());
+ if (f.isAbsolute())
+ _tmpDir = f;
+ else
+ _tmpDir = new File (_contextTmpDir, _config.getLocation());
+ }
+
+ if (!_tmpDir.exists())
+ _tmpDir.mkdirs();
+
+ String boundary="--"+QuotedStringTokenizer.unquote(value(_contentType.substring(_contentType.indexOf("boundary=")), true).trim());
+ byte[] byteBoundary=(boundary+"--").getBytes(StringUtil.__ISO_8859_1);
+
+ // Get first boundary
+ byte[] bytes=TypeUtil.readLine(_in);
+ String line=bytes==null?null:new String(bytes,"UTF-8");
+ if(line==null || !line.equals(boundary))
+ {
+ throw new IOException("Missing initial multi part boundary");
+ }
+
+ // Read each part
+ boolean lastPart=false;
+ String contentDisposition=null;
+ String contentType=null;
+ String contentTransferEncoding=null;
+ outer:while(!lastPart)
+ {
+ MultiMap<String> headers = new MultiMap<String>();
+ while(true)
+ {
+ bytes=TypeUtil.readLine(_in);
+ if(bytes==null)
+ break outer;
+
+ // If blank line, end of part headers
+ if(bytes.length==0)
+ break;
+
+ total += bytes.length;
+ if (_config.getMaxRequestSize() > 0 && total > _config.getMaxRequestSize())
+ throw new IllegalStateException ("Request exceeds maxRequestSize ("+_config.getMaxRequestSize()+")");
+
+ line=new String(bytes,"UTF-8");
+
+ //get content-disposition and content-type
+ int c=line.indexOf(':',0);
+ if(c>0)
+ {
+ String key=line.substring(0,c).trim().toLowerCase();
+ String value=line.substring(c+1,line.length()).trim();
+ headers.put(key, value);
+ if (key.equalsIgnoreCase("content-disposition"))
+ contentDisposition=value;
+ if (key.equalsIgnoreCase("content-type"))
+ contentType = value;
+ if(key.equals("content-transfer-encoding"))
+ contentTransferEncoding=value;
+
+ }
+ }
+
+ // Extract content-disposition
+ boolean form_data=false;
+ if(contentDisposition==null)
+ {
+ throw new IOException("Missing content-disposition");
+ }
+
+ QuotedStringTokenizer tok=new QuotedStringTokenizer(contentDisposition,";");
+ String name=null;
+ String filename=null;
+ while(tok.hasMoreTokens())
+ {
+ String t=tok.nextToken().trim();
+ String tl=t.toLowerCase();
+ if(t.startsWith("form-data"))
+ form_data=true;
+ else if(tl.startsWith("name="))
+ name=value(t, true);
+ else if(tl.startsWith("filename="))
+ filename=value(t, false);
+ }
+
+ // Check disposition
+ if(!form_data)
+ {
+ continue;
+ }
+ //It is valid for reset and submit buttons to have an empty name.
+ //If no name is supplied, the browser skips sending the info for that field.
+ //However, if you supply the empty string as the name, the browser sends the
+ //field, with name as the empty string. So, only continue this loop if we
+ //have not yet seen a name field.
+ if(name==null)
+ {
+ continue;
+ }
+
+ if ("base64".equalsIgnoreCase(contentTransferEncoding))
+ {
+ _in = new Base64InputStream(_in);
+ }
+ else if ("quoted-printable".equalsIgnoreCase(contentTransferEncoding))
+ {
+ _in = new FilterInputStream(_in)
+ {
+ @Override
+ public int read() throws IOException
+ {
+ int c = in.read();
+ if (c >= 0 && c == '=')
+ {
+ int hi = in.read();
+ int lo = in.read();
+ if (hi < 0 || lo < 0)
+ {
+ throw new IOException("Unexpected end to quoted-printable byte");
+ }
+ char[] chars = new char[] { (char)hi, (char)lo };
+ c = Integer.parseInt(new String(chars),16);
+ }
+ return c;
+ }
+ };
+ }
+
+
+
+ //Have a new Part
+ MultiPart part = new MultiPart(name, filename);
+ part.setHeaders(headers);
+ part.setContentType(contentType);
+ _parts.add(name, part);
+
+ part.open();
+
+ try
+ {
+ int state=-2;
+ int c;
+ boolean cr=false;
+ boolean lf=false;
+
+ // loop for all lines`
+ while(true)
+ {
+ int b=0;
+ while((c=(state!=-2)?state:_in.read())!=-1)
+ {
+ total ++;
+ if (_config.getMaxRequestSize() > 0 && total > _config.getMaxRequestSize())
+ throw new IllegalStateException("Request exceeds maxRequestSize ("+_config.getMaxRequestSize()+")");
+
+ state=-2;
+ // look for CR and/or LF
+ if(c==13||c==10)
+ {
+ if(c==13)
+ state=_in.read();
+ break;
+ }
+ // look for boundary
+ if(b>=0&&b<byteBoundary.length&&c==byteBoundary[b])
+ b++;
+ else
+ {
+ // this is not a boundary
+ if(cr)
+ part.write(13);
+
+ if(lf)
+ part.write(10);
+
+ cr=lf=false;
+ if(b>0)
+ part.write(byteBoundary,0,b);
+
+ b=-1;
+ part.write(c);
+ }
+ }
+ // check partial boundary
+ if((b>0&&b<byteBoundary.length-2)||(b==byteBoundary.length-1))
+ {
+ if(cr)
+ part.write(13);
+
+ if(lf)
+ part.write(10);
+
+ cr=lf=false;
+ part.write(byteBoundary,0,b);
+ b=-1;
+ }
+ // boundary match
+ if(b>0||c==-1)
+ {
+ if(b==byteBoundary.length)
+ lastPart=true;
+ if(state==10)
+ state=-2;
+ break;
+ }
+ // handle CR LF
+ if(cr)
+ part.write(13);
+
+ if(lf)
+ part.write(10);
+
+ cr=(c==13);
+ lf=(c==10||state==10);
+ if(state==10)
+ state=-2;
+ }
+ }
+ finally
+ {
+
+ part.close();
+ }
+ }
+ if (!lastPart)
+ throw new IOException("Incomplete parts");
+ }
+
+ public void setDeleteOnExit(boolean deleteOnExit)
+ {
+ _deleteOnExit = deleteOnExit;
+ }
+
+
+ public boolean isDeleteOnExit()
+ {
+ return _deleteOnExit;
+ }
+
+
+ /* ------------------------------------------------------------ */
+ private String value(String nameEqualsValue, boolean splitAfterSpace)
+ {
+ String value=nameEqualsValue.substring(nameEqualsValue.indexOf('=')+1).trim();
+ int i=value.indexOf(';');
+ if(i>0)
+ value=value.substring(0,i);
+ if(value.startsWith("\""))
+ {
+ value=value.substring(1,value.indexOf('"',1));
+ }
+ else if (splitAfterSpace)
+ {
+ i=value.indexOf(' ');
+ if(i>0)
+ value=value.substring(0,i);
+ }
+ return value;
+ }
+
+ private static class Base64InputStream extends InputStream
+ {
+ BufferedReader _in;
+ String _line;
+ byte[] _buffer;
+ int _pos;
+
+ public Base64InputStream (InputStream in)
+ {
+ _in = new BufferedReader(new InputStreamReader(in));
+ }
+
+ @Override
+ public int read() throws IOException
+ {
+ if (_buffer==null || _pos>= _buffer.length)
+ {
+ _line = _in.readLine();
+ if (_line==null)
+ return -1;
+ if (_line.startsWith("--"))
+ _buffer=(_line+"\r\n").getBytes();
+ else if (_line.length()==0)
+ _buffer="\r\n".getBytes();
+ else
+ _buffer=B64Code.decode(_line);
+
+ _pos=0;
+ }
+ return _buffer[_pos++];
+ }
+ }
+}
diff --git a/jetty-util/src/test/java/org/eclipse/jetty/util/MultiPartInputStreamTest.java b/jetty-util/src/test/java/org/eclipse/jetty/util/MultiPartInputStreamTest.java
new file mode 100644
index 0000000000..fffda46b32
--- /dev/null
+++ b/jetty-util/src/test/java/org/eclipse/jetty/util/MultiPartInputStreamTest.java
@@ -0,0 +1,328 @@
+//
+// ========================================================================
+// Copyright (c) 1995-2012 Mort Bay Consulting Pty. Ltd.
+// ------------------------------------------------------------------------
+// All rights reserved. This program and the accompanying materials
+// are made available under the terms of the Eclipse Public License v1.0
+// and Apache License v2.0 which accompanies this distribution.
+//
+// The Eclipse Public License is available at
+// http://www.eclipse.org/legal/epl-v10.html
+//
+// The Apache License v2.0 is available at
+// http://www.opensource.org/licenses/apache2.0.php
+//
+// You may elect to redistribute this code under either of these licenses.
+// ========================================================================
+//
+
+package org.eclipse.jetty.util;
+
+import static org.hamcrest.Matchers.is;
+import static org.hamcrest.Matchers.not;
+import static org.hamcrest.Matchers.notNullValue;
+import static org.hamcrest.Matchers.nullValue;
+import static org.junit.Assert.assertThat;
+
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.Collection;
+
+import javax.servlet.MultipartConfigElement;
+import javax.servlet.ServletException;
+import javax.servlet.http.Part;
+
+import junit.framework.TestCase;
+
+import org.eclipse.jetty.util.MultiPartInputStream.MultiPart;
+
+/**
+ * MultiPartInputStreamTest
+ *
+ *
+ */
+public class MultiPartInputStreamTest extends TestCase
+{
+ private static final String FILENAME = "stuff.txt";
+ protected String _contentType = "multipart/form-data, boundary=AaB03x";
+ protected String _multi = createMultipartRequestString(FILENAME);
+ protected String _dirname = System.getProperty("java.io.tmpdir")+File.separator+"myfiles-"+System.currentTimeMillis();
+ protected File _tmpDir = new File(_dirname);
+
+ public MultiPartInputStreamTest ()
+ {
+ _tmpDir.deleteOnExit();
+ }
+
+ public void testBadMultiPartRequest()
+ throws Exception
+ {
+ String boundary = "X0Y0";
+ String str = "--" + boundary + "\r\n"+
+ "Content-Disposition: form-data; name=\"fileup\"; filename=\"test.upload\"\r\n"+
+ "Content-Type: application/octet-stream\r\n\r\n"+
+ "How now brown cow."+
+ "\r\n--" + boundary + "-\r\n\r\n";
+
+ MultipartConfigElement config = new MultipartConfigElement(_dirname, 1024, 3072, 50);
+ MultiPartInputStream mpis = new MultiPartInputStream(new ByteArrayInputStream(str.getBytes()),
+ "multipart/form-data, boundary="+boundary,
+ config,
+ _tmpDir);
+ mpis.setDeleteOnExit(true);
+ try
+ {
+ mpis.getParts();
+ fail ("Multipart incomplete");
+ }
+ catch (IOException e)
+ {
+ assertTrue(e.getMessage().startsWith("Incomplete"));
+ }
+ }
+
+
+
+ public void testNonMultiPartRequest()
+ throws Exception
+ {
+ MultipartConfigElement config = new MultipartConfigElement(_dirname, 1024, 3072, 50);
+ MultiPartInputStream mpis = new MultiPartInputStream(new ByteArrayInputStream(_multi.getBytes()),
+ "Content-type: text/plain",
+ config,
+ _tmpDir);
+ mpis.setDeleteOnExit(true);
+ assertTrue(mpis.getParts().isEmpty());
+ }
+
+ public void testNoLimits()
+ throws Exception
+ {
+ MultipartConfigElement config = new MultipartConfigElement(_dirname);
+ MultiPartInputStream mpis = new MultiPartInputStream(new ByteArrayInputStream(_multi.getBytes()),
+ _contentType,
+ config,
+ _tmpDir);
+ mpis.setDeleteOnExit(true);
+ Collection<Part> parts = mpis.getParts();
+ assertFalse(parts.isEmpty());
+ }
+
+ public void testRequestTooBig ()
+ throws Exception
+ {
+ MultipartConfigElement config = new MultipartConfigElement(_dirname, 60, 100, 50);
+ MultiPartInputStream mpis = new MultiPartInputStream(new ByteArrayInputStream(_multi.getBytes()),
+ _contentType,
+ config,
+ _tmpDir);
+ mpis.setDeleteOnExit(true);
+ Collection<Part> parts = null;
+ try
+ {
+ parts = mpis.getParts();
+ fail("Request should have exceeded maxRequestSize");
+ }
+ catch (IllegalStateException e)
+ {
+ assertTrue(e.getMessage().startsWith("Request exceeds maxRequestSize"));
+ }
+ }
+
+ public void testFileTooBig()
+ throws Exception
+ {
+ MultipartConfigElement config = new MultipartConfigElement(_dirname, 40, 1024, 30);
+ MultiPartInputStream mpis = new MultiPartInputStream(new ByteArrayInputStream(_multi.getBytes()),
+ _contentType,
+ config,
+ _tmpDir);
+ mpis.setDeleteOnExit(true);
+ Collection<Part> parts = null;
+ try
+ {
+ parts = mpis.getParts();
+ fail("stuff.txt should have been larger than maxFileSize");
+ }
+ catch (IllegalStateException e)
+ {
+ assertTrue(e.getMessage().startsWith("Multipart Mime part"));
+ }
+ }
+
+ public void testPartFileNotDeleted () throws Exception
+ {
+ MultipartConfigElement config = new MultipartConfigElement(_dirname, 1024, 3072, 50);
+ MultiPartInputStream mpis = new MultiPartInputStream(new ByteArrayInputStream(createMultipartRequestString("tptfd").getBytes()),
+ _contentType,
+ config,
+ _tmpDir);
+ mpis.setDeleteOnExit(true);
+ Collection<Part> parts = mpis.getParts();
+
+ MultiPart part = (MultiPart)mpis.getPart("stuff");
+ File stuff = ((MultiPartInputStream.MultiPart)part).getFile();
+ assertThat(stuff,notNullValue()); // longer than 100 bytes, should already be a tmp file
+ part.write("tptfd.txt");
+ File tptfd = new File (_dirname+File.separator+"tptfd.txt");
+ assertThat(tptfd.exists(), is(true));
+ assertThat(stuff.exists(), is(false)); //got renamed
+ part.cleanUp();
+ assertThat(tptfd.exists(), is(true)); //explicitly written file did not get removed after cleanup
+ tptfd.deleteOnExit(); //clean up test
+ }
+
+
+ public void testPartTmpFileDeletion () throws Exception
+ {
+ MultipartConfigElement config = new MultipartConfigElement(_dirname, 1024, 3072, 50);
+ MultiPartInputStream mpis = new MultiPartInputStream(new ByteArrayInputStream(createMultipartRequestString("tptfd").getBytes()),
+ _contentType,
+ config,
+ _tmpDir);
+ mpis.setDeleteOnExit(true);
+ Collection<Part> parts = mpis.getParts();
+
+ MultiPart part = (MultiPart)mpis.getPart("stuff");
+ File stuff = ((MultiPartInputStream.MultiPart)part).getFile();
+ assertThat(stuff,notNullValue()); // longer than 100 bytes, should already be a tmp file
+ assertThat (stuff.exists(), is(true));
+ part.cleanUp();
+ assertThat(stuff.exists(), is(false)); //tmp file was removed after cleanup
+ }
+
+
+
+ public void testMulti ()
+ throws Exception
+ {
+ testMulti(FILENAME);
+ }
+
+ public void testMultiWithSpaceInFilename() throws Exception
+ {
+ testMulti("stuff with spaces.txt");
+ }
+
+ private void testMulti(String filename) throws IOException, ServletException
+ {
+ MultipartConfigElement config = new MultipartConfigElement(_dirname, 1024, 3072, 50);
+ MultiPartInputStream mpis = new MultiPartInputStream(new ByteArrayInputStream(createMultipartRequestString(filename).getBytes()),
+ _contentType,
+ config,
+ _tmpDir);
+ mpis.setDeleteOnExit(true);
+ Collection<Part> parts = mpis.getParts();
+ assertThat(parts.size(), is(2));
+ Part field1 = mpis.getPart("field1"); //field 1 too small to go into tmp file, should be in internal buffer
+ assertThat(field1,notNullValue());
+ assertThat(field1.getName(),is("field1"));
+ InputStream is = field1.getInputStream();
+ ByteArrayOutputStream os = new ByteArrayOutputStream();
+ IO.copy(is, os);
+ assertEquals("Joe Blow", new String(os.toByteArray()));
+ assertEquals(8, field1.getSize());
+
+ assertNotNull(((MultiPartInputStream.MultiPart)field1).getBytes());//in internal buffer
+ field1.write("field1.txt");
+ assertNull(((MultiPartInputStream.MultiPart)field1).getBytes());//no longer in internal buffer
+ File f = new File (_dirname+File.separator+"field1.txt");
+ assertTrue(f.exists());
+ field1.write("another_field1.txt"); //write after having already written
+ File f2 = new File(_dirname+File.separator+"another_field1.txt");
+ assertTrue(f2.exists());
+ assertFalse(f.exists()); //should have been renamed
+ field1.delete(); //file should be deleted
+ assertFalse(f.exists()); //original file was renamed
+ assertFalse(f2.exists()); //2nd written file was explicitly deleted
+
+ MultiPart stuff = (MultiPart)mpis.getPart("stuff");
+ assertThat(stuff.getContentDispositionFilename(), is(filename));
+ assertThat(stuff.getContentType(),is("text/plain"));
+ assertThat(stuff.getHeader("Content-Type"),is("text/plain"));
+ assertThat(stuff.getHeaders("content-type").size(),is(1));
+ assertThat(stuff.getHeader("content-disposition"),is("form-data; name=\"stuff\"; filename=\"" + filename + "\""));
+ assertThat(stuff.getHeaderNames().size(),is(2));
+ assertThat(stuff.getSize(),is(51L));
+ File tmpfile = ((MultiPartInputStream.MultiPart)stuff).getFile();
+ assertThat(tmpfile,notNullValue()); // longer than 100 bytes, should already be a tmp file
+ assertThat(((MultiPartInputStream.MultiPart)stuff).getBytes(),nullValue()); //not in an internal buffer
+ assertThat(tmpfile.exists(),is(true));
+ assertThat(tmpfile.getName(),is(not("stuff with space.txt")));
+ stuff.write(filename);
+ f = new File(_dirname+File.separator+filename);
+ assertThat(f.exists(),is(true));
+ assertThat(tmpfile.exists(), is(false));
+ try
+ {
+ stuff.getInputStream();
+ }
+ catch (Exception e)
+ {
+ fail("Part.getInputStream() after file rename operation");
+ }
+ f.deleteOnExit(); //clean up after test
+ }
+
+ public void testMultiSameNames ()
+ throws Exception
+ {
+ String sameNames = "--AaB03x\r\n"+
+ "content-disposition: form-data; name=\"stuff\"; filename=\"stuff1.txt\"\r\n"+
+ "Content-Type: text/plain\r\n"+
+ "\r\n"+
+ "00000\r\n"+
+ "--AaB03x\r\n"+
+ "content-disposition: form-data; name=\"stuff\"; filename=\"stuff2.txt\"\r\n"+
+ "Content-Type: text/plain\r\n"+
+ "\r\n"+
+ "110000000000000000000000000000000000000000000000000\r\n"+
+ "--AaB03x--\r\n";
+
+ MultipartConfigElement config = new MultipartConfigElement(_dirname, 1024, 3072, 50);
+ MultiPartInputStream mpis = new MultiPartInputStream(new ByteArrayInputStream(sameNames.getBytes()),
+ _contentType,
+ config,
+ _tmpDir);
+ mpis.setDeleteOnExit(true);
+ Collection<Part> parts = mpis.getParts();
+ assertEquals(2, parts.size());
+ for (Part p:parts)
+ assertEquals("stuff", p.getName());
+
+ //if they all have the name name, then only retrieve the first one
+ Part p = mpis.getPart("stuff");
+ assertNotNull(p);
+ assertEquals(5, p.getSize());
+ }
+
+ private String createMultipartRequestString(String filename)
+ {
+ int length = filename.length();
+ String name = filename;
+ if (length > 10)
+ name = filename.substring(0,10);
+ StringBuffer filler = new StringBuffer();
+ int i = name.length();
+ while (i < 51)
+ {
+ filler.append("0");
+ i++;
+ }
+
+ return "--AaB03x\r\n"+
+ "content-disposition: form-data; name=\"field1\"\r\n"+
+ "\r\n"+
+ "Joe Blow\r\n"+
+ "--AaB03x\r\n"+
+ "content-disposition: form-data; name=\"stuff\"; filename=\"" + filename + "\"\r\n"+
+ "Content-Type: text/plain\r\n"+
+ "\r\n"+name+
+ filler.toString()+"\r\n" +
+ "--AaB03x--\r\n";
+ }
+}
diff --git a/jetty-util/src/test/java/org/eclipse/jetty/util/resource/ResourceTest.java b/jetty-util/src/test/java/org/eclipse/jetty/util/resource/ResourceTest.java
index 28a4d39699..caa24d1732 100644
--- a/jetty-util/src/test/java/org/eclipse/jetty/util/resource/ResourceTest.java
+++ b/jetty-util/src/test/java/org/eclipse/jetty/util/resource/ResourceTest.java
@@ -115,21 +115,21 @@ public class ResourceTest
/* ------------------------------------------------------------ */
@BeforeClass
public static void setUp()
- throws Exception
+ throws Exception
{
if (data!=null)
return;
-
+
File file = new File(__userDir);
file=new File(file.getCanonicalPath());
URI uri = file.toURI();
__userURL=uri.toURL();
-
+
__userURL = new URL(__userURL.toString() + "src/test/java/org/eclipse/jetty/util/resource/");
- FilePermission perm = (FilePermission) __userURL.openConnection().getPermission();
- __userDir = new File(perm.getName()).getCanonicalPath() + File.separatorChar;
- __relDir = "src/test/java/org/eclipse/jetty/util/resource/".replace('/', File.separatorChar);
-
+ FilePermission perm = (FilePermission) __userURL.openConnection().getPermission();
+ __userDir = new File(perm.getName()).getCanonicalPath() + File.separatorChar;
+ __relDir = "src/test/java/org/eclipse/jetty/util/resource/".replace('/', File.separatorChar);
+
System.err.println("User Dir="+__userDir);
System.err.println("Rel Dir="+__relDir);
System.err.println("User URL="+__userURL);
diff --git a/jetty-util/src/test/java/org/eclipse/jetty/util/thread/TimeoutTest.java b/jetty-util/src/test/java/org/eclipse/jetty/util/thread/TimeoutTest.java
index 9cf9496f31..972f6b3bff 100644
--- a/jetty-util/src/test/java/org/eclipse/jetty/util/thread/TimeoutTest.java
+++ b/jetty-util/src/test/java/org/eclipse/jetty/util/thread/TimeoutTest.java
@@ -29,6 +29,8 @@ import org.junit.Test;
public class TimeoutTest
{
+ private boolean _stress=Boolean.getBoolean("STRESS");
+
Object lock = new Object();
Timeout timeout = new Timeout(null);
Timeout.Task[] tasks;
@@ -136,6 +138,9 @@ public class TimeoutTest
@Test
public void testStress() throws Exception
{
+ if ( !_stress )
+ return;
+
final int LOOP=250;
final AtomicBoolean running=new AtomicBoolean(true);
final AtomicIntegerArray count = new AtomicIntegerArray( 4 );
diff --git a/jetty-webapp/pom.xml b/jetty-webapp/pom.xml
index a088601b74..85d2c3d484 100644
--- a/jetty-webapp/pom.xml
+++ b/jetty-webapp/pom.xml
@@ -2,7 +2,7 @@
<parent>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-project</artifactId>
- <version>7.6.8-SNAPSHOT</version>
+ <version>8.1.8-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>jetty-webapp</artifactId>
@@ -52,6 +52,11 @@
<goals>
<goal>manifest</goal>
</goals>
+ <configuration>
+ <instructions>
+ <Import-Package>javax.servlet.*;version="2.6.0",*</Import-Package>
+ </instructions>
+ </configuration>
</execution>
</executions>
</plugin>
diff --git a/jetty-webapp/src/main/java/org/eclipse/jetty/webapp/DiscoveredAnnotation.java b/jetty-webapp/src/main/java/org/eclipse/jetty/webapp/DiscoveredAnnotation.java
index 8df641817d..988414b85f 100644
--- a/jetty-webapp/src/main/java/org/eclipse/jetty/webapp/DiscoveredAnnotation.java
+++ b/jetty-webapp/src/main/java/org/eclipse/jetty/webapp/DiscoveredAnnotation.java
@@ -21,6 +21,7 @@ package org.eclipse.jetty.webapp;
import org.eclipse.jetty.util.Loader;
import org.eclipse.jetty.util.log.Log;
import org.eclipse.jetty.util.log.Logger;
+import org.eclipse.jetty.util.resource.Resource;
/**
* DiscoveredAnnotation
@@ -36,15 +37,27 @@ public abstract class DiscoveredAnnotation
protected WebAppContext _context;
protected String _className;
protected Class<?> _clazz;
+ protected Resource _resource; //resource it was discovered on, can be null (eg from WEB-INF/classes)
public abstract void apply();
public DiscoveredAnnotation (WebAppContext context, String className)
{
+ this(context,className, null);
+ }
+
+
+ public DiscoveredAnnotation(WebAppContext context, String className, Resource resource)
+ {
_context = context;
_className = className;
- }
+ _resource = resource;
+ }
+ public Resource getResource ()
+ {
+ return _resource;
+ }
public Class<?> getTargetClass()
{
diff --git a/jetty-webapp/src/main/java/org/eclipse/jetty/webapp/FragmentDescriptor.java b/jetty-webapp/src/main/java/org/eclipse/jetty/webapp/FragmentDescriptor.java
index 884301ba13..3f185df449 100644
--- a/jetty-webapp/src/main/java/org/eclipse/jetty/webapp/FragmentDescriptor.java
+++ b/jetty-webapp/src/main/java/org/eclipse/jetty/webapp/FragmentDescriptor.java
@@ -136,7 +136,7 @@ public class FragmentDescriptor extends WebDescriptor
node = (XmlParser.Node) o;
if (node.getTag().equalsIgnoreCase("others"))
{
- if (_otherType != OtherType.After)
+ if (_otherType != OtherType.None)
throw new IllegalStateException("Duplicate <other> clause detected in "+_xml.getURI());
_otherType = OtherType.After;
diff --git a/jetty-webapp/src/main/java/org/eclipse/jetty/webapp/JettyWebXmlConfiguration.java b/jetty-webapp/src/main/java/org/eclipse/jetty/webapp/JettyWebXmlConfiguration.java
index 4975c54c31..aab89c33ed 100644
--- a/jetty-webapp/src/main/java/org/eclipse/jetty/webapp/JettyWebXmlConfiguration.java
+++ b/jetty-webapp/src/main/java/org/eclipse/jetty/webapp/JettyWebXmlConfiguration.java
@@ -18,6 +18,7 @@
package org.eclipse.jetty.webapp;
+import java.util.HashMap;
import java.util.Map;
import org.eclipse.jetty.util.log.Log;
@@ -30,7 +31,7 @@ import org.eclipse.jetty.xml.XmlConfiguration;
*
* JettyWebConfiguration.
*
- * Looks for Xmlconfiguration files in WEB-INF. Searches in order for the first of jettyX-web.xml, jetty-web.xml or web-jetty.xml
+ * Looks for Xmlconfiguration files in WEB-INF. Searches in order for the first of jetty6-web.xml, jetty-web.xml or web-jetty.xml
*
*
*
@@ -70,7 +71,7 @@ public class JettyWebXmlConfiguration extends AbstractConfiguration
if(web_inf!=null&&web_inf.isDirectory())
{
// do jetty.xml file
- Resource jetty=web_inf.addPath("jetty7-web.xml");
+ Resource jetty=web_inf.addPath("jetty8-web.xml");
if(!jetty.exists())
jetty=web_inf.addPath(JETTY_WEB_XML);
if(!jetty.exists())
@@ -133,6 +134,13 @@ public class JettyWebXmlConfiguration extends AbstractConfiguration
private void setupXmlConfiguration(XmlConfiguration jetty_config, Resource web_inf)
{
Map<String,String> props = jetty_config.getProperties();
+ if (props == null)
+ {
+ props = new HashMap<String, String>();
+ jetty_config.setProperties(props);
+ }
+
+ // TODO - should this be an id rather than a property?
props.put(PROPERTY_THIS_WEB_INF_URL, String.valueOf(web_inf.getURL()));
}
}
diff --git a/jetty-webapp/src/main/java/org/eclipse/jetty/webapp/MetaData.java b/jetty-webapp/src/main/java/org/eclipse/jetty/webapp/MetaData.java
index d6e6982124..cdd84b705d 100644
--- a/jetty-webapp/src/main/java/org/eclipse/jetty/webapp/MetaData.java
+++ b/jetty-webapp/src/main/java/org/eclipse/jetty/webapp/MetaData.java
@@ -24,6 +24,8 @@ import java.util.HashMap;
import java.util.List;
import java.util.Map;
+import javax.servlet.ServletContext;
+
import org.eclipse.jetty.util.log.Log;
import org.eclipse.jetty.util.log.Logger;
import org.eclipse.jetty.util.resource.Resource;
@@ -168,6 +170,8 @@ public class MetaData
_webXmlRoot.parse();
_metaDataComplete=_webXmlRoot.getMetaDataComplete() == MetaDataComplete.True;
+
+
if (_webXmlRoot.isOrdered())
{
if (_ordering == null)
@@ -197,7 +201,7 @@ public class MetaData
_metaDataComplete=true;
break;
case False:
- _metaDataComplete=true;
+ _metaDataComplete=false;
break;
case NotSet:
break;
@@ -267,12 +271,42 @@ public class MetaData
*/
public void addDiscoveredAnnotations(List<DiscoveredAnnotation> annotations)
{
- _annotations.addAll(annotations);
+ if (annotations == null)
+ return;
+ for (DiscoveredAnnotation a:annotations)
+ {
+ Resource r = a.getResource();
+ if (r == null || !_webInfJars.contains(r))
+ _annotations.add(a);
+ else
+ addDiscoveredAnnotation(a.getResource(), a);
+
+ }
+ }
+
+
+ public void addDiscoveredAnnotation(Resource resource, DiscoveredAnnotation annotation)
+ {
+ List<DiscoveredAnnotation> list = _webFragmentAnnotations.get(resource);
+ if (list == null)
+ {
+ list = new ArrayList<DiscoveredAnnotation>();
+ _webFragmentAnnotations.put(resource, list);
+ }
+ list.add(annotation);
}
+
public void addDiscoveredAnnotations(Resource resource, List<DiscoveredAnnotation> annotations)
{
- _webFragmentAnnotations.put(resource, new ArrayList<DiscoveredAnnotation>(annotations));
+ List<DiscoveredAnnotation> list = _webFragmentAnnotations.get(resource);
+ if (list == null)
+ {
+ list = new ArrayList<DiscoveredAnnotation>();
+ _webFragmentAnnotations.put(resource, list);
+ }
+
+ list.addAll(annotations);
}
public void addDescriptorProcessor(DescriptorProcessor p)
@@ -317,7 +351,14 @@ public class MetaData
int j = fullname.lastIndexOf("/", i);
orderedLibs.add(fullname.substring(j+1,i+4));
}
- context.setAttribute(ORDERED_LIBS, orderedLibs);
+ context.setAttribute(ServletContext.ORDERED_LIBS, orderedLibs);
+ }
+
+ // set the webxml version
+ if (_webXmlRoot != null)
+ {
+ context.getServletContext().setEffectiveMajorVersion(_webXmlRoot.getMajorVersion());
+ context.getServletContext().setEffectiveMinorVersion(_webXmlRoot.getMinorVersion());
}
for (DescriptorProcessor p:_descriptorProcessors)
@@ -497,6 +538,15 @@ public class MetaData
OriginInfo x = new OriginInfo (name, Origin.Annotation);
_origins.put(name, x);
}
+
+ public void setOrigin(String name, Origin origin)
+ {
+ if (name == null)
+ return;
+
+ OriginInfo x = new OriginInfo (name, origin);
+ _origins.put(name, x);
+ }
public boolean isMetaDataComplete()
{
diff --git a/jetty-webapp/src/main/java/org/eclipse/jetty/webapp/MetaInfConfiguration.java b/jetty-webapp/src/main/java/org/eclipse/jetty/webapp/MetaInfConfiguration.java
index 2190c30050..64f2dbab87 100644
--- a/jetty-webapp/src/main/java/org/eclipse/jetty/webapp/MetaInfConfiguration.java
+++ b/jetty-webapp/src/main/java/org/eclipse/jetty/webapp/MetaInfConfiguration.java
@@ -84,6 +84,17 @@ public class MetaInfConfiguration extends AbstractConfiguration
scanner.scan(null, uris, true);
}
}
+ @Override
+ public void configure(WebAppContext context) throws Exception
+ {
+
+ }
+
+ @Override
+ public void deconfigure(WebAppContext context) throws Exception
+ {
+
+ }
@Override
public void postConfigure(WebAppContext context) throws Exception
diff --git a/jetty-webapp/src/main/java/org/eclipse/jetty/webapp/Ordering.java b/jetty-webapp/src/main/java/org/eclipse/jetty/webapp/Ordering.java
index 7b0ada076c..3cdb86cefb 100644
--- a/jetty-webapp/src/main/java/org/eclipse/jetty/webapp/Ordering.java
+++ b/jetty-webapp/src/main/java/org/eclipse/jetty/webapp/Ordering.java
@@ -62,6 +62,7 @@ public interface Ordering
* Order the list of jars in WEB-INF/lib according to the ordering declarations in the descriptors
* @see org.eclipse.jetty.webapp.Ordering#order(java.util.List)
*/
+ @Override
public List<Resource> order(List<Resource> jars)
{
List<Resource> orderedList = new ArrayList<Resource>();
@@ -99,7 +100,7 @@ public interface Ordering
return orderedList;
}
-
+ @Override
public boolean isAbsolute()
{
return true;
@@ -119,7 +120,7 @@ public interface Ordering
_order.add(OTHER);
}
-
+ @Override
public boolean hasOther ()
{
return _hasOther;
@@ -146,7 +147,7 @@ public interface Ordering
* in the various web-fragment.xml files.
* @see org.eclipse.jetty.webapp.Ordering#order(java.util.List)
*/
-
+ @Override
public List<Resource> order(List<Resource> jars)
{
//for each jar, put it into the ordering according to the fragment ordering
@@ -216,13 +217,13 @@ public interface Ordering
return orderedList;
}
-
+ @Override
public boolean isAbsolute ()
{
return false;
}
-
+ @Override
public boolean hasOther ()
{
return !_beforeOthers.isEmpty() || !_afterOthers.isEmpty();
diff --git a/jetty-webapp/src/main/java/org/eclipse/jetty/webapp/Origin.java b/jetty-webapp/src/main/java/org/eclipse/jetty/webapp/Origin.java
index 1481b3804f..f2f941c478 100644
--- a/jetty-webapp/src/main/java/org/eclipse/jetty/webapp/Origin.java
+++ b/jetty-webapp/src/main/java/org/eclipse/jetty/webapp/Origin.java
@@ -18,4 +18,4 @@
package org.eclipse.jetty.webapp;
-public enum Origin {NotSet, WebXml, WebDefaults, WebOverride, WebFragment, Annotation} \ No newline at end of file
+public enum Origin {NotSet, WebXml, WebDefaults, WebOverride, WebFragment, Annotation, API} \ No newline at end of file
diff --git a/jetty-webapp/src/main/java/org/eclipse/jetty/webapp/StandardDescriptorProcessor.java b/jetty-webapp/src/main/java/org/eclipse/jetty/webapp/StandardDescriptorProcessor.java
index cc308ed30f..074aade440 100644
--- a/jetty-webapp/src/main/java/org/eclipse/jetty/webapp/StandardDescriptorProcessor.java
+++ b/jetty-webapp/src/main/java/org/eclipse/jetty/webapp/StandardDescriptorProcessor.java
@@ -23,23 +23,36 @@ import java.io.IOException;
import java.net.URL;
import java.net.URLClassLoader;
import java.util.ArrayList;
+import java.util.Collection;
import java.util.EnumSet;
import java.util.EventListener;
+import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Locale;
import java.util.Map;
+import java.util.Set;
+import javax.servlet.DispatcherType;
+import javax.servlet.MultipartConfigElement;
import javax.servlet.ServletException;
+import javax.servlet.ServletRegistration;
+import javax.servlet.SessionTrackingMode;
+import javax.servlet.descriptor.JspConfigDescriptor;
+import javax.servlet.descriptor.JspPropertyGroupDescriptor;
+import javax.servlet.descriptor.TaglibDescriptor;
import org.eclipse.jetty.security.ConstraintAware;
import org.eclipse.jetty.security.ConstraintMapping;
import org.eclipse.jetty.security.authentication.FormAuthenticator;
-import org.eclipse.jetty.server.DispatcherType;
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.ServletContextHandler;
+import org.eclipse.jetty.servlet.ServletContextHandler.JspConfig;
+import org.eclipse.jetty.servlet.ServletContextHandler.JspPropertyGroup;
+import org.eclipse.jetty.servlet.ServletContextHandler.TagLib;
import org.eclipse.jetty.servlet.ServletHolder;
import org.eclipse.jetty.servlet.ServletMapping;
import org.eclipse.jetty.util.LazyList;
@@ -194,7 +207,7 @@ public class StandardDescriptorProcessor extends IterativeDescriptorProcessor
*/
if (holder == null)
{
- holder = context.getServletHandler().newServletHolder();
+ holder = context.getServletHandler().newServletHolder(Holder.Source.DESCRIPTOR);
holder.setName(servlet_name);
context.getServletHandler().addServlet(holder);
}
@@ -458,6 +471,136 @@ public class StandardDescriptorProcessor extends IterativeDescriptorProcessor
}
}
}
+
+ String async=node.getString("async-supported",false,true);
+ if (async!=null)
+ {
+ boolean val = async.length()==0||Boolean.valueOf(async);
+ Origin o =context.getMetaData().getOrigin(servlet_name+".servlet.async-supported");
+ switch (o)
+ {
+ case NotSet:
+ {
+ //set it
+ holder.setAsyncSupported(val);
+ context.getMetaData().setOrigin(servlet_name+".servlet.async-supported", descriptor);
+ break;
+ }
+ case WebXml:
+ case WebDefaults:
+ case WebOverride:
+ {
+ //async-supported set by previous web xml descriptor, only allow override if we're parsing another web descriptor(web.xml/web-override.xml/web-default.xml)
+ if (!(descriptor instanceof FragmentDescriptor))
+ {
+ holder.setAsyncSupported(val);
+ context.getMetaData().setOrigin(servlet_name+".servlet.async-supported", descriptor);
+ }
+ break;
+ }
+ case WebFragment:
+ {
+ //async-supported set by another fragment, this fragment's value must match
+ if (holder.isAsyncSupported() != val)
+ throw new IllegalStateException("Conflicting async-supported="+async+" for servlet "+servlet_name+" in "+descriptor.getResource());
+ break;
+ }
+ }
+ }
+
+ String enabled = node.getString("enabled", false, true);
+ if (enabled!=null)
+ {
+ boolean is_enabled = enabled.length()==0||Boolean.valueOf(enabled);
+ Origin o = context.getMetaData().getOrigin(servlet_name+".servlet.enabled");
+ switch (o)
+ {
+ case NotSet:
+ {
+ //hasn't been set yet, so set it
+ holder.setEnabled(is_enabled);
+ context.getMetaData().setOrigin(servlet_name+".servlet.enabled", descriptor);
+ break;
+ }
+ case WebXml:
+ case WebDefaults:
+ case WebOverride:
+ {
+ //was set in a web xml descriptor, only allow override from another web xml descriptor
+ if (!(descriptor instanceof FragmentDescriptor))
+ {
+ holder.setEnabled(is_enabled);
+ context.getMetaData().setOrigin(servlet_name+".servlet.enabled", descriptor);
+ }
+ break;
+ }
+ case WebFragment:
+ {
+ //was set by another fragment, this fragment's value must match
+ if (holder.isEnabled() != is_enabled)
+ throw new IllegalStateException("Conflicting value of servlet enabled for servlet "+servlet_name+" in "+descriptor.getResource());
+ break;
+ }
+ }
+ }
+
+ /*
+ * If multipart config not set, then set it and record it was by the web.xml or fragment.
+ * If it was set by web.xml then if this is a fragment, ignore the settings.
+ * If it was set by a fragment, if this is a fragment and the values are different, error!
+ */
+ XmlParser.Node multipart = node.get("multipart-config");
+ if (multipart != null)
+ {
+ String location = multipart.getString("location", false, true);
+ String maxFile = multipart.getString("max-file-size", false, true);
+ String maxRequest = multipart.getString("max-request-size", false, true);
+ String threshold = multipart.getString("file-size-threshold",false,true);
+ MultipartConfigElement element = new MultipartConfigElement(location,
+ (maxFile==null||"".equals(maxFile)?-1L:Long.parseLong(maxFile)),
+ (maxRequest==null||"".equals(maxRequest)?-1L:Long.parseLong(maxRequest)),
+ (threshold==null||"".equals(threshold)?0:Integer.parseInt(threshold)));
+
+ Origin o = context.getMetaData().getOrigin(servlet_name+".servlet.multipart-config");
+ switch (o)
+ {
+ case NotSet:
+ {
+ //hasn't been set, so set it
+ holder.getRegistration().setMultipartConfig(element);
+ context.getMetaData().setOrigin(servlet_name+".servlet.multipart-config", descriptor);
+ break;
+ }
+ case WebXml:
+ case WebDefaults:
+ case WebOverride:
+ {
+ //was set in a web xml, only allow changes if we're parsing another web xml (web.xml/web-default.xml/web-override.xml)
+ if (!(descriptor instanceof FragmentDescriptor))
+ {
+ holder.getRegistration().setMultipartConfig(element);
+ context.getMetaData().setOrigin(servlet_name+".servlet.multipart-config", descriptor);
+ }
+ break;
+ }
+ case WebFragment:
+ {
+ //another fragment set the value, this fragment's values must match exactly or it is an error
+ MultipartConfigElement cfg = ((ServletHolder.Registration)holder.getRegistration()).getMultipartConfig();
+
+ if (cfg.getMaxFileSize() != element.getMaxFileSize())
+ throw new IllegalStateException("Conflicting multipart-config max-file-size for servlet "+servlet_name+" in "+descriptor.getResource());
+ if (cfg.getMaxRequestSize() != element.getMaxRequestSize())
+ throw new IllegalStateException("Conflicting multipart-config max-request-size for servlet "+servlet_name+" in "+descriptor.getResource());
+ if (cfg.getFileSizeThreshold() != element.getFileSizeThreshold())
+ throw new IllegalStateException("Conflicting multipart-config file-size-threshold for servlet "+servlet_name+" in "+descriptor.getResource());
+ if ((cfg.getLocation() != null && (element.getLocation() == null || element.getLocation().length()==0))
+ || (cfg.getLocation() == null && (element.getLocation()!=null || element.getLocation().length() > 0)))
+ throw new IllegalStateException("Conflicting multipart-config location for servlet "+servlet_name+" in "+descriptor.getResource());
+ break;
+ }
+ }
+ }
}
@@ -484,7 +627,8 @@ public class StandardDescriptorProcessor extends IterativeDescriptorProcessor
{
//no servlet mappings
context.getMetaData().setOrigin(servlet_name+".servlet.mappings", descriptor);
- addServletMapping(servlet_name, node, context);
+ ServletMapping mapping = addServletMapping(servlet_name, node, context, descriptor);
+ mapping.setDefault(context.getMetaData().getOrigin(servlet_name+".servlet.mappings") == Origin.WebDefaults);
break;
}
case WebXml:
@@ -495,14 +639,14 @@ public class StandardDescriptorProcessor extends IterativeDescriptorProcessor
//otherwise just ignore it
if (!(descriptor instanceof FragmentDescriptor))
{
- addServletMapping(servlet_name, node, context);
+ addServletMapping(servlet_name, node, context, descriptor);
}
break;
}
case WebFragment:
{
//mappings previously set by another web-fragment, so merge in this web-fragment's mappings
- addServletMapping(servlet_name, node, context);
+ addServletMapping(servlet_name, node, context, descriptor);
break;
}
}
@@ -522,6 +666,282 @@ public class StandardDescriptorProcessor extends IterativeDescriptorProcessor
int timeout = Integer.parseInt(tNode.toString(false, true));
context.getSessionHandler().getSessionManager().setMaxInactiveInterval(timeout * 60);
}
+
+ //Servlet Spec 3.0
+ // <tracking-mode>
+ // this is additive across web-fragments
+ Iterator iter = node.iterator("tracking-mode");
+ Set<SessionTrackingMode> modes = new HashSet<SessionTrackingMode>();
+ modes.addAll(context.getSessionHandler().getSessionManager().getEffectiveSessionTrackingModes());
+ while (iter.hasNext())
+ {
+ XmlParser.Node mNode = (XmlParser.Node) iter.next();
+ String trackMode = mNode.toString(false, true);
+ modes.add(SessionTrackingMode.valueOf(trackMode));
+ }
+ context.getSessionHandler().getSessionManager().setSessionTrackingModes(modes);
+
+
+ //Servlet Spec 3.0
+ //<cookie-config>
+ XmlParser.Node cookieConfig = node.get("cookie-config");
+ if (cookieConfig != null)
+ {
+ // <name>
+ String name = cookieConfig.getString("name", false, true);
+ if (name != null)
+ {
+ Origin o = context.getMetaData().getOrigin("cookie-config.name");
+ switch (o)
+ {
+ case NotSet:
+ {
+ //no <cookie-config><name> set yet, accept it
+ context.getSessionHandler().getSessionManager().getSessionCookieConfig().setName(name);
+ context.getMetaData().setOrigin("cookie-config.name", descriptor);
+ break;
+ }
+ case WebXml:
+ case WebDefaults:
+ case WebOverride:
+ {
+ //<cookie-config><name> set in a web xml, only allow web-default/web-override to change
+ if (!(descriptor instanceof FragmentDescriptor))
+ {
+ context.getSessionHandler().getSessionManager().getSessionCookieConfig().setName(name);
+ context.getMetaData().setOrigin("cookie-config.name", descriptor);
+ }
+ break;
+ }
+ case WebFragment:
+ {
+ //a web-fragment set the value, all web-fragments must have the same value
+ if (!context.getSessionHandler().getSessionManager().getSessionCookieConfig().getName().equals(name))
+ throw new IllegalStateException("Conflicting cookie-config name "+name+" in "+descriptor.getResource());
+ break;
+ }
+ }
+ }
+
+ // <domain>
+ String domain = cookieConfig.getString("domain", false, true);
+ if (domain != null)
+ {
+ Origin o = context.getMetaData().getOrigin("cookie-config.domain");
+ switch (o)
+ {
+ case NotSet:
+ {
+ //no <cookie-config><domain> set yet, accept it
+ context.getSessionHandler().getSessionManager().getSessionCookieConfig().setDomain(domain);
+ context.getMetaData().setOrigin("cookie-config.domain", descriptor);
+ break;
+ }
+ case WebXml:
+ case WebDefaults:
+ case WebOverride:
+ {
+ //<cookie-config><domain> set in a web xml, only allow web-default/web-override to change
+ if (!(descriptor instanceof FragmentDescriptor))
+ {
+ context.getSessionHandler().getSessionManager().getSessionCookieConfig().setDomain(domain);
+ context.getMetaData().setOrigin("cookie-config.domain", descriptor);
+ }
+ break;
+ }
+ case WebFragment:
+ {
+ //a web-fragment set the value, all web-fragments must have the same value
+ if (!context.getSessionHandler().getSessionManager().getSessionCookieConfig().getDomain().equals(domain))
+ throw new IllegalStateException("Conflicting cookie-config domain "+domain+" in "+descriptor.getResource());
+ break;
+ }
+ }
+ }
+
+ // <path>
+ String path = cookieConfig.getString("path", false, true);
+ if (path != null)
+ {
+ Origin o = context.getMetaData().getOrigin("cookie-config.path");
+ switch (o)
+ {
+ case NotSet:
+ {
+ //no <cookie-config><domain> set yet, accept it
+ context.getSessionHandler().getSessionManager().getSessionCookieConfig().setPath(path);
+ context.getMetaData().setOrigin("cookie-config.path", descriptor);
+ break;
+ }
+ case WebXml:
+ case WebDefaults:
+ case WebOverride:
+ {
+ //<cookie-config><domain> set in a web xml, only allow web-default/web-override to change
+ if (!(descriptor instanceof FragmentDescriptor))
+ {
+ context.getSessionHandler().getSessionManager().getSessionCookieConfig().setPath(path);
+ context.getMetaData().setOrigin("cookie-config.path", descriptor);
+ }
+ break;
+ }
+ case WebFragment:
+ {
+ //a web-fragment set the value, all web-fragments must have the same value
+ if (!context.getSessionHandler().getSessionManager().getSessionCookieConfig().getPath().equals(path))
+ throw new IllegalStateException("Conflicting cookie-config path "+path+" in "+descriptor.getResource());
+ break;
+ }
+ }
+ }
+
+ // <comment>
+ String comment = cookieConfig.getString("comment", false, true);
+ if (comment != null)
+ {
+ Origin o = context.getMetaData().getOrigin("cookie-config.comment");
+ switch (o)
+ {
+ case NotSet:
+ {
+ //no <cookie-config><comment> set yet, accept it
+ context.getSessionHandler().getSessionManager().getSessionCookieConfig().setComment(comment);
+ context.getMetaData().setOrigin("cookie-config.comment", descriptor);
+ break;
+ }
+ case WebXml:
+ case WebDefaults:
+ case WebOverride:
+ {
+ //<cookie-config><comment> set in a web xml, only allow web-default/web-override to change
+ if (!(descriptor instanceof FragmentDescriptor))
+ {
+ context.getSessionHandler().getSessionManager().getSessionCookieConfig().setComment(comment);
+ context.getMetaData().setOrigin("cookie-config.comment", descriptor);
+ }
+ break;
+ }
+ case WebFragment:
+ {
+ //a web-fragment set the value, all web-fragments must have the same value
+ if (!context.getSessionHandler().getSessionManager().getSessionCookieConfig().getComment().equals(comment))
+ throw new IllegalStateException("Conflicting cookie-config comment "+comment+" in "+descriptor.getResource());
+ break;
+ }
+ }
+ }
+
+ // <http-only>true/false
+ tNode = cookieConfig.get("http-only");
+ if (tNode != null)
+ {
+ boolean httpOnly = Boolean.parseBoolean(tNode.toString(false,true));
+ Origin o = context.getMetaData().getOrigin("cookie-config.http-only");
+ switch (o)
+ {
+ case NotSet:
+ {
+ //no <cookie-config><http-only> set yet, accept it
+ context.getSessionHandler().getSessionManager().getSessionCookieConfig().setHttpOnly(httpOnly);
+ context.getMetaData().setOrigin("cookie-config.http-only", descriptor);
+ break;
+ }
+ case WebXml:
+ case WebDefaults:
+ case WebOverride:
+ {
+ //<cookie-config><http-only> set in a web xml, only allow web-default/web-override to change
+ if (!(descriptor instanceof FragmentDescriptor))
+ {
+ context.getSessionHandler().getSessionManager().getSessionCookieConfig().setHttpOnly(httpOnly);
+ context.getMetaData().setOrigin("cookie-config.http-only", descriptor);
+ }
+ break;
+ }
+ case WebFragment:
+ {
+ //a web-fragment set the value, all web-fragments must have the same value
+ if (context.getSessionHandler().getSessionManager().getSessionCookieConfig().isHttpOnly() != httpOnly)
+ throw new IllegalStateException("Conflicting cookie-config http-only "+httpOnly+" in "+descriptor.getResource());
+ break;
+ }
+ }
+ }
+
+ // <secure>true/false
+ tNode = cookieConfig.get("secure");
+ if (tNode != null)
+ {
+ boolean secure = Boolean.parseBoolean(tNode.toString(false,true));
+ Origin o = context.getMetaData().getOrigin("cookie-config.secure");
+ switch (o)
+ {
+ case NotSet:
+ {
+ //no <cookie-config><secure> set yet, accept it
+ context.getSessionHandler().getSessionManager().getSessionCookieConfig().setSecure(secure);
+ context.getMetaData().setOrigin("cookie-config.secure", descriptor);
+ break;
+ }
+ case WebXml:
+ case WebDefaults:
+ case WebOverride:
+ {
+ //<cookie-config><secure> set in a web xml, only allow web-default/web-override to change
+ if (!(descriptor instanceof FragmentDescriptor))
+ {
+ context.getSessionHandler().getSessionManager().getSessionCookieConfig().setSecure(secure);
+ context.getMetaData().setOrigin("cookie-config.secure", descriptor);
+ }
+ break;
+ }
+ case WebFragment:
+ {
+ //a web-fragment set the value, all web-fragments must have the same value
+ if (context.getSessionHandler().getSessionManager().getSessionCookieConfig().isSecure() != secure)
+ throw new IllegalStateException("Conflicting cookie-config secure "+secure+" in "+descriptor.getResource());
+ break;
+ }
+ }
+ }
+
+ // <max-age>
+ tNode = cookieConfig.get("max-age");
+ if (tNode != null)
+ {
+ int maxAge = Integer.parseInt(tNode.toString(false,true));
+ Origin o = context.getMetaData().getOrigin("cookie-config.max-age");
+ switch (o)
+ {
+ case NotSet:
+ {
+ //no <cookie-config><max-age> set yet, accept it
+ context.getSessionHandler().getSessionManager().getSessionCookieConfig().setMaxAge(maxAge);
+ context.getMetaData().setOrigin("cookie-config.max-age", descriptor);
+ break;
+ }
+ case WebXml:
+ case WebDefaults:
+ case WebOverride:
+ {
+ //<cookie-config><max-age> set in a web xml, only allow web-default/web-override to change
+ if (!(descriptor instanceof FragmentDescriptor))
+ {
+ context.getSessionHandler().getSessionManager().getSessionCookieConfig().setMaxAge(maxAge);
+ context.getMetaData().setOrigin("cookie-config.max-age", descriptor);
+ }
+ break;
+ }
+ case WebFragment:
+ {
+ //a web-fragment set the value, all web-fragments must have the same value
+ if (context.getSessionHandler().getSessionManager().getSessionCookieConfig().getMaxAge() != maxAge)
+ throw new IllegalStateException("Conflicting cookie-config max-age "+maxAge+" in "+descriptor.getResource());
+ break;
+ }
+ }
+ }
+ }
}
@@ -662,7 +1082,7 @@ public class StandardDescriptorProcessor extends IterativeDescriptorProcessor
{
//a value was set by a web-fragment, all fragments must have the same value
if (!encoding.equals(context.getLocaleEncoding(locale)))
- throw new IllegalStateException("Conflicting locale-encoding mapping for locale "+locale+" in "+descriptor.getResource());
+ throw new IllegalStateException("Conflicting loacle-encoding mapping for locale "+locale+" in "+descriptor.getResource());
break;
}
}
@@ -758,7 +1178,7 @@ public class StandardDescriptorProcessor extends IterativeDescriptorProcessor
* @param node
* @param context
*/
- protected void addServletMapping (String servletName, XmlParser.Node node, WebAppContext context)
+ protected ServletMapping addServletMapping (String servletName, XmlParser.Node node, WebAppContext context, Descriptor descriptor)
{
ServletMapping mapping = new ServletMapping();
mapping.setServletName(servletName);
@@ -770,9 +1190,11 @@ public class StandardDescriptorProcessor extends IterativeDescriptorProcessor
String p = iter.next().toString(false, true);
p = normalizePattern(p);
paths.add(p);
+ context.getMetaData().setOrigin(servletName+".servlet.mapping."+p, descriptor);
}
mapping.setPathSpecs((String[]) paths.toArray(new String[paths.size()]));
context.getServletHandler().addServletMapping(mapping);
+ return mapping;
}
/**
@@ -780,7 +1202,7 @@ public class StandardDescriptorProcessor extends IterativeDescriptorProcessor
* @param node
* @param context
*/
- protected void addFilterMapping (String filterName, XmlParser.Node node, WebAppContext context)
+ protected void addFilterMapping (String filterName, XmlParser.Node node, WebAppContext context, Descriptor descriptor)
{
FilterMapping mapping = new FilterMapping();
mapping.setFilterName(filterName);
@@ -792,6 +1214,7 @@ public class StandardDescriptorProcessor extends IterativeDescriptorProcessor
String p = iter.next().toString(false, true);
p = normalizePattern(p);
paths.add(p);
+ context.getMetaData().setOrigin(filterName+".filter.mapping."+p, descriptor);
}
mapping.setPathSpecs((String[]) paths.toArray(new String[paths.size()]));
@@ -832,6 +1255,18 @@ public class StandardDescriptorProcessor extends IterativeDescriptorProcessor
String location = node.getString("taglib-location", false, true);
context.setResourceAlias(uri, location);
+
+ JspConfig config = (JspConfig)context.getServletContext().getJspConfigDescriptor();
+ if (config == null)
+ {
+ config = new JspConfig();
+ context.getServletContext().setJspConfigDescriptor(config);
+ }
+
+ TagLib tl = new TagLib();
+ tl.setTaglibLocation(location);
+ tl.setTaglibURI(uri);
+ config.addTaglibDescriptor(tl);
}
/**
@@ -840,7 +1275,16 @@ public class StandardDescriptorProcessor extends IterativeDescriptorProcessor
* @param node
*/
protected void visitJspConfig(WebAppContext context, Descriptor descriptor, XmlParser.Node node)
- {
+ {
+ //Additive across web.xml and web-fragment.xml
+ JspConfig config = (JspConfig)context.getServletContext().getJspConfigDescriptor();
+ if (config == null)
+ {
+ config = new JspConfig();
+ context.getServletContext().setJspConfigDescriptor(config);
+ }
+
+
for (int i = 0; i < node.size(); i++)
{
Object o = node.get(i);
@@ -849,19 +1293,51 @@ public class StandardDescriptorProcessor extends IterativeDescriptorProcessor
}
// Map URLs from jsp property groups to JSP servlet.
- // this is more JSP stupidness creaping into the servlet spec
+ // this is more JSP stupidness creeping into the servlet spec
Iterator<XmlParser.Node> iter = node.iterator("jsp-property-group");
List<String> paths = new ArrayList<String>();
while (iter.hasNext())
{
+ JspPropertyGroup jpg = new JspPropertyGroup();
+ config.addJspPropertyGroup(jpg);
XmlParser.Node group = iter.next();
+
+ //url-patterns
Iterator<XmlParser.Node> iter2 = group.iterator("url-pattern");
while (iter2.hasNext())
{
String url = iter2.next().toString(false, true);
url = normalizePattern(url);
paths.add( url);
+ jpg.addUrlPattern(url);
+ }
+
+ jpg.setElIgnored(group.getString("el-ignored", false, true));
+ jpg.setPageEncoding(group.getString("page-encoding", false, true));
+ jpg.setScriptingInvalid(group.getString("scripting-invalid", false, true));
+ jpg.setIsXml(group.getString("is-xml", false, true));
+ jpg.setDeferredSyntaxAllowedAsLiteral(group.getString("deferred-syntax-allowed-as-literal", false, true));
+ jpg.setTrimDirectiveWhitespaces(group.getString("trim-directive-whitespaces", false, true));
+ jpg.setDefaultContentType(group.getString("default-content-type", false, true));
+ jpg.setBuffer(group.getString("buffer", false, true));
+ jpg.setErrorOnUndeclaredNamespace(group.getString("error-on-undeclared-namespace", false, true));
+
+ //preludes
+ Iterator<XmlParser.Node> preludes = group.iterator("include-prelude");
+ while (preludes.hasNext())
+ {
+ String prelude = preludes.next().toString(false, true);
+ jpg.addIncludePrelude(prelude);
+ }
+ //codas
+ Iterator<XmlParser.Node> codas = group.iterator("include-coda");
+ while (codas.hasNext())
+ {
+ String coda = codas.next().toString(false, true);
+ jpg.addIncludeCoda(coda);
}
+
+ if (LOG.isDebugEnabled()) LOG.debug(config.toString());
}
if (paths.size() > 0)
@@ -895,6 +1371,8 @@ public class StandardDescriptorProcessor extends IterativeDescriptorProcessor
//ServletSpec 3.0, p74 security-constraints, as minOccurs > 1, are additive
//across fragments
+
+ //TODO: need to remember origin of the constraints
try
{
XmlParser.Node auths = node.get("auth-constraint");
@@ -943,29 +1421,50 @@ public class StandardDescriptorProcessor extends IterativeDescriptorProcessor
{
String url = iter2.next().toString(false, true);
url = normalizePattern(url);
-
+ //remember origin so we can process ServletRegistration.Dynamic.setServletSecurityElement() correctly
+ context.getMetaData().setOrigin("constraint.url."+url, descriptor);
+
Iterator<XmlParser.Node> iter3 = collection.iterator("http-method");
+ Iterator<XmlParser.Node> iter4 = collection.iterator("http-method-omission");
+
if (iter3.hasNext())
{
+ if (iter4.hasNext())
+ throw new IllegalStateException ("web-resource-collection cannot contain both http-method and http-method-omission");
+
+ //configure all the http-method elements for each url
while (iter3.hasNext())
{
String method = ((XmlParser.Node) iter3.next()).toString(false, true);
ConstraintMapping mapping = new ConstraintMapping();
mapping.setMethod(method);
mapping.setPathSpec(url);
+ mapping.setConstraint(sc);
+ ((ConstraintAware)context.getSecurityHandler()).addConstraintMapping(mapping);
+ }
+ }
+ else if (iter4.hasNext())
+ {
+ //configure all the http-method-omission elements for each url
+ while (iter4.hasNext())
+ {
+ String method = ((XmlParser.Node)iter4.next()).toString(false, true);
+ ConstraintMapping mapping = new ConstraintMapping();
+ mapping.setMethodOmissions(new String[]{method});
+ mapping.setPathSpec(url);
mapping.setConstraint(sc);
-
((ConstraintAware)context.getSecurityHandler()).addConstraintMapping(mapping);
}
}
else
{
+ //No http-methods or http-method-omissions specified, the constraint applies to all
ConstraintMapping mapping = new ConstraintMapping();
mapping.setPathSpec(url);
mapping.setConstraint(sc);
((ConstraintAware)context.getSecurityHandler()).addConstraintMapping(mapping);
}
- }
+ }
}
}
catch (CloneNotSupportedException e)
@@ -1165,7 +1664,7 @@ public class StandardDescriptorProcessor extends IterativeDescriptorProcessor
FilterHolder holder = context.getServletHandler().getFilter(name);
if (holder == null)
{
- holder = context.getServletHandler().newFilterHolder();
+ holder = context.getServletHandler().newFilterHolder(Holder.Source.DESCRIPTOR);
holder.setName(name);
context.getServletHandler().addFilter(holder);
}
@@ -1311,7 +1810,7 @@ public class StandardDescriptorProcessor extends IterativeDescriptorProcessor
{
//no filtermappings for this filter yet defined
context.getMetaData().setOrigin(filter_name+".filter.mappings", descriptor);
- addFilterMapping(filter_name, node, context);
+ addFilterMapping(filter_name, node, context, descriptor);
break;
}
case WebDefaults:
@@ -1321,14 +1820,14 @@ public class StandardDescriptorProcessor extends IterativeDescriptorProcessor
//filter mappings defined in a web xml file. If we're processing a fragment, we ignore filter mappings.
if (!(descriptor instanceof FragmentDescriptor))
{
- addFilterMapping(filter_name, node, context);
+ addFilterMapping(filter_name, node, context, descriptor);
}
break;
}
case WebFragment:
{
//filter mappings first defined in a web-fragment, allow other fragments to add
- addFilterMapping(filter_name, node, context);
+ addFilterMapping(filter_name, node, context, descriptor);
break;
}
}
@@ -1406,7 +1905,7 @@ public class StandardDescriptorProcessor extends IterativeDescriptorProcessor
{
try
{
- return ((ServletContextHandler.Context)context.getServletContext()).createListener(clazz);
+ return context.getServletContext().createListener(clazz);
}
catch (ServletException se)
{
diff --git a/jetty-webapp/src/main/java/org/eclipse/jetty/webapp/WebAppClassLoader.java b/jetty-webapp/src/main/java/org/eclipse/jetty/webapp/WebAppClassLoader.java
index a1f85963c5..9c218953f6 100644
--- a/jetty-webapp/src/main/java/org/eclipse/jetty/webapp/WebAppClassLoader.java
+++ b/jetty-webapp/src/main/java/org/eclipse/jetty/webapp/WebAppClassLoader.java
@@ -446,5 +446,4 @@ public class WebAppClassLoader extends URLClassLoader
{
return "WebAppClassLoader=" + _name+"@"+Long.toHexString(hashCode());
}
-
}
diff --git a/jetty-webapp/src/main/java/org/eclipse/jetty/webapp/WebAppContext.java b/jetty-webapp/src/main/java/org/eclipse/jetty/webapp/WebAppContext.java
index 96fd1ac6e0..45ffa3ad59 100644
--- a/jetty-webapp/src/main/java/org/eclipse/jetty/webapp/WebAppContext.java
+++ b/jetty-webapp/src/main/java/org/eclipse/jetty/webapp/WebAppContext.java
@@ -25,18 +25,29 @@ import java.net.URL;
import java.security.PermissionCollection;
import java.util.ArrayList;
import java.util.Arrays;
+import java.util.Collection;
import java.util.Collections;
import java.util.EventListener;
import java.util.HashMap;
+import java.util.HashSet;
import java.util.List;
import java.util.Map;
+import java.util.Set;
+import javax.servlet.HttpMethodConstraintElement;
import javax.servlet.ServletContext;
+import javax.servlet.ServletRegistration.Dynamic;
+import javax.servlet.ServletSecurityElement;
+import javax.servlet.annotation.ServletSecurity.EmptyRoleSemantic;
+import javax.servlet.annotation.ServletSecurity.TransportGuarantee;
import javax.servlet.http.HttpSessionActivationListener;
import javax.servlet.http.HttpSessionAttributeListener;
import javax.servlet.http.HttpSessionBindingListener;
import javax.servlet.http.HttpSessionListener;
+import org.eclipse.jetty.security.ConstraintAware;
+import org.eclipse.jetty.security.ConstraintMapping;
+import org.eclipse.jetty.security.ConstraintSecurityHandler;
import org.eclipse.jetty.security.SecurityHandler;
import org.eclipse.jetty.server.Connector;
import org.eclipse.jetty.server.HandlerContainer;
@@ -56,6 +67,7 @@ import org.eclipse.jetty.util.log.Log;
import org.eclipse.jetty.util.log.Logger;
import org.eclipse.jetty.util.resource.Resource;
import org.eclipse.jetty.util.resource.ResourceCollection;
+import org.eclipse.jetty.util.security.Constraint;
/* ------------------------------------------------------------ */
/** Web Application Context Handler.
@@ -90,8 +102,8 @@ public class WebAppContext extends ServletContextHandler implements WebAppClassL
"org.eclipse.jetty.webapp.WebXmlConfiguration",
"org.eclipse.jetty.webapp.MetaInfConfiguration",
"org.eclipse.jetty.webapp.FragmentConfiguration",
- "org.eclipse.jetty.webapp.JettyWebXmlConfiguration",
- "org.eclipse.jetty.webapp.TagLibConfiguration"
+ "org.eclipse.jetty.webapp.JettyWebXmlConfiguration"//,
+ //"org.eclipse.jetty.webapp.TagLibConfiguration"
} ;
// System classes are classes that cannot be replaced by
@@ -1237,6 +1249,79 @@ public class WebAppContext extends ServletContextHandler implements WebAppClassL
super.startContext();
}
+
+ /* ------------------------------------------------------------ */
+ @Override
+ public Set<String> setServletSecurity(Dynamic registration, ServletSecurityElement servletSecurityElement)
+ {
+
+ Set<String> unchangedURLMappings = new HashSet<String>();
+ //From javadoc for ServletSecurityElement:
+ /*
+ If a URL pattern of this ServletRegistration is an exact target of a security-constraint that
+ was established via the portable deployment descriptor, then this method does not change the
+ security-constraint for that pattern, and the pattern will be included in the return value.
+
+ If a URL pattern of this ServletRegistration is an exact target of a security constraint
+ that was established via the ServletSecurity annotation or a previous call to this method,
+ then this method replaces the security constraint for that pattern.
+
+ If a URL pattern of this ServletRegistration is neither the exact target of a security constraint
+ that was established via the ServletSecurity annotation or a previous call to this method,
+ nor the exact target of a security-constraint in the portable deployment descriptor, then
+ this method establishes the security constraint for that pattern from the argument ServletSecurityElement.
+ */
+
+ Collection<String> pathMappings = registration.getMappings();
+ if (pathMappings != null)
+ {
+ Constraint constraint = ConstraintSecurityHandler.createConstraint(registration.getName(), servletSecurityElement);
+
+ for (String pathSpec:pathMappings)
+ {
+ Origin origin = getMetaData().getOrigin("constraint.url."+pathSpec);
+
+ switch (origin)
+ {
+ case NotSet:
+ {
+ //No mapping for this url already established
+ List<ConstraintMapping> mappings = ConstraintSecurityHandler.createConstraintsWithMappingsForPath(registration.getName(), pathSpec, servletSecurityElement);
+ for (ConstraintMapping m:mappings)
+ ((ConstraintAware)getSecurityHandler()).addConstraintMapping(m);
+ getMetaData().setOrigin("constraint.url."+pathSpec, Origin.API);
+ break;
+ }
+ case WebXml:
+ case WebDefaults:
+ case WebOverride:
+ case WebFragment:
+ {
+ //a mapping for this url was created in a descriptor, which overrides everything
+ unchangedURLMappings.add(pathSpec);
+ break;
+ }
+ case Annotation:
+ case API:
+ {
+ //mapping established via an annotation or by previous call to this method,
+ //replace the security constraint for this pattern
+ List<ConstraintMapping> constraintMappings = ConstraintSecurityHandler.removeConstraintMappingsForPath(pathSpec, ((ConstraintAware)getSecurityHandler()).getConstraintMappings());
+
+ List<ConstraintMapping> freshMappings = ConstraintSecurityHandler.createConstraintsWithMappingsForPath(registration.getName(), pathSpec, servletSecurityElement);
+ constraintMappings.addAll(freshMappings);
+
+ ((ConstraintSecurityHandler)getSecurityHandler()).setConstraintMappings(constraintMappings);
+ break;
+ }
+ }
+ }
+ }
+
+ return unchangedURLMappings;
+ }
+
+
/* ------------------------------------------------------------ */
public class Context extends ServletContextHandler.Context
@@ -1287,6 +1372,8 @@ public class WebAppContext extends ServletContextHandler implements WebAppClassL
}
}
+
+
}
/* ------------------------------------------------------------ */
diff --git a/jetty-webapp/src/main/java/org/eclipse/jetty/webapp/WebXmlConfiguration.java b/jetty-webapp/src/main/java/org/eclipse/jetty/webapp/WebXmlConfiguration.java
index 03ef85fab0..c0af4a8067 100644
--- a/jetty-webapp/src/main/java/org/eclipse/jetty/webapp/WebXmlConfiguration.java
+++ b/jetty-webapp/src/main/java/org/eclipse/jetty/webapp/WebXmlConfiguration.java
@@ -59,6 +59,8 @@ public class WebXmlConfiguration extends AbstractConfiguration
if (webxml != null)
{
context.getMetaData().setWebXml(webxml);
+ context.getServletContext().setEffectiveMajorVersion(context.getMetaData().getWebXml().getMajorVersion());
+ context.getServletContext().setEffectiveMinorVersion(context.getMetaData().getWebXml().getMinorVersion());
}
//parse but don't process override-web.xml
diff --git a/jetty-webapp/src/test/java/org/eclipse/jetty/webapp/OrderingTest.java b/jetty-webapp/src/test/java/org/eclipse/jetty/webapp/OrderingTest.java
index 529cae4a75..fe109c48ce 100644
--- a/jetty-webapp/src/test/java/org/eclipse/jetty/webapp/OrderingTest.java
+++ b/jetty-webapp/src/test/java/org/eclipse/jetty/webapp/OrderingTest.java
@@ -853,6 +853,44 @@ public class OrderingTest
}
@Test
+ public void testRelativeOrderingWithPlainJars2 ()
+ throws Exception
+ {
+ //web.xml has no ordering, jar A has fragment after others, jar B is plain, jar C is plain
+ List<Resource> resources = new ArrayList<Resource>();
+ WebAppContext wac = new WebAppContext();
+ MetaData metaData = new MetaData();
+ metaData._ordering = new RelativeOrdering(metaData);
+
+ //A has after others
+ TestResource jar1 = new TestResource("A");
+ resources.add(jar1);
+ TestResource r1 = new TestResource("A/web-fragment.xml");
+ FragmentDescriptor f1 = new FragmentDescriptor(r1);
+ f1._name = "A";
+ metaData._webFragmentNameMap.put(f1._name, f1);
+ metaData._webFragmentResourceMap.put(jar1, f1);
+ f1._otherType = FragmentDescriptor.OtherType.After;
+
+ //No fragment jar B
+ TestResource r4 = new TestResource("plainB");
+ resources.add(r4);
+
+ //No fragment jar C
+ TestResource r5 = new TestResource("plainC");
+ resources.add(r5);
+
+ List<Resource> orderedList = metaData._ordering.order(resources);
+ String[] outcomes = {"plainBplainCA"};
+ String result = "";
+ for (Resource r:orderedList)
+ result+=(((TestResource)r)._name);
+
+ if (!checkResult(result, outcomes))
+ fail ("No outcome matched "+result);
+ }
+
+ @Test
public void testAbsoluteOrderingWithPlainJars()
throws Exception
{
diff --git a/jetty-websocket/pom.xml b/jetty-websocket/pom.xml
index bd6ea7feb2..aae72c3e52 100644
--- a/jetty-websocket/pom.xml
+++ b/jetty-websocket/pom.xml
@@ -3,7 +3,7 @@
<parent>
<artifactId>jetty-project</artifactId>
<groupId>org.eclipse.jetty</groupId>
- <version>7.6.8-SNAPSHOT</version>
+ <version>8.1.8-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
@@ -65,6 +65,11 @@
<goals>
<goal>manifest</goal>
</goals>
+ <configuration>
+ <instructions>
+ <Import-Package>javax.servlet.*;version="2.6.0",*</Import-Package>
+ </instructions>
+ </configuration>
</execution>
</executions>
</plugin>
@@ -100,5 +105,4 @@
</plugin>
</plugins>
</build>
-
</project>
diff --git a/jetty-websocket/src/test/java/org/eclipse/jetty/websocket/WebSocketParserD06Test.java b/jetty-websocket/src/test/java/org/eclipse/jetty/websocket/WebSocketParserD06Test.java
index 505dde6dba..1d17f9c0d0 100644
--- a/jetty-websocket/src/test/java/org/eclipse/jetty/websocket/WebSocketParserD06Test.java
+++ b/jetty-websocket/src/test/java/org/eclipse/jetty/websocket/WebSocketParserD06Test.java
@@ -29,6 +29,7 @@ import org.eclipse.jetty.io.BufferCache.CachedBuffer;
import org.eclipse.jetty.io.ByteArrayBuffer;
import org.eclipse.jetty.io.ByteArrayEndPoint;
import org.eclipse.jetty.util.StringUtil;
+import org.eclipse.jetty.util.TypeUtil;
import org.eclipse.jetty.util.Utf8StringBuilder;
import org.junit.Before;
import org.junit.Test;
@@ -130,7 +131,7 @@ public class WebSocketParserD06Test
_in.put((byte)0x84);
_in.put((byte)11);
_in.put("Hello World".getBytes(StringUtil.__UTF8));
- // System.err.println("tosend="+TypeUtil.toHexString(_in.asArray()));
+ System.err.println("tosend="+TypeUtil.toHexString(_in.asArray()));
int filled =_parser.parseNext();
diff --git a/jetty-xml/pom.xml b/jetty-xml/pom.xml
index 8f69dae4db..f532f8b8be 100644
--- a/jetty-xml/pom.xml
+++ b/jetty-xml/pom.xml
@@ -2,7 +2,7 @@
<parent>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-project</artifactId>
- <version>7.6.8-SNAPSHOT</version>
+ <version>8.1.8-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>jetty-xml</artifactId>
diff --git a/pom.xml b/pom.xml
index 826feab40a..6811e840db 100644
--- a/pom.xml
+++ b/pom.xml
@@ -6,14 +6,14 @@
<version>20</version>
</parent>
<artifactId>jetty-project</artifactId>
- <version>7.6.8-SNAPSHOT</version>
+ <version>8.1.8-SNAPSHOT</version>
<name>Jetty :: Project</name>
<url>${jetty.url}</url>
<packaging>pom</packaging>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<jetty.url>http://www.eclipse.org/jetty</jetty.url>
- <orbit-servlet-api-version>2.5.0.v201103041518</orbit-servlet-api-version>
+ <orbit-servlet-api-version>3.0.0.v201112011016</orbit-servlet-api-version>
<build-support-version>1.1</build-support-version>
<slf4j-version>1.6.1</slf4j-version>
<jetty-test-policy-version>1.2</jetty-test-policy-version>
@@ -29,8 +29,8 @@
<plugin>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
- <source>1.5</source>
- <target>1.5</target>
+ <source>1.6</source>
+ <target>1.6</target>
<verbose>false</verbose>
</configuration>
</plugin>
@@ -183,7 +183,7 @@
</execution>
</executions>
<configuration>
- <targetJdk>1.5</targetJdk>
+ <targetJdk>1.6</targetJdk>
<rulesets>
<ruleset>jetty/pmd_logging_ruleset.xml</ruleset>
</rulesets>
@@ -376,6 +376,7 @@
<module>jetty-start</module>
<module>jetty-nested</module>
<module>jetty-overlay-deployer</module>
+ <module>jetty-osgi</module>
<module>jetty-nosql</module>
<module>jetty-http-spi</module>
<module>jetty-jsp</module>
@@ -386,6 +387,7 @@
<module>test-jetty-webapp</module>
<module>test-jetty-nested</module>
<module>example-jetty-embedded</module>
+ <module>example-async-rest</module>
<module>tests</module>
</modules>
<dependencyManagement>
@@ -711,8 +713,8 @@
<configuration>
<excludePackageNames>com.acme</excludePackageNames>
<links>
- <link>http://java.sun.com/j2se/1.5.0/docs/api</link>
- <link>http://java.sun.com/javaee/5/docs/api</link>
+ <link>http://java.sun.com/javase/6/docs/api/</link>
+ <link>http://java.sun.com/javaee/6/docs/api</link>
<link>http://junit.sourceforge.net/javadoc/</link>
</links>
<tags>
diff --git a/settings.xml b/settings.xml
new file mode 100755
index 0000000000..9b5ddeffc7
--- /dev/null
+++ b/settings.xml
@@ -0,0 +1,21 @@
+<settings>
+ <localRepository>/tmp/jetty-builds/jetty8/localRepo</localRepository>
+ <interactiveMode>true</interactiveMode>
+ <offline>false</offline>
+<proxies>
+ <proxy>
+ <active>true</active>
+ <protocol>http</protocol>
+ <host>proxy.eclipse.org</host>
+ <port>9898</port>
+ </proxy>
+ </proxies>
+<mirrors>
+ <mirror>
+ <id>central</id>
+ <name>central</name>
+ <url>http://repo2.maven.org/maven2/</url>
+ <mirrorOf>*</mirrorOf>
+ </mirror>
+ </mirrors>
+</settings>
diff --git a/test-continuation-jetty6/pom.xml b/test-continuation-jetty6/pom.xml
index 02fa6e2917..d853b66d60 100644
--- a/test-continuation-jetty6/pom.xml
+++ b/test-continuation-jetty6/pom.xml
@@ -2,7 +2,7 @@
<parent>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-project</artifactId>
- <version>7.6.0-SNAPSHOT</version>
+ <version>8.1.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>test-continuation-jetty6</artifactId>
@@ -28,16 +28,34 @@
<scope>test</scope>
</dependency>
<dependency>
+ <groupId>org.mortbay.jetty</groupId>
+ <artifactId>servlet-api</artifactId>
+ <version>2.5-20081211</version>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-servlet</artifactId>
<version>${project.version}</version>
<scope>test</scope>
+ <exclusions>
+ <exclusion>
+ <groupId>${servlet.spec.groupId}</groupId>
+ <artifactId>${servlet.spec.artifactId}</artifactId>
+ </exclusion>
+ </exclusions>
</dependency>
<dependency>
<groupId>org.eclipse.jetty</groupId>
<artifactId>test-continuation</artifactId>
<version>${project.version}</version>
<scope>test</scope>
+ <exclusions>
+ <exclusion>
+ <groupId>${servlet.spec.groupId}</groupId>
+ <artifactId>${servlet.spec.artifactId}</artifactId>
+ </exclusion>
+ </exclusions>
</dependency>
<dependency>
<groupId>org.mortbay.jetty</groupId>
diff --git a/test-continuation-jetty6/src/test/java/org/eclipse/jetty/continuation/ContinuationBase.java b/test-continuation-jetty6/src/test/java/org/eclipse/jetty/continuation/ContinuationBase.java
new file mode 100644
index 0000000000..b61f7326a0
--- /dev/null
+++ b/test-continuation-jetty6/src/test/java/org/eclipse/jetty/continuation/ContinuationBase.java
@@ -0,0 +1,428 @@
+//
+// ========================================================================
+// Copyright (c) 1995-2012 Mort Bay Consulting Pty. Ltd.
+// ------------------------------------------------------------------------
+// All rights reserved. This program and the accompanying materials
+// are made available under the terms of the Eclipse Public License v1.0
+// and Apache License v2.0 which accompanies this distribution.
+//
+// The Eclipse Public License is available at
+// http://www.eclipse.org/legal/epl-v10.html
+//
+// The Apache License v2.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.continuation;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.net.Socket;
+import java.util.Timer;
+import java.util.TimerTask;
+
+import javax.servlet.ServletException;
+import javax.servlet.http.HttpServlet;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import junit.framework.TestCase;
+
+
+
+public abstract class ContinuationBase extends TestCase
+{
+ protected SuspendServlet _servlet=new SuspendServlet();
+ protected int _port;
+
+ protected void doit(String type) throws Exception
+ {
+ String response;
+
+ response=process(null,null);
+ assertContains(type,response);
+ assertContains("NORMAL",response);
+ assertNotContains("history: onTimeout",response);
+ assertNotContains("history: onComplete",response);
+
+ response=process("sleep=200",null);
+ assertContains("SLEPT",response);
+ assertNotContains("history: onTimeout",response);
+ assertNotContains("history: onComplete",response);
+
+ response=process("suspend=200",null);
+ assertContains("TIMEOUT",response);
+ assertContains("history: onTimeout",response);
+ assertContains("history: onComplete",response);
+
+ response=process("suspend=200&resume=10",null);
+ assertContains("RESUMED",response);
+ assertNotContains("history: onTimeout",response);
+ assertContains("history: onComplete",response);
+
+ response=process("suspend=200&resume=0",null);
+ assertContains("RESUMED",response);
+ assertNotContains("history: onTimeout",response);
+ assertContains("history: onComplete",response);
+
+ response=process("suspend=200&complete=10",null);
+ assertContains("COMPLETED",response);
+ assertNotContains("history: onTimeout",response);
+ assertContains("history: onComplete",response);
+
+ response=process("suspend=200&complete=0",null);
+ assertContains("COMPLETED",response);
+ assertNotContains("history: onTimeout",response);
+ assertContains("history: onComplete",response);
+
+
+ response=process("suspend=1000&resume=10&suspend2=1000&resume2=10",null);
+ assertEquals(2,count(response,"history: suspend"));
+ assertEquals(2,count(response,"history: resume"));
+ assertEquals(0,count(response,"history: onTimeout"));
+ assertEquals(1,count(response,"history: onComplete"));
+ assertContains("RESUMED",response);
+
+ response=process("suspend=1000&resume=10&suspend2=1000&resume2=10",null);
+ assertEquals(2,count(response,"history: suspend"));
+ assertEquals(2,count(response,"history: resume"));
+ assertEquals(0,count(response,"history: onTimeout"));
+ assertEquals(1,count(response,"history: onComplete"));
+ assertContains("RESUMED",response);
+
+ response=process("suspend=1000&resume=10&suspend2=1000&complete2=10",null);
+ assertEquals(2,count(response,"history: suspend"));
+ assertEquals(1,count(response,"history: resume"));
+ assertEquals(0,count(response,"history: onTimeout"));
+ assertEquals(1,count(response,"history: onComplete"));
+ assertContains("COMPLETED",response);
+
+ response=process("suspend=1000&resume=10&suspend2=10",null);
+ assertEquals(2,count(response,"history: suspend"));
+ assertEquals(1,count(response,"history: resume"));
+ assertEquals(1,count(response,"history: onTimeout"));
+ assertEquals(1,count(response,"history: onComplete"));
+ assertContains("TIMEOUT",response);
+
+
+
+ response=process("suspend=10&suspend2=1000&resume2=10",null);
+ assertEquals(2,count(response,"history: suspend"));
+ assertEquals(1,count(response,"history: resume"));
+ assertEquals(1,count(response,"history: onTimeout"));
+ assertEquals(1,count(response,"history: onComplete"));
+ assertContains("RESUMED",response);
+
+ response=process("suspend=10&suspend2=1000&resume2=10",null);
+ assertEquals(2,count(response,"history: suspend"));
+ assertEquals(1,count(response,"history: resume"));
+ assertEquals(1,count(response,"history: onTimeout"));
+ assertEquals(1,count(response,"history: onComplete"));
+ assertContains("RESUMED",response);
+
+ response=process("suspend=10&suspend2=1000&complete2=10",null);
+ assertEquals(2,count(response,"history: suspend"));
+ assertEquals(0,count(response,"history: resume"));
+ assertEquals(1,count(response,"history: onTimeout"));
+ assertEquals(1,count(response,"history: onComplete"));
+ assertContains("COMPLETED",response);
+
+ response=process("suspend=10&suspend2=10",null);
+ assertEquals(2,count(response,"history: suspend"));
+ assertEquals(0,count(response,"history: resume"));
+ assertEquals(2,count(response,"history: onTimeout"));
+ assertEquals(1,count(response,"history: onComplete"));
+ assertContains("TIMEOUT",response);
+
+ }
+
+
+ private int count(String responses,String substring)
+ {
+ int count=0;
+ int i=responses.indexOf(substring);
+ while (i>=0)
+ {
+ count++;
+ i=responses.indexOf(substring,i+substring.length());
+ }
+
+ return count;
+ }
+
+ protected void assertContains(String content,String response)
+ {
+ assertEquals("HTTP/1.1 200 OK",response.substring(0,15));
+ if (response.indexOf(content,15)<0)
+ {
+ System.err.println(content+" NOT IN '"+response+"'");
+ assertTrue(false);
+ }
+ }
+
+ protected void assertNotContains(String content,String response)
+ {
+ assertEquals("HTTP/1.1 200 OK",response.substring(0,15));
+ if (response.indexOf(content,15)>=0)
+ {
+ System.err.println(content+" IS IN '"+response+"'");
+ assertTrue(false);
+ }
+ }
+
+ public synchronized String process(String query,String content) throws Exception
+ {
+ String request = "GET /";
+
+ if (query!=null)
+ request+="?"+query;
+ request+=" HTTP/1.1\r\n"+
+ "Host: localhost\r\n"+
+ "Connection: close\r\n";
+ if (content!=null)
+ request+="Content-Length: "+content.length()+"\r\n";
+ request+="\r\n" + content;
+
+ Socket socket = new Socket("localhost",_port);
+ socket.getOutputStream().write(request.getBytes("UTF-8"));
+
+ String response = toString(socket.getInputStream());
+ return response;
+ }
+
+
+ protected abstract String toString(InputStream in) throws IOException;
+
+
+ private static class SuspendServlet extends HttpServlet
+ {
+ private Timer _timer=new Timer();
+
+ public SuspendServlet()
+ {}
+
+ /* ------------------------------------------------------------ */
+ protected void doGet(final HttpServletRequest request, final HttpServletResponse response) throws ServletException, IOException
+ {
+ final Continuation continuation = ContinuationSupport.getContinuation(request,response);
+
+ response.addHeader("history",continuation.getClass().toString());
+
+ int read_before=0;
+ long sleep_for=-1;
+ long suspend_for=-1;
+ long suspend2_for=-1;
+ long resume_after=-1;
+ long resume2_after=-1;
+ long complete_after=-1;
+ long complete2_after=-1;
+
+ if (request.getParameter("read")!=null)
+ read_before=Integer.parseInt(request.getParameter("read"));
+ if (request.getParameter("sleep")!=null)
+ sleep_for=Integer.parseInt(request.getParameter("sleep"));
+ if (request.getParameter("suspend")!=null)
+ suspend_for=Integer.parseInt(request.getParameter("suspend"));
+ if (request.getParameter("suspend2")!=null)
+ suspend2_for=Integer.parseInt(request.getParameter("suspend2"));
+ if (request.getParameter("resume")!=null)
+ resume_after=Integer.parseInt(request.getParameter("resume"));
+ if (request.getParameter("resume2")!=null)
+ resume2_after=Integer.parseInt(request.getParameter("resume2"));
+ if (request.getParameter("complete")!=null)
+ complete_after=Integer.parseInt(request.getParameter("complete"));
+ if (request.getParameter("complete2")!=null)
+ complete2_after=Integer.parseInt(request.getParameter("complete2"));
+
+ if (continuation.isInitial())
+ {
+ if (read_before>0)
+ {
+ byte[] buf=new byte[read_before];
+ request.getInputStream().read(buf);
+ }
+ else if (read_before<0)
+ {
+ InputStream in = request.getInputStream();
+ int b=in.read();
+ while(b!=-1)
+ b=in.read();
+ }
+
+ if (suspend_for>=0)
+ {
+ if (suspend_for>0)
+ continuation.setTimeout(suspend_for);
+ continuation.addContinuationListener(__listener);
+ ((HttpServletResponse)continuation.getServletResponse()).addHeader("history","suspend");
+ continuation.suspend();
+
+ if (complete_after>0)
+ {
+ TimerTask complete = new TimerTask()
+ {
+ public void run()
+ {
+ try
+ {
+ response.setStatus(200);
+ response.getOutputStream().println("COMPLETED\n");
+ continuation.complete();
+ }
+ catch(Exception e)
+ {
+ e.printStackTrace();
+ }
+ }
+ };
+ synchronized (_timer)
+ {
+ _timer.schedule(complete,complete_after);
+ }
+ }
+ else if (complete_after==0)
+ {
+ response.setStatus(200);
+ response.getOutputStream().println("COMPLETED\n");
+ continuation.complete();
+ }
+ else if (resume_after>0)
+ {
+ TimerTask resume = new TimerTask()
+ {
+ public void run()
+ {
+ ((HttpServletResponse)continuation.getServletResponse()).addHeader("history","resume");
+ continuation.resume();
+ }
+ };
+ synchronized (_timer)
+ {
+ _timer.schedule(resume,resume_after);
+ }
+ }
+ else if (resume_after==0)
+ {
+ ((HttpServletResponse)continuation.getServletResponse()).addHeader("history","resume");
+ continuation.resume();
+ }
+ }
+ else if (sleep_for>=0)
+ {
+ try
+ {
+ Thread.sleep(sleep_for);
+ }
+ catch (InterruptedException e)
+ {
+ e.printStackTrace();
+ }
+ response.setStatus(200);
+ response.getOutputStream().println("SLEPT\n");
+ }
+ else
+ {
+ response.setStatus(200);
+ response.getOutputStream().println("NORMAL\n");
+ }
+ }
+ else if (suspend2_for>=0 && request.getAttribute("2nd")==null)
+ {
+ request.setAttribute("2nd","cycle");
+
+ if (suspend2_for>0)
+ continuation.setTimeout(suspend2_for);
+ // continuation.addContinuationListener(__listener);
+ ((HttpServletResponse)continuation.getServletResponse()).addHeader("history","suspend");
+ continuation.suspend();
+
+ if (complete2_after>0)
+ {
+ TimerTask complete = new TimerTask()
+ {
+ public void run()
+ {
+ try
+ {
+ response.setStatus(200);
+ response.getOutputStream().println("COMPLETED\n");
+ continuation.complete();
+ }
+ catch(Exception e)
+ {
+ e.printStackTrace();
+ }
+ }
+ };
+ synchronized (_timer)
+ {
+ _timer.schedule(complete,complete2_after);
+ }
+ }
+ else if (complete2_after==0)
+ {
+ response.setStatus(200);
+ response.getOutputStream().println("COMPLETED\n");
+ continuation.complete();
+ }
+ else if (resume2_after>0)
+ {
+ TimerTask resume = new TimerTask()
+ {
+ public void run()
+ {
+ ((HttpServletResponse)continuation.getServletResponse()).addHeader("history","resume");
+ continuation.resume();
+ }
+ };
+ synchronized (_timer)
+ {
+ _timer.schedule(resume,resume2_after);
+ }
+ }
+ else if (resume2_after==0)
+ {
+ ((HttpServletResponse)continuation.getServletResponse()).addHeader("history","resume");
+ continuation.resume();
+ }
+ return;
+ }
+ else if (continuation.isExpired())
+ {
+ response.setStatus(200);
+ response.getOutputStream().println("TIMEOUT\n");
+ }
+ else if (continuation.isResumed())
+ {
+ response.setStatus(200);
+ response.getOutputStream().println("RESUMED\n");
+ }
+ else
+ {
+ response.setStatus(200);
+ response.getOutputStream().println("unknown???\n");
+ }
+ }
+ }
+
+
+
+ private static ContinuationListener __listener =
+ new ContinuationListener()
+ {
+ public void onComplete(Continuation continuation)
+ {
+ ((HttpServletResponse)continuation.getServletResponse()).addHeader("history","onComplete");
+ }
+
+ public void onTimeout(Continuation continuation)
+ {
+ ((HttpServletResponse)continuation.getServletResponse()).addHeader("history","onTimeout");
+ continuation.resume();
+ }
+
+ };
+}
diff --git a/test-continuation-jetty6/src/test/java/org/eclipse/jetty/continuation/FauxContinuationTest.java b/test-continuation-jetty6/src/test/java/org/eclipse/jetty/continuation/FauxContinuationTest.java
new file mode 100644
index 0000000000..236f0428d1
--- /dev/null
+++ b/test-continuation-jetty6/src/test/java/org/eclipse/jetty/continuation/FauxContinuationTest.java
@@ -0,0 +1,83 @@
+//
+// ========================================================================
+// Copyright (c) 1995-2012 Mort Bay Consulting Pty. Ltd.
+// ------------------------------------------------------------------------
+// All rights reserved. This program and the accompanying materials
+// are made available under the terms of the Eclipse Public License v1.0
+// and Apache License v2.0 which accompanies this distribution.
+//
+// The Eclipse Public License is available at
+// http://www.eclipse.org/legal/epl-v10.html
+//
+// The Apache License v2.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.continuation;
+
+import java.io.IOException;
+import java.io.InputStream;
+
+import javax.servlet.Filter;
+import javax.servlet.FilterChain;
+import javax.servlet.FilterConfig;
+import javax.servlet.ServletException;
+import javax.servlet.ServletRequest;
+import javax.servlet.ServletResponse;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletRequestWrapper;
+
+import org.mortbay.jetty.Connector;
+import org.mortbay.jetty.Server;
+import org.mortbay.jetty.nio.SelectChannelConnector;
+import org.mortbay.jetty.servlet.Context;
+import org.mortbay.jetty.servlet.FilterHolder;
+import org.mortbay.jetty.servlet.ServletHandler;
+import org.mortbay.jetty.servlet.ServletHolder;
+import org.mortbay.util.IO;
+
+
+public class FauxContinuationTest extends ContinuationBase
+{
+ protected Server _server = new Server();
+ protected ServletHandler _servletHandler;
+ protected SelectChannelConnector _connector;
+ FilterHolder _filter;
+
+ protected void setUp() throws Exception
+ {
+ _connector = new SelectChannelConnector();
+ _server.setConnectors(new Connector[]{ _connector });
+ Context servletContext = new Context(Context.NO_SECURITY|Context.NO_SESSIONS);
+ _server.setHandler(servletContext);
+ _servletHandler=servletContext.getServletHandler();
+ ServletHolder holder=new ServletHolder(_servlet);
+ _servletHandler.addServletWithMapping(holder,"/");
+ _filter=_servletHandler.addFilterWithMapping(ContinuationFilter.class,"/*",0);
+ }
+
+ protected void tearDown() throws Exception
+ {
+ _server.stop();
+ }
+
+ public void testFaux() throws Exception
+ {
+ _filter.setInitParameter("debug","true");
+ _filter.setInitParameter("faux","true");
+ _server.start();
+ _port=_connector.getLocalPort();
+
+ doit("FauxContinuation");
+ }
+
+
+
+ protected String toString(InputStream in) throws IOException
+ {
+ return IO.toString(in);
+ }
+}
diff --git a/test-continuation/pom.xml b/test-continuation/pom.xml
index f07979a561..426bdd5afe 100644
--- a/test-continuation/pom.xml
+++ b/test-continuation/pom.xml
@@ -2,7 +2,7 @@
<parent>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-project</artifactId>
- <version>7.6.8-SNAPSHOT</version>
+ <version>8.1.8-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>test-continuation</artifactId>
diff --git a/test-continuation/src/test/java/org/eclipse/jetty/continuation/ContinuationTest.java b/test-continuation/src/test/java/org/eclipse/jetty/continuation/ContinuationTest.java
index 62edf176ed..74bb6acd34 100644
--- a/test-continuation/src/test/java/org/eclipse/jetty/continuation/ContinuationTest.java
+++ b/test-continuation/src/test/java/org/eclipse/jetty/continuation/ContinuationTest.java
@@ -20,6 +20,7 @@ package org.eclipse.jetty.continuation;
import java.io.IOException;
import java.io.InputStream;
+import java.util.EnumSet;
import org.eclipse.jetty.continuation.test.ContinuationBase;
import org.eclipse.jetty.server.Connector;
@@ -49,6 +50,7 @@ public class ContinuationTest extends ContinuationBase
_server.setHandler(servletContext);
_servletHandler=servletContext.getServletHandler();
ServletHolder holder=new ServletHolder(_servlet);
+ holder.setAsyncSupported(true);
_servletHandler.addServletWithMapping(holder,"/");
_server.start();
diff --git a/test-continuation/src/test/java/org/eclipse/jetty/continuation/FauxContinuationTest.java b/test-continuation/src/test/java/org/eclipse/jetty/continuation/FauxContinuationTest.java
index 7d0dd38e7e..19ba537399 100644
--- a/test-continuation/src/test/java/org/eclipse/jetty/continuation/FauxContinuationTest.java
+++ b/test-continuation/src/test/java/org/eclipse/jetty/continuation/FauxContinuationTest.java
@@ -20,6 +20,9 @@ package org.eclipse.jetty.continuation;
import java.io.IOException;
import java.io.InputStream;
+import java.util.EnumSet;
+
+import javax.servlet.DispatcherType;
import org.eclipse.jetty.continuation.test.ContinuationBase;
import org.eclipse.jetty.server.Connector;
@@ -49,7 +52,7 @@ public class FauxContinuationTest extends ContinuationBase
ServletHolder holder=new ServletHolder(_servlet);
_servletHandler.addServletWithMapping(holder,"/");
- _filter=_servletHandler.addFilterWithMapping(ContinuationFilter.class,"/*",0);
+ _filter=_servletHandler.addFilterWithMapping(ContinuationFilter.class,"/*",null);
_filter.setInitParameter("debug","true");
_filter.setInitParameter("faux","true");
_server.start();
diff --git a/test-jetty-nested/pom.xml b/test-jetty-nested/pom.xml
index adf850d21f..85ae9632db 100644
--- a/test-jetty-nested/pom.xml
+++ b/test-jetty-nested/pom.xml
@@ -4,7 +4,7 @@
<parent>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-project</artifactId>
- <version>7.6.8-SNAPSHOT</version>
+ <version>8.1.8-SNAPSHOT</version>
</parent>
<artifactId>test-jetty-nested</artifactId>
<name>Jetty :: Nested Test</name>
diff --git a/test-jetty-servlet/pom.xml b/test-jetty-servlet/pom.xml
index b4b732b719..2d792340eb 100644
--- a/test-jetty-servlet/pom.xml
+++ b/test-jetty-servlet/pom.xml
@@ -2,7 +2,7 @@
<parent>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-project</artifactId>
- <version>7.6.8-SNAPSHOT</version>
+ <version>8.1.8-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>test-jetty-servlet</artifactId>
diff --git a/test-jetty-servlet/src/main/java/org/eclipse/jetty/testing/HttpTester.java b/test-jetty-servlet/src/main/java/org/eclipse/jetty/testing/HttpTester.java
index 0f360c12e6..41cab781df 100644
--- a/test-jetty-servlet/src/main/java/org/eclipse/jetty/testing/HttpTester.java
+++ b/test-jetty-servlet/src/main/java/org/eclipse/jetty/testing/HttpTester.java
@@ -382,7 +382,7 @@ public class HttpTester
cookie.getMaxAge(),
cookie.getComment(),
cookie.getSecure(),
- false,
+ cookie.isHttpOnly(),
cookie.getVersion());
}
diff --git a/test-jetty-servlet/src/main/java/org/eclipse/jetty/testing/ServletTester.java b/test-jetty-servlet/src/main/java/org/eclipse/jetty/testing/ServletTester.java
index bd07b9cdb8..4d185c2a78 100644
--- a/test-jetty-servlet/src/main/java/org/eclipse/jetty/testing/ServletTester.java
+++ b/test-jetty-servlet/src/main/java/org/eclipse/jetty/testing/ServletTester.java
@@ -19,9 +19,12 @@
package org.eclipse.jetty.testing;
import java.net.InetAddress;
+import java.util.EnumSet;
import java.util.Enumeration;
import java.util.EventListener;
+import javax.servlet.DispatcherType;
+
import org.eclipse.jetty.io.ByteArrayBuffer;
import org.eclipse.jetty.server.LocalConnector;
import org.eclipse.jetty.server.Server;
@@ -239,7 +242,7 @@ public class ServletTester
* @return the FilterHolder
* @see org.eclipse.jetty.servlet.ServletContextHandler#addFilter(java.lang.Class, java.lang.String, int)
*/
- public FilterHolder addFilter(Class filterClass, String pathSpec, int dispatches)
+ public FilterHolder addFilter(Class filterClass, String pathSpec, EnumSet<DispatcherType> dispatches)
{
return _context.addFilter(filterClass,pathSpec,dispatches);
}
@@ -252,7 +255,7 @@ public class ServletTester
* @return the FilterHolder
* @see org.eclipse.jetty.servlet.ServletContextHandler#addFilter(java.lang.String, java.lang.String, int)
*/
- public FilterHolder addFilter(String filterClass, String pathSpec, int dispatches)
+ public FilterHolder addFilter(String filterClass, String pathSpec, EnumSet<DispatcherType> dispatches)
{
return _context.addFilter(filterClass,pathSpec,dispatches);
}
diff --git a/test-jetty-webapp/pom.xml b/test-jetty-webapp/pom.xml
index 45cbfe7353..71b4f6a620 100644
--- a/test-jetty-webapp/pom.xml
+++ b/test-jetty-webapp/pom.xml
@@ -2,7 +2,7 @@
<parent>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-project</artifactId>
- <version>7.6.8-SNAPSHOT</version>
+ <version>8.1.8-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>test-jetty-webapp</artifactId>
@@ -94,11 +94,11 @@
</execution>
</executions>
</plugin>
-<!--
+<!--
<plugin>
<groupId>org.mortbay.jetty</groupId>
<artifactId>jetty-maven-plugin</artifactId>
- <version>7.5.2-SNAPSHOT</version>
+ <version>${project.version}</version>
<configuration>
<stopPort>8087</stopPort>
<stopKey>foo</stopKey>
@@ -109,6 +109,7 @@
<value>222</value>
</systemProperty>
</systemProperties>
+ <useTestScope>true</useTestScope>
<webAppConfig>
<contextPath>/test</contextPath>
<tempDirectory>${project.build.directory}/work</tempDirectory>
diff --git a/test-jetty-webapp/src/main/config/contexts/test.d/override-web.xml b/test-jetty-webapp/src/main/config/contexts/test.d/override-web.xml
index 9e42d6d5ef..7b7f9e4312 100644
--- a/test-jetty-webapp/src/main/config/contexts/test.d/override-web.xml
+++ b/test-jetty-webapp/src/main/config/contexts/test.d/override-web.xml
@@ -15,15 +15,6 @@
<param-value>a context value</param-value>
</context-param>
- <!-- Add or override filter init parameter -->
- <filter>
- <filter-name>TestFilter</filter-name>
- <filter-class>com.acme.TestFilter</filter-class>
- <init-param>
- <param-name>remote</param-name>
- <param-value>false</param-value>
- </init-param>
- </filter>
<!-- Add or override servlet init parameter -->
<servlet>
diff --git a/test-jetty-webapp/src/main/java/com/acme/Dump.java b/test-jetty-webapp/src/main/java/com/acme/Dump.java
index c6ffe0ef7f..0530fa6b7c 100644
--- a/test-jetty-webapp/src/main/java/com/acme/Dump.java
+++ b/test-jetty-webapp/src/main/java/com/acme/Dump.java
@@ -119,6 +119,18 @@ public class Dump extends HttpServlet
@Override
public void doGet(final HttpServletRequest request, final HttpServletResponse response) throws ServletException, IOException
{
+ if (!request.isUserInRole("user"))
+ {
+ try
+ {
+ request.login("user", "password");
+ }
+ catch(ServletException se)
+ {
+ se.printStackTrace();
+ }
+ }
+
// Handle a dump of data
final String data= request.getParameter("data");
final String chars= request.getParameter("chars");
diff --git a/test-jetty-webapp/src/main/java/com/acme/LoginServlet.java b/test-jetty-webapp/src/main/java/com/acme/LoginServlet.java
new file mode 100644
index 0000000000..e86598d281
--- /dev/null
+++ b/test-jetty-webapp/src/main/java/com/acme/LoginServlet.java
@@ -0,0 +1,92 @@
+//
+// ========================================================================
+// Copyright (c) 1995-2012 Mort Bay Consulting Pty. Ltd.
+// ------------------------------------------------------------------------
+// All rights reserved. This program and the accompanying materials
+// are made available under the terms of the Eclipse Public License v1.0
+// and Apache License v2.0 which accompanies this distribution.
+//
+// The Eclipse Public License is available at
+// http://www.eclipse.org/legal/epl-v10.html
+//
+// The Apache License v2.0 is available at
+// http://www.opensource.org/licenses/apache2.0.php
+//
+// You may elect to redistribute this code under either of these licenses.
+// ========================================================================
+//
+
+package com.acme;
+
+import java.io.File;
+import java.io.IOException;
+import java.io.PrintStream;
+import java.net.URL;
+import java.net.URLClassLoader;
+import java.util.Calendar;
+import java.util.GregorianCalendar;
+
+import javax.servlet.ServletConfig;
+import javax.servlet.ServletException;
+import javax.servlet.ServletOutputStream;
+import javax.servlet.http.HttpServlet;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import org.eclipse.jetty.util.log.Log;
+import org.eclipse.jetty.util.log.Logger;
+
+
+/* ------------------------------------------------------------ */
+/** Dump Servlet Request.
+ *
+ */
+public class LoginServlet extends HttpServlet
+{
+ private static final Logger LOG = Log.getLogger(SecureModeServlet.class);
+
+ /* ------------------------------------------------------------ */
+ @Override
+ public void init(ServletConfig config) throws ServletException
+ {
+ super.init(config);
+ }
+
+ /* ------------------------------------------------------------ */
+ @Override
+ public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException
+ {
+ doGet(request, response);
+ }
+
+ /* ------------------------------------------------------------ */
+ @Override
+ public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException
+ {
+
+ response.setContentType("text/html");
+ ServletOutputStream out = response.getOutputStream();
+ out.println("<html>");
+ out.println("<br/>Before getUserPrincipal="+request.getUserPrincipal());
+ out.println("<br/>Before getRemoteUser="+request.getRemoteUser());
+ String param = request.getParameter("action");
+
+ if ("login".equals(param))
+ {
+ request.login("jetty", "jetty");
+ }
+ else if ("logout".equals(param))
+ {
+ request.logout();
+ }
+ else if ("wrong".equals(param))
+ {
+ request.login("jetty", "123");
+ }
+
+ out.println("<br/>After getUserPrincipal="+request.getUserPrincipal());
+ out.println("<br/>After getRemoteUser="+request.getRemoteUser());
+ out.println("</html>");
+ out.flush();
+ }
+}
diff --git a/test-jetty-webapp/src/main/java/com/acme/RegTest.java b/test-jetty-webapp/src/main/java/com/acme/RegTest.java
new file mode 100644
index 0000000000..8d99cd11a5
--- /dev/null
+++ b/test-jetty-webapp/src/main/java/com/acme/RegTest.java
@@ -0,0 +1,194 @@
+//
+// ========================================================================
+// Copyright (c) 1995-2012 Mort Bay Consulting Pty. Ltd.
+// ------------------------------------------------------------------------
+// All rights reserved. This program and the accompanying materials
+// are made available under the terms of the Eclipse Public License v1.0
+// and Apache License v2.0 which accompanies this distribution.
+//
+// The Eclipse Public License is available at
+// http://www.eclipse.org/legal/epl-v10.html
+//
+// The Apache License v2.0 is available at
+// http://www.opensource.org/licenses/apache2.0.php
+//
+// You may elect to redistribute this code under either of these licenses.
+// ========================================================================
+//
+
+package com.acme;
+import java.io.IOException;
+import java.io.OutputStreamWriter;
+import java.io.PrintWriter;
+
+import javax.servlet.ServletConfig;
+import javax.servlet.ServletException;
+import javax.servlet.http.HttpServlet;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import org.eclipse.jetty.util.StringUtil;
+
+
+
+
+/* ------------------------------------------------------------ */
+/** Rego Servlet - tests being accessed from servlet 3.0 programmatic
+ * configuration.
+ *
+ */
+public class RegTest extends HttpServlet
+{
+
+ /* ------------------------------------------------------------ */
+ @Override
+ public void init(ServletConfig config) throws ServletException
+ {
+ super.init(config);
+ }
+
+ /* ------------------------------------------------------------ */
+ @Override
+ public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException
+ {
+ doGet(request, response);
+ }
+
+ /* ------------------------------------------------------------ */
+ @Override
+ public void doGet(final HttpServletRequest request, final HttpServletResponse response) throws ServletException, IOException
+ {
+ request.setCharacterEncoding("UTF-8");
+ PrintWriter pout=null;
+
+ try
+ {
+ pout =response.getWriter();
+ }
+ catch(IllegalStateException e)
+ {
+ pout=new PrintWriter(new OutputStreamWriter(response.getOutputStream(),"UTF-8"));
+ }
+
+ try
+ {
+ pout.write("<html>\n<body>\n");
+ pout.write("<h1>Rego Servlet</h1>\n");
+ pout.write("<table width=\"95%\">");
+ pout.write("<tr>\n");
+ pout.write("<th align=\"right\">getMethod:&nbsp;</th>");
+ pout.write("<td>" + notag(request.getMethod())+"</td>");
+ pout.write("</tr><tr>\n");
+ pout.write("<th align=\"right\">getContentLength:&nbsp;</th>");
+ pout.write("<td>"+Integer.toString(request.getContentLength())+"</td>");
+ pout.write("</tr><tr>\n");
+ pout.write("<th align=\"right\">getContentType:&nbsp;</th>");
+ pout.write("<td>"+notag(request.getContentType())+"</td>");
+ pout.write("</tr><tr>\n");
+ pout.write("<th align=\"right\">getRequestURI:&nbsp;</th>");
+ pout.write("<td>"+notag(request.getRequestURI())+"</td>");
+ pout.write("</tr><tr>\n");
+ pout.write("<th align=\"right\">getRequestURL:&nbsp;</th>");
+ pout.write("<td>"+notag(request.getRequestURL().toString())+"</td>");
+ pout.write("</tr><tr>\n");
+ pout.write("<th align=\"right\">getContextPath:&nbsp;</th>");
+ pout.write("<td>"+request.getContextPath()+"</td>");
+ pout.write("</tr><tr>\n");
+ pout.write("<th align=\"right\">getServletPath:&nbsp;</th>");
+ pout.write("<td>"+notag(request.getServletPath())+"</td>");
+ pout.write("</tr><tr>\n");
+ pout.write("<th align=\"right\">getPathInfo:&nbsp;</th>");
+ pout.write("<td>"+notag(request.getPathInfo())+"</td>");
+ pout.write("</tr><tr>\n");
+ pout.write("<th align=\"right\">getPathTranslated:&nbsp;</th>");
+ pout.write("<td>"+notag(request.getPathTranslated())+"</td>");
+ pout.write("</tr><tr>\n");
+ pout.write("<th align=\"right\">getQueryString:&nbsp;</th>");
+ pout.write("<td>"+notag(request.getQueryString())+"</td>");
+ pout.write("</tr><tr>\n");
+
+ pout.write("<th align=\"right\">getProtocol:&nbsp;</th>");
+ pout.write("<td>"+request.getProtocol()+"</td>");
+ pout.write("</tr><tr>\n");
+ pout.write("<th align=\"right\">getScheme:&nbsp;</th>");
+ pout.write("<td>"+request.getScheme()+"</td>");
+ pout.write("</tr><tr>\n");
+ pout.write("<th align=\"right\">getServerName:&nbsp;</th>");
+ pout.write("<td>"+notag(request.getServerName())+"</td>");
+ pout.write("</tr><tr>\n");
+ pout.write("<th align=\"right\">getServerPort:&nbsp;</th>");
+ pout.write("<td>"+Integer.toString(request.getServerPort())+"</td>");
+ pout.write("</tr><tr>\n");
+ pout.write("<th align=\"right\">getLocalName:&nbsp;</th>");
+ pout.write("<td>"+request.getLocalName()+"</td>");
+ pout.write("</tr><tr>\n");
+ pout.write("<th align=\"right\">getLocalAddr:&nbsp;</th>");
+ pout.write("<td>"+request.getLocalAddr()+"</td>");
+ pout.write("</tr><tr>\n");
+ pout.write("<th align=\"right\">getLocalPort:&nbsp;</th>");
+ pout.write("<td>"+Integer.toString(request.getLocalPort())+"</td>");
+ pout.write("</tr><tr>\n");
+ pout.write("<th align=\"right\">getRemoteUser:&nbsp;</th>");
+ pout.write("<td>"+request.getRemoteUser()+"</td>");
+ pout.write("</tr><tr>\n");
+ pout.write("<th align=\"right\">getUserPrincipal:&nbsp;</th>");
+ pout.write("<td>"+request.getUserPrincipal()+"</td>");
+ pout.write("</tr><tr>\n");
+ pout.write("<th align=\"right\">getRemoteAddr:&nbsp;</th>");
+ pout.write("<td>"+request.getRemoteAddr()+"</td>");
+ pout.write("</tr><tr>\n");
+ pout.write("<th align=\"right\">getRemoteHost:&nbsp;</th>");
+ pout.write("<td>"+request.getRemoteHost()+"</td>");
+ pout.write("</tr><tr>\n");
+ pout.write("<th align=\"right\">getRemotePort:&nbsp;</th>");
+ pout.write("<td>"+request.getRemotePort()+"</td>");
+ pout.write("</tr><tr>\n");
+ pout.write("<th align=\"right\">getRequestedSessionId:&nbsp;</th>");
+ pout.write("<td>"+request.getRequestedSessionId()+"</td>");
+ pout.write("</tr><tr>\n");
+ pout.write("<th align=\"right\">isSecure():&nbsp;</th>");
+ pout.write("<td>"+request.isSecure()+"</td>");
+
+ pout.write("</tr><tr>\n");
+ pout.write("<th align=\"right\">isUserInRole(admin):&nbsp;</th>");
+ pout.write("<td>"+request.isUserInRole("admin")+"</td>");
+
+ pout.write("</tr></table>");
+
+ }
+ catch (Exception e)
+ {
+ getServletContext().log("dump "+e);
+ }
+
+
+ pout.write("</body>\n</html>\n");
+
+ pout.close();
+ }
+
+
+ /* ------------------------------------------------------------ */
+ @Override
+ public String getServletInfo()
+ {
+ return "Rego Servlet";
+ }
+
+ /* ------------------------------------------------------------ */
+ @Override
+ public synchronized void destroy()
+ {
+ }
+
+
+ private String notag(String s)
+ {
+ if (s==null)
+ return "null";
+ s=StringUtil.replace(s,"&","&amp;");
+ s=StringUtil.replace(s,"<","&lt;");
+ s=StringUtil.replace(s,">","&gt;");
+ return s;
+ }
+}
diff --git a/test-jetty-webapp/src/main/java/com/acme/TestListener.java b/test-jetty-webapp/src/main/java/com/acme/TestListener.java
index faaa76085b..02674b4882 100644
--- a/test-jetty-webapp/src/main/java/com/acme/TestListener.java
+++ b/test-jetty-webapp/src/main/java/com/acme/TestListener.java
@@ -18,6 +18,7 @@
package com.acme;
+import javax.servlet.DispatcherType;
import javax.servlet.ServletContextAttributeEvent;
import javax.servlet.ServletContextAttributeListener;
import javax.servlet.ServletContextEvent;
@@ -26,6 +27,12 @@ import javax.servlet.ServletRequestAttributeEvent;
import javax.servlet.ServletRequestAttributeListener;
import javax.servlet.ServletRequestEvent;
import javax.servlet.ServletRequestListener;
+import javax.servlet.ServletRegistration;
+import javax.servlet.FilterRegistration;
+import javax.servlet.ServletSecurityElement;
+import javax.servlet.HttpConstraintElement;
+import javax.servlet.HttpMethodConstraintElement;
+import javax.servlet.annotation.ServletSecurity;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSessionActivationListener;
import javax.servlet.http.HttpSessionAttributeListener;
@@ -33,6 +40,9 @@ import javax.servlet.http.HttpSessionBindingEvent;
import javax.servlet.http.HttpSessionEvent;
import javax.servlet.http.HttpSessionListener;
+import java.util.EnumSet;
+import java.util.Set;
+
public class TestListener implements HttpSessionListener, HttpSessionAttributeListener, HttpSessionActivationListener, ServletContextListener, ServletContextAttributeListener, ServletRequestListener, ServletRequestAttributeListener
{
public void attributeAdded(HttpSessionBindingEvent se)
@@ -62,16 +72,30 @@ public class TestListener implements HttpSessionListener, HttpSessionAttributeL
public void contextInitialized(ServletContextEvent sce)
{
- /* TODO for servlet 3.0
- * FilterRegistration registration=context.addFilter("TestFilter",TestFilter.class.getName());
-
-
+ //configure programmatic security
+ ServletRegistration.Dynamic rego = sce.getServletContext().addServlet("RegoTest", RegTest.class.getName());
+ rego.addMapping("/rego/*");
+ HttpConstraintElement constraintElement = new HttpConstraintElement(ServletSecurity.EmptyRoleSemantic.PERMIT,
+ ServletSecurity.TransportGuarantee.NONE, new String[]{"admin"});
+ ServletSecurityElement securityElement = new ServletSecurityElement(constraintElement, null);
+ Set<String> unchanged = rego.setServletSecurity(securityElement);
+ //System.err.println("Security constraints registered: "+unchanged.isEmpty());
+
+ //Test that a security constraint from web.xml can't be overridden programmatically
+ ServletRegistration.Dynamic rego2 = sce.getServletContext().addServlet("RegoTest2", RegTest.class.getName());
+ rego2.addMapping("/rego2/*");
+ securityElement = new ServletSecurityElement(constraintElement, null);
+ unchanged = rego2.setServletSecurity(securityElement);
+ //System.err.println("Overridding web.xml constraints not possible:" +!unchanged.isEmpty());
+
+ /* For servlet 3.0 */
+ FilterRegistration.Dynamic registration = sce.getServletContext().addFilter("TestFilter",TestFilter.class.getName());
+ registration.setInitParameter("remote", "false");
registration.setAsyncSupported(true);
registration.addMappingForUrlPatterns(
EnumSet.of(DispatcherType.ERROR,DispatcherType.ASYNC,DispatcherType.FORWARD,DispatcherType.INCLUDE,DispatcherType.REQUEST),
true,
- new String[]{"/dump/*","/dispatch/*","*.dump"});
- */
+ new String[]{"/*"});
}
public void contextDestroyed(ServletContextEvent sce)
diff --git a/test-jetty-webapp/src/main/webapp/META-INF/MANIFEST.MF b/test-jetty-webapp/src/main/webapp/META-INF/MANIFEST.MF
index cc61b1a652..cfe644d8a6 100644
--- a/test-jetty-webapp/src/main/webapp/META-INF/MANIFEST.MF
+++ b/test-jetty-webapp/src/main/webapp/META-INF/MANIFEST.MF
@@ -4,8 +4,8 @@ Bundle-Name: TestIt
Bundle-SymbolicName: TestIt
Bundle-Version: 1.0.0.qualifier
Bundle-Activator: testit.Activator
-Import-Package: javax.servlet,
- javax.servlet.http,
+Import-Package: javax.servlet;version="2.6",
+ javax.servlet.http;version="2.6",
javax.servlet.jsp,
javax.servlet.jsp.tagext
Require-Bundle: org.eclipse.jetty.client,
diff --git a/test-jetty-webapp/src/main/webapp/WEB-INF/web.xml b/test-jetty-webapp/src/main/webapp/WEB-INF/web.xml
index f995d0162d..5a5149e53e 100644
--- a/test-jetty-webapp/src/main/webapp/WEB-INF/web.xml
+++ b/test-jetty-webapp/src/main/webapp/WEB-INF/web.xml
@@ -2,8 +2,9 @@
<web-app
xmlns="http://java.sun.com/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
- xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
- version="2.5">
+ xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"
+ metadata-complete="false"
+ version="3.0">
<display-name>Test WebApp</display-name>
@@ -17,23 +18,11 @@
<listener-class>com.acme.TestListener</listener-class>
</listener>
- <filter>
- <filter-name>TestFilter</filter-name>
- <filter-class>com.acme.TestFilter</filter-class>
- <init-param>
- <param-name>remote</param-name>
- <param-value>false</param-value>
- </init-param>
- </filter>
- <filter-mapping>
- <filter-name>TestFilter</filter-name>
- <url-pattern>/*</url-pattern>
- </filter-mapping>
-
<filter>
<filter-name>QoSFilter</filter-name>
<filter-class>org.eclipse.jetty.servlets.QoSFilter</filter-class>
+ <async-support>true</async-support>
<init-param>
<param-name>maxRequests</param-name>
<param-value>10000</param-value>
@@ -52,6 +41,7 @@
<filter>
<filter-name>MultiPart</filter-name>
<filter-class>org.eclipse.jetty.servlets.MultiPartFilter</filter-class>
+ <async-support>true</async-support>
<init-param>
<param-name>deleteFiles</param-name>
<param-value>true</param-value>
@@ -66,6 +56,7 @@
<filter>
<filter-name>GzipFilter</filter-name>
<filter-class>org.eclipse.jetty.servlets.IncludableGzipFilter</filter-class>
+ <async-support>true</async-support>
<init-param>
<param-name>bufferSize</param-name>
<param-value>8192</param-value>
@@ -114,6 +105,16 @@
<dispatcher>REQUEST</dispatcher>
</filter-mapping>
-->
+ <servlet>
+ <servlet-name>Login</servlet-name>
+ <servlet-class>com.acme.LoginServlet</servlet-class>
+ <load-on-startup>1</load-on-startup>
+ </servlet>
+
+ <servlet-mapping>
+ <servlet-name>Login</servlet-name>
+ <url-pattern>/login/*</url-pattern>
+ </servlet-mapping>
<servlet>
@@ -130,6 +131,7 @@
<servlet>
<servlet-name>Dump</servlet-name>
<servlet-class>com.acme.Dump</servlet-class>
+ <async-support>true</async-support>
<load-on-startup>1</load-on-startup>
<run-as><role-name>admin</role-name></run-as>
</servlet>
@@ -165,6 +167,7 @@
<servlet>
<servlet-name>Dispatch</servlet-name>
<servlet-class>com.acme.DispatchServlet</servlet-class>
+ <async-support>true</async-support>
<load-on-startup>1</load-on-startup>
</servlet>
@@ -187,6 +190,7 @@
<servlet>
<servlet-name>Chat</servlet-name>
<servlet-class>com.acme.ChatServlet</servlet-class>
+ <async-support>true</async-support>
<load-on-startup>1</load-on-startup>
</servlet>
@@ -234,11 +238,12 @@
<servlet>
<servlet-name>TransparentProxy</servlet-name>
<servlet-class>org.eclipse.jetty.servlets.ProxyServlet$Transparent</servlet-class>
+ <async-support>true</async-support>
<init-param>
<param-name>Prefix</param-name><param-value>/javadoc-proxy</param-value>
</init-param>
<init-param>
- <param-name>ProxyTo</param-name><param-value>http://download.eclipse.org/jetty/stable-7/apidocs</param-value>
+ <param-name>ProxyTo</param-name><param-value>http://download.eclipse.org/jetty/stable-8/apidocs</param-value>
</init-param>
<init-param>
<param-name>HostHeader</param-name><param-value>download.eclipse.org</param-value>
@@ -266,6 +271,18 @@
<location>/error404.html</location>
</error-page>
+
+
+ <security-constraint>
+ <web-resource-collection>
+ <web-resource-name>Rego2</web-resource-name>
+ <url-pattern>/rego2/*</url-pattern>
+ </web-resource-collection>
+ <auth-constraint>
+ <role-name>server-administrator</role-name>
+ </auth-constraint>
+ </security-constraint>
+
<security-constraint>
<web-resource-collection>
<web-resource-name>Auth2</web-resource-name>
diff --git a/test-jetty-webapp/src/main/webapp/auth.html b/test-jetty-webapp/src/main/webapp/auth.html
index 1b1de1157c..4b67966d26 100644
--- a/test-jetty-webapp/src/main/webapp/auth.html
+++ b/test-jetty-webapp/src/main/webapp/auth.html
@@ -18,6 +18,12 @@ This page contains several links to test the authentication constraints:
<li><a href="dump/auth/info">dump/auth/*</a> - Authenticated any user</li>
<li><a href="dump/auth/admin/info">dump/auth/admin/*</a> - Authenticated admin role (<a href="session/?Action=Invalidate">click</a> to invalidate session)</li>
<li><a href="dump/auth/ssl/info">dump/auth/ssl/*</a> - Confidential</li>
+<li><a href="rego/info">rego/info/*</a> - Authenticated admin role from programmatic security (<a href="session/?Action=Invalidate">click</a> to invalidate session)</li>
+<li><a href="rego2/info">rego2/info/*</a> - Authenticated servlet-administrator role from programmatic security (login as admin/admin, <a href="session/?Action=Invalidate">click</a> to invalidate session)</li>
+<li><a href="login?action=login">login</a> - Programmatically login as the user jetty/jetty</li>
+<li><a href="login?action=x">check login status</a> - Check the request's login status</li>
+<li><a href="login?action=logout">logout</a> - Programmatically logout the logged in user</li>
+<li><a href="login?action=wrong">incorrect login</a> - Programmatically login with incorrect credentials</li>
</ul>
<p/>
<p>
diff --git a/test-jetty-webapp/src/main/webapp/index.html b/test-jetty-webapp/src/main/webapp/index.html
index 74ef907a75..630bc1da19 100644
--- a/test-jetty-webapp/src/main/webapp/index.html
+++ b/test-jetty-webapp/src/main/webapp/index.html
@@ -11,9 +11,9 @@
</HEAD>
<BODY>
<A HREF="http://jetty.eclipse.org"><IMG SRC="jetty_banner.gif"></A>
-<h1>Welcome to Jetty 7</h1>
+<h1>Welcome to Jetty 8</h1>
<p>
-This is the Test webapp for the Jetty 7 HTTP Server and Servlet Container.
+This is the Test webapp for the Jetty 8 HTTP Server and Servlet Container.
For more information about Jetty, please visit our
<a href="http://www.eclipse.org/jetty">website</a>
or <a href="http://wiki.eclipse.org/Jetty">wiki</a> or see the bundled <a href="javadoc/">javadoc</a>.<br/>
diff --git a/tests/pom.xml b/tests/pom.xml
index b4761a4a69..cffe2358a6 100644
--- a/tests/pom.xml
+++ b/tests/pom.xml
@@ -21,7 +21,7 @@
<parent>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-project</artifactId>
- <version>7.6.8-SNAPSHOT</version>
+ <version>8.1.8-SNAPSHOT</version>
</parent>
<groupId>org.eclipse.jetty.tests</groupId>
<artifactId>tests-parent</artifactId>
diff --git a/tests/test-integration/pom.xml b/tests/test-integration/pom.xml
index 949d9b2b20..01a09ec818 100644
--- a/tests/test-integration/pom.xml
+++ b/tests/test-integration/pom.xml
@@ -20,7 +20,7 @@
<parent>
<groupId>org.eclipse.jetty.tests</groupId>
<artifactId>tests-parent</artifactId>
- <version>7.6.8-SNAPSHOT</version>
+ <version>8.1.8-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>test-integration</artifactId>
diff --git a/tests/test-loginservice/pom.xml b/tests/test-loginservice/pom.xml
index 9bf59faa9c..19b1b674c8 100644
--- a/tests/test-loginservice/pom.xml
+++ b/tests/test-loginservice/pom.xml
@@ -21,7 +21,7 @@
<parent>
<groupId>org.eclipse.jetty.tests</groupId>
<artifactId>tests-parent</artifactId>
- <version>7.6.8-SNAPSHOT</version>
+ <version>8.1.8-SNAPSHOT</version>
</parent>
<artifactId>test-loginservice</artifactId>
<name>Jetty Tests :: Login Service</name>
diff --git a/tests/test-sessions/pom.xml b/tests/test-sessions/pom.xml
index edbe06b94f..593bc6c2cd 100644
--- a/tests/test-sessions/pom.xml
+++ b/tests/test-sessions/pom.xml
@@ -21,7 +21,7 @@
<parent>
<groupId>org.eclipse.jetty.tests</groupId>
<artifactId>tests-parent</artifactId>
- <version>7.6.8-SNAPSHOT</version>
+ <version>8.1.8-SNAPSHOT</version>
</parent>
<artifactId>test-sessions-parent</artifactId>
<name>Jetty Tests :: Sessions :: Parent</name>
diff --git a/tests/test-sessions/test-hash-sessions/pom.xml b/tests/test-sessions/test-hash-sessions/pom.xml
index 28979d63e0..bfcb15b95d 100644
--- a/tests/test-sessions/test-hash-sessions/pom.xml
+++ b/tests/test-sessions/test-hash-sessions/pom.xml
@@ -21,7 +21,7 @@
<parent>
<groupId>org.eclipse.jetty.tests</groupId>
<artifactId>test-sessions-parent</artifactId>
- <version>7.6.8-SNAPSHOT</version>
+ <version>8.1.8-SNAPSHOT</version>
</parent>
<artifactId>test-hash-sessions</artifactId>
<name>Jetty Tests :: Sessions :: Hash</name>
diff --git a/tests/test-sessions/test-jdbc-sessions/pom.xml b/tests/test-sessions/test-jdbc-sessions/pom.xml
index a2fec154f5..6c28fa045b 100644
--- a/tests/test-sessions/test-jdbc-sessions/pom.xml
+++ b/tests/test-sessions/test-jdbc-sessions/pom.xml
@@ -21,7 +21,7 @@
<parent>
<groupId>org.eclipse.jetty.tests</groupId>
<artifactId>test-sessions-parent</artifactId>
- <version>7.6.8-SNAPSHOT</version>
+ <version>8.1.8-SNAPSHOT</version>
</parent>
<artifactId>test-jdbc-sessions</artifactId>
<name>Jetty Tests :: Sessions :: JDBC</name>
diff --git a/tests/test-sessions/test-mongodb-sessions/pom.xml b/tests/test-sessions/test-mongodb-sessions/pom.xml
index 4b28896243..32bb781a49 100644
--- a/tests/test-sessions/test-mongodb-sessions/pom.xml
+++ b/tests/test-sessions/test-mongodb-sessions/pom.xml
@@ -21,7 +21,7 @@
<parent>
<groupId>org.eclipse.jetty.tests</groupId>
<artifactId>test-sessions-parent</artifactId>
- <version>7.6.8-SNAPSHOT</version>
+ <version>8.1.8-SNAPSHOT</version>
</parent>
<artifactId>test-mongodb-sessions</artifactId>
<name>Jetty Tests :: Sessions :: Mongo</name>
diff --git a/tests/test-sessions/test-sessions-common/pom.xml b/tests/test-sessions/test-sessions-common/pom.xml
index 1e6a7941a5..6eab3cf4c2 100644
--- a/tests/test-sessions/test-sessions-common/pom.xml
+++ b/tests/test-sessions/test-sessions-common/pom.xml
@@ -21,7 +21,7 @@
<parent>
<groupId>org.eclipse.jetty.tests</groupId>
<artifactId>test-sessions-parent</artifactId>
- <version>7.6.8-SNAPSHOT</version>
+ <version>8.1.8-SNAPSHOT</version>
</parent>
<artifactId>test-sessions-common</artifactId>
<name>Jetty Tests :: Sessions :: Common</name>
diff --git a/tests/test-webapps/pom.xml b/tests/test-webapps/pom.xml
index 7ba2b864c0..6b28ad1c5b 100644
--- a/tests/test-webapps/pom.xml
+++ b/tests/test-webapps/pom.xml
@@ -21,7 +21,7 @@
<parent>
<groupId>org.eclipse.jetty.tests</groupId>
<artifactId>tests-parent</artifactId>
- <version>7.6.8-SNAPSHOT</version>
+ <version>8.1.8-SNAPSHOT</version>
</parent>
<artifactId>test-webapps-parent</artifactId>
<name>Jetty Tests :: WebApps :: Parent</name>
diff --git a/tests/test-webapps/test-webapp-rfc2616/pom.xml b/tests/test-webapps/test-webapp-rfc2616/pom.xml
index 3e5b85eca6..441ee23c93 100644
--- a/tests/test-webapps/test-webapp-rfc2616/pom.xml
+++ b/tests/test-webapps/test-webapp-rfc2616/pom.xml
@@ -21,7 +21,7 @@
<parent>
<groupId>org.eclipse.jetty.tests</groupId>
<artifactId>test-webapps-parent</artifactId>
- <version>7.6.8-SNAPSHOT</version>
+ <version>8.1.8-SNAPSHOT</version>
</parent>
<artifactId>test-webapp-rfc2616</artifactId>
<name>Jetty Tests :: WebApp :: RFC2616</name>

Back to the top