Merge branch 'jetty-9.4.x' of https://github.com/eclipse/jetty.project into issues/788

This commit is contained in:
WalkerWatch 2016-08-05 14:47:39 -04:00
commit 23733b1348
19 changed files with 524 additions and 234 deletions

View File

@ -52,7 +52,7 @@ public class MaxConcurrentStreamsTest extends AbstractTest
@Test
public void testOneConcurrentStream() throws Exception
{
long sleep = 1000;
long sleep = 2000;
start(1, new AbstractHandler()
{
@Override

View File

@ -0,0 +1,21 @@
[description]
Enables session data store in a local Infinispan cache
[provides]
session-store
[depend]
sessions
sessions/infinispan/default
[files]
maven://org.infinispan/infinispan-embedded/7.1.1.Final|lib/infinispan/infinispan-embedded-7.1.1.Final.jar
[lib]
lib/jetty-infinispan-${jetty.version}.jar
lib/infinispan/*.jar
[license]
Infinispan is an open source project hosted on Github and released under the Apache 2.0 license.
http://infinispan.org/
http://www.apache.org/licenses/LICENSE-2.0.html

View File

@ -0,0 +1,27 @@
[description]
Enables session data store in a remote Infinispan cache
[provides]
session-store
[depend]
sessions
sessions/infinispan/remote
[files]
maven://org.infinispan/infinispan-remote/7.1.1.Final|lib/infinispan/infinispan-remote-7.1.1.Final.jar
[lib]
lib/jetty-infinispan-${jetty.version}.jar
lib/infinispan/*.jar
[license]
Infinispan is an open source project hosted on Github and released under the Apache 2.0 license.
http://infinispan.org/
http://www.apache.org/licenses/LICENSE-2.0.html
[ini-template]
#jetty.session.remoteInfinispanCache.name=sessions
#jetty.session.infinispanIdleTimeout.seconds=0
#jetty.session.gracePeriod.seconds=3600

View File

@ -1,37 +0,0 @@
[description]
Enables session data store in an Infinispan cache
[provides]
session-store
[depend]
sessions
sessions/infinispan/${cache-type}
[files]
maven://org.infinispan/infinispan-core/7.1.1.Final|lib/infinispan/infinispan-core-7.1.1.Final.jar
maven://org.infinispan/infinispan-commons/7.1.1.Final|lib/infinispan/infinispan-commons-7.1.1.Final.jar
maven://org.jgroups/jgroups/3.6.1.Final|lib/infinispan/jgroups-3.6.1.Final.jar
maven://org.jboss.marshalling/jboss-marshalling-osgi/1.4.4.Final|lib/infinispan/jboss-marshalling-osgi-1.4.4.Final.jar
maven://org.jboss.logging/jboss-logging/3.1.2.GA|lib/infinispan/jboss-logging-3.1.2.GA.jar
[lib]
lib/jetty-infinispan-${jetty.version}.jar
lib/infinispan/*.jar
[license]
Infinispan is an open source project hosted on Github and released under the Apache 2.0 license.
http://infinispan.org/
http://www.apache.org/licenses/LICENSE-2.0.html
[ini]
cache-type=default
[ini-template]
cache-type=default
#cache-type=remote
#jetty.session.remoteInfinispanCache.name=sessions
#jetty.session.infinispanIdleTimeout.seconds=0
#jetty.session.gracePeriod.seconds=3600

View File

@ -268,7 +268,7 @@ public class ByteArrayEndPointTest
@Test
public void testIdle() throws Exception
{
long idleTimeout = 500;
long idleTimeout = 1500;
ByteArrayEndPoint endp = new ByteArrayEndPoint(_scheduler, idleTimeout);
endp.addInput("test");
endp.setGrowOutput(false);
@ -284,7 +284,7 @@ public class ByteArrayEndPointTest
FutureCallback fcb = new FutureCallback();
endp.fillInterested(fcb);
fcb.get(100,TimeUnit.MILLISECONDS);
fcb.get(idleTimeout,TimeUnit.MILLISECONDS);
assertTrue(fcb.isDone());
assertEquals(null, fcb.get());
assertEquals(4, endp.fill(buffer));

View File

@ -55,9 +55,18 @@ public abstract class NamingEntry
}
/**
* Create a naming entry.
*
* @param scope an object representing the scope of the name to be bound into jndi, where null means jvm scope.
* @param jndiName the name that will be associated with an object bound into jndi
* @throws NamingException
*/
protected NamingEntry (Object scope, String jndiName)
throws NamingException
{
if (jndiName == null)
throw new NamingException("jndi name is null");
this._scope=scope;
this._jndiName = jndiName;
}

View File

@ -23,6 +23,7 @@ import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
import java.util.ArrayList;
import java.util.Hashtable;
@ -238,6 +239,35 @@ public class TestNamingEntries
testLink();
}
@Test
public void testNullJndiName () throws Exception
{
try
{
InitialContext icontext = new InitialContext();
Resource resource = new Resource (null,"foo");
fail ("Null jndi name should not be permitted");
}
catch (NamingException e)
{
//expected
}
}
@Test
public void testNullObject () throws Exception
{
InitialContext icontext = new InitialContext();
Resource resource = new Resource ("foo/bar", null);
NamingEntry ne = NamingEntryUtil.lookupNamingEntry(null, "foo/bar");
assertNotNull(ne);
Object o = icontext.lookup("foo/bar");
assertNull(o);
}
@Test
public void testLink () throws Exception
{

View File

@ -1118,7 +1118,6 @@ public class HttpOutput extends ServletOutputStream implements Runnable
else
{
_slice=_buffer.duplicate();
_buffer.position(_buffer.limit());
}
}

View File

@ -19,6 +19,7 @@
package org.eclipse.jetty.server;
import static org.hamcrest.Matchers.containsString;
import static org.hamcrest.Matchers.endsWith;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertThat;
@ -140,6 +141,7 @@ public class HttpOutputTest
String response=_connector.getResponse("GET / HTTP/1.0\nHost: localhost:80\n\n");
assertThat(response,containsString("HTTP/1.1 200 OK"));
assertThat(response,Matchers.not(containsString("Content-Length")));
assertThat(response, endsWith(toUTF8String(big)));
}
@Test
@ -164,6 +166,7 @@ public class HttpOutputTest
assertThat(response,containsString("HTTP/1.1 200 OK"));
assertThat(response,containsString("Transfer-Encoding: chunked"));
assertThat(response, containsString("1\tThis is a big file"));
assertThat(response,containsString("400\tThis is a big file"));
assertThat(response,containsString("\r\n0\r\n"));
@ -191,7 +194,7 @@ public class HttpOutputTest
String response=_connector.getResponse("GET / HTTP/1.0\nHost: localhost:80\n\n");
assertThat(response,containsString("HTTP/1.1 200 OK"));
assertThat(response,Matchers.not(containsString("Content-Length")));
assertThat(response,containsString("400\tThis is a big file"));
assertThat(response, endsWith(toUTF8String(big)));
}
@Test
@ -202,7 +205,7 @@ public class HttpOutputTest
String response=_connector.getResponse("GET / HTTP/1.0\nHost: localhost:80\n\n");
assertThat(response,containsString("HTTP/1.1 200 OK"));
assertThat(response,containsString("Content-Length"));
assertThat(response,containsString("400\tThis is a big file"));
assertThat(response, endsWith(toUTF8String(big)));
}
@Test
@ -213,7 +216,7 @@ public class HttpOutputTest
String response=_connector.getResponse("GET / HTTP/1.0\nHost: localhost:80\n\n");
assertThat(response,containsString("HTTP/1.1 200 OK"));
assertThat(response,containsString("Content-Length"));
assertThat(response,containsString("400\tThis is a big file"));
assertThat(response, endsWith(toUTF8String(big)));
}
@ -261,6 +264,8 @@ public class HttpOutputTest
String response = endp.getResponse();
assertThat(response,containsString("HTTP/1.1 200 OK"));
assertThat(response,containsString("Transfer-Encoding: chunked"));
assertThat(response, containsString("1\tThis is a big file"));
assertThat(response, containsString("400\tThis is a big file"));
assertThat(response,containsString("\r\n0\r\n"));
response = endp.getResponse();
@ -279,7 +284,7 @@ public class HttpOutputTest
String response=_connector.getResponse("GET / HTTP/1.0\nHost: localhost:80\n\n");
assertThat(response,containsString("HTTP/1.1 200 OK"));
assertThat(response,Matchers.not(containsString("Content-Length")));
assertThat(response,containsString("400\tThis is a big file"));
assertThat(response, endsWith(toUTF8String(big)));
}
@Test
@ -293,7 +298,7 @@ public class HttpOutputTest
String response=_connector.getResponse("GET / HTTP/1.0\nHost: localhost:80\n\n");
assertThat(response,containsString("HTTP/1.1 200 OK"));
assertThat(response,Matchers.not(containsString("Content-Length")));
assertThat(response,containsString("400\tThis is a big file"));
assertThat(response, endsWith(toUTF8String(big)));
}
@Test
@ -307,7 +312,7 @@ public class HttpOutputTest
String response=_connector.getResponse("GET / HTTP/1.0\nHost: localhost:80\n\n");
assertThat(response,containsString("HTTP/1.1 200 OK"));
assertThat(response,Matchers.not(containsString("Content-Length")));
assertThat(response,containsString("400\tThis is a big file"));
assertThat(response, endsWith(toUTF8String(big)));
}
@Test
@ -321,7 +326,7 @@ public class HttpOutputTest
String response=_connector.getResponse("GET / HTTP/1.0\nHost: localhost:80\n\n");
assertThat(response,containsString("HTTP/1.1 200 OK"));
assertThat(response,Matchers.not(containsString("Content-Length")));
assertThat(response,containsString("400\tThis is a big file"));
assertThat(response, endsWith(toUTF8String(big)));
}
@Test
@ -335,7 +340,7 @@ public class HttpOutputTest
String response=_connector.getResponse("GET / HTTP/1.0\nHost: localhost:80\n\n");
assertThat(response,containsString("HTTP/1.1 200 OK"));
assertThat(response,containsString("Content-Length"));
assertThat(response,containsString("400\tThis is a big file"));
assertThat(response, endsWith(toUTF8String(big)));
}
@Test
@ -349,7 +354,7 @@ public class HttpOutputTest
String response=_connector.getResponse("GET / HTTP/1.0\nHost: localhost:80\n\n");
assertThat(response,containsString("HTTP/1.1 200 OK"));
assertThat(response,containsString("Content-Length"));
assertThat(response,containsString("400\tThis is a big file"));
assertThat(response, endsWith(toUTF8String(big)));
}
@Test
@ -363,7 +368,7 @@ public class HttpOutputTest
String response=_connector.getResponse("GET / HTTP/1.0\nHost: localhost:80\n\n");
assertThat(response,containsString("HTTP/1.1 200 OK"));
assertThat(response,containsString("Content-Length"));
assertThat(response,containsString("400\tThis is a big file"));
assertThat(response, endsWith(toUTF8String(big)));
}
@Test
@ -377,7 +382,7 @@ public class HttpOutputTest
String response=_connector.getResponse("GET / HTTP/1.0\nHost: localhost:80\n\n");
assertThat(response,containsString("HTTP/1.1 200 OK"));
assertThat(response,containsString("Content-Length"));
assertThat(response,containsString("400\tThis is a big file"));
assertThat(response, endsWith(toUTF8String(big)));
}
@ -408,7 +413,7 @@ public class HttpOutputTest
String response=_connector.getResponse("GET / HTTP/1.0\nHost: localhost:80\n\n");
assertThat(response,containsString("HTTP/1.1 200 OK"));
assertThat(response,Matchers.not(containsString("Content-Length")));
assertThat(response,containsString("400\tThis is a big file"));
assertThat(response, endsWith(toUTF8String(big)));
}
@Test
@ -422,7 +427,7 @@ public class HttpOutputTest
String response=_connector.getResponse("GET / HTTP/1.0\nHost: localhost:80\n\n");
assertThat(response,containsString("HTTP/1.1 200 OK"));
assertThat(response,Matchers.not(containsString("Content-Length")));
assertThat(response,containsString("400\tThis is a big file"));
assertThat(response, endsWith(toUTF8String(big)));
}
@Test
@ -436,7 +441,7 @@ public class HttpOutputTest
String response=_connector.getResponse("GET / HTTP/1.0\nHost: localhost:80\n\n");
assertThat(response,containsString("HTTP/1.1 200 OK"));
assertThat(response,Matchers.not(containsString("Content-Length")));
assertThat(response,containsString("400\tThis is a big file"));
assertThat(response, endsWith(toUTF8String(big)));
}
@ -452,7 +457,7 @@ public class HttpOutputTest
String response=_connector.getResponse("GET / HTTP/1.0\nHost: localhost:80\n\n");
assertThat(response,containsString("HTTP/1.1 200 OK"));
assertThat(response,Matchers.not(containsString("Content-Length")));
assertThat(response,containsString("400\tThis is a big file"));
assertThat(response, endsWith(toUTF8String(big)));
}
@Test
@ -467,7 +472,7 @@ public class HttpOutputTest
String response=_connector.getResponse("GET / HTTP/1.0\nHost: localhost:80\n\n");
assertThat(response,containsString("HTTP/1.1 200 OK"));
assertThat(response,Matchers.not(containsString("Content-Length")));
assertThat(response,containsString("400\tThis is a big file"));
assertThat(response, endsWith(toUTF8String(big)));
}
@Test
@ -482,7 +487,7 @@ public class HttpOutputTest
String response=_connector.getResponse("GET / HTTP/1.0\nHost: localhost:80\n\n");
assertThat(response,containsString("HTTP/1.1 200 OK"));
assertThat(response,Matchers.not(containsString("Content-Length")));
assertThat(response,containsString("400\tThis is a big file"));
assertThat(response, endsWith(toUTF8String(big)));
}
@Test
@ -497,7 +502,7 @@ public class HttpOutputTest
String response=_connector.getResponse("GET / HTTP/1.0\nHost: localhost:80\n\n");
assertThat(response,containsString("HTTP/1.1 200 OK"));
assertThat(response,Matchers.not(containsString("Content-Length")));
assertThat(response,containsString("400\tThis is a big file"));
assertThat(response, endsWith(toUTF8String(big)));
}
@ -531,7 +536,7 @@ public class HttpOutputTest
String response=_connector.getResponse("GET / HTTP/1.0\nHost: localhost:80\n\n");
assertThat(response,containsString("HTTP/1.1 200 OK"));
assertThat(response,Matchers.not(containsString("Content-Length")));
assertThat(response,containsString("400\tThis is a big file"));
assertThat(response, endsWith(toUTF8String(big)));
}
@Test
@ -546,7 +551,7 @@ public class HttpOutputTest
String response=_connector.getResponse("GET / HTTP/1.0\nHost: localhost:80\n\n");
assertThat(response,containsString("HTTP/1.1 200 OK"));
assertThat(response,Matchers.not(containsString("Content-Length")));
assertThat(response,containsString("400\tThis is a big file"));
assertThat(response, endsWith(toUTF8String(big)));
}
@Test
@ -561,7 +566,23 @@ public class HttpOutputTest
String response=_connector.getResponse("GET / HTTP/1.0\nHost: localhost:80\n\n");
assertThat(response,containsString("HTTP/1.1 200 OK"));
assertThat(response,Matchers.not(containsString("Content-Length")));
assertThat(response,containsString("400\tThis is a big file"));
assertThat(response, endsWith(toUTF8String(big)));
}
@Test
public void testAsyncWriteBufferLargeDirect()
throws Exception
{
final Resource big = Resource.newClassPathResource("simple/big.txt");
_handler._writeLengthIfKnown = false;
_handler._content = BufferUtil.toBuffer(big, true);
_handler._byteBuffer = BufferUtil.allocateDirect(8192);
_handler._async = true;
String response = _connector.getResponses("GET / HTTP/1.0\nHost: localhost:80\n\n");
assertThat(response, containsString("HTTP/1.1 200 OK"));
assertThat(response, Matchers.not(containsString("Content-Length")));
assertThat(response, endsWith(toUTF8String(big)));
}
@Test
@ -578,7 +599,8 @@ public class HttpOutputTest
assertThat(_handler._owp.get()-start,Matchers.greaterThan(0));
assertThat(response,containsString("HTTP/1.1 200 OK"));
assertThat(response,Matchers.not(containsString("Content-Length")));
assertThat(response,Matchers.not(containsString("400\tThis is a big file")));
assertThat(response, Matchers.not(containsString("1\tThis is a big file")));
assertThat(response, Matchers.not(containsString("400\tThis is a big file")));
}
@Test
@ -657,6 +679,12 @@ public class HttpOutputTest
assertThat(response,Matchers.not(containsString("Content-Length")));
assertThat(response,containsString("400\tTHIS IS A BIGGER FILE"));
}
private static String toUTF8String(Resource resource)
throws IOException
{
return BufferUtil.toUTF8String(BufferUtil.toBuffer(resource, false));
}
interface ChainedInterceptor extends HttpOutput.Interceptor
{
@ -775,6 +803,8 @@ public class HttpOutputTest
final AsyncContext async = request.startAsync();
out.setWriteListener(new WriteListener()
{
private boolean isFirstWrite = true;
@Override
public void onWritePossible() throws IOException
{
@ -782,6 +812,7 @@ public class HttpOutputTest
while (out.isReady())
{
Assert.assertTrue(isFirstWrite || !_byteBuffer.hasRemaining());
Assert.assertTrue(out.isReady());
if(BufferUtil.isEmpty(_content))
{
@ -793,6 +824,7 @@ public class HttpOutputTest
BufferUtil.put(_content,_byteBuffer);
BufferUtil.flipToFlush(_byteBuffer,0);
out.write(_byteBuffer);
isFirstWrite = false;
}
}

View File

@ -32,41 +32,9 @@
<onlyAnalyze>org.eclipse.jetty.start.*</onlyAnalyze>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-shade-plugin</artifactId>
<configuration>
<minimizeJar>true</minimizeJar>
<createDependencyReducedPom>false</createDependencyReducedPom>
<artifactSet>
<includes>
<include>org.eclipse.jetty:jetty-util</include>
</includes>
</artifactSet>
<relocations>
<relocation>
<pattern>org.eclipse.jetty.util</pattern>
<shadedPattern>org.eclipse.jetty.start.util</shadedPattern>
</relocation>
</relocations>
</configuration>
<executions>
<execution>
<phase>package</phase>
<goals>
<goal>shade</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
<dependencies>
<dependency>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-util</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>org.eclipse.jetty.toolchain</groupId>
<artifactId>jetty-test-helper</artifactId>

View File

@ -34,8 +34,6 @@ import java.util.function.Consumer;
import java.util.stream.Collectors;
import java.util.stream.Stream;
import org.eclipse.jetty.util.TopologicalSort;
/**
* Access for all modules declared, as well as what is enabled.
*/
@ -205,15 +203,8 @@ public class Modules implements Iterable<Module>
module.getDepends().forEach(add);
module.getOptional().forEach(add);
}
try
{
sort.sort(_modules);
}
catch (IllegalStateException e)
{
System.err.println(sort.dump());
throw e;
}
sort.sort(_modules);
}
public List<Module> getEnabled()

View File

@ -41,6 +41,7 @@ public class StartLog
private final static PrintStream stderr = System.err;
private static volatile PrintStream out = System.out;
private static volatile PrintStream err = System.err;
private static volatile PrintStream logStream = System.err;
private final static StartLog INSTANCE = new StartLog();
public static void debug(String format, Object... args)
@ -74,12 +75,12 @@ public class StartLog
public static void log(String type, String msg)
{
err.println(type + ": " + msg);
logStream.println(type + ": " + msg);
}
public static void log(String type, String format, Object... args)
{
err.printf(type + ": " + format + "%n",args);
logStream.printf(type + ": " + format + "%n",args);
}
public static void info(String format, Object... args)
@ -94,7 +95,7 @@ public class StartLog
public static void warn(Throwable t)
{
t.printStackTrace(err);
t.printStackTrace(logStream);
}
public static boolean isDebugEnabled()
@ -163,9 +164,10 @@ public class StartLog
err.println("StartLog to " + logfile);
OutputStream fileout = Files.newOutputStream(startLog,StandardOpenOption.CREATE,StandardOpenOption.APPEND);
PrintStream logger = new PrintStream(fileout);
PrintStream logger = new PrintStream(fileout,true);
out=logger;
err=logger;
setStream(logger);
System.setErr(logger);
System.setOut(logger);
err.println("StartLog Establishing " + logfile + " on " + new Date());
@ -189,7 +191,20 @@ public class StartLog
err.println("StartLog ended");
stderr.println("StartLog ended");
}
setStream(stderr);
System.setErr(stderr);
System.setOut(stdout);
}
public static PrintStream getStream()
{
return logStream;
}
public static PrintStream setStream(PrintStream stream)
{
PrintStream ret = logStream;
logStream = stream;
return ret;
}
}

View File

@ -0,0 +1,185 @@
//
// ========================================================================
// Copyright (c) 1995-2016 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.start;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Comparator;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.SortedSet;
import java.util.TreeSet;
/**
* Topological sort a list or array.
* <p>A Topological sort is used when you have a partial ordering expressed as
* dependencies between elements (also often represented as edges in a directed
* acyclic graph). A Topological sort should not be used when you have a total
* ordering expressed as a {@link Comparator} over the items. The algorithm has
* the additional characteristic that dependency sets are sorted by the original
* list order so that order is preserved when possible.</p>
* <p>
* The sort algorithm works by recursively visiting every item, once and
* only once. On each visit, the items dependencies are first visited and then the
* item is added to the sorted list. Thus the algorithm ensures that dependency
* items are always added before dependent items.</p>
*
* @param <T> The type to be sorted. It must be able to be added to a {@link HashSet}
*/
@SuppressWarnings("Duplicates")
public class TopologicalSort<T>
{
private final Map<T,Set<T>> _dependencies = new HashMap<>();
/**
* Add a dependency to be considered in the sort.
* @param dependent The dependent item will be sorted after all its dependencies
* @param dependency The dependency item, will be sorted before its dependent item
*/
public void addDependency(T dependent, T dependency)
{
Set<T> set = _dependencies.get(dependent);
if (set==null)
{
set=new HashSet<>();
_dependencies.put(dependent,set);
}
set.add(dependency);
}
/** Sort the passed array according to dependencies previously set with
* {@link #addDependency(Object, Object)}. Where possible, ordering will be
* preserved if no dependency
* @param array The array to be sorted.
*/
public void sort(T[] array)
{
List<T> sorted = new ArrayList<>();
Set<T> visited = new HashSet<>();
Comparator<T> comparator = new InitialOrderComparator<>(array);
// Visit all items in the array
for (T t : array)
visit(t,visited,sorted,comparator);
sorted.toArray(array);
}
/** Sort the passed list according to dependencies previously set with
* {@link #addDependency(Object, Object)}. Where possible, ordering will be
* preserved if no dependency
* @param list The list to be sorted.
*/
public void sort(Collection<T> list)
{
List<T> sorted = new ArrayList<>();
Set<T> visited = new HashSet<>();
Comparator<T> comparator = new InitialOrderComparator<>(list);
// Visit all items in the list
for (T t : list)
visit(t,visited,sorted,comparator);
list.clear();
list.addAll(sorted);
}
/** Visit an item to be sorted.
* @param item The item to be visited
* @param visited The Set of items already visited
* @param sorted The list to sort items into
* @param comparator A comparator used to sort dependencies.
*/
private void visit(T item, Set<T> visited, List<T> sorted,Comparator<T> comparator)
{
// If the item has not been visited
if(!visited.contains(item))
{
// We are visiting it now, so add it to the visited set
visited.add(item);
// Lookup the items dependencies
Set<T> dependencies = _dependencies.get(item);
if (dependencies!=null)
{
// Sort the dependencies
SortedSet<T> ordered_deps = new TreeSet<>(comparator);
ordered_deps.addAll(dependencies);
// recursively visit each dependency
for (T d:ordered_deps)
visit(d,visited,sorted,comparator);
}
// Now that we have visited all our dependencies, they and their
// dependencies will have been added to the sorted list. So we can
// now add the current item and it will be after its dependencies
sorted.add(item);
}
else if (!sorted.contains(item))
// If we have already visited an item, but it has not yet been put in the
// sorted list, then we must be in a cycle!
throw new IllegalStateException("cyclic at "+item);
}
/** A comparator that is used to sort dependencies in the order they
* were in the original list. This ensures that dependencies are visited
* in the original order and no needless reordering takes place.
* @param <T>
*/
private static class InitialOrderComparator<T> implements Comparator<T>
{
private final Map<T,Integer> _indexes = new HashMap<>();
InitialOrderComparator(T[] initial)
{
int i=0;
for (T t : initial)
_indexes.put(t,i++);
}
InitialOrderComparator(Collection<T> initial)
{
int i=0;
for (T t : initial)
_indexes.put(t,i++);
}
@Override
public int compare(T o1, T o2)
{
Integer i1=_indexes.get(o1);
Integer i2=_indexes.get(o2);
if (i1==null || i2==null || i1.equals(o2))
return 0;
if (i1<i2)
return -1;
return 1;
}
}
@Override
public String toString()
{
return "TopologicalSort "+_dependencies;
}
}

View File

@ -20,24 +20,25 @@ package org.eclipse.jetty.start;
import static org.hamcrest.Matchers.greaterThan;
import static org.hamcrest.Matchers.greaterThanOrEqualTo;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertThat;
import static org.junit.Assert.assertTrue;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.PrintWriter;
import java.io.StringWriter;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.stream.Stream;
import org.eclipse.jetty.start.Props.Prop;
import org.eclipse.jetty.toolchain.test.MavenTestingUtils;
import org.eclipse.jetty.toolchain.test.PathAssert;
import org.hamcrest.Matchers;
import org.junit.Assert;
@ -45,38 +46,51 @@ public class ConfigurationAssert
{
/**
* Given a provided StartArgs, assert that the configuration it has determined is valid based on values in a assert text file.
*
* @param baseHome
* the BaseHome used. Access it via {@link Main#getBaseHome()}
* @param args
* the StartArgs that has been processed via {@link Main#processCommandLine(String[])}
* @param filename
* the filename of the assertion values
*
* @param baseHome the BaseHome used. Access it via {@link Main#getBaseHome()}
* @param args the StartArgs that has been processed via {@link Main#processCommandLine(String[])}
* @param filename the filename of the assertion values
* @throws FileNotFoundException if unable to find the configuration
* @throws IOException if unable to process the configuration
*/
public static void assertConfiguration(BaseHome baseHome, StartArgs args, String filename) throws FileNotFoundException, IOException
{
assertConfiguration(baseHome,args,MavenTestingUtils.getTestResourceFile(filename));
assertConfiguration(baseHome, args, null, MavenTestingUtils.getTestResourceFile(filename));
}
/**
* Given a provided StartArgs, assert that the configuration it has determined is valid based on values in a assert text file.
*
* @param baseHome
* the BaseHome used. Access it via {@link Main#getBaseHome()}
* @param args
* the StartArgs that has been processed via {@link Main#processCommandLine(String[])}
* @param file
* the file of the assertion values
*
* @param baseHome the BaseHome used. Access it via {@link Main#getBaseHome()}
* @param args the StartArgs that has been processed via {@link Main#processCommandLine(String[])}
* @param output the captured output that you want to assert against
* @param filename the filename of the assertion values
* @throws FileNotFoundException if unable to find the configuration
* @throws IOException if unable to process the configuration
*/
public static void assertConfiguration(BaseHome baseHome, StartArgs args, File file) throws FileNotFoundException, IOException
public static void assertConfiguration(BaseHome baseHome, StartArgs args, String output, String filename) throws FileNotFoundException, IOException
{
assertConfiguration(baseHome, args, output, MavenTestingUtils.getTestResourceFile(filename));
}
/**
* Given a provided StartArgs, assert that the configuration it has determined is valid based on values in a assert text file.
*
* @param baseHome the BaseHome used. Access it via {@link Main#getBaseHome()}
* @param args the StartArgs that has been processed via {@link Main#processCommandLine(String[])}
* @param file the file of the assertion values
* @throws FileNotFoundException if unable to find the configuration
* @throws IOException if unable to process the configuration
*/
public static void assertConfiguration(BaseHome baseHome, StartArgs args, String output, File file) throws FileNotFoundException, IOException
{
if(output != null)
{
System.err.println(output);
}
Path testResourcesDir = MavenTestingUtils.getTestResourcesDir().toPath().toRealPath();
TextFile textFile = new TextFile(file.toPath());
// Validate XMLs (order is important)
List<String> expectedXmls = new ArrayList<>();
for (String line : textFile)
@ -89,10 +103,10 @@ public class ConfigurationAssert
List<String> actualXmls = new ArrayList<>();
for (Path xml : args.getXmlFiles())
{
actualXmls.add(shorten(baseHome,xml,testResourcesDir));
actualXmls.add(shorten(baseHome, xml, testResourcesDir));
}
assertOrdered("XML Resolution Order",expectedXmls,actualXmls);
assertOrdered("XML Resolution Order", expectedXmls, actualXmls);
// Validate LIBs (order is not important)
List<String> expectedLibs = new ArrayList<>();
for (String line : textFile)
@ -105,10 +119,10 @@ public class ConfigurationAssert
List<String> actualLibs = new ArrayList<>();
for (File path : args.getClasspath())
{
actualLibs.add(shorten(baseHome,path.toPath(),testResourcesDir));
actualLibs.add(shorten(baseHome, path.toPath(), testResourcesDir));
}
assertContainsUnordered("Libs",expectedLibs,actualLibs);
assertContainsUnordered("Libs", expectedLibs, actualLibs);
// Validate PROPERTIES (order is not important)
Set<String> expectedProperties = new HashSet<>();
for (String line : textFile)
@ -123,16 +137,16 @@ public class ConfigurationAssert
{
String name = prop.key;
if ("jetty.home".equals(name) || "jetty.base".equals(name) ||
"user.dir".equals(name) || prop.origin.equals(Props.ORIGIN_SYSPROP) ||
name.startsWith("java."))
"user.dir".equals(name) || prop.origin.equals(Props.ORIGIN_SYSPROP) ||
name.startsWith("java."))
{
// strip these out from assertion, to make assertions easier.
continue;
}
actualProperties.add(prop.key + "=" + args.getProperties().expand(prop.value));
}
assertContainsUnordered("Properties",expectedProperties,actualProperties);
assertContainsUnordered("Properties", expectedProperties, actualProperties);
// Validate Downloads
List<String> expectedDownloads = new ArrayList<>();
for (String line : textFile)
@ -147,20 +161,34 @@ public class ConfigurationAssert
{
if (darg.uri != null)
{
actualDownloads.add(String.format("%s|%s",darg.uri,darg.location));
actualDownloads.add(String.format("%s|%s", darg.uri, darg.location));
}
}
assertContainsUnordered("Downloads",expectedDownloads,actualDownloads);
textFile.stream()
.filter(s->s.startsWith("EXISTS|")).map(f->f.substring(7)).forEach(f->
assertContainsUnordered("Downloads", expectedDownloads, actualDownloads);
// File / Path Existence Checks
streamOf(textFile, "EXISTS").forEach(f ->
{
Path path=baseHome.getBasePath().resolve(f);
assertTrue(baseHome.toShortForm(path)+" exists?",Files.exists(path));
assertEquals(baseHome.toShortForm(path)+" isDir?",f.endsWith("/"),Files.isDirectory(path));
Path path = baseHome.getPath(f);
if (f.endsWith("/"))
{
PathAssert.assertDirExists("Required Directory", path);
}
else
{
PathAssert.assertFileExists("Required File", path);
}
});
// Output Validation
streamOf(textFile, "OUTPUT").forEach(regex ->
{
Pattern pat = Pattern.compile(regex);
Matcher mat = pat.matcher(output);
assertTrue("Output [\n" + output + "]\nContains Regex Match: " + pat.pattern(), mat.find());
});
}
private static String shorten(BaseHome baseHome, Path path, Path testResourcesDir)
{
String value = baseHome.toShortForm(path);
@ -168,7 +196,7 @@ public class ConfigurationAssert
{
return value;
}
if (path.startsWith(testResourcesDir))
{
int len = testResourcesDir.toString().length();
@ -181,41 +209,47 @@ public class ConfigurationAssert
{
try
{
Assert.assertEquals(msg,expectedSet.size(),actualSet.size());
Assert.assertEquals(msg, expectedSet.size(), actualSet.size());
if (!expectedSet.isEmpty())
Assert.assertThat(msg,actualSet,Matchers.containsInAnyOrder(expectedSet.toArray()));
assertThat(msg, actualSet, Matchers.containsInAnyOrder(expectedSet.toArray()));
}
catch(AssertionError e)
catch (AssertionError e)
{
System.err.println("Expected: "+expectedSet);
System.err.println("Actual : "+actualSet);
System.err.println("Expected: " + expectedSet);
System.err.println("Actual : " + actualSet);
throw e;
}
}
public static void assertOrdered(String msg, List<String> expectedList, List<String> actualList)
{
try
{
Assert.assertEquals(msg,expectedList.size(),actualList.size());
Assert.assertEquals(msg, expectedList.size(), actualList.size());
if (!expectedList.isEmpty())
Assert.assertThat(msg,actualList,Matchers.contains(expectedList.toArray()));
assertThat(msg, actualList, Matchers.contains(expectedList.toArray()));
}
catch(AssertionError e)
catch (AssertionError e)
{
System.err.println("Expected: "+expectedList);
System.err.println("Actual : "+actualList);
System.err.println("Expected: " + expectedList);
System.err.println("Actual : " + actualList);
throw e;
}
}
private static Stream<String> streamOf(TextFile textFile, String key)
{
return textFile.stream()
.filter(s -> s.startsWith(key + "|")).map(f -> getValue(f));
}
private static String getValue(String arg)
{
int idx = arg.indexOf('|');
Assert.assertThat("Expecting '|' sign in [" + arg + "]",idx,greaterThanOrEqualTo(0));
assertThat("Expecting '|' sign in [" + arg + "]", idx, greaterThanOrEqualTo(0));
String value = arg.substring(idx + 1).trim();
Assert.assertThat("Expecting Value after '|' in [" + arg + "]",value.length(),greaterThan(0));
assertThat("Expecting Value after '|' in [" + arg + "]", value.length(), greaterThan(0));
return value;
}
}

View File

@ -30,7 +30,7 @@ import java.util.List;
import org.eclipse.jetty.toolchain.test.MavenTestingUtils;
import org.eclipse.jetty.toolchain.test.TestTracker;
import org.eclipse.jetty.util.IO;
import org.eclipse.jetty.toolchain.test.IO;
import org.junit.Before;
import org.junit.Ignore;
import org.junit.Rule;

View File

@ -20,15 +20,19 @@ package org.eclipse.jetty.start;
import static java.util.stream.Collectors.toList;
import java.io.BufferedReader;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FilenameFilter;
import java.io.FileReader;
import java.io.IOException;
import java.io.PrintStream;
import java.nio.charset.StandardCharsets;
import java.nio.file.Path;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import org.eclipse.jetty.toolchain.test.IO;
import org.eclipse.jetty.toolchain.test.MavenTestingUtils;
import org.hamcrest.Matchers;
import org.junit.Assert;
@ -46,107 +50,114 @@ public class TestUseCases
{
@Parameters(name = "{0}")
public static List<Object[]> getCases() throws Exception
{
{
File usecases = MavenTestingUtils.getTestResourceDir("usecases/");
File[] cases=usecases.listFiles(new FilenameFilter()
{
@Override
public boolean accept(File dir, String name)
{
return name.endsWith(".assert.txt");
}
});
File[] cases = usecases.listFiles((dir, name) -> name.endsWith(".assert.txt"));
Arrays.sort(cases);
List<Object[]> ret = new ArrayList<>();
for(File assertTxt:cases)
for (File assertTxt : cases)
{
String caseName=assertTxt.getName().replace(".assert.txt","");
String baseName=caseName.split("\\.")[0];
ret.add(new Object[] {caseName,baseName, assertTxt, lines(new File(usecases,caseName+".prepare.txt")),lines(new File(usecases,caseName+".cmdline.txt"))});
String caseName = assertTxt.getName().replace(".assert.txt", "");
ret.add(new Object[]{caseName});
}
return ret;
}
static String[] lines(File file) throws IOException
{
if (!file.exists() || !file.canRead())
return new String[0];
return IO.readToString(file).split("[\n\r]+");
}
@Parameter(0)
public String caseName;
@Parameter(1)
public String baseName;
@Parameter(2)
public File assertFile;
@Parameter(3)
public String[] prepare;
@Parameter(4)
public String[] commandLineArgs;
@Test
public void testUseCase() throws Exception
{
String baseName = caseName.replaceFirst("\\..*$", "");
File assertFile = MavenTestingUtils.getTestResourceFile("usecases/" + caseName + ".assert.txt");
Path homeDir = MavenTestingUtils.getTestResourceDir("dist-home").toPath().toRealPath();
Path baseSrcDir = MavenTestingUtils.getTestResourceDir("usecases/" + baseName).toPath().toRealPath();
Path baseDir = MavenTestingUtils.getTargetTestingPath(caseName);
if (baseDir.toFile().exists())
org.eclipse.jetty.toolchain.test.FS.cleanDirectory(baseDir);
else
baseDir.toFile().mkdirs();
org.eclipse.jetty.toolchain.test.IO.copyDir(baseSrcDir.toFile(),baseDir.toFile());
org.eclipse.jetty.toolchain.test.FS.ensureEmpty(baseDir);
org.eclipse.jetty.toolchain.test.IO.copyDir(baseSrcDir.toFile(), baseDir.toFile());
System.setProperty("jetty.home", homeDir.toString());
System.setProperty("jetty.base", baseDir.toString());
System.setProperty("jetty.home",homeDir.toString());
System.setProperty("jetty.base",baseDir.toString());
ByteArrayOutputStream out = new ByteArrayOutputStream();
PrintStream originalStream = StartLog.setStream(new PrintStream(out));
try
{
if (prepare != null && prepare.length>0)
// If there is a "{caseName}.prepare.txt" then use those
// lines as if you are calling start.jar once to setup
// the base directory.
List<String> prepareArgs = lines(caseName + ".prepare.txt");
if (!prepareArgs.isEmpty())
{
for (String arg : prepare)
{
Main main = new Main();
List<String> cmdLine = new ArrayList<>();
cmdLine.add("--testing-mode");
cmdLine.addAll(Arrays.asList(arg.split(" ")));
main.start(main.processCommandLine(cmdLine));
}
Main main = new Main();
List<String> cmdLine = new ArrayList<>();
cmdLine.add("--testing-mode");
cmdLine.addAll(prepareArgs);
main.start(main.processCommandLine(cmdLine));
}
Main main = new Main();
List<String> cmdLine = new ArrayList<>();
cmdLine.add("--debug");
if (commandLineArgs != null)
{
for (String arg : commandLineArgs)
cmdLine.add(arg);
}
// cmdLine.add("--debug");
// If there is a "{caseName}.cmdline.txt" then these
// entries are extra command line argument to use for
// the actual testcase
cmdLine.addAll(lines(caseName + ".cmdline.txt"));
StartArgs args = main.processCommandLine(cmdLine);
args.getAllModules().checkEnabledModules();
BaseHome baseHome = main.getBaseHome();
ConfigurationAssert.assertConfiguration(baseHome,args,assertFile);
StartLog.setStream(originalStream);
String output = out.toString(StandardCharsets.UTF_8.name());
ConfigurationAssert.assertConfiguration(baseHome, args, output, assertFile);
}
catch (Exception e)
{
List<String> exceptions = Arrays.asList(lines(assertFile)).stream().filter(s->s.startsWith("EX|")).collect(toList());
List<String> exceptions = lines(assertFile).stream().filter(s -> s.startsWith("EX|")).collect(toList());
if (exceptions.isEmpty())
throw e;
for (String ex:exceptions)
for (String ex : exceptions)
{
ex=ex.substring(3);
Assert.assertThat(e.toString(),Matchers.containsString(ex));
ex = ex.substring(3);
Assert.assertThat(e.toString(), Matchers.containsString(ex));
}
}
finally
{
StartLog.setStream(originalStream);
}
}
private List<String> lines(String filename) throws IOException
{
return lines(MavenTestingUtils.getTestResourcesPath().resolve("usecases" + File.separator + filename).toFile());
}
private List<String> lines(File file) throws IOException
{
if (!file.exists() || !file.canRead())
return Collections.emptyList();
List<String> ret = new ArrayList<>();
try (FileReader reader = new FileReader(file);
BufferedReader buf = new BufferedReader(reader))
{
String line;
while ((line = buf.readLine()) != null)
{
line = line.trim();
if (line.length() > 0)
{
ret.add(line);
}
}
}
return ret;
}
}

View File

@ -1 +1,2 @@
--create-startd --add=tom
--create-startd
--add-to-start=tom

View File

@ -19,5 +19,9 @@ PROP|optional.prop=value0
# Files / Directories to create
EXISTS|maindir/
EXISTS|start.d/start.ini
EXISTS|start.d/main.ini
EXISTS|start.d/extra.ini
EXISTS|start.d/optional.ini
# Output Assertions [regex!] (order is irrelevant)
OUTPUT|MKDIR: \$\{jetty.base\}/maindir

View File

@ -139,7 +139,7 @@ public class WebAppContext extends ServletContextHandler implements WebAppClassL
// with a more automatic distributed mechanism
public final static String[] __dftServerClasses =
{
"-org.eclipse.jetty.session.infinispan.", //don't hide infinispan support classes
"-org.eclipse.jetty.server.session.SessionData", //don't hide SessionData for de/serialization purposes
"-org.eclipse.jetty.jmx.", // don't hide jmx classes
"-org.eclipse.jetty.util.annotation.", // don't hide jmx annotation
"-org.eclipse.jetty.continuation.", // don't hide continuation classes