Merge branch 'master' into release-9

This commit is contained in:
Jesse McConnell 2014-04-09 09:55:39 -05:00
commit 7e846e513d
160 changed files with 6539 additions and 1499 deletions

95
apache-jsp/pom.xml Normal file
View File

@ -0,0 +1,95 @@
<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.2.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>apache-jsp</artifactId>
<name>Jetty :: Apache JSP</name>
<url>http://www.eclipse.org/jetty</url>
<packaging>jar</packaging>
<properties>
<bundle-symbolic-name>${project.groupId}.${project.artifactId}</bundle-symbolic-name>
</properties>
<build>
<plugins>
<plugin>
<groupId>org.apache.felix</groupId>
<artifactId>maven-bundle-plugin</artifactId>
<extensions>true</extensions>
<executions>
<execution>
<id>generate-manifest</id>
<goals>
<goal>manifest</goal>
</goals>
<configuration>
<instructions>
<Export-Package>org.eclipse.jetty.apache.jsp.*;version="${parsedVersion.majorVersion}.${parsedVersion.minorVersion}.${parsedVersion.incrementalVersion}"</Export-Package>
<Require-Capability>osgi.extender; filter:="(osgi.extender=osgi.serviceloader.registrar)"</Require-Capability>
<Provide-Capability>osgi.serviceloader; osgi.serviceloader=javax.servlet.ServletContainerInitializer</Provide-Capability>
<_nouses>true</_nouses>
</instructions>
</configuration>
</execution>
</executions>
</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>
</plugins>
</build>
<dependencies>
<dependency>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-util</artifactId>
<version>${project.version}</version>
</dependency>
<!-- Schemas -->
<dependency>
<groupId>org.eclipse.jetty.toolchain</groupId>
<artifactId>jetty-schemas</artifactId>
</dependency>
<!-- servlet api -->
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
</dependency>
<!-- JSP Api -->
<dependency>
<groupId>javax.servlet.jsp</groupId>
<artifactId>javax.servlet.jsp-api</artifactId>
</dependency>
<!-- JSP Impl -->
<dependency>
<groupId>org.mortbay.jasper</groupId>
<artifactId>apache-jsp</artifactId>
</dependency>
<!-- Eclipse Java Compiler (for JSP Compilation) -->
<dependency>
<groupId>org.eclipse.jetty.orbit</groupId>
<artifactId>org.eclipse.jdt.core</artifactId>
</dependency>
</dependencies>
</project>

View File

@ -0,0 +1,10 @@
#
# Apache JSP Module
#
[name]
jsp-impl
[lib]
lib/apache-jsp/*.jar

View File

@ -0,0 +1,114 @@
//
// ========================================================================
// Copyright (c) 1995-2014 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.apache.jsp;
import java.io.IOException;
import java.net.URL;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
import java.util.Set;
import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import org.apache.jasper.servlet.JasperInitializer;
import org.apache.jasper.servlet.TldPreScanned;
import org.apache.jasper.servlet.TldScanner;
import org.xml.sax.SAXException;
/**
* JettyJasperInitializer
*
*/
public class JettyJasperInitializer extends JasperInitializer
{
/**
* NullTldScanner
*
* Does nothing. Used when we can tell that all jsps have been precompiled, in which case
* the tlds are not needed.
*/
private final class NullTldScanner extends TldScanner
{
/**
* @param context
* @param namespaceAware
* @param validation
* @param blockExternal
*/
private NullTldScanner(ServletContext context, boolean namespaceAware, boolean validation, boolean blockExternal)
{
super(context, namespaceAware, validation, blockExternal);
}
/**
* @see org.apache.jasper.servlet.TldScanner#scan()
*/
@Override
public void scan() throws IOException, SAXException
{
return; //do nothing
}
/**
* @see org.apache.jasper.servlet.TldScanner#getListeners()
*/
@Override
public List<String> getListeners()
{
return Collections.emptyList();
}
/**
* @see org.apache.jasper.servlet.TldScanner#scanJars()
*/
@Override
public void scanJars()
{
return; //do nothing
}
}
/**
* Make a TldScanner, and prefeed it the tlds that have already been discovered in jar files
* by the MetaInfConfiguration.
*
* @see org.apache.jasper.servlet.JasperInitializer#prepareScanner(javax.servlet.ServletContext, boolean, boolean, boolean)
*/
@Override
public TldScanner newTldScanner(ServletContext context, boolean namespaceAware, boolean validate, boolean blockExternal)
{
String tmp = context.getInitParameter("org.eclipse.jetty.jsp.precompiled");
if (tmp!=null && !tmp.equals("") && Boolean.valueOf(tmp))
{
return new NullTldScanner(context, namespaceAware, validate, blockExternal);
}
Collection<URL> tldUrls = (Collection<URL>)context.getAttribute("org.eclipse.jetty.tlds");
if (tldUrls != null && !tldUrls.isEmpty())
{
return new TldPreScanned(context,namespaceAware,validate,blockExternal,tldUrls);
}
return super.newTldScanner(context, namespaceAware, validate, blockExternal);
}
}

View File

@ -0,0 +1,188 @@
//
// ========================================================================
// Copyright (c) 1995-2014 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.apache.jsp;
public class JuliLog implements org.apache.juli.logging.Log
{
public static org.apache.juli.logging.Log getInstance(String name)
{
return new JuliLog(name);
}
private final org.eclipse.jetty.util.log.Logger _logger;
private final org.eclipse.jetty.util.log.StdErrLog _stdErrLog;
public JuliLog()
{
_logger=org.eclipse.jetty.util.log.Log.getRootLogger();
_stdErrLog=(_logger instanceof org.eclipse.jetty.util.log.StdErrLog) ? (org.eclipse.jetty.util.log.StdErrLog)_logger:null;
}
public JuliLog(String name)
{
_logger=org.eclipse.jetty.util.log.Log.getLogger(name);
_stdErrLog=(_logger instanceof org.eclipse.jetty.util.log.StdErrLog) ? (org.eclipse.jetty.util.log.StdErrLog)_logger:null;
}
@Override
public boolean isDebugEnabled()
{
return _logger.isDebugEnabled();
}
@Override
public boolean isErrorEnabled()
{
return _stdErrLog==null?true:_stdErrLog.getLevel()<=org.eclipse.jetty.util.log.StdErrLog.LEVEL_WARN;
}
@Override
public boolean isFatalEnabled()
{
return _stdErrLog==null?true:_stdErrLog.getLevel()<=org.eclipse.jetty.util.log.StdErrLog.LEVEL_WARN;
}
@Override
public boolean isInfoEnabled()
{
return _stdErrLog==null?true:_stdErrLog.getLevel()<=org.eclipse.jetty.util.log.StdErrLog.LEVEL_INFO;
}
@Override
public boolean isTraceEnabled()
{
return _stdErrLog==null?true:_stdErrLog.getLevel()<=org.eclipse.jetty.util.log.StdErrLog.LEVEL_DEBUG;
}
@Override
public boolean isWarnEnabled()
{
return _stdErrLog==null?true:_stdErrLog.getLevel()<=org.eclipse.jetty.util.log.StdErrLog.LEVEL_WARN;
}
@Override
public void trace(Object message)
{
if (message instanceof String)
_logger.debug((String)message);
else
_logger.debug("{}",message);
}
@Override
public void trace(Object message, Throwable t)
{
if (message instanceof String)
_logger.debug((String)message,t);
else
_logger.debug("{}",message,t);
}
@Override
public void debug(Object message)
{
if (message instanceof String)
_logger.debug((String)message);
else
_logger.debug("{}",message);
}
@Override
public void debug(Object message, Throwable t)
{
if (message instanceof String)
_logger.debug((String)message,t);
else
_logger.debug("{}",message,t);
}
@Override
public void info(Object message)
{
if (message instanceof String)
_logger.info((String)message);
else
_logger.info("{}",message);
}
@Override
public void info(Object message, Throwable t)
{
if (message instanceof String)
_logger.info((String)message,t);
else
_logger.info("{}",message,t);
}
@Override
public void warn(Object message)
{
if (message instanceof String)
_logger.warn((String)message);
else
_logger.warn("{}",message);
}
@Override
public void warn(Object message, Throwable t)
{
if (message instanceof String)
_logger.warn((String)message,t);
else
_logger.warn("{}",message,t);
}
@Override
public void error(Object message)
{
if (message instanceof String)
_logger.warn((String)message);
else
_logger.warn("{}",message);
}
@Override
public void error(Object message, Throwable t)
{
if (message instanceof String)
_logger.warn((String)message,t);
else
_logger.warn("{}",message,t);
}
@Override
public void fatal(Object message)
{
if (message instanceof String)
_logger.warn((String)message);
else
_logger.warn("{}",message);
}
@Override
public void fatal(Object message, Throwable t)
{
if (message instanceof String)
_logger.warn((String)message,t);
else
_logger.warn("{}",message,t);
}
}

View File

@ -0,0 +1 @@
org.eclipse.jetty.apache.jsp.JettyJasperInitializer

View File

@ -0,0 +1 @@
org.eclipse.jetty.apache.jsp.JuliLog

49
apache-jstl/pom.xml Normal file
View File

@ -0,0 +1,49 @@
<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.2.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>apache-jstl</artifactId>
<name>Apache :: JSTL module</name>
<url>http://tomcat.apache.org/taglibs/standard/</url>
<packaging>jar</packaging>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-assembly-plugin</artifactId>
<executions>
<execution>
<phase>package</phase>
<goals>
<goal>single</goal>
</goals>
<configuration>
<descriptorRefs>
<descriptorRef>config</descriptorRef>
</descriptorRefs>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
<dependencies>
<!-- JSTL Api -->
<dependency>
<groupId>org.apache.taglibs</groupId>
<artifactId>taglibs-standard-spec</artifactId>
</dependency>
<!-- JSTL Impl -->
<dependency>
<groupId>org.apache.taglibs</groupId>
<artifactId>taglibs-standard-impl</artifactId>
</dependency>
</dependencies>
</project>

View File

@ -0,0 +1,8 @@
#
# Apache JSTL
#
[name]
jstl-impl
[lib]
lib/apache-jstl/*.jar

View File

@ -0,0 +1,4 @@
This empty jar file is purely to work around a problem with the Maven Dependency plugin.
Several modules in jetty use the Dependency plugin to copy or unpack the dependencies of other modules.
However, the Dependency plugin is not capable of unpacking or copying a dependency of type 'pom', which
this module is, as it consists purely of external dependencies needed to run jsp.

View File

@ -0,0 +1,76 @@
<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-alpn-parent</artifactId>
<version>9.2.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>jetty-alpn-client</artifactId>
<name>Jetty :: ALPN Client</name>
<description>Jetty ALPN client services</description>
<url>http://www.eclipse.org/jetty</url>
<properties>
<bundle-symbolic-name>${project.groupId}.alpn.client</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>org.eclipse.jetty.alpn;resolution:=optional</Import-Package>
</instructions>
</configuration>
</execution>
</executions>
</plugin>
<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>
<!-- always include the sources to be able to prepare the eclipse-jetty-SDK feature
with a snapshot. -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-source-plugin</artifactId>
</plugin>
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>findbugs-maven-plugin</artifactId>
<configuration>
<onlyAnalyze>org.eclipse.jetty.alpn.*</onlyAnalyze>
</configuration>
</plugin>
</plugins>
</build>
<dependencies>
<dependency>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-io</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>org.eclipse.jetty.alpn</groupId>
<artifactId>alpn-api</artifactId>
<version>${alpn.api.version}</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.eclipse.jetty.toolchain</groupId>
<artifactId>jetty-test-helper</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
</project>

View File

@ -0,0 +1,87 @@
//
// ========================================================================
// Copyright (c) 1995-2014 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.alpn.client;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.concurrent.Executor;
import javax.net.ssl.SSLEngine;
import org.eclipse.jetty.alpn.ALPN;
import org.eclipse.jetty.io.ClientConnectionFactory;
import org.eclipse.jetty.io.EndPoint;
import org.eclipse.jetty.io.NegotiatingClientConnection;
import org.eclipse.jetty.util.log.Log;
import org.eclipse.jetty.util.log.Logger;
public class ALPNClientConnection extends NegotiatingClientConnection implements ALPN.ClientProvider
{
private static final Logger LOG = Log.getLogger(ALPNClientConnection.class);
private final String protocol;
public ALPNClientConnection(EndPoint endPoint, Executor executor, ClientConnectionFactory connectionFactory, SSLEngine sslEngine, Map<String, Object> context, String protocol)
{
super(endPoint, executor, sslEngine, connectionFactory, context);
this.protocol = protocol;
ALPN.put(sslEngine, this);
}
@Override
public boolean supports()
{
return true;
}
@Override
public void unsupported()
{
ALPN.remove(getSSLEngine());
completed();
}
@Override
public List<String> protocols()
{
return Arrays.asList(protocol);
}
@Override
public void selected(String protocol)
{
if (this.protocol.equals(protocol))
{
ALPN.remove(getSSLEngine());
completed();
}
else
{
LOG.info("Could not negotiate protocol: server {} - client {}", protocol, this.protocol);
close();
}
}
@Override
public void close()
{
ALPN.remove(getSSLEngine());
super.close();
}
}

View File

@ -0,0 +1,51 @@
//
// ========================================================================
// Copyright (c) 1995-2014 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.alpn.client;
import java.io.IOException;
import java.util.Map;
import java.util.concurrent.Executor;
import javax.net.ssl.SSLEngine;
import org.eclipse.jetty.io.ClientConnectionFactory;
import org.eclipse.jetty.io.Connection;
import org.eclipse.jetty.io.EndPoint;
import org.eclipse.jetty.io.NegotiatingClientConnectionFactory;
import org.eclipse.jetty.io.ssl.SslClientConnectionFactory;
public class ALPNClientConnectionFactory extends NegotiatingClientConnectionFactory
{
private final Executor executor;
private final String protocol;
public ALPNClientConnectionFactory(Executor executor, ClientConnectionFactory connectionFactory, String protocol)
{
super(connectionFactory);
this.executor = executor;
this.protocol = protocol;
}
@Override
public Connection newConnection(EndPoint endPoint, Map<String, Object> context) throws IOException
{
return new ALPNClientConnection(endPoint, executor, getClientConnectionFactory(),
(SSLEngine)context.get(SslClientConnectionFactory.SSL_ENGINE_CONTEXT_KEY), context, protocol);
}
}

View File

@ -0,0 +1,94 @@
<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-alpn-parent</artifactId>
<version>9.2.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>jetty-alpn-server</artifactId>
<name>Jetty :: ALPN Server</name>
<description>Jetty ALPN server services</description>
<url>http://www.eclipse.org/jetty</url>
<properties>
<bundle-symbolic-name>${project.groupId}.alpn.server</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>org.eclipse.jetty.alpn,*</Import-Package>
<_nouses>true</_nouses>
</instructions>
</configuration>
</execution>
</executions>
</plugin>
<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>
<!-- always include the sources to be able to prepare the eclipse-jetty-SDK feature
with a snapshot. -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-source-plugin</artifactId>
</plugin>
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>findbugs-maven-plugin</artifactId>
<configuration>
<onlyAnalyze>org.eclipse.jetty.alpn.*</onlyAnalyze>
</configuration>
</plugin>
</plugins>
</build>
<dependencies>
<dependency>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-server</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>org.eclipse.jetty.alpn</groupId>
<artifactId>alpn-api</artifactId>
<version>${alpn.api.version}</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.eclipse.jetty.toolchain</groupId>
<artifactId>jetty-test-helper</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
</project>

View File

@ -0,0 +1,16 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE Configure PUBLIC "-//Jetty//Configure//EN" "http://www.eclipse.org/jetty/configure_9_0.dtd">
<Configure id="protonego" class="org.eclipse.jetty.alpn.server.ALPNServerConnectionFactory">
<Arg name="protocols">
<Array type="String">
<Item>spdy/3</Item>
<Item>spdy/2</Item>
<Item>http/1.1</Item>
</Array>
</Arg>
<Set name="defaultProtocol">http/1.1</Set>
</Configure>

View File

@ -0,0 +1,8 @@
[name]
protonego-boot
[files]
http://central.maven.org/maven2/org/mortbay/jetty/alpn/alpn-boot/7.0.0/alpn-boot-7.0.0.jar:lib/alpn/alpn-boot-7.0.0.jar
[exec]
-Xbootclasspath/p:lib/alpn/alpn-boot-7.0.0.jar

View File

@ -0,0 +1,8 @@
[name]
protonego-boot
[files]
http://central.maven.org/maven2/org/mortbay/jetty/alpn/alpn-boot/7.0.0/alpn-boot-7.0.0.jar:lib/alpn/alpn-boot-7.0.0.jar
[exec]
-Xbootclasspath/p:lib/alpn/alpn-boot-7.0.0.jar

View File

@ -0,0 +1,8 @@
[name]
protonego-boot
[files]
http://central.maven.org/maven2/org/mortbay/jetty/alpn/alpn-boot/7.0.0/alpn-boot-7.0.0.jar:lib/alpn/alpn-boot-7.0.0.jar
[exec]
-Xbootclasspath/p:lib/alpn/alpn-boot-7.0.0.jar

View File

@ -0,0 +1,8 @@
[name]
protonego-boot
[files]
http://central.maven.org/maven2/org/mortbay/jetty/alpn/alpn-boot/8.0.0/alpn-boot-8.0.0.jar:lib/alpn/alpn-boot-8.0.0.jar
[exec]
-Xbootclasspath/p:lib/alpn/alpn-boot-8.0.0.jar

View File

@ -0,0 +1,36 @@
# ALPN is provided via a -Xbootclasspath that modifies the secure connections
# in java to support the ALPN layer needed for SPDY (and eventually HTTP/2)
#
# This modification has a tight dependency on specific recent updates of
# Java 1.7 and Java 1.8
# (Java versions prior to 1.7u40 are not supported)
#
# The alpn protonego module will use an appropriate alpn-boot jar for your
# specific version of Java.
#
# IMPORTANT: Versions of Java that exist after this module was created are
# not guaranteed to work with existing alpn-boot jars, and might
# need a new alpn-boot to be created / tested / deployed by the
# Jetty project in order to provide support for these future
# Java versions.
#
# All versions of alpn-boot can be found at
# http://central.maven.org/maven2/org/mortbay/jetty/alpn/alpn-boot/
[name]
protonego-impl
[depend]
protonego-impl/alpn-${java.version}
[lib]
lib/jetty-alpn-client-${jetty.version}.jar
lib/jetty-alpn-server-${jetty.version}.jar
[xml]
etc/protonego-alpn.xml
[files]
lib/
lib/alpn/

View File

@ -0,0 +1,77 @@
//
// ========================================================================
// Copyright (c) 1995-2014 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.alpn.server;
import java.util.Collections;
import java.util.List;
import javax.net.ssl.SSLEngine;
import org.eclipse.jetty.alpn.ALPN;
import org.eclipse.jetty.io.EndPoint;
import org.eclipse.jetty.server.Connector;
import org.eclipse.jetty.server.NegotiatingServerConnection;
import org.eclipse.jetty.util.log.Log;
import org.eclipse.jetty.util.log.Logger;
public class ALPNServerConnection extends NegotiatingServerConnection implements ALPN.ServerProvider
{
private static final Logger LOG = Log.getLogger(ALPNServerConnection.class);
public ALPNServerConnection(Connector connector, EndPoint endPoint, SSLEngine engine, List<String> protocols, String defaultProtocol)
{
super(connector, endPoint, engine, protocols, defaultProtocol);
ALPN.put(engine, this);
}
@Override
public void unsupported()
{
select(Collections.<String>emptyList());
}
@Override
public String select(List<String> clientProtocols)
{
List<String> serverProtocols = getProtocols();
String negotiated = null;
for (String clientProtocol : clientProtocols)
{
if (serverProtocols.contains(clientProtocol))
{
negotiated = clientProtocol;
break;
}
}
if (negotiated == null)
{
negotiated = getDefaultProtocol();
}
LOG.debug("{} protocol selected {}", this, negotiated);
setProtocol(negotiated);
ALPN.remove(getSSLEngine());
return negotiated;
}
@Override
public void close()
{
ALPN.remove(getSSLEngine());
super.close();
}
}

View File

@ -0,0 +1,61 @@
//
// ========================================================================
// Copyright (c) 1995-2014 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.alpn.server;
import java.util.List;
import javax.net.ssl.SSLEngine;
import org.eclipse.jetty.alpn.ALPN;
import org.eclipse.jetty.io.AbstractConnection;
import org.eclipse.jetty.io.EndPoint;
import org.eclipse.jetty.server.Connector;
import org.eclipse.jetty.server.NegotiatingServerConnectionFactory;
import org.eclipse.jetty.util.annotation.Name;
import org.eclipse.jetty.util.log.Log;
import org.eclipse.jetty.util.log.Logger;
public class ALPNServerConnectionFactory extends NegotiatingServerConnectionFactory
{
private static final Logger LOG = Log.getLogger(ALPNServerConnectionFactory.class);
public ALPNServerConnectionFactory(@Name("protocols") String... protocols)
{
super("alpn", protocols);
try
{
ClassLoader alpnClassLoader = ALPN.class.getClassLoader();
if (alpnClassLoader != null)
{
LOG.warn("ALPN must be in the boot classloader, not in: " + alpnClassLoader);
throw new IllegalStateException("ALPN must be in the boot classloader");
}
}
catch (Throwable x)
{
LOG.warn("ALPN not available", x);
throw new IllegalStateException("ALPN not available", x);
}
}
@Override
protected AbstractConnection newServerConnection(Connector connector, EndPoint endPoint, SSLEngine engine, List<String> protocols, String defaultProtocol)
{
return new ALPNServerConnection(connector, endPoint, engine, protocols, defaultProtocol);
}
}

17
jetty-alpn/pom.xml Normal file
View File

@ -0,0 +1,17 @@
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
<parent>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-project</artifactId>
<version>9.2.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>jetty-alpn-parent</artifactId>
<packaging>pom</packaging>
<name>Jetty :: ALPN :: Parent</name>
<description>Jetty ALPN services parent</description>
<url>http://www.eclipse.org/jetty</url>
<modules>
<module>jetty-alpn-server</module>
<module>jetty-alpn-client</module>
</modules>
</project>

View File

@ -43,7 +43,7 @@
</goals>
<configuration>
<instructions>
<Import-Package>javax.servlet.*;version="[2.6.0,3.2)",*</Import-Package>
<Import-Package>javax.servlet.*;version="[2.6.0,3.2)",org.objectweb.asm.*;version=4,*</Import-Package>
<Require-Capability>osgi.serviceloader; filter:="(osgi.serviceloader=javax.servlet.ServletContainerInitializer)";cardinality:=multiple, osgi.extender; filter:="(osgi.extender=osgi.serviceloader.processor)"</Require-Capability>
</instructions>
</configuration>

View File

@ -298,8 +298,8 @@ public abstract class HttpReceiver
if (decoder != null)
{
buffer = decoder.decode(buffer);
if (LOG.isDebugEnabled())
LOG.debug("Response content decoded ({}) {}{}{}", decoder, response, System.getProperty("line.separator"), BufferUtil.toDetailString(buffer));
// if (LOG.isDebugEnabled())
LOG.info("Response content decoded ({}) {}{}{}", decoder, response, System.getProperty("line.separator"), BufferUtil.toDetailString(buffer));
}
ResponseNotifier notifier = getHttpDestination().getResponseNotifier();

View File

@ -152,7 +152,7 @@ public abstract class HttpSender implements AsyncContentProvider.Listener
}
default:
{
throw new IllegalStateException(current.toString());
throw illegalSenderState(current);
}
}
}
@ -178,7 +178,7 @@ public abstract class HttpSender implements AsyncContentProvider.Listener
if (expects100Continue(request))
newSenderState = content.hasContent() ? SenderState.EXPECTING_WITH_CONTENT : SenderState.EXPECTING;
if (!updateSenderState(SenderState.IDLE, newSenderState))
throw new IllegalStateException();
throw illegalSenderState(SenderState.IDLE);
// Setting the listener may trigger calls to onContent() by other
// threads so we must set it only after the sender state has been updated
@ -462,7 +462,7 @@ public abstract class HttpSender implements AsyncContentProvider.Listener
{
// There is content to send.
if (!updateSenderState(current, SenderState.SENDING))
throw new IllegalStateException();
throw illegalSenderState(current);
LOG.debug("Proceeding while waiting");
sendContent(exchange, content, contentCallback); // TODO old style usage!
return;
@ -471,14 +471,14 @@ public abstract class HttpSender implements AsyncContentProvider.Listener
{
// No content to send yet - it's deferred.
if (!updateSenderState(current, SenderState.IDLE))
throw new IllegalStateException();
throw illegalSenderState(current);
LOG.debug("Proceeding deferred");
return;
}
}
default:
{
throw new IllegalStateException(current.toString());
throw illegalSenderState(current);
}
}
}
@ -532,6 +532,11 @@ public abstract class HttpSender implements AsyncContentProvider.Listener
}
}
private RuntimeException illegalSenderState(SenderState current)
{
return new IllegalStateException("Expected " + current + " found " + senderState.get() + " instead");
}
/**
* The request states {@link HttpSender} goes through when sending a request.
*/
@ -723,7 +728,7 @@ public abstract class HttpSender implements AsyncContentProvider.Listener
}
default:
{
throw new IllegalStateException();
throw illegalSenderState(current);
}
}
}
@ -792,11 +797,11 @@ public abstract class HttpSender implements AsyncContentProvider.Listener
return Action.SCHEDULED;
}
}
throw new IllegalStateException();
throw illegalSenderState(current);
}
default:
{
throw new IllegalStateException();
throw illegalSenderState(current);
}
}
}

View File

@ -129,6 +129,15 @@ public abstract class MultiplexHttpDestination<C extends Connection> extends Htt
return true;
}
@Override
public void close()
{
super.close();
C connection = this.connection;
if (connection != null)
connection.close();
}
@Override
public void close(Connection connection)
{

View File

@ -77,9 +77,10 @@ public class HttpChannelOverHTTP extends HttpChannel
public void exchangeTerminated(Result result)
{
super.exchangeTerminated(result);
boolean close = result.isFailed();
HttpFields responseHeaders = result.getResponse().getHeaders();
close |= responseHeaders.contains(HttpHeader.CONNECTION, HttpHeaderValue.CLOSE.asString());
boolean close = result.isFailed() ||
responseHeaders.contains(HttpHeader.CONNECTION, HttpHeaderValue.CLOSE.asString()) ||
receiver.isShutdown();
if (close)
connection.close();
else

View File

@ -18,6 +18,7 @@
package org.eclipse.jetty.client.http;
import java.nio.channels.AsynchronousCloseException;
import java.util.concurrent.TimeoutException;
import java.util.concurrent.atomic.AtomicBoolean;
@ -85,13 +86,8 @@ public class HttpConnectionOverHTTP extends AbstractConnection implements Connec
protected boolean onReadTimeout()
{
LOG.debug("{} idle timeout", this);
HttpExchange exchange = channel.getHttpExchange();
if (exchange != null)
return exchange.getRequest().abort(new TimeoutException());
getHttpDestination().close(this);
return true;
close(new TimeoutException());
return false;
}
@Override
@ -119,14 +115,23 @@ public class HttpConnectionOverHTTP extends AbstractConnection implements Connec
@Override
public void close()
{
close(new AsynchronousCloseException());
}
protected void close(Throwable failure)
{
if (softClose())
{
// First close then abort, to be sure that the connection cannot be reused
// from an onFailure() handler or by blocking code waiting for completion.
getHttpDestination().close(this);
getEndPoint().shutdownOutput();
LOG.debug("{} oshut", this);
getEndPoint().close();
LOG.debug("{} closed", this);
abort(failure);
}
}
@ -135,6 +140,12 @@ public class HttpConnectionOverHTTP extends AbstractConnection implements Connec
return closed.compareAndSet(false, true);
}
private boolean abort(Throwable failure)
{
HttpExchange exchange = channel.getHttpExchange();
return exchange != null && exchange.getRequest().abort(failure);
}
@Override
public String toString()
{

View File

@ -38,6 +38,7 @@ import org.eclipse.jetty.util.BufferUtil;
public class HttpReceiverOverHTTP extends HttpReceiver implements HttpParser.ResponseHandler<ByteBuffer>
{
private final HttpParser parser = new HttpParser(this);
private boolean shutdown;
public HttpReceiverOverHTTP(HttpChannelOverHTTP channel)
{
@ -124,11 +125,23 @@ public class HttpReceiverOverHTTP extends HttpReceiver implements HttpParser.Res
private void shutdown()
{
// Shutting down the parser may invoke messageComplete() or earlyEOF()
// Mark this receiver as shutdown, so that we can
// close the connection when the exchange terminates.
// We cannot close the connection from here because
// the request may still be in process.
shutdown = true;
// Shutting down the parser may invoke messageComplete() or earlyEOF().
// In case of content delimited by EOF, without a Connection: close
// header, the connection will be closed at exchange termination
// thanks to the flag we have set above.
parser.atEOF();
parser.parseNext(BufferUtil.EMPTY_BUFFER);
if (!responseFailure(new EOFException()))
getHttpConnection().close();
}
protected boolean isShutdown()
{
return shutdown;
}
@Override
@ -200,7 +213,11 @@ public class HttpReceiverOverHTTP extends HttpReceiver implements HttpParser.Res
@Override
public void earlyEOF()
{
failAndClose(new EOFException());
HttpExchange exchange = getHttpExchange();
if (exchange == null)
getHttpConnection().close();
else
failAndClose(new EOFException());
}
@Override
@ -232,7 +249,7 @@ public class HttpReceiverOverHTTP extends HttpReceiver implements HttpParser.Res
private void failAndClose(Throwable failure)
{
if (responseFailure(failure))
getHttpChannel().getHttpConnection().close();
getHttpConnection().close(failure);
}
@Override

View File

@ -82,9 +82,12 @@ public class HttpClientExplicitConnectionTest extends AbstractHttpClientServerTe
Assert.assertEquals(200, response.getStatus());
// Wait some time to have the client is an idle state.
TimeUnit.SECONDS.sleep(1);
connector.stop();
// Give the connection some time to process the remote close
// Give the connection some time to process the remote close.
TimeUnit.SECONDS.sleep(1);
HttpConnectionOverHTTP httpConnection = (HttpConnectionOverHTTP)connection;

View File

@ -45,6 +45,7 @@ import org.eclipse.jetty.util.ssl.SslContextFactory;
import org.hamcrest.Matchers;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Ignore;
import org.junit.Test;
public class HttpClientRedirectTest extends AbstractHttpClientServerTest
@ -244,8 +245,10 @@ public class HttpClientRedirectTest extends AbstractHttpClientServerTest
}
@Test
@Ignore
public void testRedirectFailed() throws Exception
{
// TODO this test is failing with timout after an ISP upgrade?? DNS dependent?
try
{
client.newRequest("localhost", connector.getLocalPort())

View File

@ -59,6 +59,7 @@ import org.eclipse.jetty.client.http.HttpConnectionOverHTTP;
import org.eclipse.jetty.client.http.HttpDestinationOverHTTP;
import org.eclipse.jetty.client.util.BufferingResponseListener;
import org.eclipse.jetty.client.util.BytesContentProvider;
import org.eclipse.jetty.client.util.DeferredContentProvider;
import org.eclipse.jetty.client.util.FutureResponseListener;
import org.eclipse.jetty.http.HttpField;
import org.eclipse.jetty.http.HttpHeader;
@ -72,6 +73,7 @@ import org.eclipse.jetty.util.FuturePromise;
import org.eclipse.jetty.util.IO;
import org.eclipse.jetty.util.ssl.SslContextFactory;
import org.junit.Assert;
import org.junit.Assume;
import org.junit.Rule;
import org.junit.Test;
@ -1161,4 +1163,105 @@ public class HttpClientTest extends AbstractHttpClientServerTest
Assert.assertEquals(200, response.getStatus());
Assert.assertTrue(response.getHeaders().contains(HttpHeader.CONNECTION, HttpHeaderValue.KEEP_ALIVE.asString()));
}
@Test
public void testLongPollIsAbortedWhenClientIsStopped() throws Exception
{
final CountDownLatch latch = new CountDownLatch(1);
start(new AbstractHandler()
{
@Override
public void handle(String target, org.eclipse.jetty.server.Request baseRequest, HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException
{
baseRequest.setHandled(true);
request.startAsync();
latch.countDown();
}
});
final CountDownLatch completeLatch = new CountDownLatch(1);
client.newRequest("localhost", connector.getLocalPort())
.scheme(scheme)
.send(new Response.CompleteListener()
{
@Override
public void onComplete(Result result)
{
if (result.isFailed())
completeLatch.countDown();
}
});
Assert.assertTrue(latch.await(5, TimeUnit.SECONDS));
// Stop the client, the complete listener must be invoked.
client.stop();
Assert.assertTrue(completeLatch.await(5, TimeUnit.SECONDS));
}
@Test
public void testSmallContentDelimitedByEOFWithSlowRequestHTTP10() throws Exception
{
testContentDelimitedByEOFWithSlowRequest(HttpVersion.HTTP_1_0, 1024);
}
@Test
public void testBigContentDelimitedByEOFWithSlowRequestHTTP10() throws Exception
{
testContentDelimitedByEOFWithSlowRequest(HttpVersion.HTTP_1_0, 128 * 1024);
}
@Test
public void testSmallContentDelimitedByEOFWithSlowRequestHTTP11() throws Exception
{
testContentDelimitedByEOFWithSlowRequest(HttpVersion.HTTP_1_1, 1024);
}
@Test
public void testBigContentDelimitedByEOFWithSlowRequestHTTP11() throws Exception
{
testContentDelimitedByEOFWithSlowRequest(HttpVersion.HTTP_1_1, 128 * 1024);
}
private void testContentDelimitedByEOFWithSlowRequest(final HttpVersion version, int length) throws Exception
{
// This test is crafted in a way that the response completes before the request is fully written.
// With SSL, the response coming down will close the SSLEngine so it would not be possible to
// write the last chunk of the request content, and the request will be failed, failing also the
// test, which is not what we want.
// This is a limit of Java's SSL implementation that does not allow half closes.
Assume.assumeTrue(sslContextFactory == null);
final byte[] data = new byte[length];
new Random().nextBytes(data);
start(new AbstractHandler()
{
@Override
public void handle(String target, org.eclipse.jetty.server.Request baseRequest, HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException
{
baseRequest.setHandled(true);
// Send Connection: close to avoid that the server chunks the content with HTTP 1.1.
if (version.compareTo(HttpVersion.HTTP_1_0) > 0)
response.setHeader("Connection", "close");
response.getOutputStream().write(data);
}
});
DeferredContentProvider content = new DeferredContentProvider(ByteBuffer.wrap(new byte[]{0}));
Request request = client.newRequest("localhost", connector.getLocalPort())
.scheme(scheme)
.version(version)
.content(content);
FutureResponseListener listener = new FutureResponseListener(request);
request.send(listener);
// Wait some time to simulate a slow request.
Thread.sleep(1000);
content.close();
ContentResponse response = listener.get(5, TimeUnit.SECONDS);
Assert.assertEquals(200, response.getStatus());
Assert.assertArrayEquals(data, response.getContent());
}
}

View File

@ -1,220 +0,0 @@
//
// ========================================================================
// Copyright (c) 1995-2014 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.client;
public class HttpReceiverTest
{
// @Rule
// public final TestTracker tracker = new TestTracker();
//
// private HttpClient client;
// private HttpDestination destination;
// private ByteArrayEndPoint endPoint;
// private HttpConnection connection;
// private HttpConversation conversation;
//
// @Before
// public void init() throws Exception
// {
// client = new HttpClient();
// client.start();
// destination = new HttpDestination(client, "http", "localhost", 8080);
// endPoint = new ByteArrayEndPoint();
// connection = new HttpConnection(client, endPoint, destination);
// conversation = new HttpConversation(client, 1);
// }
//
// @After
// public void destroy() throws Exception
// {
// client.stop();
// }
//
// protected HttpExchange newExchange()
// {
// HttpRequest request = new HttpRequest(client, URI.create("http://localhost"));
// FutureResponseListener listener = new FutureResponseListener(request);
// HttpExchange exchange = new HttpExchange(conversation, destination, request, Collections.<Response.ResponseListener>singletonList(listener));
// conversation.getExchanges().offer(exchange);
// connection.associate(exchange);
// exchange.requestComplete();
// exchange.terminateRequest();
// return exchange;
// }
//
// @Test
// public void test_Receive_NoResponseContent() throws Exception
// {
// endPoint.setInput("" +
// "HTTP/1.1 200 OK\r\n" +
// "Content-length: 0\r\n" +
// "\r\n");
// HttpExchange exchange = newExchange();
// FutureResponseListener listener = (FutureResponseListener)exchange.getResponseListeners().get(0);
// connection.receive();
//
// Response response = listener.get(5, TimeUnit.SECONDS);
// Assert.assertNotNull(response);
// Assert.assertEquals(200, response.getStatus());
// Assert.assertEquals("OK", response.getReason());
// Assert.assertSame(HttpVersion.HTTP_1_1, response.getVersion());
// HttpFields headers = response.getHeaders();
// Assert.assertNotNull(headers);
// Assert.assertEquals(1, headers.size());
// Assert.assertEquals("0", headers.get(HttpHeader.CONTENT_LENGTH));
// }
//
// @Test
// public void test_Receive_ResponseContent() throws Exception
// {
// String content = "0123456789ABCDEF";
// endPoint.setInput("" +
// "HTTP/1.1 200 OK\r\n" +
// "Content-length: " + content.length() + "\r\n" +
// "\r\n" +
// content);
// HttpExchange exchange = newExchange();
// FutureResponseListener listener = (FutureResponseListener)exchange.getResponseListeners().get(0);
// connection.receive();
//
// Response response = listener.get(5, TimeUnit.SECONDS);
// Assert.assertNotNull(response);
// Assert.assertEquals(200, response.getStatus());
// Assert.assertEquals("OK", response.getReason());
// Assert.assertSame(HttpVersion.HTTP_1_1, response.getVersion());
// HttpFields headers = response.getHeaders();
// Assert.assertNotNull(headers);
// Assert.assertEquals(1, headers.size());
// Assert.assertEquals(String.valueOf(content.length()), headers.get(HttpHeader.CONTENT_LENGTH));
// String received = listener.getContentAsString(StandardCharsets.UTF_8);
// Assert.assertEquals(content, received);
// }
//
// @Test
// public void test_Receive_ResponseContent_EarlyEOF() throws Exception
// {
// String content1 = "0123456789";
// String content2 = "ABCDEF";
// endPoint.setInput("" +
// "HTTP/1.1 200 OK\r\n" +
// "Content-length: " + (content1.length() + content2.length()) + "\r\n" +
// "\r\n" +
// content1);
// HttpExchange exchange = newExchange();
// FutureResponseListener listener = (FutureResponseListener)exchange.getResponseListeners().get(0);
// connection.receive();
// endPoint.setInputEOF();
// connection.receive();
//
// try
// {
// listener.get(5, TimeUnit.SECONDS);
// Assert.fail();
// }
// catch (ExecutionException e)
// {
// Assert.assertTrue(e.getCause() instanceof EOFException);
// }
// }
//
// @Test
// public void test_Receive_ResponseContent_IdleTimeout() throws Exception
// {
// endPoint.setInput("" +
// "HTTP/1.1 200 OK\r\n" +
// "Content-length: 1\r\n" +
// "\r\n");
// HttpExchange exchange = newExchange();
// FutureResponseListener listener = (FutureResponseListener)exchange.getResponseListeners().get(0);
// connection.receive();
// // Simulate an idle timeout
// connection.idleTimeout();
//
// try
// {
// listener.get(5, TimeUnit.SECONDS);
// Assert.fail();
// }
// catch (ExecutionException e)
// {
// Assert.assertTrue(e.getCause() instanceof TimeoutException);
// }
// }
//
// @Test
// public void test_Receive_BadResponse() throws Exception
// {
// endPoint.setInput("" +
// "HTTP/1.1 200 OK\r\n" +
// "Content-length: A\r\n" +
// "\r\n");
// HttpExchange exchange = newExchange();
// FutureResponseListener listener = (FutureResponseListener)exchange.getResponseListeners().get(0);
// connection.receive();
//
// try
// {
// listener.get(5, TimeUnit.SECONDS);
// Assert.fail();
// }
// catch (ExecutionException e)
// {
// Assert.assertTrue(e.getCause() instanceof HttpResponseException);
// }
// }
//
// @Test
// public void test_Receive_GZIPResponseContent_Fragmented() throws Exception
// {
// byte[] data = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9};
// ByteArrayOutputStream baos = new ByteArrayOutputStream();
// try (GZIPOutputStream gzipOutput = new GZIPOutputStream(baos))
// {
// gzipOutput.write(data);
// }
// byte[] gzip = baos.toByteArray();
//
// endPoint.setInput("" +
// "HTTP/1.1 200 OK\r\n" +
// "Content-Length: " + gzip.length + "\r\n" +
// "Content-Encoding: gzip\r\n" +
// "\r\n");
// HttpExchange exchange = newExchange();
// FutureResponseListener listener = (FutureResponseListener)exchange.getResponseListeners().get(0);
// connection.receive();
// endPoint.reset();
//
// ByteBuffer buffer = ByteBuffer.wrap(gzip);
// int fragment = buffer.limit() - 1;
// buffer.limit(fragment);
// endPoint.setInput(buffer);
// connection.receive();
// endPoint.reset();
//
// buffer.limit(gzip.length);
// buffer.position(fragment);
// endPoint.setInput(buffer);
// connection.receive();
//
// ContentResponse response = listener.get(5, TimeUnit.SECONDS);
// Assert.assertNotNull(response);
// Assert.assertEquals(200, response.getStatus());
// Assert.assertArrayEquals(data, response.getContent());
// }
}

View File

@ -1,280 +0,0 @@
//
// ========================================================================
// Copyright (c) 1995-2014 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.client;
public class HttpSenderTest
{
// @Rule
// public final TestTracker tracker = new TestTracker();
//
// private HttpClient client;
//
// @Before
// public void init() throws Exception
// {
// client = new HttpClient();
// client.start();
// }
//
// @After
// public void destroy() throws Exception
// {
// client.stop();
// }
//
// @Test
// public void test_Send_NoRequestContent() throws Exception
// {
// ByteArrayEndPoint endPoint = new ByteArrayEndPoint();
// HttpDestination destination = new HttpDestination(client, "http", "localhost", 8080);
// HttpConnection connection = new HttpConnection(client, endPoint, destination);
// Request request = client.newRequest(URI.create("http://localhost/"));
// final CountDownLatch headersLatch = new CountDownLatch(1);
// final CountDownLatch successLatch = new CountDownLatch(1);
// request.listener(new Request.Listener.Adapter()
// {
// @Override
// public void onHeaders(Request request)
// {
// headersLatch.countDown();
// }
//
// @Override
// public void onSuccess(Request request)
// {
// successLatch.countDown();
// }
// });
// connection.send(request, (Response.CompleteListener)null);
//
// String requestString = endPoint.takeOutputString();
// Assert.assertTrue(requestString.startsWith("GET "));
// Assert.assertTrue(requestString.endsWith("\r\n\r\n"));
// Assert.assertTrue(headersLatch.await(5, TimeUnit.SECONDS));
// Assert.assertTrue(successLatch.await(5, TimeUnit.SECONDS));
// }
//
// @Slow
// @Test
// public void test_Send_NoRequestContent_IncompleteFlush() throws Exception
// {
// ByteArrayEndPoint endPoint = new ByteArrayEndPoint("", 16);
// HttpDestination destination = new HttpDestination(client, "http", "localhost", 8080);
// HttpConnection connection = new HttpConnection(client, endPoint, destination);
// Request request = client.newRequest(URI.create("http://localhost/"));
// connection.send(request, (Response.CompleteListener)null);
//
// // This take will free space in the buffer and allow for the write to complete
// StringBuilder builder = new StringBuilder(endPoint.takeOutputString());
//
// // Wait for the write to complete
// TimeUnit.SECONDS.sleep(1);
//
// String chunk = endPoint.takeOutputString();
// while (chunk.length() > 0)
// {
// builder.append(chunk);
// chunk = endPoint.takeOutputString();
// }
//
// String requestString = builder.toString();
// Assert.assertTrue(requestString.startsWith("GET "));
// Assert.assertTrue(requestString.endsWith("\r\n\r\n"));
// }
//
// @Test
// public void test_Send_NoRequestContent_Exception() throws Exception
// {
// ByteArrayEndPoint endPoint = new ByteArrayEndPoint();
// // Shutdown output to trigger the exception on write
// endPoint.shutdownOutput();
// HttpDestination destination = new HttpDestination(client, "http", "localhost", 8080);
// HttpConnection connection = new HttpConnection(client, endPoint, destination);
// Request request = client.newRequest(URI.create("http://localhost/"));
// final CountDownLatch failureLatch = new CountDownLatch(2);
// request.listener(new Request.Listener.Adapter()
// {
// @Override
// public void onFailure(Request request, Throwable x)
// {
// failureLatch.countDown();
// }
// });
// connection.send(request, new Response.Listener.Adapter()
// {
// @Override
// public void onComplete(Result result)
// {
// Assert.assertTrue(result.isFailed());
// failureLatch.countDown();
// }
// });
//
// Assert.assertTrue(failureLatch.await(5, TimeUnit.SECONDS));
// }
//
// @Test
// public void test_Send_NoRequestContent_IncompleteFlush_Exception() throws Exception
// {
// ByteArrayEndPoint endPoint = new ByteArrayEndPoint("", 16);
// HttpDestination destination = new HttpDestination(client, "http", "localhost", 8080);
// HttpConnection connection = new HttpConnection(client, endPoint, destination);
// Request request = client.newRequest(URI.create("http://localhost/"));
// final CountDownLatch failureLatch = new CountDownLatch(2);
// request.listener(new Request.Listener.Adapter()
// {
// @Override
// public void onFailure(Request request, Throwable x)
// {
// failureLatch.countDown();
// }
// });
// connection.send(request, new Response.Listener.Adapter()
// {
// @Override
// public void onComplete(Result result)
// {
// Assert.assertTrue(result.isFailed());
// failureLatch.countDown();
// }
// });
//
// // Shutdown output to trigger the exception on write
// endPoint.shutdownOutput();
// // This take will free space in the buffer and allow for the write to complete
// // although it will fail because we shut down the output
// endPoint.takeOutputString();
//
// Assert.assertTrue(failureLatch.await(5, TimeUnit.SECONDS));
// }
//
// @Test
// public void test_Send_SmallRequestContent_InOneBuffer() throws Exception
// {
// ByteArrayEndPoint endPoint = new ByteArrayEndPoint();
// HttpDestination destination = new HttpDestination(client, "http", "localhost", 8080);
// HttpConnection connection = new HttpConnection(client, endPoint, destination);
// Request request = client.newRequest(URI.create("http://localhost/"));
// String content = "abcdef";
// request.content(new ByteBufferContentProvider(ByteBuffer.wrap(content.getBytes(StandardCharsets.UTF_8))));
// final CountDownLatch headersLatch = new CountDownLatch(1);
// final CountDownLatch successLatch = new CountDownLatch(1);
// request.listener(new Request.Listener.Adapter()
// {
// @Override
// public void onHeaders(Request request)
// {
// headersLatch.countDown();
// }
//
// @Override
// public void onSuccess(Request request)
// {
// successLatch.countDown();
// }
// });
// connection.send(request, (Response.CompleteListener)null);
//
// String requestString = endPoint.takeOutputString();
// Assert.assertTrue(requestString.startsWith("GET "));
// Assert.assertTrue(requestString.endsWith("\r\n\r\n" + content));
// Assert.assertTrue(headersLatch.await(5, TimeUnit.SECONDS));
// Assert.assertTrue(successLatch.await(5, TimeUnit.SECONDS));
// }
//
// @Test
// public void test_Send_SmallRequestContent_InTwoBuffers() throws Exception
// {
// ByteArrayEndPoint endPoint = new ByteArrayEndPoint();
// HttpDestination destination = new HttpDestination(client, "http", "localhost", 8080);
// HttpConnection connection = new HttpConnection(client, endPoint, destination);
// Request request = client.newRequest(URI.create("http://localhost/"));
// String content1 = "0123456789";
// String content2 = "abcdef";
// request.content(new ByteBufferContentProvider(ByteBuffer.wrap(content1.getBytes(StandardCharsets.UTF_8)), ByteBuffer.wrap(content2.getBytes(StandardCharsets.UTF_8))));
// final CountDownLatch headersLatch = new CountDownLatch(1);
// final CountDownLatch successLatch = new CountDownLatch(1);
// request.listener(new Request.Listener.Adapter()
// {
// @Override
// public void onHeaders(Request request)
// {
// headersLatch.countDown();
// }
//
// @Override
// public void onSuccess(Request request)
// {
// successLatch.countDown();
// }
// });
// connection.send(request, (Response.CompleteListener)null);
//
// String requestString = endPoint.takeOutputString();
// Assert.assertTrue(requestString.startsWith("GET "));
// Assert.assertTrue(requestString.endsWith("\r\n\r\n" + content1 + content2));
// Assert.assertTrue(headersLatch.await(5, TimeUnit.SECONDS));
// Assert.assertTrue(successLatch.await(5, TimeUnit.SECONDS));
// }
//
// @Test
// public void test_Send_SmallRequestContent_Chunked_InTwoChunks() throws Exception
// {
// ByteArrayEndPoint endPoint = new ByteArrayEndPoint();
// HttpDestination destination = new HttpDestination(client, "http", "localhost", 8080);
// HttpConnection connection = new HttpConnection(client, endPoint, destination);
// Request request = client.newRequest(URI.create("http://localhost/"));
// String content1 = "0123456789";
// String content2 = "ABCDEF";
// request.content(new ByteBufferContentProvider(ByteBuffer.wrap(content1.getBytes(StandardCharsets.UTF_8)), ByteBuffer.wrap(content2.getBytes(StandardCharsets.UTF_8)))
// {
// @Override
// public long getLength()
// {
// return -1;
// }
// });
// final CountDownLatch headersLatch = new CountDownLatch(1);
// final CountDownLatch successLatch = new CountDownLatch(1);
// request.listener(new Request.Listener.Adapter()
// {
// @Override
// public void onHeaders(Request request)
// {
// headersLatch.countDown();
// }
//
// @Override
// public void onSuccess(Request request)
// {
// successLatch.countDown();
// }
// });
// connection.send(request, (Response.CompleteListener)null);
//
// String requestString = endPoint.takeOutputString();
// Assert.assertTrue(requestString.startsWith("GET "));
// String content = Integer.toHexString(content1.length()).toUpperCase(Locale.ENGLISH) + "\r\n" + content1 + "\r\n";
// content += Integer.toHexString(content2.length()).toUpperCase(Locale.ENGLISH) + "\r\n" + content2 + "\r\n";
// content += "0\r\n\r\n";
// Assert.assertTrue(requestString.endsWith("\r\n\r\n" + content));
// Assert.assertTrue(headersLatch.await(5, TimeUnit.SECONDS));
// Assert.assertTrue(successLatch.await(5, TimeUnit.SECONDS));
// }
}

View File

@ -0,0 +1,262 @@
//
// ========================================================================
// Copyright (c) 1995-2014 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.client.http;
import java.io.ByteArrayOutputStream;
import java.io.EOFException;
import java.nio.ByteBuffer;
import java.nio.charset.StandardCharsets;
import java.util.Collections;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;
import java.util.zip.GZIPOutputStream;
import org.eclipse.jetty.client.HttpClient;
import org.eclipse.jetty.client.HttpExchange;
import org.eclipse.jetty.client.HttpRequest;
import org.eclipse.jetty.client.HttpResponseException;
import org.eclipse.jetty.client.Origin;
import org.eclipse.jetty.client.api.ContentResponse;
import org.eclipse.jetty.client.api.Response;
import org.eclipse.jetty.client.util.FutureResponseListener;
import org.eclipse.jetty.http.HttpFields;
import org.eclipse.jetty.http.HttpHeader;
import org.eclipse.jetty.http.HttpVersion;
import org.eclipse.jetty.io.ByteArrayEndPoint;
import org.eclipse.jetty.toolchain.test.TestTracker;
import org.junit.After;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
public class HttpReceiverOverHTTPTest
{
@Rule
public final TestTracker tracker = new TestTracker();
private HttpClient client;
private HttpDestinationOverHTTP destination;
private ByteArrayEndPoint endPoint;
private HttpConnectionOverHTTP connection;
@Before
public void init() throws Exception
{
client = new HttpClient();
client.start();
destination = new HttpDestinationOverHTTP(client, new Origin("http", "localhost", 8080));
endPoint = new ByteArrayEndPoint();
connection = new HttpConnectionOverHTTP(endPoint, destination);
}
@After
public void destroy() throws Exception
{
client.stop();
}
protected HttpExchange newExchange()
{
HttpRequest request = (HttpRequest)client.newRequest("http://localhost");
FutureResponseListener listener = new FutureResponseListener(request);
HttpExchange exchange = new HttpExchange(destination, request, Collections.<Response.ResponseListener>singletonList(listener));
connection.getHttpChannel().associate(exchange);
exchange.requestComplete();
exchange.terminateRequest(null);
return exchange;
}
@Test
public void test_Receive_NoResponseContent() throws Exception
{
endPoint.setInput("" +
"HTTP/1.1 200 OK\r\n" +
"Content-length: 0\r\n" +
"\r\n");
HttpExchange exchange = newExchange();
FutureResponseListener listener = (FutureResponseListener)exchange.getResponseListeners().get(0);
connection.getHttpChannel().receive();
Response response = listener.get(5, TimeUnit.SECONDS);
Assert.assertNotNull(response);
Assert.assertEquals(200, response.getStatus());
Assert.assertEquals("OK", response.getReason());
Assert.assertSame(HttpVersion.HTTP_1_1, response.getVersion());
HttpFields headers = response.getHeaders();
Assert.assertNotNull(headers);
Assert.assertEquals(1, headers.size());
Assert.assertEquals("0", headers.get(HttpHeader.CONTENT_LENGTH));
}
@Test
public void test_Receive_ResponseContent() throws Exception
{
String content = "0123456789ABCDEF";
endPoint.setInput("" +
"HTTP/1.1 200 OK\r\n" +
"Content-length: " + content.length() + "\r\n" +
"\r\n" +
content);
HttpExchange exchange = newExchange();
FutureResponseListener listener = (FutureResponseListener)exchange.getResponseListeners().get(0);
connection.getHttpChannel().receive();
Response response = listener.get(5, TimeUnit.SECONDS);
Assert.assertNotNull(response);
Assert.assertEquals(200, response.getStatus());
Assert.assertEquals("OK", response.getReason());
Assert.assertSame(HttpVersion.HTTP_1_1, response.getVersion());
HttpFields headers = response.getHeaders();
Assert.assertNotNull(headers);
Assert.assertEquals(1, headers.size());
Assert.assertEquals(String.valueOf(content.length()), headers.get(HttpHeader.CONTENT_LENGTH));
String received = listener.getContentAsString(StandardCharsets.UTF_8);
Assert.assertEquals(content, received);
}
@Test
public void test_Receive_ResponseContent_EarlyEOF() throws Exception
{
String content1 = "0123456789";
String content2 = "ABCDEF";
endPoint.setInput("" +
"HTTP/1.1 200 OK\r\n" +
"Content-length: " + (content1.length() + content2.length()) + "\r\n" +
"\r\n" +
content1);
HttpExchange exchange = newExchange();
FutureResponseListener listener = (FutureResponseListener)exchange.getResponseListeners().get(0);
connection.getHttpChannel().receive();
endPoint.setInputEOF();
connection.getHttpChannel().receive();
try
{
listener.get(5, TimeUnit.SECONDS);
Assert.fail();
}
catch (ExecutionException e)
{
Assert.assertTrue(e.getCause() instanceof EOFException);
}
}
@Test
public void test_Receive_ResponseContent_IdleTimeout() throws Exception
{
endPoint.setInput("" +
"HTTP/1.1 200 OK\r\n" +
"Content-length: 1\r\n" +
"\r\n");
HttpExchange exchange = newExchange();
FutureResponseListener listener = (FutureResponseListener)exchange.getResponseListeners().get(0);
connection.getHttpChannel().receive();
// Simulate an idle timeout
connection.onReadTimeout();
try
{
listener.get(5, TimeUnit.SECONDS);
Assert.fail();
}
catch (ExecutionException e)
{
Assert.assertTrue(e.getCause() instanceof TimeoutException);
}
}
@Test
public void test_Receive_BadResponse() throws Exception
{
endPoint.setInput("" +
"HTTP/1.1 200 OK\r\n" +
"Content-length: A\r\n" +
"\r\n");
HttpExchange exchange = newExchange();
FutureResponseListener listener = (FutureResponseListener)exchange.getResponseListeners().get(0);
connection.getHttpChannel().receive();
try
{
listener.get(5, TimeUnit.SECONDS);
Assert.fail();
}
catch (ExecutionException e)
{
Assert.assertTrue(e.getCause() instanceof HttpResponseException);
}
}
@Test
public void test_Receive_GZIPResponseContent_Fragmented() throws Exception
{
byte[] data = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9};
ByteArrayOutputStream baos = new ByteArrayOutputStream();
try (GZIPOutputStream gzipOutput = new GZIPOutputStream(baos))
{
gzipOutput.write(data);
}
byte[] gzip = baos.toByteArray();
endPoint.setInput("" +
"HTTP/1.1 200 OK\r\n" +
"Content-Length: " + gzip.length + "\r\n" +
"Content-Encoding: gzip\r\n" +
"\r\n");
HttpRequest request = (HttpRequest)client.newRequest("http://localhost");
final CountDownLatch latch = new CountDownLatch(1);
FutureResponseListener listener = new FutureResponseListener(request)
{
@Override
public void onContent(Response response, ByteBuffer content)
{
super.onContent(response, content);
latch.countDown();
}
};
HttpExchange exchange = new HttpExchange(destination, request, Collections.<Response.ResponseListener>singletonList(listener));
connection.getHttpChannel().associate(exchange);
exchange.requestComplete();
exchange.terminateRequest(null);
connection.getHttpChannel().receive();
endPoint.reset();
ByteBuffer buffer = ByteBuffer.wrap(gzip);
int fragment = buffer.limit() - 1;
buffer.limit(fragment);
endPoint.setInput(buffer);
connection.getHttpChannel().receive();
endPoint.reset();
buffer.limit(gzip.length);
buffer.position(fragment);
endPoint.setInput(buffer);
connection.getHttpChannel().receive();
ContentResponse response = listener.get(5, TimeUnit.SECONDS);
Assert.assertNotNull(response);
Assert.assertEquals(200, response.getStatus());
Assert.assertTrue(latch.await(5, TimeUnit.SECONDS));
Assert.assertArrayEquals(data, response.getContent());
}
}

View File

@ -0,0 +1,302 @@
//
// ========================================================================
// Copyright (c) 1995-2014 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.client.http;
import java.net.URI;
import java.nio.ByteBuffer;
import java.nio.charset.StandardCharsets;
import java.util.Locale;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;
import org.eclipse.jetty.client.HttpClient;
import org.eclipse.jetty.client.Origin;
import org.eclipse.jetty.client.api.Request;
import org.eclipse.jetty.client.api.Response;
import org.eclipse.jetty.client.api.Result;
import org.eclipse.jetty.client.util.ByteBufferContentProvider;
import org.eclipse.jetty.io.ByteArrayEndPoint;
import org.eclipse.jetty.toolchain.test.TestTracker;
import org.eclipse.jetty.toolchain.test.annotation.Slow;
import org.junit.After;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
public class HttpSenderOverHTTPTest
{
@Rule
public final TestTracker tracker = new TestTracker();
private HttpClient client;
@Before
public void init() throws Exception
{
client = new HttpClient();
client.start();
}
@After
public void destroy() throws Exception
{
client.stop();
}
@Test
public void test_Send_NoRequestContent() throws Exception
{
ByteArrayEndPoint endPoint = new ByteArrayEndPoint();
HttpDestinationOverHTTP destination = new HttpDestinationOverHTTP(client, new Origin("http", "localhost", 8080));
HttpConnectionOverHTTP connection = new HttpConnectionOverHTTP(endPoint, destination);
Request request = client.newRequest(URI.create("http://localhost/"));
final CountDownLatch headersLatch = new CountDownLatch(1);
final CountDownLatch successLatch = new CountDownLatch(1);
request.listener(new Request.Listener.Adapter()
{
@Override
public void onHeaders(Request request)
{
headersLatch.countDown();
}
@Override
public void onSuccess(Request request)
{
successLatch.countDown();
}
});
connection.send(request, null);
String requestString = endPoint.takeOutputString();
Assert.assertTrue(requestString.startsWith("GET "));
Assert.assertTrue(requestString.endsWith("\r\n\r\n"));
Assert.assertTrue(headersLatch.await(5, TimeUnit.SECONDS));
Assert.assertTrue(successLatch.await(5, TimeUnit.SECONDS));
}
@Slow
@Test
public void test_Send_NoRequestContent_IncompleteFlush() throws Exception
{
ByteArrayEndPoint endPoint = new ByteArrayEndPoint("", 16);
HttpDestinationOverHTTP destination = new HttpDestinationOverHTTP(client, new Origin("http", "localhost", 8080));
HttpConnectionOverHTTP connection = new HttpConnectionOverHTTP(endPoint, destination);
Request request = client.newRequest(URI.create("http://localhost/"));
connection.send(request, null);
// This take will free space in the buffer and allow for the write to complete
StringBuilder builder = new StringBuilder(endPoint.takeOutputString());
// Wait for the write to complete
TimeUnit.SECONDS.sleep(1);
String chunk = endPoint.takeOutputString();
while (chunk.length() > 0)
{
builder.append(chunk);
chunk = endPoint.takeOutputString();
}
String requestString = builder.toString();
Assert.assertTrue(requestString.startsWith("GET "));
Assert.assertTrue(requestString.endsWith("\r\n\r\n"));
}
@Test
public void test_Send_NoRequestContent_Exception() throws Exception
{
ByteArrayEndPoint endPoint = new ByteArrayEndPoint();
// Shutdown output to trigger the exception on write
endPoint.shutdownOutput();
HttpDestinationOverHTTP destination = new HttpDestinationOverHTTP(client, new Origin("http", "localhost", 8080));
HttpConnectionOverHTTP connection = new HttpConnectionOverHTTP(endPoint, destination);
Request request = client.newRequest(URI.create("http://localhost/"));
final CountDownLatch failureLatch = new CountDownLatch(2);
request.listener(new Request.Listener.Adapter()
{
@Override
public void onFailure(Request request, Throwable x)
{
failureLatch.countDown();
}
});
connection.send(request, new Response.Listener.Adapter()
{
@Override
public void onComplete(Result result)
{
Assert.assertTrue(result.isFailed());
failureLatch.countDown();
}
});
Assert.assertTrue(failureLatch.await(5, TimeUnit.SECONDS));
}
@Test
public void test_Send_NoRequestContent_IncompleteFlush_Exception() throws Exception
{
ByteArrayEndPoint endPoint = new ByteArrayEndPoint("", 16);
HttpDestinationOverHTTP destination = new HttpDestinationOverHTTP(client, new Origin("http", "localhost", 8080));
HttpConnectionOverHTTP connection = new HttpConnectionOverHTTP(endPoint, destination);
Request request = client.newRequest(URI.create("http://localhost/"));
final CountDownLatch failureLatch = new CountDownLatch(2);
request.listener(new Request.Listener.Adapter()
{
@Override
public void onFailure(Request request, Throwable x)
{
failureLatch.countDown();
}
});
connection.send(request, new Response.Listener.Adapter()
{
@Override
public void onComplete(Result result)
{
Assert.assertTrue(result.isFailed());
failureLatch.countDown();
}
});
// Shutdown output to trigger the exception on write
endPoint.shutdownOutput();
// This take will free space in the buffer and allow for the write to complete
// although it will fail because we shut down the output
endPoint.takeOutputString();
Assert.assertTrue(failureLatch.await(5, TimeUnit.SECONDS));
}
@Test
public void test_Send_SmallRequestContent_InOneBuffer() throws Exception
{
ByteArrayEndPoint endPoint = new ByteArrayEndPoint();
HttpDestinationOverHTTP destination = new HttpDestinationOverHTTP(client, new Origin("http", "localhost", 8080));
HttpConnectionOverHTTP connection = new HttpConnectionOverHTTP(endPoint, destination);
Request request = client.newRequest(URI.create("http://localhost/"));
String content = "abcdef";
request.content(new ByteBufferContentProvider(ByteBuffer.wrap(content.getBytes(StandardCharsets.UTF_8))));
final CountDownLatch headersLatch = new CountDownLatch(1);
final CountDownLatch successLatch = new CountDownLatch(1);
request.listener(new Request.Listener.Adapter()
{
@Override
public void onHeaders(Request request)
{
headersLatch.countDown();
}
@Override
public void onSuccess(Request request)
{
successLatch.countDown();
}
});
connection.send(request, null);
String requestString = endPoint.takeOutputString();
Assert.assertTrue(requestString.startsWith("GET "));
Assert.assertTrue(requestString.endsWith("\r\n\r\n" + content));
Assert.assertTrue(headersLatch.await(5, TimeUnit.SECONDS));
Assert.assertTrue(successLatch.await(5, TimeUnit.SECONDS));
}
@Test
public void test_Send_SmallRequestContent_InTwoBuffers() throws Exception
{
ByteArrayEndPoint endPoint = new ByteArrayEndPoint();
HttpDestinationOverHTTP destination = new HttpDestinationOverHTTP(client, new Origin("http", "localhost", 8080));
HttpConnectionOverHTTP connection = new HttpConnectionOverHTTP(endPoint, destination);
Request request = client.newRequest(URI.create("http://localhost/"));
String content1 = "0123456789";
String content2 = "abcdef";
request.content(new ByteBufferContentProvider(ByteBuffer.wrap(content1.getBytes(StandardCharsets.UTF_8)), ByteBuffer.wrap(content2.getBytes(StandardCharsets.UTF_8))));
final CountDownLatch headersLatch = new CountDownLatch(1);
final CountDownLatch successLatch = new CountDownLatch(1);
request.listener(new Request.Listener.Adapter()
{
@Override
public void onHeaders(Request request)
{
headersLatch.countDown();
}
@Override
public void onSuccess(Request request)
{
successLatch.countDown();
}
});
connection.send(request, null);
String requestString = endPoint.takeOutputString();
Assert.assertTrue(requestString.startsWith("GET "));
Assert.assertTrue(requestString.endsWith("\r\n\r\n" + content1 + content2));
Assert.assertTrue(headersLatch.await(5, TimeUnit.SECONDS));
Assert.assertTrue(successLatch.await(5, TimeUnit.SECONDS));
}
@Test
public void test_Send_SmallRequestContent_Chunked_InTwoChunks() throws Exception
{
ByteArrayEndPoint endPoint = new ByteArrayEndPoint();
HttpDestinationOverHTTP destination = new HttpDestinationOverHTTP(client, new Origin("http", "localhost", 8080));
HttpConnectionOverHTTP connection = new HttpConnectionOverHTTP(endPoint, destination);
Request request = client.newRequest(URI.create("http://localhost/"));
String content1 = "0123456789";
String content2 = "ABCDEF";
request.content(new ByteBufferContentProvider(ByteBuffer.wrap(content1.getBytes(StandardCharsets.UTF_8)), ByteBuffer.wrap(content2.getBytes(StandardCharsets.UTF_8)))
{
@Override
public long getLength()
{
return -1;
}
});
final CountDownLatch headersLatch = new CountDownLatch(1);
final CountDownLatch successLatch = new CountDownLatch(1);
request.listener(new Request.Listener.Adapter()
{
@Override
public void onHeaders(Request request)
{
headersLatch.countDown();
}
@Override
public void onSuccess(Request request)
{
successLatch.countDown();
}
});
connection.send(request, null);
String requestString = endPoint.takeOutputString();
Assert.assertTrue(requestString.startsWith("GET "));
String content = Integer.toHexString(content1.length()).toUpperCase(Locale.ENGLISH) + "\r\n" + content1 + "\r\n";
content += Integer.toHexString(content2.length()).toUpperCase(Locale.ENGLISH) + "\r\n" + content2 + "\r\n";
content += "0\r\n\r\n";
Assert.assertTrue(requestString.endsWith("\r\n\r\n" + content));
Assert.assertTrue(headersLatch.await(5, TimeUnit.SECONDS));
Assert.assertTrue(successLatch.await(5, TimeUnit.SECONDS));
}
}

View File

@ -77,6 +77,7 @@ import org.junit.After;
import org.junit.Assert;
import org.junit.Assume;
import org.junit.Before;
import org.junit.Ignore;
import org.junit.Test;
public class SslBytesServerTest extends SslBytesTest
@ -237,7 +238,7 @@ public class SslBytesServerTest extends SslBytesTest
threadPool.shutdownNow();
}
@Test
@Test(timeout=10000)
public void testHandshake() throws Exception
{
final SSLSocket client = newClient();
@ -1390,7 +1391,9 @@ public class SslBytesServerTest extends SslBytesTest
closeClient(client);
}
@Test
// TODO work out why this test frequently fails
@Ignore
@Test(timeout=10000)
public void testRequestWithContentWithRenegotiationInMiddleOfContentWhenRenegotiationIsForbidden() throws Exception
{
assumeJavaVersionSupportsTLSRenegotiations();
@ -1616,7 +1619,7 @@ public class SslBytesServerTest extends SslBytesTest
closeClient(client);
}
@Test
@Test(timeout=10000)
public void testRequestWithBigContentWithRenegotiationInMiddleOfContentWithSplitBoundary() throws Exception
{
assumeJavaVersionSupportsTLSRenegotiations();

View File

@ -302,7 +302,7 @@
<configuration>
<includeGroupIds>org.eclipse.jetty</includeGroupIds>
<excludeGroupIds>org.eclipse.jetty.orbit,org.eclipse.jetty.spdy,org.eclipse.jetty.websocket,org.eclipse.jetty.fcgi,org.eclipse.jetty.toolchain,org.apache.taglibs</excludeGroupIds>
<excludeArtifactIds>jetty-all,jetty-jsp,jetty-start,jetty-monitor</excludeArtifactIds>
<excludeArtifactIds>jetty-all,jetty-jsp,apache-jsp,jetty-start,jetty-monitor</excludeArtifactIds>
<includeTypes>jar</includeTypes>
<outputDirectory>${assembly-directory}/lib</outputDirectory>
</configuration>
@ -457,6 +457,20 @@
<outputDirectory>${assembly-directory}/lib/jsp</outputDirectory>
</configuration>
</execution>
<execution>
<id>copy-apache-jsp-deps</id>
<phase>generate-resources</phase>
<goals>
<goal>copy-dependencies</goal>
</goals>
<configuration>
<includeGroupIds>org.eclipse.jetty,org.eclipse.jetty.toolchain,javax.servlet.jsp,org.mortbay.jasper,org.mortbay.jasper,org.eclipse.jetty.orbit</includeGroupIds>
<includeArtifactIds>apache-jsp,javax.servlet.jsp-api,apache-el,org.eclipse.jdt.core</includeArtifactIds>
<includeTypes>jar</includeTypes>
<prependGroupId>true</prependGroupId>
<outputDirectory>${assembly-directory}/lib/apache-jsp</outputDirectory>
</configuration>
</execution>
<execution>
<id>copy-jstl-api</id>
<phase>generate-resources</phase>
@ -484,6 +498,20 @@
<outputDirectory>${assembly-directory}/lib/jsp</outputDirectory>
</configuration>
</execution>
<execution>
<id>copy-apache-jstl-deps</id>
<phase>generate-resources</phase>
<goals>
<goal>copy-dependencies</goal>
</goals>
<configuration>
<excludeGroupIds>org.glassfish.web</excludeGroupIds>
<includeArtifactIds>taglibs-standard-spec,taglibs-standard-impl</includeArtifactIds>
<prependGroupId>true</prependGroupId>
<includeTypes>jar</includeTypes>
<outputDirectory>${assembly-directory}/lib/apache-jstl</outputDirectory>
</configuration>
</execution>
<execution>
<id>copy-jaspi-deps</id>
<phase>generate-resources</phase>
@ -526,7 +554,7 @@
<argument>jetty.home=${assembly-directory}</argument>
<argument>jetty.base=${assembly-directory}</argument>
<argument>--add-to-start=server,deploy,websocket,ext,resources</argument>
<argument>--add-to-startd=jsp,http</argument>
<argument>--add-to-startd=jsp,jstl,http</argument>
</arguments>
</configuration>
<goals>
@ -542,7 +570,7 @@
<argument>jetty.home=${assembly-directory}</argument>
<argument>jetty.base=${assembly-directory}/demo-base</argument>
<argument>--add-to-start=server,continuation,deploy,ext,resources,client,annotations,jndi,servlets</argument>
<argument>--add-to-startd-ini=jsp,http,https</argument>
<argument>--add-to-startd-ini=jsp,jstl,http,https</argument>
</arguments>
</configuration>
<goals>
@ -667,6 +695,11 @@
<artifactId>jetty-monitor</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-quickstart</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-start</artifactId>
@ -697,6 +730,16 @@
<artifactId>jetty-jsp</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>org.eclipse.jetty</groupId>
<artifactId>apache-jsp</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>org.eclipse.jetty</groupId>
<artifactId>apache-jstl</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-plus</artifactId>
@ -765,6 +808,11 @@
<version>${project.version}</version>
<type>war</type>
</dependency>
<dependency>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-alpn-server</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>org.eclipse.jetty.example-async-rest</groupId>
<artifactId>example-async-rest-webapp</artifactId>

View File

@ -0,0 +1,20 @@
#
# Jetty JSP Module
#
[depend]
servlet
jsp-impl/${jsp-impl}-jsp
[ini-template]
# JSP Configuration
# Select JSP implementation, choices are
# glassfish : The reference implementation
# default in jetty <= 9.1
# apache : The apache version
# default jetty >= 9.2
jsp-impl=apache
# To use an non-jdk compiler for JSP compilation uncomment next line
# -Dorg.apache.jasper.compiler.disablejsr199=true

View File

@ -0,0 +1,14 @@
#
# Jetty JSP Module
#
[depend]
jsp
jsp-impl/${jsp-impl}-jstl
[ini-template]
# JSTL Configuration
# The glassfish jsp-impl includes JSTL by default and this module
# is not required to activate it.
# The apache jsp-impl does not include JSTL by default and this module
# is required to put JSTL on the container classpath

View File

@ -0,0 +1,15 @@
#
# Protocol Negotiatin Selection Module
#
[depend]
protonego-impl/${protonego}
[ini-template]
# Protocol Negotiation Implementation Selection
# choices are:
# 'npn' : original implementation for SPDY (now deprecated)
# 'alpn' : replacement for NPN, in use by current SPDY implementations
# and the future HTTP/2 spec
# Note: java 1.8+ are ALPN only.
protonego=alpn

View File

@ -132,7 +132,7 @@ public class HttpChannelOverFCGI extends HttpChannel
if (close)
connection.close();
else
connection.release();
connection.release(this);
}
protected void flush(Generator.Result... results)
@ -155,7 +155,7 @@ public class HttpChannelOverFCGI extends HttpChannel
protected void onIdleExpired(TimeoutException timeout)
{
LOG.debug("Idle timeout for request {}", request);
abort(timeout);
connection.abort(timeout);
}
@Override

View File

@ -20,6 +20,7 @@ package org.eclipse.jetty.fcgi.client.http;
import java.io.EOFException;
import java.nio.ByteBuffer;
import java.nio.channels.AsynchronousCloseException;
import java.util.LinkedList;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
@ -139,25 +140,19 @@ public class HttpConnectionOverFCGI extends AbstractConnection implements Connec
private void shutdown()
{
// First close then abort, to be sure that the
// connection cannot be reused from an onFailure()
// handler or by blocking code waiting for completion.
close();
for (HttpChannelOverFCGI channel : channels.values())
channel.abort(new EOFException());
close(new EOFException());
}
@Override
protected boolean onReadTimeout()
{
for (HttpChannelOverFCGI channel : channels.values())
channel.abort(new TimeoutException());
close();
close(new TimeoutException());
return false;
}
public void release()
protected void release(HttpChannelOverFCGI channel)
{
channels.remove(channel.getRequest());
if (destination instanceof PoolingHttpDestination)
{
@SuppressWarnings("unchecked")
@ -169,17 +164,37 @@ public class HttpConnectionOverFCGI extends AbstractConnection implements Connec
@Override
public void close()
{
close(new AsynchronousCloseException());
}
private void close(Throwable failure)
{
if (closed.compareAndSet(false, true))
{
// First close then abort, to be sure that the connection cannot be reused
// from an onFailure() handler or by blocking code waiting for completion.
getHttpDestination().close(this);
getEndPoint().shutdownOutput();
LOG.debug("{} oshut", this);
getEndPoint().close();
LOG.debug("{} closed", this);
abort(failure);
}
}
protected void abort(Throwable failure)
{
for (HttpChannelOverFCGI channel : channels.values())
{
HttpExchange exchange = channel.getHttpExchange();
if (exchange != null)
exchange.getRequest().abort(failure);
}
channels.clear();
}
private int acquireRequest()
{
synchronized (requests)
@ -304,7 +319,7 @@ public class HttpConnectionOverFCGI extends AbstractConnection implements Connec
@Override
public void onEnd(int request)
{
HttpChannelOverFCGI channel = channels.remove(request);
HttpChannelOverFCGI channel = channels.get(request);
if (channel != null)
{
channel.responseSuccess();

View File

@ -5,7 +5,7 @@
<parent>
<artifactId>fcgi-parent</artifactId>
<groupId>org.eclipse.jetty.fcgi</groupId>
<version>9.1.4-SNAPSHOT</version>
<version>9.2.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>

View File

@ -5,7 +5,7 @@
<parent>
<groupId>org.eclipse.jetty.fcgi</groupId>
<artifactId>fcgi-parent</artifactId>
<version>9.1.4-SNAPSHOT</version>
<version>9.2.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>

View File

@ -5,7 +5,7 @@
<parent>
<artifactId>fcgi-parent</artifactId>
<groupId>org.eclipse.jetty.fcgi</groupId>
<version>9.1.4-SNAPSHOT</version>
<version>9.2.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>

View File

@ -24,6 +24,7 @@ import java.net.URI;
import java.net.URLEncoder;
import java.nio.ByteBuffer;
import java.util.Arrays;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;
@ -37,6 +38,7 @@ import javax.servlet.http.HttpServletResponse;
import org.eclipse.jetty.client.api.ContentResponse;
import org.eclipse.jetty.client.api.Request;
import org.eclipse.jetty.client.api.Response;
import org.eclipse.jetty.client.api.Result;
import org.eclipse.jetty.client.util.BytesContentProvider;
import org.eclipse.jetty.http.HttpMethod;
import org.eclipse.jetty.server.handler.AbstractHandler;
@ -513,4 +515,40 @@ public class HttpClientTest extends AbstractHttpClientServerTest
Assert.assertEquals(200, response.getStatus());
Assert.assertEquals(length, response.getContent().length);
}
@Test
public void testLongPollIsAbortedWhenClientIsStopped() throws Exception
{
final CountDownLatch latch = new CountDownLatch(1);
start(new AbstractHandler()
{
@Override
public void handle(String target, org.eclipse.jetty.server.Request baseRequest, HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException
{
baseRequest.setHandled(true);
request.startAsync();
latch.countDown();
}
});
final CountDownLatch completeLatch = new CountDownLatch(1);
client.newRequest("localhost", connector.getLocalPort())
.scheme(scheme)
.send(new Response.CompleteListener()
{
@Override
public void onComplete(Result result)
{
if (result.isFailed())
completeLatch.countDown();
}
});
Assert.assertTrue(latch.await(5, TimeUnit.SECONDS));
// Stop the client, the complete listener must be invoked.
client.stop();
Assert.assertTrue(completeLatch.await(5, TimeUnit.SECONDS));
}
}

View File

@ -38,7 +38,8 @@ public enum HttpMethod
DELETE,
TRACE,
CONNECT,
MOVE;
MOVE,
PROXY;
/* ------------------------------------------------------------ */
/**
@ -48,7 +49,7 @@ public enum HttpMethod
* @param limit The first non valid index
* @return A HttpMethod if a match or null if no easy match.
*/
public static HttpMethod lookAheadGet(byte[] bytes, int position, int limit)
public static HttpMethod lookAheadGet(byte[] bytes, final int position, int limit)
{
int length=limit-position;
if (length<4)
@ -62,6 +63,8 @@ public enum HttpMethod
case 'P':
if (bytes[position+1]=='O' && bytes[position+2]=='S' && bytes[position+3]=='T' && length>=5 && bytes[position+4]==' ')
return POST;
if (bytes[position+1]=='R' && bytes[position+2]=='O' && bytes[position+3]=='X' && length>=6 && bytes[position+4]=='Y' && bytes[position+5]==' ')
return PROXY;
if (bytes[position+1]=='U' && bytes[position+2]=='T' && bytes[position+3]==' ')
return PUT;
break;

View File

@ -104,6 +104,7 @@ public class HttpParser
SPACE2,
REQUEST_VERSION,
REASON,
PROXY,
HEADER,
HEADER_IN_NAME,
HEADER_VALUE,
@ -403,7 +404,7 @@ public class HttpParser
* otherwise skip white space until something else to parse.
*/
private boolean quickStart(ByteBuffer buffer)
{
{
if (_requestHandler!=null)
{
_method = HttpMethod.lookAheadGet(buffer);
@ -411,6 +412,7 @@ public class HttpParser
{
_methodString = _method.asString();
buffer.position(buffer.position()+_methodString.length()+1);
setState(State.SPACE1);
return false;
}
@ -655,7 +657,29 @@ public class HttpParser
version=HttpVersion.lookAheadGet(buffer.array(),buffer.arrayOffset()+buffer.position()-1,buffer.arrayOffset()+buffer.limit());
else
version=HttpVersion.CACHE.getBest(buffer,0,buffer.remaining());
if (version!=null)
if (version==null)
{
if (_method==HttpMethod.PROXY)
{
if (!(_requestHandler instanceof ProxyHandler))
throw new BadMessage();
_uri.flip();
String protocol=BufferUtil.toString(_uri);
// This is the proxy protocol, so we can assume entire first line is in buffer else 400
buffer.position(buffer.position()-1);
String sAddr = getProxyField(buffer);
String dAddr = getProxyField(buffer);
int sPort = BufferUtil.takeInt(buffer);
next(buffer);
int dPort = BufferUtil.takeInt(buffer);
next(buffer);
_state=State.START;
((ProxyHandler)_requestHandler).proxied(protocol,sAddr,dAddr,sPort,dPort);
return false;
}
}
else
{
int pos = buffer.position()+version.asString().length()-1;
if (pos<buffer.limit())
@ -715,8 +739,7 @@ public class HttpParser
if (_connectionFields==null && _version.getVersion()>=HttpVersion.HTTP_1_1.getVersion())
{
int header_cache = _handler.getHeaderCacheSize();
if (header_cache>0)
_connectionFields=new ArrayTernaryTrie<>(header_cache);
_connectionFields=new ArrayTernaryTrie<>(header_cache);
}
setState(State.HEADER);
@ -1586,6 +1609,11 @@ public class HttpParser
public int getHeaderCacheSize();
}
public interface ProxyHandler
{
void proxied(String protocol, String sAddr, String dAddr, int sPort, int dPort);
}
public interface RequestHandler<T> extends HttpHandler<T>
{
/**
@ -1618,4 +1646,20 @@ public class HttpParser
{
return _connectionFields;
}
private String getProxyField(ByteBuffer buffer)
{
_string.setLength(0);
_length=0;
while (buffer.hasRemaining())
{
// process each character
byte ch=next(buffer);
if (ch<=' ')
return _string.toString();
_string.append((char)ch);
}
throw new BadMessage();
}
}

View File

@ -1398,6 +1398,63 @@ public class HttpParserTest
}
@Test
public void testProxyProtocol() throws Exception
{
ByteBuffer buffer=BufferUtil
.toBuffer("PROXY TCP4 107.47.45.254 10.0.1.116 27689 80\015\012"
+"GET / HTTP/1.1\015\012"
+"Host: localhost \015\012"
+"Connection: close\015\012"+"\015\012"+"\015\012");
Handler handler=new Handler();
HttpParser parser=new HttpParser((HttpParser.RequestHandler)handler);
parseAll(parser, buffer);
assertTrue(_headerCompleted);
assertTrue(_messageCompleted);
assertEquals("GET", _methodOrVersion);
assertEquals("/", _uriOrStatus);
assertEquals("HTTP/1.1", _versionOrReason);
assertEquals("PROXY TCP4 107.47.45.254 10.0.1.116 27689 80", handler._proxy);
assertEquals("Host", _hdr[0]);
assertEquals("localhost", _val[0]);
assertEquals("Connection", _hdr[1]);
assertEquals("close", _val[1]);
assertEquals(1, _headers);
}
@Test
public void testSplitProxyHeaderParseTest() throws Exception
{
Handler handler=new Handler();
HttpParser parser=new HttpParser((HttpParser.RequestHandler)handler);
ByteBuffer buffer=BufferUtil.toBuffer("PROXY TCP4 207.47.45.254 10.0.1.116 27689 80\015\012");
parser.parseNext(buffer);
buffer=BufferUtil.toBuffer(
"GET / HTTP/1.1\015\012"
+"Host: localhost \015\012"
+"Connection: close\015\012"
+"\015\012"
+"\015\012");
parser.parseNext(buffer);
assertTrue(_headerCompleted);
assertTrue(_messageCompleted);
assertEquals("GET", _methodOrVersion);
assertEquals("/", _uriOrStatus);
assertEquals("HTTP/1.1", _versionOrReason);
assertEquals("PROXY TCP4 207.47.45.254 10.0.1.116 27689 80", handler._proxy);
assertEquals("Host", _hdr[0]);
assertEquals("localhost", _val[0]);
assertEquals("Connection", _hdr[1]);
assertEquals("close", _val[1]);
assertEquals(1, _headers);
}
@Before
public void init()
{
@ -1429,9 +1486,10 @@ public class HttpParserTest
private boolean _headerCompleted;
private boolean _messageCompleted;
private class Handler implements HttpParser.RequestHandler<ByteBuffer>, HttpParser.ResponseHandler<ByteBuffer>
private class Handler implements HttpParser.RequestHandler<ByteBuffer>, HttpParser.ResponseHandler<ByteBuffer>, HttpParser.ProxyHandler
{
private HttpFields fields;
String _proxy;
@Override
public boolean content(ByteBuffer ref)
@ -1539,5 +1597,11 @@ public class HttpParserTest
{
return 512;
}
@Override
public void proxied(String protocol, String sAddr, String dAddr, int sPort, int dPort)
{
_proxy="PROXY "+protocol+" "+sAddr+" "+dAddr+" "+sPort+" "+dPort;
}
}
}

View File

@ -16,18 +16,13 @@
// ========================================================================
//
package org.eclipse.jetty.spdy.client;
package org.eclipse.jetty.io;
import java.io.IOException;
import java.util.Map;
import java.util.concurrent.Executor;
import javax.net.ssl.SSLEngine;
import org.eclipse.jetty.io.AbstractConnection;
import org.eclipse.jetty.io.ClientConnectionFactory;
import org.eclipse.jetty.io.Connection;
import org.eclipse.jetty.io.EndPoint;
import org.eclipse.jetty.io.RuntimeIOException;
import org.eclipse.jetty.util.BufferUtil;
import org.eclipse.jetty.util.log.Log;
import org.eclipse.jetty.util.log.Logger;

View File

@ -16,9 +16,8 @@
// ========================================================================
//
package org.eclipse.jetty.spdy.client;
package org.eclipse.jetty.io;
import org.eclipse.jetty.io.ClientConnectionFactory;
public abstract class NegotiatingClientConnectionFactory implements ClientConnectionFactory
{

View File

@ -2,6 +2,9 @@
# JMX Module
#
[depend]
server
[lib]
lib/jetty-jmx-${jetty.version}.jar

View File

@ -0,0 +1,8 @@
#
# Glassfish JSP Module
#
[name]
jsp-impl
[lib]
lib/jsp/*.jar

View File

@ -0,0 +1,6 @@
#
# Glassfish JSTL
[name]
jstl-impl
# This file is empty as glassfish jstl is provided by glassfish jsp

View File

@ -1,14 +0,0 @@
#
# Jetty JSP Module
#
[depend]
servlet
[lib]
lib/jsp/*.jar
[ini-template]
# JSP Configuration
# To use an non-jdk compiler for JSP compilation uncomment next line
# -Dorg.apache.jasper.compiler.disablejsr199=true

View File

@ -72,9 +72,19 @@
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.eclipse.jetty</groupId>
<artifactId>apache-jsp</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>org.apache.ant</groupId>
<artifactId>ant</artifactId>
<version>1.8.4</version>
</dependency>
<dependency>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-jsp</artifactId>
<artifactId>apache-jstl</artifactId>
<version>${project.version}</version>
</dependency>
</dependencies>

View File

@ -79,6 +79,7 @@ import org.eclipse.jetty.util.resource.Resource;
public class JspcMojo extends AbstractMojo
{
public static final String END_OF_WEBAPP = "</web-app>";
public static final String PRECOMPILED_FLAG = "org.eclipse.jetty.jsp.precompiled";
/**
@ -207,7 +208,7 @@ public class JspcMojo extends AbstractMojo
/**
* Patterns of jars on the system path that contain tlds. Use | to separate each pattern.
*
* @parameter default-value=".*taglibs[^/]*\.jar|.*jstl-impl[^/]*\.jar$
* @parameter default-value=".*taglibs[^/]*\.jar|.*jstl[^/]*\.jar$
*/
private String tldJarNamePatterns;
@ -294,9 +295,9 @@ public class JspcMojo extends AbstractMojo
jspc.setWebXmlFragment(webXmlFragment);
jspc.setUriroot(webAppSourceDirectory);
jspc.setOutputDir(generatedClasses);
jspc.setClassPath(webAppClassPath.toString());
jspc.setClassPath(sysClassPath+System.getProperty("path.separator")+webAppClassPath.toString());
jspc.setCompile(true);
jspc.setSystemClassPath(sysClassPath);
//jspc.setSystemClassPath(sysClassPath);
// JspC#setExtensions() does not exist, so
@ -419,6 +420,10 @@ public class JspcMojo extends AbstractMojo
mergedWebXmlWriter.println(line);
}
}
//put in a context init-param to flag that the contents have been precompiled
mergedWebXmlWriter.println("<context-param><param-name>"+PRECOMPILED_FLAG+"</param-name><param-value>true</param-value></context-param>");
// put in the generated fragment
try (BufferedReader fragmentWebXmlReader = new BufferedReader(
@ -541,13 +546,16 @@ public class JspcMojo extends AbstractMojo
*/
private List<URL> getSystemJarsWithTlds() throws Exception
{
getLog().debug("tld pattern=" + tldJarNamePatterns);
final List<URL> list = new ArrayList<URL>();
List<URI> artifactUris = new ArrayList<URI>();
Pattern pattern = Pattern.compile(tldJarNamePatterns);
for (Iterator<Artifact> iter = pluginArtifacts.iterator(); iter.hasNext(); )
{
Artifact pluginArtifact = iter.next();
artifactUris.add(Resource.newResource(pluginArtifact.getFile()).getURI());
Resource res = Resource.newResource(pluginArtifact.getFile());
getLog().debug("scan jar: "+res.getURI());
artifactUris.add(res.getURI());
}
PatternMatcher matcher = new PatternMatcher()

View File

@ -122,19 +122,19 @@
</dependency>
<dependency>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-jsp</artifactId>
<artifactId>apache-jsp</artifactId>
<version>${project.version}</version>
</dependency>
<!-- dependency>
<groupId>org.eclipse.jetty.orbit</groupId>
<artifactId>javax.activation</artifactId>
<scope>compile</scope>
</dependency -->
<dependency>
<groupId>javax.transaction</groupId>
<artifactId>javax.transaction-api</artifactId>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>org.eclipse.jetty</groupId>
<artifactId>apache-jstl</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>javax.transaction</groupId>
<artifactId>javax.transaction-api</artifactId>
<scope>compile</scope>
</dependency>
</dependencies>
<reporting>
<plugins>

View File

@ -62,7 +62,7 @@ public class JettyWebAppContext extends WebAppContext
{
private static final Logger LOG = Log.getLogger(JettyWebAppContext.class);
private static final String DEFAULT_CONTAINER_INCLUDE_JAR_PATTERN = ".*/javax.servlet-[^/]*\\.jar$|.*/servlet-api-[^/]*\\.jar$";
private static final String DEFAULT_CONTAINER_INCLUDE_JAR_PATTERN = ".*/javax.servlet-[^/]*\\.jar$|.*/servlet-api-[^/]*\\.jar$|.*javax.servlet.jsp.jstl-[^/]*\\.jar";
private static final String WEB_INF_CLASSES_PREFIX = "/WEB-INF/classes";
private static final String WEB_INF_LIB_PREFIX = "/WEB-INF/lib";

View File

@ -0,0 +1,47 @@
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
<parent>
<groupId>org.eclipse.jetty.osgi</groupId>
<artifactId>jetty-osgi-project</artifactId>
<version>9.2.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>jetty-osgi-alpn</artifactId>
<name>Jetty :: OSGi ALPN Fragment</name>
<packaging>jar</packaging>
<properties>
<bundle-symbolic-name>org.eclipse.jetty.osgi.alpn.fragment</bundle-symbolic-name>
</properties>
<build>
<plugins>
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>build-helper-maven-plugin</artifactId>
<version>1.7</version>
<executions>
<execution>
<id>parse-version</id>
<goals>
<goal>parse-version</goal>
</goals>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jar-plugin</artifactId>
<configuration>
<archive>
<manifestEntries>
<Bundle-ManifestVersion>2</Bundle-ManifestVersion>
<Bundle-SymbolicName>${bundle-symbolic-name};singleton:=true</Bundle-SymbolicName>
<Bundle-Name>Jetty OSGi ALPN Fragment</Bundle-Name>
<Bundle-Version>${parsedVersion.majorVersion}.${parsedVersion.minorVersion}.${parsedVersion.incrementalVersion}</Bundle-Version>
<Export-Package>org.eclipse.jetty.alpn;version="${parsedVersion.majorVersion}.${parsedVersion.minorVersion}.${parsedVersion.incrementalVersion}"</Export-Package>
<Fragment-Host>system.bundle;extension:=framework</Fragment-Host>
</manifestEntries>
</archive>
</configuration>
</plugin>
</plugins>
</build>
</project>

View File

@ -37,37 +37,81 @@ import org.osgi.framework.Bundle;
public class DefaultBundleClassLoaderHelper implements BundleClassLoaderHelper
{
private static final Logger LOG = Log.getLogger(BundleClassLoaderHelper.class);
private static enum OSGiContainerType {EquinoxOld, EquinoxLuna, FelixOld, Felix403};
private static OSGiContainerType osgiContainer;
private static Class Equinox_BundleHost_Class;
private static Class Equinox_EquinoxBundle_Class;
private static Class Felix_BundleImpl_Class;
private static Class Felix_BundleWiring_Class;
//old equinox
private static Method Equinox_BundleHost_getBundleLoader_method;
private static Method Equinox_BundleLoader_createClassLoader_method;
//new equinox
private static Method Equinox_EquinoxBundle_getModuleClassLoader_Method;
//new felix
private static Method Felix_BundleImpl_Adapt_Method;
//old felix
private static Field Felix_BundleImpl_m_Modules_Field;
private static Field Felix_ModuleImpl_m_ClassLoader_Field;
private static Method Felix_BundleWiring_getClassLoader_Method;
private static boolean identifiedOsgiImpl = false;
private static boolean isEquinox = false;
private static boolean isFelix = false;
private static void init(Bundle bundle)
private static void checkContainerType (Bundle bundle)
{
identifiedOsgiImpl = true;
if (osgiContainer != null)
return;
try
{
isEquinox = bundle.getClass().getClassLoader().loadClass("org.eclipse.osgi.framework.internal.core.BundleHost") != null;
Equinox_BundleHost_Class = bundle.getClass().getClassLoader().loadClass("org.eclipse.osgi.framework.internal.core.BundleHost");
osgiContainer = OSGiContainerType.EquinoxOld;
return;
}
catch (Throwable t)
catch (ClassNotFoundException e)
{
isEquinox = false;
LOG.ignore(e);
}
if (!isEquinox)
try
{
Equinox_EquinoxBundle_Class = bundle.getClass().getClassLoader().loadClass("org.eclipse.osgi.internal.framework.EquinoxBundle");
osgiContainer = OSGiContainerType.EquinoxLuna;
return;
}
catch (ClassNotFoundException e)
{
LOG.ignore(e);
}
try
{
//old felix or new felix?
Felix_BundleImpl_Class = bundle.getClass().getClassLoader().loadClass("org.apache.felix.framework.BundleImpl");
try
{
isFelix = bundle.getClass().getClassLoader().loadClass("org.apache.felix.framework.BundleImpl") != null;
Felix_BundleImpl_Adapt_Method = Felix_BundleImpl_Class.getDeclaredMethod("adapt", new Class[] {Class.class});
osgiContainer = OSGiContainerType.Felix403;
return;
}
catch (Throwable t2)
catch (NoSuchMethodException e)
{
isFelix = false;
osgiContainer = OSGiContainerType.FelixOld;
return;
}
}
catch (ClassNotFoundException e)
{
LOG.warn("Unknown OSGi container type");
return;
}
}
/**
* Assuming the bundle is started.
*
@ -77,7 +121,7 @@ public class DefaultBundleClassLoaderHelper implements BundleClassLoaderHelper
public ClassLoader getBundleClassLoader(Bundle bundle)
{
String bundleActivator = (String) bundle.getHeaders().get("Bundle-Activator");
if (bundleActivator == null)
{
bundleActivator = (String) bundle.getHeaders().get("Jetty-ClassInBundle");
@ -93,80 +137,135 @@ public class DefaultBundleClassLoaderHelper implements BundleClassLoaderHelper
LOG.warn(e);
}
}
// resort to introspection
if (!identifiedOsgiImpl)
// resort to introspection
return getBundleClassLoaderForContainer(bundle);
}
/**
* @param bundle
* @return
*/
private ClassLoader getBundleClassLoaderForContainer (Bundle bundle)
{
checkContainerType (bundle);
if (osgiContainer == null)
{
init(bundle);
}
if (isEquinox)
{
return internalGetEquinoxBundleClassLoader(bundle);
}
else if (isFelix)
{
return internalGetFelixBundleClassLoader(bundle);
LOG.warn("No classloader for unknown OSGi container type");
return null;
}
LOG.warn("No classloader found for bundle "+bundle.getSymbolicName());
return null;
switch (osgiContainer)
{
case EquinoxOld:
case EquinoxLuna:
{
return internalGetEquinoxBundleClassLoader(bundle);
}
case FelixOld:
case Felix403:
{
return internalGetFelixBundleClassLoader(bundle);
}
default:
{
LOG.warn("No classloader found for bundle "+bundle.getSymbolicName());
return null;
}
}
}
private static Method Equinox_BundleHost_getBundleLoader_method;
private static Method Equinox_BundleLoader_createClassLoader_method;
/**
* @param bundle
* @return
*/
private static ClassLoader internalGetEquinoxBundleClassLoader(Bundle bundle)
{
// assume equinox:
try
if (osgiContainer == OSGiContainerType.EquinoxOld)
{
if (Equinox_BundleHost_getBundleLoader_method == null)
try
{
Equinox_BundleHost_getBundleLoader_method =
bundle.getClass().getClassLoader().loadClass("org.eclipse.osgi.framework.internal.core.BundleHost").getDeclaredMethod("getBundleLoader", new Class[] {});
Equinox_BundleHost_getBundleLoader_method.setAccessible(true);
if (Equinox_BundleHost_getBundleLoader_method == null)
{
Equinox_BundleHost_getBundleLoader_method =
Equinox_BundleHost_Class.getDeclaredMethod("getBundleLoader", new Class[] {});
Equinox_BundleHost_getBundleLoader_method.setAccessible(true);
}
Object bundleLoader = Equinox_BundleHost_getBundleLoader_method.invoke(bundle, new Object[] {});
if (Equinox_BundleLoader_createClassLoader_method == null && bundleLoader != null)
{
Equinox_BundleLoader_createClassLoader_method =
bundleLoader.getClass().getClassLoader().loadClass("org.eclipse.osgi.internal.loader.BundleLoader").getDeclaredMethod("createClassLoader", new Class[] {});
Equinox_BundleLoader_createClassLoader_method.setAccessible(true);
}
return (ClassLoader) Equinox_BundleLoader_createClassLoader_method.invoke(bundleLoader, new Object[] {});
}
Object bundleLoader = Equinox_BundleHost_getBundleLoader_method.invoke(bundle, new Object[] {});
if (Equinox_BundleLoader_createClassLoader_method == null && bundleLoader != null)
catch (ClassNotFoundException t)
{
Equinox_BundleLoader_createClassLoader_method =
bundleLoader.getClass().getClassLoader().loadClass("org.eclipse.osgi.internal.loader.BundleLoader").getDeclaredMethod("createClassLoader", new Class[] {});
Equinox_BundleLoader_createClassLoader_method.setAccessible(true);
LOG.warn(t);
return null;
}
catch (Throwable t)
{
LOG.warn(t);
return null;
}
return (ClassLoader) Equinox_BundleLoader_createClassLoader_method.invoke(bundleLoader, new Object[] {});
}
catch (Throwable t)
if (osgiContainer == OSGiContainerType.EquinoxLuna)
{
LOG.warn(t);
try
{
if (Equinox_EquinoxBundle_getModuleClassLoader_Method == null)
Equinox_EquinoxBundle_getModuleClassLoader_Method = Equinox_EquinoxBundle_Class.getDeclaredMethod("getModuleClassLoader", new Class[] {Boolean.TYPE});
Equinox_EquinoxBundle_getModuleClassLoader_Method.setAccessible(true);
return (ClassLoader)Equinox_EquinoxBundle_getModuleClassLoader_Method.invoke(bundle, new Object[] {Boolean.FALSE});
}
catch (Exception e)
{
LOG.warn(e);
return null;
}
}
LOG.warn("No classloader for equinox platform for bundle "+bundle.getSymbolicName());
return null;
}
private static Field Felix_BundleImpl_m_modules_field;
private static Field Felix_ModuleImpl_m_classLoader_field;
private static Method Felix_adapt_method;
private static Method Felix_bundle_wiring_getClassLoader_method;
private static Class Felix_bundleWiringClazz;
private static Boolean isFelix403 = null;
/**
* @param bundle
* @return
*/
private static ClassLoader internalGetFelixBundleClassLoader(Bundle bundle)
{
//firstly, try to find classes matching a newer version of felix
initFelix403(bundle);
if (isFelix403.booleanValue())
if (osgiContainer == OSGiContainerType.Felix403)
{
try
{
Object wiring = Felix_adapt_method.invoke(bundle, new Object[] {Felix_bundleWiringClazz});
ClassLoader cl = (ClassLoader)Felix_bundle_wiring_getClassLoader_method.invoke(wiring);
return cl;
if (Felix_BundleWiring_Class == null)
Felix_BundleWiring_Class = bundle.getClass().getClassLoader().loadClass("org.osgi.framework.wiring.BundleWiring");
Felix_BundleImpl_Adapt_Method.setAccessible(true);
if (Felix_BundleWiring_getClassLoader_Method == null)
{
Felix_BundleWiring_getClassLoader_Method = Felix_BundleWiring_Class.getDeclaredMethod("getClassLoader");
Felix_BundleWiring_getClassLoader_Method.setAccessible(true);
}
Object wiring = Felix_BundleImpl_Adapt_Method.invoke(bundle, new Object[] {Felix_BundleWiring_Class});
return (ClassLoader)Felix_BundleWiring_getClassLoader_Method.invoke(wiring);
}
catch (Exception e)
{
@ -176,123 +275,92 @@ public class DefaultBundleClassLoaderHelper implements BundleClassLoaderHelper
}
// Fallback to trying earlier versions of felix.
if (Felix_BundleImpl_m_modules_field == null)
{
if (osgiContainer == OSGiContainerType.FelixOld)
{
try
{
Class bundleImplClazz = bundle.getClass().getClassLoader().loadClass("org.apache.felix.framework.BundleImpl");
Felix_BundleImpl_m_modules_field = bundleImplClazz.getDeclaredField("m_modules");
Felix_BundleImpl_m_modules_field.setAccessible(true);
}
catch (ClassNotFoundException e)
{
LOG.warn(e);
}
catch (NoSuchFieldException e)
{
LOG.warn(e);
}
}
if (Felix_BundleImpl_m_Modules_Field == null)
{
Felix_BundleImpl_m_Modules_Field = Felix_BundleImpl_Class.getDeclaredField("m_modules");
Felix_BundleImpl_m_Modules_Field.setAccessible(true);
}
// Figure out which version of the modules is exported
Object currentModuleImpl;
try
{
Object[] moduleArray = (Object[]) Felix_BundleImpl_m_modules_field.get(bundle);
currentModuleImpl = moduleArray[moduleArray.length - 1];
}
catch (Throwable t2)
{
try
{
List<Object> moduleArray = (List<Object>) Felix_BundleImpl_m_modules_field.get(bundle);
currentModuleImpl = moduleArray.get(moduleArray.size() - 1);
}
// Figure out which version of the modules is exported
Object currentModuleImpl;
try
{
Object[] moduleArray = (Object[]) Felix_BundleImpl_m_Modules_Field.get(bundle);
currentModuleImpl = moduleArray[moduleArray.length - 1];
}
catch (Throwable t2)
{
try
{
List<Object> moduleArray = (List<Object>) Felix_BundleImpl_m_Modules_Field.get(bundle);
currentModuleImpl = moduleArray.get(moduleArray.size() - 1);
}
catch (Exception e)
{
LOG.warn(e);
return null;
}
}
if (Felix_ModuleImpl_m_ClassLoader_Field == null && currentModuleImpl != null)
{
try
{
Felix_ModuleImpl_m_ClassLoader_Field = bundle.getClass().getClassLoader().loadClass("org.apache.felix.framework.ModuleImpl").getDeclaredField("m_classLoader");
Felix_ModuleImpl_m_ClassLoader_Field.setAccessible(true);
}
catch (Exception e)
{
LOG.warn(e);
return null;
}
}
// first make sure that the classloader is ready:
// the m_classLoader field must be initialized by the
// ModuleImpl.getClassLoader() private method.
ClassLoader cl = null;
try
{
cl = (ClassLoader) Felix_ModuleImpl_m_ClassLoader_Field.get(currentModuleImpl);
if (cl != null)
return cl;
}
catch (Exception e)
{
LOG.warn(e);
return null;
}
// looks like it was not ready:
// the m_classLoader field must be initialized by the
// ModuleImpl.getClassLoader() private method.
// this call will do that.
try
{
bundle.loadClass("java.lang.Object");
cl = (ClassLoader) Felix_ModuleImpl_m_ClassLoader_Field.get(currentModuleImpl);
return cl;
}
catch (Exception e)
{
LOG.warn(e);
return null;
}
}
catch (Exception e)
{
LOG.warn(e);
return null;
}
}
if (Felix_ModuleImpl_m_classLoader_field == null && currentModuleImpl != null)
{
try
{
Felix_ModuleImpl_m_classLoader_field = bundle.getClass().getClassLoader().loadClass("org.apache.felix.framework.ModuleImpl").getDeclaredField("m_classLoader");
Felix_ModuleImpl_m_classLoader_field.setAccessible(true);
}
catch (ClassNotFoundException e)
{
LOG.warn(e);
return null;
}
catch (NoSuchFieldException e)
{
LOG.warn(e);
return null;
}
}
// first make sure that the classloader is ready:
// the m_classLoader field must be initialized by the
// ModuleImpl.getClassLoader() private method.
ClassLoader cl = null;
try
{
cl = (ClassLoader) Felix_ModuleImpl_m_classLoader_field.get(currentModuleImpl);
if (cl != null)
return cl;
}
catch (Exception e)
{
LOG.warn(e);
return null;
}
// looks like it was not ready:
// the m_classLoader field must be initialized by the
// ModuleImpl.getClassLoader() private method.
// this call will do that.
try
{
bundle.loadClass("java.lang.Object");
cl = (ClassLoader) Felix_ModuleImpl_m_classLoader_field.get(currentModuleImpl);
return cl;
}
catch (Exception e)
{
LOG.warn(e);
return null;
}
}
private static void initFelix403 (Bundle bundle)
{
//see if the version of Felix is a new one
if (isFelix403 == null)
{
try
{
Class bundleImplClazz = bundle.getClass().getClassLoader().loadClass("org.apache.felix.framework.BundleImpl");
Felix_bundleWiringClazz = bundle.getClass().getClassLoader().loadClass("org.osgi.framework.wiring.BundleWiring");
Felix_adapt_method = bundleImplClazz.getDeclaredMethod("adapt", new Class[] {Class.class});
Felix_adapt_method.setAccessible(true);
Felix_bundle_wiring_getClassLoader_method = Felix_bundleWiringClazz.getDeclaredMethod("getClassLoader");
Felix_bundle_wiring_getClassLoader_method.setAccessible(true);
isFelix403 = Boolean.TRUE;
}
catch (ClassNotFoundException e)
{
LOG.warn("Felix 4.x classes not found in environment");
isFelix403 = Boolean.FALSE;
}
catch (NoSuchMethodException e)
{
LOG.warn("Felix 4.x classes not found in environment");
isFelix403 = Boolean.FALSE;
}
}
LOG.warn("No classloader for felix platform for bundle "+bundle.getSymbolicName());
return null;
}
}

View File

@ -63,7 +63,25 @@ public class DefaultFileLocatorHelper implements BundleFileLocatorHelper
// DirZipBundleEntry
private static Field ZIP_FILE_FILED_FOR_ZIP_BUNDLE_FILE = null;// ZipFile
private static final String[] FILE_BUNDLE_ENTRY_CLASSES = {"org.eclipse.osgi.baseadaptor.bundlefile.FileBundleEntry","org.eclipse.osgi.storage.bundlefile.FileBundleEntry"};
private static final String[] ZIP_BUNDLE_ENTRY_CLASSES = {"org.eclipse.osgi.baseadaptor.bundlefile.ZipBundleEntry","org.eclipse.osgi.storage.bundlefile.ZipBundleEntry"};
private static final String[] DIR_ZIP_BUNDLE_ENTRY_CLASSES = {"org.eclipse.osgi.baseadaptor.bundlefile.DirZipBundleEntry","org.eclipse.osgi.storage.bundlefile.DirZipBundleEntry"};
private static final String[] BUNDLE_URL_CONNECTION_CLASSES = {"org.eclipse.osgi.framework.internal.core.BundleURLConnection", "org.eclipse.osgi.storage.url.BundleURLConnection"};
public static boolean match (String name, String... names)
{
if (name == null || names == null)
return false;
boolean matched = false;
for (int i=0; i< names.length && !matched; i++)
if (name.equals(names[i]))
matched = true;
return matched;
}
/**
* Works with equinox, felix, nuxeo and probably more. Not exactly in the
* spirit of OSGi but quite necessary to support self-contained webapps and
@ -107,7 +125,8 @@ public class DefaultFileLocatorHelper implements BundleFileLocatorHelper
BUNDLE_ENTRY_FIELD.setAccessible(true);
}
Object bundleEntry = BUNDLE_ENTRY_FIELD.get(con);
if (bundleEntry.getClass().getName().equals("org.eclipse.osgi.baseadaptor.bundlefile.FileBundleEntry"))
if (match(bundleEntry.getClass().getName(), FILE_BUNDLE_ENTRY_CLASSES))
{
if (FILE_FIELD == null)
{
@ -117,7 +136,7 @@ public class DefaultFileLocatorHelper implements BundleFileLocatorHelper
File f = (File) FILE_FIELD.get(bundleEntry);
return f.getParentFile().getParentFile();
}
else if (bundleEntry.getClass().getName().equals("org.eclipse.osgi.baseadaptor.bundlefile.ZipBundleEntry"))
else if (match(bundleEntry.getClass().getName(), ZIP_BUNDLE_ENTRY_CLASSES))
{
url = bundle.getEntry("/");
@ -144,7 +163,7 @@ public class DefaultFileLocatorHelper implements BundleFileLocatorHelper
ZipFile zipFile = (ZipFile) ZIP_FILE_FILED_FOR_ZIP_BUNDLE_FILE.get(zipBundleFile);
return new File(zipFile.getName());
}
else if (bundleEntry.getClass().getName().equals("org.eclipse.osgi.baseadaptor.bundlefile.DirZipBundleEntry"))
else if (match (bundleEntry.getClass().getName(), DIR_ZIP_BUNDLE_ENTRY_CLASSES))
{
// that will not happen as we did ask for the manifest not a
// directory.
@ -309,7 +328,7 @@ public class DefaultFileLocatorHelper implements BundleFileLocatorHelper
URLConnection conn = url.openConnection();
conn.setDefaultUseCaches(Resource.getDefaultUseCaches());
if (BUNDLE_URL_CONNECTION_getLocalURL == null && conn.getClass().getName().equals("org.eclipse.osgi.framework.internal.core.BundleURLConnection"))
if (BUNDLE_URL_CONNECTION_getLocalURL == null && match(conn.getClass().getName(), BUNDLE_URL_CONNECTION_CLASSES))
{
BUNDLE_URL_CONNECTION_getLocalURL = conn.getClass().getMethod("getLocalURL", null);
BUNDLE_URL_CONNECTION_getLocalURL.setAccessible(true);
@ -340,7 +359,9 @@ public class DefaultFileLocatorHelper implements BundleFileLocatorHelper
URLConnection conn = url.openConnection();
conn.setDefaultUseCaches(Resource.getDefaultUseCaches());
if (BUNDLE_URL_CONNECTION_getFileURL == null && conn.getClass().getName().equals("org.eclipse.osgi.framework.internal.core.BundleURLConnection"))
if (BUNDLE_URL_CONNECTION_getFileURL == null
&&
match (conn.getClass().getName(), BUNDLE_URL_CONNECTION_CLASSES))
{
BUNDLE_URL_CONNECTION_getFileURL = conn.getClass().getMethod("getFileURL", null);
BUNDLE_URL_CONNECTION_getFileURL.setAccessible(true);

View File

@ -22,12 +22,23 @@
<module>jetty-osgi-boot</module>
<module>jetty-osgi-boot-jsp</module>
<module>jetty-osgi-boot-warurl</module>
<module>jetty-osgi-npn</module>
<module>jetty-osgi-httpservice</module>
<module>test-jetty-osgi-webapp</module>
<module>test-jetty-osgi-context</module>
<module>test-jetty-osgi</module>
<module>jetty-osgi-alpn</module>
</modules>
<profiles>
<profile>
<id>npn</id>
<activation>
<jdk>1.7</jdk>
</activation>
<modules>
<module>jetty-osgi-npn</module>
</modules>
</profile>
</profiles>
<build>
<resources>
<resource>

View File

@ -87,7 +87,7 @@
</dependency-->
<!-- container is not bad but not enough config parameters yet
can't pass the VMOption for npn-boot
can't pass the VMOption for alpn-boot
<dependency>
<groupId>org.ops4j.pax.exam</groupId>
<artifactId>pax-exam-container-forked</artifactId>
@ -192,11 +192,43 @@
<version>${project.version}</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.ow2.asm</groupId>
<artifactId>asm</artifactId>
<version>4.1</version>
</dependency>
<dependency>
<groupId>org.ow2.asm</groupId>
<artifactId>asm-commons</artifactId>
<version>4.1</version>
</dependency>
<dependency>
<groupId>org.ow2.asm</groupId>
<artifactId>asm-tree</artifactId>
<version>4.1</version>
</dependency>
<!-- Jetty Deps -->
<dependency>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-annotations</artifactId>
<scope>runtime</scope>
<exclusions>
<exclusion>
<groupId>org.ow2.asm</groupId>
<artifactId>asm</artifactId>
</exclusion>
<exclusion>
<groupId>org.ow2.asm</groupId>
<artifactId>asm-commons</artifactId>
</exclusion>
<exclusion>
<groupId>org.ow2.asm</groupId>
<artifactId>asm-tree</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.eclipse.jetty</groupId>
@ -324,14 +356,20 @@
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.mortbay.jetty.npn</groupId>
<artifactId>npn-boot</artifactId>
<version>${npn.version}</version>
<groupId>org.mortbay.jetty.alpn</groupId>
<artifactId>alpn-boot</artifactId>
<version>${alpn.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.eclipse.jetty.osgi</groupId>
<artifactId>jetty-osgi-npn</artifactId>
<artifactId>jetty-osgi-alpn</artifactId>
<version>${project.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-alpn-server</artifactId>
<version>${project.version}</version>
<scope>test</scope>
</dependency>
@ -402,9 +440,8 @@
<artifactId>maven-surefire-plugin</artifactId>
<configuration>
<!-- No point defining -Xbootclasspath as the actual OSGi VM is run as a forked process by pax-exam -->
<!--argLine>-Xbootclasspath/p:${settings.localRepository}/org/mortbay/jetty/npn/npn-boot/${npn.version}/npn-boot-${npn.version}.jar</argLine-->
<!-- But we do pass the sys property of the npn-boot jar -->
<argLine>-Dmortbay-npn-boot=${settings.localRepository}/org/mortbay/jetty/npn/npn-boot/${npn.version}/npn-boot-${npn.version}.jar</argLine>
<!-- But we do pass the sys property of the alpn-boot jar so that it can be configued inside tests -->
<argLine>-Dmortbay-alpn-boot=${settings.localRepository}/org/mortbay/jetty/alpn/alpn-boot/${alpn.version}/alpn-boot-${alpn.version}.jar</argLine>
</configuration>
</plugin>
<plugin>

View File

@ -4,7 +4,7 @@
<Configure id="Server" class="org.eclipse.jetty.server.Server">
<!-- =========================================================== -->
<!-- HttpChannel Configuration -->
<!-- Add HTTP Customizer for Secure request -->
<!-- =========================================================== -->
<New id="httpConfig" class="org.eclipse.jetty.server.HttpConfiguration">
<Set name="secureScheme">https</Set>
@ -16,7 +16,7 @@
<Set name="responseHeaderSize">8192</Set>
<Call name="addCustomizer">
<Arg>
<New class="org.eclipse.jetty.server.ForwardedRequestCustomizer"/>
<New class="org.eclipse.jetty.server.SecureRequestCustomizer"/>
</Arg>
</Call>
</New>
@ -35,53 +35,6 @@
<Set name="TrustStorePassword">OBF:1vny1zlo1x8e1vnw1vn61x8g1zlu1vn4</Set>
</New>
<!-- =========================================================== -->
<!-- Add HTTP Customizer for Secure request -->
<!-- =========================================================== -->
<Ref refid="httpConfig">
<Call name="addCustomizer">
<Arg>
<New class="org.eclipse.jetty.server.SecureRequestCustomizer"/>
</Arg>
</Call>
</Ref>
<!-- =========================================================== -->
<!-- Create a push strategy which can be used by reference by -->
<!-- individual connection factories below. -->
<!-- -->
<!-- Consult the javadoc of o.e.j.spdy.server.http.ReferrerPushStrategy -->
<!-- for all configuration that may be set here. -->
<!-- =========================================================== -->
<New id="pushStrategy" class="org.eclipse.jetty.spdy.server.http.ReferrerPushStrategy">
<!-- Uncomment to blacklist browsers for this push strategy. If one of the blacklisted Strings occurs in the
user-agent header sent by the client, push will be disabled for this browser. This is case insensitive" -->
<!--
<Set name="UserAgentBlacklist">
<Array type="String">
<Item>.*(?i)firefox/14.*</Item>
<Item>.*(?i)firefox/15.*</Item>
<Item>.*(?i)firefox/16.*</Item>
</Array>
</Set>
-->
<!-- Uncomment to override default file extensions to push -->
<!--
<Set name="PushRegexps">
<Array type="String">
<Item>.*\.css</Item>
<Item>.*\.js</Item>
<Item>.*\.png</Item>
<Item>.*\.jpg</Item>
<Item>.*\.gif</Item>
</Array>
</Set>
-->
<Set name="referrerPushPeriod">5000</Set>
<Set name="maxAssociatedResources">32</Set>
</New>
<!-- =========================================================== -->
<!-- Set connectors -->
<!-- =========================================================== -->
@ -95,7 +48,7 @@
<Array type="org.eclipse.jetty.server.ConnectionFactory">
<Item>
<New class="org.eclipse.jetty.server.SslConnectionFactory">
<Arg name="next">npn</Arg>
<Arg name="next">alpn</Arg>
<Arg name="sslContextFactory">
<Ref refid="sslContextFactory"/>
</Arg>
@ -103,7 +56,7 @@
</Item>
<Item>
<New class="org.eclipse.jetty.spdy.server.NPNServerConnectionFactory">
<New class="org.eclipse.jetty.alpn.server.ALPNServerConnectionFactory">
<Arg name="protocols">
<Array type="String">
<Item>spdy/3</Item>
@ -124,8 +77,6 @@
<!-- Set the initial window size for this SPDY connector. -->
<!-- See: http://www.chromium.org/spdy/spdy-protocol/spdy-protocol-draft3#TOC-2.6.8-WINDOW_UPDATE -->
<Set name="initialWindowSize">65536</Set>
<!-- Uncomment to enable the push strategy with id "pushStrategy" -->
<!-- <Arg name="pushStrategy"><Ref refid="pushStrategy"/></Arg> -->
</New>
</Item>

View File

@ -31,12 +31,14 @@ import java.util.List;
import javax.inject.Inject;
import org.junit.Assert;
import org.junit.Ignore;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.ops4j.pax.exam.CoreOptions;
import org.ops4j.pax.exam.Option;
import org.ops4j.pax.exam.junit.Configuration;
import org.ops4j.pax.exam.junit.JUnit4TestRunner;
import org.osgi.framework.Bundle;
import org.osgi.framework.BundleContext;
/**
@ -64,9 +66,9 @@ public class TestJettyOSGiBootSpdy
options.addAll(TestJettyOSGiBootWithJsp.configureJettyHomeAndPort("jetty-spdy.xml"));
options.addAll(TestJettyOSGiBootCore.coreJettyDependencies());
options.addAll(spdyJettyDependencies());
options.add(CoreOptions.junitBundles());
options.addAll(TestJettyOSGiBootCore.httpServiceJetty());
options.addAll(spdyJettyDependencies());
String logLevel = "WARN";
@ -90,37 +92,42 @@ public class TestJettyOSGiBootSpdy
{
List<Option> res = new ArrayList<Option>();
res.add(CoreOptions.systemProperty(JETTY_SPDY_PORT).value(String.valueOf(DEFAULT_JETTY_SPDY_PORT)));
// java
// -Xbootclasspath/p:${settings.localRepository}/org/mortbay/jetty/npn/npn-boot/${npn-version}/npn-boot-${npn-version}.jar
// res.add(CoreOptions.vmOptions("-Xbootclasspath/p:"+System.getenv("HOME")+"/.m2/repository/org/mortbay/jetty/npn/npn-boot/"+npnBootVersion+"/npn-boot-"+npnBootVersion+".jar"));
String npnBoot = System.getProperty("mortbay-npn-boot");
if (npnBoot == null) { throw new IllegalStateException("Define path to npn boot jar as system property -Dmortbay-npn-boot"); }
File checkNpnBoot = new File(npnBoot);
if (!checkNpnBoot.exists()) { throw new IllegalStateException("Unable to find the npn boot jar here: " + npnBoot); }
res.add(CoreOptions.vmOptions("-Xbootclasspath/p:" + npnBoot));
// res.add(CoreOptions.bootDelegationPackages("org.eclipse.jetty.npn"));
String alpnBoot = System.getProperty("mortbay-alpn-boot");
if (alpnBoot == null) { throw new IllegalStateException("Define path to alpn boot jar as system property -Dmortbay-alpn-boot"); }
File checkALPNBoot = new File(alpnBoot);
if (!checkALPNBoot.exists()) { throw new IllegalStateException("Unable to find the alpn boot jar here: " + alpnBoot); }
res.add(mavenBundle().groupId("org.eclipse.jetty.osgi").artifactId("jetty-osgi-npn").versionAsInProject().noStart());
res.add(CoreOptions.vmOptions("-Xbootclasspath/p:" + alpnBoot));
res.add(mavenBundle().groupId("org.eclipse.jetty.osgi").artifactId("jetty-osgi-alpn").versionAsInProject().start());
res.add(mavenBundle().groupId("org.eclipse.jetty").artifactId("jetty-alpn-server").versionAsInProject().start());
res.add(mavenBundle().groupId("org.eclipse.jetty.spdy").artifactId("spdy-client").versionAsInProject().noStart());
res.add(mavenBundle().groupId("org.eclipse.jetty.spdy").artifactId("spdy-core").versionAsInProject().noStart());
res.add(mavenBundle().groupId("org.eclipse.jetty.spdy").artifactId("spdy-server").versionAsInProject().noStart());
res.add(mavenBundle().groupId("org.eclipse.jetty.spdy").artifactId("spdy-http-common").versionAsInProject().noStart());
res.add(mavenBundle().groupId("org.eclipse.jetty.spdy").artifactId("spdy-http-server").versionAsInProject().noStart());
res.add(mavenBundle().groupId("org.eclipse.jetty.spdy").artifactId("spdy-client").versionAsInProject().noStart());
return res;
}
@Ignore
@Test
public void checkNpnBootOnBootstrapClasspath() throws Exception
public void checkALPNBootOnBootstrapClasspath() throws Exception
{
Class<?> npn = Thread.currentThread().getContextClassLoader().loadClass("org.eclipse.jetty.npn.NextProtoNego");
Assert.assertNotNull(npn);
Assert.assertNull(npn.getClassLoader());
Class<?> alpn = Thread.currentThread().getContextClassLoader().loadClass("org.eclipse.jetty.alpn.ALPN");
Assert.assertNotNull(alpn);
Assert.assertNull(alpn.getClassLoader());
}
@Test
public void assertAllBundlesActiveOrResolved()
{
Bundle b = TestOSGiUtil.getBundle(bundleContext, "org.eclipse.jetty.spdy.client");
TestOSGiUtil.diagnoseNonActiveOrNonResolvedBundle(b);
b = TestOSGiUtil.getBundle(bundleContext, "org.eclipse.jetty.osgi.boot");
TestOSGiUtil.diagnoseNonActiveOrNonResolvedBundle(b);
TestOSGiUtil.assertAllBundlesActiveOrResolved(bundleContext);
}

View File

@ -0,0 +1,6 @@
mvn exec:java -Dexec.classpathScope=test -Dexec.mainClass="org.eclipse.jetty.quickstart.StartBenchmarkWar"
OR
mvn exec:java -Dexec.classpathScope=test -Dexec.mainClass="org.eclipse.jetty.quickstart.PreconfigureBenchmarkWar"
mvn exec:java -Dexec.classpathScope=test -Dexec.mainClass="org.eclipse.jetty.quickstart.QuickStartBenchmarkWar"

170
jetty-quickstart/pom.xml Normal file
View File

@ -0,0 +1,170 @@
<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.2.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-quickstart</artifactId>
<name>Example :: Jetty Quick Start</name>
<description>Jetty Quick Start</description>
<url>http://www.eclipse.org/jetty</url>
<dependencies>
<dependency>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-webapp</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-jmx</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-annotations</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>javax.transaction</groupId>
<artifactId>javax.transaction-api</artifactId>
<version>1.2</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>org.eclipse.jetty.tests</groupId>
<artifactId>test-mock-resources</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>org.eclipse.jetty.orbit</groupId>
<artifactId>javax.mail.glassfish</artifactId>
<version>1.4.1.v201005082020</version>
</dependency>
<dependency>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-servlets</artifactId>
<version>${project.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.eclipse.jetty.websocket</groupId>
<artifactId>javax-websocket-server-impl</artifactId>
<version>${project.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.eclipse.jetty.websocket</groupId>
<artifactId>websocket-server</artifactId>
<version>${project.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.eclipse.jetty</groupId>
<artifactId>apache-jsp</artifactId>
<version>${project.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.eclipse.jetty</groupId>
<artifactId>apache-jstl</artifactId>
<version>${project.version}</version>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>appassembler-maven-plugin</artifactId>
<version>1.7</version>
<configuration>
<platforms>
<platform>unix</platform>
</platforms>
<programs>
<program>
<id>preconfigure</id>
<mainClass>org.eclipse.jetty.quickstart.PreconfigureQuickStartWar</mainClass>
</program>
<program>
<mainClass>org.eclipse.jetty.quickstart.QuickStartWar</mainClass>
<id>quickstart</id>
</program>
</programs>
</configuration>
</plugin>
<plugin>
<artifactId>maven-dependency-plugin</artifactId>
<executions>
<execution>
<id>copy</id>
<phase>generate-resources</phase>
<goals>
<goal>copy</goal>
</goals>
<configuration>
<artifactItems>
<artifactItem>
<groupId>org.eclipse.jetty.tests</groupId>
<artifactId>test-jndi-webapp</artifactId>
<version>${project.version}</version>
<type>war</type>
<overWrite>true</overWrite>
<includes>**</includes>
<outputDirectory>${basedir}/target</outputDirectory>
<destFileName>test-jndi.war</destFileName>
</artifactItem>
<artifactItem>
<groupId>org.eclipse.jetty.tests</groupId>
<artifactId>test-spec-webapp</artifactId>
<version>${project.version}</version>
<type>war</type>
<overWrite>true</overWrite>
<includes>**</includes>
<outputDirectory>${basedir}/target</outputDirectory>
<destFileName>test-spec.war</destFileName>
</artifactItem>
<artifactItem>
<groupId>org.eclipse.jetty</groupId>
<artifactId>test-jetty-webapp</artifactId>
<version>${project.version}</version>
<type>war</type>
<overWrite>true</overWrite>
<includes>**</includes>
<outputDirectory>${basedir}/target</outputDirectory>
<destFileName>test-standard.war</destFileName>
</artifactItem>
</artifactItems>
</configuration>
</execution>
</executions>
</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>
</plugins>
</build>
</project>

View File

@ -0,0 +1,21 @@
<?xml version="1.0" encoding="ISO-8859-1"?>
<!DOCTYPE Configure PUBLIC "-//Jetty//Configure//EN" "http://www.eclipse.org/jetty/configure_9_0.dtd">
<!-- An example context XML for a quickstart webapp
A quick started webapp has all the jar scanning and fragment resolution done in a
Preconfigure phase, with all the discovered configuration encoded into a
WEB-INF/quickstart-web.xml file.
This allows very rapid and precise starting of a webapp, without the risk of accidental
deployment of other discovered resources. This is above and beyond what is available
with web.xml meta-data-complete, as it also prevents scanning for ServletContainer
initialisers and any annotations/classes they require.
If autoPreconfigure is set to true, then the webapp will be preconfigured the first
time it is run.
-->
<Configure class="org.eclipse.jetty.quickstart.QuickStartWebApp">
<Set name="autoPreconfigure">true</Set>
<Set name="contextPath">/</Set>
<Set name="war"><Property name="jetty.webapps" default="."/>/application.war</Set>
</Configure>

View File

@ -0,0 +1,12 @@
#
# Jetty Quickstart module
#
[depend]
server
plus
annotations
[lib]
lib/jetty-quickstart-${jetty.version}.jar

View File

@ -0,0 +1,88 @@
//
// ========================================================================
// Copyright (c) 1995-2014 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.quickstart;
import org.eclipse.jetty.util.log.Log;
import org.eclipse.jetty.util.log.Logger;
import org.eclipse.jetty.webapp.Descriptor;
import org.eclipse.jetty.webapp.IterativeDescriptorProcessor;
import org.eclipse.jetty.webapp.WebAppContext;
import org.eclipse.jetty.xml.XmlParser;
/**
* Preconfigure DescriptorProcessor
*
* Saves literal XML snippets
*
*/
public class PreconfigureDescriptorProcessor extends IterativeDescriptorProcessor
{
private static final Logger LOG = Log.getLogger(PreconfigureDescriptorProcessor.class);
private final StringBuilder _buffer = new StringBuilder();
private final boolean _showOrigin;
private String _origin;
public PreconfigureDescriptorProcessor ()
{
_showOrigin=LOG.isDebugEnabled();
try
{
registerVisitor("env-entry", getClass().getDeclaredMethod("saveSnippet", __signature));
registerVisitor("resource-ref", getClass().getDeclaredMethod("saveSnippet", __signature));
registerVisitor("resource-env-ref", getClass().getDeclaredMethod("saveSnippet", __signature));
registerVisitor("message-destination-ref", getClass().getDeclaredMethod("saveSnippet", __signature));
registerVisitor("data-source", getClass().getDeclaredMethod("saveSnippet", __signature));
}
catch (Exception e)
{
throw new IllegalStateException(e);
}
}
@Override
public void start(WebAppContext context, Descriptor descriptor)
{
LOG.debug("process {}",descriptor);
_origin=(" <!-- "+descriptor+" -->\n");
}
@Override
public void end(WebAppContext context,Descriptor descriptor)
{
}
public void saveSnippet (WebAppContext context, Descriptor descriptor, XmlParser.Node node)
throws Exception
{
LOG.debug("save {}",node.getTag());
if (_showOrigin)
_buffer.append(_origin);
_buffer.append(" ").append(node.toString()).append("\n");
}
public String getXML()
{
return _buffer.toString();
}
}

View File

@ -0,0 +1,129 @@
//
// ========================================================================
// Copyright (c) 1995-2014 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.quickstart;
import org.eclipse.jetty.server.Server;
import org.eclipse.jetty.util.log.Log;
import org.eclipse.jetty.util.log.Logger;
import org.eclipse.jetty.util.resource.JarResource;
import org.eclipse.jetty.util.resource.Resource;
import org.eclipse.jetty.xml.XmlConfiguration;
public class PreconfigureQuickStartWar
{
private static final Logger LOG = Log.getLogger(PreconfigureQuickStartWar.class);
static final boolean ORIGIN=LOG.isDebugEnabled();
public static void main(String... args) throws Exception
{
Resource war = null;
Resource dir = null;
Resource xml = null;
switch (args.length)
{
case 0:
error("No WAR file or directory given");
break;
case 1:
dir = Resource.newResource(args[0]);
case 2:
war = Resource.newResource(args[0]);
if (war.isDirectory())
{
dir = war;
war = null;
xml = Resource.newResource(args[1]);
}
else
{
dir = Resource.newResource(args[1]);
}
break;
case 3:
war = Resource.newResource(args[0]);
dir = Resource.newResource(args[1]);
xml = Resource.newResource(args[2]);
break;
default:
error("Too many args");
break;
}
preconfigure(war,dir,xml);
}
/**
* @param war The war (or directory) to preconfigure
* @param dir The directory to expand the war into (or null if war is a directory)
* @param xml A context XML to apply (or null if none)
* @throws Exception
*/
public static void preconfigure(Resource war, Resource dir, Resource xml) throws Exception
{
// Do we need to unpack a war?
if (war != null)
{
if (war.isDirectory())
error("war file is directory");
if (!dir.exists())
dir.getFile().mkdirs();
JarResource.newJarResource(war).copyTo(dir.getFile());
}
final Server server = new Server();
QuickStartWebApp webapp = new QuickStartWebApp();
if (xml != null)
{
if (xml.isDirectory() || !xml.toString().toLowerCase().endsWith(".xml"))
error("Bad context.xml: "+xml);
XmlConfiguration xmlConfiguration = new XmlConfiguration(xml.getURL());
xmlConfiguration.configure(webapp);
}
webapp.setResourceBase(dir.getFile().getAbsolutePath());
webapp.setPreconfigure(true);
server.setHandler(webapp);
server.start();
server.stop();
}
private static void error(String message)
{
System.err.println("ERROR: " + message);
System.err.println("Usage: java -jar PreconfigureQuickStartWar.jar <war-directory>");
System.err.println(" java -jar PreconfigureQuickStartWar.jar <war-directory> <context-xml-file>");
System.err.println(" java -jar PreconfigureQuickStartWar.jar <war-file> <target-war-directory>");
System.err.println(" java -jar PreconfigureQuickStartWar.jar <war-file> <target-war-directory> <context-xml-file>");
System.exit(1);
}
}

View File

@ -0,0 +1,139 @@
//
// ========================================================================
// Copyright (c) 1995-2014 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.quickstart;
import org.eclipse.jetty.annotations.AnnotationConfiguration;
import org.eclipse.jetty.annotations.AnnotationDecorator;
import org.eclipse.jetty.annotations.ServletContainerInitializersStarter;
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.StandardDescriptorProcessor;
import org.eclipse.jetty.webapp.WebAppClassLoader;
import org.eclipse.jetty.webapp.WebAppContext;
import org.eclipse.jetty.webapp.WebInfConfiguration;
/**
* QuickStartConfiguration
*
* Re-inflate a deployable webapp from a saved effective-web.xml
* which combines all pre-parsed web xml descriptors and annotations.
*
*/
public class QuickStartConfiguration extends WebInfConfiguration
{
private static final Logger LOG = Log.getLogger(QuickStartConfiguration.class);
/**
* @see org.eclipse.jetty.webapp.AbstractConfiguration#preConfigure(org.eclipse.jetty.webapp.WebAppContext)
*/
@Override
public void preConfigure(WebAppContext context) throws Exception
{
//check that webapp is suitable for quick start - it is not a packed war
String war = context.getWar();
if (war == null || war.length()<=0)
throw new IllegalStateException ("No location for webapp");
//Make a temp directory for the webapp if one is not already set
resolveTempDirectory(context);
Resource webApp = context.newResource(war);
// Accept aliases for WAR files
if (webApp.getAlias() != null)
{
LOG.debug(webApp + " anti-aliased to " + webApp.getAlias());
webApp = context.newResource(webApp.getAlias());
}
// Is the WAR usable directly?
if (!webApp.exists() || !webApp.isDirectory() || webApp.toString().startsWith("jar:"))
throw new IllegalStateException("Webapp does not exist or is not unpacked");
context.setBaseResource(webApp);
LOG.debug("webapp={}",webApp);
//look for effective-web.xml in WEB-INF of webapp
Resource webInf = context.getWebInf();
if (webInf == null || !webInf.exists())
throw new IllegalStateException("No WEB-INF");
LOG.debug("webinf={}",webInf);
Resource quickStartWebXml = webInf.addPath("quickstart-web.xml");
if (!quickStartWebXml.exists())
throw new IllegalStateException ("No WEB-INF/quickstart-web.xml");
LOG.debug("quickStartWebXml={}",quickStartWebXml);
context.getMetaData().setWebXml(quickStartWebXml);
}
/**
* @see org.eclipse.jetty.webapp.AbstractConfiguration#configure(org.eclipse.jetty.webapp.WebAppContext)
*/
@Override
public void configure(WebAppContext context) throws Exception
{
LOG.debug("configure {}",this);
if (context.isStarted())
{
LOG.warn("Cannot configure webapp after it is started");
return;
}
//Temporary: set up the classpath here. This should be handled by the QuickStartDescriptorProcessor
Resource webInf = context.getWebInf();
if (webInf != null && webInf.isDirectory() && context.getClassLoader() instanceof WebAppClassLoader)
{
// Look for classes directory
Resource classes= webInf.addPath("classes/");
if (classes.exists())
((WebAppClassLoader)context.getClassLoader()).addClassPath(classes);
// Look for jars
Resource lib= webInf.addPath("lib/");
if (lib.exists() || lib.isDirectory())
((WebAppClassLoader)context.getClassLoader()).addJars(lib);
}
//add the processor to handle normal web.xml content
context.getMetaData().addDescriptorProcessor(new StandardDescriptorProcessor());
//add a processor to handle extended web.xml format
context.getMetaData().addDescriptorProcessor(new QuickStartDescriptorProcessor());
//add a decorator that will find introspectable annotations
context.addDecorator(new AnnotationDecorator(context)); //this must be the last Decorator because they are run in reverse order!
//add a context bean that will run ServletContainerInitializers as the context starts
ServletContainerInitializersStarter starter = (ServletContainerInitializersStarter)context.getAttribute(AnnotationConfiguration.CONTAINER_INITIALIZER_STARTER);
if (starter != null)
throw new IllegalStateException("ServletContainerInitializersStarter already exists");
starter = new ServletContainerInitializersStarter(context);
context.setAttribute(AnnotationConfiguration.CONTAINER_INITIALIZER_STARTER, starter);
context.addBean(starter, true);
LOG.debug("configured {}",this);
}
}

View File

@ -0,0 +1,218 @@
//
// ========================================================================
// Copyright (c) 1995-2014 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.quickstart;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashSet;
import java.util.List;
import javax.servlet.ServletContext;
import org.eclipse.jetty.annotations.AnnotationConfiguration;
import org.eclipse.jetty.annotations.ServletContainerInitializersStarter;
import org.eclipse.jetty.plus.annotation.ContainerInitializer;
import org.eclipse.jetty.util.QuotedStringTokenizer;
import org.eclipse.jetty.util.resource.Resource;
import org.eclipse.jetty.util.resource.ResourceCollection;
import org.eclipse.jetty.webapp.Descriptor;
import org.eclipse.jetty.webapp.IterativeDescriptorProcessor;
import org.eclipse.jetty.webapp.MetaInfConfiguration;
import org.eclipse.jetty.webapp.WebAppContext;
import org.eclipse.jetty.xml.XmlParser;
/**
* QuickStartDescriptorProcessor
*
* Handle extended elements for quickstart-web.xml
*/
public class QuickStartDescriptorProcessor extends IterativeDescriptorProcessor
{
/**
*
*/
public QuickStartDescriptorProcessor()
{
try
{
registerVisitor("context-param", this.getClass().getDeclaredMethod("visitContextParam", __signature));
}
catch (Exception e)
{
throw new IllegalStateException(e);
}
}
/**
* @see org.eclipse.jetty.webapp.IterativeDescriptorProcessor#start(org.eclipse.jetty.webapp.WebAppContext, org.eclipse.jetty.webapp.Descriptor)
*/
@Override
public void start(WebAppContext context, Descriptor descriptor)
{
}
/**
* @see org.eclipse.jetty.webapp.IterativeDescriptorProcessor#end(org.eclipse.jetty.webapp.WebAppContext, org.eclipse.jetty.webapp.Descriptor)
*/
@Override
public void end(WebAppContext context, Descriptor descriptor)
{
}
/**
* @param context
* @param descriptor
* @param node
*/
public void visitContextParam (WebAppContext context, Descriptor descriptor, XmlParser.Node node)
throws Exception
{
String name = node.getString("param-name", false, true);
String value = node.getString("param-value", false, true);
List<String> values = new ArrayList<>();
// extract values
switch(name)
{
case ServletContext.ORDERED_LIBS:
case AnnotationConfiguration.CONTAINER_INITIALIZERS:
case MetaInfConfiguration.METAINF_TLDS:
case MetaInfConfiguration.METAINF_RESOURCES:
context.removeAttribute(name);
QuotedStringTokenizer tok = new QuotedStringTokenizer(value,",");
while(tok.hasMoreElements())
values.add(tok.nextToken().trim());
break;
default:
values.add(value);
}
// handle values
switch(name)
{
case ServletContext.ORDERED_LIBS:
{
List<Object> libs = new ArrayList<>();
Object o=context.getAttribute(ServletContext.ORDERED_LIBS);
if (o instanceof Collection<?>)
libs.addAll((Collection<?>)o);
libs.addAll(values);
if (libs.size()>0)
context.setAttribute(ServletContext.ORDERED_LIBS,libs);
break;
}
case AnnotationConfiguration.CONTAINER_INITIALIZERS:
{
for (String i : values)
visitContainerInitializer(context, new ContainerInitializer(Thread.currentThread().getContextClassLoader(), i));
break;
}
case MetaInfConfiguration.METAINF_TLDS:
{
List<Object> tlds = new ArrayList<>();
String war=context.getBaseResource().getURI().toString();
Object o=context.getAttribute(MetaInfConfiguration.METAINF_TLDS);
if (o instanceof Collection<?>)
tlds.addAll((Collection<?>)o);
for (String i : values)
{
Resource r = Resource.newResource(i.replace("${WAR}/",war));
if (r.exists())
tlds.add(r.getURL());
else
throw new IllegalArgumentException("TLD not found: "+r);
}
if (tlds.size()>0)
context.setAttribute(MetaInfConfiguration.METAINF_TLDS,tlds);
break;
}
case MetaInfConfiguration.METAINF_RESOURCES:
{
String war=context.getBaseResource().getURI().toString();
for (String i : values)
{
Resource r = Resource.newResource(i.replace("${WAR}/",war));
if (r.exists())
visitMetaInfResource(context,r);
else
throw new IllegalArgumentException("Resource not found: "+r);
}
break;
}
default:
}
}
public void visitContainerInitializer (WebAppContext context, ContainerInitializer containerInitializer)
{
if (containerInitializer == null)
return;
//add the ContainerInitializer to the list of container initializers
List<ContainerInitializer> containerInitializers = (List<ContainerInitializer>)context.getAttribute(AnnotationConfiguration.CONTAINER_INITIALIZERS);
if (containerInitializers == null)
{
containerInitializers = new ArrayList<ContainerInitializer>();
context.setAttribute(AnnotationConfiguration.CONTAINER_INITIALIZERS, containerInitializers);
}
containerInitializers.add(containerInitializer);
//Ensure a bean is set up on the context that will invoke the ContainerInitializers as the context starts
ServletContainerInitializersStarter starter = (ServletContainerInitializersStarter)context.getAttribute(AnnotationConfiguration.CONTAINER_INITIALIZER_STARTER);
if (starter == null)
{
starter = new ServletContainerInitializersStarter(context);
context.setAttribute(AnnotationConfiguration.CONTAINER_INITIALIZER_STARTER, starter);
context.addBean(starter, true);
}
}
public void visitMetaInfResource (WebAppContext context, Resource dir)
{
Collection<Resource> metaInfResources = (Collection<Resource>)context.getAttribute(MetaInfConfiguration.METAINF_RESOURCES);
if (metaInfResources == null)
{
metaInfResources = new HashSet<Resource>();
context.setAttribute(MetaInfConfiguration.METAINF_RESOURCES, metaInfResources);
}
metaInfResources.add(dir);
//also add to base resource of webapp
Resource[] collection=new Resource[metaInfResources.size()+1];
int i=0;
collection[i++]=context.getBaseResource();
for (Resource resource : metaInfResources)
collection[i++]=resource;
context.setBaseResource(new ResourceCollection(collection));
}
}

View File

@ -0,0 +1,720 @@
//
// ========================================================================
// Copyright (c) 1995-2014 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.quickstart;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.EventListener;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;
import javax.servlet.DispatcherType;
import javax.servlet.MultipartConfigElement;
import javax.servlet.ServletContext;
import javax.servlet.SessionCookieConfig;
import javax.servlet.SessionTrackingMode;
import javax.servlet.descriptor.JspPropertyGroupDescriptor;
import javax.servlet.descriptor.TaglibDescriptor;
import org.eclipse.jetty.annotations.AnnotationConfiguration;
import org.eclipse.jetty.http.MimeTypes;
import org.eclipse.jetty.plus.annotation.LifeCycleCallback;
import org.eclipse.jetty.plus.annotation.LifeCycleCallbackCollection;
import org.eclipse.jetty.security.ConstraintAware;
import org.eclipse.jetty.security.ConstraintMapping;
import org.eclipse.jetty.security.SecurityHandler;
import org.eclipse.jetty.security.authentication.FormAuthenticator;
import org.eclipse.jetty.servlet.ErrorPageErrorHandler;
import org.eclipse.jetty.servlet.FilterHolder;
import org.eclipse.jetty.servlet.FilterMapping;
import org.eclipse.jetty.servlet.Holder;
import org.eclipse.jetty.servlet.ServletHandler;
import org.eclipse.jetty.servlet.ServletHolder;
import org.eclipse.jetty.servlet.ServletMapping;
import org.eclipse.jetty.util.QuotedStringTokenizer;
import org.eclipse.jetty.util.log.Log;
import org.eclipse.jetty.util.log.Logger;
import org.eclipse.jetty.util.resource.JarResource;
import org.eclipse.jetty.util.resource.Resource;
import org.eclipse.jetty.util.security.Constraint;
import org.eclipse.jetty.webapp.MetaData;
import org.eclipse.jetty.webapp.MetaData.OriginInfo;
import org.eclipse.jetty.webapp.MetaInfConfiguration;
import org.eclipse.jetty.webapp.WebAppContext;
import org.eclipse.jetty.xml.XmlAppendable;
/**
* QuickStartWar
*
*/
public class QuickStartWebApp extends WebAppContext
{
private static final Logger LOG = Log.getLogger(QuickStartWebApp.class);
public static final String[] __configurationClasses = new String[]
{
org.eclipse.jetty.quickstart.QuickStartConfiguration.class.getCanonicalName(),
org.eclipse.jetty.plus.webapp.EnvConfiguration.class.getCanonicalName(),
org.eclipse.jetty.plus.webapp.PlusConfiguration.class.getCanonicalName(),
org.eclipse.jetty.webapp.JettyWebXmlConfiguration.class.getCanonicalName()
};
private boolean _preconfigure=false;
private boolean _autoPreconfigure=false;
private boolean _startWebapp=false;
private PreconfigureDescriptorProcessor _preconfigProcessor;
public static final String[] __preconfigurationClasses = new String[]
{
org.eclipse.jetty.webapp.WebInfConfiguration.class.getCanonicalName(),
org.eclipse.jetty.webapp.WebXmlConfiguration.class.getCanonicalName(),
org.eclipse.jetty.webapp.MetaInfConfiguration.class.getCanonicalName(),
org.eclipse.jetty.webapp.FragmentConfiguration.class.getCanonicalName(),
org.eclipse.jetty.plus.webapp.EnvConfiguration.class.getCanonicalName(),
org.eclipse.jetty.plus.webapp.PlusConfiguration.class.getCanonicalName(),
org.eclipse.jetty.annotations.AnnotationConfiguration.class.getCanonicalName(),
};
public QuickStartWebApp()
{
super();
setConfigurationClasses(__preconfigurationClasses);
setAttribute("org.eclipse.jetty.server.webapp.ContainerIncludeJarPattern",".*\\.jar");
}
public boolean isPreconfigure()
{
return _preconfigure;
}
/* ------------------------------------------------------------ */
/** Preconfigure webapp
* @param preconfigure If true, then starting the webapp will generate
* the WEB-INF/quickstart-web.xml rather than start the webapp.
*/
public void setPreconfigure(boolean preconfigure)
{
_preconfigure = preconfigure;
}
public boolean isAutoPreconfigure()
{
return _autoPreconfigure;
}
public void setAutoPreconfigure(boolean autoPrecompile)
{
_autoPreconfigure = autoPrecompile;
}
@Override
protected void startWebapp() throws Exception
{
if (isPreconfigure())
generateQuickstartWebXml(_preconfigProcessor.getXML());
if (_startWebapp)
super.startWebapp();
}
@Override
protected void doStart() throws Exception
{
// unpack and Adjust paths.
Resource war = null;
Resource dir = null;
Resource base = getBaseResource();
if (base==null)
base=Resource.newResource(getWar());
if (base.isDirectory())
dir=base;
else if (base.toString().toLowerCase().endsWith(".war"))
{
war=base;
String w=war.toString();
dir=Resource.newResource(w.substring(0,w.length()-4));
if (!dir.exists())
{
LOG.info("Quickstart Extract " + war + " to " + dir);
dir.getFile().mkdirs();
JarResource.newJarResource(war).copyTo(dir.getFile());
}
setWar(null);
setBaseResource(dir);
}
else
throw new IllegalArgumentException();
Resource qswebxml=dir.addPath("/WEB-INF/quickstart-web.xml");
if (isPreconfigure())
{
_preconfigProcessor = new PreconfigureDescriptorProcessor();
getMetaData().addDescriptorProcessor(_preconfigProcessor);
_startWebapp=false;
}
else if (qswebxml.exists())
{
setConfigurationClasses(__configurationClasses);
_startWebapp=true;
}
else if (_autoPreconfigure)
{
LOG.info("Quickstart preconfigure: {}(war={},dir={})",this,war,dir);
_preconfigProcessor = new PreconfigureDescriptorProcessor();
getMetaData().addDescriptorProcessor(_preconfigProcessor);
setPreconfigure(true);
_startWebapp=true;
}
else
_startWebapp=true;
super.doStart();
}
public void generateQuickstartWebXml(String extraXML) throws IOException
{
getMetaData().getOrigins();
// dumpStdErr();
if (getBaseResource()==null)
throw new IllegalArgumentException("No base resource for "+this);
File webxml = new File(getWebInf().getFile(),"quickstart-web.xml");
LOG.info("Quickstart generate {}",webxml);
XmlAppendable out = new XmlAppendable(new FileOutputStream(webxml),"UTF-8");
MetaData md = getMetaData();
Map<String, String> webappAttr = new HashMap<>();
webappAttr.put("xmlns","http://xmlns.jcp.org/xml/ns/javaee");
webappAttr.put("xmlns:xsi","http://www.w3.org/2001/XMLSchema-instance");
webappAttr.put("xsi:schemaLocation","http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd");
webappAttr.put("metadata-complete","true");
webappAttr.put("version","3.1");
out.open("web-app",webappAttr);
if (getDisplayName() != null)
out.tag("display-name",getDisplayName());
// Set some special context parameters
// The location of the war file on disk
String resourceBase=getBaseResource().getFile().getCanonicalFile().getAbsoluteFile().toURI().toString();
// The library order
addContextParamFromAttribute(out,ServletContext.ORDERED_LIBS);
//the servlet container initializers
addContextParamFromAttribute(out,AnnotationConfiguration.CONTAINER_INITIALIZERS);
//the tlds discovered
addContextParamFromAttribute(out,MetaInfConfiguration.METAINF_TLDS,resourceBase);
//the META-INF/resources discovered
addContextParamFromAttribute(out,MetaInfConfiguration.METAINF_RESOURCES,resourceBase);
// init params
for (String p : getInitParams().keySet())
out.open("context-param",origin(md,"context-param." + p))
.tag("param-name",p)
.tag("param-value",getInitParameter(p))
.close();
if (getEventListeners() != null)
for (EventListener e : getEventListeners())
out.open("listener",origin(md,e.getClass().getCanonicalName() + ".listener"))
.tag("listener-class",e.getClass().getCanonicalName())
.close();
ServletHandler servlets = getServletHandler();
if (servlets.getFilters() != null)
{
for (FilterHolder holder : servlets.getFilters())
outholder(out,md,"filter",holder);
}
if (servlets.getFilterMappings() != null)
{
for (FilterMapping mapping : servlets.getFilterMappings())
{
out.open("filter-mapping");
out.tag("filter-name",mapping.getFilterName());
if (mapping.getPathSpecs() != null)
for (String s : mapping.getPathSpecs())
out.tag("url-pattern",s);
if (mapping.getServletNames() != null)
for (String n : mapping.getServletNames())
out.tag("servlet-name",n);
if (!mapping.isDefaultDispatches())
{
if (mapping.appliesTo(DispatcherType.REQUEST))
out.tag("dispatcher","REQUEST");
if (mapping.appliesTo(DispatcherType.ASYNC))
out.tag("dispatcher","ASYNC");
if (mapping.appliesTo(DispatcherType.ERROR))
out.tag("dispatcher","ERROR");
if (mapping.appliesTo(DispatcherType.FORWARD))
out.tag("dispatcher","FORWARD");
if (mapping.appliesTo(DispatcherType.INCLUDE))
out.tag("dispatcher","INCLUDE");
}
out.close();
}
}
if (servlets.getServlets() != null)
{
for (ServletHolder holder : servlets.getServlets())
outholder(out,md,"servlet",holder);
}
if (servlets.getServletMappings() != null)
{
for (ServletMapping mapping : servlets.getServletMappings())
{
out.open("servlet-mapping",origin(md,mapping.getServletName() + ".servlet.mappings"));
out.tag("servlet-name",mapping.getServletName());
if (mapping.getPathSpecs() != null)
for (String s : mapping.getPathSpecs())
out.tag("url-pattern",s);
out.close();
}
}
// Security elements
SecurityHandler security = getSecurityHandler();
if (security!=null && (security.getRealmName()!=null || security.getAuthMethod()!=null))
{
out.open("login-config");
if (security.getAuthMethod()!=null)
out.tag("auth-method",origin(md,"auth-method"),security.getAuthMethod());
if (security.getRealmName()!=null)
out.tag("realm-name",origin(md,"realm-name"),security.getRealmName());
if (Constraint.__FORM_AUTH.equalsIgnoreCase(security.getAuthMethod()))
{
out.open("form-login-config");
out.tag("form-login-page",origin(md,"form-login-page"),security.getInitParameter(FormAuthenticator.__FORM_LOGIN_PAGE));
out.tag("form-error-page",origin(md,"form-error-page"),security.getInitParameter(FormAuthenticator.__FORM_ERROR_PAGE));
out.close();
}
out.close();
}
if (security instanceof ConstraintAware)
{
ConstraintAware ca = (ConstraintAware)security;
for (String r:ca.getRoles())
out.open("security-role")
.tag("role-name",r)
.close();
for (ConstraintMapping m : ca.getConstraintMappings())
{
out.open("security-constraint");
if (m.getConstraint().getAuthenticate())
{
out.open("auth-constraint");
if (m.getConstraint().getRoles()!=null)
for (String r : m.getConstraint().getRoles())
out.tag("role-name",r);
out.close();
}
switch (m.getConstraint().getDataConstraint())
{
case Constraint.DC_NONE:
out.open("user-data-constraint").tag("transport-guarantee","NONE").close();
break;
case Constraint.DC_INTEGRAL:
out.open("user-data-constraint").tag("transport-guarantee","INTEGRAL").close();
break;
case Constraint.DC_CONFIDENTIAL:
out.open("user-data-constraint").tag("transport-guarantee","CONFIDENTIAL").close();
break;
default:
break;
}
out.open("web-resource-collection");
{
if (m.getConstraint().getName()!=null)
out.tag("web-resource-name",m.getConstraint().getName());
if (m.getPathSpec()!=null)
out.tag("url-pattern",origin(md,"constraint.url."+m.getPathSpec()),m.getPathSpec());
if (m.getMethod()!=null)
out.tag("http-method",m.getMethod());
if (m.getMethodOmissions()!=null)
for (String o:m.getMethodOmissions())
out.tag("http-method-omission",o);
out.close();
}
out.close();
}
}
if (getWelcomeFiles() != null)
{
out.open("welcome-file-list");
for (String welcomeFile:getWelcomeFiles())
{
out.tag("welcome-file", welcomeFile);
}
out.close();
}
Map<String,String> localeEncodings = getLocaleEncodings();
if (localeEncodings != null && !localeEncodings.isEmpty())
{
out.open("locale-encoding-mapping-list");
for (Map.Entry<String, String> entry:localeEncodings.entrySet())
{
out.open("locale-encoding-mapping", origin(md,"locale-encoding."+entry.getKey()));
out.tag("locale", entry.getKey());
out.tag("encoding", entry.getValue());
out.close();
}
out.close();
}
//session-config
if (getSessionHandler().getSessionManager() != null)
{
out.open("session-config");
int maxInactiveSec = getSessionHandler().getSessionManager().getMaxInactiveInterval();
out.tag("session-timeout", (maxInactiveSec==0?"0":Integer.toString(maxInactiveSec/60)));
Set<SessionTrackingMode> modes = getSessionHandler().getSessionManager().getEffectiveSessionTrackingModes();
if (modes != null)
{
for (SessionTrackingMode mode:modes)
out.tag("tracking-mode", mode.toString());
}
//cookie-config
SessionCookieConfig cookieConfig = getSessionHandler().getSessionManager().getSessionCookieConfig();
if (cookieConfig != null)
{
out.open("cookie-config");
if (cookieConfig.getName() != null)
out.tag("name", origin(md,"cookie-config.name"), cookieConfig.getName());
if (cookieConfig.getDomain() != null)
out.tag("domain", origin(md, "cookie-config.domain"), cookieConfig.getDomain());
if (cookieConfig.getPath() != null)
out.tag("path", origin(md, "cookie-config.path"), cookieConfig.getPath());
if (cookieConfig.getComment() != null)
out.tag("comment", origin(md, "cookie-config.comment"), cookieConfig.getComment());
out.tag("http-only", origin(md, "cookie-config.http-only"), Boolean.toString(cookieConfig.isHttpOnly()));
out.tag("secure", origin(md, "cookie-config.secure"), Boolean.toString(cookieConfig.isSecure()));
out.tag("max-age", origin(md, "cookie-config.max-age"), Integer.toString(cookieConfig.getMaxAge()));
out.close();
}
out.close();
}
//error-pages
Map<String,String> errorPages = ((ErrorPageErrorHandler)getErrorHandler()).getErrorPages();
if (errorPages != null)
{
for (Map.Entry<String, String> entry:errorPages.entrySet())
{
out.open("error-page", origin(md, "error."+entry.getKey()));
//a global or default error page has no code or exception
if (!ErrorPageErrorHandler.GLOBAL_ERROR_PAGE.equals(entry.getKey()))
{
if (entry.getKey().matches("\\d{3}"))
out.tag("error-code", entry.getKey());
else
out.tag("exception-type", entry.getKey());
}
out.tag("location", entry.getValue());
out.close();
}
}
//mime-types
MimeTypes mimeTypes = getMimeTypes();
if (mimeTypes != null)
{
for (Map.Entry<String, String> entry:mimeTypes.getMimeMap().entrySet())
{
out.open("mime-mapping");
out.tag("extension", origin(md, "extension."+entry.getKey()), entry.getKey());
out.tag("mime-type", entry.getValue());
out.close();
}
}
//jsp-config
JspConfig jspConfig = (JspConfig)getServletContext().getJspConfigDescriptor();
if (jspConfig != null)
{
out.open("jsp-config");
Collection<TaglibDescriptor> tlds = jspConfig.getTaglibs();
if (tlds != null && !tlds.isEmpty())
{
for (TaglibDescriptor tld:tlds)
{
out.open("taglib");
out.tag("taglib-uri", tld.getTaglibURI());
out.tag("taglib-location", tld.getTaglibLocation());
out.close();
}
}
Collection<JspPropertyGroupDescriptor> jspPropertyGroups = jspConfig.getJspPropertyGroups();
if (jspPropertyGroups != null && !jspPropertyGroups.isEmpty())
{
for (JspPropertyGroupDescriptor jspPropertyGroup:jspPropertyGroups)
{
out.open("jsp-property-group");
Collection<String> strings = jspPropertyGroup.getUrlPatterns();
if (strings != null && !strings.isEmpty())
{
for (String urlPattern:strings)
out.tag("url-pattern", urlPattern);
}
if (jspPropertyGroup.getElIgnored() != null)
out.tag("el-ignored", jspPropertyGroup.getElIgnored());
if (jspPropertyGroup.getPageEncoding() != null)
out.tag("page-encoding", jspPropertyGroup.getPageEncoding());
if (jspPropertyGroup.getScriptingInvalid() != null)
out.tag("scripting-invalid", jspPropertyGroup.getScriptingInvalid());
if (jspPropertyGroup.getIsXml() != null)
out.tag("is-xml", jspPropertyGroup.getIsXml());
if (jspPropertyGroup.getDeferredSyntaxAllowedAsLiteral() != null)
out.tag("deferred-syntax-allowed-as-literal", jspPropertyGroup.getDeferredSyntaxAllowedAsLiteral());
if (jspPropertyGroup.getTrimDirectiveWhitespaces() != null)
out.tag("trim-directive-whitespaces", jspPropertyGroup.getTrimDirectiveWhitespaces());
if (jspPropertyGroup.getDefaultContentType() != null)
out.tag("default-content-type", jspPropertyGroup.getDefaultContentType());
if (jspPropertyGroup.getBuffer() != null)
out.tag("buffer", jspPropertyGroup.getBuffer());
if (jspPropertyGroup.getErrorOnUndeclaredNamespace() != null)
out.tag("error-on-undeclared-namespace", jspPropertyGroup.getErrorOnUndeclaredNamespace());
strings = jspPropertyGroup.getIncludePreludes();
if (strings != null && !strings.isEmpty())
{
for (String prelude:strings)
out.tag("include-prelude", prelude);
}
strings = jspPropertyGroup.getIncludeCodas();
if (strings != null && !strings.isEmpty())
{
for (String coda:strings)
out.tag("include-coda", coda);
}
out.close();
}
}
out.close();
}
//lifecycle: post-construct, pre-destroy
LifeCycleCallbackCollection lifecycles = ((LifeCycleCallbackCollection)getAttribute(LifeCycleCallbackCollection.LIFECYCLE_CALLBACK_COLLECTION));
if (lifecycles != null)
{
Collection<LifeCycleCallback> tmp = lifecycles.getPostConstructCallbacks();
for (LifeCycleCallback c:tmp)
{
out.open("post-construct");
out.tag("lifecycle-callback-class", c.getTargetClassName());
out.tag("lifecycle-callback-method", c.getMethodName());
out.close();
}
tmp = lifecycles.getPreDestroyCallbacks();
for (LifeCycleCallback c:tmp)
{
out.open("pre-destroy");
out.tag("lifecycle-callback-class", c.getTargetClassName());
out.tag("lifecycle-callback-method", c.getMethodName());
out.close();
}
}
out.literal(extraXML);
out.close();
}
private void addContextParamFromAttribute(XmlAppendable out, String attribute) throws IOException
{
addContextParamFromAttribute(out,attribute,null);
}
private void addContextParamFromAttribute(XmlAppendable out, String attribute, String resourceBase) throws IOException
{
Object o=getAttribute(attribute);
if (o==null)
return;
Collection<?> c = (o instanceof Collection)? (Collection<?>)o:Collections.singletonList(o);
StringBuilder v=new StringBuilder();
for (Object i:c)
{
if (i!=null)
{
if (v.length()>0)
v.append(",\n ");
else
v.append("\n ");
if (resourceBase==null)
QuotedStringTokenizer.quote(v,i.toString());
else
QuotedStringTokenizer.quote(v,i.toString().replace(resourceBase,"${WAR}/"));
}
}
out.open("context-param")
.tag("param-name",attribute)
.tagCDATA("param-value",v.toString())
.close();
}
private static void outholder(XmlAppendable out, MetaData md, String tag, Holder<?> holder) throws IOException
{
out.open(tag,Collections.singletonMap("source",holder.getSource().toString()));
String n = holder.getName();
out.tag(tag + "-name",n);
String ot = n + "." + tag + ".";
out.tag(tag + "-class",origin(md,ot + tag + "-class"),holder.getClassName());
for (String p : holder.getInitParameters().keySet())
{
if ("scratchdir".equalsIgnoreCase(p)) //don't preconfigure the temp dir for jsp output
continue;
out.open("init-param",origin(md,ot + "init-param." + p))
.tag("param-name",p)
.tag("param-value",holder.getInitParameter(p))
.close();
}
if (holder instanceof ServletHolder)
{
ServletHolder s = (ServletHolder)holder;
if (s.getForcedPath() != null)
out.tag("jsp-file",s.getForcedPath());
if (s.getInitOrder() != 0)
out.tag("load-on-startup",Integer.toString(s.getInitOrder()));
if (s.getRunAsRole() != null)
out.open("run-as",origin(md,ot + "run-as"))
.tag("role-name",s.getRunAsRole())
.close();
Map<String,String> roles = s.getRoleRefMap();
if (roles!=null)
{
for (Map.Entry<String, String> e : roles.entrySet())
{
out.open("security-role-ref",origin(md,ot+"role-name."+e.getKey()))
.tag("role-name",e.getKey())
.tag("role-link",e.getValue())
.close();
}
}
if (!s.isEnabled())
out.tag("enabled",origin(md,ot + "enabled"),"false");
//multipart-config
MultipartConfigElement multipartConfig = ((ServletHolder.Registration)s.getRegistration()).getMultipartConfig();
if (multipartConfig != null)
{
out.open("multipart-config", origin(md, s.getName()+".servlet.multipart-config"));
if (multipartConfig.getLocation() != null)
out.tag("location", multipartConfig.getLocation());
out.tag("max-file-size", Long.toString(multipartConfig.getMaxFileSize()));
out.tag("max-request-size", Long.toString(multipartConfig.getMaxRequestSize()));
out.tag("file-size-threshold", Long.toString(multipartConfig.getFileSizeThreshold()));
out.close();
}
}
out.tag("async-supported",origin(md,ot + "async-supported"),holder.isAsyncSupported()?"true":"false");
out.close();
}
public static Map<String, String> origin(MetaData md, String name)
{
if (!LOG.isDebugEnabled())
return Collections.emptyMap();
if (name == null)
return Collections.emptyMap();
OriginInfo origin = md.getOriginInfo(name);
// System.err.println("origin of "+name+" is "+origin);
if (origin == null)
return Collections.emptyMap();
return Collections.singletonMap("origin",origin.toString());
}
}

View File

@ -0,0 +1,49 @@
//
// ========================================================================
// Copyright (c) 1995-2014 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.quickstart;
import java.io.File;
import java.io.FileInputStream;
import java.util.concurrent.TimeUnit;
import org.eclipse.jetty.server.Server;
import org.eclipse.jetty.util.IO;
import org.eclipse.jetty.util.log.Log;
import org.eclipse.jetty.util.log.Logger;
public class PreconfigureJNDIWar
{
private static final long __start=System.nanoTime();
private static final Logger LOG = Log.getLogger(Server.class);
public static void main(String[] args) throws Exception
{
String target="target/test-jndi-preconfigured";
File file = new File(target);
if (file.exists())
IO.delete(file);
PreconfigureQuickStartWar.main("target/test-jndi.war",target, "src/test/resources/test-jndi.xml");
LOG.info("Preconfigured in {}ms",TimeUnit.NANOSECONDS.toMillis(System.nanoTime()-__start));
IO.copy(new FileInputStream("target/test-jndi-preconfigured/WEB-INF/quickstart-web.xml"),System.out);
}
}

View File

@ -0,0 +1,58 @@
//
// ========================================================================
// Copyright (c) 1995-2014 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.quickstart;
import java.io.File;
import java.io.FileInputStream;
import java.util.concurrent.TimeUnit;
import org.eclipse.jetty.server.Server;
import org.eclipse.jetty.util.IO;
import org.eclipse.jetty.util.log.Log;
import org.eclipse.jetty.util.log.Logger;
import org.eclipse.jetty.util.resource.Resource;
public class PreconfigureSpecWar
{
private static final long __start=System.nanoTime();
private static final Logger LOG = Log.getLogger(Server.class);
public static void main(String[] args) throws Exception
{
String target="target/test-spec-preconfigured";
File file = new File(target);
if (file.exists())
IO.delete(file);
File realmPropertiesDest = new File ("target/test-spec-realm.properties");
if (realmPropertiesDest.exists())
IO.delete(realmPropertiesDest);
Resource realmPropertiesSrc = Resource.newResource("src/test/resources/realm.properties");
realmPropertiesSrc.copyTo(realmPropertiesDest);
System.setProperty("jetty.home", "target");
PreconfigureQuickStartWar.main("target/test-spec.war",target, "src/test/resources/test-spec.xml");
LOG.info("Preconfigured in {}ms",TimeUnit.NANOSECONDS.toMillis(System.nanoTime()-__start));
IO.copy(new FileInputStream("target/test-spec-preconfigured/WEB-INF/quickstart-web.xml"),System.out);
}
}

View File

@ -0,0 +1,62 @@
//
// ========================================================================
// Copyright (c) 1995-2014 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.quickstart;
import java.io.File;
import java.io.FileInputStream;
import java.util.concurrent.TimeUnit;
import org.eclipse.jetty.server.Server;
import org.eclipse.jetty.util.IO;
import org.eclipse.jetty.util.log.Log;
import org.eclipse.jetty.util.log.Logger;
import org.eclipse.jetty.util.resource.Resource;
/**
* PreconfigureStandardTestWar
*
*/
public class PreconfigureStandardTestWar
{
private static final long __start=System.nanoTime();
private static final Logger LOG = Log.getLogger(Server.class);
public static void main(String[] args) throws Exception
{
String target="target/test-standard-preconfigured";
File file = new File(target);
if (file.exists())
IO.delete(file);
File realmPropertiesDest = new File ("target/test-standard-realm.properties");
if (realmPropertiesDest.exists())
IO.delete(realmPropertiesDest);
Resource realmPropertiesSrc = Resource.newResource("src/test/resources/realm.properties");
realmPropertiesSrc.copyTo(realmPropertiesDest);
System.setProperty("jetty.home", "target");
PreconfigureQuickStartWar.main("target/test-standard.war",target, "src/test/resources/test.xml");
LOG.info("Preconfigured in {}ms",TimeUnit.NANOSECONDS.toMillis(System.nanoTime()-__start));
IO.copy(new FileInputStream("target/test-standard-preconfigured/WEB-INF/quickstart-web.xml"),System.out);
}
}

View File

@ -0,0 +1,31 @@
//
// ========================================================================
// Copyright (c) 1995-2014 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.quickstart;
public class QuickStartJNDIWar
{
public static void main(String... args) throws Exception
{
// Log.getRootLogger().setDebugEnabled(true);
Quickstart.main("target/test-jndi-preconfigured", "src/test/resources/test-jndi.xml");
}
}

View File

@ -0,0 +1,30 @@
//
// ========================================================================
// Copyright (c) 1995-2014 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.quickstart;
public class QuickStartSpecWar
{
public static void main(String... args) throws Exception
{
// Log.getRootLogger().setDebugEnabled(true);
System.setProperty("jetty.home", "target");
Quickstart.main("target/test-spec-preconfigured", "src/test/resources/test-spec.xml");
}
}

View File

@ -0,0 +1,30 @@
//
// ========================================================================
// Copyright (c) 1995-2014 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.quickstart;
public class QuickStartStandardTestWar
{
public static void main(String... args) throws Exception
{
// Log.getRootLogger().setDebugEnabled(true);
System.setProperty("jetty.home", "target");
Quickstart.main("target/test-standard-preconfigured", "src/test/resources/test.xml");
}
}

View File

@ -0,0 +1,73 @@
//
// ========================================================================
// Copyright (c) 1995-2014 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.quickstart;
import org.eclipse.jetty.server.Server;
import org.eclipse.jetty.util.resource.Resource;
import org.eclipse.jetty.xml.XmlConfiguration;
public class Quickstart
{
public static void main(String... args) throws Exception
{
if (args.length<1)
error("No WAR file or directory given");
//war file or dir to start
String war = args[0];
//optional jetty context xml file to configure the webapp
Resource contextXml = null;
if (args.length > 1)
contextXml = Resource.newResource(args[1]);
Server server = new Server(8080);
QuickStartWebApp webapp = new QuickStartWebApp();
webapp.setAutoPreconfigure(true);
webapp.setWar(war);
webapp.setContextPath("/");
//apply context xml file
if (contextXml != null)
{
// System.err.println("Applying "+contextXml);
XmlConfiguration xmlConfiguration = new XmlConfiguration(contextXml.getURL());
xmlConfiguration.configure(webapp);
}
server.setHandler(webapp);
server.start();
server.join();
}
private static void error(String message)
{
System.err.println("ERROR: "+message);
System.err.println("Usage: java -jar QuickStartWar.jar <war-directory> <context-xml>");
System.err.println(" java -jar QuickStartWar.jar <war-file> <context-xml>");
System.exit(1);
}
}

View File

@ -0,0 +1,21 @@
#
# This file defines users passwords and roles for a HashUserRealm
#
# The format is
# <username>: <password>[,<rolename> ...]
#
# Passwords may be clear text, obfuscated or checksummed. The class
# org.eclipse.util.Password should be used to generate obfuscated
# passwords or password checksums
#
# If DIGEST Authentication is used, the password must be in a recoverable
# format, either plain text or OBF:.
#
jetty: MD5:164c88b302622e17050af52c89945d44,user
admin: CRYPT:adpexzg3FUZAk,server-administrator,content-administrator,admin,user
other: OBF:1xmk1w261u9r1w1c1xmq,user
plain: plain,user
user: password,user
# This entry is for digest auth. The credential is a MD5 hash of username:realmname:password
digest: MD5:6e120743ad67abfbc385bc2bb754e297,user

View File

@ -0,0 +1,60 @@
<?xml version="1.0"?>
<!DOCTYPE Configure PUBLIC "-//Mort Bay Consulting//DTD Configure//EN" "http://www.eclipse.org/jetty/configure_9_0.dtd">
<!-- =============================================================== -->
<!-- Configure the test-jndi webapp -->
<!-- =============================================================== -->
<Configure id='wac' class="org.eclipse.jetty.webapp.WebAppContext">
<New id="tx" class="org.eclipse.jetty.plus.jndi.Transaction">
<Arg>
<New class="com.acme.MockUserTransaction"/>
</Arg>
</New>
<!-- Define an env entry with Server scope for java:comp/env -->
<New id="woggle" class="org.eclipse.jetty.plus.jndi.EnvEntry">
<Arg><Property name='server'/></Arg>
<Arg>woggle</Arg>
<Arg type="java.lang.Integer">4000</Arg>
<Arg type="boolean">false</Arg>
</New>
<!-- Define an env entry with webapp scope for java:comp/env -->
<New id="wiggle" class="org.eclipse.jetty.plus.jndi.EnvEntry">
<Arg><Ref refid='wac'/></Arg>
<Arg>wiggle</Arg>
<Arg type="java.lang.Double">100</Arg>
<Arg type="boolean">true</Arg>
</New>
<!-- Mail Session setup -->
<New id="xxxmail" class="org.eclipse.jetty.plus.jndi.Resource">
<Arg><Ref refid='wac'/></Arg>
<Arg>mail/Session</Arg>
<Arg>
<New class="org.eclipse.jetty.jndi.factories.MailSessionReference">
<Set name="user">CHANGE-ME</Set>
<Set name="password">CHANGE-ME</Set>
<Set name="properties">
<New class="java.util.Properties">
<Put name="mail.smtp.auth">false</Put> <!-- change to true if you want to authenticate -->
<Put name="mail.smtp.host">CHANGE-ME</Put>
<Put name="mail.from">CHANGE-ME</Put>
<Put name="mail.debug">false</Put>
</New>
</Set>
</New>
</Arg>
</New>
<!-- A mock DataSource -->
<New id="mydatasource" class="org.eclipse.jetty.plus.jndi.Resource">
<Arg><Ref refid='wac'/></Arg>
<Arg>jdbc/mydatasource</Arg>
<Arg>
<New class="com.acme.MockDataSource"/>
</Arg>
</New>
</Configure>

View File

@ -0,0 +1,39 @@
<?xml version="1.0"?>
<!DOCTYPE Configure PUBLIC "-//Mort Bay Consulting//DTD Configure//EN" "http://www.eclipse.org/jetty/configure_9_0.dtd">
<Configure id='wac' class="org.eclipse.jetty.webapp.WebAppContext">
<New id="tx" class="org.eclipse.jetty.plus.jndi.Transaction">
<Arg>
<New class="com.acme.MockUserTransaction"/>
</Arg>
</New>
<Get name="securityHandler">
<Set name="loginService">
<New class="org.eclipse.jetty.security.HashLoginService">
<Set name="name">Test Realm</Set>
<Set name="config"><SystemProperty name="jetty.home" default="."/>/test-spec-realm.properties</Set>
</New>
</Set>
</Get>
<New id="maxAmount" class="org.eclipse.jetty.plus.jndi.EnvEntry">
<Arg><Ref refid='wac'/></Arg>
<Arg>maxAmount</Arg>
<Arg type="java.lang.Double">100</Arg>
<Arg type="boolean">true</Arg>
</New>
<New id="mydatasource" class="org.eclipse.jetty.plus.jndi.Resource">
<Arg><Ref refid='wac'/></Arg>
<Arg>jdbc/mydatasource</Arg>
<Arg>
<New class="com.acme.MockDataSource">
</New>
</Arg>
</New>
</Configure>

View File

@ -0,0 +1,45 @@
<?xml version="1.0" encoding="ISO-8859-1"?>
<!DOCTYPE Configure PUBLIC "-//Jetty//Configure//EN" "http://www.eclipse.org/jetty/configure_9_0.dtd">
<!-- ==================================================================
Configure and deploy the test web application in $(jetty.home)/webapps/test
Note. If this file did not exist or used a context path other that /test
then the default configuration of jetty.xml would discover the test
webapplication with a WebAppDeployer. By specifying a context in this
directory, additional configuration may be specified and hot deployments
detected.
===================================================================== -->
<Configure class="org.eclipse.jetty.webapp.WebAppContext">
<Set name="contextPath">/test</Set>
<Get name="securityHandler">
<Set name="loginService">
<New class="org.eclipse.jetty.security.HashLoginService">
<Set name="name">Test Realm</Set>
<Set name="config"><SystemProperty name="jetty.home" default="."/>/test-standard-realm.properties</Set>
</New>
</Set>
<Set name="authenticator">
<New class="org.eclipse.jetty.security.authentication.FormAuthenticator">
<Set name="alwaysSaveUri">true</Set>
</New>
</Set>
<Set name="checkWelcomeFiles">true</Set>
</Get>
<!-- Non standard error page mapping -->
<!--
<Get name="errorHandler">
<Call name="addErrorPage">
<Arg type="int">500</Arg>
<Arg type="int">599</Arg>
<Arg type="String">/dump/errorCodeRangeMapping</Arg>
</Call>
</Get>
-->
</Configure>

View File

@ -1,9 +1,9 @@
#
# Module to add all lib/ext/*.jar files to classpath
# Module to add all lib/ext/**.jar files to classpath
#
[lib]
regex:lib/ext/.*\.jar$
lib/ext/**.jar
[files]
lib/

View File

@ -4,7 +4,6 @@
[optional]
jvm
jmx
ext
resources

View File

@ -68,7 +68,7 @@ import org.eclipse.jetty.util.thread.Scheduler;
* HttpTransport.completed().
*
*/
public class HttpChannel<T> implements HttpParser.RequestHandler<T>, Runnable
public class HttpChannel<T> implements HttpParser.RequestHandler<T>, Runnable, HttpParser.ProxyHandler
{
private static final Logger LOG = Log.getLogger(HttpChannel.class);
private static final ThreadLocal<HttpChannel<?>> __currentChannel = new ThreadLocal<>();
@ -477,6 +477,15 @@ public class HttpChannel<T> implements HttpParser.RequestHandler<T>, Runnable
);
}
@Override
public void proxied(String protocol, String sAddr, String dAddr, int sPort, int dPort)
{
_request.setAttribute("PROXY", protocol);
_request.setServerName(sAddr);
_request.setServerPort(dPort);
_request.setRemoteAddr(InetSocketAddress.createUnresolved(sAddr,sPort));
}
@Override
public boolean startRequest(HttpMethod httpMethod, String method, ByteBuffer uri, HttpVersion version)
{
@ -842,4 +851,5 @@ public class HttpChannel<T> implements HttpParser.RequestHandler<T>, Runnable
}
}
}

View File

@ -16,7 +16,7 @@
// ========================================================================
//
package org.eclipse.jetty.spdy.server;
package org.eclipse.jetty.server;
import java.io.IOException;
import java.util.List;

View File

@ -16,7 +16,7 @@
// ========================================================================
//
package org.eclipse.jetty.spdy.server;
package org.eclipse.jetty.server;
import java.util.Arrays;
import java.util.Iterator;

View File

@ -115,37 +115,13 @@ public class GzipHttpOutput extends HttpOutput
private void gzip(ByteBuffer content, boolean complete, final Callback callback)
{
if (content.hasRemaining())
if (content.hasRemaining() || complete)
{
if (content.hasArray())
new GzipArrayCB(content,complete,callback).iterate();
else
new GzipBufferCB(content,complete,callback).iterate();
}
else if (complete)
{
_deflater.finish();
int produced=_deflater.deflate(_buffer.array(),_buffer.arrayOffset()+_buffer.limit(),_buffer.capacity()-_buffer.limit(),Deflater.NO_FLUSH);
_buffer.limit(_buffer.limit()+produced);
addTrailer();
superWrite(_buffer,complete,new Callback()
{
@Override
public void succeeded()
{
getHttpChannel().getByteBufferPool().release(_buffer);
_buffer=null;
callback.succeeded();
}
@Override
public void failed(Throwable x)
{
callback.failed(x);
}
});
}
}
protected void commit(ByteBuffer content, boolean complete, Callback callback)

View File

@ -21,18 +21,19 @@
<module>spdy-http-server</module>
<module>spdy-http-client-transport</module>
<module>spdy-example-webapp</module>
<module>spdy-alpn-tests</module>
</modules>
<profiles>
<profile>
<id>jdk7-npn</id>
<activation>
<jdk>[1.7,1.8)</jdk>
</activation>
<modules>
<module>spdy-npn-tests</module>
</modules>
</profile>
<profile>
<id>npn</id>
<activation>
<jdk>1.7</jdk>
</activation>
<modules>
<module>spdy-npn-tests</module>
</modules>
</profile>
</profiles>
<build>

View File

@ -0,0 +1,95 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<groupId>org.eclipse.jetty.spdy</groupId>
<artifactId>spdy-parent</artifactId>
<version>9.2.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>spdy-alpn-tests</artifactId>
<name>Jetty :: SPDY :: ALPN Tests</name>
<build>
<plugins>
<plugin>
<artifactId>maven-dependency-plugin</artifactId>
<executions>
<execution>
<id>copy</id>
<phase>generate-resources</phase>
<goals>
<goal>copy</goal>
</goals>
<configuration>
<artifactItems>
<artifactItem>
<groupId>org.mortbay.jetty.alpn</groupId>
<artifactId>alpn-boot</artifactId>
<version>${alpn.version}</version>
<type>jar</type>
<overWrite>false</overWrite>
<outputDirectory>${project.build.directory}/alpn</outputDirectory>
</artifactItem>
</artifactItems>
</configuration>
</execution>
</executions>
</plugin>
<plugin>
<artifactId>maven-surefire-plugin</artifactId>
<configuration>
<argLine>-Xbootclasspath/p:${project.build.directory}/alpn/alpn-boot-${alpn.version}.jar</argLine>
</configuration>
</plugin>
</plugins>
</build>
<dependencies>
<dependency>
<groupId>org.eclipse.jetty.alpn</groupId>
<artifactId>alpn-api</artifactId>
<version>${alpn.api.version}</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-alpn-server</artifactId>
<version>${project.version}</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-server</artifactId>
<version>${project.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.eclipse.jetty.spdy</groupId>
<artifactId>spdy-server</artifactId>
<version>${project.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.eclipse.jetty.spdy</groupId>
<artifactId>spdy-http-server</artifactId>
<version>${project.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.eclipse.jetty.spdy</groupId>
<artifactId>spdy-http-server</artifactId>
<version>${project.version}</version>
<classifier>tests</classifier>
<scope>test</scope>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
</project>

View File

@ -0,0 +1,216 @@
//
// ========================================================================
// Copyright (c) 1995-2014 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.spdy.server;
import java.io.BufferedReader;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.net.InetSocketAddress;
import java.nio.charset.StandardCharsets;
import java.util.Arrays;
import java.util.List;
import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLSocket;
import org.eclipse.jetty.alpn.ALPN;
import org.eclipse.jetty.server.HttpConnectionFactory;
import org.eclipse.jetty.util.ssl.SslContextFactory;
import org.junit.Assert;
import org.junit.Test;
public class ALPNNegotiationTest extends AbstractALPNTest
{
@Test
public void testClientAdvertisingHTTPServerSpeaksHTTP() throws Exception
{
InetSocketAddress address = prepare();
connector.addConnectionFactory(new HttpConnectionFactory());
SslContextFactory sslContextFactory = newSslContextFactory();
sslContextFactory.start();
SSLContext sslContext = sslContextFactory.getSslContext();
try (SSLSocket client = (SSLSocket)sslContext.getSocketFactory().createSocket(address.getAddress(), address.getPort()))
{
client.setUseClientMode(true);
client.setSoTimeout(5000);
ALPN.put(client, new ALPN.ClientProvider()
{
@Override
public boolean supports()
{
return true;
}
@Override
public void unsupported()
{
}
@Override
public List<String> protocols()
{
return Arrays.asList("http/1.1");
}
@Override
public void selected(String protocol)
{
Assert.assertEquals("http/1.1", protocol);
}
});
client.startHandshake();
// Verify that the server really speaks http/1.1
OutputStream output = client.getOutputStream();
output.write(("" +
"GET / HTTP/1.1\r\n" +
"Host: localhost:" + address.getPort() + "\r\n" +
"\r\n" +
"").getBytes(StandardCharsets.UTF_8));
output.flush();
InputStream input = client.getInputStream();
BufferedReader reader = new BufferedReader(new InputStreamReader(input, StandardCharsets.UTF_8));
String line = reader.readLine();
Assert.assertTrue(line.contains(" 404 "));
}
}
@Test
public void testClientAdvertisingMultipleProtocolsServerSpeaksHTTPWhenNegotiated() throws Exception
{
InetSocketAddress address = prepare();
connector.addConnectionFactory(new HttpConnectionFactory());
SslContextFactory sslContextFactory = newSslContextFactory();
sslContextFactory.start();
SSLContext sslContext = sslContextFactory.getSslContext();
try (SSLSocket client = (SSLSocket)sslContext.getSocketFactory().createSocket(address.getAddress(), address.getPort()))
{
client.setUseClientMode(true);
client.setSoTimeout(5000);
ALPN.put(client, new ALPN.ClientProvider()
{
@Override
public boolean supports()
{
return true;
}
@Override
public void unsupported()
{
}
@Override
public List<String> protocols()
{
return Arrays.asList("unknown/1.0", "http/1.1");
}
@Override
public void selected(String protocol)
{
Assert.assertEquals("http/1.1", protocol);
}
});
client.startHandshake();
// Verify that the server really speaks http/1.1
OutputStream output = client.getOutputStream();
output.write(("" +
"GET / HTTP/1.1\r\n" +
"Host: localhost:" + address.getPort() + "\r\n" +
"\r\n" +
"").getBytes(StandardCharsets.UTF_8));
output.flush();
InputStream input = client.getInputStream();
BufferedReader reader = new BufferedReader(new InputStreamReader(input, StandardCharsets.UTF_8));
String line = reader.readLine();
Assert.assertTrue(line.contains(" 404 "));
}
}
@Test
public void testClientNotSupportingALPNServerSpeaksDefaultProtocol() throws Exception
{
InetSocketAddress address = prepare();
connector.addConnectionFactory(new HttpConnectionFactory());
SslContextFactory sslContextFactory = newSslContextFactory();
sslContextFactory.start();
SSLContext sslContext = sslContextFactory.getSslContext();
try (SSLSocket client = (SSLSocket)sslContext.getSocketFactory().createSocket(address.getAddress(), address.getPort()))
{
client.setUseClientMode(true);
client.setSoTimeout(5000);
ALPN.put(client, new ALPN.ClientProvider()
{
@Override
public boolean supports()
{
return false;
}
@Override
public void unsupported()
{
}
@Override
public List<String> protocols()
{
return null;
}
@Override
public void selected(String s)
{
}
});
client.startHandshake();
// Verify that the server really speaks http/1.1
OutputStream output = client.getOutputStream();
output.write(("" +
"GET / HTTP/1.1\r\n" +
"Host: localhost:" + address.getPort() + "\r\n" +
"\r\n" +
"").getBytes(StandardCharsets.UTF_8));
output.flush();
InputStream input = client.getInputStream();
BufferedReader reader = new BufferedReader(new InputStreamReader(input, StandardCharsets.UTF_8));
String line = reader.readLine();
Assert.assertTrue(line.contains(" 404 "));
}
}
}

View File

@ -0,0 +1,160 @@
//
// ========================================================================
// Copyright (c) 1995-2014 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.spdy.server;
import java.net.InetSocketAddress;
import java.nio.ByteBuffer;
import java.nio.channels.SocketChannel;
import java.util.List;
import javax.net.ssl.SSLEngine;
import org.eclipse.jetty.alpn.ALPN;
import org.eclipse.jetty.util.BufferUtil;
import org.eclipse.jetty.util.ssl.SslContextFactory;
import org.junit.Assert;
import org.junit.Test;
public class ALPNSynReplyTest extends AbstractALPNTest
{
@Test
public void testGentleCloseDuringHandshake() throws Exception
{
InetSocketAddress address = prepare();
SslContextFactory sslContextFactory = newSslContextFactory();
sslContextFactory.start();
SSLEngine sslEngine = sslContextFactory.newSSLEngine(address);
sslEngine.setUseClientMode(true);
ALPN.put(sslEngine, new ALPN.ClientProvider()
{
@Override
public boolean supports()
{
return true;
}
@Override
public void unsupported()
{
}
@Override
public List<String> protocols()
{
return null;
}
@Override
public void selected(String protocol)
{
}
});
sslEngine.beginHandshake();
ByteBuffer encrypted = ByteBuffer.allocate(sslEngine.getSession().getPacketBufferSize());
sslEngine.wrap(BufferUtil.EMPTY_BUFFER, encrypted);
encrypted.flip();
try (SocketChannel channel = SocketChannel.open(address))
{
// Send ClientHello, immediately followed by TLS Close Alert and then by FIN
channel.write(encrypted);
sslEngine.closeOutbound();
encrypted.clear();
sslEngine.wrap(BufferUtil.EMPTY_BUFFER, encrypted);
encrypted.flip();
channel.write(encrypted);
channel.shutdownOutput();
// Read ServerHello from server
encrypted.clear();
int read = channel.read(encrypted);
encrypted.flip();
Assert.assertTrue(read > 0);
// Cannot decrypt, as the SSLEngine has been already closed
// Now if we read more, we should either read the TLS Close Alert, or directly -1
encrypted.clear();
read = channel.read(encrypted);
// Sending a TLS Close Alert during handshake results in an exception when
// unwrapping that the server react to by closing the connection abruptly.
Assert.assertTrue(read < 0);
}
}
@Test
public void testAbruptCloseDuringHandshake() throws Exception
{
InetSocketAddress address = prepare();
SslContextFactory sslContextFactory = newSslContextFactory();
sslContextFactory.start();
SSLEngine sslEngine = sslContextFactory.newSSLEngine(address);
sslEngine.setUseClientMode(true);
ALPN.put(sslEngine, new ALPN.ClientProvider()
{
@Override
public boolean supports()
{
return true;
}
@Override
public void unsupported()
{
}
@Override
public List<String> protocols()
{
return null;
}
@Override
public void selected(String s)
{
}
});
sslEngine.beginHandshake();
ByteBuffer encrypted = ByteBuffer.allocate(sslEngine.getSession().getPacketBufferSize());
sslEngine.wrap(BufferUtil.EMPTY_BUFFER, encrypted);
encrypted.flip();
try (SocketChannel channel = SocketChannel.open(address))
{
// Send ClientHello, immediately followed by FIN (no TLS Close Alert)
channel.write(encrypted);
channel.shutdownOutput();
// Read ServerHello from server
encrypted.clear();
int read = channel.read(encrypted);
encrypted.flip();
Assert.assertTrue(read > 0);
ByteBuffer decrypted = ByteBuffer.allocate(sslEngine.getSession().getApplicationBufferSize());
sslEngine.unwrap(encrypted, decrypted);
// Now if we read more, we should either read the TLS Close Alert, or directly -1
encrypted.clear();
read = channel.read(encrypted);
// Since we have close the connection abruptly, the server also does so
Assert.assertTrue(read < 0);
}
}
}

View File

@ -0,0 +1,78 @@
//
// ========================================================================
// Copyright (c) 1995-2014 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.spdy.server;
import java.net.InetSocketAddress;
import org.eclipse.jetty.alpn.ALPN;
import org.eclipse.jetty.alpn.server.ALPNServerConnectionFactory;
import org.eclipse.jetty.server.Server;
import org.eclipse.jetty.spdy.client.SPDYClient;
import org.eclipse.jetty.toolchain.test.TestTracker;
import org.eclipse.jetty.util.ssl.SslContextFactory;
import org.eclipse.jetty.util.thread.QueuedThreadPool;
import org.junit.After;
import org.junit.Rule;
public class AbstractALPNTest
{
@Rule
public final TestTracker tracker = new TestTracker();
protected Server server;
protected SPDYServerConnector connector;
protected SPDYClient.Factory clientFactory;
protected InetSocketAddress prepare() throws Exception
{
server = new Server();
connector = new SPDYServerConnector(server, newSslContextFactory(), null, new ALPNServerConnectionFactory("spdy/3", "spdy/2", "http/1.1"));
connector.setPort(0);
connector.setIdleTimeout(30000);
server.addConnector(connector);
server.start();
QueuedThreadPool threadPool = new QueuedThreadPool();
threadPool.setName(threadPool.getName() + "-client");
clientFactory = new SPDYClient.Factory(threadPool);
clientFactory.start();
ALPN.debug = true;
return new InetSocketAddress("localhost", connector.getLocalPort());
}
protected SslContextFactory newSslContextFactory()
{
SslContextFactory sslContextFactory = new SslContextFactory();
sslContextFactory.setKeyStorePath("src/test/resources/keystore.jks");
sslContextFactory.setKeyStorePassword("storepwd");
sslContextFactory.setTrustStorePath("src/test/resources/truststore.jks");
sslContextFactory.setTrustStorePassword("storepwd");
sslContextFactory.setProtocol("TLSv1");
sslContextFactory.setIncludeProtocols("TLSv1");
return sslContextFactory;
}
@After
public void dispose() throws Exception
{
clientFactory.stop();
server.stop();
}
}

View File

@ -0,0 +1,2 @@
org.eclipse.jetty.util.log.class=org.eclipse.jetty.util.log.StdErrLog
#org.eclipse.jetty.spdy.LEVEL=DEBUG

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