Merge remote-tracking branch 'origin/master' into jetty-http2

Conflicts:
	jetty-alpn/jetty-alpn-server/src/main/config/modules/protonego-impl/alpn.mod
	jetty-http/src/main/java/org/eclipse/jetty/http/HttpParser.java
	jetty-npn/jetty-npn-server/src/main/config/modules/protonego-impl/npn.mod
	jetty-spdy/spdy-http-server/src/main/java/org/eclipse/jetty/spdy/server/http/HttpChannelOverSPDY.java
This commit is contained in:
Greg Wilkins 2014-09-04 17:43:18 +10:00
commit 5b97d652e1
12 changed files with 162 additions and 80 deletions

View File

@ -23,14 +23,14 @@ import java.net.URL;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
import java.util.Set;
import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import org.apache.jasper.servlet.JasperInitializer;
import org.apache.jasper.servlet.TldPreScanned;
import org.apache.jasper.servlet.TldScanner;
import org.eclipse.jetty.util.log.Log;
import org.eclipse.jetty.util.log.Logger;
import org.xml.sax.SAXException;
/**
@ -39,6 +39,7 @@ import org.xml.sax.SAXException;
*/
public class JettyJasperInitializer extends JasperInitializer
{
private static final Logger LOG = Log.getLogger(JettyJasperInitializer.class);
/**
* NullTldScanner
@ -99,14 +100,18 @@ public class JettyJasperInitializer extends JasperInitializer
String tmp = context.getInitParameter("org.eclipse.jetty.jsp.precompiled");
if (tmp!=null && !tmp.equals("") && Boolean.valueOf(tmp))
{
if (LOG.isDebugEnabled()) LOG.debug("Jsp precompilation detected");
return new NullTldScanner(context, namespaceAware, validate, blockExternal);
}
Collection<URL> tldUrls = (Collection<URL>)context.getAttribute("org.eclipse.jetty.tlds");
if (tldUrls != null && !tldUrls.isEmpty())
if (tldUrls != null)
{
if (LOG.isDebugEnabled()) LOG.debug("Tld pre-scan detected");
return new TldPreScanned(context,namespaceAware,validate,blockExternal,tldUrls);
}
if (LOG.isDebugEnabled()) LOG.debug("Defaulting to jasper tld scanning");
return super.newTldScanner(context, namespaceAware, validate, blockExternal);
}

View File

@ -35,3 +35,9 @@ lib/alpn/
# alpn.protocols=h2-14,http/1.1
# alpn.defaultProtocol=http/1.1
[license]
ALPN is a hosted at github under the GPL v2 with ClassPath Exception.
ALPM replaces/modified OpenJDK classes in the java.sun.security.ssl package.
http://github.com/jetty-project/jetty-alpn
http://openjdk.java.net/legal/gplv2+ce.html

View File

@ -18,6 +18,11 @@
package org.eclipse.jetty.http;
import static org.eclipse.jetty.http.HttpTokens.CARRIAGE_RETURN;
import static org.eclipse.jetty.http.HttpTokens.LINE_FEED;
import static org.eclipse.jetty.http.HttpTokens.SPACE;
import static org.eclipse.jetty.http.HttpTokens.TAB;
import java.nio.ByteBuffer;
import java.nio.charset.StandardCharsets;
@ -339,22 +344,22 @@ public class HttpParser
if (_cr)
{
if (ch!=HttpTokens.LINE_FEED)
if (ch!=LINE_FEED)
throw new BadMessageException("Bad EOL");
_cr=false;
return ch;
}
if (ch>=0 && ch<HttpTokens.SPACE)
if (ch>=0 && ch<SPACE)
{
if (ch==HttpTokens.CARRIAGE_RETURN)
if (ch==CARRIAGE_RETURN)
{
if (buffer.hasRemaining())
{
if(_maxHeaderBytes>0 && _state.ordinal()<State.END.ordinal())
_headerBytes++;
ch=buffer.get();
if (ch!=HttpTokens.LINE_FEED)
if (ch!=LINE_FEED)
throw new BadMessageException("Bad EOL");
}
else
@ -366,8 +371,8 @@ public class HttpParser
}
}
// Only LF or TAB acceptable special characters
else if (!(ch==HttpTokens.LINE_FEED || ch==HttpTokens.TAB))
throw new BadMessageException("Illegal character");
else if (!(ch==LINE_FEED || ch==TAB))
throw new IllegalCharacter(ch,buffer);
}
return ch;
@ -407,7 +412,7 @@ public class HttpParser
{
int ch=next(buffer);
if (ch > HttpTokens.SPACE)
if (ch > SPACE)
{
_string.setLength(0);
_string.append((char)ch);
@ -482,7 +487,7 @@ public class HttpParser
switch (_state)
{
case METHOD:
if (ch == HttpTokens.SPACE)
if (ch == SPACE)
{
_length=_string.length();
_methodString=takeString();
@ -491,8 +496,13 @@ public class HttpParser
_methodString=method.asString();
setState(State.SPACE1);
}
else if (ch < HttpTokens.SPACE)
throw new BadMessageException(ch<0?"Illegal character":"No URI");
else if (ch < SPACE)
{
if (ch==LINE_FEED)
throw new BadMessageException("No URI");
else
throw new IllegalCharacter(ch,buffer);
}
else
_string.append((char)ch);
break;
@ -508,7 +518,7 @@ public class HttpParser
setState(State.SPACE1);
}
else if (ch < HttpTokens.SPACE)
throw new BadMessageException(ch<0?"Illegal character":"No Status");
throw new IllegalCharacter(ch,buffer);
else
_string.append((char)ch);
break;
@ -1034,10 +1044,8 @@ public class HttpParser
_length=_string.length();
break;
}
if (LOG.isDebugEnabled())
LOG.debug("Illegal character '{}' in {}",ch,BufferUtil.toDetailString(buffer));
throw new BadMessageException("Illegal character");
throw new IllegalCharacter(ch,buffer);
case HEADER_VALUE:
if (ch>HttpTokens.SPACE || ch<0)
@ -1050,8 +1058,8 @@ public class HttpParser
if (ch==HttpTokens.SPACE || ch==HttpTokens.TAB)
break;
throw new BadMessageException();
throw new IllegalCharacter(ch,buffer);
case HEADER_IN_VALUE:
if (ch>=HttpTokens.SPACE || ch<0 || ch==HttpTokens.TAB)
@ -1080,7 +1088,8 @@ public class HttpParser
setState(State.HEADER);
break;
}
throw new BadMessageException("Illegal character");
throw new IllegalCharacter(ch,buffer);
default:
throw new IllegalStateException(_state.toString());
@ -1478,6 +1487,29 @@ public class HttpParser
_state=state;
}
/* ------------------------------------------------------------------------------- */
public Trie<HttpField> getFieldCache()
{
return _connectionFields;
}
/* ------------------------------------------------------------------------------- */
private String getProxyField(ByteBuffer buffer)
{
_string.setLength(0);
_length=0;
while (buffer.hasRemaining())
{
// process each character
byte ch=next(buffer);
if (ch<=' ')
return _string.toString();
_string.append((char)ch);
}
throw new BadMessageException();
}
/* ------------------------------------------------------------------------------- */
@Override
public String toString()
@ -1532,13 +1564,17 @@ public class HttpParser
public int getHeaderCacheSize();
}
/* ------------------------------------------------------------------------------- */
/* ------------------------------------------------------------------------------- */
/* ------------------------------------------------------------------------------- */
public interface ProxyHandler
{
void proxied(String protocol, String sAddr, String dAddr, int sPort, int dPort);
}
/* ------------------------------------------------------------------------------- */
/* ------------------------------------------------------------------------------- */
/* ------------------------------------------------------------------------------- */
public interface RequestHandler extends HttpHandler
{
/**
@ -1552,6 +1588,9 @@ public class HttpParser
}
/* ------------------------------------------------------------------------------- */
/* ------------------------------------------------------------------------------- */
/* ------------------------------------------------------------------------------- */
public interface ResponseHandler extends HttpHandler
{
/**
@ -1560,24 +1599,14 @@ public class HttpParser
public boolean startResponse(HttpVersion version, int status, String reason);
}
public Trie<HttpField> getFieldCache()
/* ------------------------------------------------------------------------------- */
/* ------------------------------------------------------------------------------- */
/* ------------------------------------------------------------------------------- */
private class IllegalCharacter extends BadMessageException
{
return _connectionFields;
}
private String getProxyField(ByteBuffer buffer)
{
_string.setLength(0);
_length=0;
while (buffer.hasRemaining())
IllegalCharacter(byte ch,ByteBuffer buffer)
{
// process each character
byte ch=next(buffer);
if (ch<=' ')
return _string.toString();
_string.append((char)ch);
super(String.format("Illegal character 0x%x in state=%s in '%s'",ch,_state,BufferUtil.toDebugString(buffer)));
}
throw new BadMessageException();
}
}

View File

@ -416,7 +416,10 @@ public class MongoSessionIdManager extends AbstractSessionIdManager
_scheduler = new ScheduledExecutorScheduler();
_ownScheduler = true;
_scheduler.start();
}
}
else if (!_scheduler.isStarted())
throw new IllegalStateException("Shared scheduler not started");
//setup the scavenger thread
if (_scavengePeriod > 0)

View File

@ -34,3 +34,9 @@ lib/npn/
[ini-template]
# npn.protocols=spdy/3,http/1.1
# npn.defaultProtocol=http/1.1
[license]
NPN is a hosted at github under the GPL v2 with ClassPath Exception.
NPN replaces/modified OpenJDK classes in the java.sun.security.ssl package.
http://github.com/jetty-project/jetty-npn
http://openjdk.java.net/legal/gplv2+ce.html

View File

@ -992,6 +992,8 @@ public class JDBCSessionIdManager extends AbstractSessionIdManager
_ownScheduler = true;
_scheduler.start();
}
else if (!_scheduler.isStarted())
throw new IllegalStateException("Shared scheduler not started");
setScavengeInterval(getScavengeInterval());
}

View File

@ -51,6 +51,11 @@ public class HttpChannelOverSPDY extends HttpChannel
this.stream = stream;
}
public long getIdleTimeout()
{
return stream.getIdleTimeout();
}
public void requestStart(final Fields headers, final boolean endRequest)
{
if (!headers.isEmpty())

View File

@ -920,6 +920,11 @@ public class BufferUtil
return builder.toString();
}
/* ------------------------------------------------------------ */
/** Convert Buffer to a detail debug string of pointers and content
* @param buffer
* @return A string showing the pointers and content of the buffer
*/
public static String toDetailString(ByteBuffer buffer)
{
if (buffer == null)
@ -942,15 +947,33 @@ public class BufferUtil
buf.append(buffer.remaining());
buf.append("]={");
appendDebugString(buf,buffer);
buf.append("}");
return buf.toString();
}
/* ------------------------------------------------------------ */
/** Convert buffer to a Debug String.
* @param buffer
* @return A string showing the escaped content of the buffer around the
* position and limit (marked with &lt;&lt;&lt; and &gt;&gt;&gt;)
*/
public static String toDebugString(ByteBuffer buffer)
{
if (buffer == null)
return "null";
StringBuilder buf = new StringBuilder();
appendDebugString(buf,buffer);
return buf.toString();
}
private static void appendDebugString(StringBuilder buf,ByteBuffer buffer)
{
for (int i = 0; i < buffer.position(); i++)
{
char c = (char)buffer.get(i);
if (c >= ' ' && c <= 127)
buf.append(c);
else if (c == '\r' || c == '\n')
buf.append('|');
else
buf.append('\ufffd');
appendContentChar(buf,buffer.get(i));
if (i == 16 && buffer.position() > 32)
{
buf.append("...");
@ -960,13 +983,7 @@ public class BufferUtil
buf.append("<<<");
for (int i = buffer.position(); i < buffer.limit(); i++)
{
char c = (char)buffer.get(i);
if (c >= ' ' && c <= 127)
buf.append(c);
else if (c == '\r' || c == '\n')
buf.append('|');
else
buf.append('\ufffd');
appendContentChar(buf,buffer.get(i));
if (i == buffer.position() + 16 && buffer.limit() > buffer.position() + 32)
{
buf.append("...");
@ -978,13 +995,7 @@ public class BufferUtil
buffer.limit(buffer.capacity());
for (int i = limit; i < buffer.capacity(); i++)
{
char c = (char)buffer.get(i);
if (c >= ' ' && c <= 127)
buf.append(c);
else if (c == '\r' || c == '\n')
buf.append('|');
else
buf.append('\ufffd');
appendContentChar(buf,buffer.get(i));
if (i == limit + 16 && buffer.capacity() > limit + 32)
{
buf.append("...");
@ -992,11 +1003,23 @@ public class BufferUtil
}
}
buffer.limit(limit);
buf.append("}");
return buf.toString();
}
private static void appendContentChar(StringBuilder buf, byte b)
{
if (b == '\\')
buf.append("\\\\");
else if (b >= ' ')
buf.append((char)b);
else if (b == '\r')
buf.append("\\r");
else if (b == '\n')
buf.append("\\n");
else if (b == '\t')
buf.append("\\t");
else
buf.append("\\x").append(TypeUtil.toHexString(b));
}
private final static int[] decDivisors =
{1000000000, 100000000, 10000000, 1000000, 100000, 10000, 1000, 100, 10, 1};

View File

@ -104,7 +104,8 @@ public class SharedBlockingCallback
{
if (idle>0)
{
if (!_idle.await(idle,TimeUnit.MILLISECONDS))
// Wait a little bit longer than the blocker might block
if (!_idle.await(idle*2,TimeUnit.MILLISECONDS))
throw new IOException(new TimeoutException());
}
else
@ -114,12 +115,7 @@ public class SharedBlockingCallback
}
catch (final InterruptedException e)
{
throw new InterruptedIOException()
{
{
initCause(e);
}
};
throw new InterruptedIOException();
}
finally
{
@ -213,7 +209,8 @@ public class SharedBlockingCallback
{
if (idle>0)
{
if (!_complete.await(idle,TimeUnit.MILLISECONDS))
// Wait a little bit longer than expected callback idle timeout
if (!_complete.await(idle+idle/2,TimeUnit.MILLISECONDS))
// The callback has not arrived in sufficient time.
// We will synthesize a TimeoutException
_state=new BlockerTimeoutException();
@ -238,12 +235,7 @@ public class SharedBlockingCallback
}
catch (final InterruptedException e)
{
throw new InterruptedIOException()
{
{
initCause(e);
}
};
throw new InterruptedIOException();
}
finally
{

View File

@ -71,6 +71,17 @@ public class MetaInfConfiguration extends AbstractConfiguration
useContainerCache = attr.booleanValue();
if (LOG.isDebugEnabled()) LOG.debug("{} = {}", USE_CONTAINER_METAINF_CACHE, useContainerCache);
//pre-emptively create empty lists for tlds, fragments and resources as context attributes
//this signals that this class has been called. This differentiates the case where this class
//has been called but finds no META-INF data from the case where this class was never called
if (context.getAttribute(METAINF_TLDS) == null)
context.setAttribute(METAINF_TLDS, new HashSet<URL>());
if (context.getAttribute(METAINF_RESOURCES) == null)
context.setAttribute(METAINF_RESOURCES, new HashSet<Resource>());
if (context.getAttribute(METAINF_FRAGMENTS) == null)
context.setAttribute(METAINF_FRAGMENTS, new HashMap<Resource, Resource>());
scanJars(context, context.getMetaData().getContainerResources(), useContainerCache);
scanJars(context, context.getMetaData().getWebInfJars(), false);
}

View File

@ -251,7 +251,7 @@ public class WebDescriptor extends Descriptor
}
}
if (_majorVersion < 2 && _minorVersion < 5)
if (_majorVersion <= 2 && _minorVersion < 5)
_metaDataComplete = MetaDataComplete.True; // does not apply before 2.5
else
{

View File

@ -175,7 +175,7 @@ public class WebInfConfiguration extends AbstractConfiguration
// Look for extra resource
@SuppressWarnings("unchecked")
Set<Resource> resources = (Set<Resource>)context.getAttribute(RESOURCE_DIRS);
if (resources!=null)
if (resources!=null && !resources.isEmpty())
{
Resource[] collection=new Resource[resources.size()+1];
int i=0;