Skip to main content
aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--.gitignore1
-rw-r--r--VERSION.txt470
-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.xml34
-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.xml17
-rw-r--r--example-jetty-embedded/pom.xml2
-rw-r--r--example-jetty-embedded/src/main/java/org/eclipse/jetty/embedded/DumpServlet.java5
-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.java483
-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.java306
-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.java144
-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.java37
-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-client/src/main/java/org/eclipse/jetty/client/AsyncHttpConnection.java2
-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.xml127
-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/JettyBootstrapActivator.java5
-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/internal/serverfactory/DefaultJettyAtJettyHomeHelper.java2
-rw-r--r--jetty-osgi/jetty-osgi-boot/src/main/java/org/eclipse/jetty/osgi/boot/internal/webapp/LibExtClassLoaderHelper.java3
-rw-r--r--jetty-osgi/jetty-osgi-boot/src/main/java/org/eclipse/jetty/osgi/boot/internal/webapp/WebBundleTrackerCustomizer.java32
-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.xml121
-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.xml54
-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.xml9
-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.java4
-rw-r--r--jetty-osgi/test-jetty-osgi/src/test/java/org/eclipse/jetty/osgi/boot/TestJettyOSGiBootWithJsp.java9
-rw-r--r--jetty-overlay-deployer/pom.xml2
-rw-r--r--jetty-overlay-deployer/src/main/java/org/eclipse/jetty/overlays/OverlayedAppProvider.java11
-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/main/java/org/eclipse/jetty/rewrite/handler/ProxyRule.java2
-rw-r--r--jetty-rewrite/src/test/java/org/eclipse/jetty/rewrite/handler/HeaderPatternRuleTest.java8
-rw-r--r--jetty-rewrite/src/test/java/org/eclipse/jetty/rewrite/handler/ValidUrlRuleTest.java1
-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/SecurityHandler.java1
-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.java78
-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.java22
-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.java246
-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.java203
-rw-r--r--jetty-server/src/main/java/org/eclipse/jetty/server/Response.java33
-rw-r--r--jetty-server/src/main/java/org/eclipse/jetty/server/Server.java3
-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.java365
-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/HttpConnectionTest.java60
-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.java163
-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.java17
-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.java54
-rw-r--r--jetty-servlet/src/main/java/org/eclipse/jetty/servlet/ServletContextHandler.java739
-rw-r--r--jetty-servlet/src/main/java/org/eclipse/jetty/servlet/ServletHandler.java274
-rw-r--r--jetty-servlet/src/main/java/org/eclipse/jetty/servlet/ServletHolder.java211
-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/AsyncServletTest.java651
-rw-r--r--jetty-servlet/src/test/java/org/eclipse/jetty/servlet/DefaultServletTest.java8
-rw-r--r--jetty-servlet/src/test/java/org/eclipse/jetty/servlet/DispatcherTest.java37
-rw-r--r--jetty-servlet/src/test/java/org/eclipse/jetty/servlet/HolderTest.java95
-rw-r--r--jetty-servlet/src/test/java/org/eclipse/jetty/servlet/ServletHandlerTest.java425
-rw-r--r--jetty-servlets/pom.xml7
-rw-r--r--jetty-servlets/src/main/java/org/eclipse/jetty/servlets/DoSFilter.java5
-rw-r--r--jetty-servlets/src/main/java/org/eclipse/jetty/servlets/MultiPartFilter.java422
-rw-r--r--jetty-servlets/src/main/java/org/eclipse/jetty/servlets/ProxyServlet.java4
-rw-r--r--jetty-servlets/src/test/java/org/eclipse/jetty/servlets/AbstractDoSFilterTest.java14
-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/DoSFilterJMXTest.java2
-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/IncludableGzipFilterTest.java2
-rw-r--r--jetty-servlets/src/test/java/org/eclipse/jetty/servlets/MultipartFilterTest.java22
-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/TransparentProxyTest.java140
-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.java851
-rw-r--r--jetty-util/src/main/java/org/eclipse/jetty/util/ReadLineInputStream.java8
-rw-r--r--jetty-util/src/main/java/org/eclipse/jetty/util/TypeUtil.java3
-rw-r--r--jetty-util/src/main/java/org/eclipse/jetty/util/ajax/JSONPojoConvertor.java2
-rw-r--r--jetty-util/src/main/java/org/eclipse/jetty/util/resource/FileResource.java8
-rw-r--r--jetty-util/src/main/java/org/eclipse/jetty/util/resource/JarFileResource.java22
-rw-r--r--jetty-util/src/test/java/org/eclipse/jetty/util/MultiPartInputStreamTest.java858
-rw-r--r--jetty-util/src/test/java/org/eclipse/jetty/util/resource/ResourceTest.java4
-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.java101
-rw-r--r--jetty-webapp/src/main/java/org/eclipse/jetty/webapp/WebXmlConfiguration.java10
-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.xml18
-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-nested/src/main/java/org/eclipse/jetty/nested/Dump.java2
-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.xml3
-rw-r--r--test-jetty-webapp/src/main/config/contexts/test.d/override-web.xml26
-rw-r--r--test-jetty-webapp/src/main/config/contexts/test.xml13
-rw-r--r--test-jetty-webapp/src/main/java/com/acme/Dump.java16
-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.java43
-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--test-jetty-webapp/src/main/webapp/remote.html11
-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
293 files changed, 14242 insertions, 5575 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 24987024a3..932b7a30b2 100644
--- a/VERSION.txt
+++ b/VERSION.txt
@@ -1,4 +1,42 @@
-jetty-7.6.13-SNAPSHOT
+jetty-8.1.13-SNAPSHOT
+
+jetty-8.1.12.v20130726 - 26 July 2013
+ + 396706 CGI support parameters
+ + 397193 MongoSessionManager refresh updates last access time
+ + 407342 ReloadedSessionMissingClassTest uses class compiled with jdk7
+ + 408529 Etags set in 304 response
+ + 408600 set correct jetty.url in all pom files
+ + 408642 setContentType from addHeader
+ + 408662 In pax-web servlet services requests even if init() has not finished
+ running
+ + 408806 getParameter returns null on Multipart request if called before
+ request.getPart()/getParts()
+ + 408909 GzipFilter setting of headers when reset and/or not compressed
+ + 409028 Jetty HttpClient does not work with proxy CONNECT method.
+ + 409133 Empty <welcome-file> causes StackOverflowError
+ + 409436 NPE on context restart using dynamic servlet registration
+ + 409449 Ensure servlets, filters and listeners added via dynamic
+ registration, annotations or descriptors are cleaned on context restarts
+ + 409556 FileInputStream not closed in DirectNIOBuffer
+ + 410405 Avoid NPE for requestDispatcher(../)
+ + 410630 MongoSessionManager conflicting session update op
+ + 410750 NoSQLSessions: implement session context data persistence across
+ server restarts
+ + 410893 async support defaults to false for spec created servlets and filters
+ + 411135 HttpClient may send proxied https requests to the proxy instead of
+ the target server.
+ + 411216 RequestLogHandler handles async completion
+ + 411458 MultiPartFilter getParameterMap doesn't preserve multivalued
+ parameters 411459 MultiPartFilter.Wrapper getParameter should use charset
+ encoding of part
+ + 411755 MultiPartInputStreamParser fails on base64 encoded content
+ + 411909 GzipFilter flushbuffer() results in erroneous finish() call
+ + 412712 HttpClient does not send the terminal chunk after partial writes.
+ + 412750 HttpClient close expired connections fix
+ + 413371 Default JSON.Converters for List and Set.
+ + 413372 JSON Enum uses name rather than toString()
+ + 413684 Trailing slash shows JSP source
+ + 413812 Make RateTracker serializable
jetty-7.6.12.v20130726 - 26 July 2013
+ 396706 CGI support parameters
@@ -31,6 +69,70 @@ jetty-7.6.12.v20130726 - 26 July 2013
+ 413684 Trailing slash shows JSP source
+ 413812 Make RateTracker serializable
+jetty-8.1.11.v20130520 - 20 May 2013
+ + 402844 STOP.PORT & STOP.KEY behaviour has changed
+ + 403281 jetty.sh waits for started or failure before returning
+ + 403513 jetty:run goal cannot be executed twice during the maven build
+ + 403570 Asynchronous Request Logging
+ + 404010 fix cast exception in mongodb session manager
+ + 404128 Add Vary headers rather than set them
+ + 404283 org.eclipse.jetty.util.Scanner.scanFile() dies with an NPE if
+ listFiles() returns null
+ + 404325 data constraint redirection does send default port
+ + 404517 Close connection if request received after half close
+ + 404789 Support IPv6 addresses in DoSFilter white list.
+ + 404958 Fixed Resource.newSystemResource striped / handling
+ + 405281 allow filemappedbuffers to not be used
+ + 405537 NPE in rendering JSP using SPDY and wrapped ServletRequest
+ + 406437 Digest Auth supports out of order nc
+ + 406618 Jetty startup in OSGi Equinox fails when using option
+ jetty.home.bundle=org.eclipse.jetty.osgi.boot
+ + 406923 CR line termination
+ + 407136 @PreDestroy called after Servlet.destroy()
+ + 407173 java.lang.IllegalStateException: null when using JDBCSessionManager
+ + 407931 Add toggle for failing on servlet availability
+ + 407976 JDBCSessionIdManager potentially leaves server in bad state after
+ startup
+ + 408077 HashSessionManager leaves file handles open after being stopped
+ + 408446 Multipart parsing issue with boundry and charset in ContentType
+ header
+
+jetty-8.1.10.v20130312 - 12 March 2013
+ + 376273 Early EOF because of SSL Protocol Error on
+ https://api-3t.paypal.com/nvp.
+ + 381521 allow compress methods to be configured
+ + 392129 fixed handling of timeouts after startAsync
+ + 394064 ensure that JarFile instances are closed on JarFileResource.release()
+ + 398649 ServletContextListener.contextDestroyed() is not called on
+ ContextHandler unregistration
+ + 399703 made encoding error handling consistent
+ + 399799 do not hold lock while calling invalidation listeners
+ + 399967 Shutdown hook calls destroy
+ + 400040 NullPointerException in HttpGenerator.prepareBuffers
+ + 400142 ConcurrentModificationException in JDBC SessionManger
+ + 400144 When loading a session fails the JDBCSessionManger produces duplicate
+ session IDs
+ + 400312 ServletContextListener.contextInitialized() is not called when added
+ in ServletContainerInitializer.onStartup
+ + 400457 Thread context classloader hierarchy not searched when finding
+ webapp's java:comp/env
+ + 400859 limit max size of writes from cached content
+ + 401211 Remove requirement for jetty-websocket.jar in WEB-INF/lib
+ + 401317 Make Safari 5.x websocket support minVersion level error more clear
+ + 401382 Prevent parseAvailable from parsing next chunk when previous has not
+ been consumed. Handle no content-type in chunked request.
+ + 401474 Performance problem in org.eclipse.jetty.annotation.AnnotationParser
+ + 401485 zip file closed exception
+ + 401531 StringIndexOutOfBoundsException for "/*" <url-pattern> of
+ <jsp-property-group> fix for multiple mappings to *.jsp
+ + 401908 Enhance DosFilter to allow dynamic configuration of attributes.
+ + 402048 org.eclipse.jetty.server.ShutdownMonitor doesn't stop after the jetty
+ server is stopped
+ + 402485 reseed secure random
+ + 402735 jetty.sh to support status which is == check
+ + 402833 Test harness for global error page and hide exception message from
+ reason string
+
jetty-7.6.11.v20130520 - 20 May 2013
+ 402844 STOP.PORT & STOP.KEY behaviour has changed
+ 403281 jetty.sh waits for started or failure before returning
@@ -88,6 +190,57 @@ jetty-7.6.10.v20130312 - 12 March 2013
+ 402833 Test harness for global error page and hide exception message from
reason string
+jetty-8.1.9.v20130131 - 31 January 2013
+ + 362226 HttpConnection "wait" call causes thread resource exhaustion
+ + 367638 throw exception for excess form keys
+ + 381521 Only set Vary header when content could be compressed
+ + 382237 support non java JSON classes
+ + 391248 fixing localhost checking in statistics servlet
+ + 391249 fix for invalid XML node dispatchedTimeMean in statistics servlet
+ + 391345 fix missing br tag in statistics servlet
+ + 391623 Add option to --stop to wait for target jetty to stop
+ + 392417 Prevent Cookie parsing interpreting unicode chars
+ + 392492 expect headers only examined for requests>=HTTP/1.1
+ + 393075 1xx 204 and 304 ignore all headers suggesting content
+ + 393158 java.lang.IllegalStateException when sending an empty InputStream
+ + 393220 remove dead code from ServletHandler and log ServletExceptions in
+ warn instead of debug
+ + 393947 additional tests
+ + 393968 fix typo in javadoc
+ + 394294 A web-bundle started before jetty-osgi should be deployed as a webapp
+ when jetty-osgi starts
+ + 394514 Preserve URI parameters in sendRedirect
+ + 394541 remove continuation jar from distro, add as dep to test-jetty-webapp
+ + 394719 remove regex from classpath matching
+ + 394811 Make JAASLoginService log login failures to DEBUG instead of WARN.
+ Same for some other exceptions.
+ + 394829 Session can not be restored after SessionManager.setIdleSavePeriod
+ has saved the session
+ + 394839 Allow multipart mime with no boundary
+ + 394870 Make enablement of remote access to test webapp configurable in
+ override-web.xml
+ + 395215 Multipart mime with just LF and no CRLF
+ + 395380 add ValidUrlRule to jetty-rewrite
+ + 395394 allow logging from boot classloader
+ + 396253 FilterRegistration wrong order
+ + 396459 Log specific message for empty request body for multipart mime
+ requests
+ + 396500 HttpClient Exchange takes forever to complete when less content sent
+ than Content-Length
+ + 396574 add JETTY_HOME as a location for pid to be found
+ + 396886 MultiPartFilter strips bad escaping on filename="..."
+ + 397110 Accept %uXXXX encodings in URIs
+ + 397111 Tolerate empty or excessive whitespace preceeding MultiParts
+ + 397112 Requests with byte-range throws NPE if requested file has no mimetype
+ (eg no file extension)
+ + 397130 maxFormContentSize set in jetty.xml is ignored
+ + 397190 improve ValidUrlRule to iterate on codepoints
+ + 397321 Wrong condition in default start.config for annotations
+ + 397535 Support pluggable alias checking to support symbolic links
+ + 398337 UTF-16 percent encoding in UTF-16 form content
+ + 399132 check parent dir of session store against file to be removed
+ + JETTY-1533 handle URL with no path
+
jetty-7.6.9.v20130131 - 31 January 2013
+ 362226 HttpConnection "wait" call causes thread resource exhaustion
+ 367638 throw exception for excess form keys
@@ -133,6 +286,52 @@ jetty-7.6.9.v20130131 - 31 January 2013
+ 399132 check parent dir of session store against file to be removed
+ JETTY-1533 handle URL with no path
+jetty-8.1.8.v20121106 - 06 November 2012
+ + 371170 MongoSessionManager LastAccessTimeTest fails
+ + 388675 Non utf8 encoded query strings not decoded to parameter map using
+ queryEncoding
+ + 388706 Avoid unnecessary indirection through Charset.name
+ + 389390 AnnotationConfiguration is ignored if the metadata-complete attribute
+ is present in an override descriptor regardless of the value
+ + 389452 if web-fragment metadata-complete==true still scan its related jar if
+ there there is a ServletContainerInitializer, ensure webapp restarts work
+ + 389686 Fix reference to org.eclipse.jetty.util.log.stderr.LONG system
+ property in javadoc for StdErrLog
+ + 389956 Bad __context set in WebAppContext.start sequence with respect to ENC
+ setup
+ + 389965 OPTIONS should allow spaces in comma separated list
+ + 390108 Servlet 3.0 API for programmatic login doesn't appear to work
+ + 390161 Apply DeferredAuthentication fix to jaspi
+ + 390163 Implement ServletRegistration.Dynamic.setServletSecurity
+ + 390503 http-method-omission element not being processed
+ + 390560 The method AnnotationParser.getAnnotationHandlers(String) always
+ returns a empty collection.
+ + 391080 Multipart temp files can be left on disk from Request.getPart and
+ getParts
+ + 391082 No exception if multipart input stream incomplete
+ + 391188 Files written with Request.getPart().write(filename) should not be
+ auto-deleted
+ + 391483 fix bad javadoc example in shutdown handler
+ + 391622 Be lenient on RFC6265 restriction on duplicate cookie names in same
+ response
+ + 391623 Add option to --stop to wait for target jetty to stop
+ + 391877 org.eclipse.jetty.webapp.FragmentDescriptor incorrectly reporting
+ duplicate others for after ordering
+ + 392239 Allow no error-code or exception for error-pages
+ + 392525 Add option to --stop-wait to specify timeout
+ + 392641 JDBC Sessions not scavenged if expired during downtime
+ + 392812 MongoSessionIDManager never purges old sessions
+ + 393014 Mongodb purgevalid using query for purgeinvalid
+ + 393015 Mongodb purge not rescheduled
+ + 393075 Jetty WebSocket client cannot connect to Tomcat WebSocket Server
+ + 393218 add xsd=application/xml mime mapping to defaults
+ + 393363 Use Locale.ENGLISH for all toUpperCase and toLowerCase calls
+ + 393368 min websocket version
+ + 393383 delay onClose call until closeOut is done
+ + 393494 HashSessionManager can't delete unrestorable sessions on Windows
+ + JETTY-1547 Jetty does not honor web.xml
+ web-app/jsp-config/jsp-property-group/default-content-type
+
jetty-7.6.8.v20121106 - 06 November 2012
+ 371170 MongoSessionManager LastAccessTimeTest fails
+ 388675 Non utf8 encoded query strings not decoded to parameter map using
@@ -162,11 +361,11 @@ jetty-7.6.8.v20121106 - 06 November 2012
+ 393383 delay onClose call until closeOut is done
+ 393494 HashSessionManager can't delete unrestorable sessions on Windows
-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
@@ -199,7 +398,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
@@ -217,15 +416,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
@@ -234,9 +438,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
@@ -257,14 +462,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
@@ -283,13 +492,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
@@ -306,11 +521,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
@@ -324,12 +540,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
@@ -436,6 +738,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
@@ -451,6 +769,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.
@@ -466,6 +840,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
@@ -505,6 +880,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
@@ -517,6 +904,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
@@ -551,6 +944,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
@@ -733,6 +1139,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
@@ -758,9 +1184,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)
@@ -946,7 +1370,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
@@ -974,6 +1397,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
@@ -1137,6 +1569,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
@@ -1285,6 +1720,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..17ac21caa4
--- /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.13-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..774dad2409
--- /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-2013 Mort Bay Consulting Pty. Ltd.
+// ------------------------------------------------------------------------
+// All rights reserved. This program and the accompanying materials
+// are made available under the terms of the Eclipse Public License v1.0
+// and Apache License v2.0 which accompanies this distribution.
+//
+// The Eclipse Public License is available at
+// http://www.eclipse.org/legal/epl-v10.html
+//
+// The Apache License v2.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..6518cdbe1b
--- /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-2013 Mort Bay Consulting Pty. Ltd.
+// ------------------------------------------------------------------------
+// All rights reserved. This program and the accompanying materials
+// are made available under the terms of the Eclipse Public License v1.0
+// and Apache License v2.0 which accompanies this distribution.
+//
+// The Eclipse Public License is available at
+// http://www.eclipse.org/legal/epl-v10.html
+//
+// The Apache License v2.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..65c1fa9d50
--- /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-2013 Mort Bay Consulting Pty. Ltd.
+// ------------------------------------------------------------------------
+// All rights reserved. This program and the accompanying materials
+// are made available under the terms of the Eclipse Public License v1.0
+// and Apache License v2.0 which accompanies this distribution.
+//
+// The Eclipse Public License is available at
+// http://www.eclipse.org/legal/epl-v10.html
+//
+// The Apache License v2.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..dcabad72c9
--- /dev/null
+++ b/example-async-rest/async-rest-webapp/pom.xml
@@ -0,0 +1,34 @@
+<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.13-SNAPSHOT</version>
+ </parent>
+ <modelVersion>4.0.0</modelVersion>
+ <groupId>org.eclipse.jetty.example-async-rest</groupId>
+ <artifactId>example-async-rest-webapp</artifactId>
+ <name>Example Async Rest :: Webapp</name>
+ <url>http://www.eclipse.org/jetty</url>
+ <packaging>war</packaging>
+ <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..7598cf8432
--- /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-2013 Mort Bay Consulting Pty. Ltd.
+// ------------------------------------------------------------------------
+// All rights reserved. This program and the accompanying materials
+// are made available under the terms of the Eclipse Public License v1.0
+// and Apache License v2.0 which accompanies this distribution.
+//
+// The Eclipse Public License is available at
+// http://www.eclipse.org/legal/epl-v10.html
+//
+// The Apache License v2.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..3142aee9d3
--- /dev/null
+++ b/example-async-rest/pom.xml
@@ -0,0 +1,17 @@
+<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.13-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>
+ <url>http://www.eclipse.org/jetty</url>
+ <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 7e156a82b2..ef7e65dd1d 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.13-SNAPSHOT</version>
+ <version>8.1.13-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/DumpServlet.java b/example-jetty-embedded/src/main/java/org/eclipse/jetty/embedded/DumpServlet.java
index d71aa2da4c..2b8aedb460 100644
--- a/example-jetty-embedded/src/main/java/org/eclipse/jetty/embedded/DumpServlet.java
+++ b/example-jetty-embedded/src/main/java/org/eclipse/jetty/embedded/DumpServlet.java
@@ -43,6 +43,11 @@ public class DumpServlet extends HttpServlet
response.getWriter().println("servletPath=" + request.getServletPath());
response.getWriter().println("pathInfo=" + request.getPathInfo());
response.getWriter().println("session=" + request.getSession(true).getId());
+
+ String r=request.getParameter("resource");
+ if (r!=null)
+ response.getWriter().println("resource("+r+")=" + getServletContext().getResource(r));
+
response.getWriter().println("</pre>");
}
} \ No newline at end of file
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 a6839cff21..7f3a6309d9 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
@@ -149,7 +149,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 de0b08cc23..bc3bfc9cbc 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 d20cb644bf..5277cba9c2 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 f63dd2a71b..c07259a010 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.13-SNAPSHOT</version>
+ <version>8.1.13-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>jetty-all-server</artifactId>
@@ -79,10 +78,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 c0a545cfb2..53a2e4797e 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.13-SNAPSHOT</version>
+ <version>8.1.13-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 6e95740590..4a7c3bd550 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.13-SNAPSHOT</version>
+ <version>8.1.13-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 3ce38704cd..b15829d7b3 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.13-SNAPSHOT</version>
+ <version>8.1.13-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 82833aa767..b9259a929f 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.13-SNAPSHOT</version>
+ <version>8.1.13-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 0148a6938a..2f187cc870 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.13-SNAPSHOT</version>
+ <version>8.1.13-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 76977699b6..a87d20ba51 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.13-SNAPSHOT</version>
+ <version>8.1.13-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 775eaa885e..fac0a68064 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.13-SNAPSHOT</version>
+ <version>8.1.13-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 0e641a817b..c095bd5b5b 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.13-SNAPSHOT</version>
+ <version>8.1.13-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 7873f992a4..d2844f0f03 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.13-SNAPSHOT</version>
+ <version>8.1.13-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>jetty-ajp</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-annotations/pom.xml b/jetty-annotations/pom.xml
index a1cc8161ff..f97ca2e059 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.13-SNAPSHOT</version>
+ <version>8.1.13-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>jetty-annotations</artifactId>
@@ -15,6 +15,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>
@@ -26,7 +43,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 81d8f417f8..b3238f9c35 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 cd2b0d2462..2d46715c4a 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,26 @@
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 javax.servlet.ServletContainerInitializer;
+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.AbstractConfiguration;
+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 +46,478 @@ 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";
+ public static final String CONTAINER_INITIALIZER_LISTENER = "org.eclipse.jetty.containerInitializerListener";
+
+
+ protected List<DiscoverableAnnotationHandler> _discoverableAnnotationHandlers = new ArrayList<DiscoverableAnnotationHandler>();
+ protected ClassInheritanceHandler _classInheritanceHandler;
+ protected List<ContainerInitializerAnnotationHandler> _containerInitializerAnnotationHandlers = new ArrayList<ContainerInitializerAnnotationHandler>();
+
+
+ @Override
+ public void preConfigure(final WebAppContext context) throws Exception
+ {
+ }
+
+ @Override
+ public void deconfigure(WebAppContext context) throws Exception
+ {
+ context.removeAttribute(CLASS_INHERITANCE_MAP);
+ context.removeAttribute(CONTAINER_INITIALIZERS);
+ ServletContainerInitializerListener listener = (ServletContainerInitializerListener)context.getAttribute(CONTAINER_INITIALIZER_LISTENER);
+ if (listener != null)
+ {
+ context.removeBean(listener);
+ context.removeAttribute(CONTAINER_INITIALIZER_LISTENER);
+ }
+ }
+
+ /**
+ * @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 bean which will call the servletcontainerinitializers when appropriate
+ ServletContainerInitializerListener listener = (ServletContainerInitializerListener)context.getAttribute(CONTAINER_INITIALIZER_LISTENER);
+ if (listener != null)
+ throw new IllegalStateException("ServletContainerInitializerListener already exists");
+ listener = new ServletContainerInitializerListener();
+ listener.setWebAppContext(context);
+ context.setAttribute(CONTAINER_INITIALIZER_LISTENER, listener);
+ context.addBean(listener, true);
+ }
+
+
+
+ /**
+ * 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 4c3a72174a..236eb9998d 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 8ae4267034..9f5808620c 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
@@ -25,12 +25,9 @@ import java.net.URL;
import java.net.URLClassLoader;
import java.util.ArrayList;
import java.util.Arrays;
-import java.util.Collections;
-import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Locale;
-import java.util.Map;
import java.util.Set;
import java.util.jar.JarEntry;
@@ -56,10 +53,7 @@ public class AnnotationParser
private static final Logger LOG = Log.getLogger(AnnotationParser.class);
protected Set<String> _parsedClassNames = new HashSet<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<Handler> _handlers = new ArrayList<Handler>();
public static String normalize (String name)
{
@@ -170,37 +164,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;
@@ -309,10 +388,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);
+ }
}
}
@@ -325,12 +407,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);
}
}
}
@@ -356,12 +439,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);
}
}
}
@@ -388,12 +472,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);
}
}
}
@@ -409,46 +494,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
{
@@ -470,6 +639,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
{
@@ -496,6 +675,15 @@ public class AnnotationParser
}
}
+
+
+ /**
+ * Parse the given classes
+ *
+ * @param classNames
+ * @param resolver
+ * @throws Exception
+ */
public void parse (String[] classNames, ClassNameResolver resolver)
throws Exception
{
@@ -505,6 +693,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
{
@@ -523,6 +719,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
{
@@ -563,8 +767,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
@@ -617,7 +822,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
@@ -663,10 +869,8 @@ public class AnnotationParser
scanner.scan(null, uris, true);
}
-
/**
- * Parse a single jar file for classes.
- *
+ * Parse a particular resource
* @param uri
* @param resolver
* @throws Exception
@@ -680,14 +884,15 @@ public class AnnotationParser
parse(uris, resolver);
}
-
+
+
/**
- * Scan a class for annotations.
+ * Use ASM on a class
*
* @param is
* @throws IOException
*/
- private void scanClass (InputStream is)
+ protected void scanClass (InputStream is)
throws IOException
{
ClassReader reader = new ClassReader(is);
@@ -756,3 +961,4 @@ public class AnnotationParser
return true;
}
}
+
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 02d7c5e340..ca6c61be12 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..93da281ddd
--- /dev/null
+++ b/jetty-annotations/src/main/java/org/eclipse/jetty/annotations/ContainerInitializerAnnotationHandler.java
@@ -0,0 +1,83 @@
+//
+// ========================================================================
+// Copyright (c) 1995-2013 Mort Bay Consulting Pty. Ltd.
+// ------------------------------------------------------------------------
+// All rights reserved. This program and the accompanying materials
+// are made available under the terms of the Eclipse Public License v1.0
+// and Apache License v2.0 which accompanies this distribution.
+//
+// The Eclipse Public License is available at
+// http://www.eclipse.org/legal/epl-v10.html
+//
+// The Apache License v2.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..a40d2653dc
--- /dev/null
+++ b/jetty-annotations/src/main/java/org/eclipse/jetty/annotations/MultiPartConfigAnnotationHandler.java
@@ -0,0 +1,95 @@
+//
+// ========================================================================
+// Copyright (c) 1995-2013 Mort Bay Consulting Pty. Ltd.
+// ------------------------------------------------------------------------
+// All rights reserved. This program and the accompanying materials
+// are made available under the terms of the Eclipse Public License v1.0
+// and Apache License v2.0 which accompanies this distribution.
+//
+// The Eclipse Public License is available at
+// http://www.eclipse.org/legal/epl-v10.html
+//
+// The Apache License v2.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 7961b1eefa..7af4041f0e 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..317d8f76bd
--- /dev/null
+++ b/jetty-annotations/src/main/java/org/eclipse/jetty/annotations/ServletContainerInitializerListener.java
@@ -0,0 +1,144 @@
+//
+// ========================================================================
+// Copyright (c) 1995-2013 Mort Bay Consulting Pty. Ltd.
+// ------------------------------------------------------------------------
+// All rights reserved. This program and the accompanying materials
+// are made available under the terms of the Eclipse Public License v1.0
+// and Apache License v2.0 which accompanies this distribution.
+//
+// The Eclipse Public License is available at
+// http://www.eclipse.org/legal/epl-v10.html
+//
+// The Apache License v2.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 org.eclipse.jetty.annotations.AnnotationConfiguration;
+import org.eclipse.jetty.plus.annotation.ContainerInitializer;
+import org.eclipse.jetty.util.MultiMap;
+import org.eclipse.jetty.util.component.AbstractLifeCycle;
+import org.eclipse.jetty.util.log.Log;
+import org.eclipse.jetty.util.log.Logger;
+import org.eclipse.jetty.webapp.WebAppContext;
+
+/**
+ * ServletContainerInitializerListener
+ *
+ *
+ */
+public class ServletContainerInitializerListener extends AbstractLifeCycle
+{
+ private static final Logger LOG = Log.getLogger(ServletContainerInitializerListener.class);
+ protected WebAppContext _context = null;
+
+
+ public void setWebAppContext (WebAppContext context)
+ {
+ _context = context;
+ }
+
+
+ /**
+ * Call the doStart method of the ServletContainerInitializers
+ * @see org.eclipse.jetty.util.component.AbstractLifeCycle#doStart()
+ */
+ public void doStart()
+ {
+ 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);
+ }
+ }
+
+
+
+ /**
+ * Nothing to do for ServletContainerInitializers on stop
+ * @see org.eclipse.jetty.util.component.AbstractLifeCycle#doStop()
+ */
+ public void doStop()
+ {
+
+ }
+
+}
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..06a437a076
--- /dev/null
+++ b/jetty-annotations/src/main/java/org/eclipse/jetty/annotations/ServletSecurityAnnotationHandler.java
@@ -0,0 +1,196 @@
+//
+// ========================================================================
+// Copyright (c) 1995-2013 Mort Bay Consulting Pty. Ltd.
+// ------------------------------------------------------------------------
+// All rights reserved. This program and the accompanying materials
+// are made available under the terms of the Eclipse Public License v1.0
+// and Apache License v2.0 which accompanies this distribution.
+//
+// The Eclipse Public License is available at
+// http://www.eclipse.org/legal/epl-v10.html
+//
+// The Apache License v2.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 d812c1b005..37a22a3081 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..3a67e26240
--- /dev/null
+++ b/jetty-annotations/src/main/java/org/eclipse/jetty/annotations/WebFilterAnnotation.java
@@ -0,0 +1,223 @@
+//
+// ========================================================================
+// Copyright (c) 1995-2013 Mort Bay Consulting Pty. Ltd.
+// ------------------------------------------------------------------------
+// All rights reserved. This program and the accompanying materials
+// are made available under the terms of the Eclipse Public License v1.0
+// and Apache License v2.0 which accompanies this distribution.
+//
+// The Eclipse Public License is available at
+// http://www.eclipse.org/legal/epl-v10.html
+//
+// The Apache License v2.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..dc6f5c154b
--- /dev/null
+++ b/jetty-annotations/src/main/java/org/eclipse/jetty/annotations/WebFilterAnnotationHandler.java
@@ -0,0 +1,74 @@
+//
+// ========================================================================
+// Copyright (c) 1995-2013 Mort Bay Consulting Pty. Ltd.
+// ------------------------------------------------------------------------
+// All rights reserved. This program and the accompanying materials
+// are made available under the terms of the Eclipse Public License v1.0
+// and Apache License v2.0 which accompanies this distribution.
+//
+// The Eclipse Public License is available at
+// http://www.eclipse.org/legal/epl-v10.html
+//
+// The Apache License v2.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..94e77ba468
--- /dev/null
+++ b/jetty-annotations/src/main/java/org/eclipse/jetty/annotations/WebListenerAnnotation.java
@@ -0,0 +1,96 @@
+//
+// ========================================================================
+// Copyright (c) 1995-2013 Mort Bay Consulting Pty. Ltd.
+// ------------------------------------------------------------------------
+// All rights reserved. This program and the accompanying materials
+// are made available under the terms of the Eclipse Public License v1.0
+// and Apache License v2.0 which accompanies this distribution.
+//
+// The Eclipse Public License is available at
+// http://www.eclipse.org/legal/epl-v10.html
+//
+// The Apache License v2.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..ab1670230a
--- /dev/null
+++ b/jetty-annotations/src/main/java/org/eclipse/jetty/annotations/WebListenerAnnotationHandler.java
@@ -0,0 +1,71 @@
+//
+// ========================================================================
+// Copyright (c) 1995-2013 Mort Bay Consulting Pty. Ltd.
+// ------------------------------------------------------------------------
+// All rights reserved. This program and the accompanying materials
+// are made available under the terms of the Eclipse Public License v1.0
+// and Apache License v2.0 which accompanies this distribution.
+//
+// The Eclipse Public License is available at
+// http://www.eclipse.org/legal/epl-v10.html
+//
+// The Apache License v2.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..f9b359bca0
--- /dev/null
+++ b/jetty-annotations/src/main/java/org/eclipse/jetty/annotations/WebServletAnnotation.java
@@ -0,0 +1,227 @@
+//
+// ========================================================================
+// Copyright (c) 1995-2013 Mort Bay Consulting Pty. Ltd.
+// ------------------------------------------------------------------------
+// All rights reserved. This program and the accompanying materials
+// are made available under the terms of the Eclipse Public License v1.0
+// and Apache License v2.0 which accompanies this distribution.
+//
+// The Eclipse Public License is available at
+// http://www.eclipse.org/legal/epl-v10.html
+//
+// The Apache License v2.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..aeed89e70e
--- /dev/null
+++ b/jetty-annotations/src/main/java/org/eclipse/jetty/annotations/WebServletAnnotationHandler.java
@@ -0,0 +1,85 @@
+//
+// ========================================================================
+// Copyright (c) 1995-2013 Mort Bay Consulting Pty. Ltd.
+// ------------------------------------------------------------------------
+// All rights reserved. This program and the accompanying materials
+// are made available under the terms of the Eclipse Public License v1.0
+// and Apache License v2.0 which accompanies this distribution.
+//
+// The Eclipse Public License is available at
+// http://www.eclipse.org/legal/epl-v10.html
+//
+// The Apache License v2.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 d11c863288..1915673d47 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 fbab9f2a65..0524dc349d 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 df50282f89..78aa093d6c 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..afe91d7a4d
--- /dev/null
+++ b/jetty-annotations/src/test/java/org/eclipse/jetty/annotations/TestAnnotationConfiguration.java
@@ -0,0 +1,58 @@
+//
+// ========================================================================
+// Copyright (c) 1995-2013 Mort Bay Consulting Pty. Ltd.
+// ------------------------------------------------------------------------
+// All rights reserved. This program and the accompanying materials
+// are made available under the terms of the Eclipse Public License v1.0
+// and Apache License v2.0 which accompanies this distribution.
+//
+// The Eclipse Public License is available at
+// http://www.eclipse.org/legal/epl-v10.html
+//
+// The Apache License v2.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 bb178275b6..02e6ab527e 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 7822095565..22cc1ecaea 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
@@ -53,10 +53,13 @@ public class TestAnnotationParser
public static class TrackingAnnotationHandler implements DiscoverableAnnotationHandler
{
+
+ private final String annotationName;
public final Set<String> foundClasses;
- public TrackingAnnotationHandler()
+ public TrackingAnnotationHandler(String annotationName)
{
+ this.annotationName = annotationName;
this.foundClasses = new HashSet<String>();
}
@@ -80,6 +83,13 @@ public class TestAnnotationParser
{
/* ignore */
}
+
+
+ @Override
+ public String getAnnotationName()
+ {
+ return this.annotationName;
+ }
}
@@ -95,6 +105,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)
{
@@ -120,9 +133,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 ()
@@ -169,9 +188,17 @@ public class TestAnnotationParser
assertTrue("org.eclipse.jetty.annotations.ClassB".equals(className));
assertTrue("a".equals(methodName));
}
+
+ @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);
}
@@ -200,11 +227,11 @@ public class TestAnnotationParser
copyClass(ClassA.class,basedir);
// Setup Tracker
- TrackingAnnotationHandler tracker = new TrackingAnnotationHandler();
+ TrackingAnnotationHandler tracker = new TrackingAnnotationHandler(Sample.class.getName());
// Setup annotation scanning
AnnotationParser parser = new AnnotationParser();
- parser.registerAnnotationHandler(Sample.class.getName(), tracker);
+ parser.registerHandler(tracker);
// Parse
parser.parse(Resource.newResource(basedir),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..ec1265efaf
--- /dev/null
+++ b/jetty-annotations/src/test/java/org/eclipse/jetty/annotations/TestSecurityAnnotationConversions.java
@@ -0,0 +1,334 @@
+//
+// ========================================================================
+// Copyright (c) 1995-2013 Mort Bay Consulting Pty. Ltd.
+// ------------------------------------------------------------------------
+// All rights reserved. This program and the accompanying materials
+// are made available under the terms of the Eclipse Public License v1.0
+// and Apache License v2.0 which accompanies this distribution.
+//
+// The Eclipse Public License is available at
+// http://www.eclipse.org/legal/epl-v10.html
+//
+// The Apache License v2.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 a74cffdd15..9790316b2f 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 4abb480d42..1ec48a11e9 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.13-SNAPSHOT</version>
+ <version>8.1.13-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
diff --git a/jetty-client/src/main/java/org/eclipse/jetty/client/AsyncHttpConnection.java b/jetty-client/src/main/java/org/eclipse/jetty/client/AsyncHttpConnection.java
index 84cf8db20c..ba268efa50 100644
--- a/jetty-client/src/main/java/org/eclipse/jetty/client/AsyncHttpConnection.java
+++ b/jetty-client/src/main/java/org/eclipse/jetty/client/AsyncHttpConnection.java
@@ -106,6 +106,8 @@ public class AsyncHttpConnection extends AbstractHttpConnection implements Async
LOG.debug("complete {}",exchange);
progress=true;
_generator.complete();
+ if (exchange.getStatus() < HttpExchange.STATUS_WAITING_FOR_RESPONSE)
+ exchange.setStatus(HttpExchange.STATUS_WAITING_FOR_RESPONSE);
}
else if (_generator.isEmpty())
{
diff --git a/jetty-continuation/pom.xml b/jetty-continuation/pom.xml
index ed07b4390d..84b7c04e2d 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.13-SNAPSHOT</version>
+ <version>8.1.13-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>jetty-continuation</artifactId>
@@ -25,7 +25,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 0a1a94e558..3e1d680f94 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 dcfe12b29f..41673cc192 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 7d654464ec..5a4bec4193 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 4643e876e9..fd568d03df 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.13-SNAPSHOT</version>
+ <version>8.1.13-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>jetty-deploy</artifactId>
@@ -25,7 +25,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 452c83c898..fbc14c168b 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.13-SNAPSHOT</version>
+ <version>8.1.13-SNAPSHOT</version>
</parent>
<artifactId>jetty-distribution</artifactId>
<name>Jetty :: Distribution Assemblies</name>
@@ -145,7 +145,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 c9e23233d7..baafc4d24e 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
# ========================
@@ -161,7 +161,7 @@ then
ETC=$HOME/etc
fi
-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
@@ -217,13 +217,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 27fd3acd2c..29cb38bc78 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.13-SNAPSHOT</version>
+ <version>8.1.13-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 6f768dd8d7..55daa1fefb 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.13-SNAPSHOT</version>
+ <version>8.1.13-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>jetty-http</artifactId>
@@ -42,7 +42,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 e815759bcc..10a648eb48 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 be35858ef3..1cdea65178 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 593851ab4a..d53f66df40 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 398486eced..20dd0c804d 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 69f9df9ddc..51bb08d6a8 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.13-SNAPSHOT</version>
+ <version>8.1.13-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 a656d16a53..397e5aa043 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 6d1c75d4e1..6b62435851 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 d11a315f4e..3eabb24a0f 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 403621f4e6..5dcc254946 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 e2a55b8e48..e32cb73e92 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.13-SNAPSHOT</version>
+ <version>8.1.13-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>jetty-jaspi</artifactId>
@@ -23,6 +23,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 2940809a8e..fbdc379fe3 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 cc7dffc7b3..54c6bff334 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 468a7acba2..5f13b56e22 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 196c6d99cf..d3e763c9e8 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.13-SNAPSHOT</version>
+ <version>8.1.13-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 c405196977..50d110f2b9 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.13-SNAPSHOT</version>
+ <version>8.1.13-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 aefc79f9f4..ae32da01c9 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.13-SNAPSHOT</version>
+ <version>8.1.13-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>jetty-jsp</artifactId>
@@ -17,13 +17,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>
@@ -41,13 +41,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 175a210db8..50cde76acd 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.13-SNAPSHOT</version>
+ <version>8.1.13-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 7a239c59ae..14986900bb 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.13-SNAPSHOT</version>
+ <version>8.1.13-SNAPSHOT</version>
</parent>
<artifactId>jetty-nested</artifactId>
<name>Jetty :: Nested</name>
@@ -27,7 +27,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 c20797a0a5..3738487fb2 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 4b1ab5342a..89ee08d647 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.13-SNAPSHOT</version>
+ <version>8.1.13-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>jetty-nosql</artifactId>
@@ -29,7 +29,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 d1d713c051..09b9f49d2e 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.13-SNAPSHOT</version>
+ <version>8.1.13-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>
<modelVersion>4.0.0</modelVersion>
@@ -94,28 +94,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,
@@ -139,13 +138,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 db2de4a6d1..0000000000
--- a/jetty-osgi/jetty-osgi-boot-logback/pom.xml
+++ /dev/null
@@ -1,127 +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.13-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>
- <url>http://www.eclipse.org/jetty</url>
- <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 2e0d0f9cbe..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-2013 Mort Bay Consulting Pty. Ltd.
-// ------------------------------------------------------------------------
-// All rights reserved. This program and the accompanying materials
-// are made available under the terms of the Eclipse Public License v1.0
-// and Apache License v2.0 which accompanies this distribution.
-//
-// The Eclipse Public License is available at
-// http://www.eclipse.org/legal/epl-v10.html
-//
-// The Apache License v2.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 7053565b94..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-2013 Mort Bay Consulting Pty. Ltd.
-// ------------------------------------------------------------------------
-// All rights reserved. This program and the accompanying materials
-// are made available under the terms of the Eclipse Public License v1.0
-// and Apache License v2.0 which accompanies this distribution.
-//
-// The Eclipse Public License is available at
-// http://www.eclipse.org/legal/epl-v10.html
-//
-// The Apache License v2.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 eb51a64ef4..366c427a0d 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.13-SNAPSHOT</version>
+ <version>8.1.13-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>
<modelVersion>4.0.0</modelVersion>
@@ -80,6 +80,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 898157b349..d717bc4ef4 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.13-SNAPSHOT</version>
+ <version>8.1.13-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>
<modelVersion>4.0.0</modelVersion>
@@ -14,6 +14,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>
@@ -115,10 +119,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,
@@ -130,12 +136,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..b4ae909819
--- /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-2013 Mort Bay Consulting Pty. Ltd.
+// ------------------------------------------------------------------------
+// All rights reserved. This program and the accompanying materials
+// are made available under the terms of the Eclipse Public License v1.0
+// and Apache License v2.0 which accompanies this distribution.
+//
+// The Eclipse Public License is available at
+// http://www.eclipse.org/legal/epl-v10.html
+//
+// The Apache License v2.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..096cb8a821
--- /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-2013 Mort Bay Consulting Pty. Ltd.
+// ------------------------------------------------------------------------
+// All rights reserved. This program and the accompanying materials
+// are made available under the terms of the Eclipse Public License v1.0
+// and Apache License v2.0 which accompanies this distribution.
+//
+// The Eclipse Public License is available at
+// http://www.eclipse.org/legal/epl-v10.html
+//
+// The Apache License v2.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/JettyBootstrapActivator.java b/jetty-osgi/jetty-osgi-boot/src/main/java/org/eclipse/jetty/osgi/boot/JettyBootstrapActivator.java
index c53d3b4f43..2ed6e7bf5e 100644
--- a/jetty-osgi/jetty-osgi-boot/src/main/java/org/eclipse/jetty/osgi/boot/JettyBootstrapActivator.java
+++ b/jetty-osgi/jetty-osgi-boot/src/main/java/org/eclipse/jetty/osgi/boot/JettyBootstrapActivator.java
@@ -105,8 +105,9 @@ public class JettyBootstrapActivator implements BundleActivator
DefaultJettyAtJettyHomeHelper.startJettyAtJettyHome(context);
// track Bundles and deploy those that represent webapps to one of the known Servers
- _webBundleTracker = new BundleTracker(context, Bundle.ACTIVE | Bundle.STOPPING, new WebBundleTrackerCustomizer());
- _webBundleTracker.open();
+ WebBundleTrackerCustomizer customizer = new WebBundleTrackerCustomizer();
+ _webBundleTracker = new BundleTracker(context, Bundle.ACTIVE | Bundle.STOPPING, customizer);
+ customizer.setAndOpenWebBundleTracker(_webBundleTracker);
}
/**
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 b643c5d289..4b48aef2a3 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/internal/serverfactory/DefaultJettyAtJettyHomeHelper.java b/jetty-osgi/jetty-osgi-boot/src/main/java/org/eclipse/jetty/osgi/boot/internal/serverfactory/DefaultJettyAtJettyHomeHelper.java
index ce8a51455f..6f8f4f835b 100644
--- a/jetty-osgi/jetty-osgi-boot/src/main/java/org/eclipse/jetty/osgi/boot/internal/serverfactory/DefaultJettyAtJettyHomeHelper.java
+++ b/jetty-osgi/jetty-osgi-boot/src/main/java/org/eclipse/jetty/osgi/boot/internal/serverfactory/DefaultJettyAtJettyHomeHelper.java
@@ -232,7 +232,7 @@ public class DefaultJettyAtJettyHomeHelper
// can define their own configuration.
if ((enUrls == null || !enUrls.hasMoreElements()))
{
- String tmp = DEFAULT_JETTYHOME+etcFile;
+ String tmp = DEFAULT_JETTYHOME+(DEFAULT_JETTYHOME.endsWith("/")?"":"/")+etcFile;
enUrls = BundleFileLocatorHelperFactory.getFactory().getHelper().findEntries(configurationBundle, tmp);
LOG.info("Configuring jetty from bundle: "
+ configurationBundle.getSymbolicName()
diff --git a/jetty-osgi/jetty-osgi-boot/src/main/java/org/eclipse/jetty/osgi/boot/internal/webapp/LibExtClassLoaderHelper.java b/jetty-osgi/jetty-osgi-boot/src/main/java/org/eclipse/jetty/osgi/boot/internal/webapp/LibExtClassLoaderHelper.java
index 9d07adf1c2..c66fa26b12 100644
--- a/jetty-osgi/jetty-osgi-boot/src/main/java/org/eclipse/jetty/osgi/boot/internal/webapp/LibExtClassLoaderHelper.java
+++ b/jetty-osgi/jetty-osgi-boot/src/main/java/org/eclipse/jetty/osgi/boot/internal/webapp/LibExtClassLoaderHelper.java
@@ -26,6 +26,7 @@ import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
+import java.util.Locale;
import java.util.Map;
import java.util.Set;
@@ -109,7 +110,7 @@ public class LibExtClassLoaderHelper
for (File f : jettyResources.listFiles())
{
jettyResFiles.put(f.getName(), f);
- if (f.getName().toLowerCase().startsWith("readme"))
+ if (f.getName().toLowerCase(Locale.ENGLISH).startsWith("readme"))
{
continue;
}
diff --git a/jetty-osgi/jetty-osgi-boot/src/main/java/org/eclipse/jetty/osgi/boot/internal/webapp/WebBundleTrackerCustomizer.java b/jetty-osgi/jetty-osgi-boot/src/main/java/org/eclipse/jetty/osgi/boot/internal/webapp/WebBundleTrackerCustomizer.java
index b971bcbcea..b8adc65705 100644
--- a/jetty-osgi/jetty-osgi-boot/src/main/java/org/eclipse/jetty/osgi/boot/internal/webapp/WebBundleTrackerCustomizer.java
+++ b/jetty-osgi/jetty-osgi-boot/src/main/java/org/eclipse/jetty/osgi/boot/internal/webapp/WebBundleTrackerCustomizer.java
@@ -30,6 +30,7 @@ import org.eclipse.jetty.util.log.Logger;
import org.osgi.framework.Bundle;
import org.osgi.framework.BundleEvent;
import org.osgi.framework.FrameworkUtil;
+import org.osgi.framework.ServiceReference;
import org.osgi.util.tracker.BundleTracker;
import org.osgi.util.tracker.BundleTrackerCustomizer;
import org.osgi.util.tracker.ServiceTracker;
@@ -56,7 +57,7 @@ public class WebBundleTrackerCustomizer implements BundleTrackerCustomizer
"("+OSGiServerConstants.MANAGED_JETTY_SERVER_NAME+"="+OSGiServerConstants.MANAGED_JETTY_SERVER_DEFAULT_NAME+"))";
private ServiceTracker _serviceTracker;
-
+ private BundleTracker _bundleTracker;
/* ------------------------------------------------------------ */
/**
@@ -68,8 +69,16 @@ public class WebBundleTrackerCustomizer implements BundleTrackerCustomizer
Bundle myBundle = FrameworkUtil.getBundle(this.getClass());
//track all instances of deployers of webapps/contexts as bundles
- _serviceTracker = new ServiceTracker(myBundle.getBundleContext(), FrameworkUtil.createFilter(FILTER),null);
+ _serviceTracker = new ServiceTracker(myBundle.getBundleContext(), FrameworkUtil.createFilter(FILTER),null) {
+ public Object addingService(ServiceReference reference) {
+ Object object = super.addingService(reference);
+ LOG.debug("Deployer registered {}", reference);
+ openBundleTracker();
+ return object;
+ }
+ };
_serviceTracker.open();
+
}
@@ -98,7 +107,7 @@ public class WebBundleTrackerCustomizer implements BundleTrackerCustomizer
{
if (bundle.getState() == Bundle.ACTIVE)
{
- register(bundle);
+ register(bundle);
}
else if (bundle.getState() == Bundle.STOPPING)
{
@@ -221,4 +230,21 @@ public class WebBundleTrackerCustomizer implements BundleTrackerCustomizer
}
}
}
+
+ public void setAndOpenWebBundleTracker(BundleTracker bundleTracker) {
+ if(_bundleTracker == null) {
+ _bundleTracker = bundleTracker;
+ LOG.debug("Bundle tracker is set");
+ openBundleTracker();
+ }
+ }
+
+ private void openBundleTracker() {
+ if(_bundleTracker != null && _serviceTracker.getServices() != null &&
+ _serviceTracker.getServices().length > 0) {
+ _bundleTracker.open();
+ LOG.debug("Bundle tracker has been opened");
+ }
+ }
+
}
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 444159ad1d..384b392c9a 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 e33590d9e2..0000000000
--- a/jetty-osgi/jetty-osgi-equinoxtools/pom.xml
+++ /dev/null
@@ -1,121 +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.13-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>
- <url>http://www.eclipse.org/jetty</url>
- <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 7604c260b5..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-2013 Mort Bay Consulting Pty. Ltd.
-// ------------------------------------------------------------------------
-// All rights reserved. This program and the accompanying materials
-// are made available under the terms of the Eclipse Public License v1.0
-// and Apache License v2.0 which accompanies this distribution.
-//
-// The Eclipse Public License is available at
-// http://www.eclipse.org/legal/epl-v10.html
-//
-// The Apache License v2.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 9ed05ab0b0..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-2013 Mort Bay Consulting Pty. Ltd.
-// ------------------------------------------------------------------------
-// All rights reserved. This program and the accompanying materials
-// are made available under the terms of the Eclipse Public License v1.0
-// and Apache License v2.0 which accompanies this distribution.
-//
-// The Eclipse Public License is available at
-// http://www.eclipse.org/legal/epl-v10.html
-//
-// The Apache License v2.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 82a358a9ec..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-2013 Mort Bay Consulting Pty. Ltd.
-// ------------------------------------------------------------------------
-// All rights reserved. This program and the accompanying materials
-// are made available under the terms of the Eclipse Public License v1.0
-// and Apache License v2.0 which accompanies this distribution.
-//
-// The Eclipse Public License is available at
-// http://www.eclipse.org/legal/epl-v10.html
-//
-// The Apache License v2.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 0baa3e3f6e..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-2013 Mort Bay Consulting Pty. Ltd.
-// ------------------------------------------------------------------------
-// All rights reserved. This program and the accompanying materials
-// are made available under the terms of the Eclipse Public License v1.0
-// and Apache License v2.0 which accompanies this distribution.
-//
-// The Eclipse Public License is available at
-// http://www.eclipse.org/legal/epl-v10.html
-//
-// The Apache License v2.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 385bc8f913..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-2013 Mort Bay Consulting Pty. Ltd.
-// ------------------------------------------------------------------------
-// All rights reserved. This program and the accompanying materials
-// are made available under the terms of the Eclipse Public License v1.0
-// and Apache License v2.0 which accompanies this distribution.
-//
-// The Eclipse Public License is available at
-// http://www.eclipse.org/legal/epl-v10.html
-//
-// The Apache License v2.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 55dc179fa3..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-2013 Mort Bay Consulting Pty. Ltd.
-// ------------------------------------------------------------------------
-// All rights reserved. This program and the accompanying materials
-// are made available under the terms of the Eclipse Public License v1.0
-// and Apache License v2.0 which accompanies this distribution.
-//
-// The Eclipse Public License is available at
-// http://www.eclipse.org/legal/epl-v10.html
-//
-// The Apache License v2.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 7bc6bf27ef..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-2013 Mort Bay Consulting Pty. Ltd.
-// ------------------------------------------------------------------------
-// All rights reserved. This program and the accompanying materials
-// are made available under the terms of the Eclipse Public License v1.0
-// and Apache License v2.0 which accompanies this distribution.
-//
-// The Eclipse Public License is available at
-// http://www.eclipse.org/legal/epl-v10.html
-//
-// The Apache License v2.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 b0e44acfa6..78d1887838 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.13-SNAPSHOT</version>
+ <version>8.1.13-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>
<modelVersion>4.0.0</modelVersion>
@@ -97,8 +97,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>
@@ -115,6 +115,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 4da36c2e85..0000000000
--- a/jetty-osgi/jetty-osgi-servletbridge/pom.xml
+++ /dev/null
@@ -1,54 +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>
- <url>http://www.eclipse.org/jetty</url>
- <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 3809364ff8..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-2013 Mort Bay Consulting Pty. Ltd.
-// ------------------------------------------------------------------------
-// All rights reserved. This program and the accompanying materials
-// are made available under the terms of the Eclipse Public License v1.0
-// and Apache License v2.0 which accompanies this distribution.
-//
-// The Eclipse Public License is available at
-// http://www.eclipse.org/legal/epl-v10.html
-//
-// The Apache License v2.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 6b0b224b28..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-2013 Mort Bay Consulting Pty. Ltd.
-// ------------------------------------------------------------------------
-// All rights reserved. This program and the accompanying materials
-// are made available under the terms of the Eclipse Public License v1.0
-// and Apache License v2.0 which accompanies this distribution.
-//
-// The Eclipse Public License is available at
-// http://www.eclipse.org/legal/epl-v10.html
-//
-// The Apache License v2.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 775be9f801..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-2013 Mort Bay Consulting Pty. Ltd.
-// ------------------------------------------------------------------------
-// All rights reserved. This program and the accompanying materials
-// are made available under the terms of the Eclipse Public License v1.0
-// and Apache License v2.0 which accompanies this distribution.
-//
-// The Eclipse Public License is available at
-// http://www.eclipse.org/legal/epl-v10.html
-//
-// The Apache License v2.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 91c87c3ec6..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-2013 Mort Bay Consulting Pty. Ltd.
-// ------------------------------------------------------------------------
-// All rights reserved. This program and the accompanying materials
-// are made available under the terms of the Eclipse Public License v1.0
-// and Apache License v2.0 which accompanies this distribution.
-//
-// The Eclipse Public License is available at
-// http://www.eclipse.org/legal/epl-v10.html
-//
-// The Apache License v2.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 301a1a8cfb..2805ee09b7 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.13-SNAPSHOT</version>
+ <version>8.1.13-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>
<groupId>org.eclipse.jetty.osgi</groupId>
@@ -22,10 +22,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>
@@ -77,7 +75,7 @@
<dependencies>
<dependency>
<groupId>org.eclipse.jetty</groupId>
- <artifactId>jetty-server</artifactId>
+ <artifactId>jetty-annotations</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
@@ -145,6 +143,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 6ca525cf01..c694bcce0f 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.13-SNAPSHOT</version>
+ <version>8.1.13-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>
<modelVersion>4.0.0</modelVersion>
@@ -17,6 +17,7 @@
<dependency>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-server</artifactId>
+ <version>${project.version}</version>
</dependency>
<dependency>
<groupId>org.eclipse.osgi</groupId>
@@ -108,8 +109,8 @@
compilation time. -->
<_nouses>true</_nouses>
<Import-Package>
- javax.servlet;version="2.5.0",
- javax.servlet.resources;version="2.5.0",
+ javax.servlet;version="2.6.0",
+ javax.servlet.resources;version="2.6.0",
org.osgi.framework,
org.osgi.service.cm;version="1.2.0",
org.osgi.service.packageadmin,
@@ -123,7 +124,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 c77c824e66..693c3bd1eb 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.13-SNAPSHOT</version>
+ <version>8.1.13-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>
<modelVersion>4.0.0</modelVersion>
@@ -118,7 +118,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 3039b420a4..a8854434ea 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.13-SNAPSHOT</version>
+ <version>8.1.13-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>
<modelVersion>4.0.0</modelVersion>
@@ -12,6 +12,7 @@
<url>http://www.eclipse.org/jetty</url>
<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>
@@ -224,7 +225,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 0975e832a4..dba40ea32e 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
@@ -39,6 +39,7 @@ import org.eclipse.jetty.webapp.WebAppContext;
import org.junit.Ignore;
import org.junit.Test;
import org.junit.runner.RunWith;
+import org.ops4j.pax.exam.CoreOptions;
import org.ops4j.pax.exam.Inject;
import org.ops4j.pax.exam.Option;
import org.ops4j.pax.exam.container.def.PaxRunnerOptions;
@@ -72,7 +73,8 @@ public class TestJettyOSGiBootWebAppAsService
{
ArrayList<Option> options = new ArrayList<Option>();
options.addAll(TestJettyOSGiBootCore.provisionCoreJetty());
-
+ options.add(CoreOptions.bootDelegationPackages("org.xml.sax", "org.xml.*",
+ "org.w3c.*", "javax.xml.*"));
File base = MavenTestingUtils.getBasedir();
File src = new File (base, "src");
File tst = new File (src, "test");
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 bf68ba3f2d..385d5a0912 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
@@ -134,14 +134,13 @@ public class TestJettyOSGiBootWithJsp
* plus your testcase, wrapped into a bundle called pax-exam-probe
*/
@Test
-
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");
@@ -150,11 +149,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 58a2c4cab3..338e0e0d4a 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.13-SNAPSHOT</version>
+ <version>8.1.13-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>jetty-overlay-deployer</artifactId>
diff --git a/jetty-overlay-deployer/src/main/java/org/eclipse/jetty/overlays/OverlayedAppProvider.java b/jetty-overlay-deployer/src/main/java/org/eclipse/jetty/overlays/OverlayedAppProvider.java
index 5820e6fa2d..6dab7c401e 100644
--- a/jetty-overlay-deployer/src/main/java/org/eclipse/jetty/overlays/OverlayedAppProvider.java
+++ b/jetty-overlay-deployer/src/main/java/org/eclipse/jetty/overlays/OverlayedAppProvider.java
@@ -32,6 +32,7 @@ import java.util.Enumeration;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
+import java.util.Locale;
import java.util.Map;
import java.util.Properties;
import java.util.Set;
@@ -389,7 +390,7 @@ public class OverlayedAppProvider extends AbstractLifeCycle implements AppProvid
List<URL> libs = new ArrayList<URL>();
for (String jar :instance_lib.list())
{
- if (!jar.toLowerCase().endsWith(".jar"))
+ if (!jar.toLowerCase(Locale.ENGLISH).endsWith(".jar"))
continue;
libs.add(instance_lib.addPath(jar).getURL());
}
@@ -610,7 +611,7 @@ public class OverlayedAppProvider extends AbstractLifeCycle implements AppProvid
{
for (String jar :lib.list())
{
- if (!jar.toLowerCase().endsWith(".jar"))
+ if (!jar.toLowerCase(Locale.ENGLISH).endsWith(".jar"))
continue;
libs.add(lib.addPath(jar).getURL());
}
@@ -832,12 +833,12 @@ public class OverlayedAppProvider extends AbstractLifeCycle implements AppProvid
File origin = new File(new URI(_scanDir.toURI()+ruri));
String name=origin.getName();
- Monitor monitor = Monitor.valueOf(origin.getParentFile().getName().toUpperCase());
+ Monitor monitor = Monitor.valueOf(origin.getParentFile().getName().toUpperCase(Locale.ENGLISH));
String ext=".war";
// check directory vs archive
- if (origin.isDirectory() || !origin.exists() && !ruri.toLowerCase().endsWith(ext))
+ if (origin.isDirectory() || !origin.exists() && !ruri.toLowerCase(Locale.ENGLISH).endsWith(ext))
{
// directories have priority over archives
directory=origin;
@@ -846,7 +847,7 @@ public class OverlayedAppProvider extends AbstractLifeCycle implements AppProvid
else
{
// check extension name
- if (!ruri.toLowerCase().endsWith(ext))
+ if (!ruri.toLowerCase(Locale.ENGLISH).endsWith(ext))
continue;
name=name.substring(0,name.length()-4);
diff --git a/jetty-plus/pom.xml b/jetty-plus/pom.xml
index 41f00148ca..47f0ae2f4e 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.13-SNAPSHOT</version>
+ <version>8.1.13-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>jetty-plus</artifactId>
@@ -29,7 +29,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..75c3cd6d9d
--- /dev/null
+++ b/jetty-plus/src/main/java/org/eclipse/jetty/plus/annotation/ContainerInitializer.java
@@ -0,0 +1,114 @@
+//
+// ========================================================================
+// Copyright (c) 1995-2013 Mort Bay Consulting Pty. Ltd.
+// ------------------------------------------------------------------------
+// All rights reserved. This program and the accompanying materials
+// are made available under the terms of the Eclipse Public License v1.0
+// and Apache License v2.0 which accompanies this distribution.
+//
+// The Eclipse Public License is available at
+// http://www.eclipse.org/legal/epl-v10.html
+//
+// The Apache License v2.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..ce02540fc2
--- /dev/null
+++ b/jetty-plus/src/test/java/org/eclipse/jetty/plus/webapp/PlusDescriptorProcessorTest.java
@@ -0,0 +1,176 @@
+//
+// ========================================================================
+// Copyright (c) 1995-2013 Mort Bay Consulting Pty. Ltd.
+// ------------------------------------------------------------------------
+// All rights reserved. This program and the accompanying materials
+// are made available under the terms of the Eclipse Public License v1.0
+// and Apache License v2.0 which accompanies this distribution.
+//
+// The Eclipse Public License is available at
+// http://www.eclipse.org/legal/epl-v10.html
+//
+// The Apache License v2.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 3934e2eb3b..a5eb59c922 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.13-SNAPSHOT</version>
+ <version>8.1.13-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 625388ba0f..402fd8410c 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.13-SNAPSHOT</version>
+ <version>8.1.13-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>jetty-rewrite</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-rewrite/src/main/java/org/eclipse/jetty/rewrite/handler/ProxyRule.java b/jetty-rewrite/src/main/java/org/eclipse/jetty/rewrite/handler/ProxyRule.java
index 808a210900..6064d868cd 100644
--- a/jetty-rewrite/src/main/java/org/eclipse/jetty/rewrite/handler/ProxyRule.java
+++ b/jetty-rewrite/src/main/java/org/eclipse/jetty/rewrite/handler/ProxyRule.java
@@ -371,7 +371,7 @@ public class ProxyRule extends PatternRule
{
// TODO could be better than this!
String hdr = (String)enm.nextElement();
- String lhdr = hdr.toLowerCase();
+ String lhdr = hdr.toLowerCase(Locale.ENGLISH);
if (_DontProxyHeaders.contains(lhdr))
continue;
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 0c0b56f896..84e7d7c07f 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-rewrite/src/test/java/org/eclipse/jetty/rewrite/handler/ValidUrlRuleTest.java b/jetty-rewrite/src/test/java/org/eclipse/jetty/rewrite/handler/ValidUrlRuleTest.java
index 32cfc74168..96554b052d 100644
--- a/jetty-rewrite/src/test/java/org/eclipse/jetty/rewrite/handler/ValidUrlRuleTest.java
+++ b/jetty-rewrite/src/test/java/org/eclipse/jetty/rewrite/handler/ValidUrlRuleTest.java
@@ -108,7 +108,6 @@ public class ValidUrlRuleTest extends AbstractRuleTestCase
assertEquals(200,_response.getStatus());
}
-
@Test
public void testCharacters() throws Exception
diff --git a/jetty-security/pom.xml b/jetty-security/pom.xml
index 4b815a3033..e95dea6591 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.13-SNAPSHOT</version>
+ <version>8.1.13-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>jetty-security</artifactId>
@@ -25,7 +25,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 fd27205278..50ae8a2230 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 a7515cc274..c1f147a4c2 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,17 +19,25 @@
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 org.eclipse.jetty.http.HttpSchemes;
+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;
@@ -43,17 +51,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.
@@ -137,8 +353,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);
@@ -157,6 +371,14 @@ public class ConstraintSecurityHandler extends SecurityHandler implements Constr
}
}
setRoles(roles);
+
+ if (isStarted())
+ {
+ for (ConstraintMapping mapping : _constraintMappings)
+ {
+ processConstraintMapping(mapping);
+ }
+ }
}
/* ------------------------------------------------------------ */
@@ -169,9 +391,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);
}
@@ -233,7 +452,9 @@ public class ConstraintSecurityHandler extends SecurityHandler implements Constr
}
super.doStart();
}
-
+
+
+ /* ------------------------------------------------------------ */
@Override
protected void doStop() throws Exception
{
@@ -242,7 +463,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());
@@ -254,8 +483,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)
{
@@ -269,10 +505,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)
{
@@ -282,50 +518,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);
@@ -335,13 +641,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)
@@ -411,7 +750,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)
@@ -420,7 +763,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
@@ -461,4 +809,5 @@ public class ConstraintSecurityHandler extends SecurityHandler implements Constr
getBeans(),
TypeUtil.asList(getHandlers()));
}
+
}
diff --git a/jetty-security/src/main/java/org/eclipse/jetty/security/SecurityHandler.java b/jetty-security/src/main/java/org/eclipse/jetty/security/SecurityHandler.java
index 93da8d2e87..1699c214b4 100644
--- a/jetty-security/src/main/java/org/eclipse/jetty/security/SecurityHandler.java
+++ b/jetty-security/src/main/java/org/eclipse/jetty/security/SecurityHandler.java
@@ -335,6 +335,7 @@ public abstract class SecurityHandler extends HandlerWrapper implements Authenti
if (_identityService==null)
{
+
if (_loginService!=null)
_identityService=_loginService.getIdentityService();
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 48712cd815..b5d85b3031 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 d16f32b751..6b026fcbe5 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 62392fbe8e..36b7a934f2 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 761080bcce..eabdc8cfec 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
@@ -148,6 +148,8 @@ public class DigestAuthenticator extends LoginAuthenticator
{
return true;
}
+
+
/* ------------------------------------------------------------ */
public Authentication validateRequest(ServletRequest req, ServletResponse res, boolean mandatory) throws ServerAuthException
@@ -217,10 +219,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 d8914f1ef9..21e83150e4 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 93993172e5..23b09e8483 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 ec462c4ea5..5f2b7b5df6 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 ebb8a9e8b1..ab1b8edc27 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 474b5eafd6..7d4945a9a6 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,10 +22,12 @@ import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
import java.io.IOException;
+import java.util.ArrayList;
import java.security.MessageDigest;
import java.util.Arrays;
import java.util.HashMap;
import java.util.HashSet;
+import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.regex.Matcher;
@@ -83,6 +85,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);
@@ -203,6 +207,46 @@ 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();
@@ -210,10 +254,10 @@ public class ConstraintTest
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);
@@ -228,7 +272,7 @@ 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"));
@@ -254,8 +298,32 @@ 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"));
}
-
+
private static String CNONCE="1234567890";
private String digest(String nonce, String username,String password,String uri,String nc) throws Exception
@@ -1023,7 +1091,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..8dab97c8ec
--- /dev/null
+++ b/jetty-security/src/test/java/org/eclipse/jetty/security/SpecExampleConstraintTest.java
@@ -0,0 +1,311 @@
+//
+// ========================================================================
+// Copyright (c) 1995-2013 Mort Bay Consulting Pty. Ltd.
+// ------------------------------------------------------------------------
+// All rights reserved. This program and the accompanying materials
+// are made available under the terms of the Eclipse Public License v1.0
+// and Apache License v2.0 which accompanies this distribution.
+//
+// The Eclipse Public License is available at
+// http://www.eclipse.org/legal/epl-v10.html
+//
+// The Apache License v2.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;
+