Merge branch 'jetty-9' into jetty-9-aggregation
This commit is contained in:
commit
72bfacd5a4
|
@ -1,82 +0,0 @@
|
||||||
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
|
|
||||||
<parent>
|
|
||||||
<groupId>org.eclipse.jetty</groupId>
|
|
||||||
<artifactId>jetty-project</artifactId>
|
|
||||||
<version>9.0.0-SNAPSHOT</version>
|
|
||||||
</parent>
|
|
||||||
<modelVersion>4.0.0</modelVersion>
|
|
||||||
<artifactId>jetty-ajp</artifactId>
|
|
||||||
<name>Jetty :: AJP</name>
|
|
||||||
<properties>
|
|
||||||
<bundle-symbolic-name>${project.groupId}.ajp</bundle-symbolic-name>
|
|
||||||
</properties>
|
|
||||||
<build>
|
|
||||||
<plugins>
|
|
||||||
<plugin>
|
|
||||||
<groupId>org.apache.felix</groupId>
|
|
||||||
<artifactId>maven-bundle-plugin</artifactId>
|
|
||||||
<extensions>true</extensions>
|
|
||||||
<executions>
|
|
||||||
<execution>
|
|
||||||
<goals>
|
|
||||||
<goal>manifest</goal>
|
|
||||||
</goals>
|
|
||||||
<configuration>
|
|
||||||
<instructions>
|
|
||||||
<Import-Package>javax.servlet.*;version="2.6.0",*</Import-Package>
|
|
||||||
</instructions>
|
|
||||||
</configuration>
|
|
||||||
</execution>
|
|
||||||
</executions>
|
|
||||||
</plugin>
|
|
||||||
<!--
|
|
||||||
Required for OSGI
|
|
||||||
-->
|
|
||||||
<plugin>
|
|
||||||
<groupId>org.apache.maven.plugins</groupId>
|
|
||||||
<artifactId>maven-jar-plugin</artifactId>
|
|
||||||
<configuration>
|
|
||||||
<archive>
|
|
||||||
<manifestFile>${project.build.outputDirectory}/META-INF/MANIFEST.MF</manifestFile>
|
|
||||||
</archive>
|
|
||||||
</configuration>
|
|
||||||
</plugin>
|
|
||||||
<plugin>
|
|
||||||
<groupId>org.apache.maven.plugins</groupId>
|
|
||||||
<artifactId>maven-assembly-plugin</artifactId>
|
|
||||||
<executions>
|
|
||||||
<execution>
|
|
||||||
<phase>package</phase>
|
|
||||||
<goals>
|
|
||||||
<goal>single</goal>
|
|
||||||
</goals>
|
|
||||||
<configuration>
|
|
||||||
<descriptorRefs>
|
|
||||||
<descriptorRef>config</descriptorRef>
|
|
||||||
</descriptorRefs>
|
|
||||||
</configuration>
|
|
||||||
</execution>
|
|
||||||
</executions>
|
|
||||||
</plugin>
|
|
||||||
<plugin>
|
|
||||||
<groupId>org.codehaus.mojo</groupId>
|
|
||||||
<artifactId>findbugs-maven-plugin</artifactId>
|
|
||||||
<configuration>
|
|
||||||
<onlyAnalyze>org.eclipse.jetty.ajp.*</onlyAnalyze>
|
|
||||||
</configuration>
|
|
||||||
</plugin>
|
|
||||||
</plugins>
|
|
||||||
</build>
|
|
||||||
<dependencies>
|
|
||||||
<dependency>
|
|
||||||
<groupId>org.eclipse.jetty</groupId>
|
|
||||||
<artifactId>jetty-server</artifactId>
|
|
||||||
<version>${project.version}</version>
|
|
||||||
</dependency>
|
|
||||||
<dependency>
|
|
||||||
<groupId>junit</groupId>
|
|
||||||
<artifactId>junit</artifactId>
|
|
||||||
<scope>test</scope>
|
|
||||||
</dependency>
|
|
||||||
</dependencies>
|
|
||||||
</project>
|
|
|
@ -1,18 +0,0 @@
|
||||||
<?xml version="1.0"?>
|
|
||||||
<!DOCTYPE Configure PUBLIC "-//Jetty//Configure//EN" "http://www.eclipse.org/jetty/configure.dtd">
|
|
||||||
|
|
||||||
<Configure id="Server" class="org.eclipse.jetty.server.Server">
|
|
||||||
|
|
||||||
<!-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -->
|
|
||||||
<!-- Add a AJP listener on port 8009 -->
|
|
||||||
<!-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -->
|
|
||||||
<Call name="addConnector">
|
|
||||||
<Arg>
|
|
||||||
<New class="org.eclipse.jetty.ajp.Ajp13SocketConnector">
|
|
||||||
<Set name="port">8009</Set>
|
|
||||||
</New>
|
|
||||||
</Arg>
|
|
||||||
</Call>
|
|
||||||
|
|
||||||
</Configure>
|
|
||||||
|
|
|
@ -1,250 +0,0 @@
|
||||||
//
|
|
||||||
// ========================================================================
|
|
||||||
// Copyright (c) 1995-2012 Mort Bay Consulting Pty. Ltd.
|
|
||||||
// ------------------------------------------------------------------------
|
|
||||||
// All rights reserved. This program and the accompanying materials
|
|
||||||
// are made available under the terms of the Eclipse Public License v1.0
|
|
||||||
// and Apache License v2.0 which accompanies this distribution.
|
|
||||||
//
|
|
||||||
// The Eclipse Public License is available at
|
|
||||||
// http://www.eclipse.org/legal/epl-v10.html
|
|
||||||
//
|
|
||||||
// The Apache License v2.0 is available at
|
|
||||||
// http://www.opensource.org/licenses/apache2.0.php
|
|
||||||
//
|
|
||||||
// You may elect to redistribute this code under either of these licenses.
|
|
||||||
// ========================================================================
|
|
||||||
//
|
|
||||||
|
|
||||||
package org.eclipse.jetty.ajp;
|
|
||||||
|
|
||||||
import java.io.ByteArrayInputStream;
|
|
||||||
import java.io.IOException;
|
|
||||||
import java.security.cert.CertificateFactory;
|
|
||||||
import java.security.cert.X509Certificate;
|
|
||||||
import java.util.Collection;
|
|
||||||
|
|
||||||
import javax.servlet.ServletInputStream;
|
|
||||||
import javax.servlet.http.HttpServletResponse;
|
|
||||||
|
|
||||||
import org.eclipse.jetty.http.HttpException;
|
|
||||||
import org.eclipse.jetty.io.Buffer;
|
|
||||||
import org.eclipse.jetty.io.EndPoint;
|
|
||||||
import org.eclipse.jetty.server.BlockingHttpConnection;
|
|
||||||
import org.eclipse.jetty.server.Connector;
|
|
||||||
import org.eclipse.jetty.server.Request;
|
|
||||||
import org.eclipse.jetty.server.Server;
|
|
||||||
import org.eclipse.jetty.util.log.Log;
|
|
||||||
import org.eclipse.jetty.util.log.Logger;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Connection implementation of the Ajp13 protocol. <p/> XXX Refactor to remove
|
|
||||||
* duplication of HttpConnection
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
public class Ajp13Connection extends BlockingHttpConnection
|
|
||||||
{
|
|
||||||
private static final Logger LOG = Log.getLogger(Ajp13Connection.class);
|
|
||||||
|
|
||||||
public Ajp13Connection(Connector connector, EndPoint endPoint, Server server)
|
|
||||||
{
|
|
||||||
super(connector, endPoint, server,
|
|
||||||
new Ajp13Parser(connector.getRequestBuffers(), endPoint),
|
|
||||||
new Ajp13Generator(connector.getResponseBuffers(), endPoint),
|
|
||||||
new Ajp13Request()
|
|
||||||
);
|
|
||||||
|
|
||||||
((Ajp13Parser)_parser).setEventHandler(new RequestHandler());
|
|
||||||
((Ajp13Parser)_parser).setGenerator((Ajp13Generator)_generator);
|
|
||||||
((Ajp13Request)_request).setConnection(this);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean isConfidential(Request request)
|
|
||||||
{
|
|
||||||
return ((Ajp13Request) request).isSslSecure();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean isIntegral(Request request)
|
|
||||||
{
|
|
||||||
return ((Ajp13Request) request).isSslSecure();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public ServletInputStream getInputStream()
|
|
||||||
{
|
|
||||||
if (_in == null)
|
|
||||||
_in = new Ajp13Parser.Input((Ajp13Parser) _parser, _connector.getMaxIdleTime());
|
|
||||||
return _in;
|
|
||||||
}
|
|
||||||
|
|
||||||
private class RequestHandler implements Ajp13Parser.EventHandler
|
|
||||||
{
|
|
||||||
public void startForwardRequest() throws IOException
|
|
||||||
{
|
|
||||||
_uri.clear();
|
|
||||||
|
|
||||||
((Ajp13Request) _request).setSslSecure(false);
|
|
||||||
_request.setTimeStamp(System.currentTimeMillis());
|
|
||||||
_request.setUri(_uri);
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
public void parsedAuthorizationType(Buffer authType) throws IOException
|
|
||||||
{
|
|
||||||
//TODO JASPI this doesn't appear to make sense yet... how does ajp auth fit into jetty auth?
|
|
||||||
// _request.setAuthType(authType.toString());
|
|
||||||
}
|
|
||||||
|
|
||||||
public void parsedRemoteUser(Buffer remoteUser) throws IOException
|
|
||||||
{
|
|
||||||
((Ajp13Request)_request).setRemoteUser(remoteUser.toString());
|
|
||||||
}
|
|
||||||
|
|
||||||
public void parsedServletPath(Buffer servletPath) throws IOException
|
|
||||||
{
|
|
||||||
_request.setServletPath(servletPath.toString());
|
|
||||||
}
|
|
||||||
|
|
||||||
public void parsedContextPath(Buffer context) throws IOException
|
|
||||||
{
|
|
||||||
_request.setContextPath(context.toString());
|
|
||||||
}
|
|
||||||
|
|
||||||
public void parsedSslCert(Buffer sslCert) throws IOException
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
CertificateFactory cf = CertificateFactory.getInstance("X.509");
|
|
||||||
ByteArrayInputStream bis = new ByteArrayInputStream(sslCert.toString().getBytes());
|
|
||||||
|
|
||||||
Collection<? extends java.security.cert.Certificate> certCollection = cf.generateCertificates(bis);
|
|
||||||
X509Certificate[] certificates = new X509Certificate[certCollection.size()];
|
|
||||||
|
|
||||||
int i=0;
|
|
||||||
for (Object aCertCollection : certCollection)
|
|
||||||
{
|
|
||||||
certificates[i++] = (X509Certificate) aCertCollection;
|
|
||||||
}
|
|
||||||
|
|
||||||
_request.setAttribute("javax.servlet.request.X509Certificate", certificates);
|
|
||||||
}
|
|
||||||
catch (Exception e)
|
|
||||||
{
|
|
||||||
LOG.warn(e.toString());
|
|
||||||
LOG.ignore(e);
|
|
||||||
if (sslCert!=null)
|
|
||||||
_request.setAttribute("javax.servlet.request.X509Certificate", sslCert.toString());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void parsedSslCipher(Buffer sslCipher) throws IOException
|
|
||||||
{
|
|
||||||
_request.setAttribute("javax.servlet.request.cipher_suite", sslCipher.toString());
|
|
||||||
}
|
|
||||||
|
|
||||||
public void parsedSslSession(Buffer sslSession) throws IOException
|
|
||||||
{
|
|
||||||
_request.setAttribute("javax.servlet.request.ssl_session", sslSession.toString());
|
|
||||||
}
|
|
||||||
|
|
||||||
public void parsedSslKeySize(int keySize) throws IOException
|
|
||||||
{
|
|
||||||
_request.setAttribute("javax.servlet.request.key_size", new Integer(keySize));
|
|
||||||
}
|
|
||||||
|
|
||||||
public void parsedMethod(Buffer method) throws IOException
|
|
||||||
{
|
|
||||||
if (method == null)
|
|
||||||
throw new HttpException(HttpServletResponse.SC_BAD_REQUEST);
|
|
||||||
_request.setMethod(method.toString());
|
|
||||||
}
|
|
||||||
|
|
||||||
public void parsedUri(Buffer uri) throws IOException
|
|
||||||
{
|
|
||||||
_uri.parse(uri.toString());
|
|
||||||
}
|
|
||||||
|
|
||||||
public void parsedProtocol(Buffer protocol) throws IOException
|
|
||||||
{
|
|
||||||
if (protocol != null && protocol.length()>0)
|
|
||||||
{
|
|
||||||
_request.setProtocol(protocol.toString());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void parsedRemoteAddr(Buffer addr) throws IOException
|
|
||||||
{
|
|
||||||
if (addr != null && addr.length()>0)
|
|
||||||
{
|
|
||||||
_request.setRemoteAddr(addr.toString());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void parsedRemoteHost(Buffer name) throws IOException
|
|
||||||
{
|
|
||||||
if (name != null && name.length()>0)
|
|
||||||
{
|
|
||||||
_request.setRemoteHost(name.toString());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void parsedServerName(Buffer name) throws IOException
|
|
||||||
{
|
|
||||||
if (name != null && name.length()>0)
|
|
||||||
{
|
|
||||||
_request.setServerName(name.toString());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void parsedServerPort(int port) throws IOException
|
|
||||||
{
|
|
||||||
_request.setServerPort(port);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void parsedSslSecure(boolean secure) throws IOException
|
|
||||||
{
|
|
||||||
((Ajp13Request) _request).setSslSecure(secure);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void parsedQueryString(Buffer value) throws IOException
|
|
||||||
{
|
|
||||||
String u = _uri + "?" + value;
|
|
||||||
_uri.parse(u);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void parsedHeader(Buffer name, Buffer value) throws IOException
|
|
||||||
{
|
|
||||||
_requestFields.add(name, value);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void parsedRequestAttribute(String key, Buffer value) throws IOException
|
|
||||||
{
|
|
||||||
if (value==null)
|
|
||||||
_request.removeAttribute(key);
|
|
||||||
else
|
|
||||||
_request.setAttribute(key,value.toString());
|
|
||||||
}
|
|
||||||
|
|
||||||
public void parsedRequestAttribute(String key, int value) throws IOException
|
|
||||||
{
|
|
||||||
_request.setAttribute(key, Integer.toString(value));
|
|
||||||
}
|
|
||||||
|
|
||||||
public void headerComplete() throws IOException
|
|
||||||
{
|
|
||||||
handleRequest();
|
|
||||||
}
|
|
||||||
|
|
||||||
public void messageComplete(long contextLength) throws IOException
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
public void content(Buffer ref) throws IOException
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
|
@ -1,831 +0,0 @@
|
||||||
//
|
|
||||||
// ========================================================================
|
|
||||||
// Copyright (c) 1995-2012 Mort Bay Consulting Pty. Ltd.
|
|
||||||
// ------------------------------------------------------------------------
|
|
||||||
// All rights reserved. This program and the accompanying materials
|
|
||||||
// are made available under the terms of the Eclipse Public License v1.0
|
|
||||||
// and Apache License v2.0 which accompanies this distribution.
|
|
||||||
//
|
|
||||||
// The Eclipse Public License is available at
|
|
||||||
// http://www.eclipse.org/legal/epl-v10.html
|
|
||||||
//
|
|
||||||
// The Apache License v2.0 is available at
|
|
||||||
// http://www.opensource.org/licenses/apache2.0.php
|
|
||||||
//
|
|
||||||
// You may elect to redistribute this code under either of these licenses.
|
|
||||||
// ========================================================================
|
|
||||||
//
|
|
||||||
|
|
||||||
package org.eclipse.jetty.ajp;
|
|
||||||
|
|
||||||
import java.io.IOException;
|
|
||||||
import java.io.UnsupportedEncodingException;
|
|
||||||
import java.util.HashMap;
|
|
||||||
|
|
||||||
import org.eclipse.jetty.http.AbstractGenerator;
|
|
||||||
import org.eclipse.jetty.http.HttpFields;
|
|
||||||
import org.eclipse.jetty.http.HttpGenerator;
|
|
||||||
import org.eclipse.jetty.http.HttpTokens;
|
|
||||||
import org.eclipse.jetty.http.HttpVersions;
|
|
||||||
import org.eclipse.jetty.io.Buffer;
|
|
||||||
import org.eclipse.jetty.io.Buffers;
|
|
||||||
import org.eclipse.jetty.io.ByteArrayBuffer;
|
|
||||||
import org.eclipse.jetty.io.EndPoint;
|
|
||||||
import org.eclipse.jetty.io.EofException;
|
|
||||||
import org.eclipse.jetty.util.StringUtil;
|
|
||||||
import org.eclipse.jetty.util.log.Log;
|
|
||||||
import org.eclipse.jetty.util.log.Logger;
|
|
||||||
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
public class Ajp13Generator extends AbstractGenerator
|
|
||||||
{
|
|
||||||
private static final Logger LOG = Log.getLogger(Ajp13Generator.class);
|
|
||||||
|
|
||||||
private static HashMap __headerHash = new HashMap();
|
|
||||||
|
|
||||||
static
|
|
||||||
{
|
|
||||||
byte[] xA001 =
|
|
||||||
{ (byte)0xA0, (byte)0x01 };
|
|
||||||
byte[] xA002 =
|
|
||||||
{ (byte)0xA0, (byte)0x02 };
|
|
||||||
byte[] xA003 =
|
|
||||||
{ (byte)0xA0, (byte)0x03 };
|
|
||||||
byte[] xA004 =
|
|
||||||
{ (byte)0xA0, (byte)0x04 };
|
|
||||||
byte[] xA005 =
|
|
||||||
{ (byte)0xA0, (byte)0x05 };
|
|
||||||
byte[] xA006 =
|
|
||||||
{ (byte)0xA0, (byte)0x06 };
|
|
||||||
byte[] xA007 =
|
|
||||||
{ (byte)0xA0, (byte)0x07 };
|
|
||||||
byte[] xA008 =
|
|
||||||
{ (byte)0xA0, (byte)0x08 };
|
|
||||||
byte[] xA009 =
|
|
||||||
{ (byte)0xA0, (byte)0x09 };
|
|
||||||
byte[] xA00A =
|
|
||||||
{ (byte)0xA0, (byte)0x0A };
|
|
||||||
byte[] xA00B =
|
|
||||||
{ (byte)0xA0, (byte)0x0B };
|
|
||||||
__headerHash.put("Content-Type",xA001);
|
|
||||||
__headerHash.put("Content-Language",xA002);
|
|
||||||
__headerHash.put("Content-Length",xA003);
|
|
||||||
__headerHash.put("Date",xA004);
|
|
||||||
__headerHash.put("Last-Modified",xA005);
|
|
||||||
__headerHash.put("Location",xA006);
|
|
||||||
__headerHash.put("Set-Cookie",xA007);
|
|
||||||
__headerHash.put("Set-Cookie2",xA008);
|
|
||||||
__headerHash.put("Servlet-Engine",xA009);
|
|
||||||
__headerHash.put("Status",xA00A);
|
|
||||||
__headerHash.put("WWW-Authenticate",xA00B);
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
// A, B ajp response header
|
|
||||||
// 0, 1 ajp int 1 packet length
|
|
||||||
// 9 CPONG response Code
|
|
||||||
private static final byte[] AJP13_CPONG_RESPONSE =
|
|
||||||
{ 'A', 'B', 0, 1, 9 };
|
|
||||||
|
|
||||||
private static final byte[] AJP13_END_RESPONSE =
|
|
||||||
{ 'A', 'B', 0, 2, 5, 1 };
|
|
||||||
|
|
||||||
// AB ajp respose
|
|
||||||
// 0, 3 int = 3 packets in length
|
|
||||||
// 6, send signal to get more data
|
|
||||||
// 31, -7 byte values for int 8185 = (8 * 1024) - 7 MAX_DATA
|
|
||||||
private static final byte[] AJP13_MORE_CONTENT =
|
|
||||||
{ 'A', 'B', 0, 3, 6, 31, -7 };
|
|
||||||
|
|
||||||
private static String SERVER = "Server: Jetty(7.x.x)";
|
|
||||||
|
|
||||||
public static void setServerVersion(String version)
|
|
||||||
{
|
|
||||||
SERVER = "Jetty(" + version + ")";
|
|
||||||
}
|
|
||||||
|
|
||||||
/* ------------------------------------------------------------ */
|
|
||||||
private boolean _expectMore = false;
|
|
||||||
|
|
||||||
private boolean _needMore = false;
|
|
||||||
|
|
||||||
private boolean _needEOC = false;
|
|
||||||
|
|
||||||
private boolean _bufferPrepared = false;
|
|
||||||
|
|
||||||
/* ------------------------------------------------------------ */
|
|
||||||
public Ajp13Generator(Buffers buffers, EndPoint io)
|
|
||||||
{
|
|
||||||
super(buffers,io);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* ------------------------------------------------------------ */
|
|
||||||
@Override
|
|
||||||
public boolean isRequest()
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* ------------------------------------------------------------ */
|
|
||||||
@Override
|
|
||||||
public boolean isResponse()
|
|
||||||
{
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* ------------------------------------------------------------ */
|
|
||||||
@Override
|
|
||||||
public void reset()
|
|
||||||
{
|
|
||||||
super.reset();
|
|
||||||
|
|
||||||
_needEOC = false;
|
|
||||||
_needMore = false;
|
|
||||||
_expectMore = false;
|
|
||||||
_bufferPrepared = false;
|
|
||||||
_last = false;
|
|
||||||
|
|
||||||
_state = STATE_HEADER;
|
|
||||||
|
|
||||||
_status = 0;
|
|
||||||
_version = HttpVersions.HTTP_1_1_ORDINAL;
|
|
||||||
_reason = null;
|
|
||||||
_method = null;
|
|
||||||
_uri = null;
|
|
||||||
|
|
||||||
_contentWritten = 0;
|
|
||||||
_contentLength = HttpTokens.UNKNOWN_CONTENT;
|
|
||||||
_last = false;
|
|
||||||
_head = false;
|
|
||||||
_noContent = false;
|
|
||||||
_persistent = true;
|
|
||||||
|
|
||||||
_header = null; // Buffer for HTTP header (and maybe small _content)
|
|
||||||
_buffer = null; // Buffer for copy of passed _content
|
|
||||||
_content = null; // Buffer passed to addContent
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
/* ------------------------------------------------------------ */
|
|
||||||
@Override
|
|
||||||
public int getContentBufferSize()
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
initContent();
|
|
||||||
}
|
|
||||||
catch (IOException e)
|
|
||||||
{
|
|
||||||
throw new RuntimeException(e);
|
|
||||||
}
|
|
||||||
return super.getContentBufferSize() - 7;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* ------------------------------------------------------------ */
|
|
||||||
@Override
|
|
||||||
public void increaseContentBufferSize(int contentBufferSize)
|
|
||||||
{
|
|
||||||
// Not supported with AJP
|
|
||||||
}
|
|
||||||
|
|
||||||
/* ------------------------------------------------------------ */
|
|
||||||
/**
|
|
||||||
* Add content.
|
|
||||||
*
|
|
||||||
* @param content
|
|
||||||
* @param last
|
|
||||||
* @throws IllegalArgumentException
|
|
||||||
* if <code>content</code> is {@link Buffer#isImmutable immutable}.
|
|
||||||
* @throws IllegalStateException
|
|
||||||
* If the request is not expecting any more content, or if the buffers are full and cannot be flushed.
|
|
||||||
* @throws IOException
|
|
||||||
* if there is a problem flushing the buffers.
|
|
||||||
*/
|
|
||||||
public void addContent(Buffer content, boolean last) throws IOException
|
|
||||||
{
|
|
||||||
if (_noContent)
|
|
||||||
{
|
|
||||||
content.clear();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (content.isImmutable())
|
|
||||||
throw new IllegalArgumentException("immutable");
|
|
||||||
|
|
||||||
if (_last || _state == STATE_END)
|
|
||||||
{
|
|
||||||
LOG.debug("Ignoring extra content {}",content);
|
|
||||||
content.clear();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
_last = last;
|
|
||||||
|
|
||||||
if (!_endp.isOpen())
|
|
||||||
{
|
|
||||||
_state = STATE_END;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Handle any unfinished business?
|
|
||||||
if (_content != null && _content.length() > 0)
|
|
||||||
{
|
|
||||||
|
|
||||||
flushBuffer();
|
|
||||||
if (_content != null && _content.length() > 0)
|
|
||||||
throw new IllegalStateException("FULL");
|
|
||||||
}
|
|
||||||
|
|
||||||
_content = content;
|
|
||||||
|
|
||||||
_contentWritten += content.length();
|
|
||||||
|
|
||||||
// Handle the _content
|
|
||||||
if (_head)
|
|
||||||
{
|
|
||||||
|
|
||||||
content.clear();
|
|
||||||
_content = null;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// Yes - so we better check we have a buffer
|
|
||||||
initContent();
|
|
||||||
// Copy _content to buffer;
|
|
||||||
int len = 0;
|
|
||||||
len = _buffer.put(_content);
|
|
||||||
|
|
||||||
// make sure there is space for a trailing null
|
|
||||||
if (len > 0 && _buffer.space() == 0)
|
|
||||||
{
|
|
||||||
len--;
|
|
||||||
_buffer.setPutIndex(_buffer.putIndex() - 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
_content.skip(len);
|
|
||||||
|
|
||||||
if (_content.length() == 0)
|
|
||||||
_content = null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* ------------------------------------------------------------ */
|
|
||||||
/**
|
|
||||||
* Add content.
|
|
||||||
*
|
|
||||||
* @param b
|
|
||||||
* byte
|
|
||||||
* @return true if the buffers are full
|
|
||||||
* @throws IOException
|
|
||||||
*/
|
|
||||||
public boolean addContent(byte b) throws IOException
|
|
||||||
{
|
|
||||||
|
|
||||||
if (_noContent)
|
|
||||||
return false;
|
|
||||||
|
|
||||||
if (_last || _state == STATE_END)
|
|
||||||
throw new IllegalStateException("Closed");
|
|
||||||
|
|
||||||
if (!_endp.isOpen())
|
|
||||||
{
|
|
||||||
_state = STATE_END;
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Handle any unfinished business?
|
|
||||||
if (_content != null && _content.length() > 0)
|
|
||||||
{
|
|
||||||
flushBuffer();
|
|
||||||
if (_content != null && _content.length() > 0)
|
|
||||||
throw new IllegalStateException("FULL");
|
|
||||||
}
|
|
||||||
|
|
||||||
_contentWritten++;
|
|
||||||
|
|
||||||
// Handle the _content
|
|
||||||
if (_head)
|
|
||||||
return false;
|
|
||||||
|
|
||||||
// we better check we have a buffer
|
|
||||||
initContent();
|
|
||||||
|
|
||||||
// Copy _content to buffer;
|
|
||||||
|
|
||||||
_buffer.put(b);
|
|
||||||
|
|
||||||
return _buffer.space() <= 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* ------------------------------------------------------------ */
|
|
||||||
/**
|
|
||||||
* Prepare buffer for unchecked writes. Prepare the generator buffer to receive unchecked writes
|
|
||||||
*
|
|
||||||
* @return the available space in the buffer.
|
|
||||||
* @throws IOException
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
public int prepareUncheckedAddContent() throws IOException
|
|
||||||
{
|
|
||||||
if (_noContent)
|
|
||||||
return -1;
|
|
||||||
|
|
||||||
if (_last || _state == STATE_END)
|
|
||||||
throw new IllegalStateException("Closed");
|
|
||||||
|
|
||||||
if (!_endp.isOpen())
|
|
||||||
{
|
|
||||||
_state = STATE_END;
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Handle any unfinished business?
|
|
||||||
Buffer content = _content;
|
|
||||||
if (content != null && content.length() > 0)
|
|
||||||
{
|
|
||||||
flushBuffer();
|
|
||||||
if (content != null && content.length() > 0)
|
|
||||||
throw new IllegalStateException("FULL");
|
|
||||||
}
|
|
||||||
|
|
||||||
// we better check we have a buffer
|
|
||||||
initContent();
|
|
||||||
|
|
||||||
_contentWritten -= _buffer.length();
|
|
||||||
|
|
||||||
// Handle the _content
|
|
||||||
if (_head)
|
|
||||||
return Integer.MAX_VALUE;
|
|
||||||
|
|
||||||
return _buffer.space() - 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* ------------------------------------------------------------ */
|
|
||||||
@Override
|
|
||||||
public void completeHeader(HttpFields fields, boolean allContentAdded) throws IOException
|
|
||||||
{
|
|
||||||
if (_state != STATE_HEADER)
|
|
||||||
return;
|
|
||||||
|
|
||||||
if (_last && !allContentAdded)
|
|
||||||
throw new IllegalStateException("last?");
|
|
||||||
_last = _last | allContentAdded;
|
|
||||||
|
|
||||||
boolean has_server = false;
|
|
||||||
if (_persistent == null)
|
|
||||||
_persistent = (_version > HttpVersions.HTTP_1_0_ORDINAL);
|
|
||||||
|
|
||||||
// get a header buffer
|
|
||||||
if (_header == null)
|
|
||||||
_header = _buffers.getHeader();
|
|
||||||
|
|
||||||
Buffer tmpbuf = _buffer;
|
|
||||||
_buffer = _header;
|
|
||||||
|
|
||||||
try
|
|
||||||
{
|
|
||||||
// start the header
|
|
||||||
_buffer.put((byte)'A');
|
|
||||||
_buffer.put((byte)'B');
|
|
||||||
addInt(0);
|
|
||||||
_buffer.put((byte)0x4);
|
|
||||||
addInt(_status);
|
|
||||||
if (_reason == null)
|
|
||||||
_reason = HttpGenerator.getReasonBuffer(_status);
|
|
||||||
if (_reason == null)
|
|
||||||
_reason = new ByteArrayBuffer(Integer.toString(_status));
|
|
||||||
addBuffer(_reason);
|
|
||||||
|
|
||||||
if (_status == 100 || _status == 204 || _status == 304)
|
|
||||||
{
|
|
||||||
_noContent = true;
|
|
||||||
_content = null;
|
|
||||||
}
|
|
||||||
|
|
||||||
// allocate 2 bytes for number of headers
|
|
||||||
int field_index = _buffer.putIndex();
|
|
||||||
addInt(0);
|
|
||||||
|
|
||||||
int num_fields = 0;
|
|
||||||
|
|
||||||
if (fields != null)
|
|
||||||
{
|
|
||||||
// Add headers
|
|
||||||
int s = fields.size();
|
|
||||||
for (int f = 0; f < s; f++)
|
|
||||||
{
|
|
||||||
HttpFields.Field field = fields.getField(f);
|
|
||||||
if (field == null)
|
|
||||||
continue;
|
|
||||||
num_fields++;
|
|
||||||
|
|
||||||
byte[] codes = (byte[])__headerHash.get(field.getName());
|
|
||||||
if (codes != null)
|
|
||||||
{
|
|
||||||
_buffer.put(codes);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
addString(field.getName());
|
|
||||||
}
|
|
||||||
addString(field.getValue());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!has_server && _status > 100 && getSendServerVersion())
|
|
||||||
{
|
|
||||||
num_fields++;
|
|
||||||
addString("Server");
|
|
||||||
addString(SERVER);
|
|
||||||
}
|
|
||||||
|
|
||||||
// TODO Add content length if last content known.
|
|
||||||
|
|
||||||
// insert the number of headers
|
|
||||||
int tmp = _buffer.putIndex();
|
|
||||||
_buffer.setPutIndex(field_index);
|
|
||||||
addInt(num_fields);
|
|
||||||
_buffer.setPutIndex(tmp);
|
|
||||||
|
|
||||||
// get the payload size ( - 4 bytes for the ajp header)
|
|
||||||
// excluding the
|
|
||||||
// ajp header
|
|
||||||
int payloadSize = _buffer.length() - 4;
|
|
||||||
// insert the total packet size on 2nd and 3rd byte that
|
|
||||||
// was previously
|
|
||||||
// allocated
|
|
||||||
addInt(2,payloadSize);
|
|
||||||
}
|
|
||||||
finally
|
|
||||||
{
|
|
||||||
_buffer = tmpbuf;
|
|
||||||
}
|
|
||||||
|
|
||||||
_state = STATE_CONTENT;
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
/* ------------------------------------------------------------ */
|
|
||||||
/**
|
|
||||||
* Complete the message.
|
|
||||||
*
|
|
||||||
* @throws IOException
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
public void complete() throws IOException
|
|
||||||
{
|
|
||||||
if (_state == STATE_END)
|
|
||||||
return;
|
|
||||||
|
|
||||||
super.complete();
|
|
||||||
|
|
||||||
if (_state < STATE_FLUSHING)
|
|
||||||
{
|
|
||||||
_state = STATE_FLUSHING;
|
|
||||||
_needEOC = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
flushBuffer();
|
|
||||||
}
|
|
||||||
|
|
||||||
/* ------------------------------------------------------------ */
|
|
||||||
@Override
|
|
||||||
public int flushBuffer() throws IOException
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
if (_state == STATE_HEADER && !_expectMore)
|
|
||||||
throw new IllegalStateException("State==HEADER");
|
|
||||||
prepareBuffers();
|
|
||||||
|
|
||||||
if (_endp == null)
|
|
||||||
{
|
|
||||||
// TODO - probably still needed!
|
|
||||||
// if (_rneedMore && _buffe != null)
|
|
||||||
// {
|
|
||||||
// if(!_hasSentEOC)
|
|
||||||
// _buffer.put(AJP13_MORE_CONTENT);
|
|
||||||
// }
|
|
||||||
if (!_expectMore && _needEOC && _buffer != null)
|
|
||||||
{
|
|
||||||
_buffer.put(AJP13_END_RESPONSE);
|
|
||||||
}
|
|
||||||
_needEOC = false;
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Keep flushing while there is something to flush
|
|
||||||
// (except break below)
|
|
||||||
int total = 0;
|
|
||||||
long last_len = -1;
|
|
||||||
Flushing: while (true)
|
|
||||||
{
|
|
||||||
int len = -1;
|
|
||||||
int to_flush = ((_header != null && _header.length() > 0)?4:0) | ((_buffer != null && _buffer.length() > 0)?2:0);
|
|
||||||
|
|
||||||
switch (to_flush)
|
|
||||||
{
|
|
||||||
case 7:
|
|
||||||
throw new IllegalStateException(); // should
|
|
||||||
// never
|
|
||||||
// happen!
|
|
||||||
case 6:
|
|
||||||
len = _endp.flush(_header,_buffer,null);
|
|
||||||
|
|
||||||
break;
|
|
||||||
case 5:
|
|
||||||
throw new IllegalStateException(); // should
|
|
||||||
// never
|
|
||||||
// happen!
|
|
||||||
case 4:
|
|
||||||
len = _endp.flush(_header);
|
|
||||||
break;
|
|
||||||
case 3:
|
|
||||||
throw new IllegalStateException(); // should
|
|
||||||
// never
|
|
||||||
// happen!
|
|
||||||
case 2:
|
|
||||||
len = _endp.flush(_buffer);
|
|
||||||
|
|
||||||
break;
|
|
||||||
case 1:
|
|
||||||
throw new IllegalStateException(); // should
|
|
||||||
// never
|
|
||||||
// happen!
|
|
||||||
case 0:
|
|
||||||
{
|
|
||||||
// Nothing more we can write now.
|
|
||||||
if (_header != null)
|
|
||||||
_header.clear();
|
|
||||||
|
|
||||||
_bufferPrepared = false;
|
|
||||||
|
|
||||||
if (_buffer != null)
|
|
||||||
{
|
|
||||||
_buffer.clear();
|
|
||||||
|
|
||||||
// reserve some space for the
|
|
||||||
// header
|
|
||||||
_buffer.setPutIndex(7);
|
|
||||||
_buffer.setGetIndex(7);
|
|
||||||
|
|
||||||
// Special case handling for
|
|
||||||
// small left over buffer from
|
|
||||||
// an addContent that caused a
|
|
||||||
// buffer flush.
|
|
||||||
if (_content != null && _content.length() < _buffer.space() && _state != STATE_FLUSHING)
|
|
||||||
{
|
|
||||||
|
|
||||||
_buffer.put(_content);
|
|
||||||
_content.clear();
|
|
||||||
_content = null;
|
|
||||||
break Flushing;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
// Are we completely finished for now?
|
|
||||||
if (!_expectMore && !_needEOC && (_content == null || _content.length() == 0))
|
|
||||||
{
|
|
||||||
if (_state == STATE_FLUSHING)
|
|
||||||
_state = STATE_END;
|
|
||||||
|
|
||||||
// if (_state == STATE_END)
|
|
||||||
// {
|
|
||||||
// _endp.close();
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
|
|
||||||
break Flushing;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Try to prepare more to write.
|
|
||||||
prepareBuffers();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// If we failed to flush anything twice in a row
|
|
||||||
// break
|
|
||||||
if (len <= 0)
|
|
||||||
{
|
|
||||||
if (last_len <= 0)
|
|
||||||
break Flushing;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
last_len = len;
|
|
||||||
total += len;
|
|
||||||
}
|
|
||||||
|
|
||||||
return total;
|
|
||||||
}
|
|
||||||
catch (IOException e)
|
|
||||||
{
|
|
||||||
LOG.ignore(e);
|
|
||||||
throw (e instanceof EofException)?e:new EofException(e);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
/* ------------------------------------------------------------ */
|
|
||||||
private void prepareBuffers()
|
|
||||||
{
|
|
||||||
if (!_bufferPrepared)
|
|
||||||
{
|
|
||||||
|
|
||||||
// Refill buffer if possible
|
|
||||||
if (_content != null && _content.length() > 0 && _buffer != null && _buffer.space() > 0)
|
|
||||||
{
|
|
||||||
|
|
||||||
int len = _buffer.put(_content);
|
|
||||||
|
|
||||||
// Make sure there is space for a trailing null
|
|
||||||
if (len > 0 && _buffer.space() == 0)
|
|
||||||
{
|
|
||||||
len--;
|
|
||||||
_buffer.setPutIndex(_buffer.putIndex() - 1);
|
|
||||||
}
|
|
||||||
_content.skip(len);
|
|
||||||
|
|
||||||
if (_content.length() == 0)
|
|
||||||
_content = null;
|
|
||||||
|
|
||||||
if (_buffer.length() == 0)
|
|
||||||
{
|
|
||||||
_content = null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// add header if needed
|
|
||||||
if (_buffer != null)
|
|
||||||
{
|
|
||||||
|
|
||||||
int payloadSize = _buffer.length();
|
|
||||||
|
|
||||||
// 4 bytes for the ajp header
|
|
||||||
// 1 byte for response type
|
|
||||||
// 2 bytes for the response size
|
|
||||||
// 1 byte because we count from zero??
|
|
||||||
|
|
||||||
if (payloadSize > 0)
|
|
||||||
{
|
|
||||||
_bufferPrepared = true;
|
|
||||||
|
|
||||||
_buffer.put((byte)0);
|
|
||||||
int put = _buffer.putIndex();
|
|
||||||
_buffer.setGetIndex(0);
|
|
||||||
_buffer.setPutIndex(0);
|
|
||||||
_buffer.put((byte)'A');
|
|
||||||
_buffer.put((byte)'B');
|
|
||||||
addInt(payloadSize + 4);
|
|
||||||
_buffer.put((byte)3);
|
|
||||||
addInt(payloadSize);
|
|
||||||
_buffer.setPutIndex(put);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (_needMore)
|
|
||||||
{
|
|
||||||
|
|
||||||
if (_header == null)
|
|
||||||
{
|
|
||||||
_header = _buffers.getHeader();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (_buffer == null && _header != null && _header.space() >= AJP13_MORE_CONTENT.length)
|
|
||||||
{
|
|
||||||
_header.put(AJP13_MORE_CONTENT);
|
|
||||||
_needMore = false;
|
|
||||||
}
|
|
||||||
else if (_buffer != null && _buffer.space() >= AJP13_MORE_CONTENT.length)
|
|
||||||
{
|
|
||||||
// send closing packet if all contents
|
|
||||||
// are added
|
|
||||||
_buffer.put(AJP13_MORE_CONTENT);
|
|
||||||
_needMore = false;
|
|
||||||
_bufferPrepared = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!_expectMore && _needEOC)
|
|
||||||
{
|
|
||||||
if (_buffer == null && _header.space() >= AJP13_END_RESPONSE.length)
|
|
||||||
{
|
|
||||||
|
|
||||||
_header.put(AJP13_END_RESPONSE);
|
|
||||||
_needEOC = false;
|
|
||||||
}
|
|
||||||
else if (_buffer != null && _buffer.space() >= AJP13_END_RESPONSE.length)
|
|
||||||
{
|
|
||||||
// send closing packet if all contents
|
|
||||||
// are added
|
|
||||||
|
|
||||||
_buffer.put(AJP13_END_RESPONSE);
|
|
||||||
_needEOC = false;
|
|
||||||
_bufferPrepared = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* ------------------------------------------------------------ */
|
|
||||||
@Override
|
|
||||||
public boolean isComplete()
|
|
||||||
{
|
|
||||||
return !_expectMore && _state == STATE_END;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* ------------------------------------------------------------ */
|
|
||||||
private void initContent() throws IOException
|
|
||||||
{
|
|
||||||
if (_buffer == null)
|
|
||||||
{
|
|
||||||
_buffer = _buffers.getBuffer();
|
|
||||||
_buffer.setPutIndex(7);
|
|
||||||
_buffer.setGetIndex(7);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* ------------------------------------------------------------ */
|
|
||||||
private void addInt(int i)
|
|
||||||
{
|
|
||||||
_buffer.put((byte)((i >> 8) & 0xFF));
|
|
||||||
_buffer.put((byte)(i & 0xFF));
|
|
||||||
}
|
|
||||||
|
|
||||||
/* ------------------------------------------------------------ */
|
|
||||||
private void addInt(int startIndex, int i)
|
|
||||||
{
|
|
||||||
_buffer.poke(startIndex,(byte)((i >> 8) & 0xFF));
|
|
||||||
_buffer.poke((startIndex + 1),(byte)(i & 0xFF));
|
|
||||||
}
|
|
||||||
|
|
||||||
/* ------------------------------------------------------------ */
|
|
||||||
private void addString(String str) throws UnsupportedEncodingException
|
|
||||||
{
|
|
||||||
if (str == null)
|
|
||||||
{
|
|
||||||
addInt(0xFFFF);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// TODO - need to use a writer to convert, to avoid this hacky
|
|
||||||
// conversion and temp buffer
|
|
||||||
byte[] b = str.getBytes(StringUtil.__ISO_8859_1);
|
|
||||||
|
|
||||||
addInt(b.length);
|
|
||||||
|
|
||||||
_buffer.put(b);
|
|
||||||
_buffer.put((byte)0);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* ------------------------------------------------------------ */
|
|
||||||
private void addBuffer(Buffer b)
|
|
||||||
{
|
|
||||||
if (b == null)
|
|
||||||
{
|
|
||||||
addInt(0xFFFF);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
addInt(b.length());
|
|
||||||
_buffer.put(b);
|
|
||||||
_buffer.put((byte)0);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* ------------------------------------------------------------ */
|
|
||||||
public void getBodyChunk() throws IOException
|
|
||||||
{
|
|
||||||
ByteArrayBuffer bf = new ByteArrayBuffer(AJP13_MORE_CONTENT);
|
|
||||||
_endp.flush(bf);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* ------------------------------------------------------------ */
|
|
||||||
public void gotBody()
|
|
||||||
{
|
|
||||||
_needMore = false;
|
|
||||||
_expectMore = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* ------------------------------------------------------------ */
|
|
||||||
public void sendCPong() throws IOException
|
|
||||||
{
|
|
||||||
|
|
||||||
Buffer buff = _buffers.getBuffer();
|
|
||||||
buff.put(AJP13_CPONG_RESPONSE);
|
|
||||||
|
|
||||||
// flushing cpong response
|
|
||||||
do
|
|
||||||
{
|
|
||||||
_endp.flush(buff);
|
|
||||||
}
|
|
||||||
while (buff.length() > 0);
|
|
||||||
_buffers.returnBuffer(buff);
|
|
||||||
|
|
||||||
reset();
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
|
@ -1,68 +0,0 @@
|
||||||
//
|
|
||||||
// ========================================================================
|
|
||||||
// Copyright (c) 1995-2012 Mort Bay Consulting Pty. Ltd.
|
|
||||||
// ------------------------------------------------------------------------
|
|
||||||
// All rights reserved. This program and the accompanying materials
|
|
||||||
// are made available under the terms of the Eclipse Public License v1.0
|
|
||||||
// and Apache License v2.0 which accompanies this distribution.
|
|
||||||
//
|
|
||||||
// The Eclipse Public License is available at
|
|
||||||
// http://www.eclipse.org/legal/epl-v10.html
|
|
||||||
//
|
|
||||||
// The Apache License v2.0 is available at
|
|
||||||
// http://www.opensource.org/licenses/apache2.0.php
|
|
||||||
//
|
|
||||||
// You may elect to redistribute this code under either of these licenses.
|
|
||||||
// ========================================================================
|
|
||||||
//
|
|
||||||
|
|
||||||
package org.eclipse.jetty.ajp;
|
|
||||||
|
|
||||||
import org.eclipse.jetty.io.BufferCache;
|
|
||||||
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
public class Ajp13Packet
|
|
||||||
{
|
|
||||||
|
|
||||||
public final static int MAX_PACKET_SIZE=(8*1024);
|
|
||||||
public final static int HDR_SIZE=4;
|
|
||||||
|
|
||||||
// Used in writing response...
|
|
||||||
public final static int DATA_HDR_SIZE=7;
|
|
||||||
public final static int MAX_DATA_SIZE=MAX_PACKET_SIZE-DATA_HDR_SIZE;
|
|
||||||
|
|
||||||
public final static String
|
|
||||||
// Server -> Container
|
|
||||||
FORWARD_REQUEST="FORWARD REQUEST",
|
|
||||||
SHUTDOWN="SHUTDOWN",
|
|
||||||
PING_REQUEST="PING REQUEST", // Obsolete
|
|
||||||
CPING_REQUEST="CPING REQUEST",
|
|
||||||
|
|
||||||
// Server <- Container
|
|
||||||
SEND_BODY_CHUNK="SEND BODY CHUNK", SEND_HEADERS="SEND HEADERS", END_RESPONSE="END RESPONSE",
|
|
||||||
GET_BODY_CHUNK="GET BODY CHUNK",
|
|
||||||
CPONG_REPLY="CPONG REPLY";
|
|
||||||
|
|
||||||
public final static int FORWARD_REQUEST_ORDINAL=2, SHUTDOWN_ORDINAL=7,
|
|
||||||
PING_REQUEST_ORDINAL=8, // Obsolete
|
|
||||||
CPING_REQUEST_ORDINAL=10, SEND_BODY_CHUNK_ORDINAL=3, SEND_HEADERS_ORDINAL=4, END_RESPONSE_ORDINAL=5, GET_BODY_CHUNK_ORDINAL=6,
|
|
||||||
CPONG_REPLY_ORDINAL=9;
|
|
||||||
|
|
||||||
public final static BufferCache CACHE=new BufferCache();
|
|
||||||
|
|
||||||
static
|
|
||||||
{
|
|
||||||
CACHE.add(FORWARD_REQUEST,FORWARD_REQUEST_ORDINAL);
|
|
||||||
CACHE.add(SHUTDOWN,SHUTDOWN_ORDINAL);
|
|
||||||
CACHE.add(PING_REQUEST,PING_REQUEST_ORDINAL); // Obsolete
|
|
||||||
CACHE.add(CPING_REQUEST,CPING_REQUEST_ORDINAL);
|
|
||||||
CACHE.add(SEND_BODY_CHUNK,SEND_BODY_CHUNK_ORDINAL);
|
|
||||||
CACHE.add(SEND_HEADERS,SEND_HEADERS_ORDINAL);
|
|
||||||
CACHE.add(END_RESPONSE,END_RESPONSE_ORDINAL);
|
|
||||||
CACHE.add(GET_BODY_CHUNK,GET_BODY_CHUNK_ORDINAL);
|
|
||||||
CACHE.add(CPONG_REPLY,CPONG_REPLY_ORDINAL);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
|
@ -1,74 +0,0 @@
|
||||||
//
|
|
||||||
// ========================================================================
|
|
||||||
// Copyright (c) 1995-2012 Mort Bay Consulting Pty. Ltd.
|
|
||||||
// ------------------------------------------------------------------------
|
|
||||||
// All rights reserved. This program and the accompanying materials
|
|
||||||
// are made available under the terms of the Eclipse Public License v1.0
|
|
||||||
// and Apache License v2.0 which accompanies this distribution.
|
|
||||||
//
|
|
||||||
// The Eclipse Public License is available at
|
|
||||||
// http://www.eclipse.org/legal/epl-v10.html
|
|
||||||
//
|
|
||||||
// The Apache License v2.0 is available at
|
|
||||||
// http://www.opensource.org/licenses/apache2.0.php
|
|
||||||
//
|
|
||||||
// You may elect to redistribute this code under either of these licenses.
|
|
||||||
// ========================================================================
|
|
||||||
//
|
|
||||||
|
|
||||||
package org.eclipse.jetty.ajp;
|
|
||||||
|
|
||||||
import org.eclipse.jetty.io.Buffer;
|
|
||||||
import org.eclipse.jetty.io.BufferCache;
|
|
||||||
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
public class Ajp13PacketMethods
|
|
||||||
{
|
|
||||||
|
|
||||||
// TODO - this can probably be replaced by HttpMethods or at least an
|
|
||||||
// extension of it.
|
|
||||||
// It is probably most efficient if "GET" ends up as the same instance
|
|
||||||
|
|
||||||
public final static String OPTIONS="OPTIONS", GET="GET", HEAD="HEAD", POST="POST", PUT="PUT", DELETE="DELETE", TRACE="TRACE", PROPFIND="PROPFIND",
|
|
||||||
PROPPATCH="PROPPATCH", MKCOL="MKCOL", COPY="COPY", MOVE="MOVE", LOCK="LOCK", UNLOCK="UNLOCK", ACL="ACL", REPORT="REPORT",
|
|
||||||
VERSION_CONTROL="VERSION-CONTROL", CHECKIN="CHECKIN", CHECKOUT="CHECKOUT", UNCHCKOUT="UNCHECKOUT", SEARCH="SEARCH", MKWORKSPACE="MKWORKSPACE",
|
|
||||||
UPDATE="UPDATE", LABEL="LABEL", MERGE="MERGE", BASELINE_CONTROL="BASELINE-CONTROL", MKACTIVITY="MKACTIVITY";
|
|
||||||
|
|
||||||
public final static int OPTIONS_ORDINAL=1, GET_ORDINAL=2, HEAD_ORDINAL=3, POST__ORDINAL=4, PUT_ORDINAL=5, DELETE_ORDINAL=6, TRACE_ORDINAL=7,
|
|
||||||
PROPFIND_ORDINAL=8, PROPPATCH_ORDINAL=9, MKCOL_ORDINAL=10, COPY_ORDINAL=11, MOVE_ORDINAL=12, LOCK_ORDINAL=13, UNLOCK_ORDINAL=14, ACL_ORDINAL=15,
|
|
||||||
REPORT_ORDINAL=16, VERSION_CONTROL_ORDINAL=17, CHECKIN_ORDINAL=18, CHECKOUT_ORDINAL=19, UNCHCKOUT_ORDINAL=20, SEARCH_ORDINAL=21,
|
|
||||||
MKWORKSPACE_ORDINAL=22, UPDATE_ORDINAL=23, LABEL_ORDINAL=24, MERGE_ORDINAL=25, BASELINE_CONTROL_ORDINAL=26, MKACTIVITY_ORDINAL=27;
|
|
||||||
|
|
||||||
public final static BufferCache CACHE=new BufferCache();
|
|
||||||
|
|
||||||
public final static Buffer
|
|
||||||
OPTIONS_BUFFER=CACHE.add(OPTIONS,OPTIONS_ORDINAL),
|
|
||||||
GET_BUFFER=CACHE.add(GET,GET_ORDINAL),
|
|
||||||
HEAD_BUFFER=CACHE.add(HEAD, HEAD_ORDINAL),
|
|
||||||
POST__BUFFER=CACHE.add(POST,POST__ORDINAL),
|
|
||||||
PUT_BUFFER=CACHE.add(PUT,PUT_ORDINAL),
|
|
||||||
DELETE_BUFFER=CACHE.add(DELETE,DELETE_ORDINAL),
|
|
||||||
TRACE_BUFFER=CACHE.add(TRACE,TRACE_ORDINAL),
|
|
||||||
PROPFIND_BUFFER=CACHE.add(PROPFIND,PROPFIND_ORDINAL),
|
|
||||||
PROPPATCH_BUFFER=CACHE.add(PROPPATCH, PROPPATCH_ORDINAL),
|
|
||||||
MKCOL_BUFFER=CACHE.add(MKCOL,MKCOL_ORDINAL),
|
|
||||||
COPY_BUFFER=CACHE.add(COPY,COPY_ORDINAL),
|
|
||||||
MOVE_BUFFER=CACHE.add(MOVE,MOVE_ORDINAL),
|
|
||||||
LOCK_BUFFER=CACHE.add(LOCK,LOCK_ORDINAL),
|
|
||||||
UNLOCK_BUFFER=CACHE.add(UNLOCK,UNLOCK_ORDINAL),
|
|
||||||
ACL_BUFFER=CACHE.add(ACL,ACL_ORDINAL),
|
|
||||||
REPORT_BUFFER=CACHE.add(REPORT,REPORT_ORDINAL),
|
|
||||||
VERSION_CONTROL_BUFFER=CACHE.add(VERSION_CONTROL,VERSION_CONTROL_ORDINAL),
|
|
||||||
CHECKIN_BUFFER=CACHE.add(CHECKIN,CHECKIN_ORDINAL),
|
|
||||||
CHECKOUT_BUFFER=CACHE.add(CHECKOUT,CHECKOUT_ORDINAL),
|
|
||||||
UNCHCKOUT_BUFFER=CACHE.add(UNCHCKOUT,UNCHCKOUT_ORDINAL),
|
|
||||||
SEARCH_BUFFER=CACHE.add(SEARCH,SEARCH_ORDINAL),
|
|
||||||
MKWORKSPACE_BUFFER=CACHE.add(MKWORKSPACE,MKWORKSPACE_ORDINAL),
|
|
||||||
UPDATE_BUFFER=CACHE.add(UPDATE,UPDATE_ORDINAL),
|
|
||||||
LABEL_BUFFER=CACHE.add(LABEL,LABEL_ORDINAL),
|
|
||||||
MERGE_BUFFER=CACHE.add(MERGE,MERGE_ORDINAL),
|
|
||||||
BASELINE_CONTROL_BUFFER=CACHE.add(BASELINE_CONTROL,BASELINE_CONTROL_ORDINAL),
|
|
||||||
MKACTIVITY_BUFFER=CACHE.add(MKACTIVITY,MKACTIVITY_ORDINAL);
|
|
||||||
}
|
|
|
@ -1,890 +0,0 @@
|
||||||
//
|
|
||||||
// ========================================================================
|
|
||||||
// Copyright (c) 1995-2012 Mort Bay Consulting Pty. Ltd.
|
|
||||||
// ------------------------------------------------------------------------
|
|
||||||
// All rights reserved. This program and the accompanying materials
|
|
||||||
// are made available under the terms of the Eclipse Public License v1.0
|
|
||||||
// and Apache License v2.0 which accompanies this distribution.
|
|
||||||
//
|
|
||||||
// The Eclipse Public License is available at
|
|
||||||
// http://www.eclipse.org/legal/epl-v10.html
|
|
||||||
//
|
|
||||||
// The Apache License v2.0 is available at
|
|
||||||
// http://www.opensource.org/licenses/apache2.0.php
|
|
||||||
//
|
|
||||||
// You may elect to redistribute this code under either of these licenses.
|
|
||||||
// ========================================================================
|
|
||||||
//
|
|
||||||
|
|
||||||
package org.eclipse.jetty.ajp;
|
|
||||||
|
|
||||||
import java.io.IOException;
|
|
||||||
import java.io.InterruptedIOException;
|
|
||||||
|
|
||||||
import javax.servlet.ServletInputStream;
|
|
||||||
|
|
||||||
import org.eclipse.jetty.http.HttpTokens;
|
|
||||||
import org.eclipse.jetty.http.Parser;
|
|
||||||
import org.eclipse.jetty.io.Buffer;
|
|
||||||
import org.eclipse.jetty.io.BufferUtil;
|
|
||||||
import org.eclipse.jetty.io.Buffers;
|
|
||||||
import org.eclipse.jetty.io.EndPoint;
|
|
||||||
import org.eclipse.jetty.io.EofException;
|
|
||||||
import org.eclipse.jetty.io.View;
|
|
||||||
import org.eclipse.jetty.util.log.Log;
|
|
||||||
import org.eclipse.jetty.util.log.Logger;
|
|
||||||
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
public class Ajp13Parser implements Parser
|
|
||||||
{
|
|
||||||
private static final Logger LOG = Log.getLogger(Ajp13Parser.class);
|
|
||||||
|
|
||||||
private final static int STATE_START = -1;
|
|
||||||
private final static int STATE_END = 0;
|
|
||||||
private final static int STATE_AJP13CHUNK_START = 1;
|
|
||||||
private final static int STATE_AJP13CHUNK = 2;
|
|
||||||
|
|
||||||
private int _state = STATE_START;
|
|
||||||
private long _contentLength;
|
|
||||||
private long _contentPosition;
|
|
||||||
private int _chunkLength;
|
|
||||||
private int _chunkPosition;
|
|
||||||
private int _headers;
|
|
||||||
private Buffers _buffers;
|
|
||||||
private EndPoint _endp;
|
|
||||||
private Buffer _buffer;
|
|
||||||
private Buffer _header; // Buffer for header data (and small _content)
|
|
||||||
private Buffer _body; // Buffer for large content
|
|
||||||
private View _contentView = new View();
|
|
||||||
private EventHandler _handler;
|
|
||||||
private Ajp13Generator _generator;
|
|
||||||
private View _tok0; // Saved token: header name, request method or response version
|
|
||||||
private View _tok1; // Saved token: header value, request URI orresponse code
|
|
||||||
protected int _length;
|
|
||||||
protected int _packetLength;
|
|
||||||
|
|
||||||
|
|
||||||
/* ------------------------------------------------------------------------------- */
|
|
||||||
public Ajp13Parser(Buffers buffers, EndPoint endPoint)
|
|
||||||
{
|
|
||||||
_buffers = buffers;
|
|
||||||
_endp = endPoint;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* ------------------------------------------------------------------------------- */
|
|
||||||
public void setEventHandler(EventHandler handler)
|
|
||||||
{
|
|
||||||
_handler=handler;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* ------------------------------------------------------------------------------- */
|
|
||||||
public void setGenerator(Ajp13Generator generator)
|
|
||||||
{
|
|
||||||
_generator=generator;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* ------------------------------------------------------------------------------- */
|
|
||||||
public long getContentLength()
|
|
||||||
{
|
|
||||||
return _contentLength;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* ------------------------------------------------------------------------------- */
|
|
||||||
public int getState()
|
|
||||||
{
|
|
||||||
return _state;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* ------------------------------------------------------------------------------- */
|
|
||||||
public boolean inContentState()
|
|
||||||
{
|
|
||||||
return _state > 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* ------------------------------------------------------------------------------- */
|
|
||||||
public boolean inHeaderState()
|
|
||||||
{
|
|
||||||
return _state < 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* ------------------------------------------------------------------------------- */
|
|
||||||
public boolean isIdle()
|
|
||||||
{
|
|
||||||
return _state == STATE_START;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* ------------------------------------------------------------------------------- */
|
|
||||||
public boolean isComplete()
|
|
||||||
{
|
|
||||||
return _state == STATE_END;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* ------------------------------------------------------------------------------- */
|
|
||||||
public boolean isMoreInBuffer()
|
|
||||||
{
|
|
||||||
|
|
||||||
if (_header != null && _header.hasContent() || _body != null && _body.hasContent())
|
|
||||||
return true;
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* ------------------------------------------------------------------------------- */
|
|
||||||
public boolean isState(int state)
|
|
||||||
{
|
|
||||||
return _state == state;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* ------------------------------------------------------------------------------- */
|
|
||||||
public void parse() throws IOException
|
|
||||||
{
|
|
||||||
if (_state == STATE_END)
|
|
||||||
reset();
|
|
||||||
if (_state != STATE_START)
|
|
||||||
throw new IllegalStateException("!START");
|
|
||||||
|
|
||||||
// continue parsing
|
|
||||||
while (!isComplete())
|
|
||||||
{
|
|
||||||
parseNext();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* ------------------------------------------------------------------------------- */
|
|
||||||
public boolean parseAvailable() throws IOException
|
|
||||||
{
|
|
||||||
boolean progress=parseNext()>0;
|
|
||||||
|
|
||||||
// continue parsing
|
|
||||||
while (!isComplete() && _buffer!=null && _buffer.length()>0)
|
|
||||||
{
|
|
||||||
progress |= parseNext()>0;
|
|
||||||
}
|
|
||||||
return progress;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* ------------------------------------------------------------------------------- */
|
|
||||||
private int fill() throws IOException
|
|
||||||
{
|
|
||||||
int filled = -1;
|
|
||||||
if (_body != null && _buffer != _body)
|
|
||||||
{
|
|
||||||
// mod_jk implementations may have some partial data from header
|
|
||||||
// check if there are partial contents in the header
|
|
||||||
// copy it to the body if there are any
|
|
||||||
if(_header.length() > 0)
|
|
||||||
{
|
|
||||||
// copy the patial data from the header to the body
|
|
||||||
_body.put(_header);
|
|
||||||
}
|
|
||||||
|
|
||||||
_buffer = _body;
|
|
||||||
|
|
||||||
if (_buffer.length()>0)
|
|
||||||
{
|
|
||||||
filled = _buffer.length();
|
|
||||||
return filled;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (_buffer.markIndex() == 0 && _buffer.putIndex() == _buffer.capacity())
|
|
||||||
throw new IOException("FULL");
|
|
||||||
if (_endp != null && filled <= 0)
|
|
||||||
{
|
|
||||||
// Compress buffer if handling _content buffer
|
|
||||||
// TODO check this is not moving data too much
|
|
||||||
if (_buffer == _body)
|
|
||||||
_buffer.compact();
|
|
||||||
|
|
||||||
if (_buffer.space() == 0)
|
|
||||||
throw new IOException("FULL");
|
|
||||||
|
|
||||||
try
|
|
||||||
{
|
|
||||||
filled = _endp.fill(_buffer);
|
|
||||||
}
|
|
||||||
catch (IOException e)
|
|
||||||
{
|
|
||||||
// This is normal in AJP since the socket closes on timeout only
|
|
||||||
LOG.debug(e);
|
|
||||||
reset();
|
|
||||||
throw (e instanceof EofException) ? e : new EofException(e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (filled < 0)
|
|
||||||
{
|
|
||||||
if (_state > STATE_END)
|
|
||||||
{
|
|
||||||
_state = STATE_END;
|
|
||||||
_handler.messageComplete(_contentPosition);
|
|
||||||
return filled;
|
|
||||||
}
|
|
||||||
reset();
|
|
||||||
throw new EofException();
|
|
||||||
}
|
|
||||||
|
|
||||||
return filled;
|
|
||||||
}
|
|
||||||
|
|
||||||
volatile int _seq=0;
|
|
||||||
/* ------------------------------------------------------------------------------- */
|
|
||||||
public int parseNext() throws IOException
|
|
||||||
{
|
|
||||||
int total_filled = 0;
|
|
||||||
|
|
||||||
if (_buffer == null)
|
|
||||||
{
|
|
||||||
if (_header == null)
|
|
||||||
_header = _buffers.getHeader();
|
|
||||||
|
|
||||||
_buffer = _header;
|
|
||||||
_tok0 = new View(_header);
|
|
||||||
_tok1 = new View(_header);
|
|
||||||
_tok0.setPutIndex(_tok0.getIndex());
|
|
||||||
_tok1.setPutIndex(_tok1.getIndex());
|
|
||||||
}
|
|
||||||
|
|
||||||
if (_state == STATE_END)
|
|
||||||
throw new IllegalStateException("STATE_END");
|
|
||||||
if (_state > STATE_END && _contentPosition == _contentLength)
|
|
||||||
{
|
|
||||||
_state = STATE_END;
|
|
||||||
_handler.messageComplete(_contentPosition);
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (_state < 0)
|
|
||||||
{
|
|
||||||
// have we seen a packet?
|
|
||||||
if (_packetLength<=0)
|
|
||||||
{
|
|
||||||
if (_buffer.length()<4)
|
|
||||||
{
|
|
||||||
if (total_filled<0)
|
|
||||||
total_filled=0;
|
|
||||||
total_filled+=fill();
|
|
||||||
if (_buffer.length()<4)
|
|
||||||
return total_filled;
|
|
||||||
}
|
|
||||||
|
|
||||||
_contentLength = HttpTokens.UNKNOWN_CONTENT;
|
|
||||||
int _magic = Ajp13RequestPacket.getInt(_buffer);
|
|
||||||
if (_magic != Ajp13RequestHeaders.MAGIC)
|
|
||||||
throw new IOException("Bad AJP13 rcv packet: " + "0x" + Integer.toHexString(_magic) + " expected " + "0x" + Integer.toHexString(Ajp13RequestHeaders.MAGIC) + " " + this);
|
|
||||||
|
|
||||||
|
|
||||||
_packetLength = Ajp13RequestPacket.getInt(_buffer);
|
|
||||||
if (_packetLength > Ajp13Packet.MAX_PACKET_SIZE)
|
|
||||||
throw new IOException("AJP13 packet (" + _packetLength + "bytes) too large for buffer");
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
if (_buffer.length() < _packetLength)
|
|
||||||
{
|
|
||||||
if (total_filled<0)
|
|
||||||
total_filled=0;
|
|
||||||
total_filled+=fill();
|
|
||||||
if (_buffer.length() < _packetLength)
|
|
||||||
return total_filled;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Parse Header
|
|
||||||
Buffer bufHeaderName = null;
|
|
||||||
Buffer bufHeaderValue = null;
|
|
||||||
int attr_type = 0;
|
|
||||||
|
|
||||||
byte packetType = Ajp13RequestPacket.getByte(_buffer);
|
|
||||||
|
|
||||||
switch (packetType)
|
|
||||||
{
|
|
||||||
case Ajp13Packet.FORWARD_REQUEST_ORDINAL:
|
|
||||||
_handler.startForwardRequest();
|
|
||||||
break;
|
|
||||||
case Ajp13Packet.CPING_REQUEST_ORDINAL:
|
|
||||||
(_generator).sendCPong();
|
|
||||||
|
|
||||||
if(_header != null)
|
|
||||||
{
|
|
||||||
_buffers.returnBuffer(_header);
|
|
||||||
_header = null;
|
|
||||||
}
|
|
||||||
|
|
||||||
if(_body != null)
|
|
||||||
{
|
|
||||||
_buffers.returnBuffer(_body);
|
|
||||||
_body = null;
|
|
||||||
}
|
|
||||||
|
|
||||||
_buffer= null;
|
|
||||||
|
|
||||||
reset();
|
|
||||||
|
|
||||||
return -1;
|
|
||||||
case Ajp13Packet.SHUTDOWN_ORDINAL:
|
|
||||||
shutdownRequest();
|
|
||||||
|
|
||||||
return -1;
|
|
||||||
|
|
||||||
default:
|
|
||||||
// XXX Throw an Exception here?? Close
|
|
||||||
// connection!
|
|
||||||
LOG.warn("AJP13 message type ({PING}: "+packetType+" ) not supported/recognized as an AJP request");
|
|
||||||
throw new IllegalStateException("PING is not implemented");
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
_handler.parsedMethod(Ajp13RequestPacket.getMethod(_buffer));
|
|
||||||
_handler.parsedProtocol(Ajp13RequestPacket.getString(_buffer, _tok0));
|
|
||||||
_handler.parsedUri(Ajp13RequestPacket.getString(_buffer, _tok1));
|
|
||||||
_handler.parsedRemoteAddr(Ajp13RequestPacket.getString(_buffer, _tok1));
|
|
||||||
_handler.parsedRemoteHost(Ajp13RequestPacket.getString(_buffer, _tok1));
|
|
||||||
_handler.parsedServerName(Ajp13RequestPacket.getString(_buffer, _tok1));
|
|
||||||
_handler.parsedServerPort(Ajp13RequestPacket.getInt(_buffer));
|
|
||||||
_handler.parsedSslSecure(Ajp13RequestPacket.getBool(_buffer));
|
|
||||||
|
|
||||||
|
|
||||||
_headers = Ajp13RequestPacket.getInt(_buffer);
|
|
||||||
|
|
||||||
for (int h=0;h<_headers;h++)
|
|
||||||
{
|
|
||||||
bufHeaderName = Ajp13RequestPacket.getHeaderName(_buffer, _tok0);
|
|
||||||
bufHeaderValue = Ajp13RequestPacket.getString(_buffer, _tok1);
|
|
||||||
|
|
||||||
if (bufHeaderName != null && bufHeaderName.toString().equals(Ajp13RequestHeaders.CONTENT_LENGTH))
|
|
||||||
{
|
|
||||||
_contentLength = BufferUtil.toLong(bufHeaderValue);
|
|
||||||
if (_contentLength == 0)
|
|
||||||
_contentLength = HttpTokens.NO_CONTENT;
|
|
||||||
}
|
|
||||||
|
|
||||||
_handler.parsedHeader(bufHeaderName, bufHeaderValue);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
attr_type = Ajp13RequestPacket.getByte(_buffer) & 0xff;
|
|
||||||
while (attr_type != 0xFF)
|
|
||||||
{
|
|
||||||
switch (attr_type)
|
|
||||||
{
|
|
||||||
// XXX How does this plug into the web
|
|
||||||
// containers
|
|
||||||
// authentication?
|
|
||||||
|
|
||||||
case Ajp13RequestHeaders.REMOTE_USER_ATTR:
|
|
||||||
_handler.parsedRemoteUser(Ajp13RequestPacket.getString(_buffer, _tok1));
|
|
||||||
break;
|
|
||||||
case Ajp13RequestHeaders.AUTH_TYPE_ATTR:
|
|
||||||
//XXX JASPI how does this make sense?
|
|
||||||
_handler.parsedAuthorizationType(Ajp13RequestPacket.getString(_buffer, _tok1));
|
|
||||||
break;
|
|
||||||
|
|
||||||
case Ajp13RequestHeaders.QUERY_STRING_ATTR:
|
|
||||||
_handler.parsedQueryString(Ajp13RequestPacket.getString(_buffer, _tok1));
|
|
||||||
break;
|
|
||||||
|
|
||||||
case Ajp13RequestHeaders.JVM_ROUTE_ATTR:
|
|
||||||
// moved to Eclipse naming usage
|
|
||||||
// used in org.eclipse.jetty.servlet.HashSessionIdManager
|
|
||||||
_handler.parsedRequestAttribute("org.eclipse.jetty.ajp.JVMRoute", Ajp13RequestPacket.getString(_buffer, _tok1));
|
|
||||||
break;
|
|
||||||
|
|
||||||
case Ajp13RequestHeaders.SSL_CERT_ATTR:
|
|
||||||
_handler.parsedSslCert(Ajp13RequestPacket.getString(_buffer, _tok1));
|
|
||||||
break;
|
|
||||||
|
|
||||||
case Ajp13RequestHeaders.SSL_CIPHER_ATTR:
|
|
||||||
_handler.parsedSslCipher(Ajp13RequestPacket.getString(_buffer, _tok1));
|
|
||||||
// SslSocketConnector.customize()
|
|
||||||
break;
|
|
||||||
|
|
||||||
case Ajp13RequestHeaders.SSL_SESSION_ATTR:
|
|
||||||
_handler.parsedSslSession(Ajp13RequestPacket.getString(_buffer, _tok1));
|
|
||||||
break;
|
|
||||||
|
|
||||||
case Ajp13RequestHeaders.REQUEST_ATTR:
|
|
||||||
_handler.parsedRequestAttribute(Ajp13RequestPacket.getString(_buffer, _tok0).toString(), Ajp13RequestPacket.getString(_buffer, _tok1));
|
|
||||||
break;
|
|
||||||
|
|
||||||
// New Jk API?
|
|
||||||
// Check if experimental or can they
|
|
||||||
// assumed to be
|
|
||||||
// supported
|
|
||||||
|
|
||||||
case Ajp13RequestHeaders.SSL_KEYSIZE_ATTR:
|
|
||||||
|
|
||||||
// This has been implemented in AJP13 as either a string or a integer.
|
|
||||||
// Servlet specs say javax.servlet.request.key_size must be an Integer
|
|
||||||
|
|
||||||
// Does it look like a string containing digits?
|
|
||||||
int length = Ajp13RequestPacket.getInt(_buffer);
|
|
||||||
|
|
||||||
if (length>0 && length<16)
|
|
||||||
{
|
|
||||||
// this must be a string length rather than a key length
|
|
||||||
_buffer.skip(-2);
|
|
||||||
_handler.parsedSslKeySize(Integer.parseInt(Ajp13RequestPacket.getString(_buffer, _tok1).toString()));
|
|
||||||
}
|
|
||||||
else
|
|
||||||
_handler.parsedSslKeySize(length);
|
|
||||||
|
|
||||||
break;
|
|
||||||
|
|
||||||
|
|
||||||
// Used to lock down jk requests with a
|
|
||||||
// secreate
|
|
||||||
// key.
|
|
||||||
|
|
||||||
case Ajp13RequestHeaders.SECRET_ATTR:
|
|
||||||
// XXX Investigate safest way to
|
|
||||||
// deal with
|
|
||||||
// this...
|
|
||||||
// should this tie into shutdown
|
|
||||||
// packet?
|
|
||||||
break;
|
|
||||||
|
|
||||||
case Ajp13RequestHeaders.STORED_METHOD_ATTR:
|
|
||||||
// XXX Confirm this should
|
|
||||||
// really overide
|
|
||||||
// previously parsed method?
|
|
||||||
// _handler.parsedMethod(Ajp13PacketMethods.CACHE.get(Ajp13RequestPacket.getString()));
|
|
||||||
break;
|
|
||||||
|
|
||||||
|
|
||||||
case Ajp13RequestHeaders.CONTEXT_ATTR:
|
|
||||||
_handler.parsedContextPath(Ajp13RequestPacket.getString(_buffer, _tok1));
|
|
||||||
break;
|
|
||||||
case Ajp13RequestHeaders.SERVLET_PATH_ATTR:
|
|
||||||
_handler.parsedServletPath(Ajp13RequestPacket.getString(_buffer, _tok1));
|
|
||||||
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
LOG.warn("Unsupported Ajp13 Request Attribute {}", new Integer(attr_type));
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
attr_type = Ajp13RequestPacket.getByte(_buffer) & 0xff;
|
|
||||||
}
|
|
||||||
|
|
||||||
_contentPosition = 0;
|
|
||||||
switch ((int) _contentLength)
|
|
||||||
{
|
|
||||||
|
|
||||||
case HttpTokens.NO_CONTENT:
|
|
||||||
_state = STATE_END;
|
|
||||||
_handler.headerComplete();
|
|
||||||
_handler.messageComplete(_contentPosition);
|
|
||||||
|
|
||||||
break;
|
|
||||||
|
|
||||||
case HttpTokens.UNKNOWN_CONTENT:
|
|
||||||
|
|
||||||
_generator.getBodyChunk();
|
|
||||||
if (_buffers != null && _body == null && _buffer == _header && _header.length() <= 0)
|
|
||||||
{
|
|
||||||
_body = _buffers.getBuffer();
|
|
||||||
_body.clear();
|
|
||||||
}
|
|
||||||
_state = STATE_AJP13CHUNK_START;
|
|
||||||
_handler.headerComplete(); // May recurse here!
|
|
||||||
|
|
||||||
return total_filled;
|
|
||||||
|
|
||||||
default:
|
|
||||||
|
|
||||||
if (_buffers != null && _body == null && _buffer == _header && _contentLength > (_header.capacity() - _header.getIndex()))
|
|
||||||
{
|
|
||||||
_body = _buffers.getBuffer();
|
|
||||||
_body.clear();
|
|
||||||
|
|
||||||
}
|
|
||||||
_state = STATE_AJP13CHUNK_START;
|
|
||||||
_handler.headerComplete(); // May recurse here!
|
|
||||||
return total_filled;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Buffer chunk;
|
|
||||||
|
|
||||||
while (_state>STATE_END)
|
|
||||||
{
|
|
||||||
switch (_state)
|
|
||||||
{
|
|
||||||
case STATE_AJP13CHUNK_START:
|
|
||||||
if (_buffer.length()<6)
|
|
||||||
{
|
|
||||||
if (total_filled<0)
|
|
||||||
total_filled=0;
|
|
||||||
total_filled+=fill();
|
|
||||||
if (_buffer.length()<6)
|
|
||||||
return total_filled;
|
|
||||||
}
|
|
||||||
int _magic=Ajp13RequestPacket.getInt(_buffer);
|
|
||||||
if (_magic!=Ajp13RequestHeaders.MAGIC)
|
|
||||||
{
|
|
||||||
throw new IOException("Bad AJP13 rcv packet: "+"0x"+Integer.toHexString(_magic)+" expected "+"0x"
|
|
||||||
+Integer.toHexString(Ajp13RequestHeaders.MAGIC)+" "+this);
|
|
||||||
}
|
|
||||||
_chunkPosition=0;
|
|
||||||
_chunkLength=Ajp13RequestPacket.getInt(_buffer)-2;
|
|
||||||
Ajp13RequestPacket.getInt(_buffer);
|
|
||||||
if (_chunkLength==0)
|
|
||||||
{
|
|
||||||
_state=STATE_END;
|
|
||||||
_generator.gotBody();
|
|
||||||
_handler.messageComplete(_contentPosition);
|
|
||||||
return total_filled;
|
|
||||||
}
|
|
||||||
_state=STATE_AJP13CHUNK;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case STATE_AJP13CHUNK:
|
|
||||||
if (_buffer.length()<_chunkLength)
|
|
||||||
{
|
|
||||||
if (total_filled<0)
|
|
||||||
total_filled=0;
|
|
||||||
total_filled+=fill();
|
|
||||||
if (_buffer.length()<_chunkLength)
|
|
||||||
return total_filled;
|
|
||||||
}
|
|
||||||
|
|
||||||
int remaining=_chunkLength-_chunkPosition;
|
|
||||||
|
|
||||||
if (remaining==0)
|
|
||||||
{
|
|
||||||
_state=STATE_AJP13CHUNK_START;
|
|
||||||
if (_contentPosition<_contentLength)
|
|
||||||
{
|
|
||||||
_generator.getBodyChunk();
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
_generator.gotBody();
|
|
||||||
}
|
|
||||||
|
|
||||||
return total_filled;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (_buffer.length()<remaining)
|
|
||||||
{
|
|
||||||
remaining=_buffer.length();
|
|
||||||
}
|
|
||||||
|
|
||||||
chunk=Ajp13RequestPacket.get(_buffer,remaining);
|
|
||||||
|
|
||||||
_contentPosition+=chunk.length();
|
|
||||||
_chunkPosition+=chunk.length();
|
|
||||||
_contentView.update(chunk);
|
|
||||||
|
|
||||||
remaining=_chunkLength-_chunkPosition;
|
|
||||||
|
|
||||||
if (remaining==0)
|
|
||||||
{
|
|
||||||
_state=STATE_AJP13CHUNK_START;
|
|
||||||
if (_contentPosition<_contentLength || _contentLength == HttpTokens.UNKNOWN_CONTENT)
|
|
||||||
{
|
|
||||||
_generator.getBodyChunk();
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
_generator.gotBody();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
_handler.content(chunk);
|
|
||||||
|
|
||||||
return total_filled;
|
|
||||||
|
|
||||||
default:
|
|
||||||
throw new IllegalStateException("Invalid Content State");
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
return total_filled;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* ------------------------------------------------------------------------------- */
|
|
||||||
public void reset()
|
|
||||||
{
|
|
||||||
_state = STATE_START;
|
|
||||||
_contentLength = HttpTokens.UNKNOWN_CONTENT;
|
|
||||||
_contentPosition = 0;
|
|
||||||
_length = 0;
|
|
||||||
_packetLength = 0;
|
|
||||||
|
|
||||||
if (_body!=null && _body.hasContent())
|
|
||||||
{
|
|
||||||
// There is content in the body after the end of the request.
|
|
||||||
// This is probably a pipelined header of the next request, so we need to
|
|
||||||
// copy it to the header buffer.
|
|
||||||
if (_header==null)
|
|
||||||
{
|
|
||||||
_header=_buffers.getHeader();
|
|
||||||
_tok0.update(_header);
|
|
||||||
_tok0.update(0,0);
|
|
||||||
_tok1.update(_header);
|
|
||||||
_tok1.update(0,0);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
_header.setMarkIndex(-1);
|
|
||||||
_header.compact();
|
|
||||||
}
|
|
||||||
int take=_header.space();
|
|
||||||
if (take>_body.length())
|
|
||||||
take=_body.length();
|
|
||||||
_body.peek(_body.getIndex(),take);
|
|
||||||
_body.skip(_header.put(_body.peek(_body.getIndex(),take)));
|
|
||||||
}
|
|
||||||
|
|
||||||
if (_header!=null)
|
|
||||||
_header.setMarkIndex(-1);
|
|
||||||
if (_body!=null)
|
|
||||||
_body.setMarkIndex(-1);
|
|
||||||
|
|
||||||
_buffer=_header;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/* ------------------------------------------------------------------------------- */
|
|
||||||
public void returnBuffers()
|
|
||||||
{
|
|
||||||
if (_body!=null && !_body.hasContent() && _body.markIndex()==-1)
|
|
||||||
{
|
|
||||||
if (_buffer==_body)
|
|
||||||
_buffer=_header;
|
|
||||||
if (_buffers!=null)
|
|
||||||
_buffers.returnBuffer(_body);
|
|
||||||
_body=null;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (_header!=null && !_header.hasContent() && _header.markIndex()==-1)
|
|
||||||
{
|
|
||||||
if (_buffer==_header)
|
|
||||||
_buffer=null;
|
|
||||||
_buffers.returnBuffer(_header);
|
|
||||||
_header=null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* ------------------------------------------------------------------------------- */
|
|
||||||
Buffer getHeaderBuffer()
|
|
||||||
{
|
|
||||||
return _buffer;
|
|
||||||
}
|
|
||||||
|
|
||||||
private void shutdownRequest()
|
|
||||||
{
|
|
||||||
_state = STATE_END;
|
|
||||||
|
|
||||||
if(!Ajp13SocketConnector.__allowShutdown)
|
|
||||||
{
|
|
||||||
LOG.warn("AJP13: Shutdown Request is Denied, allowShutdown is set to false!!!");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if(Ajp13SocketConnector.__secretWord != null)
|
|
||||||
{
|
|
||||||
LOG.warn("AJP13: Validating Secret Word");
|
|
||||||
try
|
|
||||||
{
|
|
||||||
String secretWord = Ajp13RequestPacket.getString(_buffer, _tok1).toString();
|
|
||||||
|
|
||||||
if(!Ajp13SocketConnector.__secretWord.equals(secretWord))
|
|
||||||
{
|
|
||||||
LOG.warn("AJP13: Shutdown Request Denied, Invalid Sercret word!!!");
|
|
||||||
throw new IllegalStateException("AJP13: Secret Word is Invalid: Peer has requested shutdown but, Secret Word did not match");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
catch (Exception e)
|
|
||||||
{
|
|
||||||
LOG.warn("AJP13: Secret Word is Required!!!");
|
|
||||||
LOG.debug(e);
|
|
||||||
throw new IllegalStateException("AJP13: Secret Word is Required: Peer has requested shutdown but, has not provided a Secret Word");
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
LOG.warn("AJP13: Shutdown Request is Denied, allowShutdown is set to false!!!");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
LOG.warn("AJP13: Peer Has Requested for Shutdown!!!");
|
|
||||||
LOG.warn("AJP13: Jetty 6 is shutting down !!!");
|
|
||||||
System.exit(0);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* ------------------------------------------------------------------------------- */
|
|
||||||
public interface EventHandler
|
|
||||||
{
|
|
||||||
|
|
||||||
// public void shutdownRequest() throws IOException;
|
|
||||||
// public void cpingRequest() throws IOException;
|
|
||||||
|
|
||||||
public void content(Buffer ref) throws IOException;
|
|
||||||
|
|
||||||
public void headerComplete() throws IOException;
|
|
||||||
|
|
||||||
public void messageComplete(long contextLength) throws IOException;
|
|
||||||
|
|
||||||
public void parsedHeader(Buffer name, Buffer value) throws IOException;
|
|
||||||
|
|
||||||
public void parsedMethod(Buffer method) throws IOException;
|
|
||||||
|
|
||||||
public void parsedProtocol(Buffer protocol) throws IOException;
|
|
||||||
|
|
||||||
public void parsedQueryString(Buffer value) throws IOException;
|
|
||||||
|
|
||||||
public void parsedRemoteAddr(Buffer addr) throws IOException;
|
|
||||||
|
|
||||||
public void parsedRemoteHost(Buffer host) throws IOException;
|
|
||||||
|
|
||||||
public void parsedRequestAttribute(String key, Buffer value) throws IOException;
|
|
||||||
|
|
||||||
public void parsedRequestAttribute(String key, int value) throws IOException;
|
|
||||||
|
|
||||||
public void parsedServerName(Buffer name) throws IOException;
|
|
||||||
|
|
||||||
public void parsedServerPort(int port) throws IOException;
|
|
||||||
|
|
||||||
public void parsedSslSecure(boolean secure) throws IOException;
|
|
||||||
|
|
||||||
public void parsedUri(Buffer uri) throws IOException;
|
|
||||||
|
|
||||||
public void startForwardRequest() throws IOException;
|
|
||||||
|
|
||||||
public void parsedAuthorizationType(Buffer authType) throws IOException;
|
|
||||||
|
|
||||||
public void parsedRemoteUser(Buffer remoteUser) throws IOException;
|
|
||||||
|
|
||||||
public void parsedServletPath(Buffer servletPath) throws IOException;
|
|
||||||
|
|
||||||
public void parsedContextPath(Buffer context) throws IOException;
|
|
||||||
|
|
||||||
public void parsedSslCert(Buffer sslCert) throws IOException;
|
|
||||||
|
|
||||||
public void parsedSslCipher(Buffer sslCipher) throws IOException;
|
|
||||||
|
|
||||||
public void parsedSslSession(Buffer sslSession) throws IOException;
|
|
||||||
|
|
||||||
public void parsedSslKeySize(int keySize) throws IOException;
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
/* ------------------------------------------------------------ */
|
|
||||||
/**
|
|
||||||
* TODO Make this common with HttpParser
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
public static class Input extends ServletInputStream
|
|
||||||
{
|
|
||||||
private Ajp13Parser _parser;
|
|
||||||
private EndPoint _endp;
|
|
||||||
private long _maxIdleTime;
|
|
||||||
private View _content;
|
|
||||||
|
|
||||||
/* ------------------------------------------------------------ */
|
|
||||||
public Input(Ajp13Parser parser, long maxIdleTime)
|
|
||||||
{
|
|
||||||
_parser = parser;
|
|
||||||
_endp = parser._endp;
|
|
||||||
_maxIdleTime = maxIdleTime;
|
|
||||||
_content = _parser._contentView;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* ------------------------------------------------------------ */
|
|
||||||
@Override
|
|
||||||
public int read() throws IOException
|
|
||||||
{
|
|
||||||
int c = -1;
|
|
||||||
if (blockForContent())
|
|
||||||
c = 0xff & _content.get();
|
|
||||||
return c;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* ------------------------------------------------------------ */
|
|
||||||
/*
|
|
||||||
* @see java.io.InputStream#read(byte[], int, int)
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
public int read(byte[] b, int off, int len) throws IOException
|
|
||||||
{
|
|
||||||
int l = -1;
|
|
||||||
if (blockForContent())
|
|
||||||
l = _content.get(b, off, len);
|
|
||||||
return l;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* ------------------------------------------------------------ */
|
|
||||||
private boolean blockForContent() throws IOException
|
|
||||||
{
|
|
||||||
if (_content.length() > 0)
|
|
||||||
return true;
|
|
||||||
if (_parser.isState(Ajp13Parser.STATE_END) || _parser.isState(Ajp13Parser.STATE_START))
|
|
||||||
return false;
|
|
||||||
|
|
||||||
// Handle simple end points.
|
|
||||||
if (_endp == null)
|
|
||||||
_parser.parseNext();
|
|
||||||
|
|
||||||
// Handle blocking end points
|
|
||||||
else if (_endp.isBlocking())
|
|
||||||
{
|
|
||||||
_parser.parseNext();
|
|
||||||
|
|
||||||
// parse until some progress is made (or IOException thrown for timeout)
|
|
||||||
while (_content.length() == 0 && !_parser.isState(Ajp13Parser.STATE_END))
|
|
||||||
{
|
|
||||||
// Try to get more _parser._content
|
|
||||||
_parser.parseNext();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else // Handle non-blocking end point
|
|
||||||
{
|
|
||||||
long filled = _parser.parseNext();
|
|
||||||
boolean blocked = false;
|
|
||||||
|
|
||||||
// parse until some progress is made (or
|
|
||||||
// IOException thrown for timeout)
|
|
||||||
while (_content.length() == 0 && !_parser.isState(Ajp13Parser.STATE_END))
|
|
||||||
{
|
|
||||||
// if fill called, but no bytes read,
|
|
||||||
// then block
|
|
||||||
if (filled > 0)
|
|
||||||
blocked = false;
|
|
||||||
else if (filled == 0)
|
|
||||||
{
|
|
||||||
if (blocked)
|
|
||||||
throw new InterruptedIOException("timeout");
|
|
||||||
|
|
||||||
blocked = true;
|
|
||||||
_endp.blockReadable(_maxIdleTime);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Try to get more _parser._content
|
|
||||||
filled = _parser.parseNext();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return _content.length() > 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean isPersistent()
|
|
||||||
{
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setPersistent(boolean persistent)
|
|
||||||
{
|
|
||||||
LOG.warn("AJP13.setPersistent is not IMPLEMENTED!");
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,124 +0,0 @@
|
||||||
//
|
|
||||||
// ========================================================================
|
|
||||||
// Copyright (c) 1995-2012 Mort Bay Consulting Pty. Ltd.
|
|
||||||
// ------------------------------------------------------------------------
|
|
||||||
// All rights reserved. This program and the accompanying materials
|
|
||||||
// are made available under the terms of the Eclipse Public License v1.0
|
|
||||||
// and Apache License v2.0 which accompanies this distribution.
|
|
||||||
//
|
|
||||||
// The Eclipse Public License is available at
|
|
||||||
// http://www.eclipse.org/legal/epl-v10.html
|
|
||||||
//
|
|
||||||
// The Apache License v2.0 is available at
|
|
||||||
// http://www.opensource.org/licenses/apache2.0.php
|
|
||||||
//
|
|
||||||
// You may elect to redistribute this code under either of these licenses.
|
|
||||||
// ========================================================================
|
|
||||||
//
|
|
||||||
|
|
||||||
package org.eclipse.jetty.ajp;
|
|
||||||
|
|
||||||
import org.eclipse.jetty.server.AbstractHttpConnection;
|
|
||||||
import org.eclipse.jetty.server.Request;
|
|
||||||
|
|
||||||
public class Ajp13Request extends Request
|
|
||||||
{
|
|
||||||
protected String _remoteAddr;
|
|
||||||
protected String _remoteHost;
|
|
||||||
protected String _remoteUser;
|
|
||||||
protected boolean _sslSecure;
|
|
||||||
|
|
||||||
/* ------------------------------------------------------------ */
|
|
||||||
public Ajp13Request(AbstractHttpConnection connection)
|
|
||||||
{
|
|
||||||
super(connection);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* ------------------------------------------------------------ */
|
|
||||||
public Ajp13Request()
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
/* ------------------------------------------------------------ */
|
|
||||||
void setConnection(Ajp13Connection connection)
|
|
||||||
{
|
|
||||||
super.setConnection(connection);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* ------------------------------------------------------------ */
|
|
||||||
public void setRemoteUser(String remoteUser)
|
|
||||||
{
|
|
||||||
_remoteUser = remoteUser;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* ------------------------------------------------------------ */
|
|
||||||
@Override
|
|
||||||
public String getRemoteUser()
|
|
||||||
{
|
|
||||||
if(_remoteUser != null)
|
|
||||||
return _remoteUser;
|
|
||||||
return super.getRemoteUser();
|
|
||||||
}
|
|
||||||
|
|
||||||
/* ------------------------------------------------------------ */
|
|
||||||
@Override
|
|
||||||
public String getRemoteAddr()
|
|
||||||
{
|
|
||||||
if (_remoteAddr != null)
|
|
||||||
return _remoteAddr;
|
|
||||||
if (_remoteHost != null)
|
|
||||||
return _remoteHost;
|
|
||||||
return super.getRemoteAddr();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/* ------------------------------------------------------------ */
|
|
||||||
@Override
|
|
||||||
public void setRemoteAddr(String remoteAddr)
|
|
||||||
{
|
|
||||||
_remoteAddr = remoteAddr;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* ------------------------------------------------------------ */
|
|
||||||
@Override
|
|
||||||
public String getRemoteHost()
|
|
||||||
{
|
|
||||||
if (_remoteHost != null)
|
|
||||||
return _remoteHost;
|
|
||||||
if (_remoteAddr != null)
|
|
||||||
return _remoteAddr;
|
|
||||||
return super.getRemoteHost();
|
|
||||||
}
|
|
||||||
|
|
||||||
/* ------------------------------------------------------------ */
|
|
||||||
@Override
|
|
||||||
public void setRemoteHost(String remoteHost)
|
|
||||||
{
|
|
||||||
_remoteHost = remoteHost;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* ------------------------------------------------------------ */
|
|
||||||
public boolean isSslSecure()
|
|
||||||
{
|
|
||||||
return _sslSecure;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* ------------------------------------------------------------ */
|
|
||||||
public void setSslSecure(boolean sslSecure)
|
|
||||||
{
|
|
||||||
_sslSecure = sslSecure;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* ------------------------------------------------------------ */
|
|
||||||
@Override
|
|
||||||
protected void recycle()
|
|
||||||
{
|
|
||||||
super.recycle();
|
|
||||||
_remoteAddr = null;
|
|
||||||
_remoteHost = null;
|
|
||||||
_remoteUser = null;
|
|
||||||
_sslSecure = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
|
@ -1,67 +0,0 @@
|
||||||
//
|
|
||||||
// ========================================================================
|
|
||||||
// Copyright (c) 1995-2012 Mort Bay Consulting Pty. Ltd.
|
|
||||||
// ------------------------------------------------------------------------
|
|
||||||
// All rights reserved. This program and the accompanying materials
|
|
||||||
// are made available under the terms of the Eclipse Public License v1.0
|
|
||||||
// and Apache License v2.0 which accompanies this distribution.
|
|
||||||
//
|
|
||||||
// The Eclipse Public License is available at
|
|
||||||
// http://www.eclipse.org/legal/epl-v10.html
|
|
||||||
//
|
|
||||||
// The Apache License v2.0 is available at
|
|
||||||
// http://www.opensource.org/licenses/apache2.0.php
|
|
||||||
//
|
|
||||||
// You may elect to redistribute this code under either of these licenses.
|
|
||||||
// ========================================================================
|
|
||||||
//
|
|
||||||
|
|
||||||
package org.eclipse.jetty.ajp;
|
|
||||||
|
|
||||||
import org.eclipse.jetty.io.Buffer;
|
|
||||||
import org.eclipse.jetty.io.BufferCache;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* XXX Should this implement the Buffer interface?
|
|
||||||
*
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
public class Ajp13RequestHeaders extends BufferCache
|
|
||||||
{
|
|
||||||
|
|
||||||
public final static int MAGIC=0x1234;
|
|
||||||
|
|
||||||
public final static String ACCEPT="accept", ACCEPT_CHARSET="accept-charset", ACCEPT_ENCODING="accept-encoding", ACCEPT_LANGUAGE="accept-language",
|
|
||||||
AUTHORIZATION="authorization", CONNECTION="connection", CONTENT_TYPE="content-type", CONTENT_LENGTH="content-length", COOKIE="cookie",
|
|
||||||
COOKIE2="cookie2", HOST="host", PRAGMA="pragma", REFERER="referer", USER_AGENT="user-agent";
|
|
||||||
|
|
||||||
public final static int ACCEPT_ORDINAL=1, ACCEPT_CHARSET_ORDINAL=2, ACCEPT_ENCODING_ORDINAL=3, ACCEPT_LANGUAGE_ORDINAL=4, AUTHORIZATION_ORDINAL=5,
|
|
||||||
CONNECTION_ORDINAL=6, CONTENT_TYPE_ORDINAL=7, CONTENT_LENGTH_ORDINAL=8, COOKIE_ORDINAL=9, COOKIE2_ORDINAL=10, HOST_ORDINAL=11, PRAGMA_ORDINAL=12,
|
|
||||||
REFERER_ORDINAL=13, USER_AGENT_ORDINAL=14;
|
|
||||||
|
|
||||||
public final static BufferCache CACHE=new BufferCache();
|
|
||||||
|
|
||||||
public final static Buffer ACCEPT_BUFFER=CACHE.add(ACCEPT,ACCEPT_ORDINAL), ACCEPT_CHARSET_BUFFER=CACHE.add(ACCEPT_CHARSET,ACCEPT_CHARSET_ORDINAL),
|
|
||||||
ACCEPT_ENCODING_BUFFER=CACHE.add(ACCEPT_ENCODING,ACCEPT_ENCODING_ORDINAL), ACCEPT_LANGUAGE_BUFFER=CACHE
|
|
||||||
.add(ACCEPT_LANGUAGE,ACCEPT_LANGUAGE_ORDINAL), AUTHORIZATION_BUFFER=CACHE.add(AUTHORIZATION,AUTHORIZATION_ORDINAL), CONNECTION_BUFFER=CACHE
|
|
||||||
.add(CONNECTION,CONNECTION_ORDINAL), CONTENT_TYPE_BUFFER=CACHE.add(CONTENT_TYPE,CONTENT_TYPE_ORDINAL), CONTENT_LENGTH_BUFFER=CACHE.add(
|
|
||||||
CONTENT_LENGTH,CONTENT_LENGTH_ORDINAL), COOKIE_BUFFER=CACHE.add(COOKIE,COOKIE_ORDINAL), COOKIE2_BUFFER=CACHE.add(COOKIE2,COOKIE2_ORDINAL),
|
|
||||||
HOST_BUFFER=CACHE.add(HOST,HOST_ORDINAL), PRAGMA_BUFFER=CACHE.add(PRAGMA,PRAGMA_ORDINAL), REFERER_BUFFER=CACHE.add(REFERER,REFERER_ORDINAL),
|
|
||||||
USER_AGENT_BUFFER=CACHE.add(USER_AGENT,USER_AGENT_ORDINAL);
|
|
||||||
|
|
||||||
public final static byte
|
|
||||||
CONTEXT_ATTR=1, // Legacy
|
|
||||||
SERVLET_PATH_ATTR=2, // Legacy
|
|
||||||
REMOTE_USER_ATTR=3,
|
|
||||||
AUTH_TYPE_ATTR=4,
|
|
||||||
QUERY_STRING_ATTR=5,
|
|
||||||
JVM_ROUTE_ATTR=6,
|
|
||||||
SSL_CERT_ATTR=7,
|
|
||||||
SSL_CIPHER_ATTR=8,
|
|
||||||
SSL_SESSION_ATTR=9,
|
|
||||||
REQUEST_ATTR=10,
|
|
||||||
SSL_KEYSIZE_ATTR=11,
|
|
||||||
SECRET_ATTR=12,
|
|
||||||
STORED_METHOD_ATTR=13;
|
|
||||||
|
|
||||||
}
|
|
|
@ -1,90 +0,0 @@
|
||||||
//
|
|
||||||
// ========================================================================
|
|
||||||
// Copyright (c) 1995-2012 Mort Bay Consulting Pty. Ltd.
|
|
||||||
// ------------------------------------------------------------------------
|
|
||||||
// All rights reserved. This program and the accompanying materials
|
|
||||||
// are made available under the terms of the Eclipse Public License v1.0
|
|
||||||
// and Apache License v2.0 which accompanies this distribution.
|
|
||||||
//
|
|
||||||
// The Eclipse Public License is available at
|
|
||||||
// http://www.eclipse.org/legal/epl-v10.html
|
|
||||||
//
|
|
||||||
// The Apache License v2.0 is available at
|
|
||||||
// http://www.opensource.org/licenses/apache2.0.php
|
|
||||||
//
|
|
||||||
// You may elect to redistribute this code under either of these licenses.
|
|
||||||
// ========================================================================
|
|
||||||
//
|
|
||||||
|
|
||||||
package org.eclipse.jetty.ajp;
|
|
||||||
|
|
||||||
import org.eclipse.jetty.io.Buffer;
|
|
||||||
import org.eclipse.jetty.io.View;
|
|
||||||
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
*
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
public class Ajp13RequestPacket
|
|
||||||
{
|
|
||||||
public static boolean isEmpty(Buffer _buffer)
|
|
||||||
{
|
|
||||||
return _buffer.length()==0;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static int getInt(Buffer _buffer)
|
|
||||||
{
|
|
||||||
return ((_buffer.get()&0xFF)<<8)|(_buffer.get()&0xFF);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static Buffer getString(Buffer _buffer, View tok)
|
|
||||||
{
|
|
||||||
int len=((_buffer.peek()&0xFF)<<8)|(_buffer.peek(_buffer.getIndex()+1)&0xFF);
|
|
||||||
if (len==0xffff)
|
|
||||||
{
|
|
||||||
_buffer.skip(2);
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
int start=_buffer.getIndex();
|
|
||||||
tok.update(start+2,start+len+2);
|
|
||||||
_buffer.skip(len+3);
|
|
||||||
return tok;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static byte getByte(Buffer _buffer)
|
|
||||||
{
|
|
||||||
return _buffer.get();
|
|
||||||
}
|
|
||||||
|
|
||||||
public static boolean getBool(Buffer _buffer)
|
|
||||||
{
|
|
||||||
return _buffer.get()>0;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static Buffer getMethod(Buffer _buffer)
|
|
||||||
{
|
|
||||||
return Ajp13PacketMethods.CACHE.get(_buffer.get());
|
|
||||||
}
|
|
||||||
|
|
||||||
public static Buffer getHeaderName(Buffer _buffer, View tok)
|
|
||||||
{
|
|
||||||
int len=((_buffer.peek()&0xFF)<<8)|(_buffer.peek(_buffer.getIndex()+1)&0xFF);
|
|
||||||
if ((0xFF00&len)==0xA000)
|
|
||||||
{
|
|
||||||
_buffer.skip(1);
|
|
||||||
return Ajp13RequestHeaders.CACHE.get(_buffer.get());
|
|
||||||
}
|
|
||||||
int start=_buffer.getIndex();
|
|
||||||
tok.update(start+2,start+len+2);
|
|
||||||
_buffer.skip(len+3);
|
|
||||||
return tok;
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
public static Buffer get(Buffer buffer, int length)
|
|
||||||
{
|
|
||||||
return buffer.get(length);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
|
@ -1,48 +0,0 @@
|
||||||
//
|
|
||||||
// ========================================================================
|
|
||||||
// Copyright (c) 1995-2012 Mort Bay Consulting Pty. Ltd.
|
|
||||||
// ------------------------------------------------------------------------
|
|
||||||
// All rights reserved. This program and the accompanying materials
|
|
||||||
// are made available under the terms of the Eclipse Public License v1.0
|
|
||||||
// and Apache License v2.0 which accompanies this distribution.
|
|
||||||
//
|
|
||||||
// The Eclipse Public License is available at
|
|
||||||
// http://www.eclipse.org/legal/epl-v10.html
|
|
||||||
//
|
|
||||||
// The Apache License v2.0 is available at
|
|
||||||
// http://www.opensource.org/licenses/apache2.0.php
|
|
||||||
//
|
|
||||||
// You may elect to redistribute this code under either of these licenses.
|
|
||||||
// ========================================================================
|
|
||||||
//
|
|
||||||
|
|
||||||
package org.eclipse.jetty.ajp;
|
|
||||||
|
|
||||||
import org.eclipse.jetty.io.Buffer;
|
|
||||||
import org.eclipse.jetty.io.BufferCache;
|
|
||||||
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
public class Ajp13ResponseHeaders extends BufferCache
|
|
||||||
{
|
|
||||||
|
|
||||||
public final static int MAGIC=0xab00;
|
|
||||||
|
|
||||||
public final static String CONTENT_TYPE="Content-Type", CONTENT_LANGUAGE="Content-Language", CONTENT_LENGTH="Content-Length", DATE="Date",
|
|
||||||
LAST_MODIFIED="Last-Modified", LOCATION="Location", SET_COOKIE="Set-Cookie", SET_COOKIE2="Set-Cookie2", SERVLET_ENGINE="Servlet-Engine",
|
|
||||||
STATUS="Status", WWW_AUTHENTICATE="WWW-Authenticate";
|
|
||||||
|
|
||||||
public final static int CONTENT_TYPE_ORDINAL=1, CONTENT_LANGUAGE_ORDINAL=2, CONTENT_LENGTH_ORDINAL=3, DATE_ORDINAL=4, LAST_MODIFIED_ORDINAL=5,
|
|
||||||
LOCATION_ORDINAL=6, SET_COOKIE_ORDINAL=7, SET_COOKIE2_ORDINAL=8, SERVLET_ENGINE_ORDINAL=9, STATUS_ORDINAL=10, WWW_AUTHENTICATE_ORDINAL=11;
|
|
||||||
|
|
||||||
public final static BufferCache CACHE=new BufferCache();
|
|
||||||
|
|
||||||
public final static Buffer CONTENT_TYPE_BUFFER=CACHE.add(CONTENT_TYPE,CONTENT_TYPE_ORDINAL), CONTENT_LANGUAGE_BUFFER=CACHE.add(CONTENT_LANGUAGE,
|
|
||||||
CONTENT_LANGUAGE_ORDINAL), CONTENT_LENGTH_BUFFER=CACHE.add(CONTENT_LENGTH,CONTENT_LENGTH_ORDINAL), DATE_BUFFER=CACHE.add(DATE,DATE_ORDINAL),
|
|
||||||
LAST_MODIFIED_BUFFER=CACHE.add(LAST_MODIFIED,LAST_MODIFIED_ORDINAL), LOCATION_BUFFER=CACHE.add(LOCATION,LOCATION_ORDINAL), SET_COOKIE_BUFFER=CACHE
|
|
||||||
.add(SET_COOKIE,SET_COOKIE_ORDINAL), SET_COOKIE2_BUFFER=CACHE.add(SET_COOKIE2,SET_COOKIE2_ORDINAL), SERVLET_ENGINE_BUFFER=CACHE.add(
|
|
||||||
SERVLET_ENGINE,SERVLET_ENGINE_ORDINAL), STATUS_BUFFER=CACHE.add(STATUS,STATUS_ORDINAL), WWW_AUTHENTICATE_BUFFER=CACHE.add(WWW_AUTHENTICATE,
|
|
||||||
WWW_AUTHENTICATE_ORDINAL);
|
|
||||||
|
|
||||||
}
|
|
|
@ -1,132 +0,0 @@
|
||||||
//
|
|
||||||
// ========================================================================
|
|
||||||
// Copyright (c) 1995-2012 Mort Bay Consulting Pty. Ltd.
|
|
||||||
// ------------------------------------------------------------------------
|
|
||||||
// All rights reserved. This program and the accompanying materials
|
|
||||||
// are made available under the terms of the Eclipse Public License v1.0
|
|
||||||
// and Apache License v2.0 which accompanies this distribution.
|
|
||||||
//
|
|
||||||
// The Eclipse Public License is available at
|
|
||||||
// http://www.eclipse.org/legal/epl-v10.html
|
|
||||||
//
|
|
||||||
// The Apache License v2.0 is available at
|
|
||||||
// http://www.opensource.org/licenses/apache2.0.php
|
|
||||||
//
|
|
||||||
// You may elect to redistribute this code under either of these licenses.
|
|
||||||
// ========================================================================
|
|
||||||
//
|
|
||||||
|
|
||||||
package org.eclipse.jetty.ajp;
|
|
||||||
|
|
||||||
import java.io.IOException;
|
|
||||||
|
|
||||||
import org.eclipse.jetty.http.HttpSchemes;
|
|
||||||
import org.eclipse.jetty.io.Connection;
|
|
||||||
import org.eclipse.jetty.io.EndPoint;
|
|
||||||
import org.eclipse.jetty.server.Request;
|
|
||||||
import org.eclipse.jetty.server.bio.SocketConnector;
|
|
||||||
import org.eclipse.jetty.util.log.Log;
|
|
||||||
import org.eclipse.jetty.util.log.Logger;
|
|
||||||
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
*
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
public class Ajp13SocketConnector extends SocketConnector
|
|
||||||
{
|
|
||||||
private static final Logger LOG = Log.getLogger(Ajp13SocketConnector.class);
|
|
||||||
|
|
||||||
static String __secretWord = null;
|
|
||||||
static boolean __allowShutdown = false;
|
|
||||||
public Ajp13SocketConnector()
|
|
||||||
{
|
|
||||||
super.setRequestHeaderSize(Ajp13Packet.MAX_PACKET_SIZE);
|
|
||||||
super.setResponseHeaderSize(Ajp13Packet.MAX_PACKET_SIZE);
|
|
||||||
super.setRequestBufferSize(Ajp13Packet.MAX_PACKET_SIZE);
|
|
||||||
super.setResponseBufferSize(Ajp13Packet.MAX_PACKET_SIZE);
|
|
||||||
// IN AJP protocol the socket stay open, so
|
|
||||||
// by default the time out is set to 0 seconds
|
|
||||||
super.setMaxIdleTime(0);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void doStart() throws Exception
|
|
||||||
{
|
|
||||||
super.doStart();
|
|
||||||
LOG.info("AJP13 is not a secure protocol. Please protect port {}",Integer.toString(getLocalPort()));
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/* ------------------------------------------------------------ */
|
|
||||||
/* (non-Javadoc)
|
|
||||||
* @see org.eclipse.jetty.server.bio.SocketConnector#customize(org.eclipse.io.EndPoint, org.eclipse.jetty.server.Request)
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
public void customize(EndPoint endpoint, Request request) throws IOException
|
|
||||||
{
|
|
||||||
super.customize(endpoint,request);
|
|
||||||
if (request.isSecure())
|
|
||||||
request.setScheme(HttpSchemes.HTTPS);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* ------------------------------------------------------------ */
|
|
||||||
@Override
|
|
||||||
protected Connection newConnection(EndPoint endpoint)
|
|
||||||
{
|
|
||||||
return new Ajp13Connection(this,endpoint,getServer());
|
|
||||||
}
|
|
||||||
|
|
||||||
/* ------------------------------------------------------------ */
|
|
||||||
// Secured on a packet by packet bases not by connection
|
|
||||||
@Override
|
|
||||||
public boolean isConfidential(Request request)
|
|
||||||
{
|
|
||||||
return ((Ajp13Request) request).isSslSecure();
|
|
||||||
}
|
|
||||||
|
|
||||||
/* ------------------------------------------------------------ */
|
|
||||||
// Secured on a packet by packet bases not by connection
|
|
||||||
@Override
|
|
||||||
public boolean isIntegral(Request request)
|
|
||||||
{
|
|
||||||
return ((Ajp13Request) request).isSslSecure();
|
|
||||||
}
|
|
||||||
|
|
||||||
/* ------------------------------------------------------------ */
|
|
||||||
@Deprecated
|
|
||||||
public void setHeaderBufferSize(int headerBufferSize)
|
|
||||||
{
|
|
||||||
LOG.debug(Log.IGNORED);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* ------------------------------------------------------------ */
|
|
||||||
@Override
|
|
||||||
public void setRequestBufferSize(int requestBufferSize)
|
|
||||||
{
|
|
||||||
LOG.debug(Log.IGNORED);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* ------------------------------------------------------------ */
|
|
||||||
@Override
|
|
||||||
public void setResponseBufferSize(int responseBufferSize)
|
|
||||||
{
|
|
||||||
LOG.debug(Log.IGNORED);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* ------------------------------------------------------------ */
|
|
||||||
public void setAllowShutdown(boolean allowShutdown)
|
|
||||||
{
|
|
||||||
LOG.warn("AJP13: Shutdown Request is: " + allowShutdown);
|
|
||||||
__allowShutdown = allowShutdown;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* ------------------------------------------------------------ */
|
|
||||||
public void setSecretWord(String secretWord)
|
|
||||||
{
|
|
||||||
LOG.warn("AJP13: Shutdown Request secret word is : " + secretWord);
|
|
||||||
__secretWord = secretWord;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
|
@ -1,331 +0,0 @@
|
||||||
//
|
|
||||||
// ========================================================================
|
|
||||||
// Copyright (c) 1995-2012 Mort Bay Consulting Pty. Ltd.
|
|
||||||
// ------------------------------------------------------------------------
|
|
||||||
// All rights reserved. This program and the accompanying materials
|
|
||||||
// are made available under the terms of the Eclipse Public License v1.0
|
|
||||||
// and Apache License v2.0 which accompanies this distribution.
|
|
||||||
//
|
|
||||||
// The Eclipse Public License is available at
|
|
||||||
// http://www.eclipse.org/legal/epl-v10.html
|
|
||||||
//
|
|
||||||
// The Apache License v2.0 is available at
|
|
||||||
// http://www.opensource.org/licenses/apache2.0.php
|
|
||||||
//
|
|
||||||
// You may elect to redistribute this code under either of these licenses.
|
|
||||||
// ========================================================================
|
|
||||||
//
|
|
||||||
|
|
||||||
package org.eclipse.jetty.ajp;
|
|
||||||
|
|
||||||
import static org.junit.Assert.assertTrue;
|
|
||||||
|
|
||||||
import java.io.ByteArrayOutputStream;
|
|
||||||
import java.io.IOException;
|
|
||||||
import java.io.OutputStream;
|
|
||||||
import java.net.Socket;
|
|
||||||
import java.net.SocketTimeoutException;
|
|
||||||
|
|
||||||
import javax.servlet.ServletException;
|
|
||||||
import javax.servlet.http.HttpServletRequest;
|
|
||||||
import javax.servlet.http.HttpServletResponse;
|
|
||||||
|
|
||||||
import org.eclipse.jetty.server.Connector;
|
|
||||||
import org.eclipse.jetty.server.Request;
|
|
||||||
import org.eclipse.jetty.server.Server;
|
|
||||||
import org.eclipse.jetty.server.handler.AbstractHandler;
|
|
||||||
import org.eclipse.jetty.util.IO;
|
|
||||||
import org.eclipse.jetty.util.TypeUtil;
|
|
||||||
import org.eclipse.jetty.util.log.Log;
|
|
||||||
import org.eclipse.jetty.util.log.Logger;
|
|
||||||
import org.junit.After;
|
|
||||||
import org.junit.AfterClass;
|
|
||||||
import org.junit.Before;
|
|
||||||
import org.junit.BeforeClass;
|
|
||||||
import org.junit.Test;
|
|
||||||
|
|
||||||
public class Ajp13ConnectionTest
|
|
||||||
{
|
|
||||||
private static final Logger LOG = Log.getLogger(Ajp13ConnectionTest.class);
|
|
||||||
|
|
||||||
private static Server _server;
|
|
||||||
private static Ajp13SocketConnector _connector;
|
|
||||||
private Socket _client;
|
|
||||||
|
|
||||||
@BeforeClass
|
|
||||||
public static void startServer() throws Exception
|
|
||||||
{
|
|
||||||
_server=new Server();
|
|
||||||
_connector=new Ajp13SocketConnector();
|
|
||||||
|
|
||||||
_connector.setPort(0);
|
|
||||||
_server.setConnectors(new Connector[] { _connector });
|
|
||||||
_server.setHandler(new Handler());
|
|
||||||
_server.start();
|
|
||||||
}
|
|
||||||
|
|
||||||
@AfterClass
|
|
||||||
public static void stopServer() throws Exception
|
|
||||||
{
|
|
||||||
_connector.close();
|
|
||||||
_server.stop();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Before
|
|
||||||
public void openSocket() throws Exception
|
|
||||||
{
|
|
||||||
_client=new Socket("localhost",_connector.getLocalPort());
|
|
||||||
_client.setSoTimeout(500);
|
|
||||||
}
|
|
||||||
|
|
||||||
@After
|
|
||||||
public void closeSocket() throws Exception
|
|
||||||
{
|
|
||||||
_client.close();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void testPacket1() throws Exception
|
|
||||||
{
|
|
||||||
OutputStream os=_client.getOutputStream();
|
|
||||||
|
|
||||||
String packet="123401070202000f77696474683d20485454502f312e300000122f636f6e74726f6c2f70726f647563742f2200000e3230382e32372e3230332e31323800ffff000c7777772e756c74612e636f6d000050000005a006000a6b6565702d616c69766500a00b000c7777772e756c74612e636f6d00a00e002b4d6f7a696c6c612f342e302028636f6d70617469626c653b20426f726465724d616e6167657220332e302900a0010043696d6167652f6769662c20696d6167652f782d786269746d61702c20696d6167652f6a7065672c20696d6167652f706a7065672c20696d6167652f706d672c202a2f2a00a008000130000600067570726f64310008000a4145533235362d53484100ff";
|
|
||||||
os.write(TypeUtil.fromHexString(packet));
|
|
||||||
os.flush();
|
|
||||||
|
|
||||||
readResponse(_client);
|
|
||||||
assertTrue(true);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void testPacket2() throws Exception
|
|
||||||
{
|
|
||||||
OutputStream os=_client.getOutputStream();
|
|
||||||
|
|
||||||
String packet="1234020102020008485454502f312e3100000f2f6363632d7777777777772f61616100000c38382e3838382e38382e383830ffff00116363632e6363636363636363632e636f6d0001bb010009a00b00116363632e6363636363636363632e636f6d00a00e005a4d6f7a696c6c612f352e30202857696e646f77733b20553b2057696e646f7773204e5420352e313b20656e2d55533b2072763a312e382e312e3129204765636b6f2f32303036313230342046697265666f782f322e302e302e3100a0010063746578742f786d6c2c6170706c69636174696f6e2f786d6c2c6170706c69636174696f6e2f7868746d6c2b786d6c2c746578742f68746d6c3b713d302e392c746578742f706c61696e3b713d302e382c696d6167652f706e672c2a2f2a3b713d302e3500a004000e656e2d75732c656e3b713d302e3500a003000c677a69702c6465666c61746500a002001e49534f2d383835392d312c7574662d383b713d302e372c2a3b713d302e3700000a4b6565702d416c69766500000333303000a006000a6b6565702d616c69766500000c4d61782d466f7277617264730000023130000800124448452d5253412d4145533235362d5348410009004039324643303544413043444141443232303137413743443141453939353132413330443938363838423843433041454643364231363035323543433232353341000b0100ff";
|
|
||||||
os.write(TypeUtil.fromHexString(packet));
|
|
||||||
os.flush();
|
|
||||||
|
|
||||||
readResponse(_client);
|
|
||||||
assertTrue(true);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void testPacket3() throws Exception
|
|
||||||
{
|
|
||||||
OutputStream os=_client.getOutputStream();
|
|
||||||
|
|
||||||
String packet="1234028f02020008485454502f312e3100000d2f666f726d746573742e6a737000000d3139322e3136382e342e31383000ffff00107777772e777265636b6167652e6f726700005000000aa0010063746578742f786d6c2c6170706c69636174696f6e2f786d6c2c6170706c69636174696f6e2f7868746d6c2b786d6c2c746578742f68746d6c3b713d302e392c746578742f706c61696e3b713d302e382c696d6167652f706e672c2a2f2a3b713d302e3500a00200075554462d382c2a00a003000c677a69702c6465666c61746500a004000e656e2d67622c656e3b713d302e3500a006000a6b6565702d616c69766500a00900f95048505345535349443d37626361383232616638333466316465373663633630336366636435313938633b20667041757468436f6f6b69653d433035383430394537393344364245434633324230353234344242303039343230383344443645443533304230454637464137414544413745453231313538333745363033454435364332364446353531383635333335423433374531423637414641343533364345304546323342333642323133374243423932333943363631433131443330393842333938414546334546334146454344423746353842443b204a53455353494f4e49443d7365366331623864663432762e6a657474793300a00b00107777772e777265636b6167652e6f726700000a6b6565702d616c69766500000333303000a00e00654d6f7a696c6c612f352e3020285831313b20553b204c696e7578207838365f36343b20656e2d55533b2072763a312e382e302e3929204765636b6f2f3230303631323035202844656269616e2d312e382e302e392d3129204570697068616e792f322e313400a008000130000600066a657474793300ff";
|
|
||||||
os.write(TypeUtil.fromHexString(packet));
|
|
||||||
os.flush();
|
|
||||||
readResponse(_client);
|
|
||||||
|
|
||||||
assertTrue(true);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void testSSLPacketWithIntegerKeySize() throws Exception
|
|
||||||
{
|
|
||||||
OutputStream os=_client.getOutputStream();
|
|
||||||
|
|
||||||
String packet="1234025002020008485454502f312e3100000f2f746573742f64756d702f696e666f00000e3139322e3136382e3130302e343000ffff000c776562746964652d746573740001bb01000ca00b000c776562746964652d7465737400a00e005a4d6f7a696c6c612f352e30202857696e646f77733b20553b2057696e646f7773204e5420352e313b20656e2d55533b2072763a312e382e312e3129204765636b6f2f32303036313230342046697265666f782f322e302e302e3100a0010063746578742f786d6c2c6170706c69636174696f6e2f786d6c2c6170706c69636174696f6e2f7868746d6c2b786d6c2c746578742f68746d6c3b713d302e392c746578742f706c61696e3b713d302e382c696d6167652f706e672c2a2f2a3b713d302e3500a004000e656e2d75732c656e3b713d302e3500a003000c677a69702c6465666c61746500a002001e49534f2d383835392d312c7574662d383b713d302e372c2a3b713d302e3700000a4b6565702d416c69766500000333303000a006000a6b6565702d616c69766500a00d001a68747470733a2f2f776562746964652d746573742f746573742f00a00900174a53455353494f4e49443d69326c6e307539773573387300000d43616368652d436f6e74726f6c0000096d61782d6167653d3000000c4d61782d466f7277617264730000023130000800124448452d5253412d4145533235362d5348410009004032413037364245323330433238393130383941414132303631344139384441443131314230323132343030374130363642454531363742303941464337383942000b0100ff";
|
|
||||||
os.write(TypeUtil.fromHexString(packet));
|
|
||||||
os.flush();
|
|
||||||
readResponse(_client);
|
|
||||||
|
|
||||||
assertTrue(true);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void testSSLPacketWithStringKeySize() throws Exception
|
|
||||||
{
|
|
||||||
OutputStream os=_client.getOutputStream();
|
|
||||||
|
|
||||||
String packet="1234025002020008485454502f312e3100000f2f746573742f64756d702f696e666f00000e3139322e3136382e3130302e343000ffff000c776562746964652d746573740001bb01000ca00b000c776562746964652d7465737400a00e005a4d6f7a696c6c612f352e30202857696e646f77733b20553b2057696e646f7773204e5420352e313b20656e2d55533b2072763a312e382e312e3129204765636b6f2f32303036313230342046697265666f782f322e302e302e3100a0010063746578742f786d6c2c6170706c69636174696f6e2f786d6c2c6170706c69636174696f6e2f7868746d6c2b786d6c2c746578742f68746d6c3b713d302e392c746578742f706c61696e3b713d302e382c696d6167652f706e672c2a2f2a3b713d302e3500a004000e656e2d75732c656e3b713d302e3500a003000c677a69702c6465666c61746500a002001e49534f2d383835392d312c7574662d383b713d302e372c2a3b713d302e3700000a4b6565702d416c69766500000333303000a006000a6b6565702d616c69766500a00d001a68747470733a2f2f776562746964652d746573742f746573742f00a00900174a53455353494f4e49443d69326c6e307539773573387300000d43616368652d436f6e74726f6c0000096d61782d6167653d3000000c4d61782d466f7277617264730000023130000800124448452d5253412d4145533235362d5348410009004032413037364245323330433238393130383941414132303631344139384441443131314230323132343030374130363642454531363742303941464337383942000b000332353600ff";
|
|
||||||
os.write(TypeUtil.fromHexString(packet));
|
|
||||||
os.flush();
|
|
||||||
readResponse(_client);
|
|
||||||
|
|
||||||
assertTrue(true);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void testPacketWithBody() throws Exception
|
|
||||||
{
|
|
||||||
OutputStream os=_client.getOutputStream();
|
|
||||||
|
|
||||||
os.write(TypeUtil.fromHexString(getTestHeader()));
|
|
||||||
os.write(TypeUtil.fromHexString(getTestShortBody()));
|
|
||||||
os.write(TypeUtil.fromHexString(getTestTinyBody()));
|
|
||||||
|
|
||||||
readResponse(_client);
|
|
||||||
|
|
||||||
assertTrue(true);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void testPacketWithChunkedBody() throws Exception
|
|
||||||
{
|
|
||||||
OutputStream os=_client.getOutputStream();
|
|
||||||
|
|
||||||
String packet="123400ff02040008485454502f312e3100000f2f746573742f64756d702f696e666f0000093132372e302e302e3100ffff00096c6f63616c686f7374000050000007a00e000d4a6176612f312e352e305f313100a00b00096c6f63616c686f737400a0010034746578742f68746d6c2c20696d6167652f6769662c20696d6167652f6a7065672c202a3b20713d2e322c202a2f2a3b20713d2e3200a006000a6b6565702d616c69766500a00700216170706c69636174696f6e2f782d7777772d666f726d2d75726c656e636f6465640000115472616e736665722d456e636f64696e670000076368756e6b656400000c4d61782d466f727761726473000002313000ff";
|
|
||||||
|
|
||||||
os.write(TypeUtil.fromHexString(packet));
|
|
||||||
os.flush();
|
|
||||||
|
|
||||||
os.write(TypeUtil.fromHexString("1234007e007c7468656e616d653d746865253230717569636b25323062726f776e253230666f782532306a756d70732532306f766572253230746f2532307468652532306c617a79253230646f67253230544845253230515549434b25323042524f574e253230464f582532304a554d50532532304f564552253230544f25323054"));
|
|
||||||
os.flush();
|
|
||||||
|
|
||||||
os.write(TypeUtil.fromHexString("12340042004048452532304c415a59253230444f472532302676616c75656f66323d6162636465666768696a6b6c6d6e6f707172737475767778797a31323334353637383930"));
|
|
||||||
os.flush();
|
|
||||||
|
|
||||||
os.write(TypeUtil.fromHexString("123400020000"));
|
|
||||||
os.flush();
|
|
||||||
|
|
||||||
readResponse(_client);
|
|
||||||
assertTrue(true);
|
|
||||||
}
|
|
||||||
|
|
||||||
private String getTestHeader()
|
|
||||||
{
|
|
||||||
StringBuffer header=new StringBuffer("");
|
|
||||||
header.append("1234026902040008485454502f31");
|
|
||||||
header.append("2e310000162f61646d696e2f496d6167");
|
|
||||||
header.append("6555706c6f61642e68746d00000a3130");
|
|
||||||
header.append("2e34382e31302e3100ffff000a31302e");
|
|
||||||
header.append("34382e31302e3200005000000da00b00");
|
|
||||||
header.append("0a31302e34382e31302e3200a00e005a");
|
|
||||||
header.append("4d6f7a696c6c612f352e30202857696e");
|
|
||||||
header.append("646f77733b20553b2057696e646f7773");
|
|
||||||
header.append("204e5420352e313b20656e2d55533b20");
|
|
||||||
header.append("72763a312e382e312e3129204765636b");
|
|
||||||
header.append("6f2f3230303631323034204669726566");
|
|
||||||
header.append("6f782f322e302e302e3100a001006374");
|
|
||||||
header.append("6578742f786d6c2c6170706c69636174");
|
|
||||||
header.append("696f6e2f786d6c2c6170706c69636174");
|
|
||||||
header.append("696f6e2f7868746d6c2b786d6c2c7465");
|
|
||||||
header.append("78742f68746d6c3b713d302e392c7465");
|
|
||||||
header.append("78742f706c61696e3b713d302e382c69");
|
|
||||||
header.append("6d6167652f706e672c2a2f2a3b713d30");
|
|
||||||
header.append("2e3500a004000e656e2d75732c656e3b");
|
|
||||||
header.append("713d302e3500a003000c677a69702c64");
|
|
||||||
header.append("65666c61746500a002001e49534f2d38");
|
|
||||||
header.append("3835392d312c7574662d383b713d302e");
|
|
||||||
header.append("372c2a3b713d302e3700000a4b656570");
|
|
||||||
header.append("2d416c69766500000333303000a00600");
|
|
||||||
header.append("0a6b6565702d616c69766500a00d003f");
|
|
||||||
header.append("687474703a2f2f31302e34382e31302e");
|
|
||||||
header.append("322f61646d696e2f496d61676555706c");
|
|
||||||
header.append("6f61642e68746d3f6964303d4974656d");
|
|
||||||
header.append("266964313d32266964323d696d673200");
|
|
||||||
header.append("a00900174a53455353494f4e49443d75");
|
|
||||||
header.append("383977733070696168746d00a0070046");
|
|
||||||
header.append("6d756c7469706172742f666f726d2d64");
|
|
||||||
header.append("6174613b20626f756e646172793d2d2d");
|
|
||||||
header.append("2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d");
|
|
||||||
header.append("2d2d2d2d2d2d2d2d2d39343338333235");
|
|
||||||
header.append("34323630383700a00800033735390000");
|
|
||||||
header.append("0c4d61782d466f727761726473000002");
|
|
||||||
header.append("3130000500176964303d4974656d2669");
|
|
||||||
header.append("64313d32266964323d696d673200ff");
|
|
||||||
|
|
||||||
return header.toString();
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
private String getTestShortBody()
|
|
||||||
{
|
|
||||||
StringBuffer body=new StringBuffer("");
|
|
||||||
|
|
||||||
body.append("123402f702f52d2d2d2d2d2d2d2d");
|
|
||||||
body.append("2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d");
|
|
||||||
body.append("2d2d2d2d2d3934333833323534323630");
|
|
||||||
body.append("38370d0a436f6e74656e742d44697370");
|
|
||||||
body.append("6f736974696f6e3a20666f726d2d6461");
|
|
||||||
body.append("74613b206e616d653d227265636f7264");
|
|
||||||
body.append("4964220d0a0d0a320d0a2d2d2d2d2d2d");
|
|
||||||
body.append("2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d");
|
|
||||||
body.append("2d2d2d2d2d2d2d393433383332353432");
|
|
||||||
body.append("363038370d0a436f6e74656e742d4469");
|
|
||||||
body.append("73706f736974696f6e3a20666f726d2d");
|
|
||||||
body.append("646174613b206e616d653d226e616d65");
|
|
||||||
body.append("220d0a0d0a4974656d0d0a2d2d2d2d2d");
|
|
||||||
body.append("2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d");
|
|
||||||
body.append("2d2d2d2d2d2d2d2d3934333833323534");
|
|
||||||
body.append("32363038370d0a436f6e74656e742d44");
|
|
||||||
body.append("6973706f736974696f6e3a20666f726d");
|
|
||||||
body.append("2d646174613b206e616d653d22746e49");
|
|
||||||
body.append("6d674964220d0a0d0a696d67320d0a2d");
|
|
||||||
body.append("2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d");
|
|
||||||
body.append("2d2d2d2d2d2d2d2d2d2d2d2d39343338");
|
|
||||||
body.append("3332353432363038370d0a436f6e7465");
|
|
||||||
body.append("6e742d446973706f736974696f6e3a20");
|
|
||||||
body.append("666f726d2d646174613b206e616d653d");
|
|
||||||
body.append("227468756d624e61696c496d61676546");
|
|
||||||
body.append("696c65223b2066696c656e616d653d22");
|
|
||||||
body.append("6161612e747874220d0a436f6e74656e");
|
|
||||||
body.append("742d547970653a20746578742f706c61");
|
|
||||||
body.append("696e0d0a0d0a61616161616161616161");
|
|
||||||
body.append("61616161616161616161616161616161");
|
|
||||||
body.append("61616161616161616161616161616161");
|
|
||||||
body.append("61616161616161616161616161616161");
|
|
||||||
body.append("0d0a2d2d2d2d2d2d2d2d2d2d2d2d2d2d");
|
|
||||||
body.append("2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d39");
|
|
||||||
body.append("3433383332353432363038370d0a436f");
|
|
||||||
body.append("6e74656e742d446973706f736974696f");
|
|
||||||
body.append("6e3a20666f726d2d646174613b206e61");
|
|
||||||
body.append("6d653d226c61726765496d6167654669");
|
|
||||||
body.append("6c65223b2066696c656e616d653d2261");
|
|
||||||
body.append("61612e747874220d0a436f6e74656e74");
|
|
||||||
body.append("2d547970653a20746578742f706c6169");
|
|
||||||
body.append("6e0d0a0d0a6161616161616161616161");
|
|
||||||
body.append("61616161616161616161616161616161");
|
|
||||||
body.append("61616161616161616161616161616161");
|
|
||||||
body.append("6161616161616161616161616161610d");
|
|
||||||
body.append("0a2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d");
|
|
||||||
body.append("2d2d2d2d2d2d2d2d2d2d2d2d2d2d3934");
|
|
||||||
body.append("33383332353432363038372d2d");
|
|
||||||
|
|
||||||
return body.toString();
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
private String getTestTinyBody()
|
|
||||||
{
|
|
||||||
StringBuffer body = new StringBuffer("");
|
|
||||||
|
|
||||||
body.append("123400042d2d0d0a");
|
|
||||||
|
|
||||||
return body.toString();
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
// TODO: char array instead of string?
|
|
||||||
private String readResponse(Socket _client) throws IOException
|
|
||||||
{
|
|
||||||
ByteArrayOutputStream bout = new ByteArrayOutputStream();
|
|
||||||
|
|
||||||
try
|
|
||||||
{
|
|
||||||
IO.copy(_client.getInputStream(),bout);
|
|
||||||
}
|
|
||||||
catch(SocketTimeoutException e)
|
|
||||||
{
|
|
||||||
LOG.ignore(e);
|
|
||||||
}
|
|
||||||
return bout.toString("utf-8");
|
|
||||||
}
|
|
||||||
|
|
||||||
public static class Handler extends AbstractHandler
|
|
||||||
{
|
|
||||||
public void handle(String target, Request baseRequest, HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException
|
|
||||||
{
|
|
||||||
baseRequest.setHandled(true);
|
|
||||||
response.setStatus(HttpServletResponse.SC_OK);
|
|
||||||
response.setContentType("text/plain");
|
|
||||||
response.getWriter().println("success");
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
|
@ -1,608 +0,0 @@
|
||||||
//
|
|
||||||
// ========================================================================
|
|
||||||
// Copyright (c) 1995-2012 Mort Bay Consulting Pty. Ltd.
|
|
||||||
// ------------------------------------------------------------------------
|
|
||||||
// All rights reserved. This program and the accompanying materials
|
|
||||||
// are made available under the terms of the Eclipse Public License v1.0
|
|
||||||
// and Apache License v2.0 which accompanies this distribution.
|
|
||||||
//
|
|
||||||
// The Eclipse Public License is available at
|
|
||||||
// http://www.eclipse.org/legal/epl-v10.html
|
|
||||||
//
|
|
||||||
// The Apache License v2.0 is available at
|
|
||||||
// http://www.opensource.org/licenses/apache2.0.php
|
|
||||||
//
|
|
||||||
// You may elect to redistribute this code under either of these licenses.
|
|
||||||
// ========================================================================
|
|
||||||
//
|
|
||||||
|
|
||||||
package org.eclipse.jetty.ajp;
|
|
||||||
|
|
||||||
import static junit.framework.Assert.assertEquals;
|
|
||||||
import static org.junit.Assert.assertTrue;
|
|
||||||
|
|
||||||
import java.io.IOException;
|
|
||||||
|
|
||||||
import org.eclipse.jetty.io.Buffer;
|
|
||||||
import org.eclipse.jetty.io.ByteArrayBuffer;
|
|
||||||
import org.eclipse.jetty.io.ByteArrayEndPoint;
|
|
||||||
import org.eclipse.jetty.io.EndPoint;
|
|
||||||
import org.eclipse.jetty.io.SimpleBuffers;
|
|
||||||
import org.eclipse.jetty.util.TypeUtil;
|
|
||||||
import org.junit.Test;
|
|
||||||
|
|
||||||
public class TestAjpParser
|
|
||||||
{
|
|
||||||
@Test
|
|
||||||
public void testPacket1() throws Exception
|
|
||||||
{
|
|
||||||
String packet = "123401070202000f77696474683d20485454502f312e300000122f636f6e74726f6c2f70726f647563742f2200000e3230382e32372e3230332e31323800ffff000c7777772e756c74612e636f6d000050000005a006000a6b6565702d616c69766500a00b000c7777772e756c74612e636f6d00a00e002b4d6f7a696c6c612f342e302028636f6d70617469626c653b20426f726465724d616e6167657220332e302900a0010043696d6167652f6769662c20696d6167652f782d786269746d61702c20696d6167652f6a7065672c20696d6167652f706a7065672c20696d6167652f706d672c202a2f2a00a008000130000600067570726f64310008000a4145533235362d53484100ff";
|
|
||||||
byte[] src = TypeUtil.fromHexString(packet);
|
|
||||||
|
|
||||||
ByteArrayBuffer buffer= new ByteArrayBuffer(Ajp13Packet.MAX_PACKET_SIZE);
|
|
||||||
SimpleBuffers buffers=new SimpleBuffers(buffer,null);
|
|
||||||
|
|
||||||
EndPoint endp = new ByteArrayEndPoint(src,Ajp13Packet.MAX_PACKET_SIZE);
|
|
||||||
|
|
||||||
Ajp13Parser parser = new Ajp13Parser(buffers,endp);
|
|
||||||
parser.setEventHandler(new EH());
|
|
||||||
parser.setGenerator(new Ajp13Generator(buffers,endp));
|
|
||||||
|
|
||||||
parser.parseAvailable();
|
|
||||||
|
|
||||||
assertTrue(true);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void testPacket2() throws Exception
|
|
||||||
{
|
|
||||||
String packet="1234020102020008485454502f312e3100000f2f6363632d7777777777772f61616100000c38382e3838382e38382e383830ffff00116363632e6363636363636363632e636f6d0001bb010009a00b00116363632e6363636363636363632e636f6d00a00e005a4d6f7a696c6c612f352e30202857696e646f77733b20553b2057696e646f7773204e5420352e313b20656e2d55533b2072763a312e382e312e3129204765636b6f2f32303036313230342046697265666f782f322e302e302e3100a0010063746578742f786d6c2c6170706c69636174696f6e2f786d6c2c6170706c69636174696f6e2f7868746d6c2b786d6c2c746578742f68746d6c3b713d302e392c746578742f706c61696e3b713d302e382c696d6167652f706e672c2a2f2a3b713d302e3500a004000e656e2d75732c656e3b713d302e3500a003000c677a69702c6465666c61746500a002001e49534f2d383835392d312c7574662d383b713d302e372c2a3b713d302e3700000a4b6565702d416c69766500000333303000a006000a6b6565702d616c69766500000c4d61782d466f7277617264730000023130000800124448452d5253412d4145533235362d5348410009004039324643303544413043444141443232303137413743443141453939353132413330443938363838423843433041454643364231363035323543433232353341000b0100ff";
|
|
||||||
byte[] src=TypeUtil.fromHexString(packet);
|
|
||||||
ByteArrayBuffer buffer=new ByteArrayBuffer(Ajp13Packet.MAX_PACKET_SIZE);
|
|
||||||
SimpleBuffers buffers=new SimpleBuffers(buffer,null);
|
|
||||||
EndPoint endp=new ByteArrayEndPoint(src,Ajp13Packet.MAX_PACKET_SIZE);
|
|
||||||
Ajp13Parser parser = new Ajp13Parser(buffers,endp);
|
|
||||||
parser.setEventHandler(new EH());
|
|
||||||
parser.setGenerator(new Ajp13Generator(buffers,endp));
|
|
||||||
parser.parse();
|
|
||||||
assertTrue(true);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void testPacket3() throws Exception
|
|
||||||
{
|
|
||||||
String packet="1234028f02020008485454502f312e3100000d2f666f726d746573742e6a737000000d3139322e3136382e342e31383000ffff00107777772e777265636b6167652e6f726700005000000aa0010063746578742f786d6c2c6170706c69636174696f6e2f786d6c2c6170706c69636174696f6e2f7868746d6c2b786d6c2c746578742f68746d6c3b713d302e392c746578742f706c61696e3b713d302e382c696d6167652f706e672c2a2f2a3b713d302e3500a00200075554462d382c2a00a003000c677a69702c6465666c61746500a004000e656e2d67622c656e3b713d302e3500a006000a6b6565702d616c69766500a00900f95048505345535349443d37626361383232616638333466316465373663633630336366636435313938633b20667041757468436f6f6b69653d433035383430394537393344364245434633324230353234344242303039343230383344443645443533304230454637464137414544413745453231313538333745363033454435364332364446353531383635333335423433374531423637414641343533364345304546323342333642323133374243423932333943363631433131443330393842333938414546334546334146454344423746353842443b204a53455353494f4e49443d7365366331623864663432762e6a657474793300a00b00107777772e777265636b6167652e6f726700000a6b6565702d616c69766500000333303000a00e00654d6f7a696c6c612f352e3020285831313b20553b204c696e7578207838365f36343b20656e2d55533b2072763a312e382e302e3929204765636b6f2f3230303631323035202844656269616e2d312e382e302e392d3129204570697068616e792f322e313400a008000130000600066a657474793300ff";
|
|
||||||
byte[] src=TypeUtil.fromHexString(packet);
|
|
||||||
ByteArrayBuffer buffer=new ByteArrayBuffer(Ajp13Packet.MAX_PACKET_SIZE);
|
|
||||||
SimpleBuffers buffers=new SimpleBuffers(buffer,null);
|
|
||||||
EndPoint endp=new ByteArrayEndPoint(src,Ajp13Packet.MAX_PACKET_SIZE);
|
|
||||||
Ajp13Parser parser = new Ajp13Parser(buffers,endp);
|
|
||||||
parser.setEventHandler(new EH());
|
|
||||||
parser.setGenerator(new Ajp13Generator(buffers,endp));
|
|
||||||
parser.parse();
|
|
||||||
assertTrue(true);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void testSSLPacketWithIntegerKeySize() throws Exception
|
|
||||||
{
|
|
||||||
String packet = "1234025002020008485454502f312e3100000f2f746573742f64756d702f696e666f00000e3139322e3136382e3130302e343000ffff000c776562746964652d746573740001bb01000ca00b000c776562746964652d7465737400a00e005a4d6f7a696c6c612f352e30202857696e646f77733b20553b2057696e646f7773204e5420352e313b20656e2d55533b2072763a312e382e312e3129204765636b6f2f32303036313230342046697265666f782f322e302e302e3100a0010063746578742f786d6c2c6170706c69636174696f6e2f786d6c2c6170706c69636174696f6e2f7868746d6c2b786d6c2c746578742f68746d6c3b713d302e392c746578742f706c61696e3b713d302e382c696d6167652f706e672c2a2f2a3b713d302e3500a004000e656e2d75732c656e3b713d302e3500a003000c677a69702c6465666c61746500a002001e49534f2d383835392d312c7574662d383b713d302e372c2a3b713d302e3700000a4b6565702d416c69766500000333303000a006000a6b6565702d616c69766500a00d001a68747470733a2f2f776562746964652d746573742f746573742f00a00900174a53455353494f4e49443d69326c6e307539773573387300000d43616368652d436f6e74726f6c0000096d61782d6167653d3000000c4d61782d466f7277617264730000023130000800124448452d5253412d4145533235362d5348410009004032413037364245323330433238393130383941414132303631344139384441443131314230323132343030374130363642454531363742303941464337383942000b0100ff";
|
|
||||||
byte[] src = TypeUtil.fromHexString(packet);
|
|
||||||
|
|
||||||
ByteArrayBuffer buffer= new ByteArrayBuffer(Ajp13Packet.MAX_PACKET_SIZE);
|
|
||||||
SimpleBuffers buffers=new SimpleBuffers(buffer,null);
|
|
||||||
|
|
||||||
EndPoint endp = new ByteArrayEndPoint(src,Ajp13Packet.MAX_PACKET_SIZE);
|
|
||||||
|
|
||||||
Ajp13Parser parser = new Ajp13Parser(buffers,endp);
|
|
||||||
parser.setEventHandler(new EH());
|
|
||||||
parser.setGenerator(new Ajp13Generator(buffers,endp));
|
|
||||||
|
|
||||||
parser.parseAvailable();
|
|
||||||
|
|
||||||
assertTrue(true);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void testSSLPacketWithStringKeySize() throws Exception
|
|
||||||
{
|
|
||||||
String packet = "1234025002020008485454502f312e3100000f2f746573742f64756d702f696e666f00000e3139322e3136382e3130302e343000ffff000c776562746964652d746573740001bb01000ca00b000c776562746964652d7465737400a00e005a4d6f7a696c6c612f352e30202857696e646f77733b20553b2057696e646f7773204e5420352e313b20656e2d55533b2072763a312e382e312e3129204765636b6f2f32303036313230342046697265666f782f322e302e302e3100a0010063746578742f786d6c2c6170706c69636174696f6e2f786d6c2c6170706c69636174696f6e2f7868746d6c2b786d6c2c746578742f68746d6c3b713d302e392c746578742f706c61696e3b713d302e382c696d6167652f706e672c2a2f2a3b713d302e3500a004000e656e2d75732c656e3b713d302e3500a003000c677a69702c6465666c61746500a002001e49534f2d383835392d312c7574662d383b713d302e372c2a3b713d302e3700000a4b6565702d416c69766500000333303000a006000a6b6565702d616c69766500a00d001a68747470733a2f2f776562746964652d746573742f746573742f00a00900174a53455353494f4e49443d69326c6e307539773573387300000d43616368652d436f6e74726f6c0000096d61782d6167653d3000000c4d61782d466f7277617264730000023130000800124448452d5253412d4145533235362d5348410009004032413037364245323330433238393130383941414132303631344139384441443131314230323132343030374130363642454531363742303941464337383942000b000332353600ff";
|
|
||||||
byte[] src = TypeUtil.fromHexString(packet);
|
|
||||||
|
|
||||||
ByteArrayBuffer buffer= new ByteArrayBuffer(Ajp13Packet.MAX_PACKET_SIZE);
|
|
||||||
SimpleBuffers buffers=new SimpleBuffers(buffer,null);
|
|
||||||
|
|
||||||
EndPoint endp = new ByteArrayEndPoint(src,Ajp13Packet.MAX_PACKET_SIZE);
|
|
||||||
|
|
||||||
Ajp13Parser parser = new Ajp13Parser(buffers,endp);
|
|
||||||
parser.setEventHandler(new EH());
|
|
||||||
parser.setGenerator(new Ajp13Generator(buffers,endp));
|
|
||||||
|
|
||||||
parser.parseAvailable();
|
|
||||||
|
|
||||||
assertTrue(true);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void testSSLPacketFragment() throws Exception
|
|
||||||
{
|
|
||||||
String packet = "1234025002020008485454502f312e3100000f2f746573742f64756d702f696e666f00000e3139322e3136382e3130302e343000ffff000c776562746964652d746573740001bb01000ca00b000c776562746964652d7465737400a00e005a4d6f7a696c6c612f352e30202857696e646f77733b20553b2057696e646f7773204e5420352e313b20656e2d55533b2072763a312e382e312e3129204765636b6f2f32303036313230342046697265666f782f322e302e302e3100a0010063746578742f786d6c2c6170706c69636174696f6e2f786d6c2c6170706c69636174696f6e2f7868746d6c2b786d6c2c746578742f68746d6c3b713d302e392c746578742f706c61696e3b713d302e382c696d6167652f706e672c2a2f2a3b713d302e3500a004000e656e2d75732c656e3b713d302e3500a003000c677a69702c6465666c61746500a002001e49534f2d383835392d312c7574662d383b713d302e372c2a3b713d302e3700000a4b6565702d416c69766500000333303000a006000a6b6565702d616c69766500a00d001a68747470733a2f2f776562746964652d746573742f746573742f00a00900174a53455353494f4e49443d69326c6e307539773573387300000d43616368652d436f6e74726f6c0000096d61782d6167653d3000000c4d61782d466f7277617264730000023130000800124448452d5253412d4145533235362d5348410009004032413037364245323330433238393130383941414132303631344139384441443131314230323132343030374130363642454531363742303941464337383942000b0100ff";
|
|
||||||
byte[] src = TypeUtil.fromHexString(packet);
|
|
||||||
|
|
||||||
for (int f=1;f<src.length;f++)
|
|
||||||
{
|
|
||||||
byte[] frag0=new byte[src.length-f];
|
|
||||||
byte[] frag1=new byte[f];
|
|
||||||
|
|
||||||
System.arraycopy(src,0,frag0,0,src.length-f);
|
|
||||||
System.arraycopy(src,src.length-f,frag1,0,f);
|
|
||||||
|
|
||||||
ByteArrayBuffer buffer= new ByteArrayBuffer(Ajp13Packet.MAX_PACKET_SIZE);
|
|
||||||
SimpleBuffers buffers=new SimpleBuffers(buffer,null);
|
|
||||||
|
|
||||||
ByteArrayEndPoint endp = new ByteArrayEndPoint(frag0,Ajp13Packet.MAX_PACKET_SIZE);
|
|
||||||
endp.setNonBlocking(true);
|
|
||||||
|
|
||||||
Ajp13Parser parser = new Ajp13Parser(buffers,endp);
|
|
||||||
parser.setEventHandler(new EH());
|
|
||||||
parser.setGenerator(new Ajp13Generator(buffers,endp));
|
|
||||||
parser.parseNext();
|
|
||||||
|
|
||||||
endp.setIn(new ByteArrayBuffer(frag1));
|
|
||||||
parser.parseAvailable();
|
|
||||||
}
|
|
||||||
|
|
||||||
assertTrue(true);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void testPacketWithBody() throws Exception
|
|
||||||
{
|
|
||||||
String packet=getTestHeader();
|
|
||||||
byte[] src=TypeUtil.fromHexString(packet);
|
|
||||||
ByteArrayBuffer buffer=new ByteArrayBuffer(Ajp13Packet.MAX_PACKET_SIZE);
|
|
||||||
SimpleBuffers buffers=new SimpleBuffers(buffer,null);
|
|
||||||
ByteArrayEndPoint endp=new ByteArrayEndPoint(src,Ajp13Packet.MAX_PACKET_SIZE);
|
|
||||||
endp.setNonBlocking(true);
|
|
||||||
|
|
||||||
final int count[]={0};
|
|
||||||
Ajp13Generator gen = new Ajp13Generator(buffers,endp)
|
|
||||||
{
|
|
||||||
public void getBodyChunk() throws IOException
|
|
||||||
{
|
|
||||||
count[0]++;
|
|
||||||
super.getBodyChunk();
|
|
||||||
}
|
|
||||||
};
|
|
||||||
Ajp13Parser parser = new Ajp13Parser(buffers,endp);
|
|
||||||
parser.setEventHandler(new EH());
|
|
||||||
parser.setGenerator(gen);
|
|
||||||
|
|
||||||
parser.parseNext();
|
|
||||||
assertEquals(1,parser.getState());
|
|
||||||
assertEquals(0,count[0]);
|
|
||||||
|
|
||||||
endp.setIn(new ByteArrayBuffer(TypeUtil.fromHexString(getTestShortBody())));
|
|
||||||
|
|
||||||
parser.parseNext();
|
|
||||||
assertEquals(1,parser.getState());
|
|
||||||
assertEquals(1,count[0]);
|
|
||||||
|
|
||||||
endp.setIn(new ByteArrayBuffer(TypeUtil.fromHexString(getTestTinyBody())));
|
|
||||||
|
|
||||||
parser.parseNext();
|
|
||||||
parser.parseNext();
|
|
||||||
assertEquals(0,parser.getState());
|
|
||||||
assertEquals(1,count[0]);
|
|
||||||
|
|
||||||
assertTrue(true);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void testPacketWithChunkedBody() throws Exception
|
|
||||||
{
|
|
||||||
String packet="123400ff02040008485454502f312e3100000f2f746573742f64756d702f696e666f0000093132372e302e302e3100ffff00096c6f63616c686f7374000050000007a00e000d4a6176612f312e352e305f313100a00b00096c6f63616c686f737400a0010034746578742f68746d6c2c20696d6167652f6769662c20696d6167652f6a7065672c202a3b20713d2e322c202a2f2a3b20713d2e3200a006000a6b6565702d616c69766500a00700216170706c69636174696f6e2f782d7777772d666f726d2d75726c656e636f6465640000115472616e736665722d456e636f64696e670000076368756e6b656400000c4d61782d466f727761726473000002313000ff";
|
|
||||||
byte[] src=TypeUtil.fromHexString(packet);
|
|
||||||
ByteArrayBuffer buffer=new ByteArrayBuffer(Ajp13Packet.MAX_PACKET_SIZE);
|
|
||||||
SimpleBuffers buffers=new SimpleBuffers(buffer,null);
|
|
||||||
ByteArrayEndPoint endp=new ByteArrayEndPoint(src,Ajp13Packet.MAX_PACKET_SIZE);
|
|
||||||
endp.setNonBlocking(true);
|
|
||||||
|
|
||||||
final int count[]={0};
|
|
||||||
Ajp13Generator gen = new Ajp13Generator(buffers,endp)
|
|
||||||
{
|
|
||||||
public void getBodyChunk() throws IOException
|
|
||||||
{
|
|
||||||
count[0]++;
|
|
||||||
super.getBodyChunk();
|
|
||||||
}
|
|
||||||
};
|
|
||||||
Ajp13Parser parser = new Ajp13Parser(buffers,endp);
|
|
||||||
parser.setEventHandler(new EH());
|
|
||||||
parser.setGenerator(gen);
|
|
||||||
|
|
||||||
parser.parseNext();
|
|
||||||
assertEquals(1,parser.getState());
|
|
||||||
assertEquals(1,count[0]);
|
|
||||||
|
|
||||||
endp.setIn(new ByteArrayBuffer(TypeUtil.fromHexString("1234007e007c7468656e616d653d746865253230717569636b25323062726f776e253230666f782532306a756d70732532306f766572253230746f2532307468652532306c617a79253230646f67253230544845253230515549434b25323042524f574e253230464f582532304a554d50532532304f564552253230544f25323054")));
|
|
||||||
|
|
||||||
while (parser.parseNext()>0);
|
|
||||||
assertEquals(1,parser.getState());
|
|
||||||
assertEquals(2,count[0]);
|
|
||||||
|
|
||||||
endp.setIn(new ByteArrayBuffer(TypeUtil.fromHexString("12340042004048452532304c415a59253230444f472532302676616c75656f66323d6162636465666768696a6b6c6d6e6f707172737475767778797a31323334353637383930")));
|
|
||||||
|
|
||||||
while (parser.parseNext()>0);
|
|
||||||
assertEquals(1,parser.getState());
|
|
||||||
assertEquals(3,count[0]);
|
|
||||||
|
|
||||||
endp.setIn(new ByteArrayBuffer(TypeUtil.fromHexString("123400020000")));
|
|
||||||
|
|
||||||
while (parser.getState()!=0 && parser.parseNext()>0);
|
|
||||||
assertEquals(0,parser.getState());
|
|
||||||
assertEquals(3,count[0]);
|
|
||||||
|
|
||||||
assertTrue(true);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void testPacketFragment() throws Exception
|
|
||||||
{
|
|
||||||
String packet = "123401070202000f77696474683d20485454502f312e300000122f636f6e74726f6c2f70726f647563742f2200000e3230382e32372e3230332e31323800ffff000c7777772e756c74612e636f6d000050000005a006000a6b6565702d616c69766500a00b000c7777772e756c74612e636f6d00a00e002b4d6f7a696c6c612f342e302028636f6d70617469626c653b20426f726465724d616e6167657220332e302900a0010043696d6167652f6769662c20696d6167652f782d786269746d61702c20696d6167652f6a7065672c20696d6167652f706a7065672c20696d6167652f706d672c202a2f2a00a008000130000600067570726f64310008000a4145533235362d53484100ff";
|
|
||||||
byte[] src = TypeUtil.fromHexString(packet);
|
|
||||||
|
|
||||||
for (int f=1;f<src.length;f++)
|
|
||||||
{
|
|
||||||
byte[] frag0=new byte[src.length-f];
|
|
||||||
byte[] frag1=new byte[f];
|
|
||||||
|
|
||||||
System.arraycopy(src,0,frag0,0,src.length-f);
|
|
||||||
System.arraycopy(src,src.length-f,frag1,0,f);
|
|
||||||
|
|
||||||
ByteArrayBuffer buffer= new ByteArrayBuffer(Ajp13Packet.MAX_PACKET_SIZE);
|
|
||||||
SimpleBuffers buffers=new SimpleBuffers(buffer,null);
|
|
||||||
|
|
||||||
ByteArrayEndPoint endp = new ByteArrayEndPoint(frag0,Ajp13Packet.MAX_PACKET_SIZE);
|
|
||||||
endp.setNonBlocking(true);
|
|
||||||
|
|
||||||
Ajp13Parser parser = new Ajp13Parser(buffers,endp);
|
|
||||||
parser.setEventHandler(new EH());
|
|
||||||
parser.setGenerator(new Ajp13Generator(buffers,endp));
|
|
||||||
parser.parseNext();
|
|
||||||
|
|
||||||
endp.setIn(new ByteArrayBuffer(frag1));
|
|
||||||
parser.parseAvailable();
|
|
||||||
}
|
|
||||||
|
|
||||||
assertTrue(true);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void testPacketFragmentWithBody() throws Exception
|
|
||||||
{
|
|
||||||
String packet = getTestHeader()+getTestBody();
|
|
||||||
byte[] src = TypeUtil.fromHexString(packet);
|
|
||||||
|
|
||||||
for (int f=1;f<src.length;f++)
|
|
||||||
{
|
|
||||||
byte[] frag0=new byte[src.length-f];
|
|
||||||
byte[] frag1=new byte[f];
|
|
||||||
|
|
||||||
System.arraycopy(src,0,frag0,0,src.length-f);
|
|
||||||
System.arraycopy(src,src.length-f,frag1,0,f);
|
|
||||||
|
|
||||||
ByteArrayBuffer buffer= new ByteArrayBuffer(Ajp13Packet.MAX_PACKET_SIZE);
|
|
||||||
SimpleBuffers buffers=new SimpleBuffers(buffer,null);
|
|
||||||
|
|
||||||
ByteArrayEndPoint endp = new ByteArrayEndPoint(frag0,Ajp13Packet.MAX_PACKET_SIZE);
|
|
||||||
endp.setNonBlocking(true);
|
|
||||||
|
|
||||||
Ajp13Parser parser = new Ajp13Parser(buffers,endp);
|
|
||||||
parser.setEventHandler(new EH());
|
|
||||||
parser.setGenerator(new Ajp13Generator(buffers,endp));
|
|
||||||
parser.parseNext();
|
|
||||||
|
|
||||||
endp.setIn(new ByteArrayBuffer(frag1));
|
|
||||||
parser.parseAvailable();
|
|
||||||
}
|
|
||||||
|
|
||||||
assertTrue(true);
|
|
||||||
}
|
|
||||||
|
|
||||||
private String getTestHeader()
|
|
||||||
{
|
|
||||||
StringBuffer header = new StringBuffer("");
|
|
||||||
|
|
||||||
header.append("1234026902040008485454502f31");
|
|
||||||
header.append("2e310000162f61646d696e2f496d6167");
|
|
||||||
header.append("6555706c6f61642e68746d00000a3130");
|
|
||||||
header.append("2e34382e31302e3100ffff000a31302e");
|
|
||||||
header.append("34382e31302e3200005000000da00b00");
|
|
||||||
header.append("0a31302e34382e31302e3200a00e005a");
|
|
||||||
header.append("4d6f7a696c6c612f352e30202857696e");
|
|
||||||
header.append("646f77733b20553b2057696e646f7773");
|
|
||||||
header.append("204e5420352e313b20656e2d55533b20");
|
|
||||||
header.append("72763a312e382e312e3129204765636b");
|
|
||||||
header.append("6f2f3230303631323034204669726566");
|
|
||||||
header.append("6f782f322e302e302e3100a001006374");
|
|
||||||
header.append("6578742f786d6c2c6170706c69636174");
|
|
||||||
header.append("696f6e2f786d6c2c6170706c69636174");
|
|
||||||
header.append("696f6e2f7868746d6c2b786d6c2c7465");
|
|
||||||
header.append("78742f68746d6c3b713d302e392c7465");
|
|
||||||
header.append("78742f706c61696e3b713d302e382c69");
|
|
||||||
header.append("6d6167652f706e672c2a2f2a3b713d30");
|
|
||||||
header.append("2e3500a004000e656e2d75732c656e3b");
|
|
||||||
header.append("713d302e3500a003000c677a69702c64");
|
|
||||||
header.append("65666c61746500a002001e49534f2d38");
|
|
||||||
header.append("3835392d312c7574662d383b713d302e");
|
|
||||||
header.append("372c2a3b713d302e3700000a4b656570");
|
|
||||||
header.append("2d416c69766500000333303000a00600");
|
|
||||||
header.append("0a6b6565702d616c69766500a00d003f");
|
|
||||||
header.append("687474703a2f2f31302e34382e31302e");
|
|
||||||
header.append("322f61646d696e2f496d61676555706c");
|
|
||||||
header.append("6f61642e68746d3f6964303d4974656d");
|
|
||||||
header.append("266964313d32266964323d696d673200");
|
|
||||||
header.append("a00900174a53455353494f4e49443d75");
|
|
||||||
header.append("383977733070696168746d00a0070046");
|
|
||||||
header.append("6d756c7469706172742f666f726d2d64");
|
|
||||||
header.append("6174613b20626f756e646172793d2d2d");
|
|
||||||
header.append("2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d");
|
|
||||||
header.append("2d2d2d2d2d2d2d2d2d39343338333235");
|
|
||||||
header.append("34323630383700a00800033735390000");
|
|
||||||
header.append("0c4d61782d466f727761726473000002");
|
|
||||||
header.append("3130000500176964303d4974656d2669");
|
|
||||||
header.append("64313d32266964323d696d673200ff");
|
|
||||||
|
|
||||||
return header.toString();
|
|
||||||
}
|
|
||||||
|
|
||||||
private String getTestBody()
|
|
||||||
{
|
|
||||||
StringBuffer body = new StringBuffer("");
|
|
||||||
|
|
||||||
body.append("123402f902f72d2d2d2d2d2d2d2d");
|
|
||||||
body.append("2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d");
|
|
||||||
body.append("2d2d2d2d2d3934333833323534323630");
|
|
||||||
body.append("38370d0a436f6e74656e742d44697370");
|
|
||||||
body.append("6f736974696f6e3a20666f726d2d6461");
|
|
||||||
body.append("74613b206e616d653d227265636f7264");
|
|
||||||
body.append("4964220d0a0d0a320d0a2d2d2d2d2d2d");
|
|
||||||
body.append("2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d");
|
|
||||||
body.append("2d2d2d2d2d2d2d393433383332353432");
|
|
||||||
body.append("363038370d0a436f6e74656e742d4469");
|
|
||||||
body.append("73706f736974696f6e3a20666f726d2d");
|
|
||||||
body.append("646174613b206e616d653d226e616d65");
|
|
||||||
body.append("220d0a0d0a4974656d0d0a2d2d2d2d2d");
|
|
||||||
body.append("2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d");
|
|
||||||
body.append("2d2d2d2d2d2d2d2d3934333833323534");
|
|
||||||
body.append("32363038370d0a436f6e74656e742d44");
|
|
||||||
body.append("6973706f736974696f6e3a20666f726d");
|
|
||||||
body.append("2d646174613b206e616d653d22746e49");
|
|
||||||
body.append("6d674964220d0a0d0a696d67320d0a2d");
|
|
||||||
body.append("2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d");
|
|
||||||
body.append("2d2d2d2d2d2d2d2d2d2d2d2d39343338");
|
|
||||||
body.append("3332353432363038370d0a436f6e7465");
|
|
||||||
body.append("6e742d446973706f736974696f6e3a20");
|
|
||||||
body.append("666f726d2d646174613b206e616d653d");
|
|
||||||
body.append("227468756d624e61696c496d61676546");
|
|
||||||
body.append("696c65223b2066696c656e616d653d22");
|
|
||||||
body.append("6161612e747874220d0a436f6e74656e");
|
|
||||||
body.append("742d547970653a20746578742f706c61");
|
|
||||||
body.append("696e0d0a0d0a61616161616161616161");
|
|
||||||
body.append("61616161616161616161616161616161");
|
|
||||||
body.append("61616161616161616161616161616161");
|
|
||||||
body.append("61616161616161616161616161616161");
|
|
||||||
body.append("0d0a2d2d2d2d2d2d2d2d2d2d2d2d2d2d");
|
|
||||||
body.append("2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d39");
|
|
||||||
body.append("3433383332353432363038370d0a436f");
|
|
||||||
body.append("6e74656e742d446973706f736974696f");
|
|
||||||
body.append("6e3a20666f726d2d646174613b206e61");
|
|
||||||
body.append("6d653d226c61726765496d6167654669");
|
|
||||||
body.append("6c65223b2066696c656e616d653d2261");
|
|
||||||
body.append("61612e747874220d0a436f6e74656e74");
|
|
||||||
body.append("2d547970653a20746578742f706c6169");
|
|
||||||
body.append("6e0d0a0d0a6161616161616161616161");
|
|
||||||
body.append("61616161616161616161616161616161");
|
|
||||||
body.append("61616161616161616161616161616161");
|
|
||||||
body.append("6161616161616161616161616161610d");
|
|
||||||
body.append("0a2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d");
|
|
||||||
body.append("2d2d2d2d2d2d2d2d2d2d2d2d2d2d3934");
|
|
||||||
body.append("33383332353432363038372d2d0d0a");
|
|
||||||
|
|
||||||
return body.toString();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
private String getTestShortBody()
|
|
||||||
{
|
|
||||||
StringBuffer body = new StringBuffer("");
|
|
||||||
|
|
||||||
body.append("123402f702f52d2d2d2d2d2d2d2d");
|
|
||||||
body.append("2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d");
|
|
||||||
body.append("2d2d2d2d2d3934333833323534323630");
|
|
||||||
body.append("38370d0a436f6e74656e742d44697370");
|
|
||||||
body.append("6f736974696f6e3a20666f726d2d6461");
|
|
||||||
body.append("74613b206e616d653d227265636f7264");
|
|
||||||
body.append("4964220d0a0d0a320d0a2d2d2d2d2d2d");
|
|
||||||
body.append("2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d");
|
|
||||||
body.append("2d2d2d2d2d2d2d393433383332353432");
|
|
||||||
body.append("363038370d0a436f6e74656e742d4469");
|
|
||||||
body.append("73706f736974696f6e3a20666f726d2d");
|
|
||||||
body.append("646174613b206e616d653d226e616d65");
|
|
||||||
body.append("220d0a0d0a4974656d0d0a2d2d2d2d2d");
|
|
||||||
body.append("2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d");
|
|
||||||
body.append("2d2d2d2d2d2d2d2d3934333833323534");
|
|
||||||
body.append("32363038370d0a436f6e74656e742d44");
|
|
||||||
body.append("6973706f736974696f6e3a20666f726d");
|
|
||||||
body.append("2d646174613b206e616d653d22746e49");
|
|
||||||
body.append("6d674964220d0a0d0a696d67320d0a2d");
|
|
||||||
body.append("2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d");
|
|
||||||
body.append("2d2d2d2d2d2d2d2d2d2d2d2d39343338");
|
|
||||||
body.append("3332353432363038370d0a436f6e7465");
|
|
||||||
body.append("6e742d446973706f736974696f6e3a20");
|
|
||||||
body.append("666f726d2d646174613b206e616d653d");
|
|
||||||
body.append("227468756d624e61696c496d61676546");
|
|
||||||
body.append("696c65223b2066696c656e616d653d22");
|
|
||||||
body.append("6161612e747874220d0a436f6e74656e");
|
|
||||||
body.append("742d547970653a20746578742f706c61");
|
|
||||||
body.append("696e0d0a0d0a61616161616161616161");
|
|
||||||
body.append("61616161616161616161616161616161");
|
|
||||||
body.append("61616161616161616161616161616161");
|
|
||||||
body.append("61616161616161616161616161616161");
|
|
||||||
body.append("0d0a2d2d2d2d2d2d2d2d2d2d2d2d2d2d");
|
|
||||||
body.append("2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d39");
|
|
||||||
body.append("3433383332353432363038370d0a436f");
|
|
||||||
body.append("6e74656e742d446973706f736974696f");
|
|
||||||
body.append("6e3a20666f726d2d646174613b206e61");
|
|
||||||
body.append("6d653d226c61726765496d6167654669");
|
|
||||||
body.append("6c65223b2066696c656e616d653d2261");
|
|
||||||
body.append("61612e747874220d0a436f6e74656e74");
|
|
||||||
body.append("2d547970653a20746578742f706c6169");
|
|
||||||
body.append("6e0d0a0d0a6161616161616161616161");
|
|
||||||
body.append("61616161616161616161616161616161");
|
|
||||||
body.append("61616161616161616161616161616161");
|
|
||||||
body.append("6161616161616161616161616161610d");
|
|
||||||
body.append("0a2d2d2d2d2d2d2d2d2d2d2d2d2d2d2d");
|
|
||||||
body.append("2d2d2d2d2d2d2d2d2d2d2d2d2d2d3934");
|
|
||||||
body.append("33383332353432363038372d2d");
|
|
||||||
|
|
||||||
return body.toString();
|
|
||||||
}
|
|
||||||
private String getTestTinyBody()
|
|
||||||
{
|
|
||||||
StringBuffer body = new StringBuffer("");
|
|
||||||
|
|
||||||
body.append("123400042d2d0d0a");
|
|
||||||
|
|
||||||
return body.toString();
|
|
||||||
}
|
|
||||||
|
|
||||||
private static class EH implements Ajp13Parser.EventHandler
|
|
||||||
{
|
|
||||||
final boolean debug=false;
|
|
||||||
|
|
||||||
public void content(Buffer ref) throws IOException
|
|
||||||
{
|
|
||||||
if (debug) System.err.println(ref);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void headerComplete() throws IOException
|
|
||||||
{
|
|
||||||
if (debug) System.err.println("--");
|
|
||||||
}
|
|
||||||
|
|
||||||
public void messageComplete(long contextLength) throws IOException
|
|
||||||
{
|
|
||||||
if (debug) System.err.println("==");
|
|
||||||
}
|
|
||||||
|
|
||||||
public void parsedHeader(Buffer name, Buffer value) throws IOException
|
|
||||||
{
|
|
||||||
if (debug) System.err.println(name+": "+value);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void parsedMethod(Buffer method) throws IOException
|
|
||||||
{
|
|
||||||
if (debug) System.err.println(method);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void parsedProtocol(Buffer protocol) throws IOException
|
|
||||||
{
|
|
||||||
if (debug) System.err.println(protocol);
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
public void parsedQueryString(Buffer value) throws IOException
|
|
||||||
{
|
|
||||||
if (debug) System.err.println("?"+value);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void parsedRemoteAddr(Buffer addr) throws IOException
|
|
||||||
{
|
|
||||||
if (debug) System.err.println("addr="+addr);
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
public void parsedRemoteHost(Buffer host) throws IOException
|
|
||||||
{
|
|
||||||
if (debug) System.err.println("host="+host);
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
public void parsedRequestAttribute(String key, Buffer value) throws IOException
|
|
||||||
{
|
|
||||||
if (debug) System.err.println(key+":: "+value);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void parsedServerName(Buffer name) throws IOException
|
|
||||||
{
|
|
||||||
if (debug) System.err.println("Server:: "+name);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void parsedServerPort(int port) throws IOException
|
|
||||||
{
|
|
||||||
if (debug) System.err.println("Port:: "+port);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void parsedSslSecure(boolean secure) throws IOException
|
|
||||||
{
|
|
||||||
if (debug) System.err.println("Secure:: "+secure);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void parsedUri(Buffer uri) throws IOException
|
|
||||||
{
|
|
||||||
if (debug) System.err.println("URI:: "+uri);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void startForwardRequest() throws IOException
|
|
||||||
{
|
|
||||||
if (debug) System.err.println("..");
|
|
||||||
}
|
|
||||||
|
|
||||||
public void parsedAuthorizationType(Buffer authType) throws IOException
|
|
||||||
{
|
|
||||||
if (debug) System.err.println("auth:: "+authType);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void parsedRemoteUser(Buffer remoteUser) throws IOException
|
|
||||||
{
|
|
||||||
if (debug) System.err.println("user:: "+remoteUser);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void parsedServletPath(Buffer servletPath) throws IOException
|
|
||||||
{
|
|
||||||
if (debug) System.err.println("servletPath:: "+servletPath);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void parsedContextPath(Buffer context) throws IOException
|
|
||||||
{
|
|
||||||
if (debug) System.err.println("Context:: "+context);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void parsedSslCert(Buffer sslCert) throws IOException
|
|
||||||
{
|
|
||||||
if (debug) System.err.println("sslCert:: "+sslCert);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void parsedSslCipher(Buffer sslCipher) throws IOException
|
|
||||||
{
|
|
||||||
if (debug) System.err.println("sslCipher:: "+sslCipher);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void parsedSslSession(Buffer sslSession) throws IOException
|
|
||||||
{
|
|
||||||
if (debug) System.err.println("sslSession:: "+sslSession);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void parsedSslKeySize(int keySize) throws IOException
|
|
||||||
{
|
|
||||||
if (debug) System.err.println("sslkeysize:: "+keySize);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void parsedRequestAttribute(String key, int value) throws IOException
|
|
||||||
{
|
|
||||||
if (debug) System.err.println(key+":: "+value);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -0,0 +1,45 @@
|
||||||
|
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
|
||||||
|
<parent>
|
||||||
|
<groupId>org.eclipse.jetty</groupId>
|
||||||
|
<artifactId>jetty-project</artifactId>
|
||||||
|
<version>9.0.0-SNAPSHOT</version>
|
||||||
|
</parent>
|
||||||
|
<modelVersion>4.0.0</modelVersion>
|
||||||
|
<artifactId>jetty-ant</artifactId>
|
||||||
|
<packaging>jar</packaging>
|
||||||
|
<name>Jetty :: Ant Plugin</name>
|
||||||
|
<build>
|
||||||
|
</build>
|
||||||
|
<dependencies>
|
||||||
|
<dependency>
|
||||||
|
<groupId>junit</groupId>
|
||||||
|
<artifactId>junit</artifactId>
|
||||||
|
<scope>test</scope>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>ant</groupId>
|
||||||
|
<artifactId>ant</artifactId>
|
||||||
|
<version>1.6.5</version>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.eclipse.jetty</groupId>
|
||||||
|
<artifactId>jetty-security</artifactId>
|
||||||
|
<version>${project.version}</version>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.eclipse.jetty</groupId>
|
||||||
|
<artifactId>jetty-plus</artifactId>
|
||||||
|
<version>${project.version}</version>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.eclipse.jetty</groupId>
|
||||||
|
<artifactId>jetty-webapp</artifactId>
|
||||||
|
<version>${project.version}</version>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.eclipse.jetty</groupId>
|
||||||
|
<artifactId>jetty-annotations</artifactId>
|
||||||
|
<version>${project.version}</version>
|
||||||
|
</dependency>
|
||||||
|
</dependencies>
|
||||||
|
</project>
|
|
@ -0,0 +1,146 @@
|
||||||
|
//
|
||||||
|
// ========================================================================
|
||||||
|
// Copyright (c) 1995-2012 Mort Bay Consulting Pty. Ltd.
|
||||||
|
// ------------------------------------------------------------------------
|
||||||
|
// All rights reserved. This program and the accompanying materials
|
||||||
|
// are made available under the terms of the Eclipse Public License v1.0
|
||||||
|
// and Apache License v2.0 which accompanies this distribution.
|
||||||
|
//
|
||||||
|
// The Eclipse Public License is available at
|
||||||
|
// http://www.eclipse.org/legal/epl-v10.html
|
||||||
|
//
|
||||||
|
// The Apache License v2.0 is available at
|
||||||
|
// http://www.opensource.org/licenses/apache2.0.php
|
||||||
|
//
|
||||||
|
// You may elect to redistribute this code under either of these licenses.
|
||||||
|
// ========================================================================
|
||||||
|
//
|
||||||
|
|
||||||
|
package org.eclipse.jetty.ant;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
|
import java.net.URI;
|
||||||
|
import java.net.URISyntaxException;
|
||||||
|
import java.net.URL;
|
||||||
|
import java.net.URLClassLoader;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.regex.Pattern;
|
||||||
|
|
||||||
|
import org.apache.tools.ant.AntClassLoader;
|
||||||
|
import org.eclipse.jetty.util.PatternMatcher;
|
||||||
|
import org.eclipse.jetty.util.resource.Resource;
|
||||||
|
import org.eclipse.jetty.webapp.WebAppContext;
|
||||||
|
import org.eclipse.jetty.webapp.WebInfConfiguration;
|
||||||
|
|
||||||
|
public class AntWebInfConfiguration extends WebInfConfiguration
|
||||||
|
{
|
||||||
|
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void preConfigure(final WebAppContext context) throws Exception
|
||||||
|
{
|
||||||
|
// Look for a work directory
|
||||||
|
File work = findWorkDirectory(context);
|
||||||
|
if (work != null)
|
||||||
|
makeTempDirectory(work, context, false);
|
||||||
|
|
||||||
|
//Make a temp directory for the webapp if one is not already set
|
||||||
|
resolveTempDirectory(context);
|
||||||
|
|
||||||
|
//Extract webapp if necessary
|
||||||
|
unpack (context);
|
||||||
|
|
||||||
|
|
||||||
|
//Apply an initial ordering to the jars which governs which will be scanned for META-INF
|
||||||
|
//info and annotations. The ordering is based on inclusion patterns.
|
||||||
|
String tmp = (String)context.getAttribute(WEBINF_JAR_PATTERN);
|
||||||
|
Pattern webInfPattern = (tmp==null?null:Pattern.compile(tmp));
|
||||||
|
tmp = (String)context.getAttribute(CONTAINER_JAR_PATTERN);
|
||||||
|
Pattern containerPattern = (tmp==null?null:Pattern.compile(tmp));
|
||||||
|
|
||||||
|
//Apply ordering to container jars - if no pattern is specified, we won't
|
||||||
|
//match any of the container jars
|
||||||
|
PatternMatcher containerJarNameMatcher = new PatternMatcher ()
|
||||||
|
{
|
||||||
|
public void matched(URI uri) throws Exception
|
||||||
|
{
|
||||||
|
context.getMetaData().addContainerJar(Resource.newResource(uri));
|
||||||
|
}
|
||||||
|
};
|
||||||
|
ClassLoader loader = context.getClassLoader();
|
||||||
|
if (loader != null)
|
||||||
|
{
|
||||||
|
loader = loader.getParent();
|
||||||
|
if (loader != null)
|
||||||
|
{
|
||||||
|
URI[] containerUris = null;
|
||||||
|
|
||||||
|
if (loader instanceof URLClassLoader)
|
||||||
|
{
|
||||||
|
URL[] urls = ((URLClassLoader)loader).getURLs();
|
||||||
|
if (urls != null)
|
||||||
|
{
|
||||||
|
containerUris = new URI[urls.length];
|
||||||
|
int i=0;
|
||||||
|
for (URL u : urls)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
containerUris[i] = u.toURI();
|
||||||
|
}
|
||||||
|
catch (URISyntaxException e)
|
||||||
|
{
|
||||||
|
containerUris[i] = new URI(u.toString().replaceAll(" ", "%20"));
|
||||||
|
}
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (loader instanceof AntClassLoader)
|
||||||
|
{
|
||||||
|
AntClassLoader antLoader = (AntClassLoader)loader;
|
||||||
|
String[] paths = antLoader.getClasspath().split(new String(new char[]{File.pathSeparatorChar}));
|
||||||
|
if (paths != null)
|
||||||
|
{
|
||||||
|
containerUris = new URI[paths.length];
|
||||||
|
int i=0;
|
||||||
|
for (String p:paths)
|
||||||
|
{
|
||||||
|
File f = new File(p);
|
||||||
|
containerUris[i] = f.toURI();
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
containerJarNameMatcher.match(containerPattern, containerUris, false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//Apply ordering to WEB-INF/lib jars
|
||||||
|
PatternMatcher webInfJarNameMatcher = new PatternMatcher ()
|
||||||
|
{
|
||||||
|
@Override
|
||||||
|
public void matched(URI uri) throws Exception
|
||||||
|
{
|
||||||
|
context.getMetaData().addWebInfJar(Resource.newResource(uri));
|
||||||
|
}
|
||||||
|
};
|
||||||
|
List<Resource> jars = findJars(context);
|
||||||
|
|
||||||
|
//Convert to uris for matching
|
||||||
|
URI[] uris = null;
|
||||||
|
if (jars != null)
|
||||||
|
{
|
||||||
|
uris = new URI[jars.size()];
|
||||||
|
int i=0;
|
||||||
|
for (Resource r: jars)
|
||||||
|
{
|
||||||
|
uris[i++] = r.getURI();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
webInfJarNameMatcher.match(webInfPattern, uris, true); //null is inclusive, no pattern == all jars match
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,136 @@
|
||||||
|
//
|
||||||
|
// ========================================================================
|
||||||
|
// Copyright (c) 1995-2012 Sabre Holdings.
|
||||||
|
// ------------------------------------------------------------------------
|
||||||
|
// 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.ant;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.net.URL;
|
||||||
|
import java.net.URLClassLoader;
|
||||||
|
import java.util.Iterator;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import org.apache.tools.ant.AntClassLoader;
|
||||||
|
import org.eclipse.jetty.ant.utils.TaskLog;
|
||||||
|
import org.eclipse.jetty.plus.webapp.PlusConfiguration;
|
||||||
|
import org.eclipse.jetty.util.log.Log;
|
||||||
|
import org.eclipse.jetty.util.log.Logger;
|
||||||
|
import org.eclipse.jetty.util.resource.Resource;
|
||||||
|
import org.eclipse.jetty.webapp.Descriptor;
|
||||||
|
import org.eclipse.jetty.webapp.StandardDescriptorProcessor;
|
||||||
|
import org.eclipse.jetty.webapp.WebAppClassLoader;
|
||||||
|
import org.eclipse.jetty.webapp.WebXmlConfiguration;
|
||||||
|
import org.eclipse.jetty.webapp.WebAppContext;
|
||||||
|
import org.eclipse.jetty.xml.XmlParser.Node;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This configuration object provides additional way to inject application
|
||||||
|
* properties into the configured web application. The list of classpath files,
|
||||||
|
* the application base directory and web.xml file could be specified in this
|
||||||
|
* way.
|
||||||
|
*
|
||||||
|
* @author Jakub Pawlowicz
|
||||||
|
* @author Athena Yao
|
||||||
|
*/
|
||||||
|
public class AntWebXmlConfiguration extends WebXmlConfiguration
|
||||||
|
{
|
||||||
|
private static final Logger LOG = Log.getLogger(WebXmlConfiguration.class);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/** List of classpath files. */
|
||||||
|
private List classPathFiles;
|
||||||
|
|
||||||
|
/** Web application root directory. */
|
||||||
|
private File webAppBaseDir;
|
||||||
|
|
||||||
|
/** Web application web.xml file. */
|
||||||
|
private File webXmlFile;
|
||||||
|
|
||||||
|
private File webDefaultXmlFile;
|
||||||
|
|
||||||
|
public AntWebXmlConfiguration() throws ClassNotFoundException
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
public File getWebDefaultXmlFile()
|
||||||
|
{
|
||||||
|
return this.webDefaultXmlFile;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setWebDefaultXmlFile(File webDefaultXmlfile)
|
||||||
|
{
|
||||||
|
this.webDefaultXmlFile = webDefaultXmlfile;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setClassPathFiles(List classPathFiles)
|
||||||
|
{
|
||||||
|
this.classPathFiles = classPathFiles;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setWebAppBaseDir(File webAppBaseDir)
|
||||||
|
{
|
||||||
|
this.webAppBaseDir = webAppBaseDir;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setWebXmlFile(File webXmlFile)
|
||||||
|
{
|
||||||
|
this.webXmlFile = webXmlFile;
|
||||||
|
|
||||||
|
if (webXmlFile.exists())
|
||||||
|
{
|
||||||
|
TaskLog.log("web.xml file = " + webXmlFile);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Adds classpath files into web application classloader, and
|
||||||
|
* sets web.xml and base directory for the configured web application.
|
||||||
|
*
|
||||||
|
* @see WebXmlConfiguration#configure(WebAppContext)
|
||||||
|
*/
|
||||||
|
public void configure(WebAppContext context) throws Exception
|
||||||
|
{
|
||||||
|
if (context.isStarted())
|
||||||
|
{
|
||||||
|
TaskLog.log("Cannot configure webapp after it is started");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
if (webXmlFile.exists())
|
||||||
|
{
|
||||||
|
context.setDescriptor(webXmlFile.getCanonicalPath());
|
||||||
|
}
|
||||||
|
|
||||||
|
super.configure(context);
|
||||||
|
|
||||||
|
Iterator filesIterator = classPathFiles.iterator();
|
||||||
|
|
||||||
|
while (filesIterator.hasNext())
|
||||||
|
{
|
||||||
|
File classPathFile = (File) filesIterator.next();
|
||||||
|
if (classPathFile.exists())
|
||||||
|
{
|
||||||
|
((WebAppClassLoader) context.getClassLoader())
|
||||||
|
.addClassPath(classPathFile.getCanonicalPath());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,328 @@
|
||||||
|
//
|
||||||
|
// ========================================================================
|
||||||
|
// Copyright (c) 1995-2012 Sabre Holdings.
|
||||||
|
// ------------------------------------------------------------------------
|
||||||
|
// 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.ant;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Iterator;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import org.apache.tools.ant.BuildException;
|
||||||
|
import org.apache.tools.ant.Task;
|
||||||
|
import org.apache.tools.ant.taskdefs.Property;
|
||||||
|
import org.eclipse.jetty.ant.types.Connectors;
|
||||||
|
import org.eclipse.jetty.ant.types.LoginServices;
|
||||||
|
import org.eclipse.jetty.ant.types.SystemProperties;
|
||||||
|
import org.eclipse.jetty.ant.types.WebApp;
|
||||||
|
import org.eclipse.jetty.ant.utils.ServerProxy;
|
||||||
|
import org.eclipse.jetty.ant.utils.TaskLog;
|
||||||
|
import org.eclipse.jetty.server.RequestLog;
|
||||||
|
import org.eclipse.jetty.util.Scanner;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Ant task for running a Jetty server.
|
||||||
|
*
|
||||||
|
* @author Jakub Pawlowicz
|
||||||
|
*/
|
||||||
|
public class JettyRunTask extends Task
|
||||||
|
{
|
||||||
|
|
||||||
|
/** Temporary files directory. */
|
||||||
|
private File tempDirectory;
|
||||||
|
|
||||||
|
/** List of web applications to be deployed. */
|
||||||
|
private List webapps = new ArrayList();
|
||||||
|
|
||||||
|
/** Location of jetty.xml file. */
|
||||||
|
private File jettyXml;
|
||||||
|
|
||||||
|
/** List of server connectors. */
|
||||||
|
private Connectors connectors = null;
|
||||||
|
|
||||||
|
/** Server request logger object. */
|
||||||
|
private RequestLog requestLog;
|
||||||
|
|
||||||
|
/** List of login services. */
|
||||||
|
private LoginServices loginServices;
|
||||||
|
|
||||||
|
/** List of system properties to be set. */
|
||||||
|
private SystemProperties systemProperties;
|
||||||
|
|
||||||
|
/** Port Jetty will use for the default connector */
|
||||||
|
private int jettyPort = 8080;
|
||||||
|
|
||||||
|
|
||||||
|
public JettyRunTask()
|
||||||
|
{
|
||||||
|
TaskLog.setTask(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a new <code>WebApp</code> Ant object.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
public void addWebApp(WebApp webapp)
|
||||||
|
{
|
||||||
|
webapps.add(webapp);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Adds a new Ant's connector tag object if it have not been created yet.
|
||||||
|
*/
|
||||||
|
public void addConnectors(Connectors connectors)
|
||||||
|
{
|
||||||
|
if (this.connectors != null)
|
||||||
|
{
|
||||||
|
throw new BuildException("Only one <connectors> tag is allowed!");
|
||||||
|
}
|
||||||
|
|
||||||
|
this.connectors = connectors;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @deprecated
|
||||||
|
*/
|
||||||
|
public void addUserRealms(Object o)
|
||||||
|
{
|
||||||
|
TaskLog.log("User realms are deprecated.");
|
||||||
|
}
|
||||||
|
|
||||||
|
public void addLoginServices(LoginServices services)
|
||||||
|
{
|
||||||
|
if (this.loginServices != null )
|
||||||
|
{
|
||||||
|
throw new BuildException("Only one <loginServices> tag is allowed!");
|
||||||
|
}
|
||||||
|
|
||||||
|
this.loginServices = services;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void addSystemProperties(SystemProperties systemProperties)
|
||||||
|
{
|
||||||
|
if (this.systemProperties != null)
|
||||||
|
{
|
||||||
|
throw new BuildException("Only one <systemProperties> tag is allowed!");
|
||||||
|
}
|
||||||
|
|
||||||
|
this.systemProperties = systemProperties;
|
||||||
|
}
|
||||||
|
|
||||||
|
public File getTempDirectory()
|
||||||
|
{
|
||||||
|
return tempDirectory;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setTempDirectory(File tempDirectory)
|
||||||
|
{
|
||||||
|
this.tempDirectory = tempDirectory;
|
||||||
|
}
|
||||||
|
|
||||||
|
public File getJettyXml()
|
||||||
|
{
|
||||||
|
return jettyXml;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setJettyXml(File jettyXml)
|
||||||
|
{
|
||||||
|
this.jettyXml = jettyXml;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setRequestLog(String className)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
this.requestLog = (RequestLog) Class.forName(className).newInstance();
|
||||||
|
}
|
||||||
|
catch (InstantiationException e)
|
||||||
|
{
|
||||||
|
throw new BuildException("Request logger instantiation exception: " + e);
|
||||||
|
}
|
||||||
|
catch (IllegalAccessException e)
|
||||||
|
{
|
||||||
|
throw new BuildException("Request logger instantiation exception: " + e);
|
||||||
|
}
|
||||||
|
catch (ClassNotFoundException e)
|
||||||
|
{
|
||||||
|
throw new BuildException("Unknown request logger class: " + className);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getRequestLog()
|
||||||
|
{
|
||||||
|
if (requestLog != null)
|
||||||
|
{
|
||||||
|
return requestLog.getClass().getName();
|
||||||
|
}
|
||||||
|
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the port Jetty uses for the default connector.
|
||||||
|
*
|
||||||
|
* @param jettyPort The port Jetty will use for the default connector
|
||||||
|
*/
|
||||||
|
public void setJettyPort(final int jettyPort)
|
||||||
|
{
|
||||||
|
this.jettyPort = jettyPort;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Executes this Ant task. The build flow is being stopped until Jetty
|
||||||
|
* server stops.
|
||||||
|
*
|
||||||
|
* @throws BuildException
|
||||||
|
*/
|
||||||
|
public void execute() throws BuildException
|
||||||
|
{
|
||||||
|
|
||||||
|
TaskLog.log("Configuring Jetty for project: " + getProject().getName());
|
||||||
|
WebApplicationProxyImpl.setBaseTempDirectory(tempDirectory);
|
||||||
|
setSystemProperties();
|
||||||
|
|
||||||
|
List connectorsList = null;
|
||||||
|
|
||||||
|
if (connectors != null)
|
||||||
|
{
|
||||||
|
connectorsList = connectors.getConnectors();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
connectorsList = new Connectors(jettyPort,30000).getDefaultConnectors();
|
||||||
|
}
|
||||||
|
|
||||||
|
List loginServicesList = (loginServices != null?loginServices.getLoginServices():new ArrayList());
|
||||||
|
ServerProxy server = new ServerProxyImpl(connectorsList,loginServicesList,requestLog,jettyXml);
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
Iterator iterator = webapps.iterator();
|
||||||
|
while (iterator.hasNext())
|
||||||
|
{
|
||||||
|
WebApp webAppConfiguration = (WebApp)iterator.next();
|
||||||
|
WebApplicationProxyImpl webApp = new WebApplicationProxyImpl(webAppConfiguration.getName());
|
||||||
|
webApp.setSourceDirectory(webAppConfiguration.getWarFile());
|
||||||
|
webApp.setContextPath(webAppConfiguration.getContextPath());
|
||||||
|
webApp.setWebXml(webAppConfiguration.getWebXmlFile());
|
||||||
|
webApp.setJettyEnvXml(webAppConfiguration.getJettyEnvXml());
|
||||||
|
webApp.setClassPathFiles(webAppConfiguration.getClassPathFiles());
|
||||||
|
webApp.setLibrariesConfiguration(webAppConfiguration.getLibrariesConfiguration());
|
||||||
|
webApp.setExtraScanTargetsConfiguration(webAppConfiguration.getScanTargetsConfiguration());
|
||||||
|
webApp.setContextHandlers(webAppConfiguration.getContextHandlers());
|
||||||
|
webApp.setAttributes(webAppConfiguration.getAttributes());
|
||||||
|
webApp.setWebDefaultXmlFile(webAppConfiguration.getWebDefaultXmlFile());
|
||||||
|
|
||||||
|
server.addWebApplication(webApp,webAppConfiguration.getScanIntervalSeconds());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
throw new BuildException(e);
|
||||||
|
}
|
||||||
|
|
||||||
|
server.start();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Starts a new thread which scans project files and automatically reloads a
|
||||||
|
* container on any changes.
|
||||||
|
*
|
||||||
|
* @param scanIntervalSeconds
|
||||||
|
*
|
||||||
|
* @param webapp
|
||||||
|
* @param appContext
|
||||||
|
*/
|
||||||
|
static void startScanner(final WebApplicationProxyImpl webApp, int scanIntervalSeconds) throws Exception
|
||||||
|
{
|
||||||
|
List scanList = new ArrayList();
|
||||||
|
scanList.add(webApp.getWebXmlFile());
|
||||||
|
scanList.addAll(webApp.getLibraries());
|
||||||
|
scanList.addAll(webApp.getExtraScanTargets());
|
||||||
|
|
||||||
|
Scanner.Listener changeListener = new Scanner.BulkListener()
|
||||||
|
{
|
||||||
|
|
||||||
|
public void filesChanged(List changedFiles)
|
||||||
|
{
|
||||||
|
if (hasAnyFileChanged(changedFiles))
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
webApp.stop();
|
||||||
|
webApp.applyConfiguration();
|
||||||
|
webApp.start();
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Checks if any file in this particular application has changed.
|
||||||
|
* This is not that easy, because some applications may use the same
|
||||||
|
* class'es directory.
|
||||||
|
*
|
||||||
|
* @param changedFiles list of changed files.
|
||||||
|
* @return true if any of passed files has changed, false otherwise.
|
||||||
|
*/
|
||||||
|
private boolean hasAnyFileChanged(List changedFiles)
|
||||||
|
{
|
||||||
|
Iterator changes = changedFiles.iterator();
|
||||||
|
while (changes.hasNext())
|
||||||
|
{
|
||||||
|
String className = (String) changes.next();
|
||||||
|
if (webApp.isFileScanned(className))
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
TaskLog.log("Web application '" + webApp.getName() + "': starting scanner at interval of "
|
||||||
|
+ scanIntervalSeconds + " seconds.");
|
||||||
|
|
||||||
|
Scanner scanner = new Scanner();
|
||||||
|
scanner.setScanInterval(scanIntervalSeconds);
|
||||||
|
scanner.addListener(changeListener);
|
||||||
|
scanner.setScanDirs(scanList);
|
||||||
|
scanner.setReportExistingFilesOnStartup(false);
|
||||||
|
scanner.start();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the system properties.
|
||||||
|
*/
|
||||||
|
private void setSystemProperties()
|
||||||
|
{
|
||||||
|
if (systemProperties != null)
|
||||||
|
{
|
||||||
|
Iterator propertiesIterator = systemProperties.getSystemProperties().iterator();
|
||||||
|
while (propertiesIterator.hasNext())
|
||||||
|
{
|
||||||
|
Property property = ((Property) propertiesIterator.next());
|
||||||
|
SystemProperties.setIfNotSetAlready(property);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,255 @@
|
||||||
|
//
|
||||||
|
// ========================================================================
|
||||||
|
// Copyright (c) 1995-2012 Sabre Holdings.
|
||||||
|
// ------------------------------------------------------------------------
|
||||||
|
// 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.ant;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.net.MalformedURLException;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.Iterator;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
import org.eclipse.jetty.ant.types.Connectors.Connector;
|
||||||
|
import org.eclipse.jetty.ant.utils.ServerProxy;
|
||||||
|
import org.eclipse.jetty.ant.utils.TaskLog;
|
||||||
|
import org.eclipse.jetty.ant.utils.WebApplicationProxy;
|
||||||
|
import org.eclipse.jetty.security.LoginService;
|
||||||
|
import org.eclipse.jetty.server.Handler;
|
||||||
|
import org.eclipse.jetty.server.RequestLog;
|
||||||
|
import org.eclipse.jetty.server.SelectChannelConnector;
|
||||||
|
import org.eclipse.jetty.server.Server;
|
||||||
|
import org.eclipse.jetty.server.handler.ContextHandlerCollection;
|
||||||
|
import org.eclipse.jetty.server.handler.DefaultHandler;
|
||||||
|
import org.eclipse.jetty.server.handler.HandlerCollection;
|
||||||
|
import org.eclipse.jetty.server.handler.RequestLogHandler;
|
||||||
|
import org.eclipse.jetty.util.resource.Resource;
|
||||||
|
import org.eclipse.jetty.xml.XmlConfiguration;
|
||||||
|
import org.xml.sax.SAXException;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A proxy class for interaction with Jetty server object. Used to have some
|
||||||
|
* level of abstraction over standard Jetty classes.
|
||||||
|
*
|
||||||
|
* @author Jakub Pawlowicz
|
||||||
|
*/
|
||||||
|
public class ServerProxyImpl implements ServerProxy
|
||||||
|
{
|
||||||
|
|
||||||
|
/** Proxied Jetty server object. */
|
||||||
|
private Server server;
|
||||||
|
|
||||||
|
/** Collection of context handlers (web application contexts). */
|
||||||
|
private ContextHandlerCollection contexts;
|
||||||
|
|
||||||
|
/** Location of jetty.xml file. */
|
||||||
|
private File jettyXml;
|
||||||
|
|
||||||
|
/** List of connectors. */
|
||||||
|
private List connectors;
|
||||||
|
|
||||||
|
/** Request logger. */
|
||||||
|
private RequestLog requestLog;
|
||||||
|
|
||||||
|
/** User realms. */
|
||||||
|
private List loginServices;
|
||||||
|
|
||||||
|
/** List of added web applications. */
|
||||||
|
private Map webApplications = new HashMap();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Default constructor. Creates a new Jetty server with a standard connector
|
||||||
|
* listening on a given port.
|
||||||
|
*
|
||||||
|
* @param connectors
|
||||||
|
* @param loginServicesList
|
||||||
|
* @param requestLog
|
||||||
|
* @param jettyXml
|
||||||
|
*/
|
||||||
|
public ServerProxyImpl(List connectors, List loginServicesList, RequestLog requestLog,
|
||||||
|
File jettyXml)
|
||||||
|
{
|
||||||
|
server = new Server();
|
||||||
|
server.setStopAtShutdown(true);
|
||||||
|
|
||||||
|
this.connectors = connectors;
|
||||||
|
this.loginServices = loginServicesList;
|
||||||
|
this.requestLog = requestLog;
|
||||||
|
this.jettyXml = jettyXml;
|
||||||
|
configure();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @see org.eclipse.jetty.ant.utils.ServerProxy#addWebApplication(WebApplicationProxy,
|
||||||
|
* int)
|
||||||
|
*/
|
||||||
|
public void addWebApplication(WebApplicationProxy webApp, int scanIntervalSeconds)
|
||||||
|
{
|
||||||
|
webApp.createApplicationContext(contexts);
|
||||||
|
|
||||||
|
if (scanIntervalSeconds > 0)
|
||||||
|
{
|
||||||
|
webApplications.put(webApp, new Integer(scanIntervalSeconds));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Configures Jetty server before adding any web applications to it.
|
||||||
|
*/
|
||||||
|
private void configure()
|
||||||
|
{
|
||||||
|
// Applies external configuration via jetty.xml
|
||||||
|
applyJettyXml();
|
||||||
|
|
||||||
|
// Configures connectors for this server instance.
|
||||||
|
Iterator<Connector> connectorIterator = connectors.iterator();
|
||||||
|
while (connectorIterator.hasNext())
|
||||||
|
{
|
||||||
|
Connector jettyConnector = (Connector) connectorIterator.next();
|
||||||
|
SelectChannelConnector jc = new SelectChannelConnector(server);
|
||||||
|
|
||||||
|
jc.setPort(jettyConnector.getPort());
|
||||||
|
jc.setIdleTimeout(jettyConnector.getMaxIdleTime());
|
||||||
|
|
||||||
|
server.addConnector(jc);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Configures login services
|
||||||
|
Iterator servicesIterator = loginServices.iterator();
|
||||||
|
while (servicesIterator.hasNext())
|
||||||
|
{
|
||||||
|
LoginService service = (LoginService) servicesIterator.next();
|
||||||
|
server.addBean(service);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Does not cache resources, to prevent Windows from locking files
|
||||||
|
Resource.setDefaultUseCaches(false);
|
||||||
|
|
||||||
|
// Set default server handlers
|
||||||
|
configureHandlers();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void configureHandlers()
|
||||||
|
{
|
||||||
|
RequestLogHandler requestLogHandler = new RequestLogHandler();
|
||||||
|
if (requestLog != null)
|
||||||
|
{
|
||||||
|
requestLogHandler.setRequestLog(requestLog);
|
||||||
|
}
|
||||||
|
|
||||||
|
contexts = (ContextHandlerCollection) server
|
||||||
|
.getChildHandlerByClass(ContextHandlerCollection.class);
|
||||||
|
if (contexts == null)
|
||||||
|
{
|
||||||
|
contexts = new ContextHandlerCollection();
|
||||||
|
HandlerCollection handlers = (HandlerCollection) server
|
||||||
|
.getChildHandlerByClass(HandlerCollection.class);
|
||||||
|
if (handlers == null)
|
||||||
|
{
|
||||||
|
handlers = new HandlerCollection();
|
||||||
|
server.setHandler(handlers);
|
||||||
|
handlers.setHandlers(new Handler[] { contexts, new DefaultHandler(),
|
||||||
|
requestLogHandler });
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
handlers.addHandler(contexts);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Applies jetty.xml configuration to the Jetty server instance.
|
||||||
|
*/
|
||||||
|
private void applyJettyXml()
|
||||||
|
{
|
||||||
|
if (jettyXml != null && jettyXml.exists())
|
||||||
|
{
|
||||||
|
TaskLog.log("Configuring jetty from xml configuration file = "
|
||||||
|
+ jettyXml.getAbsolutePath());
|
||||||
|
XmlConfiguration configuration;
|
||||||
|
try
|
||||||
|
{
|
||||||
|
configuration = new XmlConfiguration(Resource.toURL(jettyXml));
|
||||||
|
configuration.configure(server);
|
||||||
|
}
|
||||||
|
catch (MalformedURLException e)
|
||||||
|
{
|
||||||
|
throw new RuntimeException(e);
|
||||||
|
}
|
||||||
|
catch (SAXException e)
|
||||||
|
{
|
||||||
|
throw new RuntimeException(e);
|
||||||
|
}
|
||||||
|
catch (IOException e)
|
||||||
|
{
|
||||||
|
throw new RuntimeException(e);
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
throw new RuntimeException(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @see org.eclipse.jetty.ant.utils.ServerProxy#start()
|
||||||
|
*/
|
||||||
|
public void start()
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
server.start();
|
||||||
|
startScanners();
|
||||||
|
server.join();
|
||||||
|
|
||||||
|
}
|
||||||
|
catch (InterruptedException e)
|
||||||
|
{
|
||||||
|
new RuntimeException(e);
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
new RuntimeException(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Starts web applications' scanners.
|
||||||
|
*/
|
||||||
|
private void startScanners() throws Exception
|
||||||
|
{
|
||||||
|
Iterator i = webApplications.keySet().iterator();
|
||||||
|
while (i.hasNext())
|
||||||
|
{
|
||||||
|
WebApplicationProxyImpl webApp = (WebApplicationProxyImpl) i.next();
|
||||||
|
Integer scanIntervalSeconds = (Integer) webApplications.get(webApp);
|
||||||
|
JettyRunTask.startScanner(webApp, scanIntervalSeconds.intValue());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @see org.eclipse.jetty.ant.utils.ServerProxy#getProxiedObject()
|
||||||
|
*/
|
||||||
|
public Object getProxiedObject()
|
||||||
|
{
|
||||||
|
return server;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,542 @@
|
||||||
|
//
|
||||||
|
// ========================================================================
|
||||||
|
// Copyright (c) 1995-2012 Sabre Holdings.
|
||||||
|
// ------------------------------------------------------------------------
|
||||||
|
// 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.ant;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.net.MalformedURLException;
|
||||||
|
import java.net.URL;
|
||||||
|
import java.net.URLClassLoader;
|
||||||
|
import java.util.Iterator;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import javax.servlet.Servlet;
|
||||||
|
|
||||||
|
|
||||||
|
import org.apache.tools.ant.AntClassLoader;
|
||||||
|
import org.eclipse.jetty.annotations.AnnotationConfiguration;
|
||||||
|
import org.eclipse.jetty.ant.types.Attribute;
|
||||||
|
import org.eclipse.jetty.ant.types.FileMatchingConfiguration;
|
||||||
|
import org.eclipse.jetty.ant.utils.TaskLog;
|
||||||
|
import org.eclipse.jetty.ant.utils.WebApplicationProxy;
|
||||||
|
import org.eclipse.jetty.plus.webapp.EnvConfiguration;
|
||||||
|
import org.eclipse.jetty.plus.webapp.PlusConfiguration;
|
||||||
|
import org.eclipse.jetty.security.SecurityHandler;
|
||||||
|
import org.eclipse.jetty.server.HandlerContainer;
|
||||||
|
import org.eclipse.jetty.server.handler.ContextHandler;
|
||||||
|
import org.eclipse.jetty.server.handler.ContextHandlerCollection;
|
||||||
|
import org.eclipse.jetty.server.handler.ErrorHandler;
|
||||||
|
import org.eclipse.jetty.server.session.SessionHandler;
|
||||||
|
import org.eclipse.jetty.servlet.Holder;
|
||||||
|
import org.eclipse.jetty.servlet.ServletHandler;
|
||||||
|
import org.eclipse.jetty.servlet.ServletHolder;
|
||||||
|
import org.eclipse.jetty.util.resource.Resource;
|
||||||
|
import org.eclipse.jetty.webapp.Configuration;
|
||||||
|
import org.eclipse.jetty.webapp.FragmentConfiguration;
|
||||||
|
import org.eclipse.jetty.webapp.JettyWebXmlConfiguration;
|
||||||
|
import org.eclipse.jetty.webapp.MetaInfConfiguration;
|
||||||
|
import org.eclipse.jetty.webapp.TagLibConfiguration;
|
||||||
|
import org.eclipse.jetty.webapp.WebAppClassLoader;
|
||||||
|
import org.eclipse.jetty.webapp.WebAppContext;
|
||||||
|
import org.eclipse.jetty.webapp.WebInfConfiguration;
|
||||||
|
import org.eclipse.jetty.webapp.WebXmlConfiguration;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* An abstraction layer over Jetty WebAppContext.
|
||||||
|
*
|
||||||
|
* @author Jakub Pawlowicz
|
||||||
|
*/
|
||||||
|
public class WebApplicationProxyImpl implements WebApplicationProxy
|
||||||
|
{
|
||||||
|
|
||||||
|
/** Common root temp directory for all web applications. */
|
||||||
|
static File baseTempDirectory = new File(".");
|
||||||
|
|
||||||
|
/** Name of this web application. */
|
||||||
|
private String name;
|
||||||
|
|
||||||
|
/** Location of WAR file (either expanded or not). */
|
||||||
|
private File warFile;
|
||||||
|
|
||||||
|
/** Application context path. */
|
||||||
|
private String contextPath;
|
||||||
|
|
||||||
|
/** Location of web.xml file. */
|
||||||
|
private File webXmlFile;
|
||||||
|
|
||||||
|
/** Location of jetty-env.xml file. */
|
||||||
|
private File jettyEnvXml;
|
||||||
|
|
||||||
|
/** List of classpath files. */
|
||||||
|
private List classPathFiles;
|
||||||
|
|
||||||
|
/** Jetty6 Web Application Context. */
|
||||||
|
private WebAppContext webAppContext;
|
||||||
|
|
||||||
|
/** Extra scan targets. */
|
||||||
|
private FileMatchingConfiguration extraScanTargetsConfiguration;
|
||||||
|
|
||||||
|
/** Extra context handlers. */
|
||||||
|
private List contextHandlers;
|
||||||
|
|
||||||
|
private List attributes;
|
||||||
|
|
||||||
|
Configuration[] configurations;
|
||||||
|
|
||||||
|
private FileMatchingConfiguration librariesConfiguration;
|
||||||
|
|
||||||
|
public static void setBaseTempDirectory(File tempDirectory)
|
||||||
|
{
|
||||||
|
baseTempDirectory = tempDirectory;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public static class AntServletHolder extends ServletHolder
|
||||||
|
{
|
||||||
|
|
||||||
|
public AntServletHolder()
|
||||||
|
{
|
||||||
|
super();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public AntServletHolder(Class<? extends Servlet> servlet)
|
||||||
|
{
|
||||||
|
super(servlet);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public AntServletHolder(Servlet servlet)
|
||||||
|
{
|
||||||
|
super(servlet);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public AntServletHolder(String name, Class<? extends Servlet> servlet)
|
||||||
|
{
|
||||||
|
super(name, servlet);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public AntServletHolder(String name, Servlet servlet)
|
||||||
|
{
|
||||||
|
super(name, servlet);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void initJspServlet() throws Exception
|
||||||
|
{
|
||||||
|
//super.initJspServlet();
|
||||||
|
|
||||||
|
ContextHandler ch = ((ContextHandler.Context)getServletHandler().getServletContext()).getContextHandler();
|
||||||
|
|
||||||
|
/* Set the webapp's classpath for Jasper */
|
||||||
|
ch.setAttribute("org.apache.catalina.jsp_classpath", ch.getClassPath());
|
||||||
|
|
||||||
|
/* Set the system classpath for Jasper */
|
||||||
|
String sysClassPath = getSystemClassPath(ch.getClassLoader().getParent());
|
||||||
|
setInitParameter("com.sun.appserv.jsp.classpath", sysClassPath);
|
||||||
|
|
||||||
|
/* Set up other classpath attribute */
|
||||||
|
if ("?".equals(getInitParameter("classpath")))
|
||||||
|
{
|
||||||
|
String classpath = ch.getClassPath();
|
||||||
|
if (classpath != null)
|
||||||
|
setInitParameter("classpath", classpath);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
protected String getSystemClassPath (ClassLoader loader) throws Exception
|
||||||
|
{
|
||||||
|
StringBuilder classpath=new StringBuilder();
|
||||||
|
while (loader != null)
|
||||||
|
{
|
||||||
|
if (loader instanceof URLClassLoader)
|
||||||
|
{
|
||||||
|
URL[] urls = ((URLClassLoader)loader).getURLs();
|
||||||
|
if (urls != null)
|
||||||
|
{
|
||||||
|
for (int i=0;i<urls.length;i++)
|
||||||
|
{
|
||||||
|
Resource resource = Resource.newResource(urls[i]);
|
||||||
|
File file=resource.getFile();
|
||||||
|
if (file!=null && file.exists())
|
||||||
|
{
|
||||||
|
if (classpath.length()>0)
|
||||||
|
classpath.append(File.pathSeparatorChar);
|
||||||
|
classpath.append(file.getAbsolutePath());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (loader instanceof AntClassLoader)
|
||||||
|
{
|
||||||
|
classpath.append(((AntClassLoader)loader).getClasspath());
|
||||||
|
}
|
||||||
|
|
||||||
|
loader = loader.getParent();
|
||||||
|
}
|
||||||
|
|
||||||
|
return classpath.toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class AntServletHandler extends ServletHandler
|
||||||
|
{
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ServletHolder newServletHolder(Holder.Source source)
|
||||||
|
{
|
||||||
|
return new AntServletHolder();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class AntWebAppContext extends WebAppContext
|
||||||
|
{
|
||||||
|
public AntWebAppContext()
|
||||||
|
{
|
||||||
|
super();
|
||||||
|
}
|
||||||
|
|
||||||
|
public AntWebAppContext(HandlerContainer parent, String webApp, String contextPath)
|
||||||
|
{
|
||||||
|
super(parent, webApp, contextPath);
|
||||||
|
}
|
||||||
|
|
||||||
|
public AntWebAppContext(SessionHandler sessionHandler, SecurityHandler securityHandler, ServletHandler servletHandler, ErrorHandler errorHandler)
|
||||||
|
{
|
||||||
|
super(sessionHandler, securityHandler, servletHandler, errorHandler);
|
||||||
|
}
|
||||||
|
|
||||||
|
public AntWebAppContext(String webApp, String contextPath)
|
||||||
|
{
|
||||||
|
super(webApp, contextPath);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected ServletHandler newServletHandler()
|
||||||
|
{
|
||||||
|
return new AntServletHandler();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Default constructor. Takes application name as an argument
|
||||||
|
*
|
||||||
|
* @param name web application name.
|
||||||
|
*/
|
||||||
|
public WebApplicationProxyImpl(String name) throws Exception
|
||||||
|
{
|
||||||
|
this.name = name;
|
||||||
|
TaskLog.log("\nConfiguring Jetty for web application: " + name);
|
||||||
|
|
||||||
|
this.configurations = new Configuration[]
|
||||||
|
{ new AntWebInfConfiguration(),
|
||||||
|
new AntWebXmlConfiguration(),
|
||||||
|
new MetaInfConfiguration(),
|
||||||
|
new FragmentConfiguration(),
|
||||||
|
new EnvConfiguration(),
|
||||||
|
new PlusConfiguration(),
|
||||||
|
new AnnotationConfiguration(),
|
||||||
|
new JettyWebXmlConfiguration(),
|
||||||
|
new TagLibConfiguration() };
|
||||||
|
}
|
||||||
|
|
||||||
|
public List getClassPathFiles()
|
||||||
|
{
|
||||||
|
return classPathFiles;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getContextPath()
|
||||||
|
{
|
||||||
|
return contextPath;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getName()
|
||||||
|
{
|
||||||
|
return name;
|
||||||
|
}
|
||||||
|
|
||||||
|
public File getSourceDirectory()
|
||||||
|
{
|
||||||
|
return warFile;
|
||||||
|
}
|
||||||
|
|
||||||
|
public File getWebXmlFile()
|
||||||
|
{
|
||||||
|
return webXmlFile;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setSourceDirectory(File warFile)
|
||||||
|
{
|
||||||
|
this.warFile = warFile;
|
||||||
|
TaskLog.log("Webapp source directory = " + warFile);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setContextPath(String contextPath)
|
||||||
|
{
|
||||||
|
if (!contextPath.startsWith("/"))
|
||||||
|
{
|
||||||
|
contextPath = "/" + contextPath;
|
||||||
|
}
|
||||||
|
this.contextPath = contextPath;
|
||||||
|
TaskLog.log("Context path = " + contextPath);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setWebXml(File webXmlFile)
|
||||||
|
{
|
||||||
|
this.webXmlFile = webXmlFile;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setJettyEnvXml(File jettyEnvXml)
|
||||||
|
{
|
||||||
|
this.jettyEnvXml = jettyEnvXml;
|
||||||
|
if (this.jettyEnvXml != null)
|
||||||
|
{
|
||||||
|
TaskLog.log("jetty-env.xml file: = " + jettyEnvXml.getAbsolutePath());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setClassPathFiles(List classPathFiles)
|
||||||
|
{
|
||||||
|
this.classPathFiles = classPathFiles;
|
||||||
|
TaskLog.log("Classpath = " + classPathFiles);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Checks if a given file is scanned according to the internal
|
||||||
|
* configuration. This may be difficult due to use of 'includes' and
|
||||||
|
* 'excludes' statements.
|
||||||
|
*
|
||||||
|
* @param pathToFile a fully qualified path to file.
|
||||||
|
* @return true if file is being scanned, false otherwise.
|
||||||
|
*/
|
||||||
|
public boolean isFileScanned(String pathToFile)
|
||||||
|
{
|
||||||
|
return librariesConfiguration.isIncluded(pathToFile)
|
||||||
|
|| extraScanTargetsConfiguration.isIncluded(pathToFile);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setLibrariesConfiguration(FileMatchingConfiguration classesConfiguration)
|
||||||
|
{
|
||||||
|
TaskLog.log("Default scanned paths = " + classesConfiguration.getBaseDirectories());
|
||||||
|
this.librariesConfiguration = classesConfiguration;
|
||||||
|
}
|
||||||
|
|
||||||
|
public List getLibraries()
|
||||||
|
{
|
||||||
|
return librariesConfiguration.getBaseDirectories();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setExtraScanTargetsConfiguration(
|
||||||
|
FileMatchingConfiguration extraScanTargetsConfiguration)
|
||||||
|
{
|
||||||
|
this.extraScanTargetsConfiguration = extraScanTargetsConfiguration;
|
||||||
|
TaskLog.log("Extra scan targets = " + extraScanTargetsConfiguration.getBaseDirectories());
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setAttributes(List attributes)
|
||||||
|
{
|
||||||
|
this.attributes = attributes;
|
||||||
|
}
|
||||||
|
|
||||||
|
public List getExtraScanTargets()
|
||||||
|
{
|
||||||
|
return extraScanTargetsConfiguration.getBaseDirectories();
|
||||||
|
}
|
||||||
|
|
||||||
|
public List getContextHandlers()
|
||||||
|
{
|
||||||
|
return contextHandlers;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setContextHandlers(List contextHandlers)
|
||||||
|
{
|
||||||
|
this.contextHandlers = contextHandlers;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @see WebApplicationProxy#getProxiedObject()
|
||||||
|
*/
|
||||||
|
public Object getProxiedObject()
|
||||||
|
{
|
||||||
|
return webAppContext;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @see WebApplicationProxy#start()
|
||||||
|
*/
|
||||||
|
public void start()
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
TaskLog.logWithTimestamp("Starting web application " + name + " ...\n");
|
||||||
|
webAppContext.start();
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
TaskLog.log(e.toString());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @see WebApplicationProxy#stop()
|
||||||
|
*/
|
||||||
|
public void stop()
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
TaskLog.logWithTimestamp("Stopping web application " + name + " ...");
|
||||||
|
Thread.currentThread().sleep(500L);
|
||||||
|
webAppContext.stop();
|
||||||
|
}
|
||||||
|
catch (InterruptedException e)
|
||||||
|
{
|
||||||
|
TaskLog.log(e.toString());
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
TaskLog.log(e.toString());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @see WebApplicationProxy#createApplicationContext(org.eclipse.jetty.server.handler.ContextHandlerCollection)
|
||||||
|
*/
|
||||||
|
public void createApplicationContext(ContextHandlerCollection contexts)
|
||||||
|
{
|
||||||
|
webAppContext = new AntWebAppContext(contexts, warFile.getAbsolutePath(), contextPath);
|
||||||
|
webAppContext.setDisplayName(name);
|
||||||
|
|
||||||
|
configurePaths();
|
||||||
|
|
||||||
|
if ( !attributes.isEmpty() )
|
||||||
|
{
|
||||||
|
for ( Iterator i = attributes.iterator(); i.hasNext(); )
|
||||||
|
{
|
||||||
|
Attribute attr = (Attribute) i.next();
|
||||||
|
|
||||||
|
webAppContext.setAttribute(attr.getName(),attr.getValue());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
configureHandlers(contexts);
|
||||||
|
|
||||||
|
applyConfiguration();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void configureHandlers(ContextHandlerCollection contexts)
|
||||||
|
{
|
||||||
|
// adding extra context handlers
|
||||||
|
Iterator handlersIterator = contextHandlers.iterator();
|
||||||
|
while (handlersIterator.hasNext())
|
||||||
|
{
|
||||||
|
ContextHandler contextHandler = (ContextHandler) handlersIterator.next();
|
||||||
|
contexts.addHandler(contextHandler);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void configurePaths()
|
||||||
|
{
|
||||||
|
// configuring temp directory
|
||||||
|
File tempDir = new File(baseTempDirectory, contextPath);
|
||||||
|
if (!tempDir.exists())
|
||||||
|
{
|
||||||
|
tempDir.mkdirs();
|
||||||
|
}
|
||||||
|
webAppContext.setTempDirectory(tempDir);
|
||||||
|
tempDir.deleteOnExit();
|
||||||
|
TaskLog.log("Temp directory = " + tempDir.getAbsolutePath());
|
||||||
|
|
||||||
|
// configuring WAR directory for packaged web applications
|
||||||
|
if (warFile.isFile())
|
||||||
|
{
|
||||||
|
warFile = new File(tempDir, "webapp");
|
||||||
|
webXmlFile = new File(new File(warFile, "WEB-INF"), "web.xml");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Applies web application configuration at the end of configuration process
|
||||||
|
* or after application restart.
|
||||||
|
*/
|
||||||
|
void applyConfiguration()
|
||||||
|
{
|
||||||
|
for (int i = 0; i < configurations.length; i++)
|
||||||
|
{
|
||||||
|
if (configurations[i] instanceof EnvConfiguration)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
if (jettyEnvXml != null && jettyEnvXml.exists())
|
||||||
|
{
|
||||||
|
((EnvConfiguration) configurations[i]).setJettyEnvXml(Resource.toURL(jettyEnvXml));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (MalformedURLException e)
|
||||||
|
{
|
||||||
|
throw new RuntimeException(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (configurations[i] instanceof AntWebXmlConfiguration)
|
||||||
|
{
|
||||||
|
((AntWebXmlConfiguration) configurations[i]).setClassPathFiles(classPathFiles);
|
||||||
|
((AntWebXmlConfiguration) configurations[i]).setWebAppBaseDir(warFile);
|
||||||
|
((AntWebXmlConfiguration) configurations[i]).setWebXmlFile(webXmlFile);
|
||||||
|
((AntWebXmlConfiguration) configurations[i]).setWebDefaultXmlFile(webDefaultXmlFile);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
ClassLoader loader = new WebAppClassLoader(this.getClass().getClassLoader(),
|
||||||
|
webAppContext);
|
||||||
|
webAppContext.setParentLoaderPriority(true);
|
||||||
|
webAppContext.setClassLoader(loader);
|
||||||
|
if (webDefaultXmlFile != null)
|
||||||
|
webAppContext.setDefaultsDescriptor(webDefaultXmlFile.getCanonicalPath());
|
||||||
|
|
||||||
|
}
|
||||||
|
catch (IOException e)
|
||||||
|
{
|
||||||
|
TaskLog.log(e.toString());
|
||||||
|
}
|
||||||
|
|
||||||
|
webAppContext.setConfigurations(configurations);
|
||||||
|
}
|
||||||
|
|
||||||
|
private File webDefaultXmlFile;
|
||||||
|
|
||||||
|
public File getWebDefaultXmlFile()
|
||||||
|
{
|
||||||
|
return this.webDefaultXmlFile;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setWebDefaultXmlFile(File webDefaultXmlfile)
|
||||||
|
{
|
||||||
|
this.webDefaultXmlFile = webDefaultXmlfile;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,47 @@
|
||||||
|
//
|
||||||
|
// ========================================================================
|
||||||
|
// Copyright (c) 1995-2012 Mort Bay Consulting Pty. Ltd.
|
||||||
|
// ------------------------------------------------------------------------
|
||||||
|
// All rights reserved. This program and the accompanying materials
|
||||||
|
// are made available under the terms of the Eclipse Public License v1.0
|
||||||
|
// and Apache License v2.0 which accompanies this distribution.
|
||||||
|
//
|
||||||
|
// The Eclipse Public License is available at
|
||||||
|
// http://www.eclipse.org/legal/epl-v10.html
|
||||||
|
//
|
||||||
|
// The Apache License v2.0 is available at
|
||||||
|
// http://www.opensource.org/licenses/apache2.0.php
|
||||||
|
//
|
||||||
|
// You may elect to redistribute this code under either of these licenses.
|
||||||
|
// ========================================================================
|
||||||
|
//
|
||||||
|
|
||||||
|
package org.eclipse.jetty.ant.types;
|
||||||
|
|
||||||
|
public class Attribute
|
||||||
|
{
|
||||||
|
|
||||||
|
String name;
|
||||||
|
|
||||||
|
String value;
|
||||||
|
|
||||||
|
public void setName(String name)
|
||||||
|
{
|
||||||
|
this.name = name;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setValue(String value)
|
||||||
|
{
|
||||||
|
this.value = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getName()
|
||||||
|
{
|
||||||
|
return name;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getValue()
|
||||||
|
{
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,38 @@
|
||||||
|
//
|
||||||
|
// ========================================================================
|
||||||
|
// Copyright (c) 1995-2012 Mort Bay Consulting Pty. Ltd.
|
||||||
|
// ------------------------------------------------------------------------
|
||||||
|
// All rights reserved. This program and the accompanying materials
|
||||||
|
// are made available under the terms of the Eclipse Public License v1.0
|
||||||
|
// and Apache License v2.0 which accompanies this distribution.
|
||||||
|
//
|
||||||
|
// The Eclipse Public License is available at
|
||||||
|
// http://www.eclipse.org/legal/epl-v10.html
|
||||||
|
//
|
||||||
|
// The Apache License v2.0 is available at
|
||||||
|
// http://www.opensource.org/licenses/apache2.0.php
|
||||||
|
//
|
||||||
|
// You may elect to redistribute this code under either of these licenses.
|
||||||
|
// ========================================================================
|
||||||
|
//
|
||||||
|
|
||||||
|
package org.eclipse.jetty.ant.types;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
public class Attributes
|
||||||
|
{
|
||||||
|
|
||||||
|
List _attributes = new ArrayList();
|
||||||
|
|
||||||
|
public void addAttribute(Attribute attr )
|
||||||
|
{
|
||||||
|
_attributes.add(attr);
|
||||||
|
}
|
||||||
|
|
||||||
|
public List getAttributes()
|
||||||
|
{
|
||||||
|
return _attributes;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,116 @@
|
||||||
|
//
|
||||||
|
// ========================================================================
|
||||||
|
// Copyright (c) 1995-2012 Sabre Holdings.
|
||||||
|
// ------------------------------------------------------------------------
|
||||||
|
// 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.ant.types;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import org.eclipse.jetty.server.Connector;
|
||||||
|
import org.eclipse.jetty.server.SelectChannelConnector;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Specifies a jetty configuration <connectors/> element for Ant build file.
|
||||||
|
*
|
||||||
|
* @author Jakub Pawlowicz
|
||||||
|
*/
|
||||||
|
public class Connectors
|
||||||
|
{
|
||||||
|
private List<Connector> connectors = new ArrayList<Connector>();
|
||||||
|
private List<Connector> defaultConnectors = new ArrayList<Connector>();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Default constructor.
|
||||||
|
*/
|
||||||
|
public Connectors() {
|
||||||
|
this(8080, 30000);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructor.
|
||||||
|
*
|
||||||
|
* @param port The port that the default connector will listen on
|
||||||
|
* @param maxIdleTime The maximum idle time for the default connector
|
||||||
|
*/
|
||||||
|
public Connectors(int port, int maxIdleTime)
|
||||||
|
{
|
||||||
|
defaultConnectors.add(new Connector(port, maxIdleTime));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Adds a connector to the list of connectors to deploy.
|
||||||
|
*
|
||||||
|
* @param connector A connector to add to the list
|
||||||
|
*/
|
||||||
|
public void add(Connector connector)
|
||||||
|
{
|
||||||
|
connectors.add(connector);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the list of known connectors to deploy.
|
||||||
|
*
|
||||||
|
* @return The list of known connectors
|
||||||
|
*/
|
||||||
|
public List<Connector> getConnectors()
|
||||||
|
{
|
||||||
|
return connectors;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the default list of connectors to deploy when no connectors
|
||||||
|
* were explicitly added to the list.
|
||||||
|
*
|
||||||
|
* @return The list of default connectors
|
||||||
|
*/
|
||||||
|
public List<Connector> getDefaultConnectors()
|
||||||
|
{
|
||||||
|
return defaultConnectors;
|
||||||
|
}
|
||||||
|
|
||||||
|
public class Connector
|
||||||
|
{
|
||||||
|
private int port;
|
||||||
|
private int maxIdleTime;
|
||||||
|
|
||||||
|
public Connector(int port, int maxIdleTime)
|
||||||
|
{
|
||||||
|
this.port = port;
|
||||||
|
this.maxIdleTime = maxIdleTime;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getPort() {
|
||||||
|
return port;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setPort(int port) {
|
||||||
|
this.port = port;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getMaxIdleTime() {
|
||||||
|
return maxIdleTime;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setMaxIdleTime(int maxIdleTime) {
|
||||||
|
this.maxIdleTime = maxIdleTime;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,46 @@
|
||||||
|
//
|
||||||
|
// ========================================================================
|
||||||
|
// Copyright (c) 1995-2012 Sabre Holdings.
|
||||||
|
// ------------------------------------------------------------------------
|
||||||
|
// 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.ant.types;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import org.eclipse.jetty.server.handler.ContextHandler;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Specifies <contextHandlers/> element in web app configuration.
|
||||||
|
*
|
||||||
|
* @author Jakub Pawlowicz
|
||||||
|
*/
|
||||||
|
public class ContextHandlers
|
||||||
|
{
|
||||||
|
|
||||||
|
private List contextHandlers = new ArrayList();
|
||||||
|
|
||||||
|
public void add(ContextHandler handler)
|
||||||
|
{
|
||||||
|
contextHandlers.add(handler);
|
||||||
|
}
|
||||||
|
|
||||||
|
public List getContextHandlers()
|
||||||
|
{
|
||||||
|
return contextHandlers;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,99 @@
|
||||||
|
//
|
||||||
|
// ========================================================================
|
||||||
|
// Copyright (c) 1995-2012 Sabre Holdings.
|
||||||
|
// ------------------------------------------------------------------------
|
||||||
|
// 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.ant.types;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Iterator;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import org.apache.tools.ant.DirectoryScanner;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Describes set of files matched by <fileset/> elements in ant configuration
|
||||||
|
* file. It is used to group application classes, libraries, and scannedTargets
|
||||||
|
* elements.
|
||||||
|
*
|
||||||
|
* @author Jakub Pawlowicz
|
||||||
|
*/
|
||||||
|
public class FileMatchingConfiguration
|
||||||
|
{
|
||||||
|
|
||||||
|
private List directoryScanners;
|
||||||
|
|
||||||
|
public FileMatchingConfiguration()
|
||||||
|
{
|
||||||
|
this.directoryScanners = new ArrayList();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param directoryScanner new directory scanner retrieved from the
|
||||||
|
* <fileset/> element.
|
||||||
|
*/
|
||||||
|
public void addDirectoryScanner(DirectoryScanner directoryScanner)
|
||||||
|
{
|
||||||
|
this.directoryScanners.add(directoryScanner);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return a list of base directories denoted by a list of directory
|
||||||
|
* scanners.
|
||||||
|
*/
|
||||||
|
public List getBaseDirectories()
|
||||||
|
{
|
||||||
|
List baseDirs = new ArrayList();
|
||||||
|
Iterator scanners = directoryScanners.iterator();
|
||||||
|
while (scanners.hasNext())
|
||||||
|
{
|
||||||
|
DirectoryScanner scanner = (DirectoryScanner) scanners.next();
|
||||||
|
baseDirs.add(scanner.getBasedir());
|
||||||
|
}
|
||||||
|
|
||||||
|
return baseDirs;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Checks if passed file is scanned by any of the directory scanners.
|
||||||
|
*
|
||||||
|
* @param pathToFile a fully qualified path to tested file.
|
||||||
|
* @return true if so, false otherwise.
|
||||||
|
*/
|
||||||
|
public boolean isIncluded(String pathToFile)
|
||||||
|
{
|
||||||
|
Iterator scanners = directoryScanners.iterator();
|
||||||
|
while (scanners.hasNext())
|
||||||
|
{
|
||||||
|
DirectoryScanner scanner = (DirectoryScanner) scanners.next();
|
||||||
|
scanner.scan();
|
||||||
|
String[] includedFiles = scanner.getIncludedFiles();
|
||||||
|
|
||||||
|
for (int i = 0; i < includedFiles.length; i++)
|
||||||
|
{
|
||||||
|
File includedFile = new File(scanner.getBasedir(), includedFiles[i]);
|
||||||
|
if (pathToFile.equalsIgnoreCase(includedFile.getAbsolutePath()))
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,46 @@
|
||||||
|
//
|
||||||
|
// ========================================================================
|
||||||
|
// Copyright (c) 1995-2012 Sabre Holdings.
|
||||||
|
// ------------------------------------------------------------------------
|
||||||
|
// 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.ant.types;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import org.eclipse.jetty.security.LoginService;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Specifies a jetty configuration <loginServices/> element for Ant build file.
|
||||||
|
*
|
||||||
|
* @author Jakub Pawlowicz
|
||||||
|
*/
|
||||||
|
public class LoginServices
|
||||||
|
{
|
||||||
|
|
||||||
|
private List loginServices = new ArrayList();
|
||||||
|
|
||||||
|
public void add(LoginService service)
|
||||||
|
{
|
||||||
|
loginServices.add(service);
|
||||||
|
}
|
||||||
|
|
||||||
|
public List getLoginServices()
|
||||||
|
{
|
||||||
|
return loginServices;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,66 @@
|
||||||
|
//
|
||||||
|
// ========================================================================
|
||||||
|
// Copyright (c) 1995-2012 Sabre Holdings.
|
||||||
|
// ------------------------------------------------------------------------
|
||||||
|
// 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.ant.types;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import org.apache.tools.ant.taskdefs.Property;
|
||||||
|
import org.eclipse.jetty.ant.utils.TaskLog;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Ant <systemProperties/> tag definition.
|
||||||
|
*
|
||||||
|
* @author Jakub Pawlowicz
|
||||||
|
*/
|
||||||
|
public class SystemProperties
|
||||||
|
{
|
||||||
|
|
||||||
|
private List systemProperties = new ArrayList();
|
||||||
|
|
||||||
|
public List getSystemProperties()
|
||||||
|
{
|
||||||
|
return systemProperties;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void addSystemProperty(Property property)
|
||||||
|
{
|
||||||
|
systemProperties.add(property);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set a System.property with this value if it is not already set.
|
||||||
|
*
|
||||||
|
* @returns true if property has been set
|
||||||
|
*/
|
||||||
|
public static boolean setIfNotSetAlready(Property property)
|
||||||
|
{
|
||||||
|
if (System.getProperty(property.getName()) == null)
|
||||||
|
{
|
||||||
|
System.setProperty(property.getName(), (property.getValue() == null ? "" : property
|
||||||
|
.getValue()));
|
||||||
|
TaskLog.log("Setting property '" + property.getName() + "' to value '"
|
||||||
|
+ property.getValue() + "'");
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,296 @@
|
||||||
|
//
|
||||||
|
// ========================================================================
|
||||||
|
// Copyright (c) 1995-2012 Sabre Holdings.
|
||||||
|
// ------------------------------------------------------------------------
|
||||||
|
// 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.ant.types;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.Enumeration;
|
||||||
|
import java.util.Iterator;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
import org.apache.tools.ant.BuildException;
|
||||||
|
import org.apache.tools.ant.DirectoryScanner;
|
||||||
|
import org.apache.tools.ant.Project;
|
||||||
|
import org.apache.tools.ant.types.FileSet;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Ant's WebApp object definition.
|
||||||
|
*
|
||||||
|
* @author Jakub Pawlowicz
|
||||||
|
*/
|
||||||
|
public class WebApp
|
||||||
|
{
|
||||||
|
|
||||||
|
/** List of web application libraries. */
|
||||||
|
private List libraries = new ArrayList();
|
||||||
|
|
||||||
|
/** List of web application class directories. */
|
||||||
|
private List classes = new ArrayList();
|
||||||
|
|
||||||
|
/** Reference to Ant project variable. */
|
||||||
|
private Project project;
|
||||||
|
|
||||||
|
/** Application context path. */
|
||||||
|
private String contextPath;
|
||||||
|
|
||||||
|
/** Application name. */
|
||||||
|
private String name;
|
||||||
|
|
||||||
|
/** Application war file (either exploded or not). */
|
||||||
|
private File warFile;
|
||||||
|
|
||||||
|
/** Location of application web.xml file. */
|
||||||
|
private File webXmlFile;
|
||||||
|
|
||||||
|
/** Location of jetty-env.xml file. */
|
||||||
|
private File jettyEnvXml;
|
||||||
|
|
||||||
|
/** List of extra scan targets for this web application. */
|
||||||
|
private FileSet scanTargets;
|
||||||
|
|
||||||
|
/** List of the attributes to set to webapp context */
|
||||||
|
private Attributes attributes;
|
||||||
|
|
||||||
|
/** List of optional context handlers. */
|
||||||
|
private ContextHandlers contextHandlers;
|
||||||
|
|
||||||
|
private File webDefaultXmlFile;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Length of interval in which application will be scanned for changes (0
|
||||||
|
* means scanner wouldn't be created).
|
||||||
|
*/
|
||||||
|
private int scanIntervalSeconds = 0;
|
||||||
|
|
||||||
|
public WebApp(Project project)
|
||||||
|
{
|
||||||
|
this.project = project;
|
||||||
|
}
|
||||||
|
|
||||||
|
public File getWebDefaultXmlFile()
|
||||||
|
{
|
||||||
|
return this.webDefaultXmlFile;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setWebDefaultXmlFile(File webDefaultXmlfile)
|
||||||
|
{
|
||||||
|
this.webDefaultXmlFile = webDefaultXmlfile;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void addLib(FileSet lib)
|
||||||
|
{
|
||||||
|
libraries.add(lib);
|
||||||
|
}
|
||||||
|
|
||||||
|
public List getLibraries()
|
||||||
|
{
|
||||||
|
return libraries;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void addClasses(FileSet classes)
|
||||||
|
{
|
||||||
|
this.classes.add(classes);
|
||||||
|
}
|
||||||
|
|
||||||
|
public List getClasses()
|
||||||
|
{
|
||||||
|
return classes;
|
||||||
|
}
|
||||||
|
|
||||||
|
public File getWarFile()
|
||||||
|
{
|
||||||
|
return warFile;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setWarFile(File warFile)
|
||||||
|
{
|
||||||
|
this.warFile = warFile;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getContextPath()
|
||||||
|
{
|
||||||
|
return contextPath;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setContextPath(String contextPath)
|
||||||
|
{
|
||||||
|
this.contextPath = contextPath;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getName()
|
||||||
|
{
|
||||||
|
return name;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setName(String name)
|
||||||
|
{
|
||||||
|
this.name = name;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return a list of classpath files (libraries and class directories).
|
||||||
|
*/
|
||||||
|
public List getClassPathFiles()
|
||||||
|
{
|
||||||
|
List classPathFiles = new ArrayList();
|
||||||
|
Iterator classesIterator = classes.iterator();
|
||||||
|
while (classesIterator.hasNext())
|
||||||
|
{
|
||||||
|
FileSet clazz = (FileSet) classesIterator.next();
|
||||||
|
classPathFiles.add(clazz.getDirectoryScanner(project).getBasedir());
|
||||||
|
}
|
||||||
|
|
||||||
|
Iterator iterator = libraries.iterator();
|
||||||
|
while (iterator.hasNext())
|
||||||
|
{
|
||||||
|
FileSet library = (FileSet) iterator.next();
|
||||||
|
String[] includedFiles = library.getDirectoryScanner(project).getIncludedFiles();
|
||||||
|
File baseDir = library.getDirectoryScanner(project).getBasedir();
|
||||||
|
|
||||||
|
for (int i = 0; i < includedFiles.length; i++)
|
||||||
|
{
|
||||||
|
classPathFiles.add(new File(baseDir, includedFiles[i]));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
return classPathFiles;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return a <code>FileMatchingConfiguration</code> object describing the
|
||||||
|
* configuration of all libraries added to this particular web app
|
||||||
|
* (both classes and libraries).
|
||||||
|
*/
|
||||||
|
public FileMatchingConfiguration getLibrariesConfiguration()
|
||||||
|
{
|
||||||
|
FileMatchingConfiguration config = new FileMatchingConfiguration();
|
||||||
|
|
||||||
|
Iterator classesIterator = classes.iterator();
|
||||||
|
while (classesIterator.hasNext())
|
||||||
|
{
|
||||||
|
FileSet clazz = (FileSet) classesIterator.next();
|
||||||
|
config.addDirectoryScanner(clazz.getDirectoryScanner(project));
|
||||||
|
}
|
||||||
|
|
||||||
|
Iterator librariesIterator = libraries.iterator();
|
||||||
|
while (librariesIterator.hasNext())
|
||||||
|
{
|
||||||
|
FileSet library = (FileSet) librariesIterator.next();
|
||||||
|
config.addDirectoryScanner(library.getDirectoryScanner(project));
|
||||||
|
}
|
||||||
|
|
||||||
|
return config;
|
||||||
|
}
|
||||||
|
|
||||||
|
public FileMatchingConfiguration getScanTargetsConfiguration()
|
||||||
|
{
|
||||||
|
FileMatchingConfiguration configuration = new FileMatchingConfiguration();
|
||||||
|
|
||||||
|
if (scanTargets != null)
|
||||||
|
{
|
||||||
|
configuration.addDirectoryScanner(scanTargets.getDirectoryScanner(project));
|
||||||
|
}
|
||||||
|
|
||||||
|
return configuration;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return location of web.xml file (either inside WAR or on the external
|
||||||
|
* location).
|
||||||
|
*/
|
||||||
|
public File getWebXmlFile()
|
||||||
|
{
|
||||||
|
if (webXmlFile == null)
|
||||||
|
{
|
||||||
|
File webInf = new File(warFile, "WEB-INF");
|
||||||
|
return new File(webInf, "web.xml");
|
||||||
|
}
|
||||||
|
|
||||||
|
return webXmlFile;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setWebXmlFile(File webXmlFile)
|
||||||
|
{
|
||||||
|
this.webXmlFile = webXmlFile;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void addScanTargets(FileSet scanTargets)
|
||||||
|
{
|
||||||
|
if (this.scanTargets != null)
|
||||||
|
{
|
||||||
|
throw new BuildException("Only one <scanTargets> tag is allowed!");
|
||||||
|
}
|
||||||
|
|
||||||
|
this.scanTargets = scanTargets;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void addContextHandlers(ContextHandlers contextHandlers)
|
||||||
|
{
|
||||||
|
if (this.contextHandlers != null)
|
||||||
|
{
|
||||||
|
throw new BuildException("Only one <contextHandlers> tag is allowed!");
|
||||||
|
}
|
||||||
|
|
||||||
|
this.contextHandlers = contextHandlers;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void addAttributes(Attributes attributes)
|
||||||
|
{
|
||||||
|
if (this.attributes != null)
|
||||||
|
{
|
||||||
|
throw new BuildException("Only one <attributes> tag is allowed!");
|
||||||
|
}
|
||||||
|
|
||||||
|
this.attributes = attributes;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getScanIntervalSeconds()
|
||||||
|
{
|
||||||
|
return scanIntervalSeconds;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setScanIntervalSeconds(int scanIntervalSeconds)
|
||||||
|
{
|
||||||
|
this.scanIntervalSeconds = scanIntervalSeconds;
|
||||||
|
}
|
||||||
|
|
||||||
|
public File getJettyEnvXml()
|
||||||
|
{
|
||||||
|
return jettyEnvXml;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setJettyEnvXml(File jettyEnvXml)
|
||||||
|
{
|
||||||
|
this.jettyEnvXml = jettyEnvXml;
|
||||||
|
}
|
||||||
|
|
||||||
|
public List getContextHandlers()
|
||||||
|
{
|
||||||
|
return (contextHandlers != null ? contextHandlers.getContextHandlers() : new ArrayList());
|
||||||
|
}
|
||||||
|
|
||||||
|
public List getAttributes()
|
||||||
|
{
|
||||||
|
return (attributes != null ? attributes.getAttributes() : new ArrayList());
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,40 @@
|
||||||
|
//
|
||||||
|
// ========================================================================
|
||||||
|
// Copyright (c) 1995-2012 Sabre Holdings.
|
||||||
|
// ------------------------------------------------------------------------
|
||||||
|
// 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.ant.utils;
|
||||||
|
|
||||||
|
public interface ServerProxy
|
||||||
|
{
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Adds a new web application to this server.
|
||||||
|
*
|
||||||
|
* @param webApp a WebApplicationProxy object.
|
||||||
|
* @param scanIntervalSeconds
|
||||||
|
*/
|
||||||
|
public void addWebApplication(WebApplicationProxy webApp, int scanIntervalSeconds);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Starts this server.
|
||||||
|
*/
|
||||||
|
public void start();
|
||||||
|
|
||||||
|
public Object getProxiedObject();
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,54 @@
|
||||||
|
//
|
||||||
|
// ========================================================================
|
||||||
|
// Copyright (c) 1995-2012 Sabre Holdings.
|
||||||
|
// ------------------------------------------------------------------------
|
||||||
|
// 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.ant.utils;
|
||||||
|
|
||||||
|
import java.text.SimpleDateFormat;
|
||||||
|
import java.util.Date;
|
||||||
|
|
||||||
|
import org.apache.tools.ant.Task;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Provides logging functionality for classes without access to the Ant project
|
||||||
|
* variable.
|
||||||
|
*
|
||||||
|
* @author Jakub Pawlowicz
|
||||||
|
*/
|
||||||
|
public class TaskLog
|
||||||
|
{
|
||||||
|
|
||||||
|
private static Task task;
|
||||||
|
|
||||||
|
private static SimpleDateFormat format = new SimpleDateFormat(
|
||||||
|
"yyyy-MM-dd HH:mm:ss.SSS");
|
||||||
|
|
||||||
|
public static void setTask(Task task)
|
||||||
|
{
|
||||||
|
TaskLog.task = task;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void log(String message)
|
||||||
|
{
|
||||||
|
task.log(message);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void logWithTimestamp(String message)
|
||||||
|
{
|
||||||
|
task.log(format.format(new Date()) + ": " + message);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,47 @@
|
||||||
|
//
|
||||||
|
// ========================================================================
|
||||||
|
// Copyright (c) 1995-2012 Sabre Holdings.
|
||||||
|
// ------------------------------------------------------------------------
|
||||||
|
// 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.ant.utils;
|
||||||
|
|
||||||
|
import org.eclipse.jetty.server.handler.ContextHandlerCollection;
|
||||||
|
|
||||||
|
public interface WebApplicationProxy
|
||||||
|
{
|
||||||
|
|
||||||
|
public Object getProxiedObject();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Starts this web application context.
|
||||||
|
*/
|
||||||
|
public void start();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Stops this web application context.
|
||||||
|
*/
|
||||||
|
public void stop();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a new Jetty web application context from this object.
|
||||||
|
*
|
||||||
|
* @param contexts collection of context this application should be added
|
||||||
|
* to.
|
||||||
|
*/
|
||||||
|
public void createApplicationContext(ContextHandlerCollection contexts);
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1 @@
|
||||||
|
jetty=org.eclipse.jetty.ant.JettyRunTask
|
|
@ -0,0 +1,43 @@
|
||||||
|
<!-- =======================================================================================-->
|
||||||
|
<!-- Build file for running the test-jetty-webapp from the jetty distro. -->
|
||||||
|
<!-- -->
|
||||||
|
<!-- You will need to have a full jetty-distribution available unpacked on your local file -->
|
||||||
|
<!-- system. We will refer to the top level directory of this distribution as $JETTY_HOME. -->
|
||||||
|
<!-- -->
|
||||||
|
<!-- To use: -->
|
||||||
|
<!-- * mkdir test-jetty-ant -->
|
||||||
|
<!-- * cp this file to test-jetty-ant -->
|
||||||
|
<!-- * cd test-jetty-ant; mkdir jetty-lib; mkdir war; mkdir jetty-temp -->
|
||||||
|
<!-- * copy all jars from $JETTY_HOME/lib and all subdirs flatly into ./jetty-lib -->
|
||||||
|
<!-- * unjar the test.war from $JETTY_HOME/webapps dir into ./war -->
|
||||||
|
<!-- * cp $JETTY_HOME/etc/webdefaults.xml to . -->
|
||||||
|
<!-- * cp $JETTY_HOME/etc/realm.properties to . -->
|
||||||
|
<!-- -->
|
||||||
|
<!-- To run: -->
|
||||||
|
<!-- ant jetty.run -->
|
||||||
|
<!-- =======================================================================================-->
|
||||||
|
<project name="Jetty-Ant integration test" basedir=".">
|
||||||
|
<path id="jetty.plugin.classpath">
|
||||||
|
<fileset dir="jetty-lib" includes="*.jar"/>
|
||||||
|
</path>
|
||||||
|
<taskdef classpathref="jetty.plugin.classpath" resource="tasks.properties" loaderref="jetty.loader" />
|
||||||
|
|
||||||
|
<typedef name="hashLoginService" classname="org.eclipse.jetty.security.HashLoginService"
|
||||||
|
classpathref="jetty.plugin.classpath" loaderref="jetty.loader" />
|
||||||
|
|
||||||
|
<target name="jetty.run">
|
||||||
|
<jetty tempDirectory="jetty-temp">
|
||||||
|
<loginServices>
|
||||||
|
<hashLoginService name="Test Realm" config="realm.properties"/>
|
||||||
|
</loginServices>
|
||||||
|
<webApp name="test"
|
||||||
|
warfile="war"
|
||||||
|
webDefaultXmlFile="webdefault.xml"
|
||||||
|
contextpath="/test" >
|
||||||
|
<attributes>
|
||||||
|
<attribute name="org.eclipse.jetty.server.webapp.ContainerIncludeJarPattern" value=".*/.*jsp-api-[^/]*\.jar$|.*/.*jsp-[^/]*\.jar$|.*/.*taglibs[^/]*\.jar$"/>
|
||||||
|
</attributes>
|
||||||
|
</webApp>
|
||||||
|
</jetty>
|
||||||
|
</target>
|
||||||
|
</project>
|
|
@ -0,0 +1,28 @@
|
||||||
|
//
|
||||||
|
// ========================================================================
|
||||||
|
// Copyright (c) 1995-2012 Mort Bay Consulting Pty. Ltd.
|
||||||
|
// ------------------------------------------------------------------------
|
||||||
|
// All rights reserved. This program and the accompanying materials
|
||||||
|
// are made available under the terms of the Eclipse Public License v1.0
|
||||||
|
// and Apache License v2.0 which accompanies this distribution.
|
||||||
|
//
|
||||||
|
// The Eclipse Public License is available at
|
||||||
|
// http://www.eclipse.org/legal/epl-v10.html
|
||||||
|
//
|
||||||
|
// The Apache License v2.0 is available at
|
||||||
|
// http://www.opensource.org/licenses/apache2.0.php
|
||||||
|
//
|
||||||
|
// You may elect to redistribute this code under either of these licenses.
|
||||||
|
// ========================================================================
|
||||||
|
//
|
||||||
|
package org.eclipse.jetty.ant;
|
||||||
|
|
||||||
|
import junit.framework.TestCase;
|
||||||
|
|
||||||
|
public class JettyRunTaskTest extends TestCase
|
||||||
|
{
|
||||||
|
public void testInit()
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
|
@ -354,11 +354,6 @@
|
||||||
<artifactId>jetty-rewrite</artifactId>
|
<artifactId>jetty-rewrite</artifactId>
|
||||||
<version>${project.version}</version>
|
<version>${project.version}</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
<dependency>
|
|
||||||
<groupId>org.eclipse.jetty</groupId>
|
|
||||||
<artifactId>jetty-ajp</artifactId>
|
|
||||||
<version>${project.version}</version>
|
|
||||||
</dependency>
|
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.eclipse.jetty</groupId>
|
<groupId>org.eclipse.jetty</groupId>
|
||||||
<artifactId>jetty-annotations</artifactId>
|
<artifactId>jetty-annotations</artifactId>
|
||||||
|
|
|
@ -40,7 +40,7 @@ import org.eclipse.jetty.plus.jaas.callback.RequestParameterCallback;
|
||||||
import org.eclipse.jetty.security.DefaultIdentityService;
|
import org.eclipse.jetty.security.DefaultIdentityService;
|
||||||
import org.eclipse.jetty.security.IdentityService;
|
import org.eclipse.jetty.security.IdentityService;
|
||||||
import org.eclipse.jetty.security.LoginService;
|
import org.eclipse.jetty.security.LoginService;
|
||||||
import org.eclipse.jetty.server.AbstractHttpConnection;
|
import org.eclipse.jetty.server.HttpChannel;
|
||||||
import org.eclipse.jetty.server.Request;
|
import org.eclipse.jetty.server.Request;
|
||||||
import org.eclipse.jetty.server.UserIdentity;
|
import org.eclipse.jetty.server.UserIdentity;
|
||||||
import org.eclipse.jetty.util.Loader;
|
import org.eclipse.jetty.util.Loader;
|
||||||
|
@ -210,8 +210,11 @@ public class JAASLoginService extends AbstractLifeCycle implements LoginService
|
||||||
}
|
}
|
||||||
else if (callback instanceof RequestParameterCallback)
|
else if (callback instanceof RequestParameterCallback)
|
||||||
{
|
{
|
||||||
AbstractHttpConnection connection = AbstractHttpConnection.getCurrentConnection();
|
HttpChannel channel = HttpChannel.getCurrentHttpChannel();
|
||||||
Request request = (connection == null? null : connection.getRequest());
|
|
||||||
|
if (channel == null)
|
||||||
|
return;
|
||||||
|
Request request = channel.getRequest();
|
||||||
|
|
||||||
if (request != null)
|
if (request != null)
|
||||||
{
|
{
|
||||||
|
|
|
@ -19,6 +19,10 @@
|
||||||
package org.eclipse.jetty.websocket.client;
|
package org.eclipse.jetty.websocket.client;
|
||||||
|
|
||||||
import java.net.SocketAddress;
|
import java.net.SocketAddress;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Queue;
|
||||||
|
import java.util.concurrent.ConcurrentLinkedQueue;
|
||||||
import java.util.concurrent.Executor;
|
import java.util.concurrent.Executor;
|
||||||
import java.util.concurrent.Executors;
|
import java.util.concurrent.Executors;
|
||||||
import java.util.concurrent.ScheduledExecutorService;
|
import java.util.concurrent.ScheduledExecutorService;
|
||||||
|
@ -30,6 +34,7 @@ import org.eclipse.jetty.util.log.Log;
|
||||||
import org.eclipse.jetty.util.log.Logger;
|
import org.eclipse.jetty.util.log.Logger;
|
||||||
import org.eclipse.jetty.util.ssl.SslContextFactory;
|
import org.eclipse.jetty.util.ssl.SslContextFactory;
|
||||||
import org.eclipse.jetty.util.thread.QueuedThreadPool;
|
import org.eclipse.jetty.util.thread.QueuedThreadPool;
|
||||||
|
import org.eclipse.jetty.websocket.api.Extension;
|
||||||
import org.eclipse.jetty.websocket.api.ExtensionRegistry;
|
import org.eclipse.jetty.websocket.api.ExtensionRegistry;
|
||||||
import org.eclipse.jetty.websocket.api.WebSocketPolicy;
|
import org.eclipse.jetty.websocket.api.WebSocketPolicy;
|
||||||
import org.eclipse.jetty.websocket.client.internal.ConnectionManager;
|
import org.eclipse.jetty.websocket.client.internal.ConnectionManager;
|
||||||
|
@ -37,6 +42,8 @@ import org.eclipse.jetty.websocket.client.internal.IWebSocketClient;
|
||||||
import org.eclipse.jetty.websocket.driver.EventMethodsCache;
|
import org.eclipse.jetty.websocket.driver.EventMethodsCache;
|
||||||
import org.eclipse.jetty.websocket.driver.WebSocketEventDriver;
|
import org.eclipse.jetty.websocket.driver.WebSocketEventDriver;
|
||||||
import org.eclipse.jetty.websocket.extensions.WebSocketExtensionRegistry;
|
import org.eclipse.jetty.websocket.extensions.WebSocketExtensionRegistry;
|
||||||
|
import org.eclipse.jetty.websocket.io.WebSocketSession;
|
||||||
|
import org.eclipse.jetty.websocket.protocol.ExtensionConfig;
|
||||||
|
|
||||||
public class WebSocketClientFactory extends AggregateLifeCycle
|
public class WebSocketClientFactory extends AggregateLifeCycle
|
||||||
{
|
{
|
||||||
|
@ -47,9 +54,10 @@ public class WebSocketClientFactory extends AggregateLifeCycle
|
||||||
private final ScheduledExecutorService scheduler;
|
private final ScheduledExecutorService scheduler;
|
||||||
private final EventMethodsCache methodsCache;
|
private final EventMethodsCache methodsCache;
|
||||||
private final WebSocketPolicy policy;
|
private final WebSocketPolicy policy;
|
||||||
private final ExtensionRegistry extensionRegistry;
|
private final WebSocketExtensionRegistry extensionRegistry;
|
||||||
private SocketAddress bindAddress;
|
private SocketAddress bindAddress;
|
||||||
|
|
||||||
|
private final Queue<WebSocketSession> sessions = new ConcurrentLinkedQueue<>();
|
||||||
private ConnectionManager connectionManager;
|
private ConnectionManager connectionManager;
|
||||||
|
|
||||||
public WebSocketClientFactory()
|
public WebSocketClientFactory()
|
||||||
|
@ -69,6 +77,7 @@ public class WebSocketClientFactory extends AggregateLifeCycle
|
||||||
|
|
||||||
public WebSocketClientFactory(Executor executor, ScheduledExecutorService scheduler, SslContextFactory sslContextFactory)
|
public WebSocketClientFactory(Executor executor, ScheduledExecutorService scheduler, SslContextFactory sslContextFactory)
|
||||||
{
|
{
|
||||||
|
LOG.debug("new WebSocketClientFactory()");
|
||||||
if (executor == null)
|
if (executor == null)
|
||||||
{
|
{
|
||||||
throw new IllegalArgumentException("Executor is required");
|
throw new IllegalArgumentException("Executor is required");
|
||||||
|
@ -101,6 +110,20 @@ public class WebSocketClientFactory extends AggregateLifeCycle
|
||||||
this(new QueuedThreadPool(),Executors.newSingleThreadScheduledExecutor(),sslContextFactory);
|
this(new QueuedThreadPool(),Executors.newSingleThreadScheduledExecutor(),sslContextFactory);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void doStart() throws Exception
|
||||||
|
{
|
||||||
|
super.doStart();
|
||||||
|
LOG.debug("doStart()");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void doStop() throws Exception
|
||||||
|
{
|
||||||
|
super.doStop();
|
||||||
|
LOG.debug("doStop()");
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The address to bind local physical (outgoing) TCP Sockets to.
|
* The address to bind local physical (outgoing) TCP Sockets to.
|
||||||
*
|
*
|
||||||
|
@ -142,6 +165,26 @@ public class WebSocketClientFactory extends AggregateLifeCycle
|
||||||
return scheduler;
|
return scheduler;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public List<Extension> initExtensions(List<ExtensionConfig> requested)
|
||||||
|
{
|
||||||
|
List<Extension> extensions = new ArrayList<Extension>();
|
||||||
|
|
||||||
|
for (ExtensionConfig cfg : requested)
|
||||||
|
{
|
||||||
|
Extension extension = extensionRegistry.newInstance(cfg);
|
||||||
|
|
||||||
|
if (extension == null)
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
LOG.debug("added {}",extension);
|
||||||
|
extensions.add(extension);
|
||||||
|
}
|
||||||
|
LOG.debug("extensions={}",extensions);
|
||||||
|
return extensions;
|
||||||
|
}
|
||||||
|
|
||||||
public WebSocketClient newWebSocketClient(Object websocketPojo)
|
public WebSocketClient newWebSocketClient(Object websocketPojo)
|
||||||
{
|
{
|
||||||
LOG.debug("Creating new WebSocket for {}",websocketPojo);
|
LOG.debug("Creating new WebSocket for {}",websocketPojo);
|
||||||
|
@ -149,6 +192,33 @@ public class WebSocketClientFactory extends AggregateLifeCycle
|
||||||
return new IWebSocketClient(this,websocket);
|
return new IWebSocketClient(this,websocket);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public boolean sessionClosed(WebSocketSession session)
|
||||||
|
{
|
||||||
|
return isRunning() && sessions.remove(session);
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean sessionOpened(WebSocketSession session)
|
||||||
|
{
|
||||||
|
if (LOG.isDebugEnabled())
|
||||||
|
{
|
||||||
|
LOG.debug("Session Opened: {}",session);
|
||||||
|
}
|
||||||
|
// FIXME: what is going on?
|
||||||
|
// if (!isRunning())
|
||||||
|
// {
|
||||||
|
// LOG.debug("Factory.isRunning: {}",this.isRunning());
|
||||||
|
// LOG.debug("Factory.isStarted: {}",this.isStarted());
|
||||||
|
// LOG.debug("Factory.isStarting: {}",this.isStarting());
|
||||||
|
// LOG.debug("Factory.isStopped: {}",this.isStopped());
|
||||||
|
// LOG.debug("Factory.isStopping: {}",this.isStopping());
|
||||||
|
// LOG.warn("Factory is not running");
|
||||||
|
// return false;
|
||||||
|
// }
|
||||||
|
boolean ret = sessions.offer(session);
|
||||||
|
session.onConnect();
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param bindAddress
|
* @param bindAddress
|
||||||
* the address to bind the socket channel to
|
* the address to bind the socket channel to
|
||||||
|
|
|
@ -57,6 +57,8 @@ public class IWebSocketClient extends FutureCallback<UpgradeResponse> implements
|
||||||
public IWebSocketClient(WebSocketClientFactory factory, WebSocketEventDriver websocket)
|
public IWebSocketClient(WebSocketClientFactory factory, WebSocketEventDriver websocket)
|
||||||
{
|
{
|
||||||
this.factory = factory;
|
this.factory = factory;
|
||||||
|
LOG.debug("factory.isRunning(): {}",factory.isRunning());
|
||||||
|
LOG.debug("factory.isStarted(): {}",factory.isStarted());
|
||||||
this.policy = factory.getPolicy();
|
this.policy = factory.getPolicy();
|
||||||
this.websocket = websocket;
|
this.websocket = websocket;
|
||||||
this.upgradeRequest = new ClientUpgradeRequest();
|
this.upgradeRequest = new ClientUpgradeRequest();
|
||||||
|
@ -210,9 +212,8 @@ public class IWebSocketClient extends FutureCallback<UpgradeResponse> implements
|
||||||
return websocketUri;
|
return websocketUri;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setUpgradeResponse(UpgradeResponse response)
|
public void setUpgradeResponse(ClientUpgradeResponse response)
|
||||||
{
|
{
|
||||||
// TODO Auto-generated method stub
|
this.upgradeResponse = response;
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -25,7 +25,6 @@ import java.util.regex.Pattern;
|
||||||
import org.eclipse.jetty.util.StringUtil;
|
import org.eclipse.jetty.util.StringUtil;
|
||||||
import org.eclipse.jetty.util.Utf8LineParser;
|
import org.eclipse.jetty.util.Utf8LineParser;
|
||||||
import org.eclipse.jetty.websocket.api.UpgradeException;
|
import org.eclipse.jetty.websocket.api.UpgradeException;
|
||||||
import org.eclipse.jetty.websocket.api.UpgradeResponse;
|
|
||||||
import org.eclipse.jetty.websocket.client.internal.ClientUpgradeResponse;
|
import org.eclipse.jetty.websocket.client.internal.ClientUpgradeResponse;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -58,7 +57,7 @@ public class HttpResponseHeaderParser
|
||||||
return (state == State.END);
|
return (state == State.END);
|
||||||
}
|
}
|
||||||
|
|
||||||
public UpgradeResponse parse(ByteBuffer buf) throws UpgradeException
|
public ClientUpgradeResponse parse(ByteBuffer buf) throws UpgradeException
|
||||||
{
|
{
|
||||||
while (!isDone() && (buf.remaining() > 0))
|
while (!isDone() && (buf.remaining() > 0))
|
||||||
{
|
{
|
||||||
|
|
|
@ -22,6 +22,7 @@ import java.io.IOException;
|
||||||
import java.net.URI;
|
import java.net.URI;
|
||||||
import java.nio.ByteBuffer;
|
import java.nio.ByteBuffer;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
|
import java.util.Collections;
|
||||||
import java.util.Iterator;
|
import java.util.Iterator;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.concurrent.Executor;
|
import java.util.concurrent.Executor;
|
||||||
|
@ -36,10 +37,17 @@ import org.eclipse.jetty.util.QuotedStringTokenizer;
|
||||||
import org.eclipse.jetty.util.StringUtil;
|
import org.eclipse.jetty.util.StringUtil;
|
||||||
import org.eclipse.jetty.util.log.Log;
|
import org.eclipse.jetty.util.log.Log;
|
||||||
import org.eclipse.jetty.util.log.Logger;
|
import org.eclipse.jetty.util.log.Logger;
|
||||||
|
import org.eclipse.jetty.websocket.api.Extension;
|
||||||
import org.eclipse.jetty.websocket.api.UpgradeException;
|
import org.eclipse.jetty.websocket.api.UpgradeException;
|
||||||
import org.eclipse.jetty.websocket.api.UpgradeResponse;
|
import org.eclipse.jetty.websocket.api.UpgradeResponse;
|
||||||
|
import org.eclipse.jetty.websocket.api.WebSocketPolicy;
|
||||||
import org.eclipse.jetty.websocket.client.internal.ClientUpgradeRequest;
|
import org.eclipse.jetty.websocket.client.internal.ClientUpgradeRequest;
|
||||||
|
import org.eclipse.jetty.websocket.client.internal.ClientUpgradeResponse;
|
||||||
import org.eclipse.jetty.websocket.client.internal.IWebSocketClient;
|
import org.eclipse.jetty.websocket.client.internal.IWebSocketClient;
|
||||||
|
import org.eclipse.jetty.websocket.driver.WebSocketEventDriver;
|
||||||
|
import org.eclipse.jetty.websocket.io.IncomingFrames;
|
||||||
|
import org.eclipse.jetty.websocket.io.OutgoingFrames;
|
||||||
|
import org.eclipse.jetty.websocket.io.WebSocketSession;
|
||||||
import org.eclipse.jetty.websocket.protocol.AcceptHash;
|
import org.eclipse.jetty.websocket.protocol.AcceptHash;
|
||||||
import org.eclipse.jetty.websocket.protocol.ExtensionConfig;
|
import org.eclipse.jetty.websocket.protocol.ExtensionConfig;
|
||||||
|
|
||||||
|
@ -176,14 +184,14 @@ public class UpgradeConnection extends AbstractConnection
|
||||||
{
|
{
|
||||||
LOG.debug("Filled {} bytes - {}",filled,BufferUtil.toDetailString(buffer));
|
LOG.debug("Filled {} bytes - {}",filled,BufferUtil.toDetailString(buffer));
|
||||||
}
|
}
|
||||||
UpgradeResponse resp = parser.parse(buffer);
|
ClientUpgradeResponse resp = parser.parse(buffer);
|
||||||
if (resp != null)
|
if (resp != null)
|
||||||
{
|
{
|
||||||
// Got a response!
|
// Got a response!
|
||||||
client.setUpgradeResponse(resp);
|
client.setUpgradeResponse(resp);
|
||||||
validateResponse(resp);
|
validateResponse(resp);
|
||||||
notifyConnect();
|
notifyConnect();
|
||||||
upgradeConnection();
|
upgradeConnection(resp);
|
||||||
return false; // do no more reading
|
return false; // do no more reading
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -205,12 +213,72 @@ public class UpgradeConnection extends AbstractConnection
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void upgradeConnection()
|
private void upgradeConnection(ClientUpgradeResponse response)
|
||||||
{
|
{
|
||||||
EndPoint endp = getEndPoint();
|
EndPoint endp = getEndPoint();
|
||||||
Executor executor = getExecutor();
|
Executor executor = getExecutor();
|
||||||
WebSocketClientConnection conn = new WebSocketClientConnection(endp,executor,client);
|
WebSocketClientConnection connection = new WebSocketClientConnection(endp,executor,client);
|
||||||
endp.setConnection(conn);
|
|
||||||
|
// Initialize / Negotiate Extensions
|
||||||
|
WebSocketEventDriver websocket = client.getWebSocket();
|
||||||
|
WebSocketPolicy policy = client.getPolicy();
|
||||||
|
String acceptedSubProtocol = response.getAcceptedSubProtocol();
|
||||||
|
WebSocketSession session = new WebSocketSession(websocket,connection,policy,acceptedSubProtocol);
|
||||||
|
connection.setSession(session);
|
||||||
|
List<Extension> extensions = client.getFactory().initExtensions(response.getExtensions());
|
||||||
|
|
||||||
|
// Start with default routing.
|
||||||
|
IncomingFrames incoming = session;
|
||||||
|
OutgoingFrames outgoing = connection;
|
||||||
|
|
||||||
|
// Connect extensions
|
||||||
|
if (extensions != null)
|
||||||
|
{
|
||||||
|
Iterator<Extension> extIter;
|
||||||
|
// Connect outgoings
|
||||||
|
extIter = extensions.iterator();
|
||||||
|
while (extIter.hasNext())
|
||||||
|
{
|
||||||
|
Extension ext = extIter.next();
|
||||||
|
ext.setNextOutgoingFrames(outgoing);
|
||||||
|
outgoing = ext;
|
||||||
|
|
||||||
|
// Handle RSV reservations
|
||||||
|
if (ext.useRsv1())
|
||||||
|
{
|
||||||
|
connection.getGenerator().setRsv1InUse(true);
|
||||||
|
connection.getParser().setRsv1InUse(true);
|
||||||
|
}
|
||||||
|
if (ext.useRsv2())
|
||||||
|
{
|
||||||
|
connection.getGenerator().setRsv2InUse(true);
|
||||||
|
connection.getParser().setRsv2InUse(true);
|
||||||
|
}
|
||||||
|
if (ext.useRsv3())
|
||||||
|
{
|
||||||
|
connection.getGenerator().setRsv3InUse(true);
|
||||||
|
connection.getParser().setRsv3InUse(true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Connect incomings
|
||||||
|
Collections.reverse(extensions);
|
||||||
|
extIter = extensions.iterator();
|
||||||
|
while (extIter.hasNext())
|
||||||
|
{
|
||||||
|
Extension ext = extIter.next();
|
||||||
|
ext.setNextIncomingFrames(incoming);
|
||||||
|
incoming = ext;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// configure session for outgoing flows
|
||||||
|
session.setOutgoing(outgoing);
|
||||||
|
// configure connection for incoming flows
|
||||||
|
connection.getParser().setIncomingFramesHandler(incoming);
|
||||||
|
|
||||||
|
// Now swap out the connection
|
||||||
|
endp.setConnection(connection);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void validateResponse(UpgradeResponse response)
|
private void validateResponse(UpgradeResponse response)
|
||||||
|
|
|
@ -21,17 +21,25 @@ package org.eclipse.jetty.websocket.client.internal.io;
|
||||||
import java.util.concurrent.Executor;
|
import java.util.concurrent.Executor;
|
||||||
|
|
||||||
import org.eclipse.jetty.io.EndPoint;
|
import org.eclipse.jetty.io.EndPoint;
|
||||||
|
import org.eclipse.jetty.websocket.client.WebSocketClientFactory;
|
||||||
import org.eclipse.jetty.websocket.client.internal.IWebSocketClient;
|
import org.eclipse.jetty.websocket.client.internal.IWebSocketClient;
|
||||||
import org.eclipse.jetty.websocket.io.AbstractWebSocketConnection;
|
import org.eclipse.jetty.websocket.io.AbstractWebSocketConnection;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Client side WebSocket physical connection.
|
||||||
|
*/
|
||||||
public class WebSocketClientConnection extends AbstractWebSocketConnection
|
public class WebSocketClientConnection extends AbstractWebSocketConnection
|
||||||
{
|
{
|
||||||
|
private final WebSocketClientFactory factory;
|
||||||
private final IWebSocketClient client;
|
private final IWebSocketClient client;
|
||||||
|
private boolean connected;
|
||||||
|
|
||||||
public WebSocketClientConnection(EndPoint endp, Executor executor, IWebSocketClient client)
|
public WebSocketClientConnection(EndPoint endp, Executor executor, IWebSocketClient client)
|
||||||
{
|
{
|
||||||
super(endp,executor,client.getFactory().getScheduler(),client.getPolicy(),client.getFactory().getBufferPool());
|
super(endp,executor,client.getFactory().getScheduler(),client.getPolicy(),client.getFactory().getBufferPool());
|
||||||
this.client = client;
|
this.client = client;
|
||||||
|
this.factory = client.getFactory();
|
||||||
|
this.connected = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
public IWebSocketClient getClient()
|
public IWebSocketClient getClient()
|
||||||
|
@ -39,9 +47,21 @@ public class WebSocketClientConnection extends AbstractWebSocketConnection
|
||||||
return client;
|
return client;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onClose()
|
||||||
|
{
|
||||||
|
super.onClose();
|
||||||
|
factory.sessionClosed(getSession());
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onOpen()
|
public void onOpen()
|
||||||
{
|
{
|
||||||
|
if (!connected)
|
||||||
|
{
|
||||||
|
factory.sessionOpened(getSession());
|
||||||
|
connected = true;
|
||||||
|
}
|
||||||
super.onOpen();
|
super.onOpen();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -22,78 +22,115 @@ import static org.hamcrest.Matchers.*;
|
||||||
|
|
||||||
import java.util.concurrent.BlockingQueue;
|
import java.util.concurrent.BlockingQueue;
|
||||||
import java.util.concurrent.CountDownLatch;
|
import java.util.concurrent.CountDownLatch;
|
||||||
import java.util.concurrent.atomic.AtomicBoolean;
|
import java.util.concurrent.Exchanger;
|
||||||
import java.util.concurrent.atomic.AtomicInteger;
|
import java.util.concurrent.TimeUnit;
|
||||||
|
import java.util.concurrent.TimeoutException;
|
||||||
|
|
||||||
import org.eclipse.jetty.util.BlockingArrayQueue;
|
import org.eclipse.jetty.util.BlockingArrayQueue;
|
||||||
|
import org.eclipse.jetty.util.log.Log;
|
||||||
|
import org.eclipse.jetty.util.log.Logger;
|
||||||
import org.eclipse.jetty.websocket.api.WebSocketAdapter;
|
import org.eclipse.jetty.websocket.api.WebSocketAdapter;
|
||||||
import org.eclipse.jetty.websocket.api.WebSocketConnection;
|
import org.eclipse.jetty.websocket.api.WebSocketConnection;
|
||||||
import org.junit.Assert;
|
import org.junit.Assert;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Testing Socket used on client side WebSocket testing.
|
||||||
|
*/
|
||||||
public class TrackingSocket extends WebSocketAdapter
|
public class TrackingSocket extends WebSocketAdapter
|
||||||
{
|
{
|
||||||
public AtomicBoolean open = new AtomicBoolean(false);
|
private static final Logger LOG = Log.getLogger(TrackingSocket.class);
|
||||||
public AtomicInteger close = new AtomicInteger(-1);
|
|
||||||
|
public int closeCode = -1;
|
||||||
|
public Exchanger<String> messageExchanger;
|
||||||
public StringBuilder closeMessage = new StringBuilder();
|
public StringBuilder closeMessage = new StringBuilder();
|
||||||
public CountDownLatch openLatch = new CountDownLatch(1);
|
public CountDownLatch openLatch = new CountDownLatch(1);
|
||||||
public CountDownLatch closeLatch = new CountDownLatch(1);
|
public CountDownLatch closeLatch = new CountDownLatch(1);
|
||||||
public CountDownLatch dataLatch = new CountDownLatch(1);
|
public CountDownLatch dataLatch = new CountDownLatch(1);
|
||||||
public BlockingQueue<String> messageQueue = new BlockingArrayQueue<String>();
|
public BlockingQueue<String> messageQueue = new BlockingArrayQueue<String>();
|
||||||
|
|
||||||
public void assertClose(int expectedStatusCode, String expectedReason)
|
public void assertClose(int expectedStatusCode, String expectedReason) throws InterruptedException
|
||||||
{
|
{
|
||||||
assertCloseCode(expectedStatusCode);
|
assertCloseCode(expectedStatusCode);
|
||||||
assertCloseReason(expectedReason);
|
assertCloseReason(expectedReason);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void assertCloseCode(int expectedCode)
|
public void assertCloseCode(int expectedCode) throws InterruptedException
|
||||||
{
|
{
|
||||||
Assert.assertThat("Close Code",close.get(),is(expectedCode));
|
Assert.assertThat("Was Closed",closeLatch.await(500,TimeUnit.MILLISECONDS),is(true));
|
||||||
|
Assert.assertThat("Close Code",closeCode,is(expectedCode));
|
||||||
}
|
}
|
||||||
|
|
||||||
private void assertCloseReason(String expectedReason)
|
private void assertCloseReason(String expectedReason)
|
||||||
{
|
{
|
||||||
Assert.assertThat("Close Reaosn",closeMessage.toString(),is(expectedReason));
|
Assert.assertThat("Close Reason",closeMessage.toString(),is(expectedReason));
|
||||||
}
|
}
|
||||||
|
|
||||||
public void assertIsOpen()
|
public void assertIsOpen() throws InterruptedException
|
||||||
{
|
{
|
||||||
assertWasOpened();
|
assertWasOpened();
|
||||||
assertNotClosed();
|
assertNotClosed();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void assertMessage(String string)
|
public void assertMessage(String expected)
|
||||||
{
|
{
|
||||||
// TODO Auto-generated method stub
|
String actual = messageQueue.poll();
|
||||||
|
Assert.assertEquals("Message",expected,actual);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void assertNotClosed()
|
public void assertNotClosed()
|
||||||
{
|
{
|
||||||
Assert.assertThat("Close Code",close.get(),is(-1));
|
Assert.assertThat("Closed Latch",closeLatch.getCount(),greaterThanOrEqualTo(1L));
|
||||||
}
|
}
|
||||||
|
|
||||||
public void assertNotOpened()
|
public void assertNotOpened()
|
||||||
{
|
{
|
||||||
Assert.assertThat("Opened State",open.get(),is(false));
|
Assert.assertThat("Open Latch",openLatch.getCount(),greaterThanOrEqualTo(1L));
|
||||||
}
|
}
|
||||||
|
|
||||||
public void assertWasOpened()
|
public void assertWasOpened() throws InterruptedException
|
||||||
{
|
{
|
||||||
Assert.assertThat("Opened State",open.get(),is(true));
|
Assert.assertThat("Was Opened",openLatch.await(500,TimeUnit.MILLISECONDS),is(true));
|
||||||
|
}
|
||||||
|
|
||||||
|
public void awaitMessage(int expectedMessageCount, TimeUnit timeoutUnit, int timeoutDuration) throws TimeoutException
|
||||||
|
{
|
||||||
|
int startCount = messageQueue.size();
|
||||||
|
long msDur = TimeUnit.MILLISECONDS.convert(timeoutDuration,timeoutUnit);
|
||||||
|
long now = System.currentTimeMillis();
|
||||||
|
long expireOn = now + msDur;
|
||||||
|
LOG.debug("Now: {} - expireOn: {} ({} ms)",now,expireOn,msDur);
|
||||||
|
|
||||||
|
while (messageQueue.size() < (startCount + expectedMessageCount))
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
TimeUnit.MILLISECONDS.sleep(20);
|
||||||
|
}
|
||||||
|
catch (InterruptedException gnore)
|
||||||
|
{
|
||||||
|
/* ignore */
|
||||||
|
}
|
||||||
|
if (!LOG.isDebugEnabled() && (System.currentTimeMillis() > expireOn))
|
||||||
|
{
|
||||||
|
throw new TimeoutException(String.format("Timeout reading all %d expected messages. (managed to only read %d messages)",expectedMessageCount,
|
||||||
|
messageQueue.size()));
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onWebSocketBinary(byte[] payload, int offset, int len)
|
public void onWebSocketBinary(byte[] payload, int offset, int len)
|
||||||
{
|
{
|
||||||
|
LOG.debug("onWebSocketBinary()");
|
||||||
dataLatch.countDown();
|
dataLatch.countDown();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onWebSocketClose(int statusCode, String reason)
|
public void onWebSocketClose(int statusCode, String reason)
|
||||||
{
|
{
|
||||||
|
LOG.debug("onWebSocketClose({},{})",statusCode,reason);
|
||||||
super.onWebSocketClose(statusCode,reason);
|
super.onWebSocketClose(statusCode,reason);
|
||||||
close.set(statusCode);
|
closeCode = statusCode;
|
||||||
closeMessage.append(reason);
|
closeMessage.append(reason);
|
||||||
closeLatch.countDown();
|
closeLatch.countDown();
|
||||||
}
|
}
|
||||||
|
@ -102,20 +139,31 @@ public class TrackingSocket extends WebSocketAdapter
|
||||||
public void onWebSocketConnect(WebSocketConnection connection)
|
public void onWebSocketConnect(WebSocketConnection connection)
|
||||||
{
|
{
|
||||||
super.onWebSocketConnect(connection);
|
super.onWebSocketConnect(connection);
|
||||||
open.set(true);
|
|
||||||
openLatch.countDown();
|
openLatch.countDown();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onWebSocketText(String message)
|
public void onWebSocketText(String message)
|
||||||
{
|
{
|
||||||
|
LOG.debug("onWebSocketText({})",message);
|
||||||
|
messageQueue.offer(message);
|
||||||
dataLatch.countDown();
|
dataLatch.countDown();
|
||||||
messageQueue.add(message);
|
|
||||||
|
if (messageExchanger != null)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
messageExchanger.exchange(message);
|
||||||
|
}
|
||||||
|
catch (InterruptedException e)
|
||||||
|
{
|
||||||
|
LOG.debug(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void waitForResponseMessage()
|
public void waitForMessage(TimeUnit timeoutUnit, int timeoutDuration) throws InterruptedException
|
||||||
{
|
{
|
||||||
// TODO Auto-generated method stub
|
Assert.assertThat("Message Received",dataLatch.await(timeoutDuration,timeoutUnit),is(true));
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -22,24 +22,20 @@ import static org.hamcrest.Matchers.*;
|
||||||
|
|
||||||
import java.net.ConnectException;
|
import java.net.ConnectException;
|
||||||
import java.net.URI;
|
import java.net.URI;
|
||||||
import java.util.concurrent.CountDownLatch;
|
|
||||||
import java.util.concurrent.Exchanger;
|
import java.util.concurrent.Exchanger;
|
||||||
import java.util.concurrent.ExecutionException;
|
import java.util.concurrent.ExecutionException;
|
||||||
import java.util.concurrent.Future;
|
import java.util.concurrent.Future;
|
||||||
import java.util.concurrent.TimeUnit;
|
import java.util.concurrent.TimeUnit;
|
||||||
import java.util.concurrent.TimeoutException;
|
import java.util.concurrent.TimeoutException;
|
||||||
import java.util.concurrent.atomic.AtomicBoolean;
|
|
||||||
import java.util.concurrent.atomic.AtomicInteger;
|
import java.util.concurrent.atomic.AtomicInteger;
|
||||||
import java.util.concurrent.atomic.AtomicLong;
|
import java.util.concurrent.atomic.AtomicLong;
|
||||||
|
|
||||||
|
import org.eclipse.jetty.toolchain.test.AdvancedRunner;
|
||||||
import org.eclipse.jetty.util.FutureCallback;
|
import org.eclipse.jetty.util.FutureCallback;
|
||||||
import org.eclipse.jetty.websocket.api.StatusCode;
|
import org.eclipse.jetty.websocket.api.StatusCode;
|
||||||
import org.eclipse.jetty.websocket.api.UpgradeException;
|
import org.eclipse.jetty.websocket.api.UpgradeException;
|
||||||
import org.eclipse.jetty.websocket.api.UpgradeRequest;
|
import org.eclipse.jetty.websocket.api.UpgradeRequest;
|
||||||
import org.eclipse.jetty.websocket.api.UpgradeResponse;
|
import org.eclipse.jetty.websocket.api.UpgradeResponse;
|
||||||
import org.eclipse.jetty.websocket.api.WebSocketAdapter;
|
|
||||||
import org.eclipse.jetty.websocket.api.WebSocketConnection;
|
|
||||||
import org.eclipse.jetty.websocket.api.WebSocketListener;
|
|
||||||
import org.eclipse.jetty.websocket.client.blockhead.BlockheadServer;
|
import org.eclipse.jetty.websocket.client.blockhead.BlockheadServer;
|
||||||
import org.eclipse.jetty.websocket.client.blockhead.BlockheadServer.ServerConnection;
|
import org.eclipse.jetty.websocket.client.blockhead.BlockheadServer.ServerConnection;
|
||||||
import org.eclipse.jetty.websocket.protocol.WebSocketFrame;
|
import org.eclipse.jetty.websocket.protocol.WebSocketFrame;
|
||||||
|
@ -48,8 +44,9 @@ import org.junit.Assert;
|
||||||
import org.junit.Before;
|
import org.junit.Before;
|
||||||
import org.junit.Ignore;
|
import org.junit.Ignore;
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
|
import org.junit.runner.RunWith;
|
||||||
|
|
||||||
@Ignore("work in progress")
|
@RunWith(AdvancedRunner.class)
|
||||||
public class WebSocketClientTest
|
public class WebSocketClientTest
|
||||||
{
|
{
|
||||||
private BlockheadServer server;
|
private BlockheadServer server;
|
||||||
|
@ -149,9 +146,9 @@ public class WebSocketClientTest
|
||||||
final ServerConnection srvSock = server.accept();
|
final ServerConnection srvSock = server.accept();
|
||||||
srvSock.upgrade();
|
srvSock.upgrade();
|
||||||
|
|
||||||
UpgradeResponse resp = future.get(250,TimeUnit.MILLISECONDS);
|
UpgradeResponse resp = future.get(500,TimeUnit.MILLISECONDS);
|
||||||
Assert.assertThat("Response",resp,notNullValue());
|
Assert.assertThat("Response",resp,notNullValue());
|
||||||
Assert.assertEquals("Response.success",resp.isSuccess(),is(true));
|
Assert.assertThat("Response.success",resp.isSuccess(),is(true));
|
||||||
|
|
||||||
cliSock.assertWasOpened();
|
cliSock.assertWasOpened();
|
||||||
cliSock.assertNotClosed();
|
cliSock.assertNotClosed();
|
||||||
|
@ -159,9 +156,9 @@ public class WebSocketClientTest
|
||||||
Assert.assertThat("Factory.sockets.size",factory.getConnectionManager().getClients().size(),is(1));
|
Assert.assertThat("Factory.sockets.size",factory.getConnectionManager().getClients().size(),is(1));
|
||||||
|
|
||||||
cliSock.getConnection().write(null,new FutureCallback<Void>(),"Hello World!");
|
cliSock.getConnection().write(null,new FutureCallback<Void>(),"Hello World!");
|
||||||
srvSock.echoMessage();
|
srvSock.echoMessage(1,TimeUnit.MILLISECONDS,500);
|
||||||
// wait for response from server
|
// wait for response from server
|
||||||
cliSock.waitForResponseMessage();
|
cliSock.waitForMessage(TimeUnit.MILLISECONDS,500);
|
||||||
|
|
||||||
cliSock.assertMessage("Hello World!");
|
cliSock.assertMessage("Hello World!");
|
||||||
}
|
}
|
||||||
|
@ -177,55 +174,29 @@ public class WebSocketClientTest
|
||||||
final ServerConnection srvSock = server.accept();
|
final ServerConnection srvSock = server.accept();
|
||||||
srvSock.upgrade();
|
srvSock.upgrade();
|
||||||
|
|
||||||
|
// Validate connect
|
||||||
|
UpgradeResponse resp = future.get(500,TimeUnit.MILLISECONDS);
|
||||||
|
Assert.assertThat("Response",resp,notNullValue());
|
||||||
|
Assert.assertThat("Response.success",resp.isSuccess(),is(true));
|
||||||
|
|
||||||
// Have server send initial message
|
// Have server send initial message
|
||||||
srvSock.write(WebSocketFrame.text("Hello World"));
|
srvSock.write(WebSocketFrame.text("Hello World"));
|
||||||
|
|
||||||
// Verify connect
|
// Verify connect
|
||||||
future.get(500,TimeUnit.MILLISECONDS);
|
future.get(500,TimeUnit.MILLISECONDS);
|
||||||
|
wsocket.assertWasOpened();
|
||||||
|
wsocket.awaitMessage(1,TimeUnit.MILLISECONDS,500);
|
||||||
|
|
||||||
wsocket.assertMessage("Hello world");
|
wsocket.assertMessage("Hello World");
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testBlockReceiving() throws Exception
|
public void testBlockReceiving() throws Exception
|
||||||
{
|
{
|
||||||
final AtomicBoolean open = new AtomicBoolean(false);
|
|
||||||
final AtomicInteger close = new AtomicInteger();
|
|
||||||
final CountDownLatch _latch = new CountDownLatch(1);
|
|
||||||
final StringBuilder closeMessage = new StringBuilder();
|
|
||||||
final Exchanger<String> exchanger = new Exchanger<String>();
|
final Exchanger<String> exchanger = new Exchanger<String>();
|
||||||
|
TrackingSocket tsocket = new TrackingSocket();
|
||||||
WebSocketListener socket = new WebSocketAdapter()
|
tsocket.messageExchanger = exchanger;
|
||||||
{
|
WebSocketClient client = factory.newWebSocketClient(tsocket);
|
||||||
@Override
|
|
||||||
public void onWebSocketClose(int statusCode, String reason)
|
|
||||||
{
|
|
||||||
close.set(statusCode);
|
|
||||||
closeMessage.append(reason);
|
|
||||||
_latch.countDown();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onWebSocketConnect(WebSocketConnection connection)
|
|
||||||
{
|
|
||||||
open.set(true);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onWebSocketText(String message)
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
exchanger.exchange(message);
|
|
||||||
}
|
|
||||||
catch (InterruptedException e)
|
|
||||||
{
|
|
||||||
// e.printStackTrace();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
WebSocketClient client = factory.newWebSocketClient(socket);
|
|
||||||
client.getPolicy().setIdleTimeout(60000);
|
client.getPolicy().setIdleTimeout(60000);
|
||||||
|
|
||||||
URI wsUri = server.getWsUri();
|
URI wsUri = server.getWsUri();
|
||||||
|
@ -233,8 +204,9 @@ public class WebSocketClientTest
|
||||||
|
|
||||||
ServerConnection sconnection = server.accept();
|
ServerConnection sconnection = server.accept();
|
||||||
sconnection.setSoTimeout(60000);
|
sconnection.setSoTimeout(60000);
|
||||||
|
sconnection.upgrade();
|
||||||
|
|
||||||
UpgradeResponse resp = future.get(250,TimeUnit.MILLISECONDS);
|
future.get(500,TimeUnit.MILLISECONDS);
|
||||||
|
|
||||||
// define some messages to send server to client
|
// define some messages to send server to client
|
||||||
byte[] send = new byte[]
|
byte[] send = new byte[]
|
||||||
|
@ -300,18 +272,14 @@ public class WebSocketClientTest
|
||||||
Assert.assertEquals(m.get(),messages);
|
Assert.assertEquals(m.get(),messages);
|
||||||
|
|
||||||
// Close with code
|
// Close with code
|
||||||
start = System.currentTimeMillis();
|
sconnection.close(StatusCode.NORMAL);
|
||||||
sconnection.write(new byte[]
|
|
||||||
{ (byte)0x88, (byte)0x02, (byte)4, (byte)87 },0,4);
|
|
||||||
sconnection.flush();
|
|
||||||
|
|
||||||
_latch.await(10,TimeUnit.SECONDS);
|
Assert.assertTrue("Client Socket Closed",tsocket.closeLatch.await(10,TimeUnit.SECONDS));
|
||||||
Assert.assertTrue((System.currentTimeMillis() - start) < 5000);
|
tsocket.assertCloseCode(StatusCode.NORMAL);
|
||||||
Assert.assertEquals(1002,close.get());
|
|
||||||
Assert.assertEquals("Invalid close code 1111",closeMessage.toString());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
@Ignore("Not working, it hangs")
|
||||||
public void testBlockSending() throws Exception
|
public void testBlockSending() throws Exception
|
||||||
{
|
{
|
||||||
TrackingSocket wsocket = new TrackingSocket();
|
TrackingSocket wsocket = new TrackingSocket();
|
||||||
|
@ -324,7 +292,7 @@ public class WebSocketClientTest
|
||||||
final ServerConnection ssocket = server.accept();
|
final ServerConnection ssocket = server.accept();
|
||||||
ssocket.upgrade();
|
ssocket.upgrade();
|
||||||
|
|
||||||
UpgradeResponse resp = future.get(250,TimeUnit.MILLISECONDS);
|
future.get(250,TimeUnit.MILLISECONDS);
|
||||||
|
|
||||||
final int messages = 200000;
|
final int messages = 200000;
|
||||||
final AtomicLong totalB = new AtomicLong();
|
final AtomicLong totalB = new AtomicLong();
|
||||||
|
@ -408,6 +376,7 @@ public class WebSocketClientTest
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test(expected = ConnectException.class)
|
@Test(expected = ConnectException.class)
|
||||||
|
@Ignore("Needs work in SelectManager to support this use case")
|
||||||
public void testConnectionRefused() throws Exception
|
public void testConnectionRefused() throws Exception
|
||||||
{
|
{
|
||||||
TrackingSocket wsocket = new TrackingSocket();
|
TrackingSocket wsocket = new TrackingSocket();
|
||||||
|
@ -456,6 +425,7 @@ public class WebSocketClientTest
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
@Ignore("Work In Progress")
|
||||||
public void testIdle() throws Exception
|
public void testIdle() throws Exception
|
||||||
{
|
{
|
||||||
TrackingSocket wsocket = new TrackingSocket();
|
TrackingSocket wsocket = new TrackingSocket();
|
||||||
|
@ -520,6 +490,7 @@ public class WebSocketClientTest
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
@Ignore("Work In Progress")
|
||||||
public void testNotIdle() throws Exception
|
public void testNotIdle() throws Exception
|
||||||
{
|
{
|
||||||
TrackingSocket wsocket = new TrackingSocket();
|
TrackingSocket wsocket = new TrackingSocket();
|
||||||
|
@ -537,7 +508,7 @@ public class WebSocketClientTest
|
||||||
|
|
||||||
wsocket.assertIsOpen();
|
wsocket.assertIsOpen();
|
||||||
|
|
||||||
// Send some messages client to server
|
// Send some messages from client to server
|
||||||
byte[] recv = new byte[1024];
|
byte[] recv = new byte[1024];
|
||||||
int len = -1;
|
int len = -1;
|
||||||
for (int i = 0; i < 10; i++)
|
for (int i = 0; i < 10; i++)
|
||||||
|
@ -548,7 +519,7 @@ public class WebSocketClientTest
|
||||||
Assert.assertTrue(len > 0);
|
Assert.assertTrue(len > 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Send some messages server to client
|
// Send some messages from server to client
|
||||||
byte[] send = new byte[]
|
byte[] send = new byte[]
|
||||||
{ (byte)0x81, (byte)0x02, (byte)'H', (byte)'i' };
|
{ (byte)0x81, (byte)0x02, (byte)'H', (byte)'i' };
|
||||||
|
|
||||||
|
@ -567,11 +538,13 @@ public class WebSocketClientTest
|
||||||
ssocket.flush();
|
ssocket.flush();
|
||||||
|
|
||||||
wsocket.closeLatch.await(10,TimeUnit.SECONDS);
|
wsocket.closeLatch.await(10,TimeUnit.SECONDS);
|
||||||
Assert.assertTrue((System.currentTimeMillis() - start) < 5000);
|
long dur = (System.currentTimeMillis() - start);
|
||||||
|
Assert.assertThat("Overall duration",dur,lessThanOrEqualTo(5000L));
|
||||||
wsocket.assertClose(StatusCode.PROTOCOL,"Invalid close code 1111");
|
wsocket.assertClose(StatusCode.PROTOCOL,"Invalid close code 1111");
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
@Ignore("Test for is-open is broken")
|
||||||
public void testUpgradeThenTCPClose() throws Exception
|
public void testUpgradeThenTCPClose() throws Exception
|
||||||
{
|
{
|
||||||
TrackingSocket wsocket = new TrackingSocket();
|
TrackingSocket wsocket = new TrackingSocket();
|
||||||
|
@ -587,9 +560,8 @@ public class WebSocketClientTest
|
||||||
|
|
||||||
wsocket.assertIsOpen();
|
wsocket.assertIsOpen();
|
||||||
|
|
||||||
ssocket.close();
|
ssocket.disconnect();
|
||||||
wsocket.openLatch.await(10,TimeUnit.SECONDS);
|
|
||||||
|
|
||||||
wsocket.assertCloseCode(StatusCode.NO_CLOSE);
|
Assert.assertThat("Close should have been detected",wsocket.closeLatch.await(10,TimeUnit.SECONDS),is(true));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -31,11 +31,36 @@ import java.net.ServerSocket;
|
||||||
import java.net.Socket;
|
import java.net.Socket;
|
||||||
import java.net.SocketException;
|
import java.net.SocketException;
|
||||||
import java.net.URI;
|
import java.net.URI;
|
||||||
|
import java.nio.ByteBuffer;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.Iterator;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.concurrent.TimeUnit;
|
||||||
|
import java.util.concurrent.TimeoutException;
|
||||||
|
import java.util.concurrent.atomic.AtomicInteger;
|
||||||
|
import java.util.regex.Matcher;
|
||||||
|
import java.util.regex.Pattern;
|
||||||
|
|
||||||
|
import org.eclipse.jetty.io.ByteBufferPool;
|
||||||
|
import org.eclipse.jetty.io.StandardByteBufferPool;
|
||||||
|
import org.eclipse.jetty.util.BufferUtil;
|
||||||
|
import org.eclipse.jetty.util.Callback;
|
||||||
import org.eclipse.jetty.util.IO;
|
import org.eclipse.jetty.util.IO;
|
||||||
import org.eclipse.jetty.util.log.Log;
|
import org.eclipse.jetty.util.log.Log;
|
||||||
import org.eclipse.jetty.util.log.Logger;
|
import org.eclipse.jetty.util.log.Logger;
|
||||||
|
import org.eclipse.jetty.websocket.api.Extension;
|
||||||
|
import org.eclipse.jetty.websocket.api.WebSocketException;
|
||||||
|
import org.eclipse.jetty.websocket.api.WebSocketPolicy;
|
||||||
|
import org.eclipse.jetty.websocket.extensions.WebSocketExtensionRegistry;
|
||||||
|
import org.eclipse.jetty.websocket.io.IncomingFrames;
|
||||||
|
import org.eclipse.jetty.websocket.io.OutgoingFrames;
|
||||||
import org.eclipse.jetty.websocket.protocol.AcceptHash;
|
import org.eclipse.jetty.websocket.protocol.AcceptHash;
|
||||||
|
import org.eclipse.jetty.websocket.protocol.CloseInfo;
|
||||||
|
import org.eclipse.jetty.websocket.protocol.ExtensionConfig;
|
||||||
|
import org.eclipse.jetty.websocket.protocol.Generator;
|
||||||
|
import org.eclipse.jetty.websocket.protocol.OpCode;
|
||||||
|
import org.eclipse.jetty.websocket.protocol.Parser;
|
||||||
import org.eclipse.jetty.websocket.protocol.WebSocketFrame;
|
import org.eclipse.jetty.websocket.protocol.WebSocketFrame;
|
||||||
import org.junit.Assert;
|
import org.junit.Assert;
|
||||||
|
|
||||||
|
@ -46,26 +71,79 @@ import org.junit.Assert;
|
||||||
*/
|
*/
|
||||||
public class BlockheadServer
|
public class BlockheadServer
|
||||||
{
|
{
|
||||||
public static class ServerConnection
|
public static class ServerConnection implements IncomingFrames, OutgoingFrames
|
||||||
{
|
{
|
||||||
private final Socket socket;
|
private final Socket socket;
|
||||||
|
private final ByteBufferPool bufferPool;
|
||||||
|
private final WebSocketPolicy policy;
|
||||||
|
private final IncomingFramesCapture incomingFrames;
|
||||||
|
private final Parser parser;
|
||||||
|
private final Generator generator;
|
||||||
|
private final AtomicInteger parseCount;
|
||||||
|
private final WebSocketExtensionRegistry extensionRegistry;
|
||||||
|
|
||||||
|
/** Set to true to disable timeouts (for debugging reasons) */
|
||||||
|
private boolean debug = false;
|
||||||
private OutputStream out;
|
private OutputStream out;
|
||||||
private InputStream in;
|
private InputStream in;
|
||||||
|
|
||||||
|
private IncomingFrames incoming = this;
|
||||||
|
private OutgoingFrames outgoing = this;
|
||||||
|
|
||||||
public ServerConnection(Socket socket)
|
public ServerConnection(Socket socket)
|
||||||
{
|
{
|
||||||
this.socket = socket;
|
this.socket = socket;
|
||||||
|
this.incomingFrames = new IncomingFramesCapture();
|
||||||
|
this.policy = WebSocketPolicy.newServerPolicy();
|
||||||
|
this.bufferPool = new StandardByteBufferPool(policy.getBufferSize());
|
||||||
|
this.parser = new Parser(policy);
|
||||||
|
this.parseCount = new AtomicInteger(0);
|
||||||
|
this.generator = new Generator(policy,bufferPool,false);
|
||||||
|
this.extensionRegistry = new WebSocketExtensionRegistry(policy,bufferPool);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void close() throws IOException
|
public void close() throws IOException
|
||||||
{
|
{
|
||||||
this.socket.close();
|
write(new WebSocketFrame(OpCode.CLOSE));
|
||||||
|
flush();
|
||||||
|
disconnect();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void echoMessage()
|
public void close(int statusCode) throws IOException
|
||||||
{
|
{
|
||||||
// TODO Auto-generated method stub
|
CloseInfo close = new CloseInfo(statusCode);
|
||||||
|
write(close.asFrame());
|
||||||
|
flush();
|
||||||
|
disconnect();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void disconnect()
|
||||||
|
{
|
||||||
|
LOG.debug("disconnect");
|
||||||
|
IO.close(in);
|
||||||
|
IO.close(out);
|
||||||
|
if (socket != null)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
socket.close();
|
||||||
|
}
|
||||||
|
catch (IOException ignore)
|
||||||
|
{
|
||||||
|
/* ignore */
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void echoMessage(int expectedFrames, TimeUnit timeoutUnit, int timeoutDuration) throws IOException, TimeoutException
|
||||||
|
{
|
||||||
|
LOG.debug("Echo Frames [expecting {}]",expectedFrames);
|
||||||
|
IncomingFramesCapture cap = readFrames(expectedFrames,timeoutUnit,timeoutDuration);
|
||||||
|
// now echo them back.
|
||||||
|
for (WebSocketFrame frame : cap.getFrames())
|
||||||
|
{
|
||||||
|
write(frame);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void flush() throws IOException
|
public void flush() throws IOException
|
||||||
|
@ -91,6 +169,102 @@ public class BlockheadServer
|
||||||
return out;
|
return out;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void incoming(WebSocketException e)
|
||||||
|
{
|
||||||
|
incomingFrames.incoming(e);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void incoming(WebSocketFrame frame)
|
||||||
|
{
|
||||||
|
LOG.debug("incoming({})",frame);
|
||||||
|
int count = parseCount.incrementAndGet();
|
||||||
|
if ((count % 10) == 0)
|
||||||
|
{
|
||||||
|
LOG.info("Server parsed {} frames",count);
|
||||||
|
}
|
||||||
|
WebSocketFrame copy = new WebSocketFrame(frame);
|
||||||
|
incomingFrames.incoming(copy);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public <C> void output(C context, Callback<C> callback, WebSocketFrame frame) throws IOException
|
||||||
|
{
|
||||||
|
ByteBuffer buf = generator.generate(frame);
|
||||||
|
if (LOG.isDebugEnabled())
|
||||||
|
{
|
||||||
|
LOG.debug("writing out: {}",BufferUtil.toDetailString(buf));
|
||||||
|
}
|
||||||
|
BufferUtil.writeTo(buf,out);
|
||||||
|
out.flush();
|
||||||
|
|
||||||
|
if (frame.getOpCode() == OpCode.CLOSE)
|
||||||
|
{
|
||||||
|
disconnect();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public int read(ByteBuffer buf) throws IOException
|
||||||
|
{
|
||||||
|
int len = 0;
|
||||||
|
while ((in.available() > 0) && (buf.remaining() > 0))
|
||||||
|
{
|
||||||
|
buf.put((byte)in.read());
|
||||||
|
len++;
|
||||||
|
}
|
||||||
|
return len;
|
||||||
|
}
|
||||||
|
|
||||||
|
public IncomingFramesCapture readFrames(int expectedCount, TimeUnit timeoutUnit, int timeoutDuration) throws IOException, TimeoutException
|
||||||
|
{
|
||||||
|
LOG.debug("Read: waiting for {} frame(s) from server",expectedCount);
|
||||||
|
int startCount = incomingFrames.size();
|
||||||
|
|
||||||
|
ByteBuffer buf = bufferPool.acquire(policy.getBufferSize(),false);
|
||||||
|
BufferUtil.clearToFill(buf);
|
||||||
|
try
|
||||||
|
{
|
||||||
|
long msDur = TimeUnit.MILLISECONDS.convert(timeoutDuration,timeoutUnit);
|
||||||
|
long now = System.currentTimeMillis();
|
||||||
|
long expireOn = now + msDur;
|
||||||
|
LOG.debug("Now: {} - expireOn: {} ({} ms)",now,expireOn,msDur);
|
||||||
|
|
||||||
|
int len = 0;
|
||||||
|
while (incomingFrames.size() < (startCount + expectedCount))
|
||||||
|
{
|
||||||
|
BufferUtil.clearToFill(buf);
|
||||||
|
len = read(buf);
|
||||||
|
if (len > 0)
|
||||||
|
{
|
||||||
|
LOG.debug("Read {} bytes",len);
|
||||||
|
BufferUtil.flipToFlush(buf,0);
|
||||||
|
parser.parse(buf);
|
||||||
|
}
|
||||||
|
try
|
||||||
|
{
|
||||||
|
TimeUnit.MILLISECONDS.sleep(20);
|
||||||
|
}
|
||||||
|
catch (InterruptedException gnore)
|
||||||
|
{
|
||||||
|
/* ignore */
|
||||||
|
}
|
||||||
|
if (!debug && (System.currentTimeMillis() > expireOn))
|
||||||
|
{
|
||||||
|
incomingFrames.dump();
|
||||||
|
throw new TimeoutException(String.format("Timeout reading all %d expected frames. (managed to only read %d frame(s))",expectedCount,
|
||||||
|
incomingFrames.size()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
finally
|
||||||
|
{
|
||||||
|
bufferPool.release(buf);
|
||||||
|
}
|
||||||
|
|
||||||
|
return incomingFrames;
|
||||||
|
}
|
||||||
|
|
||||||
public String readRequest() throws IOException
|
public String readRequest() throws IOException
|
||||||
{
|
{
|
||||||
LOG.debug("Reading client request");
|
LOG.debug("Reading client request");
|
||||||
|
@ -124,6 +298,12 @@ public class BlockheadServer
|
||||||
|
|
||||||
public void upgrade() throws IOException
|
public void upgrade() throws IOException
|
||||||
{
|
{
|
||||||
|
List<ExtensionConfig> extensionConfigs = new ArrayList<>();
|
||||||
|
|
||||||
|
Pattern patExts = Pattern.compile("^Sec-WebSocket-Extensions: (.*)$",Pattern.CASE_INSENSITIVE);
|
||||||
|
Pattern patKey = Pattern.compile("^Sec-WebSocket-Key: (.*)$",Pattern.CASE_INSENSITIVE);
|
||||||
|
|
||||||
|
Matcher mat;
|
||||||
String key = "not sent";
|
String key = "not sent";
|
||||||
BufferedReader in = new BufferedReader(new InputStreamReader(getInputStream()));
|
BufferedReader in = new BufferedReader(new InputStreamReader(getInputStream()));
|
||||||
for (String line = in.readLine(); line != null; line = in.readLine())
|
for (String line = in.readLine(); line != null; line = in.readLine())
|
||||||
|
@ -132,19 +312,103 @@ public class BlockheadServer
|
||||||
{
|
{
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if (line.startsWith("Sec-WebSocket-Key:"))
|
|
||||||
|
// Check for extensions
|
||||||
|
mat = patExts.matcher(line);
|
||||||
|
if (mat.matches())
|
||||||
{
|
{
|
||||||
key = line.substring(18).trim();
|
// found extensions
|
||||||
|
String econf = mat.group(1);
|
||||||
|
ExtensionConfig config = ExtensionConfig.parse(econf);
|
||||||
|
extensionConfigs.add(config);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check for Key
|
||||||
|
mat = patKey.matcher(line);
|
||||||
|
if (mat.matches())
|
||||||
|
{
|
||||||
|
key = mat.group(1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Init extensions
|
||||||
|
List<Extension> extensions = new ArrayList<>();
|
||||||
|
for (ExtensionConfig config : extensionConfigs)
|
||||||
|
{
|
||||||
|
Extension ext = extensionRegistry.newInstance(config);
|
||||||
|
extensions.add(ext);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Start with default routing
|
||||||
|
incoming = this;
|
||||||
|
outgoing = this;
|
||||||
|
|
||||||
|
// Connect extensions
|
||||||
|
if (!extensions.isEmpty())
|
||||||
|
{
|
||||||
|
Iterator<Extension> extIter;
|
||||||
|
// Connect outgoings
|
||||||
|
extIter = extensions.iterator();
|
||||||
|
while (extIter.hasNext())
|
||||||
|
{
|
||||||
|
Extension ext = extIter.next();
|
||||||
|
ext.setNextOutgoingFrames(outgoing);
|
||||||
|
outgoing = ext;
|
||||||
|
|
||||||
|
// Handle RSV reservations
|
||||||
|
if (ext.useRsv1())
|
||||||
|
{
|
||||||
|
generator.setRsv1InUse(true);
|
||||||
|
}
|
||||||
|
if (ext.useRsv2())
|
||||||
|
{
|
||||||
|
generator.setRsv2InUse(true);
|
||||||
|
}
|
||||||
|
if (ext.useRsv3())
|
||||||
|
{
|
||||||
|
generator.setRsv3InUse(true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Connect incomings
|
||||||
|
Collections.reverse(extensions);
|
||||||
|
extIter = extensions.iterator();
|
||||||
|
while (extIter.hasNext())
|
||||||
|
{
|
||||||
|
Extension ext = extIter.next();
|
||||||
|
ext.setNextIncomingFrames(incoming);
|
||||||
|
incoming = ext;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Configure Parser
|
||||||
|
parser.setIncomingFramesHandler(incoming);
|
||||||
|
|
||||||
|
// Setup Response
|
||||||
StringBuilder resp = new StringBuilder();
|
StringBuilder resp = new StringBuilder();
|
||||||
resp.append("HTTP/1.1 101 Upgrade\r\n");
|
resp.append("HTTP/1.1 101 Upgrade\r\n");
|
||||||
resp.append("Sec-WebSocket-Accept: ");
|
resp.append("Sec-WebSocket-Accept: ");
|
||||||
resp.append(AcceptHash.hashKey(key));
|
resp.append(AcceptHash.hashKey(key)).append("\r\n");
|
||||||
resp.append("\r\n");
|
if (!extensions.isEmpty())
|
||||||
|
{
|
||||||
|
// Respond to used extensions
|
||||||
|
resp.append("Sec-WebSocket-Extensions: ");
|
||||||
|
boolean delim = false;
|
||||||
|
for (Extension ext : extensions)
|
||||||
|
{
|
||||||
|
if (delim)
|
||||||
|
{
|
||||||
|
resp.append(", ");
|
||||||
|
}
|
||||||
|
resp.append(ext.getParameterizedName());
|
||||||
|
delim = true;
|
||||||
|
}
|
||||||
|
resp.append("\r\n");
|
||||||
|
}
|
||||||
resp.append("\r\n");
|
resp.append("\r\n");
|
||||||
|
|
||||||
|
// Write Response
|
||||||
write(resp.toString().getBytes());
|
write(resp.toString().getBytes());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -163,10 +427,10 @@ public class BlockheadServer
|
||||||
getOutputStream().write(b);
|
getOutputStream().write(b);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void write(WebSocketFrame frame)
|
public void write(WebSocketFrame frame) throws IOException
|
||||||
{
|
{
|
||||||
// TODO Auto-generated method stub
|
LOG.debug("write(Frame->{}) to {}",frame,outgoing);
|
||||||
|
outgoing.output(null,null,frame);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,140 @@
|
||||||
|
//
|
||||||
|
// ========================================================================
|
||||||
|
// Copyright (c) 1995-2012 Mort Bay Consulting Pty. Ltd.
|
||||||
|
// ------------------------------------------------------------------------
|
||||||
|
// All rights reserved. This program and the accompanying materials
|
||||||
|
// are made available under the terms of the Eclipse Public License v1.0
|
||||||
|
// and Apache License v2.0 which accompanies this distribution.
|
||||||
|
//
|
||||||
|
// The Eclipse Public License is available at
|
||||||
|
// http://www.eclipse.org/legal/epl-v10.html
|
||||||
|
//
|
||||||
|
// The Apache License v2.0 is available at
|
||||||
|
// http://www.opensource.org/licenses/apache2.0.php
|
||||||
|
//
|
||||||
|
// You may elect to redistribute this code under either of these licenses.
|
||||||
|
// ========================================================================
|
||||||
|
//
|
||||||
|
|
||||||
|
package org.eclipse.jetty.websocket.client.blockhead;
|
||||||
|
|
||||||
|
import static org.hamcrest.Matchers.*;
|
||||||
|
|
||||||
|
import java.util.LinkedList;
|
||||||
|
|
||||||
|
import org.eclipse.jetty.util.BufferUtil;
|
||||||
|
import org.eclipse.jetty.util.log.Log;
|
||||||
|
import org.eclipse.jetty.util.log.Logger;
|
||||||
|
import org.eclipse.jetty.websocket.api.WebSocketException;
|
||||||
|
import org.eclipse.jetty.websocket.io.IncomingFrames;
|
||||||
|
import org.eclipse.jetty.websocket.protocol.OpCode;
|
||||||
|
import org.eclipse.jetty.websocket.protocol.WebSocketFrame;
|
||||||
|
import org.junit.Assert;
|
||||||
|
|
||||||
|
public class IncomingFramesCapture implements IncomingFrames
|
||||||
|
{
|
||||||
|
private static final Logger LOG = Log.getLogger(IncomingFramesCapture.class);
|
||||||
|
private LinkedList<WebSocketFrame> frames = new LinkedList<>();
|
||||||
|
private LinkedList<WebSocketException> errors = new LinkedList<>();
|
||||||
|
|
||||||
|
public void assertErrorCount(int expectedCount)
|
||||||
|
{
|
||||||
|
Assert.assertThat("Captured error count",errors.size(),is(expectedCount));
|
||||||
|
}
|
||||||
|
|
||||||
|
public void assertFrameCount(int expectedCount)
|
||||||
|
{
|
||||||
|
Assert.assertThat("Captured frame count",frames.size(),is(expectedCount));
|
||||||
|
}
|
||||||
|
|
||||||
|
public void assertHasErrors(Class<? extends WebSocketException> errorType, int expectedCount)
|
||||||
|
{
|
||||||
|
Assert.assertThat(errorType.getSimpleName(),getErrorCount(errorType),is(expectedCount));
|
||||||
|
}
|
||||||
|
|
||||||
|
public void assertHasFrame(byte op)
|
||||||
|
{
|
||||||
|
Assert.assertThat(OpCode.name(op),getFrameCount(op),greaterThanOrEqualTo(1));
|
||||||
|
}
|
||||||
|
|
||||||
|
public void assertHasFrame(byte op, int expectedCount)
|
||||||
|
{
|
||||||
|
Assert.assertThat(OpCode.name(op),getFrameCount(op),is(expectedCount));
|
||||||
|
}
|
||||||
|
|
||||||
|
public void assertHasNoFrames()
|
||||||
|
{
|
||||||
|
Assert.assertThat("Has no frames",frames.size(),is(0));
|
||||||
|
}
|
||||||
|
|
||||||
|
public void assertNoErrors()
|
||||||
|
{
|
||||||
|
Assert.assertThat("Has no errors",errors.size(),is(0));
|
||||||
|
}
|
||||||
|
|
||||||
|
public void dump()
|
||||||
|
{
|
||||||
|
System.err.printf("Captured %d incoming frames%n",frames.size());
|
||||||
|
for (int i = 0; i < frames.size(); i++)
|
||||||
|
{
|
||||||
|
WebSocketFrame frame = frames.get(i);
|
||||||
|
System.err.printf("[%3d] %s%n",i,frame);
|
||||||
|
System.err.printf(" %s%n",BufferUtil.toDetailString(frame.getPayload()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getErrorCount(Class<? extends WebSocketException> errorType)
|
||||||
|
{
|
||||||
|
int count = 0;
|
||||||
|
for (WebSocketException error : errors)
|
||||||
|
{
|
||||||
|
if (errorType.isInstance(error))
|
||||||
|
{
|
||||||
|
count++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return count;
|
||||||
|
}
|
||||||
|
|
||||||
|
public LinkedList<WebSocketException> getErrors()
|
||||||
|
{
|
||||||
|
return errors;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getFrameCount(byte op)
|
||||||
|
{
|
||||||
|
int count = 0;
|
||||||
|
for (WebSocketFrame frame : frames)
|
||||||
|
{
|
||||||
|
if (frame.getOpCode() == op)
|
||||||
|
{
|
||||||
|
count++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return count;
|
||||||
|
}
|
||||||
|
|
||||||
|
public LinkedList<WebSocketFrame> getFrames()
|
||||||
|
{
|
||||||
|
return frames;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void incoming(WebSocketException e)
|
||||||
|
{
|
||||||
|
LOG.debug(e);
|
||||||
|
errors.add(e);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void incoming(WebSocketFrame frame)
|
||||||
|
{
|
||||||
|
WebSocketFrame copy = new WebSocketFrame(frame);
|
||||||
|
frames.add(copy);
|
||||||
|
}
|
||||||
|
|
||||||
|
public int size()
|
||||||
|
{
|
||||||
|
return frames.size();
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,8 +1,9 @@
|
||||||
org.eclipse.jetty.util.log.class=org.eclipse.jetty.util.log.StdErrLog
|
org.eclipse.jetty.util.log.class=org.eclipse.jetty.util.log.StdErrLog
|
||||||
# org.eclipse.jetty.LEVEL=DEBUG
|
# org.eclipse.jetty.LEVEL=DEBUG
|
||||||
# org.eclipse.jetty.io.ChannelEndPoint.LEVEL=INFO
|
# org.eclipse.jetty.io.ChannelEndPoint.LEVEL=INFO
|
||||||
# org.eclipse.jetty.websocket.LEVEL=WARN
|
org.eclipse.jetty.websocket.LEVEL=WARN
|
||||||
org.eclipse.jetty.websocket.LEVEL=DEBUG
|
# org.eclipse.jetty.websocket.LEVEL=DEBUG
|
||||||
|
# org.eclipse.jetty.websocket.client.TrackingSocket.LEVEL=DEBUG
|
||||||
# See the read/write traffic
|
# See the read/write traffic
|
||||||
# org.eclipse.jetty.websocket.io.Frames.LEVEL=DEBUG
|
# org.eclipse.jetty.websocket.io.Frames.LEVEL=DEBUG
|
||||||
# org.eclipse.jetty.websocket.io.LEVEL=DEBUG
|
# org.eclipse.jetty.websocket.io.LEVEL=DEBUG
|
||||||
|
|
|
@ -224,6 +224,7 @@ public abstract class AbstractWebSocketConnection extends AbstractConnection imp
|
||||||
@Override
|
@Override
|
||||||
public void onFillable()
|
public void onFillable()
|
||||||
{
|
{
|
||||||
|
LOG.debug("{} onFillable()",policy.getBehavior());
|
||||||
ByteBuffer buffer = bufferPool.acquire(policy.getBufferSize(),false);
|
ByteBuffer buffer = bufferPool.acquire(policy.getBufferSize(),false);
|
||||||
BufferUtil.clear(buffer);
|
BufferUtil.clear(buffer);
|
||||||
boolean readMore = false;
|
boolean readMore = false;
|
||||||
|
@ -251,6 +252,7 @@ public abstract class AbstractWebSocketConnection extends AbstractConnection imp
|
||||||
public void onOpen()
|
public void onOpen()
|
||||||
{
|
{
|
||||||
super.onOpen();
|
super.onOpen();
|
||||||
|
LOG.debug("fillInterested");
|
||||||
fillInterested();
|
fillInterested();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
14
pom.xml
14
pom.xml
|
@ -351,6 +351,7 @@
|
||||||
</repository>
|
</repository>
|
||||||
</repositories>
|
</repositories>
|
||||||
<modules>
|
<modules>
|
||||||
|
<module>jetty-ant</module>
|
||||||
<module>jetty-util</module>
|
<module>jetty-util</module>
|
||||||
<module>jetty-jmx</module>
|
<module>jetty-jmx</module>
|
||||||
<module>jetty-io</module>
|
<module>jetty-io</module>
|
||||||
|
@ -375,15 +376,19 @@
|
||||||
|
|
||||||
<!--<module>jetty-client</module>-->
|
<!--<module>jetty-client</module>-->
|
||||||
<!--<module>jetty-proxy</module>-->
|
<!--<module>jetty-proxy</module>-->
|
||||||
|
<!-- Not ready to bring in yet module>jetty-maven-plugin</module>
|
||||||
|
<module>jetty-jspc-maven-plugin</module-->
|
||||||
<module>jetty-deploy</module>
|
<module>jetty-deploy</module>
|
||||||
<module>jetty-start</module>
|
<module>jetty-start</module>
|
||||||
<module>jetty-plugins</module>
|
<module>jetty-plugins</module>
|
||||||
|
<module>jetty-plus</module>
|
||||||
|
<module>jetty-annotations</module>
|
||||||
|
<module>jetty-jndi</module>
|
||||||
<!--
|
<!--
|
||||||
<module>jetty-jaspi</module>
|
<module>jetty-jaspi</module>
|
||||||
<module>jetty-ajp</module>
|
|
||||||
<module>jetty-jndi</module>
|
|
||||||
<module>jetty-annotations</module>
|
|
||||||
<module>jetty-plus</module>
|
|
||||||
<module>jetty-rewrite</module>
|
<module>jetty-rewrite</module>
|
||||||
<module>jetty-policy</module>
|
<module>jetty-policy</module>
|
||||||
<module>jetty-monitor</module>
|
<module>jetty-monitor</module>
|
||||||
|
@ -650,6 +655,7 @@
|
||||||
<exclude>jetty-util/src/main/java/org/eclipse/jetty/util/security/UnixCrypt.java</exclude>
|
<exclude>jetty-util/src/main/java/org/eclipse/jetty/util/security/UnixCrypt.java</exclude>
|
||||||
<exclude>jetty-policy/src/main/java/org/eclipse/jetty/policy/loader/DefaultPolicyLoader.java</exclude>
|
<exclude>jetty-policy/src/main/java/org/eclipse/jetty/policy/loader/DefaultPolicyLoader.java</exclude>
|
||||||
<exclude>jetty-policy/src/main/java/org/eclipse/jetty/policy/loader/PolicyFileScanner.java</exclude>
|
<exclude>jetty-policy/src/main/java/org/eclipse/jetty/policy/loader/PolicyFileScanner.java</exclude>
|
||||||
|
<exlcude>jetty-ant/**</exlcude> <!-- short term, need to add support to accept additional copyrights -->
|
||||||
</excludes>
|
</excludes>
|
||||||
</configuration>
|
</configuration>
|
||||||
<executions>
|
<executions>
|
||||||
|
|
Loading…
Reference in New Issue