This commit is contained in:
Jesse McConnell 2012-04-02 10:22:44 -05:00
commit 9521e1f124
136 changed files with 2436 additions and 1469 deletions

View File

@ -1,6 +1,6 @@
jetty-7.6.3-SNAPSHOT
jetty-7.6.2.v20120302 - 02 March 2012
jetty-7.6.2.v20120308 - 08 March 2012
+ 370387 SafariWebsocketDraft0Test failure during build.
+ 371168 Update ClientCrossContextSessionTest
+ 372093 handle quotes in Require-Bundle manifest string
@ -9,7 +9,17 @@ jetty-7.6.2.v20120302 - 02 March 2012
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-7.6.1.v20120215 - 15 February 2012
+ 369121 simplified test

View File

@ -2,7 +2,7 @@
<parent>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-project</artifactId>
<version>7.6.2-SNAPSHOT</version>
<version>7.6.3-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>example-jetty-embedded</artifactId>

View File

@ -3,7 +3,7 @@
<parent>
<groupId>org.eclipse.jetty.aggregate</groupId>
<artifactId>jetty-aggregate-project</artifactId>
<version>7.6.2-SNAPSHOT</version>
<version>7.6.3-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>jetty-all-server</artifactId>

View File

@ -3,7 +3,7 @@
<parent>
<groupId>org.eclipse.jetty.aggregate</groupId>
<artifactId>jetty-aggregate-project</artifactId>
<version>7.6.2-SNAPSHOT</version>
<version>7.6.3-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>jetty-all</artifactId>

View File

@ -2,7 +2,7 @@
<parent>
<groupId>org.eclipse.jetty.aggregate</groupId>
<artifactId>jetty-aggregate-project</artifactId>
<version>7.6.2-SNAPSHOT</version>
<version>7.6.3-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>jetty-client</artifactId>

View File

@ -2,7 +2,7 @@
<parent>
<groupId>org.eclipse.jetty.aggregate</groupId>
<artifactId>jetty-aggregate-project</artifactId>
<version>7.6.2-SNAPSHOT</version>
<version>7.6.3-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>jetty-plus</artifactId>

View File

@ -2,7 +2,7 @@
<parent>
<groupId>org.eclipse.jetty.aggregate</groupId>
<artifactId>jetty-aggregate-project</artifactId>
<version>7.6.2-SNAPSHOT</version>
<version>7.6.3-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>jetty-server</artifactId>

View File

@ -2,7 +2,7 @@
<parent>
<groupId>org.eclipse.jetty.aggregate</groupId>
<artifactId>jetty-aggregate-project</artifactId>
<version>7.6.2-SNAPSHOT</version>
<version>7.6.3-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>jetty-servlet</artifactId>

View File

@ -2,7 +2,7 @@
<parent>
<groupId>org.eclipse.jetty.aggregate</groupId>
<artifactId>jetty-aggregate-project</artifactId>
<version>7.6.2-SNAPSHOT</version>
<version>7.6.3-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>jetty-webapp</artifactId>

View File

@ -2,7 +2,7 @@
<parent>
<groupId>org.eclipse.jetty.aggregate</groupId>
<artifactId>jetty-aggregate-project</artifactId>
<version>7.6.2-SNAPSHOT</version>
<version>7.6.3-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>jetty-websocket</artifactId>

View File

@ -4,7 +4,7 @@
<parent>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-project</artifactId>
<version>7.6.2-SNAPSHOT</version>
<version>7.6.3-SNAPSHOT</version>
</parent>
<groupId>org.eclipse.jetty.aggregate</groupId>
<artifactId>jetty-aggregate-project</artifactId>

View File

@ -2,7 +2,7 @@
<parent>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-project</artifactId>
<version>7.6.2-SNAPSHOT</version>
<version>7.6.3-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>jetty-ajp</artifactId>

View File

@ -2,7 +2,7 @@
<parent>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-project</artifactId>
<version>7.6.2-SNAPSHOT</version>
<version>7.6.3-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>jetty-annotations</artifactId>

View File

@ -2,7 +2,7 @@
<parent>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-project</artifactId>
<version>7.6.2-SNAPSHOT</version>
<version>7.6.3-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>

View File

@ -171,7 +171,7 @@ public class HttpClient extends AggregateLifeCycle implements HttpBuffers, Attri
/* ------------------------------------------------------------ */
/** Set the ThreadPool.
* The threadpool passed is added via {@link #addBean(Object)} so that
* The threadpool passed is added via {@link #addBean(Object)} so that
* it's lifecycle may be managed as a {@link AggregateLifeCycle}.
* @param threadPool the threadPool to set
*/
@ -878,7 +878,7 @@ public class HttpClient extends AggregateLifeCycle implements HttpBuffers, Attri
@Deprecated
public void setProvider(String provider)
{
setProvider(provider);
_sslContextFactory.setProvider(provider);
}
/* ------------------------------------------------------------ */

View File

@ -276,6 +276,11 @@ class SelectConnector extends AggregateLifeCycle implements HttpClient.Connector
_endp.shutdownOutput();
}
public void dispatch()
{
_endp.asyncDispatch();
}
public void asyncDispatch()
{
_endp.asyncDispatch();

View File

@ -2,7 +2,7 @@
<parent>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-project</artifactId>
<version>7.6.2-SNAPSHOT</version>
<version>7.6.3-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>jetty-continuation</artifactId>

View File

@ -2,7 +2,7 @@
<parent>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-project</artifactId>
<version>7.6.2-SNAPSHOT</version>
<version>7.6.3-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>jetty-deploy</artifactId>

View File

@ -3,7 +3,7 @@
<parent>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-project</artifactId>
<version>7.6.2-SNAPSHOT</version>
<version>7.6.3-SNAPSHOT</version>
</parent>
<artifactId>jetty-distribution</artifactId>
<name>Jetty :: Distribution Assemblies</name>
@ -103,6 +103,16 @@
<outputDirectory>${assembly-directory}/webapps</outputDirectory>
<destFileName>test.war</destFileName>
</artifactItem>
<artifactItem>
<groupId>org.eclipse.jetty.spdy</groupId>
<artifactId>spdy-jetty-http-webapp</artifactId>
<version>${project.version}</version>
<type>war</type>
<overWrite>true</overWrite>
<includes>**</includes>
<outputDirectory>${assembly-directory}/webapps</outputDirectory>
<destFileName>spdy.war</destFileName>
</artifactItem>
<artifactItem>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-start</artifactId>
@ -124,12 +134,24 @@
</goals>
<configuration>
<includeGroupIds>org.eclipse.jetty</includeGroupIds>
<excludeGroupIds>org.eclipse.jetty.orbit</excludeGroupIds>
<excludeGroupIds>org.eclipse.jetty.orbit,org.eclipse.jetty.spdy</excludeGroupIds>
<excludeArtifactIds>jetty-all,jetty-start,jetty-monitor,jetty-jsp</excludeArtifactIds>
<includeTypes>jar</includeTypes>
<outputDirectory>${assembly-directory}/lib</outputDirectory>
</configuration>
</execution>
<execution>
<id>copy-lib-spdy-deps</id>
<phase>generate-resources</phase>
<goals>
<goal>copy-dependencies</goal>
</goals>
<configuration>
<includeGroupIds>org.eclipse.jetty.spdy</includeGroupIds>
<includeTypes>jar</includeTypes>
<outputDirectory>${assembly-directory}/lib/spdy</outputDirectory>
</configuration>
</execution>
<execution>
<id>copy-orbit-servlet-api-deps</id>
<phase>generate-resources</phase>
@ -222,7 +244,7 @@
<goal>unpack-dependencies</goal>
</goals>
<configuration>
<includeGroupIds>org.eclipse.jetty</includeGroupIds>
<includeGroupIds>org.eclipse.jetty,org.eclipse.jetty.spdy</includeGroupIds>
<classifier>config</classifier>
<failOnMissingClassifierArtifact>false</failOnMissingClassifierArtifact>
<excludes>META-INF/**</excludes>
@ -398,6 +420,27 @@
<artifactId>jetty-overlay-deployer</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>org.eclipse.jetty.spdy</groupId>
<artifactId>spdy-core</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>org.eclipse.jetty.spdy</groupId>
<artifactId>spdy-jetty</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>org.eclipse.jetty.spdy</groupId>
<artifactId>spdy-jetty-http</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>org.eclipse.jetty.spdy</groupId>
<artifactId>spdy-jetty-http-webapp</artifactId>
<version>${project.version}</version>
<type>war</type>
</dependency>
<dependency>
<groupId>org.eclipse.jetty.aggregate</groupId>
<artifactId>jetty-all</artifactId>

View File

@ -2,7 +2,7 @@
<parent>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-project</artifactId>
<version>7.6.2-SNAPSHOT</version>
<version>7.6.3-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>jetty-http-spi</artifactId>

View File

@ -3,7 +3,7 @@
<parent>
<artifactId>jetty-project</artifactId>
<groupId>org.eclipse.jetty</groupId>
<version>7.6.2-SNAPSHOT</version>
<version>7.6.3-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>jetty-http</artifactId>

View File

@ -0,0 +1,345 @@
// ========================================================================
// Copyright (c) 2009-2009 Mort Bay Consulting Pty. Ltd.
// ------------------------------------------------------------------------
// All rights reserved. This program and the accompanying materials
// are made available under the terms of the Eclipse Public License v1.0
// and Apache License v2.0 which accompanies this distribution.
// The Eclipse Public License is available at
// http://www.eclipse.org/legal/epl-v10.html
// The Apache License v2.0 is available at
// http://www.opensource.org/licenses/apache2.0.php
// You may elect to redistribute this code under either of these licenses.
// ========================================================================
package org.eclipse.jetty.http.gzip;
import java.io.IOException;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.io.UnsupportedEncodingException;
import java.util.zip.DeflaterOutputStream;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.eclipse.jetty.util.ByteArrayOutputStream2;
/* ------------------------------------------------------------ */
/**
* Skeletal implementation of a CompressedStream. This class adds compression features to a ServletOutputStream and takes care of setting response headers, etc.
* Major work and configuration is done here. Subclasses using different kinds of compression only have to implement the abstract methods doCompress() and
* setContentEncoding() using the desired compression and setting the appropriate Content-Encoding header string.
*/
public abstract class AbstractCompressedStream extends ServletOutputStream
{
private final String _encoding;
protected HttpServletRequest _request;
protected 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)
throws IOException
{
_encoding=encoding;
_request = request;
_response = response;
_contentLength = contentLength;
_bufferSize = bufferSize;
_minCompressSize = minCompressSize;
if (minCompressSize == 0)
doCompress();
}
/**
* Reset buffer.
*/
public void resetBuffer()
{
if (_response.isCommitted())
throw new IllegalStateException("Committed");
_closed = false;
_out = null;
_bOut = null;
if (_compressedOutputStream != null)
_response.setHeader("Content-Encoding",null);
_compressedOutputStream = null;
_doNotCompress = false;
}
/**
* Sets the content length.
*
* @param length
* the new content length
*/
public void setContentLength(long length)
{
_contentLength = length;
if (_doNotCompress && length >= 0)
{
if (_contentLength < Integer.MAX_VALUE)
_response.setContentLength((int)_contentLength);
else
_response.setHeader("Content-Length",Long.toString(_contentLength));
}
}
/* ------------------------------------------------------------ */
/**
* @see java.io.OutputStream#flush()
*/
@Override
public void flush() throws IOException
{
if (_out == null || _bOut != null)
{
if (_contentLength > 0 && _contentLength < _minCompressSize)
doNotCompress();
else
doCompress();
}
_out.flush();
}
/* ------------------------------------------------------------ */
/**
* @see java.io.OutputStream#close()
*/
@Override
public void close() throws IOException
{
if (_closed)
return;
if (_request.getAttribute("javax.servlet.include.request_uri") != null)
flush();
else
{
if (_bOut != null)
{
if (_contentLength < 0)
_contentLength = _bOut.getCount();
if (_contentLength < _minCompressSize)
doNotCompress();
else
doCompress();
}
else if (_out == null)
{
doNotCompress();
}
if (_compressedOutputStream != null)
_compressedOutputStream.close();
else
_out.close();
_closed = true;
}
}
/**
* Finish.
*
* @throws IOException
* Signals that an I/O exception has occurred.
*/
public void finish() throws IOException
{
if (!_closed)
{
if (_out == null || _bOut != null)
{
if (_contentLength > 0 && _contentLength < _minCompressSize)
doNotCompress();
else
doCompress();
}
if (_compressedOutputStream != null && !_closed)
{
_closed = true;
_compressedOutputStream.close();
}
}
}
/* ------------------------------------------------------------ */
/**
* @see java.io.OutputStream#write(int)
*/
@Override
public void write(int b) throws IOException
{
checkOut(1);
_out.write(b);
}
/* ------------------------------------------------------------ */
/**
* @see java.io.OutputStream#write(byte[])
*/
@Override
public void write(byte b[]) throws IOException
{
checkOut(b.length);
_out.write(b);
}
/* ------------------------------------------------------------ */
/**
* @see java.io.OutputStream#write(byte[], int, int)
*/
@Override
public void write(byte b[], int off, int len) throws IOException
{
checkOut(len);
_out.write(b,off,len);
}
/**
* Do compress.
*
* @throws IOException Signals that an I/O exception has occurred.
*/
public void doCompress() throws IOException
{
if (_compressedOutputStream==null)
{
if (_response.isCommitted())
throw new IllegalStateException();
setHeader("Content-Encoding", _encoding);
if (_response.containsHeader("Content-Encoding"))
{
_out=_compressedOutputStream=createStream();
if (_bOut!=null)
{
_out.write(_bOut.getBuf(),0,_bOut.getCount());
_bOut=null;
}
}
else
doNotCompress();
}
}
/**
* Do not compress.
*
* @throws IOException
* Signals that an I/O exception has occurred.
*/
public void doNotCompress() throws IOException
{
if (_compressedOutputStream != null)
throw new IllegalStateException();
if (_out == null || _bOut != null)
{
_doNotCompress = true;
_out = _response.getOutputStream();
setContentLength(_contentLength);
if (_bOut != null)
_out.write(_bOut.getBuf(),0,_bOut.getCount());
_bOut = null;
}
}
/**
* Check out.
*
* @param length
* the length
* @throws IOException
* Signals that an I/O exception has occurred.
*/
private void checkOut(int length) throws IOException
{
if (_closed)
throw new IOException("CLOSED");
if (_out == null)
{
if (_response.isCommitted() || (_contentLength >= 0 && _contentLength < _minCompressSize))
doNotCompress();
else if (length > _minCompressSize)
doCompress();
else
_out = _bOut = new ByteArrayOutputStream2(_bufferSize);
}
else if (_bOut != null)
{
if (_response.isCommitted() || (_contentLength >= 0 && _contentLength < _minCompressSize))
doNotCompress();
else if (length >= (_bOut.getBuf().length - _bOut.getCount()))
doCompress();
}
}
/**
* @see org.eclipse.jetty.http.gzip.CompressedStream#getOutputStream()
*/
public OutputStream getOutputStream()
{
return _out;
}
/**
* @see org.eclipse.jetty.http.gzip.CompressedStream#isClosed()
*/
public boolean isClosed()
{
return _closed;
}
/**
* Allows derived implementations to replace PrintWriter implementation.
*/
protected PrintWriter newWriter(OutputStream out, String encoding) throws UnsupportedEncodingException
{
return encoding == null?new PrintWriter(out):new PrintWriter(new OutputStreamWriter(out,encoding));
}
protected void setHeader(String name,String value)
{
_response.setHeader(name, value);
}
/**
* Create the stream fitting to the underlying compression type.
*
* @throws IOException
* Signals that an I/O exception has occurred.
*/
protected abstract DeflaterOutputStream createStream() throws IOException;
}

View File

@ -1,5 +1,5 @@
// ========================================================================
// Copyright (c) Webtide LLC
// Copyright (c) 2009-2009 Mort Bay Consulting Pty. Ltd.
// ------------------------------------------------------------------------
// All rights reserved. This program and the accompanying materials
// are made available under the terms of the Eclipse Public License v1.0
@ -11,7 +11,6 @@
// You may elect to redistribute this code under either of these licenses.
// ========================================================================
package org.eclipse.jetty.http.gzip;
import java.io.IOException;
@ -28,42 +27,34 @@ import javax.servlet.http.HttpServletResponseWrapper;
import org.eclipse.jetty.util.StringUtil;
/* ------------------------------------------------------------ */
/*------------------------------------------------------------ */
/**
*/
public class GzipResponseWrapper extends HttpServletResponseWrapper
public abstract class CompressedResponseWrapper extends HttpServletResponseWrapper
{
public static final int DEFAULT_BUFFER_SIZE = 8192;
public static final int DEFAULT_MIN_GZIP_SIZE = 256;
private HttpServletRequest _request;
public static final int DEFAULT_BUFFER_SIZE = 8192;
public static final int DEFAULT_MIN_COMPRESS_SIZE = 256;
private Set<String> _mimeTypes;
private int _bufferSize=DEFAULT_BUFFER_SIZE;
private int _minGzipSize=DEFAULT_MIN_GZIP_SIZE;
private int _minCompressSize=DEFAULT_MIN_COMPRESS_SIZE;
protected HttpServletRequest _request;
private PrintWriter _writer;
private GzipStream _gzStream;
private AbstractCompressedStream _compressedStream;
private long _contentLength=-1;
private boolean _noGzip;
private boolean _noCompression;
/**
* Instantiates a new gzip response wrapper.
*
* @param request the request
* @param response the response
*/
public GzipResponseWrapper(HttpServletRequest request, HttpServletResponse response)
public CompressedResponseWrapper(HttpServletRequest request, HttpServletResponse response)
{
super(response);
_request=request;
_request = request;
}
/* ------------------------------------------------------------ */
/**
* Sets the mime types.
*
* @param mimeTypes the new mime types
* @see org.eclipse.jetty.http.gzip.CompressedResponseWrapper#setMimeTypes(java.util.Set)
*/
public void setMimeTypes(Set<String> mimeTypes)
{
@ -72,8 +63,9 @@ public class GzipResponseWrapper extends HttpServletResponseWrapper
/* ------------------------------------------------------------ */
/**
* @see javax.servlet.ServletResponseWrapper#setBufferSize(int)
* @see org.eclipse.jetty.http.gzip.CompressedResponseWrapper#setBufferSize(int)
*/
@Override
public void setBufferSize(int bufferSize)
{
_bufferSize = bufferSize;
@ -81,64 +73,66 @@ public class GzipResponseWrapper extends HttpServletResponseWrapper
/* ------------------------------------------------------------ */
/**
* Sets the min gzip size.
*
* @param minGzipSize the new min gzip size
* @see org.eclipse.jetty.http.gzip.CompressedResponseWrapper#setMinCompressSize(int)
*/
public void setMinGzipSize(int minGzipSize)
public void setMinCompressSize(int minCompressSize)
{
_minGzipSize = minGzipSize;
_minCompressSize = minCompressSize;
}
/* ------------------------------------------------------------ */
/**
* @see javax.servlet.ServletResponseWrapper#setContentType(java.lang.String)
* @see org.eclipse.jetty.http.gzip.CompressedResponseWrapper#setContentType(java.lang.String)
*/
@Override
public void setContentType(String ct)
{
super.setContentType(ct);
if (ct!=null)
{
int colon=ct.indexOf(";");
if (colon>0)
ct=ct.substring(0,colon);
}
if ((_gzStream==null || _gzStream._out==null) &&
if ((_compressedStream==null || _compressedStream.getOutputStream()==null) &&
(_mimeTypes==null && ct!=null && ct.contains("gzip") ||
_mimeTypes!=null && (ct==null||!_mimeTypes.contains(StringUtil.asciiToLowerCase(ct)))))
{
noGzip();
noCompression();
}
}
/* ------------------------------------------------------------ */
/**
* @see javax.servlet.http.HttpServletResponseWrapper#setStatus(int, java.lang.String)
* @see org.eclipse.jetty.http.gzip.CompressedResponseWrapper#setStatus(int, java.lang.String)
*/
@Override
public void setStatus(int sc, String sm)
{
super.setStatus(sc,sm);
if (sc<200 || sc==204 || sc==205 || sc>=300)
noGzip();
noCompression();
}
/* ------------------------------------------------------------ */
/**
* @see javax.servlet.http.HttpServletResponseWrapper#setStatus(int)
* @see org.eclipse.jetty.http.gzip.CompressedResponseWrapper#setStatus(int)
*/
@Override
public void setStatus(int sc)
{
super.setStatus(sc);
if (sc<200 || sc==204 || sc==205 ||sc>=300)
noGzip();
noCompression();
}
/* ------------------------------------------------------------ */
/**
* @see javax.servlet.ServletResponseWrapper#setContentLength(int)
* @see org.eclipse.jetty.http.gzip.CompressedResponseWrapper#setContentLength(int)
*/
@Override
public void setContentLength(int length)
{
setContentLength((long)length);
@ -148,9 +142,9 @@ public class GzipResponseWrapper extends HttpServletResponseWrapper
protected void setContentLength(long length)
{
_contentLength=length;
if (_gzStream!=null)
_gzStream.setContentLength(length);
else if (_noGzip && _contentLength>=0)
if (_compressedStream!=null)
_compressedStream.setContentLength(length);
else if (_noCompression && _contentLength>=0)
{
HttpServletResponse response = (HttpServletResponse)getResponse();
if(_contentLength<Integer.MAX_VALUE)
@ -166,15 +160,16 @@ public class GzipResponseWrapper extends HttpServletResponseWrapper
/* ------------------------------------------------------------ */
/**
* @see javax.servlet.http.HttpServletResponseWrapper#addHeader(java.lang.String, java.lang.String)
* @see org.eclipse.jetty.http.gzip.CompressedResponseWrapper#addHeader(java.lang.String, java.lang.String)
*/
@Override
public void addHeader(String name, String value)
{
if ("content-length".equalsIgnoreCase(name))
{
_contentLength=Long.parseLong(value);
if (_gzStream!=null)
_gzStream.setContentLength(_contentLength);
if (_compressedStream!=null)
_compressedStream.setContentLength(_contentLength);
}
else if ("content-type".equalsIgnoreCase(name))
{
@ -185,7 +180,7 @@ public class GzipResponseWrapper extends HttpServletResponseWrapper
super.addHeader(name,value);
if (!isCommitted())
{
noGzip();
noCompression();
}
}
else
@ -194,8 +189,119 @@ public class GzipResponseWrapper extends HttpServletResponseWrapper
/* ------------------------------------------------------------ */
/**
* @see javax.servlet.http.HttpServletResponseWrapper#setHeader(java.lang.String, java.lang.String)
* @see org.eclipse.jetty.http.gzip.CompressedResponseWrapper#flushBuffer()
*/
@Override
public void flushBuffer() throws IOException
{
if (_writer!=null)
_writer.flush();
if (_compressedStream!=null)
_compressedStream.finish();
else
getResponse().flushBuffer();
}
/* ------------------------------------------------------------ */
/**
* @see org.eclipse.jetty.http.gzip.CompressedResponseWrapper#reset()
*/
@Override
public void reset()
{
super.reset();
if (_compressedStream!=null)
_compressedStream.resetBuffer();
_writer=null;
_compressedStream=null;
_noCompression=false;
_contentLength=-1;
}
/* ------------------------------------------------------------ */
/**
* @see org.eclipse.jetty.http.gzip.CompressedResponseWrapper#resetBuffer()
*/
@Override
public void resetBuffer()
{
super.resetBuffer();
if (_compressedStream!=null)
_compressedStream.resetBuffer();
_writer=null;
_compressedStream=null;
}
/* ------------------------------------------------------------ */
/**
* @see org.eclipse.jetty.http.gzip.CompressedResponseWrapper#sendError(int, java.lang.String)
*/
@Override
public void sendError(int sc, String msg) throws IOException
{
resetBuffer();
super.sendError(sc,msg);
}
/* ------------------------------------------------------------ */
/**
* @see org.eclipse.jetty.http.gzip.CompressedResponseWrapper#sendError(int)
*/
@Override
public void sendError(int sc) throws IOException
{
resetBuffer();
super.sendError(sc);
}
/* ------------------------------------------------------------ */
/**
* @see org.eclipse.jetty.http.gzip.CompressedResponseWrapper#sendRedirect(java.lang.String)
*/
@Override
public void sendRedirect(String location) throws IOException
{
resetBuffer();
super.sendRedirect(location);
}
/* ------------------------------------------------------------ */
/**
* @see org.eclipse.jetty.http.gzip.CompressedResponseWrapper#noCompression()
*/
public void noCompression()
{
_noCompression=true;
if (_compressedStream!=null)
{
try
{
_compressedStream.doNotCompress();
}
catch (IOException e)
{
throw new IllegalStateException(e);
}
}
}
/* ------------------------------------------------------------ */
/**
* @see org.eclipse.jetty.http.gzip.CompressedResponseWrapper#finish()
*/
public void finish() throws IOException
{
if (_writer!=null && !_compressedStream.isClosed())
_writer.flush();
if (_compressedStream!=null)
_compressedStream.finish();
}
/* ------------------------------------------------------------ */
/**
* @see org.eclipse.jetty.http.gzip.CompressedResponseWrapper#setHeader(java.lang.String, java.lang.String)
*/
@Override
public void setHeader(String name, String value)
{
if ("content-length".equalsIgnoreCase(name))
@ -211,197 +317,77 @@ public class GzipResponseWrapper extends HttpServletResponseWrapper
super.setHeader(name,value);
if (!isCommitted())
{
noGzip();
noCompression();
}
}
else
super.setHeader(name,value);
}
/* ------------------------------------------------------------ */
/**
* @see javax.servlet.http.HttpServletResponseWrapper#setIntHeader(java.lang.String, int)
*/
public void setIntHeader(String name, int value)
{
if ("content-length".equalsIgnoreCase(name))
{
_contentLength=value;
if (_gzStream!=null)
_gzStream.setContentLength(_contentLength);
}
else
super.setIntHeader(name,value);
}
/* ------------------------------------------------------------ */
/**
* @see javax.servlet.ServletResponseWrapper#flushBuffer()
*/
public void flushBuffer() throws IOException
{
if (_writer!=null)
_writer.flush();
if (_gzStream!=null)
_gzStream.finish();
else
getResponse().flushBuffer();
}
/* ------------------------------------------------------------ */
/**
* @see javax.servlet.ServletResponseWrapper#reset()
*/
public void reset()
{
super.reset();
if (_gzStream!=null)
_gzStream.resetBuffer();
_writer=null;
_gzStream=null;
_noGzip=false;
_contentLength=-1;
}
/* ------------------------------------------------------------ */
/**
* @see javax.servlet.ServletResponseWrapper#resetBuffer()
*/
public void resetBuffer()
{
super.resetBuffer();
if (_gzStream!=null)
_gzStream.resetBuffer();
_writer=null;
_gzStream=null;
}
/* ------------------------------------------------------------ */
/**
* @see javax.servlet.http.HttpServletResponseWrapper#sendError(int, java.lang.String)
*/
public void sendError(int sc, String msg) throws IOException
{
resetBuffer();
super.sendError(sc,msg);
}
/* ------------------------------------------------------------ */
/**
* @see javax.servlet.http.HttpServletResponseWrapper#sendError(int)
*/
public void sendError(int sc) throws IOException
{
resetBuffer();
super.sendError(sc);
}
/* ------------------------------------------------------------ */
/**
* @see javax.servlet.http.HttpServletResponseWrapper#sendRedirect(java.lang.String)
*/
public void sendRedirect(String location) throws IOException
{
resetBuffer();
super.sendRedirect(location);
}
/* ------------------------------------------------------------ */
/**
* @see javax.servlet.ServletResponseWrapper#getOutputStream()
* @see org.eclipse.jetty.http.gzip.CompressedResponseWrapper#getOutputStream()
*/
@Override
public ServletOutputStream getOutputStream() throws IOException
{
if (_gzStream==null)
if (_compressedStream==null)
{
if (getResponse().isCommitted() || _noGzip)
if (getResponse().isCommitted() || _noCompression)
{
setContentLength(_contentLength);
return getResponse().getOutputStream();
}
_gzStream=newGzipStream(_request,(HttpServletResponse)getResponse(),_contentLength,_bufferSize,_minGzipSize);
_compressedStream=newCompressedStream(_request,(HttpServletResponse)getResponse(),_contentLength,_bufferSize,_minCompressSize);
}
else if (_writer!=null)
throw new IllegalStateException("getWriter() called");
return _gzStream;
return (ServletOutputStream)_compressedStream;
}
/* ------------------------------------------------------------ */
/**
* @see javax.servlet.ServletResponseWrapper#getWriter()
* @see org.eclipse.jetty.http.gzip.CompressedResponseWrapper#getWriter()
*/
@Override
public PrintWriter getWriter() throws IOException
{
if (_writer==null)
{
if (_gzStream!=null)
if (_compressedStream!=null)
throw new IllegalStateException("getOutputStream() called");
if (getResponse().isCommitted() || _noGzip)
if (getResponse().isCommitted() || _noCompression)
{
setContentLength(_contentLength);
return getResponse().getWriter();
}
_gzStream=newGzipStream(_request,(HttpServletResponse)getResponse(),_contentLength,_bufferSize,_minGzipSize);
_writer=newWriter(_gzStream,getCharacterEncoding());
_compressedStream=newCompressedStream(_request,(HttpServletResponse)getResponse(),_contentLength,_bufferSize,_minCompressSize);
_writer=newWriter((OutputStream)_compressedStream,getCharacterEncoding());
}
return _writer;
}
/* ------------------------------------------------------------ */
/**
* No gzip.
*/
public void noGzip()
{
_noGzip=true;
if (_gzStream!=null)
{
try
{
_gzStream.doNotGzip();
}
catch (IOException e)
{
throw new IllegalStateException(e);
}
}
}
/* ------------------------------------------------------------ */
/**
* Finish.
*
* @throws IOException Signals that an I/O exception has occurred.
* @see org.eclipse.jetty.http.gzip.CompressedResponseWrapper#setIntHeader(java.lang.String, int)
*/
public void finish() throws IOException
@Override
public void setIntHeader(String name, int value)
{
if (_writer!=null && !_gzStream._closed)
_writer.flush();
if (_gzStream!=null)
_gzStream.finish();
if ("content-length".equalsIgnoreCase(name))
{
_contentLength=value;
if (_compressedStream!=null)
_compressedStream.setContentLength(_contentLength);
}
else
super.setIntHeader(name,value);
}
/* ------------------------------------------------------------ */
/**
* Allows derived implementations to replace GzipStream implementation.
*
* @param request the request
* @param response the response
* @param contentLength the content length
* @param bufferSize the buffer size
* @param minGzipSize the min gzip size
* @return the gzip stream
* @throws IOException Signals that an I/O exception has occurred.
*/
protected GzipStream newGzipStream(HttpServletRequest request,HttpServletResponse response,long contentLength,int bufferSize, int minGzipSize) throws IOException
{
return new GzipStream(request,response,contentLength,bufferSize,minGzipSize);
}
/* ------------------------------------------------------------ */
/**
* Allows derived implementations to replace PrintWriter implementation.
@ -415,5 +401,11 @@ public class GzipResponseWrapper extends HttpServletResponseWrapper
{
return encoding==null?new PrintWriter(out):new PrintWriter(new OutputStreamWriter(out,encoding));
}
}
/* ------------------------------------------------------------ */
/**
*@return the underlying CompressedStream implementation
*/
protected abstract AbstractCompressedStream newCompressedStream(HttpServletRequest _request, HttpServletResponse response, long _contentLength2, int _bufferSize2, int _minCompressedSize2) throws IOException;
}

View File

@ -1,305 +0,0 @@
// ========================================================================
// Copyright (c) Webtide LLC
// ------------------------------------------------------------------------
// All rights reserved. This program and the accompanying materials
// are made available under the terms of the Eclipse Public License v1.0
// and Apache License v2.0 which accompanies this distribution.
// The Eclipse Public License is available at
// http://www.eclipse.org/legal/epl-v10.html
// The Apache License v2.0 is available at
// http://www.opensource.org/licenses/apache2.0.php
// You may elect to redistribute this code under either of these licenses.
// ========================================================================
package org.eclipse.jetty.http.gzip;
import java.io.IOException;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.io.UnsupportedEncodingException;
import java.util.zip.GZIPOutputStream;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.eclipse.jetty.util.ByteArrayOutputStream2;
/* ------------------------------------------------------------ */
/**
*/
public class GzipStream extends ServletOutputStream
{
protected HttpServletRequest _request;
protected HttpServletResponse _response;
protected OutputStream _out;
protected ByteArrayOutputStream2 _bOut;
protected GZIPOutputStream _gzOut;
protected boolean _closed;
protected int _bufferSize;
protected int _minGzipSize;
protected long _contentLength;
protected boolean _doNotGzip;
/**
* Instantiates a new gzip stream.
*
* @param request the request
* @param response the response
* @param contentLength the content length
* @param bufferSize the buffer size
* @param minGzipSize the min gzip size
* @throws IOException Signals that an I/O exception has occurred.
*/
public GzipStream(HttpServletRequest request,HttpServletResponse response,long contentLength,int bufferSize, int minGzipSize) throws IOException
{
_request=request;
_response=response;
_contentLength=contentLength;
_bufferSize=bufferSize;
_minGzipSize=minGzipSize;
if (minGzipSize==0)
doGzip();
}
/**
* Reset buffer.
*/
public void resetBuffer()
{
if (_response.isCommitted())
throw new IllegalStateException("Committed");
_closed=false;
_out=null;
_bOut=null;
if (_gzOut!=null)
_response.setHeader("Content-Encoding",null);
_gzOut=null;
_doNotGzip=false;
}
/**
* Sets the content length.
*
* @param length the new content length
*/
public void setContentLength(long length)
{
_contentLength=length;
if (_doNotGzip && length>=0)
{
if(_contentLength<Integer.MAX_VALUE)
_response.setContentLength((int)_contentLength);
else
_response.setHeader("Content-Length",Long.toString(_contentLength));
}
}
/* ------------------------------------------------------------ */
/**
* @see java.io.OutputStream#flush()
*/
public void flush() throws IOException
{
if (_out==null || _bOut!=null)
{
if (_contentLength>0 && _contentLength<_minGzipSize)
doNotGzip();
else
doGzip();
}
_out.flush();
}
/* ------------------------------------------------------------ */
/**
* @see java.io.OutputStream#close()
*/
public void close() throws IOException
{
if (_closed)
return;
if (_request.getAttribute("javax.servlet.include.request_uri")!=null)
flush();
else
{
if (_bOut!=null)
{
if (_contentLength<0)
_contentLength=_bOut.getCount();
if (_contentLength<_minGzipSize)
doNotGzip();
else
doGzip();
}
else if (_out==null)
{
doNotGzip();
}
if (_gzOut!=null)
_gzOut.close();
else
_out.close();
_closed=true;
}
}
/**
* Finish.
*
* @throws IOException Signals that an I/O exception has occurred.
*/
public void finish() throws IOException
{
if (!_closed)
{
if (_out==null || _bOut!=null)
{
if (_contentLength>0 && _contentLength<_minGzipSize)
doNotGzip();
else
doGzip();
}
if (_gzOut!=null && !_closed)
{
_closed=true;
_gzOut.close();
}
}
}
/* ------------------------------------------------------------ */
/**
* @see java.io.OutputStream#write(int)
*/
public void write(int b) throws IOException
{
checkOut(1);
_out.write(b);
}
/* ------------------------------------------------------------ */
/**
* @see java.io.OutputStream#write(byte[])
*/
public void write(byte b[]) throws IOException
{
checkOut(b.length);
_out.write(b);
}
/* ------------------------------------------------------------ */
/**
* @see java.io.OutputStream#write(byte[], int, int)
*/
public void write(byte b[], int off, int len) throws IOException
{
checkOut(len);
_out.write(b,off,len);
}
/**
* Sets the content encoding gzip.
*
* @return true, if successful
*/
protected boolean setContentEncodingGzip()
{
_response.setHeader("Content-Encoding", "gzip");
return _response.containsHeader("Content-Encoding");
}
/**
* Do gzip.
*
* @throws IOException Signals that an I/O exception has occurred.
*/
public void doGzip() throws IOException
{
if (_gzOut==null)
{
if (_response.isCommitted())
throw new IllegalStateException();
if (setContentEncodingGzip())
{
_out=_gzOut=new GZIPOutputStream(_response.getOutputStream(),_bufferSize);
if (_bOut!=null)
{
_out.write(_bOut.getBuf(),0,_bOut.getCount());
_bOut=null;
}
}
else
doNotGzip();
}
}
/**
* Do not gzip.
*
* @throws IOException Signals that an I/O exception has occurred.
*/
public void doNotGzip() throws IOException
{
if (_gzOut!=null)
throw new IllegalStateException();
if (_out==null || _bOut!=null )
{
_doNotGzip = true;
_out=_response.getOutputStream();
setContentLength(_contentLength);
if (_bOut!=null)
_out.write(_bOut.getBuf(),0,_bOut.getCount());
_bOut=null;
}
}
/**
* Check out.
*
* @param length the length
* @throws IOException Signals that an I/O exception has occurred.
*/
private void checkOut(int length) throws IOException
{
if (_closed)
throw new IOException("CLOSED");
if (_out==null)
{
if (_response.isCommitted() || (_contentLength>=0 && _contentLength<_minGzipSize))
doNotGzip();
else if (length>_minGzipSize)
doGzip();
else
_out=_bOut=new ByteArrayOutputStream2(_bufferSize);
}
else if (_bOut!=null)
{
if (_response.isCommitted() || (_contentLength>=0 && _contentLength<_minGzipSize))
doNotGzip();
else if (length>=(_bOut.getBuf().length -_bOut.getCount()))
doGzip();
}
}
/**
* Allows derived implementations to replace PrintWriter implementation.
*/
protected PrintWriter newWriter(OutputStream out,String encoding) throws UnsupportedEncodingException
{
return encoding==null?new PrintWriter(out):new PrintWriter(new OutputStreamWriter(out,encoding));
}
}

View File

@ -2,7 +2,7 @@
<parent>
<artifactId>jetty-project</artifactId>
<groupId>org.eclipse.jetty</groupId>
<version>7.6.2-SNAPSHOT</version>
<version>7.6.3-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>jetty-io</artifactId>

View File

@ -19,7 +19,14 @@ public interface AsyncEndPoint extends ConnectedEndPoint
{
/* ------------------------------------------------------------ */
/**
* Dispatch the endpoint to a thread to attend to it.
* Dispatch the endpoint if it is not already dispatched
*
*/
public void dispatch();
/* ------------------------------------------------------------ */
/**
* Dispatch the endpoint. If it is already dispatched, schedule a redispatch
*
*/
public void asyncDispatch();

View File

@ -280,24 +280,17 @@ public class ChannelEndPoint implements EndPoint
if (buf instanceof NIOBuffer)
{
final NIOBuffer nbuf = (NIOBuffer)buf;
final ByteBuffer bbuf=nbuf.getByteBuffer();
//noinspection SynchronizationOnLocalVariableOrMethodParameter
synchronized(bbuf)
final ByteBuffer bbuf=nbuf.getByteBuffer().asReadOnlyBuffer();
try
{
try
{
bbuf.position(buffer.getIndex());
bbuf.limit(buffer.putIndex());
len=_channel.write(bbuf);
}
finally
{
if (len>0)
buffer.skip(len);
bbuf.position(0);
bbuf.limit(bbuf.capacity());
}
bbuf.position(buffer.getIndex());
bbuf.limit(buffer.putIndex());
len=_channel.write(bbuf);
}
finally
{
if (len>0)
buffer.skip(len);
}
}
else if (buf instanceof RandomAccessFileBuffer)
@ -363,46 +356,29 @@ public class ChannelEndPoint implements EndPoint
synchronized(this)
{
// We must sync because buffers may be shared (eg nbuf1 is likely to be cached content).
//noinspection SynchronizationOnLocalVariableOrMethodParameter
synchronized(bbuf0)
// Adjust position indexs of buf0 and buf1
bbuf0=bbuf0.asReadOnlyBuffer();
bbuf0.position(header.getIndex());
bbuf0.limit(header.putIndex());
bbuf1=bbuf1.asReadOnlyBuffer();
bbuf1.position(buffer.getIndex());
bbuf1.limit(buffer.putIndex());
_gather2[0]=bbuf0;
_gather2[1]=bbuf1;
// do the gathering write.
length=(int)((GatheringByteChannel)_channel).write(_gather2);
int hl=header.length();
if (length>hl)
{
//noinspection SynchronizationOnLocalVariableOrMethodParameter
synchronized(bbuf1)
{
try
{
// Adjust position indexs of buf0 and buf1
bbuf0.position(header.getIndex());
bbuf0.limit(header.putIndex());
bbuf1.position(buffer.getIndex());
bbuf1.limit(buffer.putIndex());
_gather2[0]=bbuf0;
_gather2[1]=bbuf1;
// do the gathering write.
length=(int)((GatheringByteChannel)_channel).write(_gather2);
int hl=header.length();
if (length>hl)
{
header.clear();
buffer.skip(length-hl);
}
else if (length>0)
{
header.skip(length);
}
}
finally
{
bbuf0.position(0);
bbuf1.position(0);
bbuf0.limit(bbuf0.capacity());
bbuf1.limit(bbuf1.capacity());
}
}
header.clear();
buffer.skip(length-hl);
}
else if (length>0)
{
header.skip(length);
}
}
return length;

View File

@ -37,6 +37,7 @@ public class SelectChannelEndPoint extends ChannelEndPoint implements AsyncEndPo
{
public static final Logger LOG=Log.getLogger("org.eclipse.jetty.io.nio");
private final boolean WORK_AROUND_JVM_BUG_6346658 = System.getProperty("os.name").toLowerCase().contains("win");
private final SelectorManager.SelectSet _selectSet;
private final SelectorManager _manager;
private SelectionKey _key;
@ -208,11 +209,7 @@ public class SelectChannelEndPoint extends ChannelEndPoint implements AsyncEndPo
{
synchronized(this)
{
if (_dispatched)
{
throw new IllegalStateException("dispatched");
}
else
if (!_dispatched)
{
_dispatched = true;
boolean dispatched = _manager.dispatch(_handler);
@ -685,15 +682,23 @@ public class SelectChannelEndPoint extends ChannelEndPoint implements AsyncEndPo
@Override
public void close() throws IOException
{
try
// On unix systems there is a JVM issue that if you cancel before closing, it can
// cause the selector to block waiting for a channel to close and that channel can
// block waiting for the remote end. But on windows, if you don't cancel before a
// close, then the selector can block anyway!
// https://bugs.eclipse.org/bugs/show_bug.cgi?id=357318
if (WORK_AROUND_JVM_BUG_6346658)
{
SelectionKey key = _key;
if (key!=null)
key.cancel();
}
catch (Throwable e)
{
LOG.ignore(e);
try
{
SelectionKey key = _key;
if (key!=null)
key.cancel();
}
catch (Throwable e)
{
LOG.ignore(e);
}
}
try

View File

@ -237,6 +237,9 @@ public class SslConnection extends AbstractConnection implements AsyncConnection
/* ------------------------------------------------------------ */
public void onClose()
{
Connection connection = _sslEndPoint.getConnection();
if (connection != null && connection != this)
connection.onClose();
}
/* ------------------------------------------------------------ */
@ -408,8 +411,8 @@ public class SslConnection extends AbstractConnection implements AsyncConnection
}
// If we are reading into the temp buffer and it has some content, then we should be dispatched.
if (toFill==_unwrapBuf && _unwrapBuf.hasContent())
_aEndp.asyncDispatch();
if (toFill==_unwrapBuf && _unwrapBuf.hasContent() && !_connection.isSuspended())
_aEndp.dispatch();
}
finally
{
@ -550,7 +553,7 @@ public class SslConnection extends AbstractConnection implements AsyncConnection
break;
case BUFFER_OVERFLOW:
_logger.debug("{} unwrap {} {}->{}",_session,result.getStatus(),_inbound.toDetailString(),buffer.toDetailString());
if (_logger.isDebugEnabled()) _logger.debug("{} unwrap {} {}->{}",_session,result.getStatus(),_inbound.toDetailString(),buffer.toDetailString());
break;
case OK:
@ -718,6 +721,11 @@ public class SslConnection extends AbstractConnection implements AsyncConnection
process(null, null);
}
public void dispatch()
{
_aEndp.dispatch();
}
public void asyncDispatch()
{
_aEndp.asyncDispatch();

View File

@ -2,7 +2,7 @@
<parent>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-project</artifactId>
<version>7.6.2-SNAPSHOT</version>
<version>7.6.3-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>jetty-jaspi</artifactId>

View File

@ -2,7 +2,7 @@
<parent>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-project</artifactId>
<version>7.6.2-SNAPSHOT</version>
<version>7.6.3-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>jetty-jmx</artifactId>

View File

@ -69,7 +69,7 @@
-->
<!--
<Call name="createRegistry" class="java.rmi.registry.LocateRegistry">
<Arg type="java.lang.Integer">1099</Arg>
<Arg type="java.lang.Integer"><SystemProperty name="jetty.jmxrmiport" default="1099"/></Arg>
<Call name="sleep" class="java.lang.Thread">
<Arg type="java.lang.Integer">1000</Arg>
</Call>
@ -91,11 +91,11 @@
<New class="javax.management.remote.JMXServiceURL">
<Arg type="java.lang.String">rmi</Arg>
<Arg type="java.lang.String" />
<Arg type="java.lang.Integer">0</Arg>
<Arg type="java.lang.String">/jndi/rmi://localhost:1099/jettyjmx</Arg>
<Arg type="java.lang.Integer"><SystemProperty name="jetty.jmxrmiport" default="1099"/></Arg>
<Arg type="java.lang.String">/jndi/rmi://<SystemProperty name="jetty.jmxrmihost" default="localhost"/>:<SystemProperty name="jetty.jmxrmiport" default="1099"/>/jmxrmi</Arg>
</New>
</Arg>
<Arg>org.eclipse.jetty:name=rmiconnectorserver</Arg>
<Arg>org.eclipse.jetty.jmx:name=rmiconnectorserver</Arg>
<Call name="start" />
</New>
-->

View File

@ -2,7 +2,7 @@
<parent>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-project</artifactId>
<version>7.6.2-SNAPSHOT</version>
<version>7.6.3-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>jetty-jndi</artifactId>

View File

@ -2,7 +2,7 @@
<parent>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-project</artifactId>
<version>7.6.2-SNAPSHOT</version>
<version>7.6.3-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>jetty-jsp</artifactId>

View File

@ -19,7 +19,7 @@
<parent>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-project</artifactId>
<version>7.6.2-SNAPSHOT</version>
<version>7.6.3-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>jetty-monitor</artifactId>

View File

@ -4,7 +4,7 @@
<parent>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-project</artifactId>
<version>7.6.2-SNAPSHOT</version>
<version>7.6.3-SNAPSHOT</version>
</parent>
<artifactId>jetty-nested</artifactId>
<name>Jetty :: Nested</name>

View File

@ -2,7 +2,7 @@
<parent>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-project</artifactId>
<version>7.6.2-SNAPSHOT</version>
<version>7.6.3-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>jetty-nosql</artifactId>

View File

@ -245,21 +245,37 @@ public class MongoSessionManager extends NoSqlSessionManager
{
for (String name : attrs.keySet())
{
if ( __METADATA.equals(name) )
if (__METADATA.equals(name))
{
continue;
}
String attr = decodeName(name);
Object value = decodeValue(attrs.get(name));
session.doPutOrRemove(attr,value);
session.bindValue(attr,value);
if (attrs.keySet().contains(name))
{
session.doPutOrRemove(attr,value);
session.bindValue(attr,value);
}
else
{
session.doPutOrRemove(attr,value);
}
}
// cleanup, remove values from session, that don't exist in data anymore:
for (String name : session.getNames())
{
if (!attrs.keySet().contains(name))
{
session.doPutOrRemove(name,null);
session.unbindValue(name,session.getAttribute(name));
}
}
}
session.didActivate();
return version;
}
catch (Exception e)
@ -348,7 +364,7 @@ public class MongoSessionManager extends NoSqlSessionManager
BasicDBObject remove = new BasicDBObject();
BasicDBObject unsets = new BasicDBObject();
unsets.put(getContextKey(),1);
remove.put("$unsets",unsets);
remove.put("$unset",unsets);
_sessions.update(key,remove);
return true;

View File

@ -1,7 +1,5 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<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>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-parent</artifactId>

View File

@ -31,7 +31,7 @@ Import-Package: com.sun.el;resolution:=optional,
org.apache.jasper.tagplugins.jstl;version="6.0.0";resolution:=optional,
org.apache.jasper.util;version="6.0.0";resolution:=optional,
org.apache.jasper.xmlparser;version="6.0.0";resolution:=optional,
org.glassfish.jasper.api;version="2.1.3";resolution:=optional,
org.glassfish.jsp.api;version="2.1.3";resolution:=optional,
org.apache.taglibs.standard;version="1.2.0";resolution:=optional,
org.apache.taglibs.standard.extra.spath;version="1.2.0";resolution:=optional,
org.apache.taglibs.standard.functions;version="1.2.0";resolution:=optional,

View File

@ -2,7 +2,7 @@
<parent>
<groupId>org.eclipse.jetty.osgi</groupId>
<artifactId>jetty-osgi-project</artifactId>
<version>7.6.2-SNAPSHOT</version>
<version>7.6.3-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>
<modelVersion>4.0.0</modelVersion>

View File

@ -2,7 +2,7 @@
<parent>
<groupId>org.eclipse.jetty.osgi</groupId>
<artifactId>jetty-osgi-project</artifactId>
<version>7.6.2-SNAPSHOT</version>
<version>7.6.3-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>
<modelVersion>4.0.0</modelVersion>

View File

@ -2,7 +2,7 @@
<parent>
<groupId>org.eclipse.jetty.osgi</groupId>
<artifactId>jetty-osgi-project</artifactId>
<version>7.6.2-SNAPSHOT</version>
<version>7.6.3-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>
<modelVersion>4.0.0</modelVersion>

View File

@ -2,7 +2,7 @@
<parent>
<groupId>org.eclipse.jetty.osgi</groupId>
<artifactId>jetty-osgi-project</artifactId>
<version>7.6.2-SNAPSHOT</version>
<version>7.6.3-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>
<modelVersion>4.0.0</modelVersion>

View File

@ -39,7 +39,7 @@ import org.osgi.framework.BundleContext;
public class DefaultJettyAtJettyHomeHelper {
private static final Logger LOG = Log.getLogger(DefaultJettyAtJettyHomeHelper.class);
/**
* contains a comma separated list of pathes to the etc/jetty-*.xml files
* used to configure jetty. By default the value is 'etc/jetty.xml' when the
@ -69,7 +69,7 @@ public class DefaultJettyAtJettyHomeHelper {
* Usual system property used as the port for https for a typical jetty configuration.
*/
public static final String SYS_PROP_JETTY_PORT_SSL = "jetty.port.ssl";
/**
* Called by the JettyBootStrapActivator.
* If the system property jetty.home is defined and points to a folder,
@ -88,81 +88,76 @@ public class DefaultJettyAtJettyHomeHelper {
* that might use them as part of their properties.
* </p>
*/
public static void startJettyAtJettyHome(BundleContext bundleContext)
public static void startJettyAtJettyHome(BundleContext bundleContext) throws Exception
{
String jettyHomeSysProp = System.getProperty(SYS_PROP_JETTY_HOME);
String jettyHomeBundleSysProp = System.getProperty(SYS_PROP_JETTY_HOME_BUNDLE);
File jettyHome = null;
Bundle jettyHomeBundle = null;
if (jettyHomeSysProp != null)
{
jettyHomeSysProp = resolvePropertyValue(jettyHomeSysProp);
//bug 329621
if (jettyHomeSysProp.startsWith("\"") && jettyHomeSysProp.endsWith("\"")
|| (jettyHomeSysProp.startsWith("'") && jettyHomeSysProp.endsWith("'"))) {
jettyHomeSysProp = jettyHomeSysProp.substring(1, jettyHomeSysProp.length() - 1);
}
if (jettyHomeBundleSysProp != null)
{
LOG.warn("Both the jetty.home property and the jetty.home.bundle property are defined."
+ " jetty.home.bundle is not taken into account.");
}
jettyHome = new File(jettyHomeSysProp);
if (!jettyHome.exists() || !jettyHome.isDirectory())
{
LOG.warn("Unable to locate the jetty.home folder " + jettyHomeSysProp);
return;
}
}
else if (jettyHomeBundleSysProp != null)
{
jettyHomeBundleSysProp = resolvePropertyValue(jettyHomeBundleSysProp);
for (Bundle b : bundleContext.getBundles())
{
if (b.getSymbolicName().equals(jettyHomeBundleSysProp))
{
jettyHomeBundle = b;
break;
}
}
if (jettyHomeBundle == null)
{
LOG.warn("Unable to find the jetty.home.bundle named " + jettyHomeSysProp);
return;
}
}
if (jettyHome == null && jettyHomeBundle == null)
{
LOG.warn("No default jetty started.");
return;
}
try
{
Server server = new Server();
Dictionary properties = new Hashtable();
properties.put(OSGiServerConstants.MANAGED_JETTY_SERVER_NAME, OSGiServerConstants.MANAGED_JETTY_SERVER_DEFAULT_NAME);
String configURLs = jettyHome != null ? getJettyConfigurationURLs(jettyHome) : getJettyConfigurationURLs(jettyHomeBundle);
properties.put(OSGiServerConstants.MANAGED_JETTY_XML_CONFIG_URLS, configURLs);
String jettyHomeSysProp = System.getProperty(SYS_PROP_JETTY_HOME);
String jettyHomeBundleSysProp = System.getProperty(SYS_PROP_JETTY_HOME_BUNDLE);
File jettyHome = null;
Bundle jettyHomeBundle = null;
if (jettyHomeSysProp != null)
{
jettyHomeSysProp = resolvePropertyValue(jettyHomeSysProp);
//bug 329621
if (jettyHomeSysProp.startsWith("\"") && jettyHomeSysProp.endsWith("\"")
|| (jettyHomeSysProp.startsWith("'") && jettyHomeSysProp.endsWith("'"))) {
jettyHomeSysProp = jettyHomeSysProp.substring(1, jettyHomeSysProp.length() - 1);
}
if (jettyHomeBundleSysProp != null)
{
LOG.warn("Both the jetty.home property and the jetty.home.bundle property are defined."
+ " jetty.home.bundle is not taken into account.");
}
jettyHome = new File(jettyHomeSysProp);
if (!jettyHome.exists() || !jettyHome.isDirectory())
{
LOG.warn("Unable to locate the jetty.home folder " + jettyHomeSysProp);
return;
}
}
else if (jettyHomeBundleSysProp != null)
{
jettyHomeBundleSysProp = resolvePropertyValue(jettyHomeBundleSysProp);
for (Bundle b : bundleContext.getBundles())
{
if (b.getSymbolicName().equals(jettyHomeBundleSysProp))
{
jettyHomeBundle = b;
break;
}
}
if (jettyHomeBundle == null)
{
LOG.warn("Unable to find the jetty.home.bundle named " + jettyHomeSysProp);
return;
}
LOG.info("Configuring the default jetty server with " + configURLs);
//these properties usually are the ones passed to this type of configuration.
setProperty(properties,SYS_PROP_JETTY_HOME,System.getProperty(SYS_PROP_JETTY_HOME));
setProperty(properties,SYS_PROP_JETTY_HOST,System.getProperty(SYS_PROP_JETTY_HOST));
setProperty(properties,SYS_PROP_JETTY_PORT,System.getProperty(SYS_PROP_JETTY_PORT));
setProperty(properties,SYS_PROP_JETTY_PORT_SSL,System.getProperty(SYS_PROP_JETTY_PORT_SSL));
}
if (jettyHome == null && jettyHomeBundle == null)
{
LOG.warn("No default jetty started.");
return;
}
Server server = new Server();
Dictionary properties = new Hashtable();
properties.put(OSGiServerConstants.MANAGED_JETTY_SERVER_NAME, OSGiServerConstants.MANAGED_JETTY_SERVER_DEFAULT_NAME);
String configURLs = jettyHome != null ? getJettyConfigurationURLs(jettyHome) : getJettyConfigurationURLs(jettyHomeBundle);
properties.put(OSGiServerConstants.MANAGED_JETTY_XML_CONFIG_URLS, configURLs);
LOG.info("Configuring the default jetty server with " + configURLs);
//these properties usually are the ones passed to this type of configuration.
setProperty(properties,SYS_PROP_JETTY_HOME,System.getProperty(SYS_PROP_JETTY_HOME));
setProperty(properties,SYS_PROP_JETTY_HOST,System.getProperty(SYS_PROP_JETTY_HOST));
setProperty(properties,SYS_PROP_JETTY_PORT,System.getProperty(SYS_PROP_JETTY_PORT));
setProperty(properties,SYS_PROP_JETTY_PORT_SSL,System.getProperty(SYS_PROP_JETTY_PORT_SSL));
bundleContext.registerService(Server.class.getName(), server, properties);
// hookNestedConnectorToBridgeServlet(server);
bundleContext.registerService(Server.class.getName(), server, properties);
// hookNestedConnectorToBridgeServlet(server);
}
catch (Throwable t)
{
t.printStackTrace();
}
}
/**
* Minimum setup for the location of the configuration files given a jettyhome folder.
* Reads the system property jetty.etc.config.urls and look for the corresponding jetty
@ -172,22 +167,22 @@ public class DefaultJettyAtJettyHomeHelper {
*/
private static String getJettyConfigurationURLs(File jettyhome)
{
String jettyetc = System.getProperty(SYS_PROP_JETTY_ETC_FILES,"etc/jetty.xml");
String jettyetc = System.getProperty(SYS_PROP_JETTY_ETC_FILES,"etc/jetty.xml");
StringTokenizer tokenizer = new StringTokenizer(jettyetc,";,", false);
StringBuilder res = new StringBuilder();
while (tokenizer.hasMoreTokens())
{
String next = tokenizer.nextToken().trim();
if (!next.startsWith("/") && next.indexOf(':') == -1)
{
try {
next = new File(jettyhome, next).toURI().toURL().toString();
} catch (MalformedURLException e) {
e.printStackTrace();
continue;
}
}
appendToCommaSeparatedList(res, next);
String next = tokenizer.nextToken().trim();
if (!next.startsWith("/") && next.indexOf(':') == -1)
{
try {
next = new File(jettyhome, next).toURI().toURL().toString();
} catch (MalformedURLException e) {
e.printStackTrace();
continue;
}
}
appendToCommaSeparatedList(res, next);
}
return res.toString();
}
@ -202,108 +197,108 @@ public class DefaultJettyAtJettyHomeHelper {
*/
private static String getJettyConfigurationURLs(Bundle configurationBundle)
{
String jettyetc = System.getProperty(SYS_PROP_JETTY_ETC_FILES,"etc/jetty.xml");
String jettyetc = System.getProperty(SYS_PROP_JETTY_ETC_FILES,"etc/jetty.xml");
StringTokenizer tokenizer = new StringTokenizer(jettyetc,";,", false);
StringBuilder res = new StringBuilder();
while (tokenizer.hasMoreTokens())
{
String etcFile = tokenizer.nextToken().trim();
if (etcFile.startsWith("/") || etcFile.indexOf(":") != -1)
{
appendToCommaSeparatedList(res, etcFile);
appendToCommaSeparatedList(res, etcFile);
}
else
{
Enumeration<URL> enUrls = BundleFileLocatorHelper.DEFAULT
.findEntries(configurationBundle, etcFile);
//default for org.eclipse.osgi.boot where we look inside jettyhome for the default embedded configuration.
//default inside jettyhome. this way fragments to the bundle can define their own configuration.
if ((enUrls == null || !enUrls.hasMoreElements()) && etcFile.endsWith("etc/jetty.xml"))
{
enUrls = BundleFileLocatorHelper.DEFAULT
.findEntries(configurationBundle, "/jettyhome/etc/jetty-osgi-default.xml");
System.err.println("Configuring jetty with the default embedded configuration:" +
"bundle: " + configurationBundle.getSymbolicName() +
" config: /jettyhome/etc/jetty-osgi-default.xml");
}
if (enUrls == null || !enUrls.hasMoreElements())
{
System.err.println("Unable to locate a jetty configuration file for " + etcFile);
}
if (enUrls != null)
{
while (enUrls.hasMoreElements())
{
appendToCommaSeparatedList(res, enUrls.nextElement().toString());
}
}
Enumeration<URL> enUrls = BundleFileLocatorHelper.DEFAULT
.findEntries(configurationBundle, etcFile);
//default for org.eclipse.osgi.boot where we look inside jettyhome for the default embedded configuration.
//default inside jettyhome. this way fragments to the bundle can define their own configuration.
if ((enUrls == null || !enUrls.hasMoreElements()) && etcFile.endsWith("etc/jetty.xml"))
{
enUrls = BundleFileLocatorHelper.DEFAULT
.findEntries(configurationBundle, "/jettyhome/etc/jetty-osgi-default.xml");
System.err.println("Configuring jetty with the default embedded configuration:" +
"bundle: " + configurationBundle.getSymbolicName() +
" config: /jettyhome/etc/jetty-osgi-default.xml");
}
if (enUrls == null || !enUrls.hasMoreElements())
{
System.err.println("Unable to locate a jetty configuration file for " + etcFile);
}
if (enUrls != null)
{
while (enUrls.hasMoreElements())
{
appendToCommaSeparatedList(res, enUrls.nextElement().toString());
}
}
}
}
return res.toString();
}
private static void appendToCommaSeparatedList(StringBuilder buffer, String value)
{
if (buffer.length() != 0)
{
buffer.append(",");
}
buffer.append(value);
}
private static void setProperty(Dictionary properties, String key, String value)
{
if (value != null)
{
properties.put(key, value);
}
}
/**
* recursively substitute the ${sysprop} by their actual system property.
* ${sysprop,defaultvalue} will use 'defaultvalue' as the value if no sysprop is defined.
* Not the most efficient code but we are shooting for simplicity and speed of development here.
*
* @param value
* @return
*/
public static String resolvePropertyValue(String value)
{
int ind = value.indexOf("${");
if (ind == -1) {
return value;
}
int ind2 = value.indexOf('}', ind);
if (ind2 == -1) {
return value;
}
String sysprop = value.substring(ind+2, ind2);
String defaultValue = null;
int comma = sysprop.indexOf(',');
if (comma != -1 && comma+1 != sysprop.length())
{
defaultValue = sysprop.substring(comma+1);
defaultValue = resolvePropertyValue(defaultValue);
sysprop = sysprop.substring(0,comma);
}
else
{
defaultValue = "${" + sysprop + "}";
}
String v = System.getProperty(sysprop);
String reminder = value.length() > ind2 + 1 ? value.substring(ind2+1) : "";
reminder = resolvePropertyValue(reminder);
if (v != null)
{
return value.substring(0, ind) + v + reminder;
}
else
{
return value.substring(0, ind) + defaultValue + reminder;
}
}
private static void appendToCommaSeparatedList(StringBuilder buffer, String value)
{
if (buffer.length() != 0)
{
buffer.append(",");
}
buffer.append(value);
}
private static void setProperty(Dictionary properties, String key, String value)
{
if (value != null)
{
properties.put(key, value);
}
}
/**
* recursively substitute the ${sysprop} by their actual system property.
* ${sysprop,defaultvalue} will use 'defaultvalue' as the value if no sysprop is defined.
* Not the most efficient code but we are shooting for simplicity and speed of development here.
*
* @param value
* @return
*/
public static String resolvePropertyValue(String value)
{
int ind = value.indexOf("${");
if (ind == -1) {
return value;
}
int ind2 = value.indexOf('}', ind);
if (ind2 == -1) {
return value;
}
String sysprop = value.substring(ind+2, ind2);
String defaultValue = null;
int comma = sysprop.indexOf(',');
if (comma != -1 && comma+1 != sysprop.length())
{
defaultValue = sysprop.substring(comma+1);
defaultValue = resolvePropertyValue(defaultValue);
sysprop = sysprop.substring(0,comma);
}
else
{
defaultValue = "${" + sysprop + "}";
}
String v = System.getProperty(sysprop);
String reminder = value.length() > ind2 + 1 ? value.substring(ind2+1) : "";
reminder = resolvePropertyValue(reminder);
if (v != null)
{
return value.substring(0, ind) + v + reminder;
}
else
{
return value.substring(0, ind) + defaultValue + reminder;
}
}
}

View File

@ -18,50 +18,53 @@ import java.util.Properties;
import org.eclipse.jetty.osgi.boot.OSGiServerConstants;
import org.eclipse.jetty.server.Server;
import org.eclipse.jetty.util.log.Log;
import org.eclipse.jetty.util.log.Logger;
import org.osgi.framework.Bundle;
import org.osgi.framework.ServiceEvent;
import org.osgi.framework.ServiceListener;
import org.osgi.framework.ServiceReference;
/**
* Deploy the jetty server instances when they are registered as an OSGi service.
* Deploy the jetty server instances when they are registered as an OSGi
* service.
*/
public class JettyServerServiceTracker implements ServiceListener, IManagedJettyServerRegistry
{
private static Logger LOG = Log.getLogger(JettyServerServiceTracker.class.getName());
/**
* Servers indexed by PIDs. PIDs are generated by the ConfigurationAdmin service.
* Servers indexed by PIDs. PIDs are generated by the ConfigurationAdmin
* service.
*/
private Map<String, ServerInstanceWrapper> _serversIndexedByName = new HashMap<String, ServerInstanceWrapper>();
/** The context-handler to deactivate indexed by ServerInstanceWrapper */
private Map<ServiceReference, ServerInstanceWrapper> _indexByServiceReference = new HashMap<ServiceReference, ServerInstanceWrapper>();
/**
* Stops each one of the registered servers.
*/
public void stop()
{
//not sure that this is really useful but here we go.
for (ServerInstanceWrapper wrapper : _serversIndexedByName.values())
{
try
{
wrapper.stop();
}
catch (Throwable t)
{
}
}
// not sure that this is really useful but here we go.
for (ServerInstanceWrapper wrapper : _serversIndexedByName.values())
{
try
{
wrapper.stop();
}
catch (Throwable t)
{
LOG.warn(t);
}
}
}
/**
* Receives notification that a service has had a lifecycle change.
*
* @param ev
* The <code>ServiceEvent</code> object.
* @param ev The <code>ServiceEvent</code> object.
*/
public void serviceChanged(ServiceEvent ev)
{
@ -71,17 +74,16 @@ public class JettyServerServiceTracker implements ServiceListener, IManagedJetty
case ServiceEvent.MODIFIED:
case ServiceEvent.UNREGISTERING:
{
ServerInstanceWrapper instance = unregisterInIndex(ev.getServiceReference());
ServerInstanceWrapper instance = unregisterInIndex(ev.getServiceReference());
if (instance != null)
{
try
{
instance.stop();
instance.stop();
}
catch (Exception e)
{
// TODO Auto-generated catch block
e.printStackTrace();
LOG.warn(e);
}
}
}
@ -96,32 +98,35 @@ public class JettyServerServiceTracker implements ServiceListener, IManagedJetty
}
case ServiceEvent.REGISTERED:
{
Bundle contributor = sr.getBundle();
Server server = (Server)contributor.getBundleContext().getService(sr);
ServerInstanceWrapper wrapper = registerInIndex(server, sr);
Properties props = new Properties();
for (String key : sr.getPropertyKeys())
{
Object value = sr.getProperty(key);
props.put(key, value);
}
wrapper.start(server, props);
break;
try
{
Bundle contributor = sr.getBundle();
Server server = (Server) contributor.getBundleContext().getService(sr);
ServerInstanceWrapper wrapper = registerInIndex(server, sr);
Properties props = new Properties();
for (String key : sr.getPropertyKeys())
{
Object value = sr.getProperty(key);
props.put(key, value);
}
wrapper.start(server, props);
}
catch (Exception e)
{
LOG.warn(e);
}
break;
}
}
}
private ServerInstanceWrapper registerInIndex(Server server, ServiceReference sr)
{
String name = (String)sr.getProperty(OSGiServerConstants.MANAGED_JETTY_SERVER_NAME);
if (name == null)
{
throw new IllegalArgumentException("The property " +
OSGiServerConstants.MANAGED_JETTY_SERVER_NAME + " is mandatory");
}
String name = (String) sr.getProperty(OSGiServerConstants.MANAGED_JETTY_SERVER_NAME);
if (name == null) { throw new IllegalArgumentException("The property " + OSGiServerConstants.MANAGED_JETTY_SERVER_NAME + " is mandatory"); }
ServerInstanceWrapper wrapper = new ServerInstanceWrapper(name);
_indexByServiceReference.put(sr,wrapper);
_serversIndexedByName.put(name,wrapper);
_indexByServiceReference.put(sr, wrapper);
_serversIndexedByName.put(name, wrapper);
return wrapper;
}
@ -133,7 +138,7 @@ public class JettyServerServiceTracker implements ServiceListener, IManagedJetty
*/
private ServerInstanceWrapper unregisterInIndex(ServiceReference sr)
{
ServerInstanceWrapper handler = _indexByServiceReference.remove(sr);
ServerInstanceWrapper handler = _indexByServiceReference.remove(sr);
if (handler == null)
{
// a warning?
@ -149,13 +154,12 @@ public class JettyServerServiceTracker implements ServiceListener, IManagedJetty
/**
* @param managedServerName The server name
* @return the corresponding jetty server wrapped with its deployment properties.
* @return the corresponding jetty server wrapped with its deployment
* properties.
*/
public ServerInstanceWrapper getServerInstanceWrapper(String managedServerName)
{
return _serversIndexedByName.get(managedServerName == null
? OSGiServerConstants.MANAGED_JETTY_SERVER_DEFAULT_NAME : managedServerName);
return _serversIndexedByName.get(managedServerName == null ? OSGiServerConstants.MANAGED_JETTY_SERVER_DEFAULT_NAME : managedServerName);
}
}

View File

@ -99,14 +99,21 @@ public class JettyServersManagedFactory implements ManagedServiceFactory, IManag
String name = (String)properties.get(OSGiServerConstants.MANAGED_JETTY_SERVER_NAME);
if (name == null)
{
throw new ConfigurationException(OSGiServerConstants.MANAGED_JETTY_SERVER_NAME,
"The name of the server is mandatory");
throw new ConfigurationException(OSGiServerConstants.MANAGED_JETTY_SERVER_NAME,
"The name of the server is mandatory");
}
serverInstanceWrapper = new ServerInstanceWrapper(name);
_serversIndexedByPID.put(pid, serverInstanceWrapper);
_serversNameIndexedByPID.put(pid, name);
_serversPIDIndexedByName.put(name, pid);
serverInstanceWrapper.start(new Server(), properties);
try
{
serverInstanceWrapper.start(new Server(), properties);
}
catch (Exception e)
{
throw new ConfigurationException(null, "Error starting jetty server instance", e);
}
}
public synchronized void deleted(String pid)

View File

@ -44,28 +44,29 @@ import org.eclipse.jetty.util.resource.Resource;
import org.eclipse.jetty.xml.XmlConfiguration;
import org.xml.sax.SAXParseException;
/**
* Exposes a Jetty Server to be managed by an OSGi ManagedServiceFactory
* Configure and start it.
* Can also be used from the ManagedServiceFactory
* Configure and start it. Can also be used from the ManagedServiceFactory
*/
public class ServerInstanceWrapper {
public class ServerInstanceWrapper
{
/** The value of this property points to the parent director of
* the jetty.xml configuration file currently executed.
* Everything is passed as a URL to support the
* case where the bundle is zipped. */
/**
* The value of this property points to the parent director of the jetty.xml
* configuration file currently executed. Everything is passed as a URL to
* support the case where the bundle is zipped.
*/
public static final String PROPERTY_THIS_JETTY_XML_FOLDER_URL = "this.jetty.xml.parent.folder.url";
private static Logger __logger = Log.getLogger(ServerInstanceWrapper.class.getName());
private static Logger LOG = Log.getLogger(ServerInstanceWrapper.class.getName());
private final String _managedServerName;
/**
* The managed jetty server
*/
private Server _server;
private ContextHandlerCollection _ctxtHandler;
/**
@ -74,32 +75,34 @@ public class ServerInstanceWrapper {
* let the TldScanner find the jars where the tld files are.
*/
private ClassLoader _commonParentClassLoaderForWebapps;
private DeploymentManager _deploymentManager;
private OSGiAppProvider _provider;
private WebBundleDeployerHelper _webBundleDeployerHelper;
public ServerInstanceWrapper(String managedServerName)
{
_managedServerName = managedServerName;
}
public String getManagedServerName()
{
return _managedServerName;
}
/**
* The classloader that should be the parent classloader for
* each webapp deployed on this server.
* The classloader that should be the parent classloader for each webapp
* deployed on this server.
*
* @return
*/
public ClassLoader getParentClassLoaderForWebapps()
{
return _commonParentClassLoaderForWebapps;
}
/**
* @return The deployment manager registered on this server.
*/
@ -107,7 +110,7 @@ public class ServerInstanceWrapper {
{
return _deploymentManager;
}
/**
* @return The app provider registered on this server.
*/
@ -115,19 +118,17 @@ public class ServerInstanceWrapper {
{
return _provider;
}
public Server getServer()
{
return _server;
}
public WebBundleDeployerHelper getWebBundleDeployerHelp()
{
return _webBundleDeployerHelper;
}
/**
* @return The collection of context handlers
*/
@ -136,8 +137,7 @@ public class ServerInstanceWrapper {
return _ctxtHandler;
}
public void start(Server server, Dictionary props)
public void start(Server server, Dictionary props) throws Exception
{
_server = server;
ClassLoader contextCl = Thread.currentThread().getContextClassLoader();
@ -146,62 +146,61 @@ public class ServerInstanceWrapper {
// passing this bundle's classloader as the context classlaoder
// makes sure there is access to all the jetty's bundles
ClassLoader libExtClassLoader = null;
String sharedURLs = (String)props.get(OSGiServerConstants.MANAGED_JETTY_SHARED_LIB_FOLDER_URLS);
try
{
List<File> shared = sharedURLs != null ? extractFiles(sharedURLs) : null;
libExtClassLoader = LibExtClassLoaderHelper.createLibExtClassLoader(
shared, null, server, JettyBootstrapActivator.class.getClassLoader());
}
catch (MalformedURLException e)
{
e.printStackTrace();
}
String sharedURLs = (String) props.get(OSGiServerConstants.MANAGED_JETTY_SHARED_LIB_FOLDER_URLS);
List<File> shared = sharedURLs != null ? extractFiles(sharedURLs) : null;
libExtClassLoader = LibExtClassLoaderHelper.createLibExtClassLoader(shared, null, server, JettyBootstrapActivator.class.getClassLoader());
Thread.currentThread().setContextClassLoader(libExtClassLoader);
configure(server, props);
init();
//now that we have an app provider we can call the registration customizer.
try
{
URL[] jarsWithTlds = getJarsWithTlds();
_commonParentClassLoaderForWebapps = jarsWithTlds == null
? libExtClassLoader
:new TldLocatableURLClassloader(libExtClassLoader,jarsWithTlds);
}
catch (MalformedURLException e)
{
e.printStackTrace();
}
// now that we have an app provider we can call the registration
// customizer.
URL[] jarsWithTlds = getJarsWithTlds();
_commonParentClassLoaderForWebapps = jarsWithTlds == null ? libExtClassLoader : new TldLocatableURLClassloader(libExtClassLoader, jarsWithTlds);
server.start();
_webBundleDeployerHelper = new WebBundleDeployerHelper(this);
}
catch (Throwable t)
catch (Exception e)
{
t.printStackTrace();
if (server != null)
{
try
{
server.stop();
}
catch (Exception x)
{
LOG.ignore(x);
}
}
throw e;
}
finally
{
Thread.currentThread().setContextClassLoader(contextCl);
}
_webBundleDeployerHelper = new WebBundleDeployerHelper(this);
}
public void stop()
{
try {
try
{
if (_server.isRunning())
{
_server.stop();
}
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
catch (Exception e)
{
LOG.warn(e);
}
}
@ -229,14 +228,13 @@ public class ServerInstanceWrapper {
private URL[] getJarsWithTlds() throws Exception
{
ArrayList<URL> res = new ArrayList<URL>();
WebBundleDeployerHelper.staticInit();//that is not looking great.
WebBundleDeployerHelper.staticInit();// that is not looking great.
for (WebappRegistrationCustomizer regCustomizer : WebBundleDeployerHelper.JSP_REGISTRATION_HELPERS)
{
URL[] urls = regCustomizer.getJarsWithTlds(_provider, WebBundleDeployerHelper.BUNDLE_FILE_LOCATOR_HELPER);
for (URL url : urls)
{
if (!res.contains(url))
res.add(url);
if (!res.contains(url)) res.add(url);
}
}
if (!res.isEmpty())
@ -244,19 +242,15 @@ public class ServerInstanceWrapper {
else
return null;
}
private void configure(Server server, Dictionary props) throws Exception
{
String jettyConfigurationUrls = (String) props.get(OSGiServerConstants.MANAGED_JETTY_XML_CONFIG_URLS);
List<URL> jettyConfigurations = jettyConfigurationUrls != null
? extractResources(jettyConfigurationUrls) : null;
if (jettyConfigurations == null || jettyConfigurations.isEmpty())
{
return;
}
Map<String,Object> id_map = new HashMap<String,Object>();
id_map.put("Server",server);
Map<String,String> properties = new HashMap<String,String>();
List<URL> jettyConfigurations = jettyConfigurationUrls != null ? extractResources(jettyConfigurationUrls) : null;
if (jettyConfigurations == null || jettyConfigurations.isEmpty()) { return; }
Map<String, Object> id_map = new HashMap<String, Object>();
id_map.put("Server", server);
Map<String, String> properties = new HashMap<String, String>();
Enumeration<Object> en = props.keys();
while (en.hasMoreElements())
{
@ -275,15 +269,17 @@ public class ServerInstanceWrapper {
is = r.getInputStream();
XmlConfiguration config = new XmlConfiguration(is);
config.getIdMap().putAll(id_map);
//#334062 compute the URL of the folder that contains the jetty.xml conf file
//and set it as a property so we can compute relative paths from it.
// #334062 compute the URL of the folder that contains the
// jetty.xml conf file
// and set it as a property so we can compute relative paths
// from it.
String urlPath = jettyConfiguration.toString();
int lastSlash = urlPath.lastIndexOf('/');
if (lastSlash > 4)
{
urlPath = urlPath.substring(0, lastSlash);
Map<String,String> properties2 = new HashMap<String,String>(properties);
Map<String, String> properties2 = new HashMap<String, String>(properties);
properties2.put(PROPERTY_THIS_JETTY_XML_FOLDER_URL, urlPath);
config.getProperties().putAll(properties2);
}
@ -292,11 +288,11 @@ public class ServerInstanceWrapper {
config.getProperties().putAll(properties);
}
config.configure();
id_map=config.getIdMap();
id_map = config.getIdMap();
}
catch (SAXParseException saxparse)
{
__logger.warn("Unable to configure the jetty/etc file " + jettyConfiguration,saxparse);
LOG.warn("Unable to configure the jetty/etc file " + jettyConfiguration, saxparse);
throw saxparse;
}
finally
@ -306,8 +302,7 @@ public class ServerInstanceWrapper {
}
}
/**
* Must be called after the server is configured.
*
@ -319,50 +314,48 @@ public class ServerInstanceWrapper {
private void init()
{
// Get the context handler
_ctxtHandler = (ContextHandlerCollection)_server.getChildHandlerByClass(ContextHandlerCollection.class);
_ctxtHandler = (ContextHandlerCollection) _server.getChildHandlerByClass(ContextHandlerCollection.class);
// get a deployerManager
List<DeploymentManager> deployers = _server.getBeans(DeploymentManager.class);
if (deployers != null && !deployers.isEmpty())
{
_deploymentManager = deployers.get(0);
for (AppProvider provider : _deploymentManager.getAppProviders())
{
if (provider instanceof OSGiAppProvider)
{
_provider=(OSGiAppProvider)provider;
_provider = (OSGiAppProvider) provider;
break;
}
}
if (_provider == null)
{
//create it on the fly with reasonable default values.
// create it on the fly with reasonable default values.
try
{
_provider = new OSGiAppProvider();
_provider.setMonitoredDirResource(
Resource.newResource(getDefaultOSGiContextsHome(
new File(System.getProperty("jetty.home"))).toURI()));
} catch (IOException e) {
e.printStackTrace();
_provider.setMonitoredDirResource(Resource.newResource(getDefaultOSGiContextsHome(new File(System.getProperty("jetty.home"))).toURI()));
}
catch (IOException e)
{
LOG.warn(e);
}
_deploymentManager.addAppProvider(_provider);
}
}
if (_ctxtHandler == null || _provider==null)
throw new IllegalStateException("ERROR: No ContextHandlerCollection or OSGiAppProvider configured");
if (_ctxtHandler == null || _provider == null) throw new IllegalStateException("ERROR: No ContextHandlerCollection or OSGiAppProvider configured");
}
/**
* @return The default folder in which the context files of the osgi bundles
* are located and watched. Or null when the system property
* "jetty.osgi.contexts.home" is not defined.
* If the configuration file defines the OSGiAppProvider's context.
* This will not be taken into account.
* "jetty.osgi.contexts.home" is not defined. If the configuration
* file defines the OSGiAppProvider's context. This will not be
* taken into account.
*/
File getDefaultOSGiContextsHome(File jettyHome)
{
@ -370,20 +363,19 @@ public class ServerInstanceWrapper {
if (jettyContextsHome != null)
{
File contextsHome = new File(jettyContextsHome);
if (!contextsHome.exists() || !contextsHome.isDirectory())
{
throw new IllegalArgumentException("the ${jetty.osgi.contexts.home} '" + jettyContextsHome + " must exist and be a folder");
}
if (!contextsHome.exists() || !contextsHome.isDirectory()) { throw new IllegalArgumentException(
"the ${jetty.osgi.contexts.home} '" + jettyContextsHome
+ " must exist and be a folder"); }
return contextsHome;
}
return new File(jettyHome, "/contexts");
}
File getOSGiContextsHome()
{
return _provider.getContextXmlDirAsFile();
}
/**
* @return the urls in this string.
*/
@ -396,19 +388,19 @@ public class ServerInstanceWrapper {
String tok = tokenizer.nextToken();
try
{
urls.add(((DefaultFileLocatorHelper) WebBundleDeployerHelper
.BUNDLE_FILE_LOCATOR_HELPER).getLocalURL(new URL(tok)));
urls.add(((DefaultFileLocatorHelper) WebBundleDeployerHelper.BUNDLE_FILE_LOCATOR_HELPER).getLocalURL(new URL(tok)));
}
catch (Throwable mfe)
{
LOG.warn(mfe);
}
}
return urls;
}
/**
* Get the folders that might contain jars for the legacy J2EE shared libraries
* Get the folders that might contain jars for the legacy J2EE shared
* libraries
*/
private List<File> extractFiles(String propertyValue)
{
@ -420,8 +412,7 @@ public class ServerInstanceWrapper {
try
{
URL url = new URL(tok);
url = ((DefaultFileLocatorHelper) WebBundleDeployerHelper
.BUNDLE_FILE_LOCATOR_HELPER).getFileURL(url);
url = ((DefaultFileLocatorHelper) WebBundleDeployerHelper.BUNDLE_FILE_LOCATOR_HELPER).getFileURL(url);
if (url.getProtocol().equals("file"))
{
Resource res = Resource.newResource(url);
@ -434,11 +425,10 @@ public class ServerInstanceWrapper {
}
catch (Throwable mfe)
{
LOG.warn(mfe);
}
}
return files;
}
}

View File

@ -2,7 +2,7 @@
<parent>
<groupId>org.eclipse.jetty.osgi</groupId>
<artifactId>jetty-osgi-project</artifactId>
<version>7.6.2-SNAPSHOT</version>
<version>7.6.3-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>
<modelVersion>4.0.0</modelVersion>

View File

@ -2,7 +2,7 @@
<parent>
<groupId>org.eclipse.jetty.osgi</groupId>
<artifactId>jetty-osgi-project</artifactId>
<version>7.6.2-SNAPSHOT</version>
<version>7.6.3-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>
<modelVersion>4.0.0</modelVersion>

View File

@ -3,7 +3,7 @@
<parent>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-project</artifactId>
<version>7.6.2-SNAPSHOT</version>
<version>7.6.3-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>
<groupId>org.eclipse.jetty.osgi</groupId>

View File

@ -2,7 +2,7 @@
<parent>
<groupId>org.eclipse.jetty.osgi</groupId>
<artifactId>jetty-osgi-project</artifactId>
<version>7.6.2-SNAPSHOT</version>
<version>7.6.3-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>
<modelVersion>4.0.0</modelVersion>

View File

@ -2,7 +2,7 @@
<parent>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-project</artifactId>
<version>7.6.2-SNAPSHOT</version>
<version>7.6.3-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>jetty-overlay-deployer</artifactId>

View File

@ -2,7 +2,7 @@
<parent>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-project</artifactId>
<version>7.6.2-SNAPSHOT</version>
<version>7.6.3-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>jetty-plus</artifactId>

View File

@ -3,7 +3,7 @@
<parent>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-project</artifactId>
<version>7.6.2-SNAPSHOT</version>
<version>7.6.3-SNAPSHOT</version>
</parent>
<artifactId>jetty-policy</artifactId>
<name>Jetty :: Policy Tool</name>

View File

@ -2,7 +2,7 @@
<parent>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-project</artifactId>
<version>7.6.2-SNAPSHOT</version>
<version>7.6.3-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>jetty-rewrite</artifactId>

View File

@ -24,12 +24,15 @@ import org.eclipse.jetty.server.Request;
* Rewrite the URI by matching with a regular expression.
* The replacement string may use $n" to replace the nth capture group.
* If the replacement string contains ? character, then it is split into a path
* and query string component. The returned target contains only the path.
* and query string component. The replacement query string may also contain $Q, which
* is replaced with the original query string.
* The returned target contains only the path.
*/
public class RewriteRegexRule extends RegexRule implements Rule.ApplyURI
{
private String _replacement;
private String _query;
private boolean _queryGroup;
/* ------------------------------------------------------------ */
public RewriteRegexRule()
@ -49,6 +52,7 @@ public class RewriteRegexRule extends RegexRule implements Rule.ApplyURI
String[] split=replacement.split("\\?",2);
_replacement = split[0];
_query=split.length==2?split[1]:null;
_queryGroup=_query!=null && _query.contains("$Q");
}
@ -73,7 +77,12 @@ public class RewriteRegexRule extends RegexRule implements Rule.ApplyURI
}
if (query!=null)
{
if (_queryGroup)
query=query.replace("$Q",request.getQueryString()==null?"":request.getQueryString());
request.setAttribute("org.eclipse.jetty.rewrite.handler.RewriteRegexRule.Q",query);
}
return target;
}
@ -84,7 +93,7 @@ public class RewriteRegexRule extends RegexRule implements Rule.ApplyURI
if (_query!=null)
{
String query=(String)request.getAttribute("org.eclipse.jetty.rewrite.handler.RewriteRegexRule.Q");
if (request.getQueryString()==null)
if (_queryGroup||request.getQueryString()==null)
request.setQueryString(query);
else
request.setQueryString(request.getQueryString()+"&"+query);

View File

@ -197,28 +197,25 @@ public class RuleContainer extends Rule
if (applied!=null)
{
LOG.debug("applied {}",rule);
if (!target.equals(applied))
{
LOG.debug("rewrote {} to {}",target,applied);
if (!original_set)
{
original_set=true;
request.setAttribute(_originalPathAttribute, target);
}
LOG.debug("rewrote {} to {}",target,applied);
if (!original_set)
{
original_set=true;
request.setAttribute(_originalPathAttribute, target);
}
if (_rewriteRequestURI)
{
if (rule instanceof Rule.ApplyURI && !target.equals(request.getRequestURI()))
((Rule.ApplyURI)rule).applyURI((Request)request, target, applied);
else
((Request)request).setRequestURI(applied);
}
if (_rewritePathInfo)
((Request)request).setPathInfo(applied);
target=applied;
if (_rewriteRequestURI)
{
if (rule instanceof Rule.ApplyURI)
((Rule.ApplyURI)rule).applyURI((Request)request, target, applied);
else
((Request)request).setRequestURI(applied);
}
if (_rewritePathInfo)
((Request)request).setPathInfo(applied);
target=applied;
if (rule.isHandling())
{

View File

@ -23,13 +23,21 @@ public class RewriteRegexRuleTest extends AbstractRuleTestCase
{
private String[][] _tests=
{
{"/foo/bar",".*","/replace","/replace",null},
{"/foo/bar","/xxx.*","/replace",null,null},
{"/foo/bar","/(.*)/(.*)","/$2/$1/xxx","/bar/foo/xxx",null},
{"/foo/bar","/(foo)/(.*)(bar)","/$3/$1/xxx$2","/bar/foo/xxx",null},
{"/foo/$bar",".*","/$replace","/$replace",null},
{"/foo/$bar","/foo/(.*)","/$1/replace","/$bar/replace",null},
{"/foo/bar/info","/foo/(NotHere)?([^/]*)/(.*)","/$3/other?p1=$2","/info/other","p1=bar"},
{"/foo/bar",null,".*","/replace","/replace",null},
{"/foo/bar","n=v",".*","/replace","/replace","n=v"},
{"/foo/bar",null,"/xxx.*","/replace",null,null},
{"/foo/bar",null,"/(.*)/(.*)","/$2/$1/xxx","/bar/foo/xxx",null},
{"/foo/bar",null,"/(.*)/(.*)","/test?p2=$2&p1=$1","/test","p2=bar&p1=foo"},
{"/foo/bar","n=v","/(.*)/(.*)","/test?p2=$2&p1=$1","/test","n=v&p2=bar&p1=foo"},
{"/foo/bar",null,"/(.*)/(.*)","/foo/bar?p2=$2&p1=$1","/foo/bar","p2=bar&p1=foo"},
{"/foo/bar","n=v","/(.*)/(.*)","/foo/bar?p2=$2&p1=$1","/foo/bar","n=v&p2=bar&p1=foo"},
{"/foo/bar",null,"/(foo)/(.*)(bar)","/$3/$1/xxx$2","/bar/foo/xxx",null},
{"/foo/$bar",null,".*","/$replace","/$replace",null},
{"/foo/$bar",null,"/foo/(.*)","/$1/replace","/$bar/replace",null},
{"/foo/bar/info",null,"/foo/(NotHere)?([^/]*)/(.*)","/$3/other?p1=$2","/info/other","p1=bar"},
{"/foo/bar/info",null,"/foo/(NotHere)?([^/]*)/(.*)","/$3/other?p1=$2&$Q","/info/other","p1=bar&"},
{"/foo/bar/info","n=v","/foo/(NotHere)?([^/]*)/(.*)","/$3/other?p1=$2&$Q","/info/other","p1=bar&n=v"},
{"/foo/bar/info","n=v","/foo/(NotHere)?([^/]*)/(.*)","/$3/other?p1=$2","/info/other","n=v&p1=bar"},
};
private RewriteRegexRule _rule;
@ -45,17 +53,43 @@ public class RewriteRegexRuleTest extends AbstractRuleTestCase
{
for (String[] test : _tests)
{
_rule.setRegex(test[1]);
_rule.setReplacement(test[2]);
String result = _rule.matchAndApply(test[0], _request, _response);
assertEquals(test[1], test[3], result);
String t=test[0]+"?"+test[1]+">"+test[2]+"|"+test[3];
_rule.setRegex(test[2]);
_rule.setReplacement(test[3]);
_request.setRequestURI(test[0]);
_request.setQueryString(null);
_request.setQueryString(test[1]);
_request.getAttributes().clearAttributes();
String result = _rule.matchAndApply(test[0], _request, _response);
assertEquals(t, test[4], result);
_rule.applyURI(_request,test[0],result);
assertEquals(test[3], _request.getRequestURI());
assertEquals(test[4], _request.getQueryString());
assertEquals(t,test[4], _request.getRequestURI());
assertEquals(t,test[5], _request.getQueryString());
}
}
@Test
public void testContainedRequestUriEnabled() throws IOException
{
RuleContainer container = new RuleContainer();
container.setRewriteRequestURI(true);
container.addRule(_rule);
for (String[] test : _tests)
{
String t=test[0]+"?"+test[1]+">"+test[2]+"|"+test[3];
_rule.setRegex(test[2]);
_rule.setReplacement(test[3]);
_request.setRequestURI(test[0]);
_request.setQueryString(test[1]);
_request.getAttributes().clearAttributes();
String result = container.apply(test[0],_request,_response);
assertEquals(t,test[4]==null?test[0]:test[4], result);
assertEquals(t,test[4]==null?test[0]:test[4], _request.getRequestURI());
assertEquals(t,test[5], _request.getQueryString());
}
}
}

View File

@ -2,7 +2,7 @@
<parent>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-project</artifactId>
<version>7.6.2-SNAPSHOT</version>
<version>7.6.3-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>jetty-security</artifactId>

View File

@ -12,7 +12,7 @@ The easiest place to put these lines are in the start.ini file.
For debugging the spengo authentication the following options are helpful:
-Dorg.eclipse.jetty.LEVEL=debug
-Dsun.security.spnego.debug=all
-Dsun.security.spnego.debug=true
Spengo Authentication is enabled in the webapp with the following setup.
@ -59,7 +59,4 @@ embedded, via the jetty.xml or in a context file for the webapp.
</New>
</Set>
<Set name="checkWelcomeFiles">true</Set>
</Get>
8
</Get>

View File

@ -254,7 +254,7 @@ public class DigestAuthenticator extends LoginAuthenticator
Nonce nonce=_nonceQueue.peek();
while (nonce!=null && nonce._ts<expired)
{
_nonceQueue.remove();
_nonceQueue.remove(nonce);
_nonceCount.remove(nonce._nonce);
nonce=_nonceQueue.peek();
}

View File

@ -2,7 +2,7 @@
<parent>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-project</artifactId>
<version>7.6.2-SNAPSHOT</version>
<version>7.6.3-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>jetty-server</artifactId>

View File

@ -819,6 +819,7 @@ public class AsyncContinuation implements AsyncContext, Continuation
{
synchronized (this)
{
_responseWrapped=!(response instanceof Response);
doSuspend(context,request,response);
if (request instanceof HttpServletRequest)
{

View File

@ -193,7 +193,7 @@ public class CookieCutter
continue;
case ';':
case ',':
// case ',':
if (tokenstart>=0)
value = hdr.substring(tokenstart, tokenend+1);
else
@ -239,7 +239,7 @@ public class CookieCutter
continue;
case ';':
case ',':
// case ',':
if (tokenstart>=0)
{
name = hdr.substring(tokenstart, tokenend+1);

View File

@ -265,7 +265,7 @@ public class Server extends HandlerWrapper implements Attributes
mex.add(e);
}
if (_connectors!=null)
if (_connectors!=null && mex.size()==0)
{
for (int i=0;i<_connectors.length;i++)
{

View File

@ -21,6 +21,8 @@ import java.io.UnsupportedEncodingException;
import java.util.HashSet;
import java.util.Set;
import java.util.StringTokenizer;
import java.util.zip.DeflaterOutputStream;
import java.util.zip.GZIPOutputStream;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
@ -30,7 +32,8 @@ import org.eclipse.jetty.continuation.Continuation;
import org.eclipse.jetty.continuation.ContinuationListener;
import org.eclipse.jetty.continuation.ContinuationSupport;
import org.eclipse.jetty.http.HttpMethods;
import org.eclipse.jetty.http.gzip.GzipResponseWrapper;
import org.eclipse.jetty.http.gzip.CompressedResponseWrapper;
import org.eclipse.jetty.http.gzip.AbstractCompressedStream;
import org.eclipse.jetty.server.Request;
import org.eclipse.jetty.util.log.Log;
import org.eclipse.jetty.util.log.Logger;
@ -222,7 +225,7 @@ public class GzipHandler extends HandlerWrapper
}
}
final GzipResponseWrapper wrappedResponse = newGzipResponseWrapper(request,response);
final CompressedResponseWrapper wrappedResponse = newGzipResponseWrapper(request,response);
boolean exceptional=true;
try
@ -256,7 +259,7 @@ public class GzipHandler extends HandlerWrapper
else if (exceptional && !response.isCommitted())
{
wrappedResponse.resetBuffer();
wrappedResponse.noGzip();
wrappedResponse.noCompression();
}
else
wrappedResponse.finish();
@ -276,14 +279,27 @@ public class GzipHandler extends HandlerWrapper
* @param response the response
* @return the gzip response wrapper
*/
protected GzipResponseWrapper newGzipResponseWrapper(HttpServletRequest request, HttpServletResponse response)
protected CompressedResponseWrapper newGzipResponseWrapper(HttpServletRequest request, HttpServletResponse response)
{
return new GzipResponseWrapper(request, response)
return new CompressedResponseWrapper(request,response)
{
{
super.setMimeTypes(GzipHandler.this._mimeTypes);
super.setBufferSize(GzipHandler.this._bufferSize);
super.setMinGzipSize(GzipHandler.this._minGzipSize);
super.setMinCompressSize(GzipHandler.this._minGzipSize);
}
@Override
protected AbstractCompressedStream newCompressedStream(HttpServletRequest request,HttpServletResponse response,long contentLength,int bufferSize, int minCompressSize) throws IOException
{
return new AbstractCompressedStream("gzip",request,response,contentLength,bufferSize,minCompressSize)
{
@Override
protected DeflaterOutputStream createStream() throws IOException
{
return new GZIPOutputStream(_response.getOutputStream(),_bufferSize);
}
};
}
@Override

View File

@ -32,7 +32,6 @@ import javax.servlet.http.HttpServletResponse;
import junit.framework.Assert;
import org.eclipse.jetty.http.HttpParser;
import org.eclipse.jetty.io.EndPoint;
import org.eclipse.jetty.server.handler.AbstractHandler;
import org.eclipse.jetty.util.IO;
@ -1280,4 +1279,51 @@ public abstract class HttpServerTestBase extends HttpServerTestFixture
response.setStatus(200);
}
}
@Test
public void testSuspendedPipeline() throws Exception
{
SuspendHandler suspend = new SuspendHandler();
suspend.setSuspendFor(30000);
suspend.setResumeAfter(1000);
configureServer(suspend);
long start=System.currentTimeMillis();
Socket client=newSocket(HOST,_connector.getLocalPort());
try
{
OutputStream os=client.getOutputStream();
InputStream is=client.getInputStream();
// write an initial request
os.write((
"GET / HTTP/1.1\r\n"+
"host: "+HOST+":"+_connector.getLocalPort()+"\r\n"+
"\r\n"
).getBytes());
os.flush();
Thread.sleep(200);
// write an pipelined request
os.write((
"GET / HTTP/1.1\r\n"+
"host: "+HOST+":"+_connector.getLocalPort()+"\r\n"+
"connection: close\r\n"+
"\r\n"
).getBytes());
os.flush();
String response=readResponse(client);
assertThat(response,JUnitMatchers.containsString("RESUMEDHTTP/1.1 200 OK"));
assertThat((System.currentTimeMillis()-start),greaterThanOrEqualTo(1999L));
// TODO This test should also check that that the CPU did not spin during the suspend.
}
finally
{
client.close();
}
}
}

View File

@ -669,7 +669,7 @@ public class RequestTest
"POST / HTTP/1.1\r\n"+
"Host: whatever\r\n"+
"Cookie: name0=value0; name1 = value1 ; \"\\\"name2\\\"\" = \"\\\"value2\\\"\" \n" +
"Cookie: $Version=2; name3=value3=value3;$path=/path;$domain=acme.com;$port=8080, name4=; name5 = ; name6\n" +
"Cookie: $Version=2; name3=value3=value3;$path=/path;$domain=acme.com;$port=8080; name4=; name5 = ; name6\n" +
"Cookie: name7=value7;\n" +
"Connection: close\r\n"+
"\r\n");
@ -694,6 +694,20 @@ public class RequestTest
assertEquals("", cookies.get(6).getValue());
assertEquals("name7", cookies.get(7).getName());
assertEquals("value7", cookies.get(7).getValue());
cookies.clear();
response=_connector.getResponses(
"GET /other HTTP/1.1\n"+
"Host: whatever\n"+
"Other: header\n"+
"Cookie: __utmz=14316.133020.1.1.utr=gna.de|ucn=(real)|utd=reral|utct=/games/hen-one,gnt-50-ba-keys:key,2072262.html\n"+
"\n"
);
assertTrue(response.startsWith("HTTP/1.1 200 OK"));
assertEquals(1,cookies.size());
assertEquals("__utmz", cookies.get(0).getName());
assertEquals("14316.133020.1.1.utr=gna.de|ucn=(real)|utd=reral|utct=/games/hen-one,gnt-50-ba-keys:key,2072262.html", cookies.get(0).getValue());
}
@Test

View File

@ -31,6 +31,12 @@ public class SelectChannelServerTest extends HttpServerTestBase
{
super.testCommittedError();
}
@Override
public void testSuspendedPipeline() throws Exception
{
super.testSuspendedPipeline();
}
}

View File

@ -121,8 +121,7 @@ class SuspendHandler extends HandlerWrapper
try
{
Thread.sleep(_resumeAfter);
if(((HttpServletRequest)asyncContext.getRequest()).getSession(true).getId()!=null)
asyncContext.dispatch();
asyncContext.dispatch();
}
catch(Exception e)
{

View File

@ -99,8 +99,6 @@ public class SSLEngineTest
connector.setRequestHeaderSize(512);
server.setConnectors(new Connector[]{connector });
server.setHandler(new HelloWorldHandler());
server.start();
}
@AfterClass
@ -109,10 +107,15 @@ public class SSLEngineTest
server.stop();
server.join();
}
@Test
public void testBigResponse() throws Exception
{
server.stop();
server.setHandler(new HelloWorldHandler());
server.start();
SSLContext ctx=SSLContext.getInstance("TLS");
ctx.init(null,SslContextFactory.TRUST_ALL_CERTS,new java.security.SecureRandom());
@ -123,7 +126,7 @@ public class SSLEngineTest
String request =
"GET /?dump=102400 HTTP/1.1\r\n"+
"Host: localhost:8080\r\n"+
"Host: localhost:"+port+"\r\n"+
"Connection: close\r\n"+
"\r\n";
@ -138,6 +141,10 @@ public class SSLEngineTest
@Test
public void testRequestJettyHttps() throws Exception
{
server.stop();
server.setHandler(new HelloWorldHandler());
server.start();
final int loops=10;
final int numConns=10;
@ -204,8 +211,7 @@ public class SSLEngineTest
@Test
public void testServletPost() throws Exception
{
stopServer();
server.stop();
StreamHandler handler = new StreamHandler();
server.setHandler(handler);
server.start();
@ -308,6 +314,7 @@ public class SSLEngineTest
{
ServletOutputStream out=response.getOutputStream();
byte[] buf = new byte[Integer.valueOf(request.getParameter("dump"))];
// System.err.println("DUMP "+buf.length);
for (int i=0;i<buf.length;i++)
buf[i]=(byte)('0'+(i%10));
out.write(buf);

View File

@ -15,20 +15,29 @@ package org.eclipse.jetty.server.ssl;
import static org.junit.Assert.assertEquals;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.net.Socket;
import java.security.KeyStore;
import java.util.Arrays;
import java.util.concurrent.atomic.AtomicInteger;
import javax.net.ssl.HttpsURLConnection;
import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLEngine;
import javax.net.ssl.TrustManagerFactory;
import org.eclipse.jetty.io.AsyncEndPoint;
import org.eclipse.jetty.io.Connection;
import org.eclipse.jetty.io.nio.SslConnection;
import org.eclipse.jetty.server.HttpServerTestBase;
import org.eclipse.jetty.util.ssl.SslContextFactory;
import org.junit.BeforeClass;
import org.junit.Ignore;
import org.junit.Test;
import static org.junit.Assert.assertThat;
import static org.hamcrest.Matchers.lessThan;
/**
* HttpServer Tester.
@ -46,11 +55,28 @@ public class SelectChannelServerSslTest extends HttpServerTestBase
return __sslContext.getSocketFactory().createSocket(host,port);
}
private static final AtomicInteger _handlecount = new AtomicInteger();
@BeforeClass
public static void init() throws Exception
{
SslSelectChannelConnector connector = new SslSelectChannelConnector();
SslSelectChannelConnector connector = new SslSelectChannelConnector()
{
@Override
protected SslConnection newSslConnection(AsyncEndPoint endPoint, SSLEngine engine)
{
return new SslConnection(engine, endPoint)
{
@Override
public Connection handle() throws IOException
{
_handlecount.incrementAndGet();
return super.handle();
}
};
}
};
String keystorePath = System.getProperty("basedir",".") + "/src/test/resources/keystore";
SslContextFactory cf = connector.getSslContextFactory();
cf.setKeyStorePath(keystorePath);
@ -69,7 +95,6 @@ public class SelectChannelServerSslTest extends HttpServerTestBase
__sslContext = SSLContext.getInstance("TLS");
__sslContext.init(null, trustManagerFactory.getTrustManagers(), null);
try
{
HttpsURLConnection.setDefaultHostnameVerifier(__hostnameverifier);
@ -105,7 +130,6 @@ public class SelectChannelServerSslTest extends HttpServerTestBase
{
OutputStream os=client.getOutputStream();
int last=0;
// Write out the fragments
@ -137,12 +161,17 @@ public class SelectChannelServerSslTest extends HttpServerTestBase
}
}
@Override
@Ignore
public void testAvailable() throws Exception
{
}
@Override
public void testSuspendedPipeline() throws Exception
{
_handlecount.set(0);
super.testSuspendedPipeline();
assertThat(_handlecount.get(),lessThan(50));
}
}

View File

@ -3,7 +3,7 @@
<parent>
<artifactId>jetty-project</artifactId>
<groupId>org.eclipse.jetty</groupId>
<version>7.6.2-SNAPSHOT</version>
<version>7.6.3-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>jetty-servlet</artifactId>

View File

@ -583,7 +583,8 @@ public class ServletHandler extends ScopedHandler
}
finally
{
baseRequest.setHandled(true);
if (servlet_holder!=null)
baseRequest.setHandled(true);
}
}

View File

@ -3,6 +3,7 @@ package org.eclipse.jetty.servlet;
import static org.hamcrest.Matchers.equalTo;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertThat;
import static org.junit.Assert.assertTrue;
import java.io.BufferedReader;
import java.io.IOException;
@ -12,6 +13,7 @@ import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpServletResponseWrapper;
import junit.framework.Assert;
@ -223,17 +225,20 @@ public class AsyncContextTest
}
else
{
boolean wrapped = false;
final AsyncContext asyncContext;
if (request.getParameter("dispatchRequestResponse") != null)
{
asyncContext = request.startAsync(request,response);
wrapped = true;
asyncContext = request.startAsync(request, new Wrapper(response));
}
else
{
asyncContext = request.startAsync();
}
new Thread(new DispatchingRunnable(asyncContext)).start();
new Thread(new DispatchingRunnable(asyncContext, wrapped)).start();
}
}
}
@ -241,14 +246,18 @@ public class AsyncContextTest
private class DispatchingRunnable implements Runnable
{
private AsyncContext asyncContext;
private boolean wrapped;
public DispatchingRunnable(AsyncContext asyncContext)
public DispatchingRunnable(AsyncContext asyncContext, boolean wrapped)
{
this.asyncContext = asyncContext;
this.wrapped = wrapped;
}
public void run()
{
if (wrapped)
assertTrue(asyncContext.getResponse() instanceof Wrapper);
asyncContext.dispatch();
}
}
@ -347,4 +356,13 @@ public class AsyncContextTest
}
}
private class Wrapper extends HttpServletResponseWrapper
{
public Wrapper (HttpServletResponse response)
{
super(response);
}
}
}

View File

@ -3,7 +3,7 @@
<parent>
<artifactId>jetty-project</artifactId>
<groupId>org.eclipse.jetty</groupId>
<version>7.6.2-SNAPSHOT</version>
<version>7.6.3-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>jetty-servlets</artifactId>

View File

@ -992,7 +992,7 @@ public class DoSFilter implements Filter
if (_rateTrackers != null && _trackerTimeoutQ != null)
{
long now = _trackerTimeoutQ.getNow();
int latestIndex = _next == 0 ? 3 : (_next - 1 ) % _timestamps.length;
int latestIndex = _next == 0 ? (_timestamps.length-1) : (_next - 1 );
long last=_timestamps[latestIndex];
boolean hasRecentRequest = last != 0 && (now-last)<1000L;

View File

@ -13,14 +13,12 @@
package org.eclipse.jetty.servlets;
import java.io.IOException;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.io.UnsupportedEncodingException;
import java.util.HashSet;
import java.util.Set;
import java.util.StringTokenizer;
import java.util.regex.Pattern;
import java.util.zip.DeflaterOutputStream;
import java.util.zip.GZIPOutputStream;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
@ -34,14 +32,16 @@ import org.eclipse.jetty.continuation.Continuation;
import org.eclipse.jetty.continuation.ContinuationListener;
import org.eclipse.jetty.continuation.ContinuationSupport;
import org.eclipse.jetty.http.HttpMethods;
import org.eclipse.jetty.http.gzip.GzipResponseWrapper;
import org.eclipse.jetty.http.gzip.CompressedResponseWrapper;
import org.eclipse.jetty.http.gzip.AbstractCompressedStream;
import org.eclipse.jetty.util.log.Log;
import org.eclipse.jetty.util.log.Logger;
/* ------------------------------------------------------------ */
/** GZIP Filter
* This filter will gzip the content of a response iff: <ul>
* This filter will gzip or deflate the content of a response if: <ul>
* <li>The filter is mapped to a matching path</li>
* <li>accept-encoding header is set to either gzip, deflate or a combination of those</li>
* <li>The response status code is >=200 and <300
* <li>The content length is unknown or more than the <code>minGzipSize</code> initParameter or the minGzipSize is 0(default)</li>
* <li>The content-type is in the comma separated list of mimeTypes set in the <code>mimeTypes</code> initParameter or
@ -50,8 +50,11 @@ import org.eclipse.jetty.util.log.Logger;
* </ul>
*
* <p>
* If both gzip and deflate are specified in the accept-encoding header, then gzip will be used.
* </p>
* <p>
* Compressing the content can greatly improve the network bandwidth usage, but at a cost of memory and
* CPU cycles. If this filter is mapped for static content, then use of efficient direct NIO may be
* CPU cycles. If this filter is mapped for static content, then use of efficient direct NIO may be
* prevented, thus use of the gzip mechanism of the {@link org.eclipse.jetty.servlet.DefaultServlet} is
* advised instead.
* </p>
@ -64,6 +67,8 @@ import org.eclipse.jetty.util.log.Logger;
public class GzipFilter extends UserAgentFilter
{
private static final Logger LOG = Log.getLogger(GzipFilter.class);
public final static String GZIP="gzip";
public final static String DEFLATE="deflate";
protected Set<String> _mimeTypes;
protected int _bufferSize=8192;
@ -144,7 +149,7 @@ public class GzipFilter extends UserAgentFilter
public void destroy()
{
}
/* ------------------------------------------------------------ */
/**
* @see org.eclipse.jetty.servlets.UserAgentFilter#doFilter(javax.servlet.ServletRequest, javax.servlet.ServletResponse, javax.servlet.FilterChain)
@ -156,9 +161,8 @@ public class GzipFilter extends UserAgentFilter
HttpServletRequest request=(HttpServletRequest)req;
HttpServletResponse response=(HttpServletResponse)res;
String ae = request.getHeader("accept-encoding");
if (ae != null && ae.indexOf("gzip")>=0 && !response.containsHeader("Content-Encoding")
&& !HttpMethods.HEAD.equalsIgnoreCase(request.getMethod()))
String compressionType = selectCompression(request.getHeader("accept-encoding"));
if (compressionType!=null && !response.containsHeader("Content-Encoding") && !HttpMethods.HEAD.equalsIgnoreCase(request.getMethod()))
{
String ua = getUserAgent(request);
if (isExcludedAgent(ua))
@ -172,8 +176,8 @@ public class GzipFilter extends UserAgentFilter
super.doFilter(request,response,chain);
return;
}
final GzipResponseWrapper wrappedResponse=newGzipResponseWrapper(request,response);
CompressedResponseWrapper wrappedResponse = createWrappedResponse(request,response,compressionType);
boolean exceptional=true;
try
@ -186,28 +190,12 @@ public class GzipFilter extends UserAgentFilter
Continuation continuation = ContinuationSupport.getContinuation(request);
if (continuation.isSuspended() && continuation.isResponseWrapped())
{
continuation.addContinuationListener(new ContinuationListener()
{
public void onComplete(Continuation continuation)
{
try
{
wrappedResponse.finish();
}
catch(IOException e)
{
LOG.warn(e);
}
}
public void onTimeout(Continuation continuation)
{}
});
continuation.addContinuationListener(new ContinuationListenerWaitingForWrappedResponseToFinish(wrappedResponse));
}
else if (exceptional && !response.isCommitted())
{
wrappedResponse.resetBuffer();
wrappedResponse.noGzip();
wrappedResponse.noCompression();
}
else
wrappedResponse.finish();
@ -218,7 +206,102 @@ public class GzipFilter extends UserAgentFilter
super.doFilter(request,response,chain);
}
}
/* ------------------------------------------------------------ */
private String selectCompression(String encodingHeader)
{
// TODO, this could be a little more robust.
// prefer gzip over deflate
if (encodingHeader!=null)
{
if (encodingHeader.toLowerCase().contains(GZIP))
return GZIP;
else if (encodingHeader.toLowerCase().contains(DEFLATE))
return DEFLATE;
}
return null;
}
protected CompressedResponseWrapper createWrappedResponse(HttpServletRequest request, HttpServletResponse response, final String compressionType)
{
CompressedResponseWrapper wrappedResponse = null;
if (compressionType.equals(GZIP))
{
wrappedResponse = new CompressedResponseWrapper(request,response)
{
@Override
protected AbstractCompressedStream newCompressedStream(HttpServletRequest request,HttpServletResponse response,long contentLength,int bufferSize, int minCompressSize) throws IOException
{
return new AbstractCompressedStream(compressionType,request,response,contentLength,bufferSize,minCompressSize)
{
@Override
protected DeflaterOutputStream createStream() throws IOException
{
return new GZIPOutputStream(_response.getOutputStream(),_bufferSize);
}
};
}
};
}
else if (compressionType.equals(DEFLATE))
{
wrappedResponse = new CompressedResponseWrapper(request,response)
{
@Override
protected AbstractCompressedStream newCompressedStream(HttpServletRequest request,HttpServletResponse response,long contentLength,int bufferSize, int minCompressSize) throws IOException
{
return new AbstractCompressedStream(compressionType,request,response,contentLength,bufferSize,minCompressSize)
{
@Override
protected DeflaterOutputStream createStream() throws IOException
{
return new DeflaterOutputStream(_response.getOutputStream());
}
};
}
};
}
else
{
throw new IllegalStateException(compressionType + " not supported");
}
configureWrappedResponse(wrappedResponse);
return wrappedResponse;
}
protected void configureWrappedResponse(CompressedResponseWrapper wrappedResponse)
{
wrappedResponse.setMimeTypes(_mimeTypes);
wrappedResponse.setBufferSize(_bufferSize);
wrappedResponse.setMinCompressSize(_minGzipSize);
}
private class ContinuationListenerWaitingForWrappedResponseToFinish implements ContinuationListener{
private CompressedResponseWrapper wrappedResponse;
public ContinuationListenerWaitingForWrappedResponseToFinish(CompressedResponseWrapper wrappedResponse)
{
this.wrappedResponse = wrappedResponse;
}
public void onComplete(Continuation continuation)
{
try
{
wrappedResponse.finish();
}
catch (IOException e)
{
LOG.warn(e);
}
}
public void onTimeout(Continuation continuation)
{
}
}
/**
* Checks to see if the UserAgent is excluded
*
@ -275,42 +358,4 @@ public class GzipFilter extends UserAgentFilter
}
return false;
}
/**
* Allows derived implementations to replace ResponseWrapper implementation.
*
* @param request the request
* @param response the response
* @return the gzip response wrapper
*/
protected GzipResponseWrapper newGzipResponseWrapper(HttpServletRequest request, HttpServletResponse response)
{
return new GzipResponseWrapper(request, response)
{
{
setMimeTypes(GzipFilter.this._mimeTypes);
setBufferSize(GzipFilter.this._bufferSize);
setMinGzipSize(GzipFilter.this._minGzipSize);
}
@Override
protected PrintWriter newWriter(OutputStream out,String encoding) throws UnsupportedEncodingException
{
return GzipFilter.this.newWriter(out,encoding);
}
};
}
/**
* Allows derived implementations to replace PrintWriter implementation.
*
* @param out the out
* @param encoding the encoding
* @return the prints the writer
* @throws UnsupportedEncodingException
*/
protected PrintWriter newWriter(OutputStream out,String encoding) throws UnsupportedEncodingException
{
return encoding==null?new PrintWriter(out):new PrintWriter(new OutputStreamWriter(out,encoding));
}
}

View File

@ -18,18 +18,18 @@ import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.io.UnsupportedEncodingException;
import java.util.zip.DeflaterOutputStream;
import java.util.zip.GZIPOutputStream;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.eclipse.jetty.http.gzip.GzipResponseWrapper;
import org.eclipse.jetty.http.gzip.GzipStream;
import org.eclipse.jetty.http.gzip.CompressedResponseWrapper;
import org.eclipse.jetty.http.gzip.AbstractCompressedStream;
import org.eclipse.jetty.io.UncheckedPrintWriter;
/* ------------------------------------------------------------ */
/** Includable GZip Filter.
* This extension to the {@link GzipFilter} that uses Jetty features to allow
@ -56,61 +56,82 @@ public class IncludableGzipFilter extends GzipFilter
_uncheckedPrintWriter=Boolean.valueOf(tmp).booleanValue();
}
/* ------------------------------------------------------------ */
/**
* @see org.eclipse.jetty.servlets.GzipFilter#createWrappedResponse(javax.servlet.http.HttpServletRequest, javax.servlet.http.HttpServletResponse, java.lang.String)
*/
@Override
protected GzipResponseWrapper newGzipResponseWrapper(HttpServletRequest request, HttpServletResponse response)
protected CompressedResponseWrapper createWrappedResponse(HttpServletRequest request, HttpServletResponse response, final String compressionType)
{
return new IncludableResponseWrapper(request,response);
CompressedResponseWrapper wrappedResponse = null;
if (compressionType.equals(GZIP))
{
wrappedResponse = new IncludableResponseWrapper(request,response)
{
@Override
protected AbstractCompressedStream newCompressedStream(HttpServletRequest request,HttpServletResponse response,long contentLength,int bufferSize, int minCompressSize) throws IOException
{
return new AbstractCompressedStream(compressionType,request,response,contentLength,bufferSize,minCompressSize)
{
@Override
protected DeflaterOutputStream createStream() throws IOException
{
return new GZIPOutputStream(_response.getOutputStream(),_bufferSize);
}
};
}
};
}
else if (compressionType.equals(DEFLATE))
{
wrappedResponse = new IncludableResponseWrapper(request,response)
{
@Override
protected AbstractCompressedStream newCompressedStream(HttpServletRequest request,HttpServletResponse response,long contentLength,int bufferSize, int minCompressSize) throws IOException
{
return new AbstractCompressedStream(compressionType,request,response,contentLength,bufferSize,minCompressSize)
{
@Override
protected DeflaterOutputStream createStream() throws IOException
{
return new DeflaterOutputStream(_response.getOutputStream());
}
};
}
};
}
else
{
throw new IllegalStateException(compressionType + " not supported");
}
configureWrappedResponse(wrappedResponse);
return wrappedResponse;
}
public class IncludableResponseWrapper extends GzipResponseWrapper
// Extend CompressedResponseWrapper to be able to set headers during include and to create unchecked printwriters
private abstract class IncludableResponseWrapper extends CompressedResponseWrapper
{
public IncludableResponseWrapper(HttpServletRequest request, HttpServletResponse response)
{
super(request,response);
super.setMimeTypes(IncludableGzipFilter.this._mimeTypes);
super.setBufferSize(IncludableGzipFilter.this._bufferSize);
super.setMinGzipSize(IncludableGzipFilter.this._minGzipSize);
}
@Override
protected GzipStream newGzipStream(HttpServletRequest request,HttpServletResponse response,long contentLength,int bufferSize, int minGzipSize) throws IOException
public void setHeader(String name,String value)
{
return new IncludableGzipStream(request,response,contentLength,bufferSize,minGzipSize);
super.setHeader(name,value);
HttpServletResponse response = (HttpServletResponse)getResponse();
if (!response.containsHeader(name))
response.setHeader("org.eclipse.jetty.server.include."+name,value);;
}
@Override
protected PrintWriter newWriter(OutputStream out,String encoding) throws UnsupportedEncodingException
protected PrintWriter newWriter(OutputStream out, String encoding) throws UnsupportedEncodingException
{
return IncludableGzipFilter.this.newWriter(out,encoding);
}
}
public class IncludableGzipStream extends GzipStream
{
public IncludableGzipStream(HttpServletRequest request, HttpServletResponse response, long contentLength, int bufferSize, int minGzipSize)
throws IOException
{
super(request,response,contentLength,bufferSize,minGzipSize);
}
@Override
protected boolean setContentEncodingGzip()
{
if (_request.getAttribute("javax.servlet.include.request_uri")!=null)
_response.setHeader("org.eclipse.jetty.server.include.Content-Encoding", "gzip");
else
_response.setHeader("Content-Encoding", "gzip");
return _response.containsHeader("Content-Encoding");
if (_uncheckedPrintWriter)
return encoding == null?new UncheckedPrintWriter(out):new UncheckedPrintWriter(new OutputStreamWriter(out,encoding));
return super.newWriter(out,encoding);
}
}
@Override
protected PrintWriter newWriter(OutputStream out,String encoding) throws UnsupportedEncodingException
{
if (_uncheckedPrintWriter)
return encoding==null?new UncheckedPrintWriter(out):new UncheckedPrintWriter(new OutputStreamWriter(out,encoding));
return super.newWriter(out,encoding);
}
}

View File

@ -414,7 +414,7 @@ public class ProxyServlet implements Servlet
if (request.getQueryString() != null)
uri += "?" + request.getQueryString();
HttpURI url = proxyHttpURI(request.getScheme(),request.getServerName(),request.getServerPort(),uri);
HttpURI url = proxyHttpURI(request,uri);
if (debug != 0)
_log.debug(debug + " proxy " + uri + "-->" + url);
@ -677,6 +677,11 @@ public class ProxyServlet implements Servlet
}
/* ------------------------------------------------------------ */
protected HttpURI proxyHttpURI(HttpServletRequest request, String uri) throws MalformedURLException
{
return proxyHttpURI(request.getScheme(), request.getServerName(), request.getServerPort(), uri);
}
protected HttpURI proxyHttpURI(String scheme, String serverName, int serverPort, String uri) throws MalformedURLException
{
if (!validateDestination(serverName,uri))

View File

@ -6,7 +6,7 @@ import java.util.List;
import javax.servlet.Servlet;
import org.eclipse.jetty.http.HttpStatus;
import org.eclipse.jetty.http.gzip.GzipResponseWrapper;
import org.eclipse.jetty.http.gzip.CompressedResponseWrapper;
import org.eclipse.jetty.servlet.FilterHolder;
import org.eclipse.jetty.servlets.gzip.GzipTester;
import org.eclipse.jetty.servlets.gzip.TestServletLengthStreamTypeWrite;
@ -48,32 +48,42 @@ public class GzipFilterContentLengthTest
{
return Arrays.asList(new Object[][]
{
{ TestServletLengthStreamTypeWrite.class },
{ TestServletLengthTypeStreamWrite.class },
{ TestServletStreamLengthTypeWrite.class },
{ TestServletStreamTypeLengthWrite.class },
{ TestServletTypeLengthStreamWrite.class },
{ TestServletTypeStreamLengthWrite.class } });
{ TestServletLengthStreamTypeWrite.class, GzipFilter.GZIP },
{ TestServletLengthTypeStreamWrite.class, GzipFilter.GZIP },
{ TestServletStreamLengthTypeWrite.class, GzipFilter.GZIP },
{ TestServletStreamTypeLengthWrite.class, GzipFilter.GZIP },
{ TestServletTypeLengthStreamWrite.class, GzipFilter.GZIP },
{ TestServletTypeStreamLengthWrite.class, GzipFilter.GZIP },
{ TestServletLengthStreamTypeWrite.class, GzipFilter.DEFLATE },
{ TestServletLengthTypeStreamWrite.class, GzipFilter.DEFLATE },
{ TestServletStreamLengthTypeWrite.class, GzipFilter.DEFLATE },
{ TestServletStreamTypeLengthWrite.class, GzipFilter.DEFLATE },
{ TestServletTypeLengthStreamWrite.class, GzipFilter.DEFLATE },
{ TestServletTypeStreamLengthWrite.class, GzipFilter.DEFLATE }
});
}
private static final int LARGE = GzipResponseWrapper.DEFAULT_BUFFER_SIZE * 8;
private static final int MEDIUM = GzipResponseWrapper.DEFAULT_BUFFER_SIZE;
private static final int SMALL = GzipResponseWrapper.DEFAULT_BUFFER_SIZE / 4;
private static final int TINY = GzipResponseWrapper.DEFAULT_MIN_GZIP_SIZE / 2;
private static final int LARGE = CompressedResponseWrapper.DEFAULT_BUFFER_SIZE * 8;
private static final int MEDIUM = CompressedResponseWrapper.DEFAULT_BUFFER_SIZE;
private static final int SMALL = CompressedResponseWrapper.DEFAULT_BUFFER_SIZE / 4;
private static final int TINY = CompressedResponseWrapper.DEFAULT_MIN_COMPRESS_SIZE/ 2;
private String compressionType;
public GzipFilterContentLengthTest(Class<? extends Servlet> testServlet, String compressionType)
{
this.testServlet = testServlet;
this.compressionType = compressionType;
}
@Rule
public TestingDir testingdir = new TestingDir();
private Class<? extends Servlet> testServlet;
public GzipFilterContentLengthTest(Class<? extends Servlet> testServlet)
{
this.testServlet = testServlet;
}
private void assertIsGzipCompressed(String filename, int filesize) throws Exception
{
GzipTester tester = new GzipTester(testingdir);
GzipTester tester = new GzipTester(testingdir, compressionType);
File testfile = tester.prepareServerFile(testServlet.getSimpleName() + "-" + filename,filesize);
@ -93,7 +103,7 @@ public class GzipFilterContentLengthTest
private void assertIsNotGzipCompressed(String filename, int filesize) throws Exception
{
GzipTester tester = new GzipTester(testingdir);
GzipTester tester = new GzipTester(testingdir, compressionType);
File testfile = tester.prepareServerFile(testServlet.getSimpleName() + "-" + filename,filesize);

View File

@ -31,22 +31,41 @@ public class GzipFilterDefaultNoRecompressTest
return Arrays.asList(new Object[][]
{
// Some already compressed files
{ "test_quotes.gz", "application/gzip" },
{ "test_quotes.bz2", "application/bzip2" },
{ "test_quotes.zip", "application/zip" },
{ "test_quotes.rar", "application/octet-stream" },
{ "test_quotes.gz", "application/gzip", GzipFilter.GZIP },
{ "test_quotes.bz2", "application/bzip2", GzipFilter.GZIP },
{ "test_quotes.zip", "application/zip", GzipFilter.GZIP },
{ "test_quotes.rar", "application/octet-stream", GzipFilter.GZIP },
// Some images (common first)
{ "jetty_logo.png", "image/png" },
{ "jetty_logo.gif", "image/gif" },
{ "jetty_logo.jpeg", "image/jpeg" },
{ "jetty_logo.jpg", "image/jpeg" },
{ "jetty_logo.png", "image/png", GzipFilter.GZIP },
{ "jetty_logo.gif", "image/gif", GzipFilter.GZIP },
{ "jetty_logo.jpeg", "image/jpeg", GzipFilter.GZIP },
{ "jetty_logo.jpg", "image/jpeg", GzipFilter.GZIP },
// Lesser encountered images (usually found being requested from non-browser clients)
{ "jetty_logo.bmp", "image/bmp" },
{ "jetty_logo.tga", "application/tga" },
{ "jetty_logo.tif", "image/tiff" },
{ "jetty_logo.tiff", "image/tiff" },
{ "jetty_logo.xcf", "image/xcf" },
{ "jetty_logo.jp2", "image/jpeg2000" } });
{ "jetty_logo.bmp", "image/bmp", GzipFilter.GZIP },
{ "jetty_logo.tga", "application/tga", GzipFilter.GZIP },
{ "jetty_logo.tif", "image/tiff", GzipFilter.GZIP },
{ "jetty_logo.tiff", "image/tiff", GzipFilter.GZIP },
{ "jetty_logo.xcf", "image/xcf", GzipFilter.GZIP },
{ "jetty_logo.jp2", "image/jpeg2000", GzipFilter.GZIP },
// Same tests again for deflate
// Some already compressed files
{ "test_quotes.gz", "application/gzip", GzipFilter.DEFLATE },
{ "test_quotes.bz2", "application/bzip2", GzipFilter.DEFLATE },
{ "test_quotes.zip", "application/zip", GzipFilter.DEFLATE },
{ "test_quotes.rar", "application/octet-stream", GzipFilter.DEFLATE },
// Some images (common first)
{ "jetty_logo.png", "image/png", GzipFilter.DEFLATE },
{ "jetty_logo.gif", "image/gif", GzipFilter.DEFLATE },
{ "jetty_logo.jpeg", "image/jpeg", GzipFilter.DEFLATE },
{ "jetty_logo.jpg", "image/jpeg", GzipFilter.DEFLATE },
// Lesser encountered images (usually found being requested from non-browser clients)
{ "jetty_logo.bmp", "image/bmp", GzipFilter.DEFLATE },
{ "jetty_logo.tga", "application/tga", GzipFilter.DEFLATE },
{ "jetty_logo.tif", "image/tiff", GzipFilter.DEFLATE },
{ "jetty_logo.tiff", "image/tiff", GzipFilter.DEFLATE },
{ "jetty_logo.xcf", "image/xcf", GzipFilter.DEFLATE },
{ "jetty_logo.jp2", "image/jpeg2000", GzipFilter.DEFLATE } });
}
@Rule
@ -54,17 +73,19 @@ public class GzipFilterDefaultNoRecompressTest
private String alreadyCompressedFilename;
private String expectedContentType;
private String compressionType;
public GzipFilterDefaultNoRecompressTest(String testFilename, String expectedContentType)
public GzipFilterDefaultNoRecompressTest(String testFilename, String expectedContentType, String compressionType)
{
this.alreadyCompressedFilename = testFilename;
this.expectedContentType = expectedContentType;
this.compressionType = compressionType;
}
@Test
public void testNotGzipFiltered_Default_AlreadyCompressed() throws Exception
{
GzipTester tester = new GzipTester(testingdir);
GzipTester tester = new GzipTester(testingdir, compressionType);
copyTestFileToServer(alreadyCompressedFilename);

View File

@ -1,6 +1,8 @@
package org.eclipse.jetty.servlets;
import java.io.IOException;
import java.util.Arrays;
import java.util.Collection;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
@ -8,23 +10,47 @@ import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.eclipse.jetty.http.HttpStatus;
import org.eclipse.jetty.http.gzip.GzipResponseWrapper;
import org.eclipse.jetty.http.gzip.CompressedResponseWrapper;
import org.eclipse.jetty.servlet.DefaultServlet;
import org.eclipse.jetty.servlet.FilterHolder;
import org.eclipse.jetty.servlets.gzip.GzipTester;
import org.eclipse.jetty.toolchain.test.TestingDir;
import org.junit.Rule;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.Parameterized;
import org.junit.runners.Parameterized.Parameters;
/**
* Test the GzipFilter support built into the {@link DefaultServlet}
*/
@RunWith(Parameterized.class)
public class GzipFilterDefaultTest
{
@Parameters
public static Collection<String[]> data()
{
String[][] data = new String[][]
{
{ GzipFilter.GZIP },
{ GzipFilter.DEFLATE }
};
return Arrays.asList(data);
}
private String compressionType;
public GzipFilterDefaultTest(String compressionType)
{
this.compressionType = compressionType;
}
public static class HttpStatusServlet extends HttpServlet
{
private static final long serialVersionUID = 1L;
private int _status = 204;
public HttpStatusServlet()
@ -50,10 +76,10 @@ public class GzipFilterDefaultTest
@Test
public void testIsGzipCompressedTiny() throws Exception
{
GzipTester tester = new GzipTester(testingdir);
GzipTester tester = new GzipTester(testingdir, compressionType);
// Test content that is smaller than the buffer.
int filesize = GzipResponseWrapper.DEFAULT_BUFFER_SIZE / 4;
int filesize = CompressedResponseWrapper.DEFAULT_BUFFER_SIZE / 4;
tester.prepareServerFile("file.txt",filesize);
FilterHolder holder = tester.setContentServlet(org.eclipse.jetty.servlet.DefaultServlet.class);
@ -73,10 +99,10 @@ public class GzipFilterDefaultTest
@Test
public void testIsGzipCompressedLarge() throws Exception
{
GzipTester tester = new GzipTester(testingdir);
GzipTester tester = new GzipTester(testingdir, compressionType);
// Test content that is smaller than the buffer.
int filesize = GzipResponseWrapper.DEFAULT_BUFFER_SIZE * 4;
int filesize = CompressedResponseWrapper.DEFAULT_BUFFER_SIZE * 4;
tester.prepareServerFile("file.txt",filesize);
FilterHolder holder = tester.setContentServlet(org.eclipse.jetty.servlet.DefaultServlet.class);
@ -96,10 +122,10 @@ public class GzipFilterDefaultTest
@Test
public void testIsNotGzipCompressed() throws Exception
{
GzipTester tester = new GzipTester(testingdir);
GzipTester tester = new GzipTester(testingdir, compressionType);
// Test content that is smaller than the buffer.
int filesize = GzipResponseWrapper.DEFAULT_BUFFER_SIZE * 4;
int filesize = CompressedResponseWrapper.DEFAULT_BUFFER_SIZE * 4;
tester.prepareServerFile("file.mp3",filesize);
FilterHolder holder = tester.setContentServlet(org.eclipse.jetty.servlet.DefaultServlet.class);
@ -119,7 +145,7 @@ public class GzipFilterDefaultTest
@Test
public void testIsNotGzipCompressedHttpStatus() throws Exception
{
GzipTester tester = new GzipTester(testingdir);
GzipTester tester = new GzipTester(testingdir, compressionType);
// Test error code 204
FilterHolder holder = tester.setContentServlet(HttpStatusServlet.class);
@ -140,13 +166,13 @@ public class GzipFilterDefaultTest
@Test
public void testUserAgentExclusion() throws Exception
{
GzipTester tester = new GzipTester(testingdir);
GzipTester tester = new GzipTester(testingdir, compressionType);
FilterHolder holder = tester.setContentServlet(DefaultServlet.class);
holder.setInitParameter("excludedAgents", "foo");
tester.setUserAgent("foo");
int filesize = GzipResponseWrapper.DEFAULT_BUFFER_SIZE * 4;
int filesize = CompressedResponseWrapper.DEFAULT_BUFFER_SIZE * 4;
tester.prepareServerFile("file.txt",filesize);
try

View File

@ -1,17 +1,22 @@
package org.eclipse.jetty.servlets;
import static org.hamcrest.Matchers.*;
import static org.junit.Assert.*;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.URI;
import java.security.DigestOutputStream;
import java.security.MessageDigest;
import java.util.Arrays;
import java.util.Collection;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.zip.GZIPInputStream;
import java.util.zip.InflaterInputStream;
import org.eclipse.jetty.server.Connector;
import org.eclipse.jetty.server.Server;
@ -25,21 +30,46 @@ import org.eclipse.jetty.toolchain.test.IO;
import org.eclipse.jetty.toolchain.test.MavenTestingUtils;
import org.eclipse.jetty.toolchain.test.TestingDir;
import org.junit.After;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.Parameterized;
import org.junit.runners.Parameterized.Parameters;
/**
* Test the effects of Gzip filtering when in the context of HTTP/1.1 Pipelining.
*/
@RunWith(Parameterized.class)
public class GzipWithPipeliningTest
{
@Parameters
public static Collection<String[]> data()
{
// Test different Content-Encoding header combinations. So implicitly testing that gzip is preferred oder deflate
String[][] data = new String[][]
{
{ GzipFilter.GZIP },
{ GzipFilter.DEFLATE + ", " + GzipFilter.GZIP },
{ GzipFilter.GZIP + ", " + GzipFilter.DEFLATE },
{ GzipFilter.DEFLATE }
};
return Arrays.asList(data);
}
@Rule
public TestingDir testingdir = new TestingDir();
private Server server;
private URI serverUri;
private String encodingHeader;
public GzipWithPipeliningTest(String encodingHeader)
{
this.encodingHeader = encodingHeader;
}
@Before
public void startServer() throws Exception
@ -86,7 +116,7 @@ public class GzipWithPipeliningTest
testingdir.ensureEmpty();
File outputDir = testingdir.getDir();
PipelineHelper client = new PipelineHelper(serverUri);
PipelineHelper client = new PipelineHelper(serverUri, encodingHeader);
try
{
@ -95,7 +125,7 @@ public class GzipWithPipeliningTest
// Size of content, as it exists on disk, without gzip compression.
long rawsize = txtFile.length() + pngFile.length();
Assert.assertThat("Ensure that we have sufficient file size to trigger chunking",rawsize,greaterThan(300000L));
assertThat("Ensure that we have sufficient file size to trigger chunking",rawsize,greaterThan(300000L));
String respHeader;
@ -106,8 +136,9 @@ public class GzipWithPipeliningTest
respHeader = client.readResponseHeader();
System.out.println("Response Header #1 --\n" + respHeader);
Assert.assertThat("Content-Encoding should be gzipped",respHeader,containsString("Content-Encoding: gzip\r\n"));
Assert.assertThat("Transfer-Encoding should be chunked",respHeader,containsString("Transfer-Encoding: chunked\r\n"));
String expectedEncodingHeader = encodingHeader.equals(GzipFilter.DEFLATE) ? GzipFilter.DEFLATE : GzipFilter.GZIP;
assertThat("Content-Encoding should be gzipped",respHeader,containsString("Content-Encoding: " + expectedEncodingHeader + "\r\n"));
assertThat("Transfer-Encoding should be chunked",respHeader,containsString("Transfer-Encoding: chunked\r\n"));
// Raw output / gzipped, writted to disk (checked for sha1sum later)
File rawOutputFile = new File(outputDir, "response-1.gz");
@ -118,7 +149,7 @@ public class GzipWithPipeliningTest
// Read only 20% - intentionally a partial read.
System.out.println("Attempting to read partial content ...");
int readBytes = client.readBody(rawOutputStream,(int)((float)chunkSize * 0.20f));
int readBytes = client.readBody(rawOutputStream,(int)(chunkSize * 0.20f));
System.out.printf("Read %,d bytes%n",readBytes);
// Issue another request
@ -133,14 +164,14 @@ public class GzipWithPipeliningTest
readBytes = client.readBody(rawOutputStream,(int)chunkSize);
System.out.printf("Read %,d bytes%n",readBytes);
line = client.readLine();
Assert.assertThat("Chunk delim should be an empty line with CR+LF",line,is(""));
assertThat("Chunk delim should be an empty line with CR+LF",line,is(""));
chunkSize = client.readChunkSize();
System.out.printf("Next Chunk: (0x%X) %,d bytes%n",chunkSize,chunkSize);
}
// Inter-pipeline delim
line = client.readLine();
Assert.assertThat("Inter-pipeline delim should be an empty line with CR+LF",line,is(""));
assertThat("Inter-pipeline delim should be an empty line with CR+LF",line,is(""));
// Sha1tracking for 1st Request
MessageDigest digestTxt = MessageDigest.getInstance("SHA1");
@ -149,14 +180,23 @@ public class GzipWithPipeliningTest
// Decompress 1st request and calculate sha1sum
IO.close(rawOutputStream);
FileInputStream rawInputStream = new FileInputStream(rawOutputFile);
GZIPInputStream ungzipStream = new GZIPInputStream(rawInputStream);
IO.copy(ungzipStream, digesterTxt);
InputStream uncompressedStream = null;
if (GzipFilter.DEFLATE.equals(encodingHeader))
{
uncompressedStream = new InflaterInputStream(rawInputStream);
}
else
{
uncompressedStream = new GZIPInputStream(rawInputStream);
}
IO.copy(uncompressedStream, digesterTxt);
// Read 2nd request http response header
respHeader = client.readResponseHeader();
System.out.println("Response Header #2 --\n" + respHeader);
Assert.assertThat("Content-Encoding should NOT be gzipped",respHeader,not(containsString("Content-Encoding: gzip\r\n")));
Assert.assertThat("Transfer-Encoding should NOT be chunked",respHeader,not(containsString("Transfer-Encoding: chunked\r\n")));
assertThat("Content-Encoding should NOT be gzipped",respHeader,not(containsString("Content-Encoding: gzip\r\n")));
assertThat("Transfer-Encoding should NOT be chunked",respHeader,not(containsString("Transfer-Encoding: chunked\r\n")));
// Sha1tracking for 2nd Request
MessageDigest digestImg = MessageDigest.getInstance("SHA1");
@ -164,7 +204,7 @@ public class GzipWithPipeliningTest
// Read 2nd request body
int contentLength = client.getContentLength(respHeader);
Assert.assertThat("Image Content Length",(long)contentLength,is(pngFile.length()));
assertThat("Image Content Length",(long)contentLength,is(pngFile.length()));
client.readBody(digesterImg,contentLength);
// Validate checksums
@ -183,7 +223,7 @@ public class GzipWithPipeliningTest
{
String expectedSha1 = loadSha1sum(testResourceFile + ".sha1");
String actualSha1 = Hex.asHex(digest.digest());
Assert.assertEquals(testResourceFile + " / SHA1Sum of content",expectedSha1,actualSha1);
assertEquals(testResourceFile + " / SHA1Sum of content",expectedSha1,actualSha1);
}
private String loadSha1sum(String testResourceSha1Sum) throws IOException
@ -192,7 +232,7 @@ public class GzipWithPipeliningTest
String contents = IO.readToString(sha1File);
Pattern pat = Pattern.compile("^[0-9A-Fa-f]*");
Matcher mat = pat.matcher(contents);
Assert.assertTrue("Should have found HEX code in SHA1 file: " + sha1File,mat.find());
assertTrue("Should have found HEX code in SHA1 file: " + sha1File,mat.find());
return mat.group();
}

View File

@ -13,6 +13,9 @@
package org.eclipse.jetty.servlets;
import java.util.Arrays;
import java.util.Collection;
import javax.servlet.Servlet;
import org.eclipse.jetty.servlet.FilterHolder;
@ -21,6 +24,9 @@ import org.eclipse.jetty.servlets.gzip.TestMinGzipSizeServlet;
import org.eclipse.jetty.toolchain.test.TestingDir;
import org.junit.Rule;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.Parameterized;
import org.junit.runners.Parameterized.Parameters;
/**
* Perform specific tests on the IncludableGzipFilter's ability to manage
@ -28,17 +34,36 @@ import org.junit.Test;
*
* @see <a href="Eclipse Bug 366106">http://bugs.eclipse.org/366106</a>
*/
@RunWith(Parameterized.class)
public class IncludableGzipFilterMinSizeTest
{
@Parameters
public static Collection<String[]> data()
{
String[][] data = new String[][]
{
{ GzipFilter.GZIP },
{ GzipFilter.DEFLATE }
};
return Arrays.asList(data);
}
public IncludableGzipFilterMinSizeTest(String compressionType)
{
this.compressionType = compressionType;
}
@Rule
public TestingDir testdir = new TestingDir();
private String compressionType;
private Class<? extends Servlet> testServlet = TestMinGzipSizeServlet.class;
@Test
public void testUnderMinSize() throws Exception
{
GzipTester tester = new GzipTester(testdir);
GzipTester tester = new GzipTester(testdir, compressionType);
// Use IncludableGzipFilter
tester.setGzipFilterClass(IncludableGzipFilter.class);
@ -64,7 +89,7 @@ public class IncludableGzipFilterMinSizeTest
@Test
public void testOverMinSize() throws Exception
{
GzipTester tester = new GzipTester(testdir);
GzipTester tester = new GzipTester(testdir, compressionType);
// Use IncludableGzipFilter
tester.setGzipFilterClass(IncludableGzipFilter.class);

View File

@ -22,7 +22,10 @@ import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.util.Arrays;
import java.util.Collection;
import java.util.zip.GZIPInputStream;
import java.util.zip.InflaterInputStream;
import javax.servlet.http.HttpServletResponse;
@ -36,9 +39,28 @@ import org.junit.After;
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.Parameterized;
import org.junit.runners.Parameterized.Parameters;
@RunWith(Parameterized.class)
public class IncludableGzipFilterTest
{
@Parameters
public static Collection<String[]> data()
{
String[][] data = new String[][]
{
{ GzipFilter.GZIP },
{ GzipFilter.DEFLATE }
};
return Arrays.asList(data);
}
@Rule
public TestingDir testdir = new TestingDir();
private static String __content =
"Lorem ipsum dolor sit amet, consectetur adipiscing elit. In quis felis nunc. "+
"Quisque suscipit mauris et ante auctor ornare rhoncus lacus aliquet. Pellentesque "+
@ -53,11 +75,14 @@ public class IncludableGzipFilterTest
"Aliquam purus mauris, consectetur nec convallis lacinia, porta sed ante. Suspendisse "+
"et cursus magna. Donec orci enim, molestie a lobortis eu, imperdiet vitae neque.";
@Rule
public TestingDir testdir = new TestingDir();
private ServletTester tester;
private String compressionType;
public IncludableGzipFilterTest(String compressionType)
{
this.compressionType = compressionType;
}
@Before
public void setUp() throws Exception
{
@ -95,7 +120,7 @@ public class IncludableGzipFilterTest
request.setMethod("GET");
request.setVersion("HTTP/1.0");
request.setHeader("Host","tester");
request.setHeader("accept-encoding","gzip");
request.setHeader("accept-encoding", compressionType);
request.setURI("/context/file.txt");
ByteArrayBuffer reqsBuff = new ByteArrayBuffer(request.generate().getBytes());
@ -103,10 +128,19 @@ public class IncludableGzipFilterTest
response.parse(respBuff.asArray());
assertTrue(response.getMethod()==null);
assertTrue(response.getHeader("Content-Encoding").equalsIgnoreCase("gzip"));
assertTrue(response.getHeader("Content-Encoding").equalsIgnoreCase(compressionType));
assertEquals(HttpServletResponse.SC_OK,response.getStatus());
InputStream testIn = new GZIPInputStream(new ByteArrayInputStream(response.getContentBytes()));
InputStream testIn = null;
ByteArrayInputStream compressedResponseStream = new ByteArrayInputStream(response.getContentBytes());
if (compressionType.equals(GzipFilter.GZIP))
{
testIn = new GZIPInputStream(compressedResponseStream);
}
else if (compressionType.equals(GzipFilter.DEFLATE))
{
testIn = new InflaterInputStream(compressedResponseStream);
}
ByteArrayOutputStream testOut = new ByteArrayOutputStream();
IO.copy(testIn,testOut);

View File

@ -25,8 +25,9 @@ public class PipelineHelper
private Socket socket;
private OutputStream outputStream;
private InputStream inputStream;
private String encodingHeader;
public PipelineHelper(URI uri)
public PipelineHelper(URI uri, String encodingHeader)
{
if (LOG instanceof StdErrLog)
{
@ -34,6 +35,7 @@ public class PipelineHelper
}
this.uri = uri;
this.endpoint = new InetSocketAddress(uri.getHost(),uri.getPort());
this.encodingHeader = encodingHeader;
}
/**
@ -76,7 +78,7 @@ public class PipelineHelper
req.append("Accept-Language: en-us\r\n");
if (acceptGzipped)
{
req.append("Accept-Encoding: gzip, deflate\r\n");
req.append("Accept-Encoding: " + encodingHeader + "\r\n");
}
req.append("Cookie: JSESSIONID=spqx8v8szylt1336t96vc6mw0\r\n");
if ( close )
@ -134,7 +136,7 @@ public class PipelineHelper
while (!(foundCR && foundLF))
{
b = inputStream.read();
Assert.assertThat("Should not have hit EOL (yet) during chunk size read",(int)b,not(-1));
Assert.assertThat("Should not have hit EOL (yet) during chunk size read",b,not(-1));
if (b == 0x0D)
{
foundCR = true;
@ -163,7 +165,7 @@ public class PipelineHelper
while (!(foundCR && foundLF))
{
b = inputStream.read();
Assert.assertThat("Should not have hit EOL (yet) during chunk size read",(int)b,not(-1));
Assert.assertThat("Should not have hit EOL (yet) during chunk size read",b,not(-1));
if (b == 0x0D)
{
foundCR = true;

View File

@ -1,5 +1,13 @@
package org.eclipse.jetty.servlets.gzip;
import static org.hamcrest.Matchers.containsString;
import static org.hamcrest.Matchers.equalTo;
import static org.hamcrest.Matchers.is;
import static org.hamcrest.Matchers.not;
import static org.hamcrest.Matchers.notNullValue;
import static org.hamcrest.Matchers.nullValue;
import static org.junit.Assert.assertThat;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.File;
@ -12,6 +20,8 @@ import java.util.Enumeration;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.zip.GZIPInputStream;
import java.util.zip.InflaterInputStream;
import javax.servlet.Servlet;
import javax.servlet.http.HttpServletResponse;
@ -26,12 +36,6 @@ import org.eclipse.jetty.toolchain.test.MavenTestingUtils;
import org.eclipse.jetty.toolchain.test.TestingDir;
import org.junit.Assert;
import static org.hamcrest.Matchers.containsString;
import static org.hamcrest.Matchers.is;
import static org.hamcrest.Matchers.not;
import static org.hamcrest.Matchers.notNullValue;
import static org.hamcrest.Matchers.nullValue;
public class GzipTester
{
private Class<? extends GzipFilter> gzipFilterClass = GzipFilter.class;
@ -39,10 +43,12 @@ public class GzipTester
private String userAgent = null;
private ServletTester servletTester;
private TestingDir testdir;
private String compressionType;
public GzipTester(TestingDir testingdir)
public GzipTester(TestingDir testingdir, String compressionType)
{
this.testdir = testingdir;
this.compressionType = compressionType;
// Make sure we start with a clean testing directory.
// DOES NOT WORK IN WINDOWS - this.testdir.ensureEmpty();
}
@ -61,7 +67,7 @@ public class GzipTester
request.setMethod("GET");
request.setVersion("HTTP/1.0");
request.setHeader("Host","tester");
request.setHeader("Accept-Encoding","gzip");
request.setHeader("Accept-Encoding",compressionType);
if (this.userAgent != null)
request.setHeader("User-Agent", this.userAgent);
request.setURI("/context/" + requestedFilename);
@ -76,7 +82,7 @@ public class GzipTester
Assert.assertThat("Response.method",response.getMethod(),nullValue());
Assert.assertThat("Response.status",response.getStatus(),is(HttpServletResponse.SC_OK));
Assert.assertThat("Response.header[Content-Length]",response.getHeader("Content-Length"),notNullValue());
Assert.assertThat("Response.header[Content-Encoding]",response.getHeader("Content-Encoding"),containsString("gzip"));
Assert.assertThat("Response.header[Content-Encoding]",response.getHeader("Content-Encoding"),containsString(compressionType));
// Assert that the decompressed contents are what we expect.
File serverFile = testdir.getFile(serverFilename);
@ -89,12 +95,19 @@ public class GzipTester
try
{
bais = new ByteArrayInputStream(response.getContentBytes());
in = new GZIPInputStream(bais);
if (compressionType.equals(GzipFilter.GZIP))
{
in = new GZIPInputStream(bais);
}
else if (compressionType.equals(GzipFilter.DEFLATE))
{
in = new InflaterInputStream(bais);
}
out = new ByteArrayOutputStream();
IO.copy(in,out);
actual = out.toString(encoding);
Assert.assertEquals("Uncompressed contents",expected,actual);
assertThat("Uncompressed contents",actual,equalTo(expected));
}
finally
{
@ -128,7 +141,7 @@ public class GzipTester
request.setMethod("GET");
request.setVersion("HTTP/1.0");
request.setHeader("Host","tester");
request.setHeader("Accept-Encoding","gzip");
request.setHeader("Accept-Encoding",compressionType);
if (this.userAgent != null)
request.setHeader("User-Agent", this.userAgent);
request.setURI("/context/" + requestedFilename);
@ -215,7 +228,7 @@ public class GzipTester
request.setMethod("GET");
request.setVersion("HTTP/1.0");
request.setHeader("Host","tester");
request.setHeader("Accept-Encoding","gzip");
request.setHeader("Accept-Encoding",compressionType);
if (this.userAgent != null)
request.setHeader("User-Agent", this.userAgent);
if (filename == null)
@ -238,7 +251,7 @@ public class GzipTester
int serverLength = Integer.parseInt(response.getHeader("Content-Length"));
Assert.assertThat("Response.header[Content-Length]",serverLength,is(expectedFilesize));
}
Assert.assertThat("Response.header[Content-Encoding]",response.getHeader("Content-Encoding"),not(containsString("gzip")));
Assert.assertThat("Response.header[Content-Encoding]",response.getHeader("Content-Encoding"),not(containsString(compressionType)));
// Assert that the contents are what we expect.
if (filename != null)

View File

@ -1,10 +1,9 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<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>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-project</artifactId>
<version>7.6.2-SNAPSHOT</version>
<version>7.6.3-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
@ -13,6 +12,14 @@
<packaging>pom</packaging>
<name>Jetty :: SPDY :: Parent</name>
<properties>
<!--
npn version only needs to change when there are changes in that binary, not
with each and every release.
-->
<npn.version>7.6.2.v20120308</npn.version>
</properties>
<modules>
<module>spdy-core</module>
<module>spdy-jetty</module>

View File

@ -1,11 +1,9 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<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>
<groupId>org.eclipse.jetty.spdy</groupId>
<artifactId>spdy-parent</artifactId>
<version>7.6.2-SNAPSHOT</version>
<version>7.6.3-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>

View File

@ -35,6 +35,4 @@ public interface ISession extends Session
public <C> void control(IStream stream, ControlFrame frame, long timeout, TimeUnit unit, Handler<C> handler, C context);
public <C> void data(IStream stream, DataInfo dataInfo, long timeout, TimeUnit unit, Handler<C> handler, C context);
public int getWindowSize();
}

View File

@ -80,7 +80,9 @@ public class Promise<T> implements Handler<T>, Future<T>
@Override
public T get(long timeout, TimeUnit unit) throws InterruptedException, ExecutionException, TimeoutException
{
latch.await(timeout, unit);
boolean elapsed = !latch.await(timeout, unit);
if (elapsed)
throw new TimeoutException();
return result();
}

View File

@ -18,10 +18,10 @@ package org.eclipse.jetty.spdy;
import java.nio.ByteBuffer;
import java.nio.channels.InterruptedByTimeoutException;
import java.util.ArrayList;
import java.util.Deque;
import java.util.HashSet;
import java.util.LinkedList;
import java.util.List;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
import java.util.concurrent.CopyOnWriteArrayList;
@ -78,7 +78,7 @@ public class StandardSession implements ISession, Parser.Listener, Handler<Stand
private final List<Listener> listeners = new CopyOnWriteArrayList<>();
private final ConcurrentMap<Integer, IStream> streams = new ConcurrentHashMap<>();
private final Deque<FrameBytes> queue = new LinkedList<>();
private final LinkedList<FrameBytes> queue = new LinkedList<>();
private final ByteBufferPool bufferPool;
private final Executor threadPool;
private final ScheduledExecutorService scheduler;
@ -253,9 +253,9 @@ public class StandardSession implements ISession, Parser.Listener, Handler<Stand
}
@Override
public List<Stream> getStreams()
public Set<Stream> getStreams()
{
List<Stream> result = new ArrayList<>();
Set<Stream> result = new HashSet<>();
result.addAll(streams.values());
return result;
}
@ -540,7 +540,10 @@ public class StandardSession implements ISession, Parser.Listener, Handler<Stand
Settings.Setting windowSizeSetting = frame.getSettings().get(Settings.ID.INITIAL_WINDOW_SIZE);
if (windowSizeSetting != null)
{
int prevWindowSize = windowSize;
windowSize = windowSizeSetting.value();
for (IStream stream : streams.values())
stream.updateWindowSize(windowSize - prevWindowSize);
logger.debug("Updated window size to {}", windowSize);
}
@ -728,10 +731,10 @@ public class StandardSession implements ISession, Parser.Listener, Handler<Stand
{
ByteBuffer buffer = generator.control(frame);
logger.debug("Queuing {} on {}", frame, stream);
ControlFrameBytes<C> frameBytes = new ControlFrameBytes<>(handler, context, frame, buffer);
ControlFrameBytes<C> frameBytes = new ControlFrameBytes<>(stream, handler, context, frame, buffer);
if (timeout > 0)
frameBytes.task = scheduler.schedule(frameBytes, timeout, unit);
enqueueLast(frameBytes);
append(frameBytes);
}
flush();
@ -762,10 +765,10 @@ public class StandardSession implements ISession, Parser.Listener, Handler<Stand
public <C> void data(IStream stream, DataInfo dataInfo, long timeout, TimeUnit unit, Handler<C> handler, C context)
{
logger.debug("Queuing {} on {}", dataInfo, stream);
DataFrameBytes<C> frameBytes = new DataFrameBytes<>(handler, context, stream, dataInfo);
DataFrameBytes<C> frameBytes = new DataFrameBytes<>(stream, handler, context, dataInfo);
if (timeout > 0)
frameBytes.task = scheduler.schedule(frameBytes, timeout, unit);
enqueueLast(frameBytes);
append(frameBytes);
flush();
}
@ -774,56 +777,71 @@ public class StandardSession implements ISession, Parser.Listener, Handler<Stand
threadPool.execute(task);
}
@Override
public int getWindowSize()
{
return windowSize;
}
@Override
public void flush()
{
FrameBytes frameBytes;
ByteBuffer buffer;
FrameBytes frameBytes = null;
ByteBuffer buffer = null;
synchronized (queue)
{
if (flushing)
if (flushing || queue.isEmpty())
return;
frameBytes = queue.poll();
if (frameBytes == null)
return;
buffer = frameBytes.getByteBuffer();
if (buffer == null)
Set<IStream> stalledStreams = null;
for (int i = 0; i < queue.size(); ++i)
{
enqueueFirst(frameBytes);
logger.debug("Flush skipped, {} frame(s) in queue", queue.size());
return;
frameBytes = queue.get(i);
if (stalledStreams != null && stalledStreams.contains(frameBytes.getStream()))
continue;
buffer = frameBytes.getByteBuffer();
if (buffer != null)
{
queue.remove(i);
break;
}
if (stalledStreams == null)
stalledStreams = new HashSet<>();
stalledStreams.add(frameBytes.getStream());
logger.debug("Flush stalled for {}, {} frame(s) in queue", frameBytes, queue.size());
}
if (buffer == null)
return;
flushing = true;
logger.debug("Flushing {}, {} frame(s) in queue", frameBytes, queue.size());
}
logger.debug("Writing {} frame bytes of {}", buffer.remaining(), frameBytes);
write(buffer, this, frameBytes);
}
private void enqueueLast(FrameBytes frameBytes)
private void append(FrameBytes frameBytes)
{
// TODO: handle priority; e.g. use queues to prioritize the buffers ?
synchronized (queue)
{
queue.offerLast(frameBytes);
}
enqueue(frameBytes, false);
}
private void enqueueFirst(FrameBytes frameBytes)
private void prepend(FrameBytes frameBytes)
{
enqueue(frameBytes, true);
}
private void enqueue(FrameBytes frameBytes, boolean prepend)
{
synchronized (queue)
{
queue.offerFirst(frameBytes);
int index = 0;
while (index < queue.size())
{
FrameBytes element = queue.get(index);
int comparison = element.compareTo(frameBytes);
if (comparison > 0 || prepend && comparison == 0)
break;
++index;
}
queue.add(index, frameBytes);
}
}
@ -836,6 +854,7 @@ public class StandardSession implements ISession, Parser.Listener, Handler<Stand
flushing = false;
}
frameBytes.complete();
flush();
}
@Override
@ -847,7 +866,10 @@ public class StandardSession implements ISession, Parser.Listener, Handler<Stand
protected void write(ByteBuffer buffer, Handler<FrameBytes> handler, FrameBytes frameBytes)
{
if (controller != null)
{
logger.debug("Writing {} frame bytes of {}", buffer.remaining(), frameBytes);
controller.write(buffer, handler, frameBytes);
}
}
private <C> void complete(final Handler<C> handler, final C context)
@ -913,8 +935,10 @@ public class StandardSession implements ISession, Parser.Listener, Handler<Stand
}
}
public interface FrameBytes
public interface FrameBytes extends Comparable<FrameBytes>
{
public IStream getStream();
public abstract ByteBuffer getByteBuffer();
public abstract void complete();
@ -922,16 +946,30 @@ public class StandardSession implements ISession, Parser.Listener, Handler<Stand
private abstract class AbstractFrameBytes<C> implements FrameBytes, Runnable
{
private final IStream stream;
private final Handler<C> handler;
private final C context;
protected volatile ScheduledFuture<?> task;
protected AbstractFrameBytes(Handler<C> handler, C context)
protected AbstractFrameBytes(IStream stream, Handler<C> handler, C context)
{
this.stream = stream;
this.handler = handler;
this.context = context;
}
@Override
public IStream getStream()
{
return stream;
}
@Override
public int compareTo(FrameBytes that)
{
return getStream().getPriority() - that.getStream().getPriority();
}
@Override
public void complete()
{
@ -959,9 +997,9 @@ public class StandardSession implements ISession, Parser.Listener, Handler<Stand
private final ControlFrame frame;
private final ByteBuffer buffer;
private ControlFrameBytes(Handler<C> handler, C context, ControlFrame frame, ByteBuffer buffer)
private ControlFrameBytes(IStream stream, Handler<C> handler, C context, ControlFrame frame, ByteBuffer buffer)
{
super(handler, context);
super(stream, handler, context);
this.frame = frame;
this.buffer = buffer;
}
@ -996,15 +1034,13 @@ public class StandardSession implements ISession, Parser.Listener, Handler<Stand
private class DataFrameBytes<C> extends AbstractFrameBytes<C>
{
private final IStream stream;
private final DataInfo dataInfo;
private int length;
private ByteBuffer buffer;
private int size;
private volatile ByteBuffer buffer;
private DataFrameBytes(Handler<C> handler, C context, IStream stream, DataInfo dataInfo)
private DataFrameBytes(IStream stream, Handler<C> handler, C context, DataInfo dataInfo)
{
super(handler, context);
this.stream = stream;
super(stream, handler, context);
this.dataInfo = dataInfo;
}
@ -1013,15 +1049,16 @@ public class StandardSession implements ISession, Parser.Listener, Handler<Stand
{
try
{
IStream stream = getStream();
int windowSize = stream.getWindowSize();
if (windowSize <= 0)
return null;
length = dataInfo.length();
if (length > windowSize)
length = windowSize;
size = dataInfo.available();
if (size > windowSize)
size = windowSize;
buffer = generator.data(stream.getId(), length, dataInfo);
buffer = generator.data(stream.getId(), size, dataInfo);
return buffer;
}
catch (Throwable x)
@ -1034,14 +1071,16 @@ public class StandardSession implements ISession, Parser.Listener, Handler<Stand
@Override
public void complete()
{
stream.updateWindowSize(-length);
bufferPool.release(buffer);
IStream stream = getStream();
stream.updateWindowSize(-size);
if (dataInfo.available() > 0)
{
// If we could not write a full data frame, then we need first
// to finish it, and then process the others (to avoid data garbling)
enqueueFirst(this);
// We have written a frame out of this DataInfo, but there is more to write.
// We need to keep the correct ordering of frames, to avoid that another
// DataInfo for the same stream is written before this one is finished.
prepend(this);
}
else
{
@ -1055,7 +1094,7 @@ public class StandardSession implements ISession, Parser.Listener, Handler<Stand
@Override
public String toString()
{
return String.format("DATA bytes @%x available=%d consumed=%d on %s", dataInfo.hashCode(), dataInfo.available(), dataInfo.consumed(), stream);
return String.format("DATA bytes @%x available=%d consumed=%d on %s", dataInfo.hashCode(), dataInfo.available(), dataInfo.consumed(), getStream());
}
}
}

View File

@ -17,7 +17,7 @@
package org.eclipse.jetty.spdy.api;
import java.util.EventListener;
import java.util.List;
import java.util.Set;
import java.util.concurrent.Future;
import java.util.concurrent.TimeUnit;
@ -181,7 +181,7 @@ public interface Session
/**
* @return the streams currently active in this session
*/
public List<Stream> getStreams();
public Set<Stream> getStreams();
/**
* <p>Super interface for listeners with callbacks that are invoked on specific session events.</p>

View File

@ -65,7 +65,7 @@ public class SettingsGenerator extends ControlFrameGenerator
case SPDY.V2:
{
// In v2 the format is 24 bits of ID + 8 bits of flag
int idAndFlags = (id << 8) + flags;
int idAndFlags = (id << 8) + (flags & 0xFF);
// A bug in the Chromium implementation forces v2 to have
// the 3 ID bytes little endian, so we swap first and third
int result = idAndFlags & 0x00_FF_00_FF;

View File

@ -58,6 +58,10 @@ public class GoAwayBodyParser extends ControlFrameBodyParser
state = State.STATUS_CODE;
break;
}
default:
{
throw new IllegalStateException();
}
}
}
else
@ -87,6 +91,10 @@ public class GoAwayBodyParser extends ControlFrameBodyParser
state = State.STATUS_CODE;
break;
}
default:
{
throw new IllegalStateException();
}
}
}
break;

View File

@ -22,7 +22,6 @@ import java.util.concurrent.Executor;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicInteger;
import org.eclipse.jetty.spdy.api.Handler;
import org.eclipse.jetty.spdy.api.SPDY;
@ -94,17 +93,15 @@ public class AsyncTimeoutTest
Generator generator = new Generator(new StandardByteBufferPool(), new StandardCompressionFactory.StandardCompressor());
Session session = new StandardSession(SPDY.V2, bufferPool, threadPool, scheduler, new TestController(), null, 1, null, generator)
{
private final AtomicInteger flushes = new AtomicInteger();
@Override
public void flush()
protected void write(ByteBuffer buffer, Handler<FrameBytes> handler, FrameBytes frameBytes)
{
try
{
int flushes = this.flushes.incrementAndGet();
if (flushes == 3)
// Wait if we're writing the data frame (control frame's first byte is 0x80)
if (buffer.get(0) == 0)
unit.sleep(2 * timeout);
super.flush();
super.write(buffer, handler, frameBytes);
}
catch (InterruptedException x)
{

View File

@ -1,19 +1,35 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<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>
<groupId>org.eclipse.jetty.spdy</groupId>
<artifactId>spdy-parent</artifactId>
<version>7.6.2-SNAPSHOT</version>
<version>7.6.3-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>spdy-jetty-http-webapp</artifactId>
<packaging>war</packaging>
<name>Jetty :: SPDY :: Jetty HTTP Web Application</name>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-assembly-plugin</artifactId>
<executions>
<execution>
<phase>package</phase>
<goals>
<goal>single</goal>
</goals>
<configuration>
<descriptorRefs>
<descriptorRef>config</descriptorRef>
</descriptorRefs>
</configuration>
</execution>
</executions>
</plugin>
<!--
<build>
<plugins>
<plugin>
<groupId>org.mortbay.jetty</groupId>
<artifactId>jetty-maven-plugin</artifactId>
@ -41,7 +57,7 @@
</dependency>
</dependencies>
</plugin>
</plugins>
</build>
-->
</plugins>
</build>
</project>

Some files were not shown because too many files have changed in this diff Show More