Merge from 'master' to 'ws-refactor'
This commit is contained in:
commit
42ec683297
334
VERSION.txt
334
VERSION.txt
|
@ -1,5 +1,109 @@
|
|||
jetty-9.0.0-SNAPSHOT
|
||||
|
||||
jetty-9.0.0.M2 - 06 November 2012
|
||||
+ 371170 MongoSessionManager LastAccessTimeTest fails
|
||||
+ 391877 org.eclipse.jetty.webapp.FragmentDescriptor incorrectly reporting
|
||||
duplicate others for after ordering
|
||||
+ 392237 Split jaas from jetty-plus into jetty-jaas and port the
|
||||
test-jaas-webapp from codehaus
|
||||
+ 392239 Allow no error-code or exception for error-pages
|
||||
+ 392304 fixed intermittent client SSL failure. Correctly compact in flip2fill
|
||||
+ 392525 Add option to --stop-wait to specify timeout
|
||||
+ 392641 JDBC Sessions not scavenged if expired during downtime
|
||||
+ 392812 MongoSessionIDManager never purges old sessions
|
||||
+ 392959 Review HttpClient.getConversation(long).
|
||||
+ 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
|
||||
+ 393291 Confusing log entry about (non) existing webAppSourceDirectory
|
||||
+ 393303 use jetty-web.xml to explicitly add the jetty packages that need
|
||||
visability. This commit also sucked in some changes made to help with the
|
||||
documentation process (improving deployer configuration management
|
||||
+ 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-1549 jetty-maven-plugin fails to reload the LoginService properly
|
||||
+ JETTY-1550 virtual WEB-INF not created if project has overlays
|
||||
|
||||
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
|
||||
queryEncoding
|
||||
+ 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
|
||||
+ 390161 Apply DeferredAuthentication fix to jaspi
|
||||
+ 390560 The method AnnotationParser.getAnnotationHandlers(String) always
|
||||
returns a empty collection.
|
||||
+ 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
|
||||
+ 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-9.0.0.M1 - 15 October 2012
|
||||
+ 369349 directory with spaces --dry-run fix
|
||||
+ 385049 fix issue with pipelined connections when switching protocols
|
||||
|
@ -68,6 +172,10 @@ jetty-8.1.7.v20120910 - 10 September 2012
|
|||
+ 388895 Update dependencies for jetty-jndi
|
||||
+ fix busy logging statement re: sessions
|
||||
|
||||
jetty-7.6.7.v20120910 - 10 September 2012
|
||||
+ 388895 Update dependencies for jetty-jndi
|
||||
+ fix busy logging statement re: sessions
|
||||
|
||||
jetty-8.1.6.v20120903 - 03 September 2012
|
||||
+ 347130 Empty getResourcePaths due to ZipFileClosedException
|
||||
+ 367591 Support Env variables in XmlConfiguration.
|
||||
|
@ -101,6 +209,39 @@ jetty-8.1.6.v20120903 - 03 September 2012
|
|||
+ JETTY-1532 HTTP headers decoded with platform's default encoding
|
||||
+ JETTY-1541 fixed different behaviour for single byte writes
|
||||
|
||||
jetty-7.6.6.v20120903 - 03 September 2012
|
||||
+ 347130 Empty getResourcePaths due to ZipFileClosedException
|
||||
+ 367591 Support Env variables in XmlConfiguration.
|
||||
+ 377055 Prevent webapp classloader leaks
|
||||
+ 379207 backported fixes from jetty-9 to make hierarchy work
|
||||
+ 379423 Jetty URL Decoding fails for certain international characters
|
||||
+ 383304 Reset PrintWriter on response recycle
|
||||
+ 384847 better name
|
||||
+ 385049 fix issue with pipelined connections when switching protocols
|
||||
+ 385651 Message 'Address already in use' not specific enough
|
||||
+ 386010 JspRuntimeContext rewraps System.err
|
||||
+ 386591 add UnixCrypt note to about.html
|
||||
+ 386714 used deferred auth for form login and error pages
|
||||
+ 387896 populate session in SessionAuthentication as a valueBound in addition
|
||||
to activation so it is populate when needed
|
||||
+ 387943 Catch CNFE when no jstl jars are installed
|
||||
+ 387953 jstl does not work with jetty-7 in osgi
|
||||
+ 388072 GZipFilter incorrectly gzips when Accept-Encoding: gzip; q=0
|
||||
+ 388073 null session id from cookie causes NPE fixed
|
||||
+ 388102 Jetty HttpClient memory leaks when sending larger files
|
||||
+ 388393 WebAppProvider doesn't work alongside OSGi deployer
|
||||
+ 388502 handle earlyEOF with 500
|
||||
+ 388652 Do not flush on handle return if request is suspended
|
||||
+ JETTY-1501 Setting custom error response message changes page title
|
||||
+ JETTY-1515 Include cookies on 304 responses from DefaultServlet.
|
||||
+ JETTY-1527 handle requests with URIs like http://host (ie no / )
|
||||
+ JETTY-1529 Ensure new session that has just been authenticated does not get
|
||||
renewed
|
||||
+ JETTY-1532 HTTP headers decoded with platform's default encoding
|
||||
+ JETTY-1541 fixed different behaviour for single byte writes
|
||||
+ 385925: make SslContextFactory.setProtocols and
|
||||
SslContextFactory.setCipherSuites preserve the order of the given parameters
|
||||
|
||||
jetty-8.1.5.v20120716 - 16 June 2012
|
||||
+ 376717 Balancer Servlet with round robin support, contribution, added
|
||||
missing license
|
||||
|
@ -132,6 +273,32 @@ jetty-8.1.5.v20120716 - 16 June 2012
|
|||
+ JETTY-1525 Show handle status in response debug message
|
||||
+ JETTY-1530 refine search control on ldap login module
|
||||
|
||||
jetty-7.6.5.v20120716 - 16 July 2012
|
||||
+ 376717 Balancer Servlet with round robin support, contribution, added
|
||||
missing license
|
||||
+ 379250 Server is added to shutdown hook twice
|
||||
+ 380866 maxIdleTime set to 0 after session migration
|
||||
+ 381399 Unable to stop a jetty instance that has not finished starting
|
||||
+ 381401 Print log warning when stop attempt made with incorrect STOP.KEY
|
||||
+ 381402 Make ContextHandler take set of protected directories
|
||||
+ 381521 set Vary:Accept-Encoding header for content that might be compressed
|
||||
+ 381639 CrossOriginFilter does not support Access-Control-Expose-Headers.
|
||||
+ 381712 Support all declared servlets that implement
|
||||
org.apache.jasper.servlet.JspServlet
|
||||
+ 381825 leave URI params in forwarded requestURI
|
||||
+ 381876 Monitor should wait for child to finish before exiting.
|
||||
+ 382343 Jetty XML support for Map is broken.
|
||||
+ 383251 500 for SocketExceptions
|
||||
+ 383881 WebSocketHandler sets request as handled
|
||||
+ 384254 revert change to writable when not dispatched
|
||||
+ 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.
|
||||
+ JETTY-1525 Show handle status in response debug message
|
||||
+ JETTY-1530 refine search control on ldap login module
|
||||
|
||||
jetty-8.1.4.v20120524 - 24 May 2012
|
||||
+ 367608 ignore the aysncrequestreadtest as it is known to fail and is waiting
|
||||
for a fix
|
||||
|
@ -165,6 +332,38 @@ jetty-8.1.4.v20120524 - 24 May 2012
|
|||
+ 380212 Clear buffer if parsing fails due to full buffer
|
||||
+ 380222 JettyPolicyRuntimeTest failure
|
||||
|
||||
jetty-7.6.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
|
||||
osgi bundle
|
||||
+ 373620 Add ch.qos.logback.access.jetty to the Import-Package for
|
||||
jetty-osgi-boot-logback bundle
|
||||
+ 376152 apply context resources recursively
|
||||
+ 376801 Make JAAS login modules useable without jetty infrastructure
|
||||
+ 377391 Manifest updates to jetty-osgi-boot-logback
|
||||
+ 377492 NPE when deploying a Web Application Bundle with unresolved
|
||||
Require-TldBundle
|
||||
+ 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
|
||||
of same request
|
||||
+ 377709 Support for RequestParameterCallback missing
|
||||
+ 378242 Re-extract war on restart if incomplete extraction
|
||||
+ 378273 Remove default Bundle-Localization header
|
||||
+ 378487 Null out contextPath on Request.recycle
|
||||
+ 379015 Use factored jetty xml config files for defaults
|
||||
+ 379046 avoid closing idle connections from selector thread
|
||||
+ 379089 DefaultServlet ignores its resourceBase and uses context's
|
||||
ResourceCollection when listing diretories
|
||||
+ 379194 ProxyServlet enhancement to enable easy creation of alternative
|
||||
HttpClient implementations
|
||||
+ 379909 FormAuthenticator Rembers only the URL of first Request before
|
||||
authentication
|
||||
+ 380034 last modified times taken from JarEntry for JarFile resources
|
||||
+ 380212 Clear buffer if parsing fails due to full buffer
|
||||
+ 380222 JettyPolicyRuntimeTest failure
|
||||
|
||||
jetty-8.1.3.v20120416 - 16 April 2012
|
||||
+ 349110 MultiPartFilter records the content-type in request params
|
||||
+ 367172 Remove detection for slf4j NOPLogger
|
||||
|
@ -207,6 +406,38 @@ jetty-8.1.3.v20120416 - 16 April 2012
|
|||
request.getParameter
|
||||
+ JETTY-1504 HttpServletResponseWrapper ignored when using asyncContext?
|
||||
|
||||
jetty-7.6.3.v20120416 - 16 April 2012
|
||||
+ 367172 Remove detection for slf4j NOPLogger
|
||||
+ 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
|
||||
+ 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
|
||||
+ 374475 Response.sendRedirect does not encode UTF-8 characters properly
|
||||
+ 374881 Set copyWebInf to false by default
|
||||
+ 374891 enhancement to how ProxyServlet determines the proxy target
|
||||
+ 375009 Filter initialization error will throw MultiException
|
||||
+ 375083 Flow control should take in account window size changes from
|
||||
concurrent SETTINGS
|
||||
+ 375096 If starting a server instance fails in osgi it is cleaned up.
|
||||
+ 375490 NPE with --help on command line
|
||||
+ 375509 Stalled stream stalls other streams or session control frames. Now
|
||||
using a "death pill" instead of a boolean in order to avoid race conditions
|
||||
where DataInfos were read from the queue (but the boolean not updated yet),
|
||||
and viceversa.
|
||||
+ 375594 fixed SSL tests so they are not order dependent
|
||||
+ 375709 Ensure resolveTempDirectory failure does not deadlock; improve error
|
||||
message
|
||||
+ 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.
|
||||
+ JETTY-1504 HttpServletResponseWrapper ignored when using asyncContext?
|
||||
|
||||
jetty-8.1.2.v20120308 - 08 March 2012
|
||||
+ 370387 SafariWebsocketDraft0Test failure during build.
|
||||
+ 371168 Update ClientCrossContextSessionTest
|
||||
|
@ -229,6 +460,27 @@ jetty-8.1.2.v20120308 - 08 March 2012
|
|||
+ JETTY-1489 WebAppProvider attempts to deploy .svn folder
|
||||
+ JETTY-1494 .
|
||||
|
||||
jetty-7.6.2.v20120308 - 08 March 2012
|
||||
+ 370387 SafariWebsocketDraft0Test failure during build.
|
||||
+ 371168 Update ClientCrossContextSessionTest
|
||||
+ 372093 handle quotes in Require-Bundle manifest string
|
||||
+ 372457 Big response + slow clients + pipelined requests cause Jetty spinning
|
||||
and eventually closing connections. Added a TODO for a method renaming that
|
||||
will happen in the next major release (to avoid break implementers).
|
||||
+ 372487 JDBCSessionManager does not work with Oracle
|
||||
+ 372806 Command line should accept relative paths for xml config files
|
||||
+ 373037 jetty.server.Response.setContentLength(int) should not close a Writer
|
||||
when length=0
|
||||
+ 373162 add improved implementation for getParameterMap(), needs a test
|
||||
though and the existing setup doesn't seem like it would easily support the
|
||||
needed test so need to do that still
|
||||
+ 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
|
||||
+ JETTY-1409 GzipFilter will double-compress application/x-gzip content
|
||||
+ JETTY-1489 WebAppProvider attempts to deploy .svn folder
|
||||
+ JETTY-1494 .
|
||||
|
||||
jetty-8.1.1.v20120215 - 15 February 2012
|
||||
+ 369121 simplified test
|
||||
+ 370120 jvm arguments added via start.ini and --exec are missing spaces
|
||||
|
@ -243,12 +495,32 @@ jetty-8.1.1.v20120215 - 15 February 2012
|
|||
+ JETTY-1484 Add option for HashSessionManager to delete session files if it
|
||||
can't restore them
|
||||
|
||||
jetty-7.6.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
|
||||
[included|excluded]Protocols() and [included|excluded]CipherSuites().
|
||||
+ 370368 resolve stack overflow in mongo db session manager
|
||||
+ 370386 Remove META-INF from jetty distro
|
||||
+ 371040 nosqlsession needs to call correct super contructor for new sessions
|
||||
+ 371041 valid was not being set to new mongo db sessions, and the call to
|
||||
mongodb api was wrong in isIdInUse
|
||||
+ 371162 NPE protection for nested security handlers
|
||||
+ JETTY-1484 Add option for HashSessionManager to delete session files if it
|
||||
can't restore them
|
||||
|
||||
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-7.6.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
|
||||
|
@ -264,6 +536,22 @@ jetty-8.1.0.RC5 - 20 January 2012
|
|||
+ JETTY-1475 made output state fields volatile to provide memory barrier for
|
||||
non dispatched thread IO
|
||||
|
||||
jetty-7.6.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 avoid non-blocking flush when writing to avoid setting !_writable
|
||||
without _writeblocked
|
||||
+ 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.
|
||||
|
@ -293,6 +581,21 @@ jetty-8.1.0.RC4 - 13 January 2012
|
|||
BeanELResolver.properties
|
||||
+ JETTY-1467 close half closed when idle
|
||||
|
||||
jetty-7.6.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.
|
||||
+ 367716 simplified maxIdleTime logic
|
||||
+ 368035 WebSocketClientFactory does not invoke super.doStop().
|
||||
+ 368060 do not encode sendRedirect URLs
|
||||
+ 368114 Protect against non-Strings in System properties for Log
|
||||
+ 368189 WebSocketClientFactory should not manage external thread pool.
|
||||
+ 368215 Remove debug from jaspi
|
||||
+ 368240 Improve AggregateLifeCycle handling of shared lifecycles
|
||||
+ 368291 Change warning to info for NoSuchFieldException on
|
||||
BeanELResolver.properties
|
||||
|
||||
jetty-8.1.0.RC2 - 22 December 2011
|
||||
+ 359329 jetty-jaspi must exports its packages. jetty-plus must import
|
||||
javax.security
|
||||
|
@ -317,6 +620,37 @@ jetty-8.1.0.RC2 - 22 December 2011
|
|||
+ JETTY-1463 websocket D0 parser should return progress even if no fill done
|
||||
+ JETTY-1465 NPE in ContextHandler.toString
|
||||
|
||||
jetty-7.6.0.RC3 - 05 January 2012
|
||||
+ 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.
|
||||
+ 367591 corrected configuration.xml version to 7.6
|
||||
+ 367635 Added support for start.d directory
|
||||
+ 367638 limit number of form parameters to avoid DOS
|
||||
+ JETTY-1467 close half closed when idle
|
||||
|
||||
jetty-7.6.0.RC2 - 22 December 2011
|
||||
+ 364638 HttpParser closes if data received while seeking EOF. Tests fixed to
|
||||
cope
|
||||
+ 364921 Made test less time sensitive for ssl
|
||||
+ 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.
|
||||
+ 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
|
||||
|
|
|
@ -0,0 +1,78 @@
|
|||
<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">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<parent>
|
||||
<groupId>org.eclipse.jetty.dist</groupId>
|
||||
<artifactId>dist-parent</artifactId>
|
||||
<version>9.0.0-SNAPSHOT</version>
|
||||
</parent>
|
||||
<artifactId>jetty-deb</artifactId>
|
||||
<name>Jetty :: Unix Distributions :: Debian</name>
|
||||
<packaging>deb</packaging>
|
||||
<build>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>org.mortbay.jetty.toolchain</groupId>
|
||||
<artifactId>unix-maven-plugin</artifactId>
|
||||
<version>1.0-alpha-6.1</version>
|
||||
<extensions>true</extensions>
|
||||
<configuration>
|
||||
<contact>Jetty Project</contact>
|
||||
<contactEmail>jetty-dev@eclipse.org</contactEmail>
|
||||
<name>Core Jetty ${project.version} Distribution</name>
|
||||
<description>Jetty provides an Web server and javax.servlet
|
||||
container, plus support for Web Sockets, OSGi, JMX, JNDI,
|
||||
JASPI, AJP and many other integrations. These components are
|
||||
open source and available for commercial use and
|
||||
distribution.</description>
|
||||
<deb>
|
||||
<useFakeroot>false</useFakeroot>
|
||||
<priority>optional</priority>
|
||||
<section>java</section>
|
||||
</deb>
|
||||
<packages>
|
||||
<package>
|
||||
<id>jetty-server</id>
|
||||
<assembly>
|
||||
<extractArtifact>
|
||||
<artifact>org.eclipse.jetty:jetty-distribution:zip</artifact>
|
||||
<to>/opt/jetty</to>
|
||||
<pattern>/jetty-distribution-${project.version}(.*)</pattern>
|
||||
<replacement>$1</replacement>
|
||||
<excludes>
|
||||
<include>jetty-distribution-*/contexts/javadoc.xml</include>
|
||||
<exclude>jetty-distribution-*/javadoc</exclude>
|
||||
<exclude>jetty-distribution-*/javadoc/**</exclude>
|
||||
</excludes>
|
||||
</extractArtifact>
|
||||
</assembly>
|
||||
</package>
|
||||
<!--package>
|
||||
<id>jetty-javadoc</id>
|
||||
<classifier>javadoc</classifier>
|
||||
<assembly>
|
||||
<extractArtifact>
|
||||
<artifact>org.eclipse.jetty:jetty-distribution:zip</artifact>
|
||||
<to>/opt/jetty</to>
|
||||
<pattern>/jetty-distribution-${project.version}(.*)</pattern>
|
||||
<replacement>$1</replacement>
|
||||
<includes>
|
||||
<include>jetty-distribution-*/contexts/javadoc.xml</include>
|
||||
<include>jetty-distribution-*/javadoc/**</include>
|
||||
</includes>
|
||||
</extractArtifact>
|
||||
</assembly>
|
||||
</package-->
|
||||
</packages>
|
||||
</configuration>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>org.eclipse.jetty</groupId>
|
||||
<artifactId>jetty-distribution</artifactId>
|
||||
<version>${project.version}</version>
|
||||
<type>zip</type>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
</project>
|
|
@ -0,0 +1,6 @@
|
|||
#!/bin/bash
|
||||
|
||||
cp /opt/jetty/bin/jetty.sh /etc/init.d/jetty
|
||||
|
||||
chmod 755 /etc/init.d/jetty
|
||||
chmod 755 /opt/jetty/bin/*.sh
|
|
@ -0,0 +1,3 @@
|
|||
#!/bin/bash
|
||||
|
||||
rm -f /etc/init.d/jetty
|
|
@ -0,0 +1,26 @@
|
|||
<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/xsd/maven-4.0.0.xsd">
|
||||
<parent>
|
||||
<artifactId>jetty-project</artifactId>
|
||||
<groupId>org.eclipse.jetty</groupId>
|
||||
<version>9.0.0-SNAPSHOT</version>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<groupId>org.eclipse.jetty.dist</groupId>
|
||||
<artifactId>dist-parent</artifactId>
|
||||
<packaging>pom</packaging>
|
||||
<name>Jetty :: Distribution :: Parent</name>
|
||||
<profiles>
|
||||
<profile>
|
||||
<id>linux-packaging</id>
|
||||
<!-- activation>
|
||||
<os>
|
||||
<name>Linux</name>
|
||||
</os>
|
||||
</activation-->
|
||||
<modules>
|
||||
<module>jetty-deb</module>
|
||||
<!--module>jetty-rpm</module-->
|
||||
</modules>
|
||||
</profile>
|
||||
</profiles>
|
||||
</project>
|
|
@ -3,6 +3,7 @@
|
|||
<groupId>org.eclipse.jetty</groupId>
|
||||
<artifactId>jetty-project</artifactId>
|
||||
<version>9.0.0-SNAPSHOT</version>
|
||||
<relativePath>../../pom.xml</relativePath>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<groupId>org.eclipse.jetty</groupId>
|
||||
|
|
|
@ -3,6 +3,7 @@
|
|||
<groupId>org.eclipse.jetty</groupId>
|
||||
<artifactId>jetty-project</artifactId>
|
||||
<version>9.0.0-SNAPSHOT</version>
|
||||
<relativePath>../../pom.xml</relativePath>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<artifactId>example-jetty-embedded</artifactId>
|
||||
|
|
|
@ -106,7 +106,7 @@ public class LikeJettyXml
|
|||
webapp_provider.setParentLoaderPriority(false);
|
||||
webapp_provider.setExtractWars(true);
|
||||
webapp_provider.setScanInterval(2);
|
||||
webapp_provider.setDefaultsDescriptor(jetty_home + "/etc/webdefault.xml");
|
||||
//webapp_provider.setDefaultsDescriptor(jetty_home + "/etc/webdefault.xml");
|
||||
deployer.addAppProvider(webapp_provider);
|
||||
|
||||
HashLoginService login = new HashLoginService();
|
||||
|
|
|
@ -21,13 +21,6 @@ package org.eclipse.jetty.embedded;
|
|||
import org.eclipse.jetty.server.Server;
|
||||
import org.eclipse.jetty.server.handler.ContextHandler;
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
/**
|
||||
* A {@link ContextHandler} provides a common environment for multiple Handlers,
|
||||
* such as: URI context path, class loader, static resource base.
|
||||
*
|
||||
* Typically a ContextHandler is used only when multiple contexts are likely.
|
||||
*/
|
||||
public class OneContext
|
||||
{
|
||||
public static void main(String[] args) throws Exception
|
||||
|
@ -38,10 +31,10 @@ public class OneContext
|
|||
context.setContextPath("/");
|
||||
context.setResourceBase(".");
|
||||
context.setClassLoader(Thread.currentThread().getContextClassLoader());
|
||||
server.setHandler(context);
|
||||
|
||||
context.setHandler(new HelloHandler());
|
||||
|
||||
server.setHandler(context);
|
||||
|
||||
server.start();
|
||||
server.join();
|
||||
}
|
||||
|
|
|
@ -26,6 +26,7 @@ import java.net.URLClassLoader;
|
|||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
import java.util.jar.JarEntry;
|
||||
|
||||
import org.eclipse.jetty.util.Loader;
|
||||
|
@ -807,7 +808,7 @@ public class AnnotationParser
|
|||
try
|
||||
{
|
||||
String name = entry.getName();
|
||||
if (name.toLowerCase().endsWith(".class"))
|
||||
if (name.toLowerCase(Locale.ENGLISH).endsWith(".class"))
|
||||
{
|
||||
String shortName = name.replace('/', '.').substring(0,name.length()-6);
|
||||
if ((resolver == null)
|
||||
|
@ -853,7 +854,7 @@ public class AnnotationParser
|
|||
try
|
||||
{
|
||||
String name = entry.getName();
|
||||
if (name.toLowerCase().endsWith(".class"))
|
||||
if (name.toLowerCase(Locale.ENGLISH).endsWith(".class"))
|
||||
{
|
||||
String shortName = name.replace('/', '.').substring(0,name.length()-6);
|
||||
|
||||
|
|
|
@ -21,6 +21,7 @@ package org.eclipse.jetty.annotations;
|
|||
import java.lang.reflect.Field;
|
||||
import java.lang.reflect.Method;
|
||||
import java.lang.reflect.Modifier;
|
||||
import java.util.Locale;
|
||||
import javax.annotation.Resource;
|
||||
import javax.naming.InitialContext;
|
||||
import javax.naming.NameNotFoundException;
|
||||
|
@ -261,7 +262,7 @@ public class ResourceAnnotationHandler extends AbstractIntrospectableAnnotationH
|
|||
|
||||
//default name is the javabean property name
|
||||
String name = method.getName().substring(3);
|
||||
name = name.substring(0,1).toLowerCase()+name.substring(1);
|
||||
name = name.substring(0,1).toLowerCase(Locale.ENGLISH)+name.substring(1);
|
||||
name = clazz.getCanonicalName()+"/"+name;
|
||||
|
||||
name = (resource.name()!=null && !resource.name().trim().equals("")? resource.name(): name);
|
||||
|
|
|
@ -30,6 +30,7 @@ import java.util.ArrayList;
|
|||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.concurrent.ConcurrentMap;
|
||||
|
@ -323,7 +324,7 @@ public class HttpClient extends ContainerLifeCycle
|
|||
|
||||
protected void send(final Request request, List<Response.ResponseListener> listeners)
|
||||
{
|
||||
String scheme = request.getScheme().toLowerCase();
|
||||
String scheme = request.getScheme().toLowerCase(Locale.ENGLISH);
|
||||
if (!Arrays.asList("http", "https").contains(scheme))
|
||||
throw new IllegalArgumentException("Invalid protocol " + scheme);
|
||||
|
||||
|
|
|
@ -44,7 +44,7 @@ public class HttpCookieParser
|
|||
|
||||
public static List<HttpCookie> parseCookies(String headerValue)
|
||||
{
|
||||
if (headerValue.toLowerCase().contains("expires="))
|
||||
if (headerValue.toLowerCase(Locale.ENGLISH).contains("expires="))
|
||||
{
|
||||
HttpCookie cookie = parseCookie(headerValue, 0);
|
||||
if (cookie != null)
|
||||
|
@ -111,7 +111,7 @@ public class HttpCookieParser
|
|||
try
|
||||
{
|
||||
String[] attributeParts = cookieParts[i].split("=", 2);
|
||||
String attributeName = attributeParts[0].trim().toLowerCase();
|
||||
String attributeName = attributeParts[0].trim().toLowerCase(Locale.ENGLISH);
|
||||
String attributeValue = attributeParts.length < 2 ? "" : attributeParts[1].trim();
|
||||
switch (attributeName)
|
||||
{
|
||||
|
|
|
@ -24,6 +24,7 @@ import java.util.ArrayList;
|
|||
import java.util.Collections;
|
||||
import java.util.Enumeration;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
import java.util.concurrent.TimeoutException;
|
||||
import java.util.concurrent.atomic.AtomicMarkableReference;
|
||||
import java.util.concurrent.atomic.AtomicReference;
|
||||
|
@ -191,7 +192,7 @@ public class HttpReceiver implements HttpParser.ResponseHandler<ByteBuffer>
|
|||
if (exchange != null)
|
||||
{
|
||||
exchange.getResponse().getHeaders().add(name, value);
|
||||
switch (name.toLowerCase())
|
||||
switch (name.toLowerCase(Locale.ENGLISH))
|
||||
{
|
||||
case "set-cookie":
|
||||
case "set-cookie2":
|
||||
|
|
|
@ -21,6 +21,7 @@ package org.eclipse.jetty.client.util;
|
|||
import java.io.UnsupportedEncodingException;
|
||||
import java.nio.ByteBuffer;
|
||||
import java.nio.charset.UnsupportedCharsetException;
|
||||
import java.util.Locale;
|
||||
|
||||
import org.eclipse.jetty.client.api.Response;
|
||||
import org.eclipse.jetty.client.api.Result;
|
||||
|
@ -69,7 +70,7 @@ public abstract class BufferingResponseListener extends Response.Listener.Empty
|
|||
if (contentType != null)
|
||||
{
|
||||
String charset = "charset=";
|
||||
int index = contentType.toLowerCase().indexOf(charset);
|
||||
int index = contentType.toLowerCase(Locale.ENGLISH).indexOf(charset);
|
||||
if (index > 0)
|
||||
{
|
||||
String encoding = contentType.substring(index + charset.length());
|
||||
|
|
|
@ -25,6 +25,7 @@ import java.util.ArrayList;
|
|||
import java.util.Arrays;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
import java.util.Map;
|
||||
import java.util.Random;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
|
@ -108,7 +109,7 @@ public class DigestAuthentication implements Authentication
|
|||
Matcher matcher = PARAM_PATTERN.matcher(part);
|
||||
if (matcher.matches())
|
||||
{
|
||||
String name = matcher.group(1).trim().toLowerCase();
|
||||
String name = matcher.group(1).trim().toLowerCase(Locale.ENGLISH);
|
||||
String value = matcher.group(2).trim();
|
||||
if (value.startsWith("\"") && value.endsWith("\""))
|
||||
value = value.substring(1, value.length() - 1);
|
||||
|
@ -251,7 +252,7 @@ public class DigestAuthentication implements Authentication
|
|||
private String nextNonceCount()
|
||||
{
|
||||
String padding = "00000000";
|
||||
String next = Integer.toHexString(nonceCount.incrementAndGet()).toLowerCase();
|
||||
String next = Integer.toHexString(nonceCount.incrementAndGet()).toLowerCase(Locale.ENGLISH);
|
||||
return padding.substring(0, padding.length() - next.length()) + next;
|
||||
}
|
||||
|
||||
|
@ -265,7 +266,7 @@ public class DigestAuthentication implements Authentication
|
|||
|
||||
private String toHexString(byte[] bytes)
|
||||
{
|
||||
return TypeUtil.toHexString(bytes).toLowerCase();
|
||||
return TypeUtil.toHexString(bytes).toLowerCase(Locale.ENGLISH);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -23,6 +23,7 @@ import java.nio.ByteBuffer;
|
|||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
import java.util.Random;
|
||||
import java.util.concurrent.CountDownLatch;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
@ -184,7 +185,7 @@ public class HttpClientLoadTest extends AbstractHttpClientServerTest
|
|||
@Override
|
||||
public void handle(String target, org.eclipse.jetty.server.Request baseRequest, HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException
|
||||
{
|
||||
String method = request.getMethod().toUpperCase();
|
||||
String method = request.getMethod().toUpperCase(Locale.ENGLISH);
|
||||
switch (method)
|
||||
{
|
||||
case "GET":
|
||||
|
|
|
@ -20,6 +20,7 @@ package org.eclipse.jetty.client;
|
|||
|
||||
import java.net.URI;
|
||||
import java.nio.ByteBuffer;
|
||||
import java.util.Locale;
|
||||
import java.util.concurrent.CountDownLatch;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
|
@ -288,8 +289,8 @@ public class HttpSenderTest
|
|||
|
||||
String requestString = endPoint.takeOutputString();
|
||||
Assert.assertTrue(requestString.startsWith("GET "));
|
||||
String content = Integer.toHexString(content1.length()).toUpperCase() + "\r\n" + content1 + "\r\n";
|
||||
content += Integer.toHexString(content2.length()).toUpperCase() + "\r\n" + content2 + "\r\n";
|
||||
String content = Integer.toHexString(content1.length()).toUpperCase(Locale.ENGLISH) + "\r\n" + content1 + "\r\n";
|
||||
content += Integer.toHexString(content2.length()).toUpperCase(Locale.ENGLISH) + "\r\n" + content2 + "\r\n";
|
||||
content += "0\r\n\r\n";
|
||||
Assert.assertTrue(requestString.endsWith("\r\n\r\n" + content));
|
||||
Assert.assertTrue(headersLatch.await(5, TimeUnit.SECONDS));
|
||||
|
|
|
@ -43,6 +43,16 @@
|
|||
<Set name="defaultsDescriptor"><Property name="jetty.home" default="." />/etc/webdefault.xml</Set>
|
||||
<Set name="scanInterval">1</Set>
|
||||
<Set name="extractWars">true</Set>
|
||||
<Set name="configurationManager">
|
||||
<New class="org.eclipse.jetty.deploy.PropertiesConfigurationManager">
|
||||
<!-- file of context configuration properties
|
||||
<Set name="file"><SystemProperty name="jetty.home"/>/etc/some.properties</Set>
|
||||
-->
|
||||
<!-- set a context configuration property
|
||||
<Call name="put"><Arg>name</Arg><Arg>value</Arg></Call>
|
||||
-->
|
||||
</New>
|
||||
</Set>
|
||||
</New>
|
||||
</Arg>
|
||||
</Call>
|
||||
|
|
|
@ -21,10 +21,15 @@ package org.eclipse.jetty.deploy;
|
|||
import java.io.FileNotFoundException;
|
||||
import java.io.IOException;
|
||||
import java.net.MalformedURLException;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.Properties;
|
||||
|
||||
import org.eclipse.jetty.util.annotation.ManagedAttribute;
|
||||
import org.eclipse.jetty.util.annotation.ManagedObject;
|
||||
import org.eclipse.jetty.util.annotation.ManagedOperation;
|
||||
import org.eclipse.jetty.util.annotation.Name;
|
||||
import org.eclipse.jetty.util.resource.Resource;
|
||||
|
||||
/**
|
||||
|
@ -32,42 +37,55 @@ import org.eclipse.jetty.util.resource.Resource;
|
|||
*
|
||||
* Supplies properties defined in a file.
|
||||
*/
|
||||
public class FileConfigurationManager implements ConfigurationManager
|
||||
@ManagedObject("Configure deployed webapps via properties")
|
||||
public class PropertiesConfigurationManager implements ConfigurationManager
|
||||
{
|
||||
private Resource _file;
|
||||
private Map<String,String> _map = new HashMap<String,String>();
|
||||
private String _properties;
|
||||
private final Map<String,String> _map = new HashMap<String,String>();
|
||||
|
||||
public FileConfigurationManager()
|
||||
public PropertiesConfigurationManager(String properties)
|
||||
{
|
||||
}
|
||||
|
||||
public PropertiesConfigurationManager()
|
||||
{
|
||||
}
|
||||
|
||||
public void setFile(String filename) throws MalformedURLException, IOException
|
||||
@ManagedAttribute("A file or URL of properties")
|
||||
public void setFile(String resource) throws MalformedURLException, IOException
|
||||
{
|
||||
_file = Resource.newResource(filename);
|
||||
_properties=resource;
|
||||
_map.clear();
|
||||
loadProperties(_properties);
|
||||
}
|
||||
|
||||
public String getFile()
|
||||
{
|
||||
return _properties;
|
||||
}
|
||||
|
||||
@ManagedOperation("Set a property")
|
||||
public void put(@Name("name")String name, @Name("value")String value)
|
||||
{
|
||||
_map.put(name,value);
|
||||
}
|
||||
|
||||
/**
|
||||
* @see org.eclipse.jetty.deploy.ConfigurationManager#getProperties()
|
||||
*/
|
||||
@Override
|
||||
public Map<String, String> getProperties()
|
||||
{
|
||||
try
|
||||
{
|
||||
loadProperties();
|
||||
return _map;
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
return new HashMap<>(_map);
|
||||
}
|
||||
|
||||
private void loadProperties() throws FileNotFoundException, IOException
|
||||
{
|
||||
if (_map.isEmpty() && _file!=null)
|
||||
private void loadProperties(String resource) throws FileNotFoundException, IOException
|
||||
{
|
||||
Resource file=Resource.newResource(resource);
|
||||
if (file!=null && file.exists())
|
||||
{
|
||||
Properties properties = new Properties();
|
||||
properties.load(_file.getInputStream());
|
||||
properties.load(file.getInputStream());
|
||||
for (Map.Entry<Object, Object> entry : properties.entrySet())
|
||||
_map.put(entry.getKey().toString(),String.valueOf(entry.getValue()));
|
||||
}
|
|
@ -22,6 +22,7 @@ import java.io.File;
|
|||
import java.io.FilenameFilter;
|
||||
import java.io.IOException;
|
||||
import java.net.MalformedURLException;
|
||||
import java.util.Locale;
|
||||
|
||||
import org.eclipse.jetty.deploy.App;
|
||||
import org.eclipse.jetty.deploy.ConfigurationManager;
|
||||
|
@ -77,7 +78,7 @@ public class WebAppProvider extends ScanningAppProvider
|
|||
{
|
||||
return false;
|
||||
}
|
||||
String lowername = name.toLowerCase();
|
||||
String lowername = name.toLowerCase(Locale.ENGLISH);
|
||||
|
||||
File file = new File(dir,name);
|
||||
|
||||
|
@ -299,9 +300,9 @@ public class WebAppProvider extends ScanningAppProvider
|
|||
{
|
||||
context = URIUtil.SLASH;
|
||||
}
|
||||
else if (context.toLowerCase().startsWith("root-"))
|
||||
else if (context.toLowerCase(Locale.ENGLISH).startsWith("root-"))
|
||||
{
|
||||
int dash=context.toLowerCase().indexOf('-');
|
||||
int dash=context.toLowerCase(Locale.ENGLISH).indexOf('-');
|
||||
String virtual = context.substring(dash+1);
|
||||
wah.setVirtualHosts(new String[]{virtual});
|
||||
context = URIUtil.SLASH;
|
||||
|
|
|
@ -19,6 +19,7 @@
|
|||
package org.eclipse.jetty.deploy.util;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.Locale;
|
||||
|
||||
/**
|
||||
* Simple, yet surprisingly common utility methods for identifying various file types commonly seen and worked with in a
|
||||
|
@ -38,7 +39,7 @@ public class FileID
|
|||
{
|
||||
if (path.isFile())
|
||||
{
|
||||
String name = path.getName().toLowerCase();
|
||||
String name = path.getName().toLowerCase(Locale.ENGLISH);
|
||||
return (name.endsWith(".war") || name.endsWith(".jar"));
|
||||
}
|
||||
|
||||
|
@ -62,7 +63,7 @@ public class FileID
|
|||
return false;
|
||||
}
|
||||
|
||||
String name = path.getName().toLowerCase();
|
||||
String name = path.getName().toLowerCase(Locale.ENGLISH);
|
||||
return (name.endsWith(".war") || name.endsWith(".jar"));
|
||||
}
|
||||
|
||||
|
@ -73,7 +74,7 @@ public class FileID
|
|||
return false;
|
||||
}
|
||||
|
||||
String name = path.getName().toLowerCase();
|
||||
String name = path.getName().toLowerCase(Locale.ENGLISH);
|
||||
return name.endsWith(".xml");
|
||||
}
|
||||
}
|
||||
|
|
|
@ -50,7 +50,7 @@
|
|||
<Set name="monitoredDirName"><SystemProperty name="jetty.home" />/webapps</Set>
|
||||
<Set name="scanInterval">1</Set>
|
||||
<Set name="configurationManager">
|
||||
<New class="org.eclipse.jetty.deploy.FileConfigurationManager">
|
||||
<New class="org.eclipse.jetty.deploy.PropertiesConfigurationManager">
|
||||
<Set name="file">
|
||||
<SystemProperty name="jetty.home"/>/xml-configured-jetty.properties
|
||||
</Set>
|
||||
|
|
|
@ -17,7 +17,7 @@
|
|||
<Set name="monitoredDirName"><SystemProperty name="jetty.home" />/webapps</Set>
|
||||
<Set name="scanInterval">1</Set>
|
||||
<Set name="configurationManager">
|
||||
<New class="org.eclipse.jetty.deploy.FileConfigurationManager">
|
||||
<New class="org.eclipse.jetty.deploy.PropertiesConfigurationManager">
|
||||
<Set name="file">
|
||||
<SystemProperty name="jetty.home"/>/xml-configured-jetty.properties
|
||||
</Set>
|
||||
|
|
|
@ -364,6 +364,12 @@
|
|||
<version>${project.version}</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.eclipse.jetty</groupId>
|
||||
<artifactId>jetty-jaas</artifactId>
|
||||
<version>${project.version}</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.eclipse.jetty</groupId>
|
||||
<artifactId>jetty-annotations</artifactId>
|
||||
|
@ -381,11 +387,6 @@
|
|||
<artifactId>jetty-jndi</artifactId>
|
||||
<version>${project.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.eclipse.jetty</groupId>
|
||||
<artifactId>jetty-plus</artifactId>
|
||||
<version>${project.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.eclipse.jetty</groupId>
|
||||
<artifactId>jetty-client</artifactId>
|
||||
|
|
|
@ -1,13 +1,7 @@
|
|||
<?xml version="1.0" encoding="ISO-8859-1"?>
|
||||
<!DOCTYPE Configure PUBLIC "-//Jetty//Configure//EN" "http://www.eclipse.org/jetty/configure.dtd">
|
||||
|
||||
<!--
|
||||
Configure a custom context for the javadoc.
|
||||
|
||||
This context contains only a ServletHandler with a default servlet
|
||||
to serve static html files and images.
|
||||
-->
|
||||
|
||||
<!--Configure a context for the javadoc -->
|
||||
<Configure class="org.eclipse.jetty.server.handler.ContextHandler">
|
||||
<Set name="contextPath">/javadoc</Set>
|
||||
<Set name="resourceBase"><SystemProperty name="jetty.home" default="."/>/javadoc/</Set>
|
||||
|
@ -21,6 +15,5 @@ to serve static html files and images.
|
|||
<Set name="cacheControl">max-age=3600,public</Set>
|
||||
</New>
|
||||
</Set>
|
||||
|
||||
</Configure>
|
||||
|
||||
|
|
|
@ -36,6 +36,7 @@ public interface HttpContent
|
|||
String getLastModified();
|
||||
ByteBuffer getIndirectBuffer();
|
||||
ByteBuffer getDirectBuffer();
|
||||
String getETag();
|
||||
Resource getResource();
|
||||
long getContentLength();
|
||||
InputStream getInputStream() throws IOException;
|
||||
|
@ -50,19 +51,33 @@ public interface HttpContent
|
|||
final Resource _resource;
|
||||
final String _mimeType;
|
||||
final int _maxBuffer;
|
||||
final String _etag;
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
public ResourceAsHttpContent(final Resource resource, final String mimeType)
|
||||
{
|
||||
_resource=resource;
|
||||
_mimeType=mimeType;
|
||||
_maxBuffer=-1;
|
||||
this(resource,mimeType,-1,false);
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
public ResourceAsHttpContent(final Resource resource, final String mimeType, int maxBuffer)
|
||||
{
|
||||
this(resource,mimeType,maxBuffer,false);
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
public ResourceAsHttpContent(final Resource resource, final String mimeType, boolean etag)
|
||||
{
|
||||
this(resource,mimeType,-1,etag);
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
public ResourceAsHttpContent(final Resource resource, final String mimeType, int maxBuffer, boolean etag)
|
||||
{
|
||||
_resource=resource;
|
||||
_mimeType=mimeType;
|
||||
_maxBuffer=maxBuffer;
|
||||
_etag=etag?resource.getWeakETag():null;
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
|
@ -85,6 +100,13 @@ public interface HttpContent
|
|||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
@Override
|
||||
public String getETag()
|
||||
{
|
||||
return _etag;
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
@Override
|
||||
|
|
|
@ -810,7 +810,7 @@ public class HttpFields implements Iterable<HttpFields.Field>
|
|||
{
|
||||
hasDomain = true;
|
||||
buf.append(";Domain=");
|
||||
QuotedStringTokenizer.quoteIfNeeded(buf,domain.toLowerCase(),delim);
|
||||
QuotedStringTokenizer.quoteIfNeeded(buf,domain.toLowerCase(Locale.ENGLISH),delim);
|
||||
}
|
||||
|
||||
if (maxAge >= 0)
|
||||
|
|
|
@ -562,7 +562,7 @@ public class HttpParser
|
|||
switch (_header)
|
||||
{
|
||||
case CONTENT_LENGTH:
|
||||
if (_endOfContent != EndOfContent.CHUNKED_CONTENT && _responseStatus!=304 && _responseStatus!=204 && (_responseStatus<100 || _responseStatus>=200))
|
||||
if (_endOfContent != EndOfContent.CHUNKED_CONTENT)
|
||||
{
|
||||
try
|
||||
{
|
||||
|
@ -640,7 +640,6 @@ public class HttpParser
|
|||
_header=null;
|
||||
_value=null;
|
||||
|
||||
|
||||
// now handle the ch
|
||||
if (ch == HttpTokens.CARRIAGE_RETURN || ch == HttpTokens.LINE_FEED)
|
||||
{
|
||||
|
@ -657,8 +656,15 @@ public class HttpParser
|
|||
return true;
|
||||
}
|
||||
|
||||
// so work out the _content demarcation
|
||||
if (_endOfContent == EndOfContent.UNKNOWN_CONTENT)
|
||||
// is it a response that cannot have a body?
|
||||
if (_responseHandler !=null && // response
|
||||
(_responseStatus == 304 || // not-modified response
|
||||
_responseStatus == 204 || // no-content response
|
||||
_responseStatus < 200)) // 1xx response
|
||||
_endOfContent=EndOfContent.NO_CONTENT; // ignore any other headers set
|
||||
|
||||
// else if we don't know framing
|
||||
else if (_endOfContent == EndOfContent.UNKNOWN_CONTENT)
|
||||
{
|
||||
if (_responseStatus == 0 // request
|
||||
|| _responseStatus == 304 // not-modified response
|
||||
|
|
|
@ -22,6 +22,7 @@ import java.nio.ByteBuffer;
|
|||
import java.nio.charset.Charset;
|
||||
import java.util.Enumeration;
|
||||
import java.util.HashMap;
|
||||
import java.util.Locale;
|
||||
import java.util.Map;
|
||||
import java.util.MissingResourceException;
|
||||
import java.util.ResourceBundle;
|
||||
|
@ -70,7 +71,7 @@ public class MimeTypes
|
|||
_string=s;
|
||||
_buffer=BufferUtil.toBuffer(s);
|
||||
|
||||
int i=s.toLowerCase().indexOf("charset=");
|
||||
int i=s.toLowerCase(Locale.ENGLISH).indexOf("charset=");
|
||||
_charset=(i>0)?Charset.forName(s.substring(i+8)):null;
|
||||
}
|
||||
|
||||
|
|
|
@ -171,6 +171,7 @@ xhtml=application/xhtml+xml
|
|||
xls=application/vnd.ms-excel
|
||||
xml=application/xml
|
||||
xpm=image/x-xpixmap
|
||||
xsd=application/xml
|
||||
xsl=application/xml
|
||||
xslt=application/xslt+xml
|
||||
xul=application/vnd.mozilla.xul+xml
|
||||
|
|
|
@ -21,6 +21,7 @@ package org.eclipse.jetty.http;
|
|||
import java.nio.ByteBuffer;
|
||||
import java.util.Enumeration;
|
||||
import java.util.HashSet;
|
||||
import java.util.Locale;
|
||||
import java.util.Set;
|
||||
|
||||
import org.eclipse.jetty.util.BufferUtil;
|
||||
|
@ -385,7 +386,7 @@ public class HttpFieldsTest
|
|||
{
|
||||
Set<String> s=new HashSet<String>();
|
||||
while(e.hasMoreElements())
|
||||
s.add(e.nextElement().toLowerCase());
|
||||
s.add(e.nextElement().toLowerCase(Locale.ENGLISH));
|
||||
return s;
|
||||
}
|
||||
|
||||
|
|
|
@ -470,6 +470,25 @@ public class HttpParserTest
|
|||
assertTrue(_messageCompleted);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testResponse101WithTransferEncoding() throws Exception
|
||||
{
|
||||
ByteBuffer buffer= BufferUtil.toBuffer(
|
||||
"HTTP/1.1 101 switching protocols\015\012"
|
||||
+ "Transfer-Encoding: chunked\015\012"
|
||||
+ "\015\012");
|
||||
|
||||
Handler handler = new Handler();
|
||||
HttpParser parser= new HttpParser((HttpParser.ResponseHandler)handler);
|
||||
parser.parseNext(buffer);
|
||||
assertEquals("HTTP/1.1", _methodOrVersion);
|
||||
assertEquals("101", _uriOrStatus);
|
||||
assertEquals("switching protocols", _versionOrReason);
|
||||
assertEquals(null,_content);
|
||||
assertTrue(_headerCompleted);
|
||||
assertTrue(_messageCompleted);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSeekEOF() throws Exception
|
||||
{
|
||||
|
|
|
@ -21,38 +21,19 @@ package org.eclipse.jetty.io;
|
|||
import java.io.IOException;
|
||||
import java.net.InetSocketAddress;
|
||||
import java.nio.ByteBuffer;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.concurrent.TimeoutException;
|
||||
import java.util.concurrent.atomic.AtomicReference;
|
||||
|
||||
import org.eclipse.jetty.util.Callback;
|
||||
import org.eclipse.jetty.util.log.Log;
|
||||
import org.eclipse.jetty.util.log.Logger;
|
||||
import org.eclipse.jetty.util.thread.Scheduler;
|
||||
|
||||
public abstract class AbstractEndPoint implements EndPoint
|
||||
public abstract class AbstractEndPoint extends IdleTimeout implements EndPoint
|
||||
{
|
||||
private static final Logger LOG = Log.getLogger(AbstractEndPoint.class);
|
||||
private final long _created=System.currentTimeMillis();
|
||||
private final InetSocketAddress _local;
|
||||
private final InetSocketAddress _remote;
|
||||
|
||||
private final Scheduler _scheduler;
|
||||
private final AtomicReference<Scheduler.Task> _timeout = new AtomicReference<>();
|
||||
private final Runnable _idleTask = new Runnable()
|
||||
{
|
||||
@Override
|
||||
public void run()
|
||||
{
|
||||
long idleLeft=checkIdleTimeout();
|
||||
if (idleLeft>=0)
|
||||
scheduleIdleTimeout(idleLeft > 0 ? idleLeft : getIdleTimeout());
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
private volatile long _idleTimeout;
|
||||
private volatile long _idleTimestamp=System.currentTimeMillis();
|
||||
private volatile Connection _connection;
|
||||
|
||||
private final FillInterest _fillInterest = new FillInterest()
|
||||
|
@ -74,9 +55,9 @@ public abstract class AbstractEndPoint implements EndPoint
|
|||
|
||||
protected AbstractEndPoint(Scheduler scheduler,InetSocketAddress local,InetSocketAddress remote)
|
||||
{
|
||||
super(scheduler);
|
||||
_local=local;
|
||||
_remote=remote;
|
||||
_scheduler=scheduler;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -85,19 +66,6 @@ public abstract class AbstractEndPoint implements EndPoint
|
|||
return _created;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public long getIdleTimeout()
|
||||
{
|
||||
return _idleTimeout;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setIdleTimeout(long idleTimeout)
|
||||
{
|
||||
_idleTimeout = idleTimeout;
|
||||
}
|
||||
|
||||
@Override
|
||||
public InetSocketAddress getLocalAddress()
|
||||
{
|
||||
|
@ -109,17 +77,7 @@ public abstract class AbstractEndPoint implements EndPoint
|
|||
{
|
||||
return _remote;
|
||||
}
|
||||
|
||||
public long getIdleTimestamp()
|
||||
{
|
||||
return _idleTimestamp;
|
||||
}
|
||||
|
||||
protected void notIdle()
|
||||
{
|
||||
_idleTimestamp=System.currentTimeMillis();
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public Connection getConnection()
|
||||
{
|
||||
|
@ -145,6 +103,12 @@ public abstract class AbstractEndPoint implements EndPoint
|
|||
_writeFlusher.onClose();
|
||||
_fillInterest.onClose();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void close()
|
||||
{
|
||||
super.close();
|
||||
}
|
||||
|
||||
@Override
|
||||
public <C> void fillInterested(C context, Callback<C> callback) throws IllegalStateException
|
||||
|
@ -173,56 +137,23 @@ public abstract class AbstractEndPoint implements EndPoint
|
|||
return _writeFlusher;
|
||||
}
|
||||
|
||||
protected void scheduleIdleTimeout(long delay)
|
||||
@Override
|
||||
protected void onIdleExpired(TimeoutException timeout)
|
||||
{
|
||||
Scheduler.Task newTimeout = null;
|
||||
if (isOpen() && delay > 0 && _scheduler!=null)
|
||||
newTimeout = _scheduler.schedule(_idleTask, delay, TimeUnit.MILLISECONDS);
|
||||
Scheduler.Task oldTimeout = _timeout.getAndSet(newTimeout);
|
||||
if (oldTimeout != null)
|
||||
oldTimeout.cancel();
|
||||
}
|
||||
|
||||
protected long checkIdleTimeout()
|
||||
{
|
||||
if (isOpen())
|
||||
if (isOutputShutdown() || _fillInterest.isInterested() || _writeFlusher.isInProgress())
|
||||
{
|
||||
long idleTimestamp = getIdleTimestamp();
|
||||
long idleTimeout = getIdleTimeout();
|
||||
long idleElapsed = System.currentTimeMillis() - idleTimestamp;
|
||||
long idleLeft = idleTimeout - idleElapsed;
|
||||
|
||||
LOG.debug("{} idle timeout check, elapsed: {} ms, remaining: {} ms", this, idleElapsed, idleLeft);
|
||||
|
||||
if (isOutputShutdown() || _fillInterest.isInterested() || _writeFlusher.isInProgress())
|
||||
{
|
||||
if (idleTimestamp != 0 && idleTimeout > 0)
|
||||
{
|
||||
if (idleLeft <= 0)
|
||||
{
|
||||
LOG.debug("{} idle timeout expired", this);
|
||||
|
||||
boolean output_shutdown=isOutputShutdown();
|
||||
TimeoutException timeout = new TimeoutException("Idle timeout expired: " + idleElapsed + "/" + idleTimeout + " ms");
|
||||
_fillInterest.onFail(timeout);
|
||||
_writeFlusher.onFail(timeout);
|
||||
|
||||
if (output_shutdown)
|
||||
close();
|
||||
notIdle();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return idleLeft>=0?idleLeft:0;
|
||||
boolean output_shutdown=isOutputShutdown();
|
||||
_fillInterest.onFail(timeout);
|
||||
_writeFlusher.onFail(timeout);
|
||||
if (output_shutdown)
|
||||
close();
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString()
|
||||
{
|
||||
return String.format("%s@%x{%s<r-l>%s,o=%b,is=%b,os=%b,fi=%s,wf=%s,to=%d}{%s}",
|
||||
return String.format("%s@%x{%s<r-l>%s,o=%b,is=%b,os=%b,fi=%s,wf=%s,it=%d}{%s}",
|
||||
getClass().getSimpleName(),
|
||||
hashCode(),
|
||||
getRemoteAddress(),
|
||||
|
@ -232,7 +163,7 @@ public abstract class AbstractEndPoint implements EndPoint
|
|||
isOutputShutdown(),
|
||||
_fillInterest,
|
||||
_writeFlusher,
|
||||
_idleTimeout,
|
||||
getIdleTimeout(),
|
||||
getConnection());
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,153 @@
|
|||
//
|
||||
// ========================================================================
|
||||
// Copyright (c) 1995-2012 Mort Bay Consulting Pty. Ltd.
|
||||
// ------------------------------------------------------------------------
|
||||
// All rights reserved. This program and the accompanying materials
|
||||
// are made available under the terms of the Eclipse Public License v1.0
|
||||
// and Apache License v2.0 which accompanies this distribution.
|
||||
//
|
||||
// The Eclipse Public License is available at
|
||||
// http://www.eclipse.org/legal/epl-v10.html
|
||||
//
|
||||
// The Apache License v2.0 is available at
|
||||
// http://www.opensource.org/licenses/apache2.0.php
|
||||
//
|
||||
// You may elect to redistribute this code under either of these licenses.
|
||||
// ========================================================================
|
||||
//
|
||||
|
||||
package org.eclipse.jetty.io;
|
||||
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.concurrent.TimeoutException;
|
||||
import java.util.concurrent.atomic.AtomicReference;
|
||||
|
||||
import org.eclipse.jetty.util.log.Log;
|
||||
import org.eclipse.jetty.util.log.Logger;
|
||||
import org.eclipse.jetty.util.thread.Scheduler;
|
||||
|
||||
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
/** An Abstract implementation of an Idle Timeout.
|
||||
*
|
||||
* This implementation is optimised that timeout operations are not cancelled on
|
||||
* every operation. Rather timeout are allowed to expire and a check is then made
|
||||
* to see when the last operation took place. If the idle timeout has not expired,
|
||||
* the timeout is rescheduled for the earliest possible time a timeout could occur.
|
||||
*
|
||||
*/
|
||||
public abstract class IdleTimeout
|
||||
{
|
||||
private static final Logger LOG = Log.getLogger(IdleTimeout.class);
|
||||
private final Scheduler _scheduler;
|
||||
private final AtomicReference<Scheduler.Task> _timeout = new AtomicReference<>();
|
||||
private volatile long _idleTimeout;
|
||||
private volatile long _idleTimestamp=System.currentTimeMillis();
|
||||
|
||||
private final Runnable _idleTask = new Runnable()
|
||||
{
|
||||
@Override
|
||||
public void run()
|
||||
{
|
||||
long idleLeft=checkIdleTimeout();
|
||||
if (idleLeft>=0)
|
||||
scheduleIdleTimeout(idleLeft > 0 ? idleLeft : getIdleTimeout());
|
||||
}
|
||||
};
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
/**
|
||||
* @param scheduler A scheduler used to schedule checks for the idle timeout.
|
||||
*/
|
||||
public IdleTimeout(Scheduler scheduler)
|
||||
{
|
||||
_scheduler=scheduler;
|
||||
}
|
||||
|
||||
public long getIdleTimestamp()
|
||||
{
|
||||
return _idleTimestamp;
|
||||
}
|
||||
|
||||
public long getIdleTimeout()
|
||||
{
|
||||
return _idleTimeout;
|
||||
}
|
||||
|
||||
public void setIdleTimeout(long idleTimeout)
|
||||
{
|
||||
_idleTimeout = idleTimeout;
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
/** This method should be called when non-idle activity has taken place.
|
||||
*/
|
||||
public void notIdle()
|
||||
{
|
||||
_idleTimestamp=System.currentTimeMillis();
|
||||
}
|
||||
|
||||
protected void scheduleIdleTimeout(long delay)
|
||||
{
|
||||
Scheduler.Task newTimeout = null;
|
||||
if (isOpen() && delay > 0 && _scheduler!=null)
|
||||
newTimeout = _scheduler.schedule(_idleTask, delay, TimeUnit.MILLISECONDS);
|
||||
Scheduler.Task oldTimeout = _timeout.getAndSet(newTimeout);
|
||||
if (oldTimeout != null)
|
||||
oldTimeout.cancel();
|
||||
}
|
||||
|
||||
protected void close()
|
||||
{
|
||||
Scheduler.Task oldTimeout = _timeout.getAndSet(null);
|
||||
if (oldTimeout != null)
|
||||
oldTimeout.cancel();
|
||||
}
|
||||
|
||||
protected long checkIdleTimeout()
|
||||
{
|
||||
if (isOpen())
|
||||
{
|
||||
long idleTimestamp = getIdleTimestamp();
|
||||
long idleTimeout = getIdleTimeout();
|
||||
long idleElapsed = System.currentTimeMillis() - idleTimestamp;
|
||||
long idleLeft = idleTimeout - idleElapsed;
|
||||
|
||||
LOG.debug("{} idle timeout check, elapsed: {} ms, remaining: {} ms", this, idleElapsed, idleLeft);
|
||||
|
||||
if (idleTimestamp != 0 && idleTimeout > 0)
|
||||
{
|
||||
if (idleLeft <= 0)
|
||||
{
|
||||
LOG.debug("{} idle timeout expired", this);
|
||||
try
|
||||
{
|
||||
onIdleExpired(new TimeoutException("Idle timeout expired: " + idleElapsed + "/" + idleTimeout + " ms"));
|
||||
}
|
||||
finally
|
||||
{
|
||||
notIdle();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return idleLeft>=0?idleLeft:0;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
/** This abstract method is called when the idle timeout has expired.
|
||||
* @param timeout a TimeoutException
|
||||
*/
|
||||
abstract protected void onIdleExpired(TimeoutException timeout);
|
||||
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
/** This abstract method should be called to check if idle timeouts
|
||||
* should still be checked.
|
||||
* @return True if the entity monitored should still be checked for idle timeouts
|
||||
*/
|
||||
abstract protected boolean isOpen();
|
||||
}
|
|
@ -45,7 +45,6 @@
|
|||
</archive>
|
||||
</configuration>
|
||||
</plugin>
|
||||
<!--
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-assembly-plugin</artifactId>
|
||||
|
@ -63,7 +62,6 @@
|
|||
</execution>
|
||||
</executions>
|
||||
</plugin>
|
||||
-->
|
||||
<!-- always include the sources to be able to prepare the eclipse-jetty-SDK feature
|
||||
with a snapshot. -->
|
||||
<plugin>
|
||||
|
|
|
@ -14,17 +14,4 @@
|
|||
<Arg><SystemProperty name="jetty.home" default="." />/etc/login.conf</Arg>
|
||||
</Call>
|
||||
|
||||
|
||||
<!-- ======================================================== -->
|
||||
<!-- An example JAAS realm setup -->
|
||||
<!-- ======================================================== -->
|
||||
<Call name="addBean">
|
||||
<Arg>
|
||||
<New class="org.eclipse.jetty.jaas.JAASLoginService">
|
||||
<Set name="Name">Test JAAS Realm</Set>
|
||||
<Set name="LoginModuleName">xyz</Set>
|
||||
</New>
|
||||
</Arg>
|
||||
</Call>
|
||||
|
||||
</Configure>
|
|
@ -22,6 +22,7 @@ import java.io.IOException;
|
|||
import java.util.ArrayList;
|
||||
import java.util.Hashtable;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
import java.util.Map;
|
||||
import java.util.Properties;
|
||||
import javax.naming.Context;
|
||||
|
@ -652,12 +653,12 @@ public class LdapLoginModule extends AbstractLoginModule
|
|||
|
||||
public static String convertCredentialJettyToLdap(String encryptedPassword)
|
||||
{
|
||||
if ("MD5:".startsWith(encryptedPassword.toUpperCase()))
|
||||
if ("MD5:".startsWith(encryptedPassword.toUpperCase(Locale.ENGLISH)))
|
||||
{
|
||||
return "{MD5}" + encryptedPassword.substring("MD5:".length(), encryptedPassword.length());
|
||||
}
|
||||
|
||||
if ("CRYPT:".startsWith(encryptedPassword.toUpperCase()))
|
||||
if ("CRYPT:".startsWith(encryptedPassword.toUpperCase(Locale.ENGLISH)))
|
||||
{
|
||||
return "{CRYPT}" + encryptedPassword.substring("CRYPT:".length(), encryptedPassword.length());
|
||||
}
|
||||
|
@ -672,12 +673,12 @@ public class LdapLoginModule extends AbstractLoginModule
|
|||
return encryptedPassword;
|
||||
}
|
||||
|
||||
if ("{MD5}".startsWith(encryptedPassword.toUpperCase()))
|
||||
if ("{MD5}".startsWith(encryptedPassword.toUpperCase(Locale.ENGLISH)))
|
||||
{
|
||||
return "MD5:" + encryptedPassword.substring("{MD5}".length(), encryptedPassword.length());
|
||||
}
|
||||
|
||||
if ("{CRYPT}".startsWith(encryptedPassword.toUpperCase()))
|
||||
if ("{CRYPT}".startsWith(encryptedPassword.toUpperCase(Locale.ENGLISH)))
|
||||
{
|
||||
return "CRYPT:" + encryptedPassword.substring("{CRYPT}".length(), encryptedPassword.length());
|
||||
}
|
||||
|
|
|
@ -20,6 +20,7 @@ package org.eclipse.jetty.jmx;
|
|||
|
||||
import java.io.IOException;
|
||||
import java.util.HashMap;
|
||||
import java.util.Locale;
|
||||
import java.util.Map;
|
||||
import java.util.WeakHashMap;
|
||||
|
||||
|
@ -164,7 +165,7 @@ public class MBeanContainer implements Container.InheritedListener, Dumpable
|
|||
domain = obj.getClass().getPackage().getName();
|
||||
|
||||
|
||||
String type = obj.getClass().getName().toLowerCase();
|
||||
String type = obj.getClass().getName().toLowerCase(Locale.ENGLISH);
|
||||
int dot = type.lastIndexOf('.');
|
||||
if (dot >= 0)
|
||||
type = type.substring(dot + 1);
|
||||
|
|
|
@ -30,6 +30,7 @@ import java.util.HashMap;
|
|||
import java.util.HashSet;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import javax.management.Attribute;
|
||||
|
@ -622,7 +623,7 @@ public class ObjectMBean implements DynamicMBean
|
|||
convert = true;
|
||||
}
|
||||
|
||||
String uName = name.substring(0, 1).toUpperCase() + name.substring(1);
|
||||
String uName = name.substring(0, 1).toUpperCase(Locale.ENGLISH) + name.substring(1);
|
||||
Class<?> oClass = onMBean ? this.getClass() : _managed.getClass();
|
||||
|
||||
LOG.debug("defineAttribute {} {}:{}:{}:{}",name,onMBean,readonly,oClass,description);
|
||||
|
@ -862,7 +863,7 @@ public class ObjectMBean implements DynamicMBean
|
|||
variableName = variableName.substring(2);
|
||||
}
|
||||
|
||||
variableName = variableName.substring(0,1).toLowerCase() + variableName.substring(1);
|
||||
variableName = variableName.substring(0,1).toLowerCase(Locale.ENGLISH) + variableName.substring(1);
|
||||
|
||||
return variableName;
|
||||
}
|
||||
|
|
|
@ -483,7 +483,7 @@ public abstract class AbstractJettyMojo extends AbstractMojo
|
|||
if (connectors == null || connectors.length == 0)
|
||||
{
|
||||
//if a SystemProperty -Djetty.port=<portnum> has been supplied, use that as the default port
|
||||
this.connectors = new Connector[] { this.server.createDefaultConnector(server, System.getProperty(PORT_SYSPROPERTY, null)) };
|
||||
this.connectors = new Connector[] { this.server.createDefaultConnector(System.getProperty(PORT_SYSPROPERTY, null)) };
|
||||
this.server.setConnectors(this.connectors);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -16,58 +16,55 @@
|
|||
// ========================================================================
|
||||
//
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
package org.eclipse.jetty.maven.plugin;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
public class ConsoleScanner extends Thread
|
||||
public class ConsoleScanner extends Thread
|
||||
{
|
||||
|
||||
|
||||
private final AbstractJettyMojo mojo;
|
||||
|
||||
public ConsoleScanner(AbstractJettyMojo mojo)
|
||||
|
||||
public ConsoleScanner(AbstractJettyMojo mojo)
|
||||
{
|
||||
this.mojo = mojo;
|
||||
setName("Console scanner");
|
||||
setDaemon(true);
|
||||
}
|
||||
|
||||
public void run()
|
||||
{
|
||||
try
|
||||
|
||||
public void run()
|
||||
{
|
||||
try
|
||||
{
|
||||
while (true)
|
||||
while (true)
|
||||
{
|
||||
checkSystemInput();
|
||||
getSomeSleep();
|
||||
}
|
||||
}
|
||||
catch (IOException e)
|
||||
}
|
||||
catch (IOException e)
|
||||
{
|
||||
mojo.getLog().warn(e);
|
||||
}
|
||||
}
|
||||
|
||||
private void getSomeSleep()
|
||||
|
||||
private void getSomeSleep()
|
||||
{
|
||||
try
|
||||
try
|
||||
{
|
||||
Thread.sleep(500);
|
||||
}
|
||||
catch (InterruptedException e)
|
||||
}
|
||||
catch (InterruptedException e)
|
||||
{
|
||||
mojo.getLog().debug(e);
|
||||
}
|
||||
}
|
||||
|
||||
private void checkSystemInput() throws IOException
|
||||
{
|
||||
|
||||
private void checkSystemInput() throws IOException
|
||||
{
|
||||
while (System.in.available() > 0) {
|
||||
int inputByte = System.in.read();
|
||||
if (inputByte >= 0)
|
||||
if (inputByte >= 0)
|
||||
{
|
||||
char c = (char)inputByte;
|
||||
if (c == '\n') {
|
||||
|
@ -76,12 +73,12 @@ public class ConsoleScanner extends Thread
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Skip buffered bytes of system console.
|
||||
*/
|
||||
private void clearInputBuffer()
|
||||
private void clearInputBuffer()
|
||||
{
|
||||
try
|
||||
{
|
||||
|
@ -101,9 +98,9 @@ public class ConsoleScanner extends Thread
|
|||
catch (IOException e)
|
||||
{
|
||||
mojo.getLog().warn("Error discarding console input buffer", e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private void restartWebApp()
|
||||
{
|
||||
try
|
||||
|
|
|
@ -1,46 +1,45 @@
|
|||
//
|
||||
// ========================================================================
|
||||
// Copyright (c) 1995-2012 Mort Bay Consulting Pty. Ltd.
|
||||
// ------------------------------------------------------------------------
|
||||
// All rights reserved. This program and the accompanying materials
|
||||
// are made available under the terms of the Eclipse Public License v1.0
|
||||
// and Apache License v2.0 which accompanies this distribution.
|
||||
//
|
||||
// The Eclipse Public License is available at
|
||||
// http://www.eclipse.org/legal/epl-v10.html
|
||||
//
|
||||
// The Apache License v2.0 is available at
|
||||
// http://www.opensource.org/licenses/apache2.0.php
|
||||
//
|
||||
// You may elect to redistribute this code under either of these licenses.
|
||||
// ========================================================================
|
||||
//
|
||||
|
||||
package org.eclipse.jetty.maven.plugin;
|
||||
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* This goal is used to run Jetty with a pre-assembled war.
|
||||
* </p>
|
||||
* <p>
|
||||
* It accepts exactly the same options as the <a href="run-war-mojo.html">run-war</a> goal.
|
||||
* However, it doesn't assume that the current artifact is a
|
||||
* webapp and doesn't try to assemble it into a war before its execution.
|
||||
* So using it makes sense only when used in conjunction with the
|
||||
* <a href="run-war-mojo.html#webApp">webApp</a> configuration parameter pointing to a pre-built WAR.
|
||||
* </p>
|
||||
* <p>
|
||||
* This goal is useful e.g. for launching a web app in Jetty as a target for unit-tested
|
||||
* HTTP client components.
|
||||
* </p>
|
||||
*
|
||||
* @goal deploy-war
|
||||
* @requiresDependencyResolution runtime
|
||||
* @execute phase="validate"
|
||||
* @description Deploy a pre-assembled war
|
||||
*
|
||||
*/
|
||||
public class JettyDeployWar extends JettyRunWarMojo
|
||||
{
|
||||
}
|
||||
//
|
||||
// ========================================================================
|
||||
// Copyright (c) 1995-2012 Mort Bay Consulting Pty. Ltd.
|
||||
// ------------------------------------------------------------------------
|
||||
// All rights reserved. This program and the accompanying materials
|
||||
// are made available under the terms of the Eclipse Public License v1.0
|
||||
// and Apache License v2.0 which accompanies this distribution.
|
||||
//
|
||||
// The Eclipse Public License is available at
|
||||
// http://www.eclipse.org/legal/epl-v10.html
|
||||
//
|
||||
// The Apache License v2.0 is available at
|
||||
// http://www.opensource.org/licenses/apache2.0.php
|
||||
//
|
||||
// You may elect to redistribute this code under either of these licenses.
|
||||
// ========================================================================
|
||||
//
|
||||
|
||||
package org.eclipse.jetty.maven.plugin;
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* This goal is used to run Jetty with a pre-assembled war.
|
||||
* </p>
|
||||
* <p>
|
||||
* It accepts exactly the same options as the <a href="run-war-mojo.html">run-war</a> goal.
|
||||
* However, it doesn't assume that the current artifact is a
|
||||
* webapp and doesn't try to assemble it into a war before its execution.
|
||||
* So using it makes sense only when used in conjunction with the
|
||||
* <a href="run-war-mojo.html#webApp">webApp</a> configuration parameter pointing to a pre-built WAR.
|
||||
* </p>
|
||||
* <p>
|
||||
* This goal is useful e.g. for launching a web app in Jetty as a target for unit-tested
|
||||
* HTTP client components.
|
||||
* </p>
|
||||
*
|
||||
* @goal deploy-war
|
||||
* @requiresDependencyResolution runtime
|
||||
* @execute phase="validate"
|
||||
* @description Deploy a pre-assembled war
|
||||
*
|
||||
*/
|
||||
public class JettyDeployWar extends JettyRunWarMojo
|
||||
{
|
||||
}
|
||||
|
|
|
@ -18,23 +18,33 @@
|
|||
|
||||
package org.eclipse.jetty.maven.plugin;
|
||||
|
||||
import java.io.BufferedInputStream;
|
||||
import java.io.BufferedOutputStream;
|
||||
import java.io.BufferedReader;
|
||||
import java.io.BufferedWriter;
|
||||
import java.io.File;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.FileWriter;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.InputStreamReader;
|
||||
import java.io.LineNumberReader;
|
||||
import java.net.MalformedURLException;
|
||||
import java.net.URL;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.HashSet;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
import java.util.Map;
|
||||
import java.util.Properties;
|
||||
import java.util.Random;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.CountDownLatch;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
import org.apache.maven.artifact.Artifact;
|
||||
import org.apache.maven.plugin.AbstractMojo;
|
||||
|
@ -42,7 +52,10 @@ import org.apache.maven.plugin.MojoExecutionException;
|
|||
import org.apache.maven.plugin.MojoFailureException;
|
||||
import org.apache.maven.plugin.descriptor.PluginDescriptor;
|
||||
import org.apache.maven.project.MavenProject;
|
||||
import org.codehaus.plexus.component.repository.ComponentDependency;
|
||||
import org.eclipse.jetty.server.RequestLog;
|
||||
import org.eclipse.jetty.util.IO;
|
||||
import org.eclipse.jetty.util.resource.Resource;
|
||||
|
||||
|
||||
/**
|
||||
|
@ -64,7 +77,7 @@ import org.eclipse.jetty.util.IO;
|
|||
* There is a <a href="run-war-mojo.html">reference guide</a> to the configuration parameters for this plugin, and more detailed information
|
||||
* with examples in the <a href="http://docs.codehaus.org/display/JETTY/Maven+Jetty+Plugin/">Configuration Guide</a>.
|
||||
* </p>
|
||||
*
|
||||
*
|
||||
* @goal run-forked
|
||||
* @requiresDependencyResolution compile+runtime
|
||||
* @execute phase="test-compile"
|
||||
|
@ -72,17 +85,17 @@ import org.eclipse.jetty.util.IO;
|
|||
*
|
||||
*/
|
||||
public class JettyRunForkedMojo extends AbstractMojo
|
||||
{
|
||||
{
|
||||
public String PORT_SYSPROPERTY = "jetty.port";
|
||||
|
||||
|
||||
/**
|
||||
* Whether or not to include dependencies on the plugin's classpath with <scope>provided</scope>
|
||||
* Use WITH CAUTION as you may wind up with duplicate jars/classes.
|
||||
* @parameter default-value="false"
|
||||
*/
|
||||
protected boolean useProvidedScope;
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* The maven project.
|
||||
*
|
||||
|
@ -91,9 +104,9 @@ public class JettyRunForkedMojo extends AbstractMojo
|
|||
* @readonly
|
||||
*/
|
||||
private MavenProject project;
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* If true, the <testOutputDirectory>
|
||||
* and the dependencies of <scope>test<scope>
|
||||
|
@ -101,27 +114,27 @@ public class JettyRunForkedMojo extends AbstractMojo
|
|||
* @parameter alias="useTestClasspath" default-value="false"
|
||||
*/
|
||||
private boolean useTestScope;
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* The default location of the web.xml file. Will be used
|
||||
* if <webAppConfig><descriptor> is not set.
|
||||
*
|
||||
*
|
||||
* @parameter expression="${basedir}/src/main/webapp/WEB-INF/web.xml"
|
||||
* @readonly
|
||||
*/
|
||||
private String webXml;
|
||||
|
||||
|
||||
/**
|
||||
* The target directory
|
||||
*
|
||||
*
|
||||
* @parameter expression="${project.build.directory}"
|
||||
* @required
|
||||
* @readonly
|
||||
*/
|
||||
protected File target;
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* The temporary directory to use for the webapp.
|
||||
* Defaults to target/tmp
|
||||
|
@ -132,26 +145,26 @@ public class JettyRunForkedMojo extends AbstractMojo
|
|||
*/
|
||||
protected File tmpDirectory;
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* The directory containing generated classes.
|
||||
*
|
||||
* @parameter expression="${project.build.outputDirectory}"
|
||||
* @required
|
||||
*
|
||||
*
|
||||
*/
|
||||
private File classesDirectory;
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* The directory containing generated test classes.
|
||||
*
|
||||
*
|
||||
* @parameter expression="${project.build.testOutputDirectory}"
|
||||
* @required
|
||||
*/
|
||||
private File testClassesDirectory;
|
||||
|
||||
|
||||
/**
|
||||
* Root directory for all html/jsp etc files
|
||||
*
|
||||
|
@ -159,34 +172,34 @@ public class JettyRunForkedMojo extends AbstractMojo
|
|||
*
|
||||
*/
|
||||
private File webAppSourceDirectory;
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Directories that contain static resources
|
||||
* for the webapp. Optional.
|
||||
*
|
||||
*
|
||||
* @parameter
|
||||
*/
|
||||
private File[] resourceBases;
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* If true, the webAppSourceDirectory will be first on the list of
|
||||
* resources that form the resource base for the webapp. If false,
|
||||
* If true, the webAppSourceDirectory will be first on the list of
|
||||
* resources that form the resource base for the webapp. If false,
|
||||
* it will be last.
|
||||
*
|
||||
*
|
||||
* @parameter default-value="true"
|
||||
*/
|
||||
private boolean baseAppFirst;
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Location of jetty xml configuration files whose contents
|
||||
* Location of jetty xml configuration files whose contents
|
||||
* will be applied before any plugin configuration. Optional.
|
||||
* @parameter
|
||||
*/
|
||||
private String jettyXml;
|
||||
|
||||
|
||||
/**
|
||||
* The context path for the webapp. Defaults to the
|
||||
* name of the webapp's artifact.
|
||||
|
@ -205,71 +218,71 @@ public class JettyRunForkedMojo extends AbstractMojo
|
|||
*/
|
||||
private String contextXml;
|
||||
|
||||
|
||||
/**
|
||||
|
||||
/**
|
||||
* @parameter expression="${jetty.skip}" default-value="false"
|
||||
*/
|
||||
private boolean skip;
|
||||
|
||||
/**
|
||||
* Port to listen to stop jetty on executing -DSTOP.PORT=<stopPort>
|
||||
* Port to listen to stop jetty on executing -DSTOP.PORT=<stopPort>
|
||||
* -DSTOP.KEY=<stopKey> -jar start.jar --stop
|
||||
* @parameter
|
||||
* @required
|
||||
*/
|
||||
protected int stopPort;
|
||||
|
||||
|
||||
/**
|
||||
* Key to provide when stopping jetty on executing java -DSTOP.KEY=<stopKey>
|
||||
* Key to provide when stopping jetty on executing java -DSTOP.KEY=<stopKey>
|
||||
* -DSTOP.PORT=<stopPort> -jar start.jar --stop
|
||||
* @parameter
|
||||
* @required
|
||||
*/
|
||||
protected String stopKey;
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Arbitrary jvm args to pass to the forked process
|
||||
* @parameter
|
||||
*/
|
||||
private String jvmArgs;
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* @parameter expression="${plugin.artifacts}"
|
||||
* @readonly
|
||||
*/
|
||||
private List pluginArtifacts;
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* @parameter expression="${plugin}"
|
||||
* @readonly
|
||||
*/
|
||||
private PluginDescriptor plugin;
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* @parameter expression="true" default-value="true"
|
||||
*/
|
||||
private boolean waitForChild;
|
||||
|
||||
|
||||
|
||||
private Process forkedProcess;
|
||||
|
||||
|
||||
private Random random;
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
public class ShutdownThread extends Thread
|
||||
{
|
||||
public ShutdownThread()
|
||||
{
|
||||
super("RunForkedShutdown");
|
||||
}
|
||||
|
||||
|
||||
public void run ()
|
||||
{
|
||||
if (forkedProcess != null && waitForChild)
|
||||
|
@ -278,7 +291,7 @@ public class JettyRunForkedMojo extends AbstractMojo
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @see org.apache.maven.plugin.Mojo#execute()
|
||||
*/
|
||||
|
@ -295,20 +308,20 @@ public class JettyRunForkedMojo extends AbstractMojo
|
|||
random = new Random();
|
||||
startJettyRunner();
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
public List<String> getProvidedJars() throws MojoExecutionException
|
||||
{
|
||||
{
|
||||
//if we are configured to include the provided dependencies on the plugin's classpath
|
||||
//(which mimics being on jetty's classpath vs being on the webapp's classpath), we first
|
||||
//try and filter out ones that will clash with jars that are plugin dependencies, then
|
||||
//create a new classloader that we setup in the parent chain.
|
||||
if (useProvidedScope)
|
||||
{
|
||||
|
||||
List<String> provided = new ArrayList<String>();
|
||||
|
||||
List<String> provided = new ArrayList<String>();
|
||||
for ( Iterator<Artifact> iter = project.getArtifacts().iterator(); iter.hasNext(); )
|
||||
{
|
||||
{
|
||||
Artifact artifact = iter.next();
|
||||
if (Artifact.SCOPE_PROVIDED.equals(artifact.getScope()) && !isPluginArtifact(artifact))
|
||||
{
|
||||
|
@ -322,16 +335,16 @@ public class JettyRunForkedMojo extends AbstractMojo
|
|||
else
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
public File prepareConfiguration() throws MojoExecutionException
|
||||
{
|
||||
try
|
||||
{
|
||||
{
|
||||
//work out the configuration based on what is configured in the pom
|
||||
File propsFile = new File (target, "fork.props");
|
||||
if (propsFile.exists())
|
||||
propsFile.delete();
|
||||
propsFile.delete();
|
||||
|
||||
propsFile.createNewFile();
|
||||
//propsFile.deleteOnExit();
|
||||
|
@ -358,9 +371,9 @@ public class JettyRunForkedMojo extends AbstractMojo
|
|||
//sort out base dir of webapp
|
||||
if (webAppSourceDirectory != null)
|
||||
props.put("base.dir", webAppSourceDirectory.getAbsolutePath());
|
||||
|
||||
|
||||
//sort out the resource base directories of the webapp
|
||||
StringBuilder builder = new StringBuilder();
|
||||
StringBuilder builder = new StringBuilder();
|
||||
if (baseAppFirst)
|
||||
{
|
||||
add((webAppSourceDirectory==null?null:webAppSourceDirectory.getAbsolutePath()), builder);
|
||||
|
@ -371,7 +384,7 @@ public class JettyRunForkedMojo extends AbstractMojo
|
|||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
{
|
||||
if (resourceBases != null)
|
||||
{
|
||||
for (File resDir:resourceBases)
|
||||
|
@ -380,7 +393,7 @@ public class JettyRunForkedMojo extends AbstractMojo
|
|||
add((webAppSourceDirectory==null?null:webAppSourceDirectory.getAbsolutePath()), builder);
|
||||
}
|
||||
props.put("res.dirs", builder.toString());
|
||||
|
||||
|
||||
|
||||
//web-inf classes
|
||||
List<File> classDirs = getClassesDirs();
|
||||
|
@ -397,7 +410,7 @@ public class JettyRunForkedMojo extends AbstractMojo
|
|||
{
|
||||
props.put("classes.dir", classesDirectory.getAbsolutePath());
|
||||
}
|
||||
|
||||
|
||||
if (useTestScope && testClassesDirectory != null)
|
||||
{
|
||||
props.put("testClasses.dir", testClassesDirectory.getAbsolutePath());
|
||||
|
@ -435,7 +448,7 @@ public class JettyRunForkedMojo extends AbstractMojo
|
|||
throw new MojoExecutionException("Prepare webapp configuration", e);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private void add (String string, StringBuilder builder)
|
||||
{
|
||||
if (string == null)
|
||||
|
@ -448,62 +461,62 @@ public class JettyRunForkedMojo extends AbstractMojo
|
|||
private List<File> getClassesDirs ()
|
||||
{
|
||||
List<File> classesDirs = new ArrayList<File>();
|
||||
|
||||
|
||||
//if using the test classes, make sure they are first
|
||||
//on the list
|
||||
if (useTestScope && (testClassesDirectory != null))
|
||||
classesDirs.add(testClassesDirectory);
|
||||
|
||||
|
||||
if (classesDirectory != null)
|
||||
classesDirs.add(classesDirectory);
|
||||
|
||||
|
||||
return classesDirs;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
private List<File> getOverlays()
|
||||
throws MalformedURLException, IOException
|
||||
{
|
||||
List<File> overlays = new ArrayList<File>();
|
||||
for ( Iterator<Artifact> iter = project.getArtifacts().iterator(); iter.hasNext(); )
|
||||
{
|
||||
Artifact artifact = (Artifact) iter.next();
|
||||
|
||||
Artifact artifact = (Artifact) iter.next();
|
||||
|
||||
if (artifact.getType().equals("war"))
|
||||
overlays.add(artifact.getFile());
|
||||
}
|
||||
|
||||
return overlays;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
private List<File> getDependencyFiles ()
|
||||
{
|
||||
List<File> dependencyFiles = new ArrayList<File>();
|
||||
|
||||
|
||||
for ( Iterator<Artifact> iter = project.getArtifacts().iterator(); iter.hasNext(); )
|
||||
{
|
||||
Artifact artifact = (Artifact) iter.next();
|
||||
|
||||
if (((!Artifact.SCOPE_PROVIDED.equals(artifact.getScope())) && (!Artifact.SCOPE_TEST.equals( artifact.getScope())))
|
||||
|
||||
if (((!Artifact.SCOPE_PROVIDED.equals(artifact.getScope())) && (!Artifact.SCOPE_TEST.equals( artifact.getScope())))
|
||||
||
|
||||
(useTestScope && Artifact.SCOPE_TEST.equals( artifact.getScope())))
|
||||
{
|
||||
dependencyFiles.add(artifact.getFile());
|
||||
getLog().debug( "Adding artifact " + artifact.getFile().getName() + " for WEB-INF/lib " );
|
||||
getLog().debug( "Adding artifact " + artifact.getFile().getName() + " for WEB-INF/lib " );
|
||||
}
|
||||
}
|
||||
|
||||
return dependencyFiles;
|
||||
|
||||
return dependencyFiles;
|
||||
}
|
||||
|
||||
|
||||
public boolean isPluginArtifact(Artifact artifact)
|
||||
{
|
||||
if (pluginArtifacts == null || pluginArtifacts.isEmpty())
|
||||
return false;
|
||||
|
||||
|
||||
boolean isPluginArtifact = false;
|
||||
for (Iterator<Artifact> iter = pluginArtifacts.iterator(); iter.hasNext() && !isPluginArtifact; )
|
||||
{
|
||||
|
@ -512,18 +525,18 @@ public class JettyRunForkedMojo extends AbstractMojo
|
|||
if (pluginArtifact.getGroupId().equals(artifact.getGroupId()) && pluginArtifact.getArtifactId().equals(artifact.getArtifactId()))
|
||||
isPluginArtifact = true;
|
||||
}
|
||||
|
||||
|
||||
return isPluginArtifact;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
private Set<Artifact> getExtraJars()
|
||||
throws Exception
|
||||
{
|
||||
Set<Artifact> extraJars = new HashSet<Artifact>();
|
||||
|
||||
|
||||
|
||||
|
||||
List l = pluginArtifacts;
|
||||
Artifact pluginArtifact = null;
|
||||
|
||||
|
@ -531,7 +544,7 @@ public class JettyRunForkedMojo extends AbstractMojo
|
|||
{
|
||||
Iterator itor = l.iterator();
|
||||
while (itor.hasNext() && pluginArtifact == null)
|
||||
{
|
||||
{
|
||||
Artifact a = (Artifact)itor.next();
|
||||
if (a.getArtifactId().equals(plugin.getArtifactId())) //get the jetty-maven-plugin jar
|
||||
{
|
||||
|
@ -543,18 +556,18 @@ public class JettyRunForkedMojo extends AbstractMojo
|
|||
return extraJars;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
public void startJettyRunner() throws MojoExecutionException
|
||||
{
|
||||
{
|
||||
try
|
||||
{
|
||||
|
||||
|
||||
File props = prepareConfiguration();
|
||||
|
||||
|
||||
List<String> cmd = new ArrayList<String>();
|
||||
cmd.add(getJavaBin());
|
||||
|
||||
|
||||
if (jvmArgs != null)
|
||||
{
|
||||
String[] args = jvmArgs.split(" ");
|
||||
|
@ -564,7 +577,7 @@ public class JettyRunForkedMojo extends AbstractMojo
|
|||
cmd.add(args[i].trim());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
String classPath = getClassPath();
|
||||
if (classPath != null && classPath.length() > 0)
|
||||
{
|
||||
|
@ -572,7 +585,7 @@ public class JettyRunForkedMojo extends AbstractMojo
|
|||
cmd.add(classPath);
|
||||
}
|
||||
cmd.add(Starter.class.getCanonicalName());
|
||||
|
||||
|
||||
if (stopPort > 0 && stopKey != null)
|
||||
{
|
||||
cmd.add("--stop-port");
|
||||
|
@ -585,26 +598,26 @@ public class JettyRunForkedMojo extends AbstractMojo
|
|||
cmd.add("--jetty-xml");
|
||||
cmd.add(jettyXml);
|
||||
}
|
||||
|
||||
|
||||
if (contextXml != null)
|
||||
{
|
||||
cmd.add("--context-xml");
|
||||
cmd.add(contextXml);
|
||||
}
|
||||
|
||||
|
||||
cmd.add("--props");
|
||||
cmd.add(props.getAbsolutePath());
|
||||
|
||||
|
||||
String token = createToken();
|
||||
cmd.add("--token");
|
||||
cmd.add(token);
|
||||
|
||||
|
||||
ProcessBuilder builder = new ProcessBuilder(cmd);
|
||||
builder.directory(project.getBasedir());
|
||||
|
||||
|
||||
if (PluginLog.getLog().isDebugEnabled())
|
||||
PluginLog.getLog().debug(Arrays.toString(cmd.toArray()));
|
||||
|
||||
|
||||
forkedProcess = builder.start();
|
||||
PluginLog.getLog().info("Forked process starting");
|
||||
|
||||
|
@ -612,7 +625,7 @@ public class JettyRunForkedMojo extends AbstractMojo
|
|||
{
|
||||
startPump("STDOUT",forkedProcess.getInputStream());
|
||||
startPump("STDERR",forkedProcess.getErrorStream());
|
||||
int exitcode = forkedProcess.waitFor();
|
||||
int exitcode = forkedProcess.waitFor();
|
||||
PluginLog.getLog().info("Forked execution exit: "+exitcode);
|
||||
}
|
||||
else
|
||||
|
@ -652,20 +665,20 @@ public class JettyRunForkedMojo extends AbstractMojo
|
|||
{
|
||||
if (forkedProcess != null && waitForChild)
|
||||
forkedProcess.destroy();
|
||||
|
||||
|
||||
throw new MojoExecutionException("Failed to start Jetty within time limit");
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
if (forkedProcess != null && waitForChild)
|
||||
forkedProcess.destroy();
|
||||
|
||||
|
||||
throw new MojoExecutionException("Failed to create Jetty process", ex);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
public String getClassPath() throws Exception
|
||||
{
|
||||
StringBuilder classPath = new StringBuilder();
|
||||
|
@ -682,16 +695,16 @@ public class JettyRunForkedMojo extends AbstractMojo
|
|||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//Any jars that we need from the plugin environment (like the ones containing Starter class)
|
||||
Set<Artifact> extraJars = getExtraJars();
|
||||
for (Artifact a:extraJars)
|
||||
{
|
||||
{
|
||||
classPath.append(File.pathSeparator);
|
||||
classPath.append(a.getFile().getAbsolutePath());
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
//Any jars that we need from the project's dependencies because we're useProvided
|
||||
List<String> providedJars = getProvidedJars();
|
||||
if (providedJars != null && !providedJars.isEmpty())
|
||||
|
@ -703,7 +716,7 @@ public class JettyRunForkedMojo extends AbstractMojo
|
|||
if (getLog().isDebugEnabled()) getLog().debug("Adding provided jar: "+jar);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
return classPath.toString();
|
||||
}
|
||||
|
||||
|
@ -724,7 +737,7 @@ public class JettyRunForkedMojo extends AbstractMojo
|
|||
|
||||
return "java";
|
||||
}
|
||||
|
||||
|
||||
public static String fileSeparators(String path)
|
||||
{
|
||||
StringBuilder ret = new StringBuilder();
|
||||
|
@ -759,13 +772,13 @@ public class JettyRunForkedMojo extends AbstractMojo
|
|||
return ret.toString();
|
||||
}
|
||||
|
||||
|
||||
|
||||
private String createToken ()
|
||||
{
|
||||
return Long.toString(random.nextLong()^System.currentTimeMillis(), 36).toUpperCase();
|
||||
return Long.toString(random.nextLong()^System.currentTimeMillis(), 36).toUpperCase(Locale.ENGLISH);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
private void startPump(String mode, InputStream inputStream)
|
||||
{
|
||||
ConsoleStreamer pump = new ConsoleStreamer(mode,inputStream);
|
||||
|
@ -774,7 +787,7 @@ public class JettyRunForkedMojo extends AbstractMojo
|
|||
thread.start();
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
|
|
|
@ -63,6 +63,9 @@ import org.eclipse.jetty.webapp.WebAppContext;
|
|||
*/
|
||||
public class JettyRunMojo extends AbstractJettyMojo
|
||||
{
|
||||
public static final String DEFAULT_WEBAPP_SRC = "src"+File.separator+"main"+File.separator+"webapp";
|
||||
|
||||
|
||||
/**
|
||||
* If true, the <testOutputDirectory>
|
||||
* and the dependencies of <scope>test<scope>
|
||||
|
@ -134,12 +137,13 @@ public class JettyRunMojo extends AbstractJettyMojo
|
|||
*/
|
||||
private List<File> extraScanTargets;
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Verify the configuration given in the pom.
|
||||
*
|
||||
* @see org.eclipse.jetty.maven.plugin.AbstractJettyMojo#checkPomConfiguration()
|
||||
* @see org.mortbay.jetty.plugin.AbstractJettyMojo#checkPomConfiguration()
|
||||
*/
|
||||
public void checkPomConfiguration () throws MojoExecutionException
|
||||
{
|
||||
|
@ -147,9 +151,10 @@ public class JettyRunMojo extends AbstractJettyMojo
|
|||
try
|
||||
{
|
||||
if ((getWebAppSourceDirectory() == null) || !getWebAppSourceDirectory().exists())
|
||||
{
|
||||
webAppSourceDirectory = new File (project.getBasedir(), "src"+File.separator+"main"+File.separator+"webapp");
|
||||
getLog().info("webAppSourceDirectory "+getWebAppSourceDirectory() +" does not exist. Defaulting to "+webAppSourceDirectory.getAbsolutePath());
|
||||
{
|
||||
File defaultWebAppSrcDir = new File (project.getBasedir(), DEFAULT_WEBAPP_SRC);
|
||||
getLog().info("webAppSourceDirectory"+(getWebAppSourceDirectory()==null?" not set.":" does not exist.")+" Defaulting to "+defaultWebAppSrcDir.getAbsolutePath());
|
||||
webAppSourceDirectory = defaultWebAppSrcDir;
|
||||
}
|
||||
else
|
||||
getLog().info( "Webapp source directory = " + getWebAppSourceDirectory().getCanonicalPath());
|
||||
|
@ -441,6 +446,7 @@ public class JettyRunMojo extends AbstractJettyMojo
|
|||
for ( Iterator<Artifact> iter = projectArtifacts.iterator(); iter.hasNext(); )
|
||||
{
|
||||
Artifact artifact = (Artifact) iter.next();
|
||||
|
||||
// Include runtime and compile time libraries, and possibly test libs too
|
||||
if(artifact.getType().equals("war"))
|
||||
{
|
||||
|
@ -448,6 +454,7 @@ public class JettyRunMojo extends AbstractJettyMojo
|
|||
{
|
||||
Resource r=Resource.newResource("jar:"+Resource.toURL(artifact.getFile()).toString()+"!/");
|
||||
overlays.add(r);
|
||||
getLog().info("Adding overlay for war project artifact "+artifact.getId());
|
||||
getExtraScanTargets().add(artifact.getFile());
|
||||
}
|
||||
catch(Exception e)
|
||||
|
|
|
@ -25,19 +25,21 @@ import java.util.List;
|
|||
import org.apache.maven.plugin.MojoExecutionException;
|
||||
import org.apache.maven.plugin.MojoFailureException;
|
||||
import org.eclipse.jetty.util.Scanner;
|
||||
import org.eclipse.jetty.util.resource.Resource;
|
||||
import org.eclipse.jetty.xml.XmlConfiguration;
|
||||
|
||||
/**
|
||||
*
|
||||
*
|
||||
* <p>
|
||||
* This goal is used to assemble your webapp into an exploded war and automatically deploy it to Jetty.
|
||||
* </p>
|
||||
* <p>
|
||||
* Once invoked, the plugin can be configured to run continuously, scanning for changes in the pom.xml and
|
||||
* to WEB-INF/web.xml, WEB-INF/classes or WEB-INF/lib and hot redeploy when a change is detected.
|
||||
* Once invoked, the plugin can be configured to run continuously, scanning for changes in the pom.xml and
|
||||
* to WEB-INF/web.xml, WEB-INF/classes or WEB-INF/lib and hot redeploy when a change is detected.
|
||||
* </p>
|
||||
* <p>
|
||||
* You may also specify the location of a jetty.xml file whose contents will be applied before any plugin configuration.
|
||||
* This can be used, for example, to deploy a static webapp that is not part of your maven build.
|
||||
* This can be used, for example, to deploy a static webapp that is not part of your maven build.
|
||||
* </p>
|
||||
* <p>
|
||||
* There is a <a href="run-exploded-mojo.html">reference guide</a> to the configuration parameters for this plugin, and more detailed information
|
||||
|
@ -51,24 +53,24 @@ import org.eclipse.jetty.util.Scanner;
|
|||
public class JettyRunWarExplodedMojo extends AbstractJettyMojo
|
||||
{
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* The location of the war file.
|
||||
*
|
||||
*
|
||||
* @parameter alias="webApp" expression="${project.build.directory}/${project.build.finalName}"
|
||||
* @required
|
||||
*/
|
||||
private File war;
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
*
|
||||
* @see org.eclipse.jetty.maven.plugin.AbstractJettyMojo#checkPomConfiguration()
|
||||
*
|
||||
* @see org.mortbay.jetty.plugin.AbstractJettyMojo#checkPomConfiguration()
|
||||
*/
|
||||
public void checkPomConfiguration() throws MojoExecutionException
|
||||
{
|
||||
|
@ -76,7 +78,7 @@ public class JettyRunWarExplodedMojo extends AbstractJettyMojo
|
|||
}
|
||||
|
||||
/**
|
||||
* @see org.eclipse.jetty.maven.plugin.AbstractJettyMojo#configureScanner()
|
||||
* @see org.mortbay.jetty.plugin.AbstractJettyMojo#configureScanner()
|
||||
*/
|
||||
public void configureScanner() throws MojoExecutionException
|
||||
{
|
||||
|
@ -93,7 +95,7 @@ public class JettyRunWarExplodedMojo extends AbstractJettyMojo
|
|||
scanList.add(new File(webInfDir, "classes"));
|
||||
scanList.add(new File(webInfDir, "lib"));
|
||||
setScanList(scanList);
|
||||
|
||||
|
||||
ArrayList<Scanner.BulkListener> listeners = new ArrayList<Scanner.BulkListener>();
|
||||
listeners.add(new Scanner.BulkListener()
|
||||
{
|
||||
|
@ -113,10 +115,10 @@ public class JettyRunWarExplodedMojo extends AbstractJettyMojo
|
|||
setScannerListeners(listeners);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
public void restartWebApp(boolean reconfigureScanner) throws Exception
|
||||
|
||||
|
||||
|
||||
public void restartWebApp(boolean reconfigureScanner) throws Exception
|
||||
{
|
||||
getLog().info("Restarting webapp");
|
||||
getLog().debug("Stopping webapp ...");
|
||||
|
@ -152,20 +154,20 @@ public class JettyRunWarExplodedMojo extends AbstractJettyMojo
|
|||
getLog().info("Restart completed.");
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
public void configureWebApplication () throws Exception
|
||||
{
|
||||
super.configureWebApplication();
|
||||
super.configureWebApplication();
|
||||
webApp.setWar(war.getCanonicalPath());
|
||||
}
|
||||
|
||||
|
||||
public void execute () throws MojoExecutionException, MojoFailureException
|
||||
{
|
||||
super.execute();
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
|
|
@ -21,10 +21,14 @@ package org.eclipse.jetty.maven.plugin;
|
|||
import java.io.File;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
import org.apache.maven.artifact.Artifact;
|
||||
import org.apache.maven.plugin.MojoExecutionException;
|
||||
import org.apache.maven.plugin.MojoFailureException;
|
||||
import org.eclipse.jetty.util.Scanner;
|
||||
import org.eclipse.jetty.util.resource.Resource;
|
||||
import org.eclipse.jetty.xml.XmlConfiguration;
|
||||
|
||||
/**
|
||||
* <p>
|
||||
|
@ -32,18 +36,18 @@ import org.eclipse.jetty.util.Scanner;
|
|||
* </p>
|
||||
* <p>
|
||||
* Once invoked, the plugin can be configured to run continuously, scanning for changes in the project and to the
|
||||
* war file and automatically performing a
|
||||
* hot redeploy when necessary.
|
||||
* war file and automatically performing a
|
||||
* hot redeploy when necessary.
|
||||
* </p>
|
||||
* <p>
|
||||
* You may also specify the location of a jetty.xml file whose contents will be applied before any plugin configuration.
|
||||
* This can be used, for example, to deploy a static webapp that is not part of your maven build.
|
||||
* This can be used, for example, to deploy a static webapp that is not part of your maven build.
|
||||
* </p>
|
||||
* <p>
|
||||
* There is a <a href="run-war-mojo.html">reference guide</a> to the configuration parameters for this plugin, and more detailed information
|
||||
* with examples in the <a href="http://docs.codehaus.org/display/JETTY/Maven+Jetty+Plugin/">Configuration Guide</a>.
|
||||
* </p>
|
||||
*
|
||||
*
|
||||
* @goal run-war
|
||||
* @requiresDependencyResolution compile+runtime
|
||||
* @execute phase="package"
|
||||
|
@ -61,13 +65,13 @@ public class JettyRunWarMojo extends AbstractJettyMojo
|
|||
private File war;
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* @see org.apache.maven.plugin.Mojo#execute()
|
||||
*/
|
||||
public void execute() throws MojoExecutionException, MojoFailureException
|
||||
{
|
||||
super.execute();
|
||||
super.execute();
|
||||
}
|
||||
|
||||
|
||||
|
@ -75,18 +79,18 @@ public class JettyRunWarMojo extends AbstractJettyMojo
|
|||
public void configureWebApplication () throws Exception
|
||||
{
|
||||
super.configureWebApplication();
|
||||
|
||||
|
||||
webApp.setWar(war.getCanonicalPath());
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* @see org.eclipse.jetty.maven.plugin.AbstractJettyMojo#checkPomConfiguration()
|
||||
* @see org.mortbay.jetty.plugin.AbstractJettyMojo#checkPomConfiguration()
|
||||
*/
|
||||
public void checkPomConfiguration() throws MojoExecutionException
|
||||
{
|
||||
return;
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
|
@ -100,7 +104,7 @@ public class JettyRunWarMojo extends AbstractJettyMojo
|
|||
scanList.add(getProject().getFile());
|
||||
scanList.add(war);
|
||||
setScanList(scanList);
|
||||
|
||||
|
||||
ArrayList listeners = new ArrayList();
|
||||
listeners.add(new Scanner.BulkListener()
|
||||
{
|
||||
|
@ -117,11 +121,11 @@ public class JettyRunWarMojo extends AbstractJettyMojo
|
|||
}
|
||||
}
|
||||
});
|
||||
setScannerListeners(listeners);
|
||||
setScannerListeners(listeners);
|
||||
}
|
||||
|
||||
|
||||
public void restartWebApp(boolean reconfigureScanner) throws Exception
|
||||
public void restartWebApp(boolean reconfigureScanner) throws Exception
|
||||
{
|
||||
getLog().info("Restarting webapp ...");
|
||||
getLog().debug("Stopping webapp ...");
|
||||
|
|
|
@ -23,7 +23,6 @@ import org.eclipse.jetty.server.Connector;
|
|||
import org.eclipse.jetty.server.Handler;
|
||||
import org.eclipse.jetty.server.RequestLog;
|
||||
import org.eclipse.jetty.server.ServerConnector;
|
||||
import org.eclipse.jetty.server.Server;
|
||||
import org.eclipse.jetty.server.handler.ContextHandlerCollection;
|
||||
import org.eclipse.jetty.server.handler.DefaultHandler;
|
||||
import org.eclipse.jetty.server.handler.HandlerCollection;
|
||||
|
@ -33,20 +32,20 @@ import org.eclipse.jetty.webapp.WebAppContext;
|
|||
|
||||
/**
|
||||
* JettyServer
|
||||
*
|
||||
*
|
||||
* Maven jetty plugin version of a wrapper for the Server class.
|
||||
*
|
||||
*
|
||||
*/
|
||||
public class JettyServer extends org.eclipse.jetty.server.Server
|
||||
{
|
||||
public static int DEFAULT_PORT = 8080;
|
||||
public static int DEFAULT_MAX_IDLE_TIME = 30000;
|
||||
|
||||
|
||||
|
||||
private RequestLog requestLog;
|
||||
private ContextHandlerCollection contexts;
|
||||
|
||||
|
||||
|
||||
|
||||
public JettyServer()
|
||||
{
|
||||
super();
|
||||
|
@ -55,7 +54,7 @@ public class JettyServer extends org.eclipse.jetty.server.Server
|
|||
Resource.setDefaultUseCaches(false);
|
||||
}
|
||||
|
||||
|
||||
|
||||
public void setRequestLog (RequestLog requestLog)
|
||||
{
|
||||
this.requestLog = requestLog;
|
||||
|
@ -69,16 +68,16 @@ public class JettyServer extends org.eclipse.jetty.server.Server
|
|||
super.doStart();
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* @see org.eclipse.jetty.server.handler.HandlerCollection#addHandler(org.eclipse.jetty.server.Handler)
|
||||
*/
|
||||
public void addWebApplication(WebAppContext webapp) throws Exception
|
||||
{
|
||||
{
|
||||
contexts.addHandler (webapp);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Set up the handler structure to receive a webapp.
|
||||
* Also put in a DefaultHandler so we get a nice page
|
||||
|
@ -86,43 +85,43 @@ public class JettyServer extends org.eclipse.jetty.server.Server
|
|||
* context isn't at root.
|
||||
* @throws Exception
|
||||
*/
|
||||
public void configureHandlers () throws Exception
|
||||
public void configureHandlers () throws Exception
|
||||
{
|
||||
DefaultHandler defaultHandler = new DefaultHandler();
|
||||
RequestLogHandler requestLogHandler = new RequestLogHandler();
|
||||
if (this.requestLog != null)
|
||||
requestLogHandler.setRequestLog(this.requestLog);
|
||||
|
||||
|
||||
contexts = (ContextHandlerCollection)super.getChildHandlerByClass(ContextHandlerCollection.class);
|
||||
if (contexts==null)
|
||||
{
|
||||
{
|
||||
contexts = new ContextHandlerCollection();
|
||||
HandlerCollection handlers = (HandlerCollection)super.getChildHandlerByClass(HandlerCollection.class);
|
||||
if (handlers==null)
|
||||
{
|
||||
handlers = new HandlerCollection();
|
||||
super.setHandler(handlers);
|
||||
handlers = new HandlerCollection();
|
||||
super.setHandler(handlers);
|
||||
handlers.setHandlers(new Handler[]{contexts, defaultHandler, requestLogHandler});
|
||||
}
|
||||
else
|
||||
{
|
||||
handlers.addHandler(contexts);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
public Connector createDefaultConnector(Server server, String portnum) throws Exception
|
||||
|
||||
|
||||
|
||||
|
||||
public Connector createDefaultConnector(String portnum) throws Exception
|
||||
{
|
||||
ServerConnector connector = new ServerConnector(server);
|
||||
ServerConnector connector = new ServerConnector(this);
|
||||
int port = ((portnum==null||portnum.equals(""))?DEFAULT_PORT:Integer.parseInt(portnum.trim()));
|
||||
connector.setPort(port);
|
||||
connector.setIdleTimeout(DEFAULT_MAX_IDLE_TIME);
|
||||
|
||||
// connector.setMaxIdleTime(DEFAULT_MAX_IDLE_TIME);
|
||||
|
||||
return connector;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
|
|
@ -28,7 +28,6 @@ import java.util.Map;
|
|||
import java.util.Set;
|
||||
import java.util.TreeSet;
|
||||
|
||||
import org.eclipse.jetty.annotations.AnnotationConfiguration;
|
||||
import org.eclipse.jetty.plus.webapp.EnvConfiguration;
|
||||
import org.eclipse.jetty.util.URIUtil;
|
||||
import org.eclipse.jetty.util.log.Log;
|
||||
|
@ -39,8 +38,8 @@ import org.eclipse.jetty.webapp.Configuration;
|
|||
import org.eclipse.jetty.webapp.FragmentConfiguration;
|
||||
import org.eclipse.jetty.webapp.JettyWebXmlConfiguration;
|
||||
import org.eclipse.jetty.webapp.MetaInfConfiguration;
|
||||
import org.eclipse.jetty.webapp.TagLibConfiguration;
|
||||
import org.eclipse.jetty.webapp.WebAppContext;
|
||||
import org.eclipse.jetty.webapp.WebInfConfiguration;
|
||||
import org.eclipse.jetty.webapp.WebXmlConfiguration;
|
||||
|
||||
/**
|
||||
|
@ -56,6 +55,7 @@ public class JettyWebAppContext extends WebAppContext
|
|||
{
|
||||
private static final Logger LOG = Log.getLogger(JettyWebAppContext.class);
|
||||
|
||||
private static final String DEFAULT_CONTAINER_INCLUDE_JAR_PATTERN = ".*/javax.servlet-[^/]*\\.jar$|.*/servlet-api-[^/]*\\.jar$";
|
||||
private static final String WEB_INF_CLASSES_PREFIX = "/WEB-INF/classes";
|
||||
private static final String WEB_INF_LIB_PREFIX = "/WEB-INF/lib";
|
||||
|
||||
|
@ -73,6 +73,19 @@ public class JettyWebAppContext extends WebAppContext
|
|||
* @deprecated The value of this parameter will be ignored by the plugin. Overlays will always be unpacked.
|
||||
*/
|
||||
private boolean unpackOverlays;
|
||||
|
||||
/**
|
||||
* Set the "org.eclipse.jetty.server.webapp.ContainerIncludeJarPattern" with a pattern for matching jars on
|
||||
* container classpath to scan. This is analogous to the WebAppContext.setAttribute() call.
|
||||
*/
|
||||
private String containerIncludeJarPattern = null;
|
||||
|
||||
/**
|
||||
* Set the "org.eclipse.jetty.server.webapp.WebInfIncludeJarPattern" with a pattern for matching jars on
|
||||
* webapp's classpath to scan. This is analogous to the WebAppContext.setAttribute() call.
|
||||
*/
|
||||
private String webInfIncludeJarPattern = null;
|
||||
|
||||
|
||||
/**
|
||||
* @deprecated The value of this parameter will be ignored by the plugin. This option will be always disabled.
|
||||
|
@ -91,14 +104,34 @@ public class JettyWebAppContext extends WebAppContext
|
|||
new MetaInfConfiguration(),
|
||||
new FragmentConfiguration(),
|
||||
envConfig = new EnvConfiguration(),
|
||||
new AnnotationConfiguration(),
|
||||
new org.eclipse.jetty.plus.webapp.PlusConfiguration(),
|
||||
new JettyWebXmlConfiguration(),
|
||||
new TagLibConfiguration()
|
||||
new MavenAnnotationConfiguration(),
|
||||
new JettyWebXmlConfiguration()
|
||||
});
|
||||
// Turn off copyWebInf option as it is not applicable for plugin.
|
||||
super.setCopyWebInf(false);
|
||||
}
|
||||
public void setContainerIncludeJarPattern(String pattern)
|
||||
{
|
||||
containerIncludeJarPattern = pattern;
|
||||
}
|
||||
|
||||
public String getContainerIncludeJarPattern()
|
||||
{
|
||||
return containerIncludeJarPattern;
|
||||
}
|
||||
|
||||
|
||||
public String getWebInfIncludeJarPattern()
|
||||
{
|
||||
return webInfIncludeJarPattern;
|
||||
}
|
||||
public void setWebInfIncludeJarPattern(String pattern)
|
||||
{
|
||||
webInfIncludeJarPattern = pattern;
|
||||
}
|
||||
|
||||
|
||||
|
||||
public boolean getUnpackOverlays()
|
||||
{
|
||||
|
@ -218,17 +251,21 @@ public class JettyWebAppContext extends WebAppContext
|
|||
{
|
||||
//Set up the pattern that tells us where the jars are that need scanning for
|
||||
//stuff like taglibs so we can tell jasper about it (see TagLibConfiguration)
|
||||
String tmp = (String)getAttribute("org.eclipse.jetty.server.webapp.ContainerIncludeJarPattern");
|
||||
|
||||
tmp = addPattern(tmp, ".*/.*jsp-api-[^/]*\\.jar$");
|
||||
tmp = addPattern(tmp, ".*/.*jsp-[^/]*\\.jar$");
|
||||
tmp = addPattern(tmp, ".*/.*taglibs[^/]*\\.jar$");
|
||||
tmp = addPattern(tmp, ".*/.*jstl[^/]*\\.jar$");
|
||||
tmp = addPattern(tmp, ".*/.*jsf-impl-[^/]*\\.jar$"); // add in 2 most popular jsf impls
|
||||
tmp = addPattern(tmp, ".*/.*javax.faces-[^/]*\\.jar$");
|
||||
tmp = addPattern(tmp, ".*/.*myfaces-impl-[^/]*\\.jar$");
|
||||
|
||||
setAttribute("org.eclipse.jetty.server.webapp.ContainerIncludeJarPattern", tmp);
|
||||
//Allow user to set up pattern for names of jars from the container classpath
|
||||
//that will be scanned - note that by default NO jars are scanned
|
||||
String tmp = containerIncludeJarPattern;
|
||||
if (tmp==null || "".equals(tmp))
|
||||
tmp = (String)getAttribute(WebInfConfiguration.CONTAINER_JAR_PATTERN);
|
||||
|
||||
tmp = addPattern(tmp, DEFAULT_CONTAINER_INCLUDE_JAR_PATTERN);
|
||||
setAttribute(WebInfConfiguration.CONTAINER_JAR_PATTERN, tmp);
|
||||
|
||||
//Allow user to set up pattern of jar names from WEB-INF that will be scanned.
|
||||
//Note that by default ALL jars considered to be in WEB-INF will be scanned - setting
|
||||
//a pattern restricts scanning
|
||||
if (webInfIncludeJarPattern != null)
|
||||
setAttribute(WebInfConfiguration.WEBINF_JAR_PATTERN, webInfIncludeJarPattern);
|
||||
|
||||
//Set up the classes dirs that comprises the equivalent of WEB-INF/classes
|
||||
if (testClasses != null)
|
||||
|
@ -241,7 +278,6 @@ public class JettyWebAppContext extends WebAppContext
|
|||
classpathFiles.addAll(webInfClasses);
|
||||
classpathFiles.addAll(webInfJars);
|
||||
|
||||
|
||||
// Initialize map containing all jars in /WEB-INF/lib
|
||||
webInfJarMap.clear();
|
||||
for (File file : webInfJars)
|
||||
|
@ -255,13 +291,28 @@ public class JettyWebAppContext extends WebAppContext
|
|||
if (this.jettyEnvXml != null)
|
||||
envConfig.setJettyEnvXml(Resource.toURL(new File(this.jettyEnvXml)));
|
||||
|
||||
//setShutdown(false);
|
||||
// CHECK setShutdown(false);
|
||||
super.doStart();
|
||||
}
|
||||
|
||||
public void doStop () throws Exception
|
||||
{
|
||||
//setShutdown(true);
|
||||
if (classpathFiles != null)
|
||||
classpathFiles.clear();
|
||||
classpathFiles = null;
|
||||
|
||||
classes = null;
|
||||
testClasses = null;
|
||||
|
||||
if (webInfJarMap != null)
|
||||
webInfJarMap.clear();
|
||||
|
||||
webInfClasses.clear();
|
||||
webInfJars.clear();
|
||||
|
||||
|
||||
|
||||
// CHECK setShutdown(true);
|
||||
//just wait a little while to ensure no requests are still being processed
|
||||
Thread.currentThread().sleep(500L);
|
||||
super.doStop();
|
||||
|
@ -344,37 +395,40 @@ public class JettyWebAppContext extends WebAppContext
|
|||
@Override
|
||||
public Set<String> getResourcePaths(String path)
|
||||
{
|
||||
// Try to get regular resource paths
|
||||
// Try to get regular resource paths - this will get appropriate paths from any overlaid wars etc
|
||||
Set<String> paths = super.getResourcePaths(path);
|
||||
|
||||
// If no paths are returned check for virtual paths /WEB-INF/classes and /WEB-INF/lib
|
||||
if (paths.isEmpty() && path != null)
|
||||
|
||||
if (path != null)
|
||||
{
|
||||
path = URIUtil.canonicalPath(path);
|
||||
TreeSet<String> allPaths = new TreeSet<String>();
|
||||
allPaths.addAll(paths);
|
||||
|
||||
//add in the dependency jars as a virtual WEB-INF/lib entry
|
||||
if (path.startsWith(WEB_INF_LIB_PREFIX))
|
||||
{
|
||||
paths = new TreeSet<String>();
|
||||
for (String fileName : webInfJarMap.keySet())
|
||||
{
|
||||
// Return all jar files from class path
|
||||
paths.add(WEB_INF_LIB_PREFIX + "/" + fileName);
|
||||
allPaths.add(WEB_INF_LIB_PREFIX + "/" + fileName);
|
||||
}
|
||||
}
|
||||
else if (path.startsWith(WEB_INF_CLASSES_PREFIX))
|
||||
{
|
||||
int i=0;
|
||||
|
||||
while (paths.isEmpty() && (i < webInfClasses.size()))
|
||||
while (i < webInfClasses.size())
|
||||
{
|
||||
String newPath = path.replace(WEB_INF_CLASSES_PREFIX, webInfClasses.get(i).getPath());
|
||||
paths = super.getResourcePaths(newPath);
|
||||
allPaths.addAll(super.getResourcePaths(newPath));
|
||||
i++;
|
||||
}
|
||||
}
|
||||
return allPaths;
|
||||
}
|
||||
return paths;
|
||||
}
|
||||
|
||||
|
||||
public String addPattern (String s, String pattern)
|
||||
{
|
||||
if (s == null)
|
||||
|
|
|
@ -0,0 +1,109 @@
|
|||
//
|
||||
// ========================================================================
|
||||
// Copyright (c) 1995-2012 Mort Bay Consulting Pty. Ltd.
|
||||
// ------------------------------------------------------------------------
|
||||
// All rights reserved. This program and the accompanying materials
|
||||
// are made available under the terms of the Eclipse Public License v1.0
|
||||
// and Apache License v2.0 which accompanies this distribution.
|
||||
//
|
||||
// The Eclipse Public License is available at
|
||||
// http://www.eclipse.org/legal/epl-v10.html
|
||||
//
|
||||
// The Apache License v2.0 is available at
|
||||
// http://www.opensource.org/licenses/apache2.0.php
|
||||
//
|
||||
// You may elect to redistribute this code under either of these licenses.
|
||||
// ========================================================================
|
||||
//
|
||||
|
||||
package org.eclipse.jetty.maven.plugin;
|
||||
|
||||
import java.io.File;
|
||||
|
||||
import org.eclipse.jetty.annotations.AbstractDiscoverableAnnotationHandler;
|
||||
import org.eclipse.jetty.annotations.AnnotationConfiguration;
|
||||
import org.eclipse.jetty.annotations.AnnotationParser;
|
||||
import org.eclipse.jetty.annotations.AnnotationParser.DiscoverableAnnotationHandler;
|
||||
import org.eclipse.jetty.annotations.ClassNameResolver;
|
||||
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.MetaData;
|
||||
import org.eclipse.jetty.webapp.WebAppContext;
|
||||
|
||||
public class MavenAnnotationConfiguration extends AnnotationConfiguration
|
||||
{
|
||||
private static final Logger LOG = Log.getLogger(MavenAnnotationConfiguration.class);
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
@Override
|
||||
public void parseWebInfClasses(final WebAppContext context, final AnnotationParser parser) throws Exception
|
||||
{
|
||||
JettyWebAppContext jwac = (JettyWebAppContext)context;
|
||||
if (jwac.getClassPathFiles() == null || jwac.getClassPathFiles().size() == 0)
|
||||
super.parseWebInfClasses (context, parser);
|
||||
else
|
||||
{
|
||||
LOG.debug("Scanning classes ");
|
||||
//Look for directories on the classpath and process each one of those
|
||||
|
||||
MetaData metaData = context.getMetaData();
|
||||
if (metaData == null)
|
||||
throw new IllegalStateException ("No metadata");
|
||||
|
||||
parser.clearHandlers();
|
||||
for (DiscoverableAnnotationHandler h:_discoverableAnnotationHandlers)
|
||||
{
|
||||
if (h instanceof AbstractDiscoverableAnnotationHandler)
|
||||
((AbstractDiscoverableAnnotationHandler)h).setResource(null); //
|
||||
}
|
||||
parser.registerHandlers(_discoverableAnnotationHandlers);
|
||||
parser.registerHandler(_classInheritanceHandler);
|
||||
parser.registerHandlers(_containerInitializerAnnotationHandlers);
|
||||
|
||||
|
||||
for (File f:jwac.getClassPathFiles())
|
||||
{
|
||||
//scan the equivalent of the WEB-INF/classes directory that has been synthesised by the plugin
|
||||
if (f.isDirectory() && f.exists())
|
||||
{
|
||||
doParse(context, parser, Resource.newResource(f.toURL()));
|
||||
}
|
||||
}
|
||||
|
||||
//if an actual WEB-INF/classes directory also exists (eg because of overlayed wars) then scan that
|
||||
//too
|
||||
if (context.getWebInf() != null && context.getWebInf().exists())
|
||||
{
|
||||
Resource classesDir = context.getWebInf().addPath("classes/");
|
||||
if (classesDir.exists())
|
||||
{
|
||||
doParse(context, parser, classesDir);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public void doParse (final WebAppContext context, final AnnotationParser parser, Resource resource)
|
||||
throws Exception
|
||||
{
|
||||
parser.parse(resource, 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;
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
|
@ -24,8 +24,10 @@ import java.net.URLClassLoader;
|
|||
import java.util.ArrayList;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
|
||||
import org.eclipse.jetty.util.IO;
|
||||
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;
|
||||
|
@ -40,8 +42,8 @@ public class MavenWebInfConfiguration extends WebInfConfiguration
|
|||
|
||||
protected Resource _originalResourceBase;
|
||||
protected Resource[] _unpackedOverlays;
|
||||
|
||||
|
||||
|
||||
|
||||
public void configure(WebAppContext context) throws Exception
|
||||
{
|
||||
JettyWebAppContext jwac = (JettyWebAppContext)context;
|
||||
|
@ -54,11 +56,11 @@ public class MavenWebInfConfiguration extends WebInfConfiguration
|
|||
while (itor.hasNext())
|
||||
((WebAppClassLoader)context.getClassLoader()).addClassPath(((File)itor.next()).getCanonicalPath());
|
||||
|
||||
if (LOG.isDebugEnabled())
|
||||
LOG.debug("Classpath = "+((URLClassLoader)context.getClassLoader()).getURLs());
|
||||
//if (LOG.isDebugEnabled())
|
||||
//LOG.debug("Classpath = "+LazyList.array2List(((URLClassLoader)context.getClassLoader()).getURLs()));
|
||||
}
|
||||
super.configure(context);
|
||||
|
||||
|
||||
// knock out environmental maven and plexus classes from webAppContext
|
||||
String[] existingServerClasses = context.getServerClasses();
|
||||
String[] newServerClasses = new String[2+(existingServerClasses==null?0:existingServerClasses.length)];
|
||||
|
@ -71,7 +73,7 @@ public class MavenWebInfConfiguration extends WebInfConfiguration
|
|||
for (int i=0;i<newServerClasses.length;i++)
|
||||
LOG.debug(newServerClasses[i]);
|
||||
}
|
||||
context.setServerClasses( newServerClasses );
|
||||
context.setServerClasses( newServerClasses );
|
||||
}
|
||||
|
||||
|
||||
|
@ -79,6 +81,53 @@ public class MavenWebInfConfiguration extends WebInfConfiguration
|
|||
{
|
||||
super.preConfigure(context);
|
||||
|
||||
}
|
||||
|
||||
public void postConfigure(WebAppContext context) throws Exception
|
||||
{
|
||||
super.postConfigure(context);
|
||||
}
|
||||
|
||||
|
||||
public void deconfigure(WebAppContext context) throws Exception
|
||||
{
|
||||
JettyWebAppContext jwac = (JettyWebAppContext)context;
|
||||
|
||||
//remove the unpacked wars
|
||||
if (_unpackedOverlays != null && _unpackedOverlays.length>0)
|
||||
{
|
||||
try
|
||||
{
|
||||
for (int i=0; i<_unpackedOverlays.length; i++)
|
||||
{
|
||||
IO.delete(_unpackedOverlays[i].getFile());
|
||||
}
|
||||
}
|
||||
catch (IOException e)
|
||||
{
|
||||
LOG.ignore(e);
|
||||
}
|
||||
}
|
||||
super.deconfigure(context);
|
||||
//restore whatever the base resource was before we might have included overlaid wars
|
||||
context.setBaseResource(_originalResourceBase);
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* @see org.eclipse.jetty.webapp.WebInfConfiguration#unpack(org.eclipse.jetty.webapp.WebAppContext)
|
||||
*/
|
||||
@Override
|
||||
public void unpack(WebAppContext context) throws IOException
|
||||
{
|
||||
//Unpack and find base resource as normal
|
||||
super.unpack(context);
|
||||
|
||||
|
||||
//Add in any overlays as a resource collection for the base
|
||||
_originalResourceBase = context.getBaseResource();
|
||||
JettyWebAppContext jwac = (JettyWebAppContext)context;
|
||||
|
||||
|
@ -102,7 +151,7 @@ public class MavenWebInfConfiguration extends WebInfConfiguration
|
|||
origSize = 1;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
int overlaySize = jwac.getOverlays().size();
|
||||
Resource[] newResources = new Resource[origSize + overlaySize];
|
||||
|
||||
|
@ -112,7 +161,6 @@ public class MavenWebInfConfiguration extends WebInfConfiguration
|
|||
if (jwac.getBaseAppFirst())
|
||||
{
|
||||
System.arraycopy(origResources,0,newResources,0,origSize);
|
||||
|
||||
offset = origSize;
|
||||
}
|
||||
else
|
||||
|
@ -120,53 +168,23 @@ public class MavenWebInfConfiguration extends WebInfConfiguration
|
|||
System.arraycopy(origResources,0,newResources,overlaySize,origSize);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Overlays are always unpacked
|
||||
_unpackedOverlays = new Resource[overlaySize];
|
||||
List<Resource> overlays = jwac.getOverlays();
|
||||
for (int idx=0; idx<overlaySize; idx++)
|
||||
{
|
||||
{
|
||||
LOG.info("Unpacking overlay: " + overlays.get(idx));
|
||||
_unpackedOverlays[idx] = unpackOverlay(context, overlays.get(idx));
|
||||
newResources[idx+offset] = _unpackedOverlays[idx];
|
||||
|
||||
LOG.info("Adding overlay: " + _unpackedOverlays[idx]);
|
||||
}
|
||||
|
||||
|
||||
jwac.setBaseResource(new ResourceCollection(newResources));
|
||||
}
|
||||
}
|
||||
|
||||
public void postConfigure(WebAppContext context) throws Exception
|
||||
{
|
||||
super.postConfigure(context);
|
||||
}
|
||||
|
||||
|
||||
public void deconfigure(WebAppContext context) throws Exception
|
||||
{
|
||||
JettyWebAppContext jwac = (JettyWebAppContext)context;
|
||||
|
||||
//remove the unpacked wars
|
||||
if (_unpackedOverlays != null && _unpackedOverlays.length>0)
|
||||
{
|
||||
try
|
||||
{
|
||||
for (int i=0; i<_unpackedOverlays.length; i++)
|
||||
{
|
||||
IO.delete(_unpackedOverlays[i].getFile());
|
||||
}
|
||||
}
|
||||
catch (IOException e)
|
||||
{
|
||||
LOG.ignore(e);
|
||||
}
|
||||
}
|
||||
super.deconfigure(context);
|
||||
//restore whatever the base resource was before we might have included overlaid wars
|
||||
context.setBaseResource(_originalResourceBase);
|
||||
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Get the jars to examine from the files from which we have
|
||||
|
@ -175,6 +193,7 @@ public class MavenWebInfConfiguration extends WebInfConfiguration
|
|||
* @param context
|
||||
* @return the list of jars found
|
||||
*/
|
||||
@Override
|
||||
protected List<Resource> findJars (WebAppContext context)
|
||||
throws Exception
|
||||
{
|
||||
|
@ -184,7 +203,7 @@ public class MavenWebInfConfiguration extends WebInfConfiguration
|
|||
{
|
||||
for (File f: jwac.getClassPathFiles())
|
||||
{
|
||||
if (f.getName().toLowerCase().endsWith(".jar"))
|
||||
if (f.getName().toLowerCase(Locale.ENGLISH).endsWith(".jar"))
|
||||
{
|
||||
try
|
||||
{
|
||||
|
@ -203,14 +222,16 @@ public class MavenWebInfConfiguration extends WebInfConfiguration
|
|||
list.addAll(superList);
|
||||
return list;
|
||||
}
|
||||
|
||||
|
||||
|
||||
protected Resource unpackOverlay (WebAppContext context, Resource overlay)
|
||||
throws IOException
|
||||
{
|
||||
//resolve if not already resolved
|
||||
resolveTempDirectory(context);
|
||||
|
||||
|
||||
|
||||
|
||||
//Get the name of the overlayed war and unpack it to a dir of the
|
||||
//same name in the temporary directory
|
||||
String name = overlay.getName();
|
||||
|
@ -225,6 +246,4 @@ public class MavenWebInfConfiguration extends WebInfConfiguration
|
|||
Resource unpackedOverlay = Resource.newResource(dir.getCanonicalPath());
|
||||
return unpackedOverlay;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
|
|
@ -16,12 +16,12 @@
|
|||
// ========================================================================
|
||||
//
|
||||
|
||||
|
||||
package org.eclipse.jetty.maven.plugin;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStreamReader;
|
||||
import java.io.LineNumberReader;
|
||||
import java.net.InetAddress;
|
||||
import java.net.InetSocketAddress;
|
||||
import java.net.ServerSocket;
|
||||
import java.net.Socket;
|
||||
|
@ -41,7 +41,7 @@ import org.eclipse.jetty.server.Server;
|
|||
* by stopping the Server instances. The choice of
|
||||
* behaviour is controlled by either passing true
|
||||
* (exit jvm) or false (stop Servers) in the constructor.
|
||||
*
|
||||
*
|
||||
*/
|
||||
public class Monitor extends Thread
|
||||
{
|
||||
|
@ -51,7 +51,7 @@ public class Monitor extends Thread
|
|||
ServerSocket _serverSocket;
|
||||
boolean _kill;
|
||||
|
||||
public Monitor(int port, String key, Server[] servers, boolean kill)
|
||||
public Monitor(int port, String key, Server[] servers, boolean kill)
|
||||
throws UnknownHostException, IOException
|
||||
{
|
||||
if (port <= 0)
|
||||
|
@ -64,7 +64,7 @@ public class Monitor extends Thread
|
|||
_kill = kill;
|
||||
setDaemon(true);
|
||||
setName("StopJettyPluginMonitor");
|
||||
InetSocketAddress address = new InetSocketAddress("127.0.0.1", port);
|
||||
InetSocketAddress address = new InetSocketAddress("127.0.0.1", port);
|
||||
_serverSocket=new ServerSocket();
|
||||
_serverSocket.setReuseAddress(true);
|
||||
try
|
||||
|
@ -77,7 +77,7 @@ public class Monitor extends Thread
|
|||
throw x;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public void run()
|
||||
{
|
||||
while (_serverSocket != null)
|
||||
|
@ -88,7 +88,7 @@ public class Monitor extends Thread
|
|||
socket = _serverSocket.accept();
|
||||
socket.setSoLinger(false, 0);
|
||||
LineNumberReader lin = new LineNumberReader(new InputStreamReader(socket.getInputStream()));
|
||||
|
||||
|
||||
String key = lin.readLine();
|
||||
if (!_key.equals(key)) continue;
|
||||
String cmd = lin.readLine();
|
||||
|
@ -97,13 +97,13 @@ public class Monitor extends Thread
|
|||
try{socket.close();}catch (Exception e){e.printStackTrace();}
|
||||
try{socket.close();}catch (Exception e){e.printStackTrace();}
|
||||
try{_serverSocket.close();}catch (Exception e){e.printStackTrace();}
|
||||
|
||||
|
||||
_serverSocket = null;
|
||||
|
||||
|
||||
if (_kill)
|
||||
{
|
||||
System.out.println("Killing Jetty");
|
||||
System.exit(0);
|
||||
System.exit(0);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -111,7 +111,7 @@ public class Monitor extends Thread
|
|||
{
|
||||
try
|
||||
{
|
||||
System.out.println("Stopping server "+i);
|
||||
System.out.println("Stopping server "+i);
|
||||
_servers[i].stop();
|
||||
}
|
||||
catch (Exception e)
|
||||
|
|
|
@ -23,19 +23,23 @@ import java.io.FileInputStream;
|
|||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Properties;
|
||||
import java.util.StringTokenizer;
|
||||
|
||||
import org.eclipse.jetty.server.Connector;
|
||||
import org.eclipse.jetty.server.Handler;
|
||||
import org.eclipse.jetty.server.Server;
|
||||
import org.eclipse.jetty.server.handler.ContextHandler;
|
||||
import org.eclipse.jetty.server.handler.ContextHandlerCollection;
|
||||
import org.eclipse.jetty.server.handler.HandlerCollection;
|
||||
import org.eclipse.jetty.util.log.Log;
|
||||
import org.eclipse.jetty.util.log.Logger;
|
||||
import org.eclipse.jetty.util.resource.Resource;
|
||||
import org.eclipse.jetty.util.resource.ResourceCollection;
|
||||
import org.eclipse.jetty.webapp.WebAppContext;
|
||||
import org.eclipse.jetty.xml.XmlConfiguration;
|
||||
|
||||
public class Starter
|
||||
{
|
||||
{
|
||||
public static final String PORT_SYSPROPERTY = "jetty.port";
|
||||
private static final Logger LOG = Log.getLogger(Starter.class);
|
||||
|
||||
|
@ -45,21 +49,21 @@ public class Starter
|
|||
private JettyServer server;
|
||||
private JettyWebAppContext webApp;
|
||||
private Monitor monitor;
|
||||
|
||||
|
||||
private int stopPort=0;
|
||||
private String stopKey=null;
|
||||
private Properties props;
|
||||
private String token;
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
public void configureJetty () throws Exception
|
||||
{
|
||||
LOG.debug("Starting Jetty Server ...");
|
||||
|
||||
this.server = new JettyServer();
|
||||
|
||||
//apply any configs from jetty.xml files first
|
||||
//apply any configs from jetty.xml files first
|
||||
applyJettyXml ();
|
||||
|
||||
// if the user hasn't configured a connector in the jetty.xml
|
||||
|
@ -68,7 +72,7 @@ public class Starter
|
|||
if (connectors == null|| connectors.length == 0)
|
||||
{
|
||||
//if a SystemProperty -Djetty.port=<portnum> has been supplied, use that as the default port
|
||||
connectors = new Connector[] { this.server.createDefaultConnector(server, System.getProperty(PORT_SYSPROPERTY, null)) };
|
||||
connectors = new Connector[] { this.server.createDefaultConnector(System.getProperty(PORT_SYSPROPERTY, null)) };
|
||||
this.server.setConnectors(connectors);
|
||||
}
|
||||
|
||||
|
@ -84,15 +88,15 @@ public class Starter
|
|||
this.server.configureHandlers();
|
||||
|
||||
webApp = new JettyWebAppContext();
|
||||
|
||||
|
||||
//configure webapp from properties file describing unassembled webapp
|
||||
configureWebApp();
|
||||
|
||||
|
||||
//set up the webapp from the context xml file provided
|
||||
//NOTE: just like jetty:run mojo this means that the context file can
|
||||
//potentially override settings made in the pom. Ideally, we'd like
|
||||
//the pom to override the context xml file, but as the other mojos all
|
||||
//configure a WebAppContext in the pom (the <webApp> element), it is
|
||||
//configure a WebAppContext in the pom (the <webApp> element), it is
|
||||
//already configured by the time the context xml file is applied.
|
||||
if (contextXml != null)
|
||||
{
|
||||
|
@ -109,30 +113,30 @@ public class Starter
|
|||
monitor = new Monitor(stopPort, stopKey, new Server[]{server}, true);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
public void configureWebApp ()
|
||||
throws Exception
|
||||
{
|
||||
if (props == null)
|
||||
return;
|
||||
|
||||
|
||||
//apply a properties file that defines the things that we configure in the jetty:run plugin:
|
||||
// - the context path
|
||||
String str = (String)props.get("context.path");
|
||||
if (str != null)
|
||||
webApp.setContextPath(str);
|
||||
|
||||
|
||||
// - web.xml
|
||||
str = (String)props.get("web.xml");
|
||||
if (str != null)
|
||||
webApp.setDescriptor(str);
|
||||
|
||||
|
||||
// - the tmp directory
|
||||
str = (String)props.getProperty("tmp.dir");
|
||||
if (str != null)
|
||||
webApp.setTempDirectory(new File(str.trim()));
|
||||
|
||||
|
||||
// - the base directory
|
||||
str = (String)props.getProperty("base.dir");
|
||||
if (str != null && !"".equals(str.trim()))
|
||||
|
@ -145,7 +149,7 @@ public class Starter
|
|||
ResourceCollection resources = new ResourceCollection(str);
|
||||
webApp.setBaseResource(resources);
|
||||
}
|
||||
|
||||
|
||||
// - overlays
|
||||
str = (String)props.getProperty("overlay.files");
|
||||
if (str != null && !"".equals(str.trim()))
|
||||
|
@ -163,8 +167,8 @@ public class Starter
|
|||
{
|
||||
webApp.setClasses(new File(str));
|
||||
}
|
||||
|
||||
str = (String)props.getProperty("testClasses.dir");
|
||||
|
||||
str = (String)props.getProperty("testClasses.dir");
|
||||
if (str != null && !"".equals(str.trim()))
|
||||
{
|
||||
webApp.setTestClasses(new File(str));
|
||||
|
@ -181,7 +185,7 @@ public class Starter
|
|||
jars.add(new File(names[j].trim()));
|
||||
webApp.setWebInfLib(jars);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
public void getConfiguration (String[] args)
|
||||
|
@ -205,7 +209,7 @@ public class Starter
|
|||
for (int j=0; names!= null && j < names.length; j++)
|
||||
{
|
||||
jettyXmls.add(new File(names[j].trim()));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//--context-xml
|
||||
|
@ -221,7 +225,7 @@ public class Starter
|
|||
props = new Properties();
|
||||
props.load(new FileInputStream(f));
|
||||
}
|
||||
|
||||
|
||||
//--token
|
||||
if ("--token".equals(args[i]))
|
||||
{
|
||||
|
@ -237,16 +241,16 @@ public class Starter
|
|||
monitor.start();
|
||||
|
||||
LOG.info("Started Jetty Server");
|
||||
server.start();
|
||||
server.start();
|
||||
}
|
||||
|
||||
|
||||
|
||||
public void join () throws Exception
|
||||
{
|
||||
server.join();
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
public void communicateStartupResult (Exception e)
|
||||
{
|
||||
if (token != null)
|
||||
|
@ -257,16 +261,16 @@ public class Starter
|
|||
System.out.println(token+"\t"+e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
public void applyJettyXml() throws Exception
|
||||
{
|
||||
if (jettyXmls == null)
|
||||
return;
|
||||
|
||||
|
||||
for ( File xmlFile : jettyXmls )
|
||||
{
|
||||
LOG.info( "Configuring Jetty from xml configuration file = " + xmlFile.getCanonicalPath() );
|
||||
LOG.info( "Configuring Jetty from xml configuration file = " + xmlFile.getCanonicalPath() );
|
||||
XmlConfiguration xmlConfiguration = new XmlConfiguration(Resource.toURL(xmlFile));
|
||||
xmlConfiguration.configure(this.server);
|
||||
}
|
||||
|
@ -286,8 +290,8 @@ public class Starter
|
|||
System.arraycopy(existing, 0, children, 1, existing.length);
|
||||
handlers.setHandlers(children);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
public static final void main(String[] args)
|
||||
{
|
||||
if (args == null)
|
||||
|
|
|
@ -23,6 +23,7 @@ import java.io.FilenameFilter;
|
|||
import java.io.IOException;
|
||||
import java.util.HashSet;
|
||||
import java.util.Iterator;
|
||||
import java.util.Locale;
|
||||
import java.util.Map.Entry;
|
||||
import java.util.Set;
|
||||
|
||||
|
@ -116,7 +117,7 @@ public class OSGiAppProvider extends ScanningAppProvider implements AppProvider
|
|||
*/
|
||||
private static String getDeployedAppName(String contextFileName)
|
||||
{
|
||||
String lowername = contextFileName.toLowerCase();
|
||||
String lowername = contextFileName.toLowerCase(Locale.ENGLISH);
|
||||
if (lowername.endsWith(".xml"))
|
||||
{
|
||||
String contextName = contextFileName.substring(0, lowername.length() - ".xml".length());
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -7,16 +7,19 @@
|
|||
<!-- HttpChannel Configuration -->
|
||||
<!-- =========================================================== -->
|
||||
<New id="httpConfig" class="org.eclipse.jetty.server.HttpConfiguration">
|
||||
<Set name="secureScheme">https</Set>
|
||||
<Set name="securePort"><SystemProperty name="jetty.spdy.port" default="8443"/></Set>
|
||||
<Set name="outputBufferSize">32768</Set>
|
||||
<Set name="requestHeaderSize">8192</Set>
|
||||
<Set name="responseHeaderSize">8192</Set>
|
||||
<Call name="addCustomizer">
|
||||
<Arg><New class="org.eclipse.jetty.server.ForwardedRequestCustomizer"/></Arg>
|
||||
</Call>
|
||||
<Set name="secureScheme">https</Set>
|
||||
<Set name="securePort">
|
||||
<SystemProperty name="jetty.spdy.port" default="8443"/>
|
||||
</Set>
|
||||
<Set name="outputBufferSize">32768</Set>
|
||||
<Set name="requestHeaderSize">8192</Set>
|
||||
<Set name="responseHeaderSize">8192</Set>
|
||||
<Call name="addCustomizer">
|
||||
<Arg>
|
||||
<New class="org.eclipse.jetty.server.ForwardedRequestCustomizer"/>
|
||||
</Arg>
|
||||
</Call>
|
||||
</New>
|
||||
|
||||
|
||||
|
||||
<!-- =========================================================== -->
|
||||
|
@ -44,18 +47,39 @@
|
|||
</Ref>
|
||||
|
||||
<!-- =========================================================== -->
|
||||
<!-- Create a push strategy -->
|
||||
<!-- Create a push strategy which can be used by reference by -->
|
||||
<!-- individual connection factories below. -->
|
||||
<!-- -->
|
||||
<!-- Consult the javadoc of o.e.j.spdy.server.http.ReferrerPushStrategy -->
|
||||
<!-- for all configuration that may be set here. -->
|
||||
<!-- =========================================================== -->
|
||||
<New id="pushStrategy" class="org.eclipse.jetty.spdy.server.http.ReferrerPushStrategy">
|
||||
<Arg type="List">
|
||||
<Array type="String">
|
||||
<Item>.*\.css</Item>
|
||||
<Item>.*\.js</Item>
|
||||
<Item>.*\.png</Item>
|
||||
<Item>.*\.jpg</Item>
|
||||
<Item>.*\.gif</Item>
|
||||
</Array>
|
||||
</Arg>
|
||||
<!-- Uncomment to blacklist browsers for this push strategy. If one of the blacklisted Strings occurs in the
|
||||
user-agent header sent by the client, push will be disabled for this browser. This is case insensitive" -->
|
||||
<!--
|
||||
<Set name="UserAgentBlacklist">
|
||||
<Array type="String">
|
||||
<Item>.*(?i)firefox/14.*</Item>
|
||||
<Item>.*(?i)firefox/15.*</Item>
|
||||
<Item>.*(?i)firefox/16.*</Item>
|
||||
</Array>
|
||||
</Set>
|
||||
-->
|
||||
|
||||
<!-- Uncomment to override default file extensions to push -->
|
||||
<!--
|
||||
<Set name="PushRegexps">
|
||||
<Array type="String">
|
||||
<Item>.*\.css</Item>
|
||||
<Item>.*\.js</Item>
|
||||
<Item>.*\.png</Item>
|
||||
<Item>.*\.jpg</Item>
|
||||
<Item>.*\.gif</Item>
|
||||
</Array>
|
||||
</Set>
|
||||
-->
|
||||
<Set name="referrerPushPeriod">5000</Set>
|
||||
<Set name="maxAssociatedResources">32</Set>
|
||||
</New>
|
||||
|
||||
<!-- =========================================================== -->
|
||||
|
|
|
@ -1,13 +1,11 @@
|
|||
<?xml version="1.0"?>
|
||||
<!DOCTYPE Configure PUBLIC "-//Jetty//Configure//EN" "http://www.eclipse.org/jetty/configure.dtd">
|
||||
|
||||
<!DOCTYPE Configure PUBLIC "-" "http://www.eclipse.org/jetty/configure.dtd">
|
||||
<Configure id="Server" class="org.eclipse.jetty.server.Server">
|
||||
|
||||
<!-- =========================================================== -->
|
||||
<!-- Configure Authentication Login Service -->
|
||||
<!-- Realms may be configured for the entire server here, or -->
|
||||
<!-- they can be configured for a specific web app in a context -->
|
||||
<!-- configuration (see $(jetty.home)/contexts/test.xml for an -->
|
||||
<!-- configuration (see $(jetty.home)/webapps/test.xml for an -->
|
||||
<!-- example). -->
|
||||
<!-- =========================================================== -->
|
||||
<Call name="addBean">
|
||||
|
@ -19,5 +17,4 @@
|
|||
</New>
|
||||
</Arg>
|
||||
</Call>
|
||||
|
||||
</Configure>
|
||||
</Configure>
|
|
@ -21,6 +21,7 @@ package org.eclipse.jetty.plus.annotation;
|
|||
import java.lang.reflect.Field;
|
||||
import java.lang.reflect.Member;
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.Locale;
|
||||
import javax.naming.InitialContext;
|
||||
import javax.naming.NamingException;
|
||||
|
||||
|
@ -140,7 +141,7 @@ public class Injection
|
|||
_resourceClass = resourceType;
|
||||
|
||||
//first look for a javabeans style setter matching the targetName
|
||||
String setter = "set"+target.substring(0,1).toUpperCase()+target.substring(1);
|
||||
String setter = "set"+target.substring(0,1).toUpperCase(Locale.ENGLISH)+target.substring(1);
|
||||
try
|
||||
{
|
||||
LOG.debug("Looking for method for setter: "+setter+" with arg "+_resourceClass);
|
||||
|
|
|
@ -26,6 +26,7 @@ import java.sql.ResultSet;
|
|||
import java.sql.SQLException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
import javax.naming.InitialContext;
|
||||
import javax.naming.NameNotFoundException;
|
||||
import javax.naming.NamingException;
|
||||
|
@ -413,7 +414,7 @@ public class DataSourceLoginService extends MappedLoginService
|
|||
DatabaseMetaData metaData = connection.getMetaData();
|
||||
|
||||
//check if tables exist
|
||||
String tableName = (metaData.storesLowerCaseIdentifiers()? _userTableName.toLowerCase(): (metaData.storesUpperCaseIdentifiers()?_userTableName.toUpperCase(): _userTableName));
|
||||
String tableName = (metaData.storesLowerCaseIdentifiers()? _userTableName.toLowerCase(Locale.ENGLISH): (metaData.storesUpperCaseIdentifiers()?_userTableName.toUpperCase(Locale.ENGLISH): _userTableName));
|
||||
ResultSet result = metaData.getTables(null, null, tableName, null);
|
||||
if (!result.next())
|
||||
{
|
||||
|
@ -431,7 +432,7 @@ public class DataSourceLoginService extends MappedLoginService
|
|||
|
||||
result.close();
|
||||
|
||||
tableName = (metaData.storesLowerCaseIdentifiers()? _roleTableName.toLowerCase(): (metaData.storesUpperCaseIdentifiers()?_roleTableName.toUpperCase(): _roleTableName));
|
||||
tableName = (metaData.storesLowerCaseIdentifiers()? _roleTableName.toLowerCase(Locale.ENGLISH): (metaData.storesUpperCaseIdentifiers()?_roleTableName.toUpperCase(Locale.ENGLISH): _roleTableName));
|
||||
result = metaData.getTables(null, null, tableName, null);
|
||||
if (!result.next())
|
||||
{
|
||||
|
@ -448,7 +449,7 @@ public class DataSourceLoginService extends MappedLoginService
|
|||
|
||||
result.close();
|
||||
|
||||
tableName = (metaData.storesLowerCaseIdentifiers()? _userRoleTableName.toLowerCase(): (metaData.storesUpperCaseIdentifiers()?_userRoleTableName.toUpperCase(): _userRoleTableName));
|
||||
tableName = (metaData.storesLowerCaseIdentifiers()? _userRoleTableName.toLowerCase(Locale.ENGLISH): (metaData.storesUpperCaseIdentifiers()?_userRoleTableName.toUpperCase(Locale.ENGLISH): _userRoleTableName));
|
||||
result = metaData.getTables(null, null, tableName, null);
|
||||
if (!result.next())
|
||||
{
|
||||
|
|
|
@ -30,6 +30,7 @@ import java.util.Collections;
|
|||
import java.util.Enumeration;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
import java.util.Map;
|
||||
import java.util.StringTokenizer;
|
||||
|
||||
|
@ -489,7 +490,7 @@ public class ProxyServlet implements Servlet
|
|||
protected void onResponseHeader(Buffer name, Buffer value) throws IOException
|
||||
{
|
||||
String nameString = name.toString();
|
||||
String s = nameString.toLowerCase();
|
||||
String s = nameString.toLowerCase(Locale.ENGLISH);
|
||||
if (!_DontProxyHeaders.contains(s) || (HttpHeader.CONNECTION.is(name) && HttpHeaderValue.CLOSE.is(value)))
|
||||
{
|
||||
if (debug != 0)
|
||||
|
@ -560,7 +561,7 @@ public class ProxyServlet implements Servlet
|
|||
String connectionHdr = request.getHeader("Connection");
|
||||
if (connectionHdr != null)
|
||||
{
|
||||
connectionHdr = connectionHdr.toLowerCase();
|
||||
connectionHdr = connectionHdr.toLowerCase(Locale.ENGLISH);
|
||||
if (connectionHdr.indexOf("keep-alive") < 0 && connectionHdr.indexOf("close") < 0)
|
||||
connectionHdr = null;
|
||||
}
|
||||
|
@ -578,7 +579,7 @@ public class ProxyServlet implements Servlet
|
|||
{
|
||||
// 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;
|
||||
|
|
|
@ -27,6 +27,7 @@ import java.io.IOException;
|
|||
import java.net.Socket;
|
||||
import java.net.SocketTimeoutException;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.Locale;
|
||||
import java.util.Map;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
|
@ -105,7 +106,7 @@ public abstract class AbstractConnectHandlerTest
|
|||
assertTrue(header.lookingAt());
|
||||
String headerName = header.group(1);
|
||||
String headerValue = header.group(2);
|
||||
headers.put(headerName.toLowerCase(), headerValue.toLowerCase());
|
||||
headers.put(headerName.toLowerCase(Locale.ENGLISH), headerValue.toLowerCase(Locale.ENGLISH));
|
||||
}
|
||||
|
||||
StringBuilder body;
|
||||
|
|
|
@ -79,6 +79,20 @@ public class RewriteHandlerTest extends AbstractRuleTestCase
|
|||
@Test
|
||||
public void test() throws Exception
|
||||
{
|
||||
_response.setStatus(200);
|
||||
_request.setHandled(false);
|
||||
_handler.setOriginalPathAttribute("/before");
|
||||
_handler.setRewriteRequestURI(true);
|
||||
_handler.setRewritePathInfo(true);
|
||||
_request.setRequestURI("/xxx/bar");
|
||||
_request.setPathInfo("/xxx/bar");
|
||||
_handler.handle("/xxx/bar",_request,_request, _response);
|
||||
assertEquals(201,_response.getStatus());
|
||||
assertEquals("/bar/zzz",_request.getAttribute("target"));
|
||||
assertEquals("/bar/zzz",_request.getAttribute("URI"));
|
||||
assertEquals("/bar/zzz",_request.getAttribute("info"));
|
||||
assertEquals(null,_request.getAttribute("before"));
|
||||
|
||||
_response.setStatus(200);
|
||||
_request.setHandled(false);
|
||||
_handler.setOriginalPathAttribute("/before");
|
||||
|
|
|
@ -70,10 +70,12 @@ public abstract class SecurityHandler extends HandlerWrapper implements Authenti
|
|||
private Authenticator.Factory _authenticatorFactory=new DefaultAuthenticatorFactory();
|
||||
private String _realmName;
|
||||
private String _authMethod;
|
||||
private final Map<String,String> _initParameters=new HashMap<>();
|
||||
private final Map<String,String> _initParameters=new HashMap<String,String>();
|
||||
private LoginService _loginService;
|
||||
private IdentityService _identityService;
|
||||
private boolean _renewSession=true;
|
||||
private boolean _discoveredIdentityService = false;
|
||||
private boolean _discoveredLoginService = false;
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
protected SecurityHandler()
|
||||
|
@ -338,7 +340,10 @@ public abstract class SecurityHandler extends HandlerWrapper implements Authenti
|
|||
// many different ways these can be constructed and injected.
|
||||
|
||||
if (_loginService==null)
|
||||
{
|
||||
setLoginService(findLoginService());
|
||||
_discoveredLoginService = true;
|
||||
}
|
||||
|
||||
if (_identityService==null)
|
||||
{
|
||||
|
@ -350,6 +355,8 @@ public abstract class SecurityHandler extends HandlerWrapper implements Authenti
|
|||
|
||||
if (_identityService==null && _realmName!=null)
|
||||
setIdentityService(new DefaultIdentityService());
|
||||
|
||||
_discoveredIdentityService = true;
|
||||
}
|
||||
|
||||
if (_loginService!=null)
|
||||
|
@ -375,6 +382,27 @@ public abstract class SecurityHandler extends HandlerWrapper implements Authenti
|
|||
super.doStart();
|
||||
}
|
||||
|
||||
@Override
|
||||
/* ------------------------------------------------------------ */
|
||||
protected void doStop() throws Exception
|
||||
{
|
||||
//if we discovered the services (rather than had them explicitly configured), remove them.
|
||||
if (_discoveredIdentityService)
|
||||
{
|
||||
removeBean(_identityService);
|
||||
_identityService = null;
|
||||
|
||||
}
|
||||
|
||||
if (_discoveredLoginService)
|
||||
{
|
||||
removeBean(_loginService);
|
||||
_loginService = null;
|
||||
}
|
||||
|
||||
super.doStop();
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
protected boolean checkSecurity(Request request)
|
||||
{
|
||||
|
|
|
@ -21,6 +21,7 @@ package org.eclipse.jetty.security.authentication;
|
|||
import java.io.IOException;
|
||||
import java.util.Collections;
|
||||
import java.util.Enumeration;
|
||||
import java.util.Locale;
|
||||
import javax.servlet.RequestDispatcher;
|
||||
import javax.servlet.ServletException;
|
||||
import javax.servlet.ServletRequest;
|
||||
|
@ -413,7 +414,7 @@ public class FormAuthenticator extends LoginAuthenticator
|
|||
@Override
|
||||
public long getDateHeader(String name)
|
||||
{
|
||||
if (name.toLowerCase().startsWith("if-"))
|
||||
if (name.toLowerCase(Locale.ENGLISH).startsWith("if-"))
|
||||
return -1;
|
||||
return super.getDateHeader(name);
|
||||
}
|
||||
|
@ -421,7 +422,7 @@ public class FormAuthenticator extends LoginAuthenticator
|
|||
@Override
|
||||
public String getHeader(String name)
|
||||
{
|
||||
if (name.toLowerCase().startsWith("if-"))
|
||||
if (name.toLowerCase(Locale.ENGLISH).startsWith("if-"))
|
||||
return null;
|
||||
return super.getHeader(name);
|
||||
}
|
||||
|
@ -435,7 +436,7 @@ public class FormAuthenticator extends LoginAuthenticator
|
|||
@Override
|
||||
public Enumeration<String> getHeaders(String name)
|
||||
{
|
||||
if (name.toLowerCase().startsWith("if-"))
|
||||
if (name.toLowerCase(Locale.ENGLISH).startsWith("if-"))
|
||||
return Collections.<String>enumeration(Collections.<String>emptyList());
|
||||
return super.getHeaders(name);
|
||||
}
|
||||
|
|
|
@ -25,6 +25,7 @@ import java.util.ArrayList;
|
|||
import java.util.Collection;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.CountDownLatch;
|
||||
import java.util.concurrent.Executor;
|
||||
|
@ -314,7 +315,7 @@ public abstract class AbstractConnector extends ContainerLifeCycle implements Co
|
|||
{
|
||||
synchronized (_factories)
|
||||
{
|
||||
return _factories.get(protocol.toLowerCase());
|
||||
return _factories.get(protocol.toLowerCase(Locale.ENGLISH));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -337,7 +338,7 @@ public abstract class AbstractConnector extends ContainerLifeCycle implements Co
|
|||
ConnectionFactory old=_factories.remove(factory.getProtocol());
|
||||
if (old!=null)
|
||||
removeBean(old);
|
||||
_factories.put(factory.getProtocol().toLowerCase(), factory);
|
||||
_factories.put(factory.getProtocol().toLowerCase(Locale.ENGLISH), factory);
|
||||
addBean(factory);
|
||||
if (_defaultProtocol==null)
|
||||
_defaultProtocol=factory.getProtocol();
|
||||
|
@ -348,7 +349,7 @@ public abstract class AbstractConnector extends ContainerLifeCycle implements Co
|
|||
{
|
||||
synchronized (_factories)
|
||||
{
|
||||
ConnectionFactory factory= _factories.remove(protocol.toLowerCase());
|
||||
ConnectionFactory factory= _factories.remove(protocol.toLowerCase(Locale.ENGLISH));
|
||||
removeBean(factory);
|
||||
return factory;
|
||||
}
|
||||
|
@ -403,7 +404,7 @@ public abstract class AbstractConnector extends ContainerLifeCycle implements Co
|
|||
|
||||
public void setDefaultProtocol(String defaultProtocol)
|
||||
{
|
||||
_defaultProtocol = defaultProtocol.toLowerCase();
|
||||
_defaultProtocol = defaultProtocol.toLowerCase(Locale.ENGLISH);
|
||||
if (isRunning())
|
||||
_defaultConnectionFactory=getConnectionFactory(_defaultProtocol);
|
||||
}
|
||||
|
|
|
@ -50,7 +50,7 @@ public abstract class AbstractNetworkConnector extends AbstractConnector impleme
|
|||
}
|
||||
|
||||
@Override
|
||||
@ManagedAttribute("Host this connector binds to")
|
||||
@ManagedAttribute("The network interface this connector binds to as an IP address or a hostname. If null or 0.0.0.0, then bind to all interfaces.")
|
||||
public String getHost()
|
||||
{
|
||||
return _host;
|
||||
|
@ -62,7 +62,7 @@ public abstract class AbstractNetworkConnector extends AbstractConnector impleme
|
|||
}
|
||||
|
||||
@Override
|
||||
@ManagedAttribute("Port this connector listens on")
|
||||
@ManagedAttribute("Port this connector listens on. If set the 0 a random port is assigned which may be obtained with getLocalPort()")
|
||||
public int getPort()
|
||||
{
|
||||
return _port;
|
||||
|
|
|
@ -75,7 +75,7 @@ public interface Connector extends LifeCycle, Graceful
|
|||
public List<String> getProtocols();
|
||||
|
||||
/**
|
||||
* @return the dle timeout for connections in milliseconds
|
||||
* @return the max idle timeout for connections in milliseconds
|
||||
*/
|
||||
@ManagedAttribute("maximum time a connection can be idle before being closed (in ms)")
|
||||
public long getIdleTimeout();
|
||||
|
|
|
@ -17,6 +17,8 @@
|
|||
//
|
||||
|
||||
package org.eclipse.jetty.server;
|
||||
import java.util.Locale;
|
||||
|
||||
import javax.servlet.http.Cookie;
|
||||
|
||||
import org.eclipse.jetty.util.LazyList;
|
||||
|
@ -283,7 +285,7 @@ public class CookieCutter
|
|||
{
|
||||
if (name.startsWith("$"))
|
||||
{
|
||||
String lowercaseName = name.toLowerCase();
|
||||
String lowercaseName = name.toLowerCase(Locale.ENGLISH);
|
||||
if ("$path".equals(lowercaseName))
|
||||
{
|
||||
if (cookie!=null)
|
||||
|
|
|
@ -420,39 +420,42 @@ public class HttpChannel<T> implements HttpParser.RequestHandler<T>, Runnable
|
|||
switch (header)
|
||||
{
|
||||
case EXPECT:
|
||||
HttpHeaderValue expect = HttpHeaderValue.CACHE.get(value);
|
||||
switch (expect == null ? HttpHeaderValue.UNKNOWN : expect)
|
||||
if (_version.getVersion()>=HttpVersion.HTTP_1_1.getVersion())
|
||||
{
|
||||
case CONTINUE:
|
||||
_expect100Continue = true;
|
||||
break;
|
||||
HttpHeaderValue expect = HttpHeaderValue.CACHE.get(value);
|
||||
switch (expect == null ? HttpHeaderValue.UNKNOWN : expect)
|
||||
{
|
||||
case CONTINUE:
|
||||
_expect100Continue = true;
|
||||
break;
|
||||
|
||||
case PROCESSING:
|
||||
_expect102Processing = true;
|
||||
break;
|
||||
case PROCESSING:
|
||||
_expect102Processing = true;
|
||||
break;
|
||||
|
||||
default:
|
||||
String[] values = value.split(",");
|
||||
for (int i = 0; values != null && i < values.length; i++)
|
||||
{
|
||||
expect = HttpHeaderValue.CACHE.get(values[i].trim());
|
||||
if (expect == null)
|
||||
_expect = true;
|
||||
else
|
||||
default:
|
||||
String[] values = value.split(",");
|
||||
for (int i = 0; values != null && i < values.length; i++)
|
||||
{
|
||||
switch (expect)
|
||||
expect = HttpHeaderValue.CACHE.get(values[i].trim());
|
||||
if (expect == null)
|
||||
_expect = true;
|
||||
else
|
||||
{
|
||||
case CONTINUE:
|
||||
_expect100Continue = true;
|
||||
break;
|
||||
case PROCESSING:
|
||||
_expect102Processing = true;
|
||||
break;
|
||||
default:
|
||||
_expect = true;
|
||||
switch (expect)
|
||||
{
|
||||
case CONTINUE:
|
||||
_expect100Continue = true;
|
||||
break;
|
||||
case PROCESSING:
|
||||
_expect102Processing = true;
|
||||
break;
|
||||
default:
|
||||
_expect = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
|
|
|
@ -237,6 +237,10 @@ public class HttpOutput extends ServletOutputStream
|
|||
response.getHttpFields().putDateField(HttpHeader.LAST_MODIFIED, lml);
|
||||
}
|
||||
|
||||
String etag=httpContent.getETag();
|
||||
if (etag!=null)
|
||||
response.getHttpFields().put(HttpHeader.ETAG,etag);
|
||||
|
||||
content = httpContent.getDirectBuffer();
|
||||
if (content == null)
|
||||
content = httpContent.getIndirectBuffer();
|
||||
|
|
|
@ -56,24 +56,18 @@ public class ResourceCache
|
|||
private final ResourceFactory _factory;
|
||||
private final ResourceCache _parent;
|
||||
private final MimeTypes _mimeTypes;
|
||||
private final boolean _etagSupported;
|
||||
|
||||
private boolean _useFileMappedBuffer=true;
|
||||
private int _maxCachedFileSize =4*1024*1024;
|
||||
private int _maxCachedFiles=2048;
|
||||
private int _maxCacheSize =32*1024*1024;
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
public ResourceCache(ResourceCache parent, ResourceFactory factory, MimeTypes mimeTypes,boolean useFileMappedBuffer)
|
||||
{
|
||||
this(parent,factory,mimeTypes);
|
||||
setUseFileMappedBuffer(useFileMappedBuffer);
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
/** Constructor.
|
||||
* @param mimeTypes Mimetype to use for meta data
|
||||
*/
|
||||
public ResourceCache(ResourceCache parent, ResourceFactory factory, MimeTypes mimeTypes)
|
||||
public ResourceCache(ResourceCache parent, ResourceFactory factory, MimeTypes mimeTypes,boolean useFileMappedBuffer,boolean etags)
|
||||
{
|
||||
_factory = factory;
|
||||
_cache=new ConcurrentHashMap<String,Content>();
|
||||
|
@ -81,6 +75,7 @@ public class ResourceCache
|
|||
_cachedFiles=new AtomicInteger();
|
||||
_mimeTypes=mimeTypes;
|
||||
_parent=parent;
|
||||
_etagSupported=etags;
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
|
@ -247,7 +242,7 @@ public class ResourceCache
|
|||
return content;
|
||||
}
|
||||
|
||||
return new HttpContent.ResourceAsHttpContent(resource,_mimeTypes.getMimeByExtension(resource.toString()),getMaxCachedFileSize());
|
||||
return new HttpContent.ResourceAsHttpContent(resource,_mimeTypes.getMimeByExtension(resource.toString()),getMaxCachedFileSize(),_etagSupported);
|
||||
|
||||
}
|
||||
|
||||
|
@ -375,6 +370,7 @@ public class ResourceCache
|
|||
final long _lastModified;
|
||||
final ByteBuffer _lastModifiedBytes;
|
||||
final ByteBuffer _contentType;
|
||||
final String _etag;
|
||||
|
||||
volatile long _lastAccessed;
|
||||
AtomicReference<ByteBuffer> _indirectBuffer=new AtomicReference<ByteBuffer>();
|
||||
|
@ -395,6 +391,8 @@ public class ResourceCache
|
|||
_cachedSize.addAndGet(_length);
|
||||
_cachedFiles.incrementAndGet();
|
||||
_lastAccessed=System.currentTimeMillis();
|
||||
|
||||
_etag=ResourceCache.this._etagSupported?resource.getWeakETag():null;
|
||||
}
|
||||
|
||||
|
||||
|
@ -422,11 +420,18 @@ public class ResourceCache
|
|||
{
|
||||
return _resource;
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
@Override
|
||||
public String getETag()
|
||||
{
|
||||
return _etag;
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
boolean isValid()
|
||||
{
|
||||
if (_lastModified==_resource.lastModified())
|
||||
if (_lastModified==_resource.lastModified() && _length==_resource.length())
|
||||
{
|
||||
_lastAccessed=System.currentTimeMillis();
|
||||
return true;
|
||||
|
|
|
@ -50,6 +50,7 @@ import org.eclipse.jetty.util.annotation.ManagedAttribute;
|
|||
import org.eclipse.jetty.util.annotation.ManagedObject;
|
||||
import org.eclipse.jetty.util.annotation.Name;
|
||||
import org.eclipse.jetty.util.component.Graceful;
|
||||
import org.eclipse.jetty.util.component.LifeCycle;
|
||||
import org.eclipse.jetty.util.log.Log;
|
||||
import org.eclipse.jetty.util.log.Logger;
|
||||
import org.eclipse.jetty.util.thread.QueuedThreadPool;
|
||||
|
@ -298,6 +299,14 @@ public class Server extends HandlerWrapper implements Attributes
|
|||
mex.ifExceptionThrow();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void start(LifeCycle l) throws Exception
|
||||
{
|
||||
// start connectors last
|
||||
if (!(l instanceof Connector))
|
||||
super.start(l);
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
@Override
|
||||
protected void doStop() throws Exception
|
||||
|
|
|
@ -83,17 +83,28 @@ public class ServerConnector extends AbstractNetworkConnector
|
|||
private volatile ServerSocketChannel _acceptChannel;
|
||||
private volatile boolean _inheritChannel = false;
|
||||
private volatile int _localPort = -1;
|
||||
private volatile int _acceptQueueSize = 128;
|
||||
private volatile int _acceptQueueSize = 0;
|
||||
private volatile boolean _reuseAddress = true;
|
||||
private volatile int _lingerTime = -1;
|
||||
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
/** HTTP Server Connection.
|
||||
* <p>Construct a ServerConnector with a private instance of {@link HttpConnectionFactory} as the only factory.</p>
|
||||
* @param server The {@link Server} this connector will accept connection for.
|
||||
*/
|
||||
public ServerConnector(
|
||||
@Name("server") Server server)
|
||||
{
|
||||
this(server,null,null,null,0,0,new HttpConnectionFactory());
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
/** Generic Server Connection with default configuration.
|
||||
* <p>Construct a Server Connector with the passed Connection factories.</p>
|
||||
* @param server The {@link Server} this connector will accept connection for.
|
||||
* @param factories Zero or more {@link ConnectionFactory} instances used to create and configure connections.
|
||||
*/
|
||||
public ServerConnector(
|
||||
@Name("server") Server server,
|
||||
@Name("factories") ConnectionFactory... factories)
|
||||
|
@ -101,6 +112,13 @@ public class ServerConnector extends AbstractNetworkConnector
|
|||
this(server,null,null,null,0,0,factories);
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
/** HTTP Server Connection.
|
||||
* <p>Construct a ServerConnector with a private instance of {@link HttpConnectionFactory} as the primary protocol</p>.
|
||||
* @param server The {@link Server} this connector will accept connection for.
|
||||
* @param sslContextFactory If non null, then a {@link SslConnectionFactory} is instantiated and prepended to the
|
||||
* list of HTTP Connection Factory.
|
||||
*/
|
||||
public ServerConnector(
|
||||
@Name("server") Server server,
|
||||
@Name("sslContextFactory") SslContextFactory sslContextFactory)
|
||||
|
@ -108,6 +126,13 @@ public class ServerConnector extends AbstractNetworkConnector
|
|||
this(server,null,null,null,0,0,AbstractConnectionFactory.getFactories(sslContextFactory,new HttpConnectionFactory()));
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
/** Generic SSL Server Connection.
|
||||
* @param server The {@link Server} this connector will accept connection for.
|
||||
* @param sslContextFactory If non null, then a {@link SslConnectionFactory} is instantiated and prepended to the
|
||||
* list of ConnectionFactories, with the first factory being the default protocol for the SslConnectionFactory.
|
||||
* @param factories Zero or more {@link ConnectionFactory} instances used to create and configure connections.
|
||||
*/
|
||||
public ServerConnector(
|
||||
@Name("server") Server server,
|
||||
@Name("sslContextFactory") SslContextFactory sslContextFactory,
|
||||
|
@ -116,24 +141,33 @@ public class ServerConnector extends AbstractNetworkConnector
|
|||
this(server,null,null,null,0,0,AbstractConnectionFactory.getFactories(sslContextFactory,factories));
|
||||
}
|
||||
|
||||
/**
|
||||
* @param server The server this connector will be added to. Must not be null.
|
||||
* @param executor An executor for this connector or null to use the servers executor
|
||||
* @param scheduler A scheduler for this connector or null to use the servers scheduler
|
||||
* @param pool A buffer pool for this connector or null to use a default {@link ByteBufferPool}
|
||||
* @param acceptors the number of acceptor threads to use, or 0 for a default value.
|
||||
* @param factories Zero or more {@link ConnectionFactory} instances.
|
||||
/** Generic Server Connection.
|
||||
* @param server
|
||||
* The server this connector will be accept connection for.
|
||||
* @param executor
|
||||
* An executor used to run tasks for handling requests, acceptors and selectors. I
|
||||
* If null then use the servers executor
|
||||
* @param scheduler
|
||||
* A scheduler used to schedule timeouts. If null then use the servers scheduler
|
||||
* @param bufferPool
|
||||
* A ByteBuffer pool used to allocate buffers. If null then create a private pool with default configuration.
|
||||
* @param acceptors
|
||||
* the number of acceptor threads to use, or 0 for a default value. Acceptors accept new TCP/IP connections.
|
||||
* @param selectors
|
||||
* the number of selector threads, or 0 for a default value. Selectors notice and schedule established connection that can make IO progress.
|
||||
* @param factories
|
||||
* Zero or more {@link ConnectionFactory} instances used to create and configure connections.
|
||||
*/
|
||||
public ServerConnector(
|
||||
@Name("server") Server server,
|
||||
@Name("executor") Executor executor,
|
||||
@Name("scheduler") Scheduler scheduler,
|
||||
@Name("bufferPool") ByteBufferPool pool,
|
||||
@Name("bufferPool") ByteBufferPool bufferPool,
|
||||
@Name("acceptors") int acceptors,
|
||||
@Name("selectors") int selectors,
|
||||
@Name("factories") ConnectionFactory... factories)
|
||||
{
|
||||
super(server,executor,scheduler,pool,acceptors,factories);
|
||||
super(server,executor,scheduler,bufferPool,acceptors,factories);
|
||||
_manager = new ServerConnectorManager(getExecutor(), getScheduler(), selectors > 0 ? selectors : Runtime.getRuntime().availableProcessors());
|
||||
addBean(_manager, true);
|
||||
}
|
||||
|
@ -298,8 +332,8 @@ public class ServerConnector extends AbstractNetworkConnector
|
|||
* @return the linger time
|
||||
* @see Socket#getSoLinger()
|
||||
*/
|
||||
@ManagedAttribute("linger time")
|
||||
public int getLingerTime()
|
||||
@ManagedAttribute("TCP/IP solinger time or -1 to disable")
|
||||
public int getSoLingerTime()
|
||||
{
|
||||
return _lingerTime;
|
||||
}
|
||||
|
|
|
@ -746,13 +746,13 @@ public class ContextHandler extends ScopedHandler implements Attributes, Gracefu
|
|||
|
||||
super.doStart();
|
||||
|
||||
// Context listeners
|
||||
// Call context listeners
|
||||
if (!_contextListeners.isEmpty())
|
||||
{
|
||||
ServletContextEvent event = new ServletContextEvent(_scontext);
|
||||
for (ServletContextListener listener:_contextListeners)
|
||||
callContextInitialized(listener, event);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
|
|
|
@ -66,6 +66,7 @@ public class ResourceHandler extends HandlerWrapper
|
|||
String _cacheControl;
|
||||
boolean _aliases;
|
||||
boolean _directory;
|
||||
boolean _etags;
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
public ResourceHandler()
|
||||
|
@ -125,6 +126,24 @@ public class ResourceHandler extends HandlerWrapper
|
|||
_directory = directory;
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
/**
|
||||
* @return True if ETag processing is done
|
||||
*/
|
||||
public boolean isEtags()
|
||||
{
|
||||
return _etags;
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
/**
|
||||
* @param etags True if ETag processing is done
|
||||
*/
|
||||
public void setEtags(boolean etags)
|
||||
{
|
||||
_etags = etags;
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
@Override
|
||||
public void doStart()
|
||||
|
@ -417,6 +436,21 @@ public class ResourceHandler extends HandlerWrapper
|
|||
|
||||
// set some headers
|
||||
long last_modified=resource.lastModified();
|
||||
String etag=null;
|
||||
if (_etags)
|
||||
{
|
||||
// simple handling of only a single etag
|
||||
String ifnm = request.getHeader(HttpHeader.IF_NONE_MATCH.asString());
|
||||
etag=resource.getWeakETag();
|
||||
if (ifnm!=null && resource!=null && ifnm.equals(etag))
|
||||
{
|
||||
response.setStatus(HttpStatus.NOT_MODIFIED_304);
|
||||
baseRequest.getResponse().getHttpFields().put(HttpHeader.ETAG,etag);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (last_modified>0)
|
||||
{
|
||||
long if_modified=request.getDateHeader(HttpHeader.IF_MODIFIED_SINCE.asString());
|
||||
|
@ -434,6 +468,9 @@ public class ResourceHandler extends HandlerWrapper
|
|||
// set the headers
|
||||
doResponseHeaders(response,resource,mime!=null?mime.toString():null);
|
||||
response.setDateHeader(HttpHeader.LAST_MODIFIED.asString(),last_modified);
|
||||
if (_etags)
|
||||
baseRequest.getResponse().getHttpFields().put(HttpHeader.ETAG,etag);
|
||||
|
||||
if(skipContentBody)
|
||||
return;
|
||||
// Send the content
|
||||
|
|
|
@ -513,33 +513,40 @@ public class HashSessionManager extends AbstractSessionManager
|
|||
protected synchronized HashedSession restoreSession(String idInCuster)
|
||||
{
|
||||
File file = new File(_storeDir,idInCuster);
|
||||
FileInputStream in = null;
|
||||
Exception error = null;
|
||||
try
|
||||
{
|
||||
if (file.exists())
|
||||
{
|
||||
FileInputStream in = new FileInputStream(file);
|
||||
in = new FileInputStream(file);
|
||||
HashedSession session = restoreSession(in, null);
|
||||
in.close();
|
||||
addSession(session, false);
|
||||
session.didActivate();
|
||||
file.delete();
|
||||
return session;
|
||||
}
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
|
||||
if (isDeleteUnrestorableSessions())
|
||||
error = e;
|
||||
}
|
||||
finally
|
||||
{
|
||||
if (in != null)
|
||||
try {in.close();} catch (Exception x) {__log.ignore(x);}
|
||||
|
||||
if (error != null)
|
||||
{
|
||||
if (file.exists())
|
||||
if (isDeleteUnrestorableSessions() && file.exists())
|
||||
{
|
||||
file.delete();
|
||||
LOG.warn("Deleting file for unrestorable session "+idInCuster, e);
|
||||
LOG.warn("Deleting file for unrestorable session "+idInCuster, error);
|
||||
}
|
||||
else
|
||||
LOG.warn("Problem restoring session "+idInCuster, error);
|
||||
}
|
||||
else
|
||||
LOG.warn("Problem restoring session "+idInCuster, e);
|
||||
|
||||
file.delete(); //delete successfully restored file
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
|
|
@ -34,6 +34,7 @@ import java.util.Collection;
|
|||
import java.util.HashSet;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
import java.util.Random;
|
||||
import java.util.Timer;
|
||||
import java.util.TimerTask;
|
||||
|
@ -124,7 +125,7 @@ public class JDBCSessionIdManager extends AbstractSessionIdManager
|
|||
public DatabaseAdaptor (DatabaseMetaData dbMeta)
|
||||
throws SQLException
|
||||
{
|
||||
_dbName = dbMeta.getDatabaseProductName().toLowerCase();
|
||||
_dbName = dbMeta.getDatabaseProductName().toLowerCase(Locale.ENGLISH);
|
||||
LOG.debug ("Using database {}",_dbName);
|
||||
_isLower = dbMeta.storesLowerCaseIdentifiers();
|
||||
_isUpper = dbMeta.storesUpperCaseIdentifiers();
|
||||
|
@ -140,9 +141,9 @@ public class JDBCSessionIdManager extends AbstractSessionIdManager
|
|||
public String convertIdentifier (String identifier)
|
||||
{
|
||||
if (_isLower)
|
||||
return identifier.toLowerCase();
|
||||
return identifier.toLowerCase(Locale.ENGLISH);
|
||||
if (_isUpper)
|
||||
return identifier.toUpperCase();
|
||||
return identifier.toUpperCase(Locale.ENGLISH);
|
||||
|
||||
return identifier;
|
||||
}
|
||||
|
|
|
@ -47,9 +47,9 @@ public class ResourceCacheTest
|
|||
Resource[] r = rc.getResources();
|
||||
MimeTypes mime = new MimeTypes();
|
||||
|
||||
ResourceCache rc3 = new ResourceCache(null,r[2],mime,false);
|
||||
ResourceCache rc2 = new ResourceCache(rc3,r[1],mime,false);
|
||||
ResourceCache rc1 = new ResourceCache(rc2,r[0],mime,false);
|
||||
ResourceCache rc3 = new ResourceCache(null,r[2],mime,false,false);
|
||||
ResourceCache rc2 = new ResourceCache(rc3,r[1],mime,false,false);
|
||||
ResourceCache rc1 = new ResourceCache(rc2,r[0],mime,false,false);
|
||||
|
||||
assertEquals("1 - one", getContent(rc1, "1.txt"));
|
||||
assertEquals("2 - two", getContent(rc1, "2.txt"));
|
||||
|
@ -77,8 +77,8 @@ public class ResourceCacheTest
|
|||
Resource[] r = rc.getResources();
|
||||
MimeTypes mime = new MimeTypes();
|
||||
|
||||
ResourceCache rc3 = new ResourceCache(null,r[2],mime,false);
|
||||
ResourceCache rc2 = new ResourceCache(rc3,r[1],mime,false)
|
||||
ResourceCache rc3 = new ResourceCache(null,r[2],mime,false,false);
|
||||
ResourceCache rc2 = new ResourceCache(rc3,r[1],mime,false,false)
|
||||
{
|
||||
@Override
|
||||
public boolean isCacheable(Resource resource)
|
||||
|
@ -87,7 +87,7 @@ public class ResourceCacheTest
|
|||
}
|
||||
};
|
||||
|
||||
ResourceCache rc1 = new ResourceCache(rc2,r[0],mime,false);
|
||||
ResourceCache rc1 = new ResourceCache(rc2,r[0],mime,false,false);
|
||||
|
||||
assertEquals("1 - one", getContent(rc1, "1.txt"));
|
||||
assertEquals("2 - two", getContent(rc1, "2.txt"));
|
||||
|
@ -127,7 +127,7 @@ public class ResourceCacheTest
|
|||
directory=Resource.newResource(files[0].getParentFile().getAbsolutePath());
|
||||
|
||||
|
||||
cache=new ResourceCache(null,directory,new MimeTypes(),false);
|
||||
cache=new ResourceCache(null,directory,new MimeTypes(),false,false);
|
||||
|
||||
cache.setMaxCacheSize(95);
|
||||
cache.setMaxCachedFileSize(85);
|
||||
|
|
|
@ -24,6 +24,7 @@ import java.io.IOException;
|
|||
import java.io.InputStream;
|
||||
import java.io.UnsupportedEncodingException;
|
||||
import java.net.Socket;
|
||||
import java.util.Locale;
|
||||
|
||||
import org.eclipse.jetty.server.session.SessionHandler;
|
||||
import org.eclipse.jetty.util.IO;
|
||||
|
@ -52,7 +53,7 @@ public class SelectChannelTimeoutTest extends ConnectorTimeoutTest
|
|||
|
||||
_handler.setSuspendFor(100);
|
||||
_handler.setResumeAfter(25);
|
||||
assertTrue(process(null).toUpperCase().contains("RESUMED"));
|
||||
assertTrue(process(null).toUpperCase(Locale.ENGLISH).contains("RESUMED"));
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -66,7 +67,7 @@ public class SelectChannelTimeoutTest extends ConnectorTimeoutTest
|
|||
_server.start();
|
||||
|
||||
_handler.setSuspendFor(50);
|
||||
assertTrue(process(null).toUpperCase().contains("TIMEOUT"));
|
||||
assertTrue(process(null).toUpperCase(Locale.ENGLISH).contains("TIMEOUT"));
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -81,7 +82,7 @@ public class SelectChannelTimeoutTest extends ConnectorTimeoutTest
|
|||
|
||||
_handler.setSuspendFor(100);
|
||||
_handler.setCompleteAfter(25);
|
||||
assertTrue(process(null).toUpperCase().contains("COMPLETED"));
|
||||
assertTrue(process(null).toUpperCase(Locale.ENGLISH).contains("COMPLETED"));
|
||||
}
|
||||
|
||||
private synchronized String process(String content) throws UnsupportedEncodingException, IOException, InterruptedException
|
||||
|
|
|
@ -30,6 +30,7 @@ import java.net.Socket;
|
|||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.Locale;
|
||||
import java.util.Map;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
|
@ -153,7 +154,7 @@ public class IPAccessHandlerTest
|
|||
assertTrue(header.lookingAt());
|
||||
String headerName = header.group(1);
|
||||
String headerValue = header.group(2);
|
||||
headers.put(headerName.toLowerCase(), headerValue.toLowerCase());
|
||||
headers.put(headerName.toLowerCase(Locale.ENGLISH), headerValue.toLowerCase(Locale.ENGLISH));
|
||||
}
|
||||
|
||||
StringBuilder body = new StringBuilder();
|
||||
|
|
|
@ -25,7 +25,6 @@ import java.io.OutputStream;
|
|||
import java.net.MalformedURLException;
|
||||
import java.net.URL;
|
||||
import java.nio.ByteBuffer;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Enumeration;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
@ -53,6 +52,7 @@ import org.eclipse.jetty.server.handler.ContextHandler;
|
|||
import org.eclipse.jetty.util.BufferUtil;
|
||||
import org.eclipse.jetty.util.IO;
|
||||
import org.eclipse.jetty.util.MultiPartOutputStream;
|
||||
import org.eclipse.jetty.util.QuotedStringTokenizer;
|
||||
import org.eclipse.jetty.util.URIUtil;
|
||||
import org.eclipse.jetty.util.log.Log;
|
||||
import org.eclipse.jetty.util.log.Logger;
|
||||
|
@ -111,6 +111,8 @@ import org.eclipse.jetty.util.resource.ResourceFactory;
|
|||
*
|
||||
* aliases If True, aliases of resources are allowed (eg. symbolic
|
||||
* links and caps variations). May bypass security constraints.
|
||||
*
|
||||
* etags If True, weak etags will be generated and handled.
|
||||
*
|
||||
* maxCacheSize The maximum total size of the cache or 0 for no cache.
|
||||
* maxCachedFileSize The maximum size of a file to cache
|
||||
|
@ -147,6 +149,7 @@ public class DefaultServlet extends HttpServlet implements ResourceFactory
|
|||
private boolean _redirectWelcome=false;
|
||||
private boolean _gzip=true;
|
||||
private boolean _pathInfoOnly=false;
|
||||
private boolean _etags=false;
|
||||
|
||||
private Resource _resourceBase;
|
||||
private ResourceCache _cache;
|
||||
|
@ -255,11 +258,13 @@ public class DefaultServlet extends HttpServlet implements ResourceFactory
|
|||
LOG.debug("Cache {}={}",resourceCache,_cache);
|
||||
}
|
||||
|
||||
_etags = getInitBoolean("etags",_etags);
|
||||
|
||||
try
|
||||
{
|
||||
if (_cache==null && max_cached_files>0)
|
||||
{
|
||||
_cache= new ResourceCache(null,this,_mimeTypes,_useFileMappedBuffer);
|
||||
_cache= new ResourceCache(null,this,_mimeTypes,_useFileMappedBuffer,_etags);
|
||||
|
||||
if (max_cache_size>0)
|
||||
_cache.setMaxCacheSize(max_cache_size);
|
||||
|
@ -280,6 +285,7 @@ public class DefaultServlet extends HttpServlet implements ResourceFactory
|
|||
if (h.getServletInstance()==this)
|
||||
_defaultHolder=h;
|
||||
|
||||
|
||||
if (LOG.isDebugEnabled())
|
||||
LOG.debug("resource base = "+_resourceBase);
|
||||
}
|
||||
|
@ -492,7 +498,7 @@ public class DefaultServlet extends HttpServlet implements ResourceFactory
|
|||
{
|
||||
// ensure we have content
|
||||
if (content==null)
|
||||
content=new HttpContent.ResourceAsHttpContent(resource,_mimeTypes.getMimeByExtension(resource.toString()),response.getBufferSize());
|
||||
content=new HttpContent.ResourceAsHttpContent(resource,_mimeTypes.getMimeByExtension(resource.toString()),response.getBufferSize(),_etags);
|
||||
|
||||
if (included.booleanValue() || passConditionalHeaders(request,response, resource,content))
|
||||
{
|
||||
|
@ -563,7 +569,7 @@ public class DefaultServlet extends HttpServlet implements ResourceFactory
|
|||
}
|
||||
else
|
||||
{
|
||||
content=new HttpContent.ResourceAsHttpContent(resource,_mimeTypes.getMimeByExtension(resource.toString()));
|
||||
content=new HttpContent.ResourceAsHttpContent(resource,_mimeTypes.getMimeByExtension(resource.toString()),_etags);
|
||||
if (included.booleanValue() || passConditionalHeaders(request,response, resource,content))
|
||||
sendDirectory(request,response,resource,pathInContext);
|
||||
}
|
||||
|
@ -665,6 +671,77 @@ public class DefaultServlet extends HttpServlet implements ResourceFactory
|
|||
{
|
||||
if (!HttpMethod.HEAD.is(request.getMethod()))
|
||||
{
|
||||
if (_etags)
|
||||
{
|
||||
String ifm=request.getHeader(HttpHeader.IF_MATCH.asString());
|
||||
if (ifm!=null)
|
||||
{
|
||||
boolean match=false;
|
||||
if (content!=null && content.getETag()!=null)
|
||||
{
|
||||
QuotedStringTokenizer quoted = new QuotedStringTokenizer(ifm,", ",false,true);
|
||||
while (!match && quoted.hasMoreTokens())
|
||||
{
|
||||
String tag = quoted.nextToken();
|
||||
if (content.getETag().toString().equals(tag))
|
||||
match=true;
|
||||
}
|
||||
}
|
||||
|
||||
if (!match)
|
||||
{
|
||||
Response r = Response.getResponse(response);
|
||||
r.reset(true);
|
||||
r.setStatus(HttpServletResponse.SC_PRECONDITION_FAILED);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
String ifnm=request.getHeader(HttpHeader.IF_NONE_MATCH.asString());
|
||||
if (ifnm!=null && content!=null && content.getETag()!=null)
|
||||
{
|
||||
// Look for GzipFiltered version of etag
|
||||
if (content.getETag().toString().equals(request.getAttribute("o.e.j.s.GzipFilter.ETag")))
|
||||
{
|
||||
Response r = Response.getResponse(response);
|
||||
r.reset(true);
|
||||
r.setStatus(HttpServletResponse.SC_NOT_MODIFIED);
|
||||
r.getHttpFields().put(HttpHeader.ETAG,ifnm);
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
// Handle special case of exact match.
|
||||
if (content.getETag().toString().equals(ifnm))
|
||||
{
|
||||
Response r = Response.getResponse(response);
|
||||
r.reset(true);
|
||||
r.setStatus(HttpServletResponse.SC_NOT_MODIFIED);
|
||||
r.getHttpFields().put(HttpHeader.ETAG,content.getETag());
|
||||
return false;
|
||||
}
|
||||
|
||||
// Handle list of tags
|
||||
QuotedStringTokenizer quoted = new QuotedStringTokenizer(ifnm,", ",false,true);
|
||||
while (quoted.hasMoreTokens())
|
||||
{
|
||||
String tag = quoted.nextToken();
|
||||
if (content.getETag().toString().equals(tag))
|
||||
{
|
||||
Response r = Response.getResponse(response);
|
||||
r.reset(true);
|
||||
r.setStatus(HttpServletResponse.SC_NOT_MODIFIED);
|
||||
r.getHttpFields().put(HttpHeader.ETAG,content.getETag());
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// If etag requires content to be served, then do not check if-modified-since
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
// Handle if modified since
|
||||
String ifms=request.getHeader(HttpHeader.IF_MODIFIED_SINCE.asString());
|
||||
if (ifms!=null)
|
||||
{
|
||||
|
@ -964,7 +1041,7 @@ public class DefaultServlet extends HttpServlet implements ResourceFactory
|
|||
/* ------------------------------------------------------------ */
|
||||
protected void writeHeaders(HttpServletResponse response,HttpContent content,long count)
|
||||
throws IOException
|
||||
{
|
||||
{
|
||||
if (content.getContentType()!=null && response.getContentType()==null)
|
||||
response.setContentType(content.getContentType().toString());
|
||||
|
||||
|
@ -986,6 +1063,9 @@ public class DefaultServlet extends HttpServlet implements ResourceFactory
|
|||
r.setLongContentLength(count);
|
||||
|
||||
writeOptionHeaders(fields);
|
||||
|
||||
if (_etags)
|
||||
fields.put(HttpHeader.ETAG,content.getETag());
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -1002,11 +1082,14 @@ public class DefaultServlet extends HttpServlet implements ResourceFactory
|
|||
}
|
||||
|
||||
writeOptionHeaders(response);
|
||||
|
||||
if (_etags)
|
||||
response.setHeader(HttpHeader.ETAG.asString(),content.getETag().toString());
|
||||
}
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
protected void writeOptionHeaders(HttpFields fields) throws IOException
|
||||
protected void writeOptionHeaders(HttpFields fields)
|
||||
{
|
||||
if (_acceptRanges)
|
||||
fields.put(HttpHeader.ACCEPT_RANGES,"bytes");
|
||||
|
@ -1016,7 +1099,7 @@ public class DefaultServlet extends HttpServlet implements ResourceFactory
|
|||
}
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
protected void writeOptionHeaders(HttpServletResponse response) throws IOException
|
||||
protected void writeOptionHeaders(HttpServletResponse response)
|
||||
{
|
||||
if (_acceptRanges)
|
||||
response.setHeader(HttpHeader.ACCEPT_RANGES.asString(),"bytes");
|
||||
|
@ -1024,8 +1107,6 @@ public class DefaultServlet extends HttpServlet implements ResourceFactory
|
|||
if (_cacheControl!=null)
|
||||
response.setHeader(HttpHeader.CACHE_CONTROL.asString(),_cacheControl);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
/*
|
||||
|
|
|
@ -21,6 +21,7 @@ package org.eclipse.jetty.servlet;
|
|||
import java.io.IOException;
|
||||
import java.util.Enumeration;
|
||||
import java.util.HashMap;
|
||||
import java.util.Locale;
|
||||
import java.util.Map;
|
||||
import javax.servlet.ServletContext;
|
||||
import javax.servlet.ServletException;
|
||||
|
@ -90,7 +91,7 @@ public class Invoker extends HttpServlet
|
|||
{
|
||||
String param=(String)e.nextElement();
|
||||
String value=getInitParameter(param);
|
||||
String lvalue=value.toLowerCase();
|
||||
String lvalue=value.toLowerCase(Locale.ENGLISH);
|
||||
if ("nonContextServlets".equals(param))
|
||||
{
|
||||
_nonContextServlets=value.length()>0 && lvalue.startsWith("t");
|
||||
|
|
|
@ -257,7 +257,7 @@ public class ServletContextHandler extends ContextHandler
|
|||
@Override
|
||||
protected void startContext() throws Exception
|
||||
{
|
||||
// OK to Initialize servlet handler now
|
||||
|
||||
if (_servletHandler != null)
|
||||
{
|
||||
for (int i=_decorators.size()-1;i>=0; i--)
|
||||
|
@ -270,11 +270,13 @@ public class ServletContextHandler extends ContextHandler
|
|||
for (ServletHolder holder:_servletHandler.getServlets())
|
||||
decorator.decorateServletHolder(holder);
|
||||
}
|
||||
|
||||
_servletHandler.initialize();
|
||||
}
|
||||
|
||||
super.startContext();
|
||||
|
||||
// OK to Initialize servlet handler now that all relevant object trees have been started
|
||||
if (_servletHandler != null)
|
||||
_servletHandler.initialize();
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
|
|
|
@ -68,6 +68,7 @@ import org.eclipse.jetty.util.TypeUtil;
|
|||
import org.eclipse.jetty.util.URIUtil;
|
||||
import org.eclipse.jetty.util.annotation.ManagedAttribute;
|
||||
import org.eclipse.jetty.util.annotation.ManagedObject;
|
||||
import org.eclipse.jetty.util.component.LifeCycle;
|
||||
import org.eclipse.jetty.util.log.Log;
|
||||
import org.eclipse.jetty.util.log.Logger;
|
||||
|
||||
|
@ -160,6 +161,19 @@ public class ServletHandler extends ScopedHandler
|
|||
|
||||
super.doStart();
|
||||
}
|
||||
|
||||
|
||||
/* ----------------------------------------------------------------- */
|
||||
@Override
|
||||
protected void start(LifeCycle l) throws Exception
|
||||
{
|
||||
//Don't start the whole object tree (ie all the servlet and filter Holders) when
|
||||
//this handler starts. They have a slightly special lifecycle, and should only be
|
||||
//started AFTER the handlers have all started (and the ContextHandler has called
|
||||
//the context listeners).
|
||||
if (!(l instanceof Holder))
|
||||
super.start(l);
|
||||
}
|
||||
|
||||
/* ----------------------------------------------------------------- */
|
||||
@Override
|
||||
|
@ -715,8 +729,22 @@ public class ServletHandler extends ScopedHandler
|
|||
mx.add(e);
|
||||
}
|
||||
}
|
||||
mx.ifExceptionThrow();
|
||||
}
|
||||
|
||||
//start the servlet and filter holders now
|
||||
for (Holder<?> h: getBeans(Holder.class))
|
||||
{
|
||||
try
|
||||
{
|
||||
h.start();
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
mx.add(e);
|
||||
}
|
||||
}
|
||||
|
||||
mx.ifExceptionThrow();
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
|
|
|
@ -23,6 +23,8 @@ import java.io.FileOutputStream;
|
|||
import java.io.IOException;
|
||||
import java.util.EnumSet;
|
||||
import javax.servlet.DispatcherType;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
import javax.servlet.Filter;
|
||||
import javax.servlet.FilterChain;
|
||||
import javax.servlet.FilterConfig;
|
||||
|
@ -30,12 +32,14 @@ import javax.servlet.ServletException;
|
|||
import javax.servlet.ServletRequest;
|
||||
import javax.servlet.ServletResponse;
|
||||
|
||||
import org.eclipse.jetty.http.HttpFields;
|
||||
import org.eclipse.jetty.server.LocalConnector;
|
||||
import org.eclipse.jetty.server.Server;
|
||||
import org.eclipse.jetty.toolchain.test.FS;
|
||||
import org.eclipse.jetty.toolchain.test.MavenTestingUtils;
|
||||
import org.eclipse.jetty.toolchain.test.OS;
|
||||
import org.eclipse.jetty.toolchain.test.TestingDir;
|
||||
import org.eclipse.jetty.util.DateCache;
|
||||
import org.eclipse.jetty.util.IO;
|
||||
import org.eclipse.jetty.util.StringUtil;
|
||||
import org.hamcrest.Matchers;
|
||||
|
@ -495,6 +499,123 @@ public class DefaultServletTest
|
|||
assertResponseNotContains("Content-Length: 12", response);
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void testIfModifiedSmall() throws Exception
|
||||
{
|
||||
testIfModified("Hello World");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testIfModifiedLarge() throws Exception
|
||||
{
|
||||
testIfModified("Now is the time for all good men to come to the aid of the party");
|
||||
}
|
||||
|
||||
public void testIfModified(String content) throws Exception
|
||||
{
|
||||
testdir.ensureEmpty();
|
||||
File resBase = testdir.getFile("docroot");
|
||||
FS.ensureDirExists(resBase);
|
||||
File file = new File(resBase, "file.txt");
|
||||
|
||||
String resBasePath = resBase.getAbsolutePath();
|
||||
|
||||
ServletHolder defholder = context.addServlet(DefaultServlet.class, "/");
|
||||
defholder.setInitParameter("resourceBase", resBasePath);
|
||||
defholder.setInitParameter("maxCacheSize", "4096");
|
||||
defholder.setInitParameter("maxCachedFileSize", "25");
|
||||
defholder.setInitParameter("maxCachedFiles", "100");
|
||||
|
||||
String response = connector.getResponses("GET /context/file.txt HTTP/1.0\r\n\r\n");
|
||||
assertResponseContains("404", response);
|
||||
|
||||
createFile(file, content);
|
||||
response = connector.getResponses("GET /context/file.txt HTTP/1.1\r\nHost:test\r\nConnection:close\r\n\r\n");
|
||||
|
||||
assertResponseContains("200", response);
|
||||
assertResponseContains("Last-Modified", response);
|
||||
String last_modified = getHeaderValue("Last-Modified",response);
|
||||
|
||||
response = connector.getResponses("GET /context/file.txt HTTP/1.1\r\nHost:test\r\nConnection:close\r\nIf-Modified-Since: "+last_modified+"\r\n\r\n");
|
||||
assertResponseContains("304", response);
|
||||
|
||||
response = connector.getResponses("GET /context/file.txt HTTP/1.1\r\nHost:test\r\nConnection:close\r\nIf-Modified-Since: "+HttpFields.formatDate(System.currentTimeMillis()-10000)+"\r\n\r\n");
|
||||
assertResponseContains("200", response);
|
||||
|
||||
response = connector.getResponses("GET /context/file.txt HTTP/1.1\r\nHost:test\r\nConnection:close\r\nIf-Modified-Since: "+HttpFields.formatDate(System.currentTimeMillis()+10000)+"\r\n\r\n");
|
||||
assertResponseContains("304", response);
|
||||
|
||||
response = connector.getResponses("GET /context/file.txt HTTP/1.1\r\nHost:test\r\nConnection:close\r\nIf-Unmodified-Since: "+HttpFields.formatDate(System.currentTimeMillis()+10000)+"\r\n\r\n");
|
||||
assertResponseContains("200", response);
|
||||
|
||||
response = connector.getResponses("GET /context/file.txt HTTP/1.1\r\nHost:test\r\nConnection:close\r\nIf-Unmodified-Since: "+HttpFields.formatDate(System.currentTimeMillis()-10000)+"\r\n\r\n");
|
||||
assertResponseContains("412", response);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testIfETagSmall() throws Exception
|
||||
{
|
||||
testIfETag("Hello World");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testIfETagLarge() throws Exception
|
||||
{
|
||||
testIfETag("Now is the time for all good men to come to the aid of the party");
|
||||
}
|
||||
|
||||
public void testIfETag(String content) throws Exception
|
||||
{
|
||||
testdir.ensureEmpty();
|
||||
File resBase = testdir.getFile("docroot");
|
||||
FS.ensureDirExists(resBase);
|
||||
File file = new File(resBase, "file.txt");
|
||||
|
||||
String resBasePath = resBase.getAbsolutePath();
|
||||
|
||||
ServletHolder defholder = context.addServlet(DefaultServlet.class, "/");
|
||||
defholder.setInitParameter("resourceBase", resBasePath);
|
||||
defholder.setInitParameter("maxCacheSize", "4096");
|
||||
defholder.setInitParameter("maxCachedFileSize", "25");
|
||||
defholder.setInitParameter("maxCachedFiles", "100");
|
||||
defholder.setInitParameter("etags", "true");
|
||||
|
||||
String response;
|
||||
|
||||
createFile(file, content);
|
||||
response = connector.getResponses("GET /context/file.txt HTTP/1.1\r\nHost:test\r\nConnection:close\r\n\r\n");
|
||||
|
||||
assertResponseContains("200", response);
|
||||
assertResponseContains("ETag", response);
|
||||
String etag = getHeaderValue("ETag",response);
|
||||
|
||||
response = connector.getResponses("GET /context/file.txt HTTP/1.1\r\nHost:test\r\nConnection:close\r\nIf-None-Match: "+etag+"\r\n\r\n");
|
||||
assertResponseContains("304", response);
|
||||
|
||||
response = connector.getResponses("GET /context/file.txt HTTP/1.1\r\nHost:test\r\nConnection:close\r\nIf-None-Match: wibble,"+etag+",wobble\r\n\r\n");
|
||||
assertResponseContains("304", response);
|
||||
|
||||
response = connector.getResponses("GET /context/file.txt HTTP/1.1\r\nHost:test\r\nConnection:close\r\nIf-None-Match: wibble\r\n\r\n");
|
||||
assertResponseContains("200", response);
|
||||
|
||||
response = connector.getResponses("GET /context/file.txt HTTP/1.1\r\nHost:test\r\nConnection:close\r\nIf-None-Match: wibble, wobble\r\n\r\n");
|
||||
assertResponseContains("200", response);
|
||||
|
||||
response = connector.getResponses("GET /context/file.txt HTTP/1.1\r\nHost:test\r\nConnection:close\r\nIf-Match: "+etag+"\r\n\r\n");
|
||||
assertResponseContains("200", response);
|
||||
|
||||
response = connector.getResponses("GET /context/file.txt HTTP/1.1\r\nHost:test\r\nConnection:close\r\nIf-Match: wibble,"+etag+",wobble\r\n\r\n");
|
||||
assertResponseContains("200", response);
|
||||
|
||||
response = connector.getResponses("GET /context/file.txt HTTP/1.1\r\nHost:test\r\nConnection:close\r\nIf-Match: wibble\r\n\r\n");
|
||||
assertResponseContains("412", response);
|
||||
|
||||
response = connector.getResponses("GET /context/file.txt HTTP/1.1\r\nHost:test\r\nConnection:close\r\nIf-Match: wibble, wobble\r\n\r\n");
|
||||
assertResponseContains("412", response);
|
||||
|
||||
}
|
||||
|
||||
public static class OutputFilter implements Filter
|
||||
{
|
||||
@Override
|
||||
|
@ -583,4 +704,13 @@ public class DefaultServletTest
|
|||
Assert.assertTrue("Deleting: " + file.getName(), file.delete());
|
||||
}
|
||||
}
|
||||
|
||||
private String getHeaderValue(String header, String response)
|
||||
{
|
||||
Pattern pattern=Pattern.compile("[\\r\\n]"+header+"\\s*:\\s*(.*?)\\s*[\\r\\n]");
|
||||
Matcher matcher = pattern.matcher(response);
|
||||
if (matcher.find())
|
||||
return matcher.group(1);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -24,6 +24,7 @@ import java.io.InputStream;
|
|||
import java.io.OutputStream;
|
||||
import java.util.Enumeration;
|
||||
import java.util.HashMap;
|
||||
import java.util.Locale;
|
||||
import java.util.Map;
|
||||
import javax.servlet.ServletException;
|
||||
import javax.servlet.http.HttpServlet;
|
||||
|
@ -138,7 +139,7 @@ public class CGI extends HttpServlet
|
|||
if (!_env.envMap.containsKey("SystemRoot"))
|
||||
{
|
||||
String os = System.getProperty("os.name");
|
||||
if (os != null && os.toLowerCase().indexOf("windows") != -1)
|
||||
if (os != null && os.toLowerCase(Locale.ENGLISH).indexOf("windows") != -1)
|
||||
{
|
||||
_env.set("SystemRoot","C:\\WINDOWS");
|
||||
}
|
||||
|
@ -255,7 +256,7 @@ public class CGI extends HttpServlet
|
|||
{
|
||||
String name = (String)enm.nextElement();
|
||||
String value = req.getHeader(name);
|
||||
env.set("HTTP_" + name.toUpperCase().replace('-','_'),value);
|
||||
env.set("HTTP_" + name.toUpperCase(Locale.ENGLISH).replace('-','_'),value);
|
||||
}
|
||||
|
||||
// these extra ones were from printenv on www.dev.nomura.co.uk
|
||||
|
|
|
@ -20,6 +20,7 @@ package org.eclipse.jetty.servlets;
|
|||
|
||||
import java.io.IOException;
|
||||
import java.util.HashSet;
|
||||
import java.util.Locale;
|
||||
import java.util.Set;
|
||||
import java.util.StringTokenizer;
|
||||
import java.util.regex.Pattern;
|
||||
|
@ -104,8 +105,10 @@ public class GzipFilter extends UserAgentFilter
|
|||
{
|
||||
private static final Logger LOG = Log.getLogger(GzipFilter.class);
|
||||
public final static String GZIP="gzip";
|
||||
public final static String ETAG_GZIP="-gzip\"";
|
||||
public final static String DEFLATE="deflate";
|
||||
|
||||
public final static String ETAG_DEFLATE="-deflate\"";
|
||||
public final static String ETAG="o.e.j.s.GzipFilter.ETag";
|
||||
|
||||
protected Set<String> _mimeTypes;
|
||||
protected int _bufferSize=8192;
|
||||
|
@ -233,6 +236,16 @@ public class GzipFilter extends UserAgentFilter
|
|||
return;
|
||||
}
|
||||
|
||||
// Special handling for etags
|
||||
String etag = request.getHeader("If-None-Match");
|
||||
if (etag!=null)
|
||||
{
|
||||
if (etag.endsWith(ETAG_GZIP))
|
||||
request.setAttribute(ETAG,etag.substring(0,etag.length()-ETAG_GZIP.length())+'"');
|
||||
else if (etag.endsWith(ETAG_DEFLATE))
|
||||
request.setAttribute(ETAG,etag.substring(0,etag.length()-ETAG_DEFLATE.length())+'"');
|
||||
}
|
||||
|
||||
CompressedResponseWrapper wrappedResponse = createWrappedResponse(request,response,compressionType);
|
||||
|
||||
boolean exceptional=true;
|
||||
|
@ -277,7 +290,7 @@ public class GzipFilter extends UserAgentFilter
|
|||
{
|
||||
for (int i=0; i< encodings.length; i++)
|
||||
{
|
||||
if (encodings[i].toLowerCase().contains(GZIP))
|
||||
if (encodings[i].toLowerCase(Locale.ENGLISH).contains(GZIP))
|
||||
{
|
||||
if (isEncodingAcceptable(encodings[i]))
|
||||
{
|
||||
|
@ -286,7 +299,7 @@ public class GzipFilter extends UserAgentFilter
|
|||
}
|
||||
}
|
||||
|
||||
if (encodings[i].toLowerCase().contains(DEFLATE))
|
||||
if (encodings[i].toLowerCase(Locale.ENGLISH).contains(DEFLATE))
|
||||
{
|
||||
if (isEncodingAcceptable(encodings[i]))
|
||||
{
|
||||
|
@ -360,9 +373,9 @@ public class GzipFilter extends UserAgentFilter
|
|||
wrappedResponse = new CompressedResponseWrapper(request,response)
|
||||
{
|
||||
@Override
|
||||
protected AbstractCompressedStream newCompressedStream(HttpServletRequest request,HttpServletResponse response,long contentLength,int bufferSize, int minCompressSize) throws IOException
|
||||
protected AbstractCompressedStream newCompressedStream(HttpServletRequest request,HttpServletResponse response) throws IOException
|
||||
{
|
||||
return new AbstractCompressedStream(compressionType,request,response,contentLength,bufferSize,minCompressSize)
|
||||
return new AbstractCompressedStream(compressionType,request,this)
|
||||
{
|
||||
@Override
|
||||
protected DeflaterOutputStream createStream() throws IOException
|
||||
|
@ -378,9 +391,9 @@ public class GzipFilter extends UserAgentFilter
|
|||
wrappedResponse = new CompressedResponseWrapper(request,response)
|
||||
{
|
||||
@Override
|
||||
protected AbstractCompressedStream newCompressedStream(HttpServletRequest request,HttpServletResponse response,long contentLength,int bufferSize, int minCompressSize) throws IOException
|
||||
protected AbstractCompressedStream newCompressedStream(HttpServletRequest request,HttpServletResponse response) throws IOException
|
||||
{
|
||||
return new AbstractCompressedStream(compressionType,request,response,contentLength,bufferSize,minCompressSize)
|
||||
return new AbstractCompressedStream(compressionType,request,this)
|
||||
{
|
||||
@Override
|
||||
protected DeflaterOutputStream createStream() throws IOException
|
||||
|
@ -415,6 +428,7 @@ public class GzipFilter extends UserAgentFilter
|
|||
this.wrappedResponse = wrappedResponse;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onComplete(Continuation continuation)
|
||||
{
|
||||
try
|
||||
|
@ -427,6 +441,7 @@ public class GzipFilter extends UserAgentFilter
|
|||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onTimeout(Continuation continuation)
|
||||
{
|
||||
}
|
||||
|
|
|
@ -74,9 +74,9 @@ public class IncludableGzipFilter extends GzipFilter
|
|||
wrappedResponse = new IncludableResponseWrapper(request,response)
|
||||
{
|
||||
@Override
|
||||
protected AbstractCompressedStream newCompressedStream(HttpServletRequest request,HttpServletResponse response,long contentLength,int bufferSize, int minCompressSize) throws IOException
|
||||
protected AbstractCompressedStream newCompressedStream(HttpServletRequest request,HttpServletResponse response) throws IOException
|
||||
{
|
||||
return new AbstractCompressedStream(compressionType,request,response,contentLength,bufferSize,minCompressSize)
|
||||
return new AbstractCompressedStream(compressionType,request,this)
|
||||
{
|
||||
@Override
|
||||
protected DeflaterOutputStream createStream() throws IOException
|
||||
|
@ -101,9 +101,9 @@ public class IncludableGzipFilter extends GzipFilter
|
|||
wrappedResponse = new IncludableResponseWrapper(request,response)
|
||||
{
|
||||
@Override
|
||||
protected AbstractCompressedStream newCompressedStream(HttpServletRequest request,HttpServletResponse response,long contentLength,int bufferSize, int minCompressSize) throws IOException
|
||||
protected AbstractCompressedStream newCompressedStream(HttpServletRequest request,HttpServletResponse response) throws IOException
|
||||
{
|
||||
return new AbstractCompressedStream(compressionType,request,response,contentLength,bufferSize,minCompressSize)
|
||||
return new AbstractCompressedStream(compressionType,request,this)
|
||||
{
|
||||
@Override
|
||||
protected DeflaterOutputStream createStream() throws IOException
|
||||
|
|
|
@ -31,6 +31,7 @@ import java.util.Enumeration;
|
|||
import java.util.HashMap;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
import java.util.Map;
|
||||
import javax.servlet.Filter;
|
||||
import javax.servlet.FilterChain;
|
||||
|
|
|
@ -39,43 +39,26 @@ import org.eclipse.jetty.util.ByteArrayOutputStream2;
|
|||
public abstract class AbstractCompressedStream extends ServletOutputStream
|
||||
{
|
||||
private final String _encoding;
|
||||
protected HttpServletRequest _request;
|
||||
protected HttpServletResponse _response;
|
||||
protected final CompressedResponseWrapper _wrapper;
|
||||
protected final HttpServletResponse _response;
|
||||
protected OutputStream _out;
|
||||
protected ByteArrayOutputStream2 _bOut;
|
||||
protected DeflaterOutputStream _compressedOutputStream;
|
||||
protected boolean _closed;
|
||||
protected int _bufferSize;
|
||||
protected int _minCompressSize;
|
||||
protected long _contentLength;
|
||||
protected boolean _doNotCompress;
|
||||
|
||||
/**
|
||||
* Instantiates a new compressed stream.
|
||||
*
|
||||
* @param request
|
||||
* the request
|
||||
* @param response
|
||||
* the response
|
||||
* @param contentLength
|
||||
* the content length
|
||||
* @param bufferSize
|
||||
* the buffer size
|
||||
* @param minCompressSize
|
||||
* the min compress size
|
||||
* @throws IOException
|
||||
* Signals that an I/O exception has occurred.
|
||||
*/
|
||||
public AbstractCompressedStream(String encoding,HttpServletRequest request, HttpServletResponse response, long contentLength, int bufferSize, int minCompressSize)
|
||||
public AbstractCompressedStream(String encoding,HttpServletRequest request, CompressedResponseWrapper wrapper)
|
||||
throws IOException
|
||||
{
|
||||
_encoding=encoding;
|
||||
_request = request;
|
||||
_response = response;
|
||||
_contentLength = contentLength;
|
||||
_bufferSize = bufferSize;
|
||||
_minCompressSize = minCompressSize;
|
||||
if (minCompressSize == 0)
|
||||
_wrapper = wrapper;
|
||||
_response = (HttpServletResponse)wrapper.getResponse();
|
||||
|
||||
if (_wrapper.getMinCompressSize()==0)
|
||||
doCompress();
|
||||
}
|
||||
|
||||
|
@ -95,21 +78,19 @@ public abstract class AbstractCompressedStream extends ServletOutputStream
|
|||
_doNotCompress = false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the content length.
|
||||
*
|
||||
* @param length
|
||||
* the new content length
|
||||
*/
|
||||
public void setContentLength(long length)
|
||||
/* ------------------------------------------------------------ */
|
||||
public void setContentLength()
|
||||
{
|
||||
_contentLength = length;
|
||||
if (_doNotCompress && length >= 0)
|
||||
if (_doNotCompress)
|
||||
{
|
||||
if (_contentLength < Integer.MAX_VALUE)
|
||||
_response.setContentLength((int)_contentLength);
|
||||
else
|
||||
_response.setHeader("Content-Length",Long.toString(_contentLength));
|
||||
long length=_wrapper.getContentLength();
|
||||
if (length>=0)
|
||||
{
|
||||
if (length < Integer.MAX_VALUE)
|
||||
_response.setContentLength((int)length);
|
||||
else
|
||||
_response.setHeader("Content-Length",Long.toString(length));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -122,7 +103,8 @@ public abstract class AbstractCompressedStream extends ServletOutputStream
|
|||
{
|
||||
if (_out == null || _bOut != null)
|
||||
{
|
||||
if (_contentLength > 0 && _contentLength < _minCompressSize)
|
||||
long length=_wrapper.getContentLength();
|
||||
if (length > 0 && length < _wrapper.getMinCompressSize())
|
||||
doNotCompress();
|
||||
else
|
||||
doCompress();
|
||||
|
@ -141,15 +123,19 @@ public abstract class AbstractCompressedStream extends ServletOutputStream
|
|||
if (_closed)
|
||||
return;
|
||||
|
||||
if (_request.getAttribute("javax.servlet.include.request_uri") != null)
|
||||
if (_wrapper.getRequest().getAttribute("javax.servlet.include.request_uri") != null)
|
||||
flush();
|
||||
else
|
||||
{
|
||||
if (_bOut != null)
|
||||
{
|
||||
if (_contentLength < 0)
|
||||
_contentLength = _bOut.getCount();
|
||||
if (_contentLength < _minCompressSize)
|
||||
long length=_wrapper.getContentLength();
|
||||
if (length < 0)
|
||||
{
|
||||
length = _bOut.getCount();
|
||||
_wrapper.setContentLength(length);
|
||||
}
|
||||
if (length < _wrapper.getMinCompressSize())
|
||||
doNotCompress();
|
||||
else
|
||||
doCompress();
|
||||
|
@ -179,7 +165,8 @@ public abstract class AbstractCompressedStream extends ServletOutputStream
|
|||
{
|
||||
if (_out == null || _bOut != null)
|
||||
{
|
||||
if (_contentLength > 0 && _contentLength < _minCompressSize)
|
||||
long length=_wrapper.getContentLength();
|
||||
if (length > 0 && length < _wrapper.getMinCompressSize())
|
||||
doNotCompress();
|
||||
else
|
||||
doCompress();
|
||||
|
@ -248,6 +235,10 @@ public abstract class AbstractCompressedStream extends ServletOutputStream
|
|||
_out.write(_bOut.getBuf(),0,_bOut.getCount());
|
||||
_bOut=null;
|
||||
}
|
||||
|
||||
String etag=_wrapper.getETag();
|
||||
if (etag!=null)
|
||||
setHeader("ETag",etag.substring(0,etag.length()-1)+'-'+_encoding+'"');
|
||||
}
|
||||
else
|
||||
doNotCompress();
|
||||
|
@ -266,10 +257,13 @@ public abstract class AbstractCompressedStream extends ServletOutputStream
|
|||
throw new IllegalStateException("Compressed output stream is already assigned.");
|
||||
if (_out == null || _bOut != null)
|
||||
{
|
||||
if (_wrapper.getETag()!=null)
|
||||
setHeader("ETag",_wrapper.getETag());
|
||||
|
||||
_doNotCompress = true;
|
||||
|
||||
_out = _response.getOutputStream();
|
||||
setContentLength(_contentLength);
|
||||
setContentLength();
|
||||
|
||||
if (_bOut != null)
|
||||
_out.write(_bOut.getBuf(),0,_bOut.getCount());
|
||||
|
@ -280,30 +274,32 @@ public abstract class AbstractCompressedStream extends ServletOutputStream
|
|||
/**
|
||||
* Check out.
|
||||
*
|
||||
* @param length
|
||||
* @param lengthToWrite
|
||||
* the length
|
||||
* @throws IOException
|
||||
* Signals that an I/O exception has occurred.
|
||||
*/
|
||||
private void checkOut(int length) throws IOException
|
||||
private void checkOut(int lengthToWrite) throws IOException
|
||||
{
|
||||
if (_closed)
|
||||
throw new IOException("CLOSED");
|
||||
|
||||
if (_out == null)
|
||||
{
|
||||
if (_response.isCommitted() || (_contentLength >= 0 && _contentLength < _minCompressSize))
|
||||
long length=_wrapper.getContentLength();
|
||||
if (_response.isCommitted() || (length >= 0 && length < _wrapper.getMinCompressSize()))
|
||||
doNotCompress();
|
||||
else if (length > _minCompressSize)
|
||||
else if (lengthToWrite > _wrapper.getMinCompressSize())
|
||||
doCompress();
|
||||
else
|
||||
_out = _bOut = new ByteArrayOutputStream2(_bufferSize);
|
||||
_out = _bOut = new ByteArrayOutputStream2(_wrapper.getBufferSize());
|
||||
}
|
||||
else if (_bOut != null)
|
||||
{
|
||||
if (_response.isCommitted() || (_contentLength >= 0 && _contentLength < _minCompressSize))
|
||||
long length=_wrapper.getContentLength();
|
||||
if (_response.isCommitted() || (length >= 0 && length < _wrapper.getMinCompressSize()))
|
||||
doNotCompress();
|
||||
else if (length >= (_bOut.getBuf().length - _bOut.getCount()))
|
||||
else if (lengthToWrite >= (_bOut.getBuf().length - _bOut.getCount()))
|
||||
doCompress();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -47,15 +47,48 @@ public abstract class CompressedResponseWrapper extends HttpServletResponseWrapp
|
|||
|
||||
private PrintWriter _writer;
|
||||
private AbstractCompressedStream _compressedStream;
|
||||
private String _etag;
|
||||
private long _contentLength=-1;
|
||||
private boolean _noCompression;
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
public CompressedResponseWrapper(HttpServletRequest request, HttpServletResponse response)
|
||||
{
|
||||
super(response);
|
||||
_request = request;
|
||||
}
|
||||
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
public long getContentLength()
|
||||
{
|
||||
return _contentLength;
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
public int getBufferSize()
|
||||
{
|
||||
return _bufferSize;
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
public int getMinCompressSize()
|
||||
{
|
||||
return _minCompressSize;
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
public String getETag()
|
||||
{
|
||||
return _etag;
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
public HttpServletRequest getRequest()
|
||||
{
|
||||
return _request;
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
/**
|
||||
* @see org.eclipse.jetty.servlets.gzip.CompressedResponseWrapper#setMimeTypes(java.util.Set)
|
||||
|
@ -147,7 +180,7 @@ public abstract class CompressedResponseWrapper extends HttpServletResponseWrapp
|
|||
{
|
||||
_contentLength=length;
|
||||
if (_compressedStream!=null)
|
||||
_compressedStream.setContentLength(length);
|
||||
_compressedStream.setContentLength();
|
||||
else if (_noCompression && _contentLength>=0)
|
||||
{
|
||||
HttpServletResponse response = (HttpServletResponse)getResponse();
|
||||
|
@ -161,7 +194,7 @@ public abstract class CompressedResponseWrapper extends HttpServletResponseWrapp
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
/**
|
||||
* @see org.eclipse.jetty.servlets.gzip.CompressedResponseWrapper#addHeader(java.lang.String, java.lang.String)
|
||||
|
@ -173,7 +206,7 @@ public abstract class CompressedResponseWrapper extends HttpServletResponseWrapp
|
|||
{
|
||||
_contentLength=Long.parseLong(value);
|
||||
if (_compressedStream!=null)
|
||||
_compressedStream.setContentLength(_contentLength);
|
||||
_compressedStream.setContentLength();
|
||||
}
|
||||
else if ("content-type".equalsIgnoreCase(name))
|
||||
{
|
||||
|
@ -187,6 +220,8 @@ public abstract class CompressedResponseWrapper extends HttpServletResponseWrapp
|
|||
noCompression();
|
||||
}
|
||||
}
|
||||
else if ("etag".equalsIgnoreCase(name))
|
||||
_etag=value;
|
||||
else
|
||||
super.addHeader(name,value);
|
||||
}
|
||||
|
@ -324,10 +359,21 @@ public abstract class CompressedResponseWrapper extends HttpServletResponseWrapp
|
|||
noCompression();
|
||||
}
|
||||
}
|
||||
else if ("etag".equalsIgnoreCase(name))
|
||||
_etag=value;
|
||||
else
|
||||
super.setHeader(name,value);
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
@Override
|
||||
public boolean containsHeader(String name)
|
||||
{
|
||||
if ("etag".equalsIgnoreCase(name) && _etag!=null)
|
||||
return true;
|
||||
return super.containsHeader(name);
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
/**
|
||||
* @see org.eclipse.jetty.servlets.gzip.CompressedResponseWrapper#getOutputStream()
|
||||
|
@ -343,7 +389,7 @@ public abstract class CompressedResponseWrapper extends HttpServletResponseWrapp
|
|||
return getResponse().getOutputStream();
|
||||
}
|
||||
|
||||
_compressedStream=newCompressedStream(_request,(HttpServletResponse)getResponse(),_contentLength,_bufferSize,_minCompressSize);
|
||||
_compressedStream=newCompressedStream(_request,(HttpServletResponse)getResponse());
|
||||
}
|
||||
else if (_writer!=null)
|
||||
throw new IllegalStateException("getWriter() called");
|
||||
|
@ -369,7 +415,7 @@ public abstract class CompressedResponseWrapper extends HttpServletResponseWrapp
|
|||
return getResponse().getWriter();
|
||||
}
|
||||
|
||||
_compressedStream=newCompressedStream(_request,(HttpServletResponse)getResponse(),_contentLength,_bufferSize,_minCompressSize);
|
||||
_compressedStream=newCompressedStream(_request,(HttpServletResponse)getResponse());
|
||||
_writer=newWriter(_compressedStream,getCharacterEncoding());
|
||||
}
|
||||
return _writer;
|
||||
|
@ -386,7 +432,7 @@ public abstract class CompressedResponseWrapper extends HttpServletResponseWrapp
|
|||
{
|
||||
_contentLength=value;
|
||||
if (_compressedStream!=null)
|
||||
_compressedStream.setContentLength(_contentLength);
|
||||
_compressedStream.setContentLength();
|
||||
}
|
||||
else
|
||||
super.setIntHeader(name,value);
|
||||
|
@ -410,6 +456,6 @@ public abstract class CompressedResponseWrapper extends HttpServletResponseWrapp
|
|||
/**
|
||||
*@return the underlying CompressedStream implementation
|
||||
*/
|
||||
protected abstract AbstractCompressedStream newCompressedStream(HttpServletRequest _request, HttpServletResponse response, long _contentLength2, int _bufferSize2, int _minCompressedSize2) throws IOException;
|
||||
protected abstract AbstractCompressedStream newCompressedStream(HttpServletRequest _request, HttpServletResponse response) throws IOException;
|
||||
|
||||
}
|
||||
|
|
|
@ -293,9 +293,9 @@ public class GzipHandler extends HandlerWrapper
|
|||
}
|
||||
|
||||
@Override
|
||||
protected AbstractCompressedStream newCompressedStream(HttpServletRequest request,HttpServletResponse response,long contentLength,int bufferSize, int minCompressSize) throws IOException
|
||||
protected AbstractCompressedStream newCompressedStream(HttpServletRequest request,HttpServletResponse response) throws IOException
|
||||
{
|
||||
return new AbstractCompressedStream("gzip",request,response,contentLength,bufferSize,minCompressSize)
|
||||
return new AbstractCompressedStream("gzip",request,this)
|
||||
{
|
||||
@Override
|
||||
protected DeflaterOutputStream createStream() throws IOException
|
||||
|
|
|
@ -26,6 +26,7 @@ import java.net.URL;
|
|||
import java.util.Arrays;
|
||||
import java.util.EnumSet;
|
||||
import java.util.HashSet;
|
||||
import java.util.Locale;
|
||||
import java.util.Set;
|
||||
import javax.servlet.DispatcherType;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
|
@ -62,7 +63,7 @@ public class PutFilterTest
|
|||
FilterHolder holder = tester.addFilter(PutFilter.class,"/*",EnumSet.of(DispatcherType.REQUEST));
|
||||
holder.setInitParameter("delAllowed","true");
|
||||
// Bloody Windows does not allow file renaming
|
||||
if (!System.getProperty("os.name").toLowerCase().contains("windows"))
|
||||
if (!System.getProperty("os.name").toLowerCase(Locale.ENGLISH).contains("windows"))
|
||||
holder.setInitParameter("putAtomic","true");
|
||||
tester.start();
|
||||
}
|
||||
|
|
|
@ -21,6 +21,7 @@ package org.eclipse.jetty.spdy.generator;
|
|||
import java.io.ByteArrayOutputStream;
|
||||
import java.nio.ByteBuffer;
|
||||
import java.nio.charset.Charset;
|
||||
import java.util.Locale;
|
||||
|
||||
import org.eclipse.jetty.spdy.CompressionDictionary;
|
||||
import org.eclipse.jetty.spdy.CompressionFactory;
|
||||
|
@ -45,7 +46,7 @@ public class HeadersBlockGenerator
|
|||
writeCount(version, buffer, headers.size());
|
||||
for (Fields.Field header : headers)
|
||||
{
|
||||
String name = header.name().toLowerCase();
|
||||
String name = header.name().toLowerCase(Locale.ENGLISH);
|
||||
byte[] nameBytes = name.getBytes(iso1);
|
||||
writeNameLength(version, buffer, nameBytes.length);
|
||||
buffer.write(nameBytes, 0, nameBytes.length);
|
||||
|
|
|
@ -25,7 +25,7 @@
|
|||
<Set name="TrustStorePath"><Property name="jetty.home" default="." />/etc/keystore</Set>
|
||||
<Set name="TrustStorePassword">OBF:1vny1zlo1x8e1vnw1vn61x8g1zlu1vn4</Set>
|
||||
</New>
|
||||
|
||||
|
||||
<!-- =========================================================== -->
|
||||
<!-- Create a TLS specific HttpConfiguration based on the -->
|
||||
<!-- common HttpConfiguration defined in jetty.xml -->
|
||||
|
@ -38,7 +38,7 @@
|
|||
<Arg><New class="org.eclipse.jetty.server.SecureRequestCustomizer"/></Arg>
|
||||
</Call>
|
||||
</New>
|
||||
|
||||
|
||||
<!-- =========================================================== -->
|
||||
<!-- Create a push strategy which can be used by reference by -->
|
||||
<!-- individual connection factories below. -->
|
||||
|
@ -47,15 +47,30 @@
|
|||
<!-- for all configuration that may be set here. -->
|
||||
<!-- =========================================================== -->
|
||||
<New id="pushStrategy" class="org.eclipse.jetty.spdy.server.http.ReferrerPushStrategy">
|
||||
<Arg name="pushPatterns" type="List">
|
||||
<Array type="String">
|
||||
<Item>.*\.css</Item>
|
||||
<Item>.*\.js</Item>
|
||||
<Item>.*\.png</Item>
|
||||
<Item>.*\.jpg</Item>
|
||||
<Item>.*\.gif</Item>
|
||||
</Array>
|
||||
</Arg>
|
||||
<!-- Uncomment to blacklist browsers for this push strategy. If one of the blacklisted Strings occurs in the
|
||||
user-agent header sent by the client, push will be disabled for this browser. This is case insensitive" -->
|
||||
<!--
|
||||
<Set name="UserAgentBlacklist">
|
||||
<Array type="String">
|
||||
<Item>.*(?i)firefox/14.*</Item>
|
||||
<Item>.*(?i)firefox/15.*</Item>
|
||||
<Item>.*(?i)firefox/16.*</Item>
|
||||
</Array>
|
||||
</Set>
|
||||
-->
|
||||
|
||||
<!-- Uncomment to override default file extensions to push -->
|
||||
<!--
|
||||
<Set name="PushRegexps">
|
||||
<Array type="String">
|
||||
<Item>.*\.css</Item>
|
||||
<Item>.*\.js</Item>
|
||||
<Item>.*\.png</Item>
|
||||
<Item>.*\.jpg</Item>
|
||||
<Item>.*\.gif</Item>
|
||||
</Array>
|
||||
</Set>
|
||||
-->
|
||||
<Set name="referrerPushPeriod">5000</Set>
|
||||
<Set name="maxAssociatedResources">32</Set>
|
||||
</New>
|
||||
|
@ -64,7 +79,7 @@
|
|||
<!-- Add a SPDY/HTTPS Connector. -->
|
||||
<!-- Configure an o.e.j.server.ServerConnector with connection -->
|
||||
<!-- factories for TLS (aka SSL), NPN, SPDY and HTTP to provide -->
|
||||
<!-- a connector that can accept HTTPS or SPDY connections. -->
|
||||
<!-- a connector that can accept HTTPS or SPDY connections. -->
|
||||
<!-- -->
|
||||
<!-- All accepted TLS connections are initially wired to a NPN -->
|
||||
<!-- connection, which attempts to use a TLS extension to -->
|
||||
|
@ -87,7 +102,7 @@
|
|||
<Arg name="server"><Ref id="Server" /></Arg>
|
||||
<Arg name="factories">
|
||||
<Array type="org.eclipse.jetty.server.ConnectionFactory">
|
||||
|
||||
|
||||
<!-- SSL Connection factory with NPN as next protocol -->
|
||||
<Item>
|
||||
<New class="org.eclipse.jetty.server.SslConnectionFactory">
|
||||
|
@ -113,7 +128,7 @@
|
|||
<New class="org.eclipse.jetty.spdy.server.http.HTTPSPDYServerConnectionFactory">
|
||||
<Arg name="version" type="int">3</Arg>
|
||||
<Arg name="config"><Ref id="tlsHttpConfig" /></Arg>
|
||||
<Arg name="pushStrategy"><Ref id="pushStrategy"/></Arg>
|
||||
<Arg name="pushStrategy"><Ref id="pushStrategy"/></Arg>
|
||||
</New>
|
||||
</Item>
|
||||
|
||||
|
@ -133,7 +148,7 @@
|
|||
</Item>
|
||||
</Array>
|
||||
</Arg>
|
||||
|
||||
|
||||
<Set name="host"><Property name="jetty.host" /></Set>
|
||||
<Set name="port"><Property name="jetty.tls.port" default="8443" /></Set>
|
||||
<Set name="idleTimeout">30000</Set>
|
||||
|
|
|
@ -23,6 +23,7 @@ import java.util.Arrays;
|
|||
import java.util.Collections;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.concurrent.ConcurrentMap;
|
||||
|
@ -32,32 +33,25 @@ import java.util.regex.Pattern;
|
|||
|
||||
import org.eclipse.jetty.spdy.api.Stream;
|
||||
import org.eclipse.jetty.util.Fields;
|
||||
import org.eclipse.jetty.util.annotation.Name;
|
||||
import org.eclipse.jetty.util.log.Log;
|
||||
import org.eclipse.jetty.util.log.Logger;
|
||||
|
||||
/**
|
||||
* <p>A SPDY push strategy that auto-populates push metadata based on referrer URLs.</p>
|
||||
* <p>A typical request for a main resource such as <tt>index.html</tt> is immediately
|
||||
* followed by a number of requests for associated resources. Associated resource requests
|
||||
* will have a <tt>Referer</tt> HTTP header that points to <tt>index.html</tt>, which is
|
||||
* used to link the associated resource to the main resource.</p>
|
||||
* <p>However, also following a hyperlink generates a HTTP request with a <tt>Referer</tt>
|
||||
* HTTP header that points to <tt>index.html</tt>; therefore a proper value for {@link #getReferrerPushPeriod()}
|
||||
* has to be set. If the referrerPushPeriod for a main resource has elapsed, no more
|
||||
* associated resources will be added for that main resource.</p>
|
||||
* <p>This class distinguishes associated main resources by their URL path suffix and content
|
||||
* type.
|
||||
* CSS stylesheets, images and JavaScript files have recognizable URL path suffixes that
|
||||
* are classified as associated resources. The suffix regexs can be configured by constructor argument</p>
|
||||
* <p>When CSS stylesheets refer to images, the CSS image request will have the CSS
|
||||
* stylesheet as referrer. This implementation will push also the CSS image.</p>
|
||||
* <p>The push metadata built by this implementation is limited by the number of pages
|
||||
* of the application itself, and by the
|
||||
* {@link #getMaxAssociatedResources() max associated resources} parameter.
|
||||
* This parameter limits the number of associated resources per each main resource, so
|
||||
* that if a main resource has hundreds of associated resources, only up to the number
|
||||
* specified by this parameter will be pushed.</p>
|
||||
* <p>A SPDY push strategy that auto-populates push metadata based on referrer URLs.</p> <p>A typical request for a main
|
||||
* resource such as <tt>index.html</tt> is immediately followed by a number of requests for associated resources.
|
||||
* Associated resource requests will have a <tt>Referer</tt> HTTP header that points to <tt>index.html</tt>, which is
|
||||
* used to link the associated resource to the main resource.</p> <p>However, also following a hyperlink generates a
|
||||
* HTTP request with a <tt>Referer</tt> HTTP header that points to <tt>index.html</tt>; therefore a proper value for
|
||||
* {@link #setReferrerPushPeriod(int)} has to be set. If the referrerPushPeriod for a main resource has elapsed,
|
||||
* no more associated resources will be added for that main resource.</p> <p>This class distinguishes associated main
|
||||
* resources by their URL path suffix and content type. CSS stylesheets, images and JavaScript files have
|
||||
* recognizable URL path suffixes that are classified as associated resources. The suffix regexs can be configured by
|
||||
* constructor argument</p>
|
||||
* <p>When CSS stylesheets refer to images, the CSS image request will have the CSS stylesheet as referrer. This
|
||||
* implementation will push also the CSS image.</p> <p>The push metadata built by this implementation is limited by the
|
||||
* number of pages of the application itself, and by the {@link #setMaxAssociatedResources(int)} max associated resources}
|
||||
* parameter. This parameter limits the number of associated resources per each main resource, so that if a main
|
||||
* resource has hundreds of associated resources, only up to the number specified by this parameter will be pushed.</p>
|
||||
*/
|
||||
public class ReferrerPushStrategy implements PushStrategy
|
||||
{
|
||||
|
@ -66,42 +60,56 @@ public class ReferrerPushStrategy implements PushStrategy
|
|||
private final Set<Pattern> pushRegexps = new HashSet<>();
|
||||
private final Set<String> pushContentTypes = new HashSet<>();
|
||||
private final Set<Pattern> allowedPushOrigins = new HashSet<>();
|
||||
private final Set<Pattern> userAgentBlacklist = new HashSet<>();
|
||||
private volatile int maxAssociatedResources = 32;
|
||||
private volatile int referrerPushPeriod = 5000;
|
||||
|
||||
public ReferrerPushStrategy()
|
||||
{
|
||||
this(Arrays.asList(".*\\.css", ".*\\.js", ".*\\.png", ".*\\.jpeg", ".*\\.jpg", ".*\\.gif", ".*\\.ico"));
|
||||
}
|
||||
List<String> defaultPushRegexps = Arrays.asList(".*\\.css", ".*\\.js", ".*\\.png", ".*\\.jpeg", ".*\\.jpg",
|
||||
".*\\.gif", ".*\\.ico");
|
||||
addPushRegexps(defaultPushRegexps);
|
||||
|
||||
public ReferrerPushStrategy(@Name("pushPatterns") List<String> pushRegexps)
|
||||
{
|
||||
this(pushRegexps, Arrays.asList(
|
||||
List<String> defaultPushContentTypes = Arrays.asList(
|
||||
"text/css",
|
||||
"text/javascript", "application/javascript", "application/x-javascript",
|
||||
"image/png", "image/x-png",
|
||||
"image/jpeg",
|
||||
"image/gif",
|
||||
"image/x-icon", "image/vnd.microsoft.icon"));
|
||||
"image/x-icon", "image/vnd.microsoft.icon");
|
||||
this.pushContentTypes.addAll(defaultPushContentTypes);
|
||||
}
|
||||
|
||||
public ReferrerPushStrategy(List<String> pushRegexps, List<String> pushContentTypes)
|
||||
public void setPushRegexps(List<String> pushRegexps)
|
||||
{
|
||||
this(pushRegexps, pushContentTypes, Collections.<String>emptyList());
|
||||
pushRegexps.clear();
|
||||
addPushRegexps(pushRegexps);
|
||||
}
|
||||
|
||||
public ReferrerPushStrategy(List<String> pushRegexps, List<String> pushContentTypes, List<String> allowedPushOrigins)
|
||||
private void addPushRegexps(List<String> pushRegexps)
|
||||
{
|
||||
for (String pushRegexp : pushRegexps)
|
||||
this.pushRegexps.add(Pattern.compile(pushRegexp));
|
||||
this.pushContentTypes.addAll(pushContentTypes);
|
||||
}
|
||||
|
||||
public void setPushContentTypes(List<String> pushContentTypes)
|
||||
{
|
||||
pushContentTypes.clear();
|
||||
pushContentTypes.addAll(pushContentTypes);
|
||||
}
|
||||
|
||||
public void setAllowedPushOrigins(List<String> allowedPushOrigins)
|
||||
{
|
||||
allowedPushOrigins.clear();
|
||||
for (String allowedPushOrigin : allowedPushOrigins)
|
||||
this.allowedPushOrigins.add(Pattern.compile(allowedPushOrigin.replace(".", "\\.").replace("*", ".*")));
|
||||
}
|
||||
|
||||
public int getMaxAssociatedResources()
|
||||
public void setUserAgentBlacklist(List<String> userAgentPatterns)
|
||||
{
|
||||
return maxAssociatedResources;
|
||||
userAgentBlacklist.clear();
|
||||
for (String userAgentPattern : userAgentPatterns)
|
||||
userAgentBlacklist.add(Pattern.compile(userAgentPattern));
|
||||
}
|
||||
|
||||
public void setMaxAssociatedResources(int maxAssociatedResources)
|
||||
|
@ -109,22 +117,48 @@ public class ReferrerPushStrategy implements PushStrategy
|
|||
this.maxAssociatedResources = maxAssociatedResources;
|
||||
}
|
||||
|
||||
public int getReferrerPushPeriod()
|
||||
{
|
||||
return referrerPushPeriod;
|
||||
}
|
||||
|
||||
public void setReferrerPushPeriod(int referrerPushPeriod)
|
||||
{
|
||||
this.referrerPushPeriod = referrerPushPeriod;
|
||||
}
|
||||
|
||||
public Set<Pattern> getPushRegexps()
|
||||
{
|
||||
return pushRegexps;
|
||||
}
|
||||
|
||||
public Set<String> getPushContentTypes()
|
||||
{
|
||||
return pushContentTypes;
|
||||
}
|
||||
|
||||
public Set<Pattern> getAllowedPushOrigins()
|
||||
{
|
||||
return allowedPushOrigins;
|
||||
}
|
||||
|
||||
public Set<Pattern> getUserAgentBlacklist()
|
||||
{
|
||||
return userAgentBlacklist;
|
||||
}
|
||||
|
||||
public int getMaxAssociatedResources()
|
||||
{
|
||||
return maxAssociatedResources;
|
||||
}
|
||||
|
||||
public int getReferrerPushPeriod()
|
||||
{
|
||||
return referrerPushPeriod;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Set<String> apply(Stream stream, Fields requestHeaders, Fields responseHeaders)
|
||||
{
|
||||
Set<String> result = Collections.<String>emptySet();
|
||||
short version = stream.getSession().getVersion();
|
||||
if (!isIfModifiedSinceHeaderPresent(requestHeaders) && isValidMethod(requestHeaders.get(HTTPSPDYHeader.METHOD.name(version)).value()))
|
||||
if (!isIfModifiedSinceHeaderPresent(requestHeaders) && isValidMethod(requestHeaders.get(HTTPSPDYHeader.METHOD
|
||||
.name(version)).value()) && !isUserAgentBlacklisted(requestHeaders))
|
||||
{
|
||||
String scheme = requestHeaders.get(HTTPSPDYHeader.SCHEME.name(version)).value();
|
||||
String host = requestHeaders.get(HTTPSPDYHeader.HOST.name(version)).value();
|
||||
|
@ -196,6 +230,16 @@ public class ReferrerPushStrategy implements PushStrategy
|
|||
return !isPushResource(url, responseHeaders);
|
||||
}
|
||||
|
||||
public boolean isUserAgentBlacklisted(Fields headers)
|
||||
{
|
||||
Fields.Field userAgentHeader = headers.get("user-agent");
|
||||
if (userAgentHeader != null)
|
||||
for (Pattern userAgentPattern : userAgentBlacklist)
|
||||
if (userAgentPattern.matcher(userAgentHeader.value()).matches())
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
private boolean isPushResource(String url, Fields responseHeaders)
|
||||
{
|
||||
for (Pattern pushRegexp : pushRegexps)
|
||||
|
@ -206,7 +250,7 @@ public class ReferrerPushStrategy implements PushStrategy
|
|||
if (header == null)
|
||||
return true;
|
||||
|
||||
String contentType = header.value().toLowerCase();
|
||||
String contentType = header.value().toLowerCase(Locale.ENGLISH);
|
||||
for (String pushContentType : pushContentTypes)
|
||||
if (contentType.startsWith(pushContentType))
|
||||
return true;
|
||||
|
@ -275,10 +319,8 @@ public class ReferrerPushStrategy implements PushStrategy
|
|||
private boolean isPushOriginAllowed(String origin)
|
||||
{
|
||||
for (Pattern allowedPushOrigin : allowedPushOrigins)
|
||||
{
|
||||
if (allowedPushOrigin.matcher(origin).matches())
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -20,6 +20,7 @@ package org.eclipse.jetty.spdy.server.proxy;
|
|||
|
||||
import java.io.IOException;
|
||||
import java.nio.ByteBuffer;
|
||||
import java.util.Locale;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
|
@ -92,7 +93,7 @@ public class ProxyHTTPSPDYConnection extends HttpConnection implements HttpParse
|
|||
@Override
|
||||
public boolean parsedHeader(HttpHeader header, String headerName, String headerValue)
|
||||
{
|
||||
switch (headerName.toLowerCase())
|
||||
switch (headerName.toLowerCase(Locale.ENGLISH))
|
||||
{
|
||||
case "host":
|
||||
headers.put(HTTPSPDYHeader.HOST.name(version), headerValue);
|
||||
|
|
|
@ -21,6 +21,7 @@ package org.eclipse.jetty.spdy.server.http;
|
|||
import java.io.IOException;
|
||||
import java.io.PrintWriter;
|
||||
import java.net.InetSocketAddress;
|
||||
import java.util.Arrays;
|
||||
import java.util.concurrent.CountDownLatch;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import javax.servlet.ServletException;
|
||||
|
@ -42,12 +43,21 @@ import org.eclipse.jetty.spdy.api.SynInfo;
|
|||
import org.eclipse.jetty.spdy.server.NPNServerConnectionFactory;
|
||||
import org.eclipse.jetty.util.Fields;
|
||||
import org.junit.Assert;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
|
||||
import static org.hamcrest.CoreMatchers.is;
|
||||
import static org.junit.Assert.assertThat;
|
||||
|
||||
public class ReferrerPushStrategyTest extends AbstractHTTPSPDYTest
|
||||
{
|
||||
private final String mainResource = "/index.html";
|
||||
private final int referrerPushPeriod = 1000;
|
||||
private final String cssResource = "/style.css";
|
||||
private InetSocketAddress serverAddress;
|
||||
private ReferrerPushStrategy pushStrategy;
|
||||
private ConnectionFactory defaultFactory;
|
||||
private Fields mainRequestHeaders;
|
||||
|
||||
public ReferrerPushStrategyTest(short version)
|
||||
{
|
||||
|
@ -57,82 +67,63 @@ public class ReferrerPushStrategyTest extends AbstractHTTPSPDYTest
|
|||
@Override
|
||||
protected HTTPSPDYServerConnector newHTTPSPDYServerConnector(short version)
|
||||
{
|
||||
HTTPSPDYServerConnector connector =
|
||||
new HTTPSPDYServerConnector(server,version,new HttpConfiguration(),new ReferrerPushStrategy());
|
||||
return connector;
|
||||
return new HTTPSPDYServerConnector(server, version, new HttpConfiguration(), new ReferrerPushStrategy());
|
||||
}
|
||||
|
||||
@Before
|
||||
public void setUp() throws Exception
|
||||
{
|
||||
serverAddress = createServer();
|
||||
pushStrategy = new ReferrerPushStrategy();
|
||||
pushStrategy.setReferrerPushPeriod(referrerPushPeriod);
|
||||
defaultFactory = new HTTPSPDYServerConnectionFactory(version, new HttpConfiguration(), pushStrategy);
|
||||
connector.addConnectionFactory(defaultFactory);
|
||||
if (connector.getConnectionFactory(NPNServerConnectionFactory.class) != null)
|
||||
connector.getConnectionFactory(NPNServerConnectionFactory.class).setDefaultProtocol(defaultFactory.getProtocol());
|
||||
else
|
||||
connector.setDefaultProtocol(defaultFactory.getProtocol());
|
||||
mainRequestHeaders = createHeadersWithoutReferrer(mainResource);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testPushHeadersAreValid() throws Exception
|
||||
{
|
||||
InetSocketAddress address = createServer();
|
||||
sendMainRequestAndCSSRequest();
|
||||
run2ndClientRequests(true, true);
|
||||
}
|
||||
|
||||
ReferrerPushStrategy pushStrategy = new ReferrerPushStrategy();
|
||||
int referrerPushPeriod = 1000;
|
||||
pushStrategy.setReferrerPushPeriod(referrerPushPeriod);
|
||||
ConnectionFactory defaultFactory = new HTTPSPDYServerConnectionFactory(version,new HttpConfiguration(), pushStrategy);
|
||||
connector.addConnectionFactory(defaultFactory);
|
||||
if (connector.getConnectionFactory(NPNServerConnectionFactory.class)!=null)
|
||||
connector.getConnectionFactory(NPNServerConnectionFactory.class).setDefaultProtocol(defaultFactory.getProtocol());
|
||||
else
|
||||
connector.setDefaultProtocol(defaultFactory.getProtocol());
|
||||
|
||||
connector.setDefaultProtocol(defaultFactory.getProtocol()); // TODO I don't think this is right
|
||||
|
||||
Fields mainRequestHeaders = createHeadersWithoutReferrer(mainResource);
|
||||
Session session1 = sendMainRequestAndCSSRequest(address, mainRequestHeaders);
|
||||
|
||||
// Sleep for pushPeriod This should prevent application.js from being mapped as pushResource
|
||||
Thread.sleep(referrerPushPeriod + 1);
|
||||
|
||||
sendJSRequest(session1);
|
||||
|
||||
run2ndClientRequests(address, mainRequestHeaders, true);
|
||||
@Test
|
||||
public void testUserAgentBlackList() throws Exception
|
||||
{
|
||||
pushStrategy.setUserAgentBlacklist(Arrays.asList(".*(?i)firefox/16.*"));
|
||||
sendMainRequestAndCSSRequest();
|
||||
run2ndClientRequests(false, false);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testReferrerPushPeriod() throws Exception
|
||||
{
|
||||
InetSocketAddress address = createServer();
|
||||
|
||||
ReferrerPushStrategy pushStrategy = new ReferrerPushStrategy();
|
||||
int referrerPushPeriod = 1000;
|
||||
pushStrategy.setReferrerPushPeriod(referrerPushPeriod);
|
||||
ConnectionFactory defaultFactory = new HTTPSPDYServerConnectionFactory(version,new HttpConfiguration(), pushStrategy);
|
||||
connector.addConnectionFactory(defaultFactory);
|
||||
if (connector.getConnectionFactory(NPNServerConnectionFactory.class)!=null)
|
||||
connector.getConnectionFactory(NPNServerConnectionFactory.class).setDefaultProtocol(defaultFactory.getProtocol());
|
||||
else
|
||||
connector.setDefaultProtocol(defaultFactory.getProtocol());
|
||||
|
||||
Fields mainRequestHeaders = createHeadersWithoutReferrer(mainResource);
|
||||
Session session1 = sendMainRequestAndCSSRequest(address, mainRequestHeaders);
|
||||
Session session1 = sendMainRequestAndCSSRequest();
|
||||
|
||||
// Sleep for pushPeriod This should prevent application.js from being mapped as pushResource
|
||||
Thread.sleep(referrerPushPeriod+1);
|
||||
|
||||
Thread.sleep(referrerPushPeriod + 1);
|
||||
sendJSRequest(session1);
|
||||
|
||||
run2ndClientRequests(address, mainRequestHeaders, false);
|
||||
run2ndClientRequests(false, true);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testMaxAssociatedResources() throws Exception
|
||||
{
|
||||
InetSocketAddress address = createServer();
|
||||
|
||||
ReferrerPushStrategy pushStrategy = new ReferrerPushStrategy();
|
||||
pushStrategy.setMaxAssociatedResources(1);
|
||||
ConnectionFactory defaultFactory = new HTTPSPDYServerConnectionFactory(version,new HttpConfiguration(), pushStrategy);
|
||||
connector.addConnectionFactory(defaultFactory);
|
||||
connector.setDefaultProtocol(defaultFactory.getProtocol()); // TODO I don't think this is right
|
||||
|
||||
Fields mainRequestHeaders = createHeadersWithoutReferrer(mainResource);
|
||||
Session session1 = sendMainRequestAndCSSRequest(address, mainRequestHeaders);
|
||||
Session session1 = sendMainRequestAndCSSRequest();
|
||||
|
||||
sendJSRequest(session1);
|
||||
|
||||
run2ndClientRequests(address, mainRequestHeaders, false);
|
||||
run2ndClientRequests(false, true);
|
||||
}
|
||||
|
||||
private InetSocketAddress createServer() throws Exception
|
||||
|
@ -155,9 +146,9 @@ public class ReferrerPushStrategyTest extends AbstractHTTPSPDYTest
|
|||
});
|
||||
}
|
||||
|
||||
private Session sendMainRequestAndCSSRequest(InetSocketAddress address, Fields mainRequestHeaders) throws Exception
|
||||
private Session sendMainRequestAndCSSRequest() throws Exception
|
||||
{
|
||||
Session session1 = startClient(version, address, null);
|
||||
Session session1 = startClient(version, serverAddress, null);
|
||||
|
||||
final CountDownLatch mainResourceLatch = new CountDownLatch(1);
|
||||
session1.syn(new SynInfo(mainRequestHeaders, true), new StreamFrameListener.Adapter()
|
||||
|
@ -207,7 +198,8 @@ public class ReferrerPushStrategyTest extends AbstractHTTPSPDYTest
|
|||
Assert.assertTrue(associatedResourceLatch2.await(5, TimeUnit.SECONDS));
|
||||
}
|
||||
|
||||
private void run2ndClientRequests(InetSocketAddress address, Fields mainRequestHeaders, final boolean validateHeaders) throws Exception
|
||||
private void run2ndClientRequests(final boolean validateHeaders,
|
||||
boolean expectPushResource) throws Exception
|
||||
{
|
||||
// Create another client, and perform the same request for the main resource,
|
||||
// we expect the css being pushed, but not the js
|
||||
|
@ -215,16 +207,20 @@ public class ReferrerPushStrategyTest extends AbstractHTTPSPDYTest
|
|||
final CountDownLatch mainStreamLatch = new CountDownLatch(2);
|
||||
final CountDownLatch pushDataLatch = new CountDownLatch(1);
|
||||
final CountDownLatch pushSynHeadersValid = new CountDownLatch(1);
|
||||
Session session2 = startClient(version, address, new SessionFrameListener.Adapter()
|
||||
Session session2 = startClient(version, serverAddress, new SessionFrameListener.Adapter()
|
||||
{
|
||||
@Override
|
||||
public StreamFrameListener onSyn(Stream stream, SynInfo synInfo)
|
||||
{
|
||||
if(validateHeaders)
|
||||
if (validateHeaders)
|
||||
validateHeaders(synInfo.getHeaders(), pushSynHeadersValid);
|
||||
|
||||
Assert.assertTrue(stream.isUnidirectional());
|
||||
Assert.assertTrue(synInfo.getHeaders().get(HTTPSPDYHeader.URI.name(version)).value().endsWith(".css"));
|
||||
assertThat("Stream is unidirectional",stream.isUnidirectional(),is(true));
|
||||
assertThat("URI header ends with css", synInfo.getHeaders().get(HTTPSPDYHeader.URI.name(version))
|
||||
.value().endsWith
|
||||
("" +
|
||||
".css"),
|
||||
is(true));
|
||||
return new StreamFrameListener.Adapter()
|
||||
{
|
||||
@Override
|
||||
|
@ -243,7 +239,7 @@ public class ReferrerPushStrategyTest extends AbstractHTTPSPDYTest
|
|||
@Override
|
||||
public void onReply(Stream stream, ReplyInfo replyInfo)
|
||||
{
|
||||
Assert.assertFalse(replyInfo.isClose());
|
||||
assertThat("replyInfo.isClose() is false", replyInfo.isClose(), is(false));
|
||||
mainStreamLatch.countDown();
|
||||
}
|
||||
|
||||
|
@ -256,10 +252,13 @@ public class ReferrerPushStrategyTest extends AbstractHTTPSPDYTest
|
|||
}
|
||||
});
|
||||
|
||||
Assert.assertTrue("Main request reply and/or data not received", mainStreamLatch.await(5, TimeUnit.SECONDS));
|
||||
Assert.assertTrue("Pushed data not received", pushDataLatch.await(5, TimeUnit.SECONDS));
|
||||
if(validateHeaders)
|
||||
Assert.assertTrue("Push syn headers not valid", pushSynHeadersValid.await(5, TimeUnit.SECONDS));
|
||||
assertThat("Main request reply and/or data not received", mainStreamLatch.await(5, TimeUnit.SECONDS), is(true));
|
||||
if (expectPushResource)
|
||||
assertThat("Pushed data not received", pushDataLatch.await(5, TimeUnit.SECONDS), is(true));
|
||||
else
|
||||
assertThat("No push data is received", pushDataLatch.await(1, TimeUnit.SECONDS), is(false));
|
||||
if (validateHeaders)
|
||||
assertThat("Push syn headers not valid", pushSynHeadersValid.await(5, TimeUnit.SECONDS), is(true));
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -758,7 +757,7 @@ public class ReferrerPushStrategyTest extends AbstractHTTPSPDYTest
|
|||
});
|
||||
|
||||
Assert.assertTrue(mainStreamLatch.await(5, TimeUnit.SECONDS));
|
||||
Assert.assertFalse("We don't expect data to be pushed as the main request contained an if-modified-since header",pushDataLatch.await(1, TimeUnit.SECONDS));
|
||||
Assert.assertFalse("We don't expect data to be pushed as the main request contained an if-modified-since header", pushDataLatch.await(1, TimeUnit.SECONDS));
|
||||
}
|
||||
|
||||
private void validateHeaders(Fields headers, CountDownLatch pushSynHeadersValid)
|
||||
|
@ -805,12 +804,14 @@ public class ReferrerPushStrategyTest extends AbstractHTTPSPDYTest
|
|||
|
||||
private Fields createHeadersWithoutReferrer(String resource)
|
||||
{
|
||||
Fields associatedRequestHeaders = new Fields();
|
||||
associatedRequestHeaders.put(HTTPSPDYHeader.METHOD.name(version), "GET");
|
||||
associatedRequestHeaders.put(HTTPSPDYHeader.URI.name(version), resource);
|
||||
associatedRequestHeaders.put(HTTPSPDYHeader.VERSION.name(version), "HTTP/1.1");
|
||||
associatedRequestHeaders.put(HTTPSPDYHeader.SCHEME.name(version), "http");
|
||||
associatedRequestHeaders.put(HTTPSPDYHeader.HOST.name(version), "localhost:" + connector.getLocalPort());
|
||||
return associatedRequestHeaders;
|
||||
Fields requestHeaders = new Fields();
|
||||
requestHeaders.put("User-Agent", "Mozilla/5.0 (Macintosh; Intel Mac OS X 10.7; rv:16.0) " +
|
||||
"Gecko/20100101 Firefox/16.0");
|
||||
requestHeaders.put(HTTPSPDYHeader.METHOD.name(version), "GET");
|
||||
requestHeaders.put(HTTPSPDYHeader.URI.name(version), resource);
|
||||
requestHeaders.put(HTTPSPDYHeader.VERSION.name(version), "HTTP/1.1");
|
||||
requestHeaders.put(HTTPSPDYHeader.SCHEME.name(version), "http");
|
||||
requestHeaders.put(HTTPSPDYHeader.HOST.name(version), "localhost:" + connector.getLocalPort());
|
||||
return requestHeaders;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -18,6 +18,7 @@
|
|||
|
||||
package org.eclipse.jetty.spdy.server.http;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.Set;
|
||||
|
||||
import org.eclipse.jetty.spdy.api.SPDY;
|
||||
|
@ -44,7 +45,7 @@ public class ReferrerPushStrategyUnitTest
|
|||
public static final String METHOD = "GET";
|
||||
|
||||
// class under test
|
||||
private ReferrerPushStrategy referrerPushStrategy;
|
||||
private ReferrerPushStrategy referrerPushStrategy = new ReferrerPushStrategy();
|
||||
|
||||
@Mock
|
||||
Stream stream;
|
||||
|
@ -55,7 +56,7 @@ public class ReferrerPushStrategyUnitTest
|
|||
@Before
|
||||
public void setup()
|
||||
{
|
||||
referrerPushStrategy = new ReferrerPushStrategy();
|
||||
referrerPushStrategy.setUserAgentBlacklist(Arrays.asList(".*(?i)firefox/16.*"));
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -67,22 +68,45 @@ public class ReferrerPushStrategyUnitTest
|
|||
setMockExpectations();
|
||||
|
||||
String referrerUrl = fillPushStrategyCache(requestHeaders);
|
||||
Set<String> pushResources;
|
||||
|
||||
// sleep to pretend that the user manually clicked on a linked resource instead the browser requesting subresources immediately
|
||||
// sleep to pretend that the user manually clicked on a linked resource instead the browser requesting sub
|
||||
// resources immediately
|
||||
Thread.sleep(referrerCallTimeout + 1);
|
||||
|
||||
requestHeaders.put(HTTPSPDYHeader.URI.name(VERSION), "image2.jpg");
|
||||
requestHeaders.put("referer", referrerUrl);
|
||||
pushResources = referrerPushStrategy.apply(stream, requestHeaders, new Fields());
|
||||
Set<String> pushResources = referrerPushStrategy.apply(stream, requestHeaders, new Fields());
|
||||
assertThat("pushResources is empty", pushResources.size(), is(0));
|
||||
|
||||
requestHeaders.put(HTTPSPDYHeader.URI.name(VERSION), MAIN_URI);
|
||||
pushResources = referrerPushStrategy.apply(stream, requestHeaders, new Fields());
|
||||
// as the image2.jpg request has been a link and not a subresource, we expect that pushResources.size() is still 2
|
||||
// as the image2.jpg request has been a link and not a sub resource, we expect that pushResources.size() is
|
||||
// still 2
|
||||
assertThat("pushResources contains two elements image.jpg and style.css", pushResources.size(), is(2));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testUserAgentFilter() throws InterruptedException
|
||||
{
|
||||
Fields requestHeaders = getBaseHeaders(VERSION);
|
||||
setMockExpectations();
|
||||
|
||||
fillPushStrategyCache(requestHeaders);
|
||||
|
||||
Set<String> pushResources = referrerPushStrategy.apply(stream, requestHeaders, new Fields());
|
||||
assertThat("pushResources contains two elements image.jpg and style.css as no user-agent header is present",
|
||||
pushResources.size(), is(2));
|
||||
|
||||
requestHeaders.put("User-Agent", "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_7_5) AppleWebKit/537.4 (KHTML, like Gecko) Chrome/22.0.1229.94 Safari/537.4");
|
||||
pushResources = referrerPushStrategy.apply(stream, requestHeaders, new Fields());
|
||||
assertThat("pushResources contains two elements image.jpg and style.css as chrome is not blacklisted",
|
||||
pushResources.size(), is(2));
|
||||
|
||||
requestHeaders.put("User-Agent", "Mozilla/5.0 (Macintosh; Intel Mac OS X 10.7; rv:16.0) Gecko/20100101 Firefox/16.0");
|
||||
pushResources = referrerPushStrategy.apply(stream, requestHeaders, new Fields());
|
||||
assertThat("no resources are returned as we want to filter firefox", pushResources.size(), is(0));
|
||||
}
|
||||
|
||||
private Fields getBaseHeaders(short version)
|
||||
{
|
||||
Fields requestHeaders = new Fields();
|
||||
|
|
|
@ -38,6 +38,7 @@ import java.util.Enumeration;
|
|||
import java.util.HashMap;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
import java.util.Map;
|
||||
import java.util.Properties;
|
||||
import java.util.Set;
|
||||
|
@ -269,7 +270,7 @@ public class Config
|
|||
}
|
||||
else
|
||||
{
|
||||
String name = entry.getName().toLowerCase();
|
||||
String name = entry.getName().toLowerCase(Locale.ENGLISH);
|
||||
if (name.endsWith(".jar") || name.endsWith(".zip"))
|
||||
{
|
||||
String jar = entry.getCanonicalPath();
|
||||
|
@ -796,7 +797,7 @@ public class Config
|
|||
}
|
||||
|
||||
// Add XML configuration
|
||||
if (subject.toLowerCase().endsWith(".xml"))
|
||||
if (subject.toLowerCase(Locale.ENGLISH).endsWith(".xml"))
|
||||
{
|
||||
// Config file
|
||||
File f = new File(fixPath(file));
|
||||
|
@ -807,7 +808,7 @@ public class Config
|
|||
}
|
||||
|
||||
// Set the main class to execute (overrides any previously set)
|
||||
if (subject.toLowerCase().endsWith(".class"))
|
||||
if (subject.toLowerCase(Locale.ENGLISH).endsWith(".class"))
|
||||
{
|
||||
// Class
|
||||
String cn = expand(subject.substring(0,subject.length() - 6));
|
||||
|
@ -820,7 +821,7 @@ public class Config
|
|||
}
|
||||
|
||||
// Add raw classpath entry
|
||||
if (subject.toLowerCase().endsWith(".path"))
|
||||
if (subject.toLowerCase(Locale.ENGLISH).endsWith(".path"))
|
||||
{
|
||||
// classpath (jetty.class.path?) to add to runtime classpath
|
||||
String cn = expand(subject.substring(0,subject.length() - 5));
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue