Merge remote-tracking branch 'origin/master' into servlet-3.1-api

This commit is contained in:
Jan Bartel 2012-11-02 16:59:11 +11:00
commit 2a2215cf0b
222 changed files with 8375 additions and 987 deletions

View File

@ -21,13 +21,6 @@ package org.eclipse.jetty.embedded;
import org.eclipse.jetty.server.Server; import org.eclipse.jetty.server.Server;
import org.eclipse.jetty.server.handler.ContextHandler; import org.eclipse.jetty.server.handler.ContextHandler;
/* ------------------------------------------------------------ */
/**
* A {@link ContextHandler} provides a common environment for multiple Handlers,
* such as: URI context path, class loader, static resource base.
*
* Typically a ContextHandler is used only when multiple contexts are likely.
*/
public class OneContext public class OneContext
{ {
public static void main(String[] args) throws Exception public static void main(String[] args) throws Exception
@ -38,10 +31,10 @@ public class OneContext
context.setContextPath("/"); context.setContextPath("/");
context.setResourceBase("."); context.setResourceBase(".");
context.setClassLoader(Thread.currentThread().getContextClassLoader()); context.setClassLoader(Thread.currentThread().getContextClassLoader());
server.setHandler(context);
context.setHandler(new HelloHandler()); context.setHandler(new HelloHandler());
server.setHandler(context);
server.start(); server.start();
server.join(); server.join();
} }

View File

@ -26,6 +26,7 @@ import java.net.URLClassLoader;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Arrays; import java.util.Arrays;
import java.util.List; import java.util.List;
import java.util.Locale;
import java.util.jar.JarEntry; import java.util.jar.JarEntry;
import org.eclipse.jetty.util.Loader; import org.eclipse.jetty.util.Loader;
@ -807,7 +808,7 @@ public class AnnotationParser
try try
{ {
String name = entry.getName(); String name = entry.getName();
if (name.toLowerCase().endsWith(".class")) if (name.toLowerCase(Locale.ENGLISH).endsWith(".class"))
{ {
String shortName = name.replace('/', '.').substring(0,name.length()-6); String shortName = name.replace('/', '.').substring(0,name.length()-6);
if ((resolver == null) if ((resolver == null)
@ -853,7 +854,7 @@ public class AnnotationParser
try try
{ {
String name = entry.getName(); String name = entry.getName();
if (name.toLowerCase().endsWith(".class")) if (name.toLowerCase(Locale.ENGLISH).endsWith(".class"))
{ {
String shortName = name.replace('/', '.').substring(0,name.length()-6); String shortName = name.replace('/', '.').substring(0,name.length()-6);

View File

@ -21,6 +21,7 @@ package org.eclipse.jetty.annotations;
import java.lang.reflect.Field; import java.lang.reflect.Field;
import java.lang.reflect.Method; import java.lang.reflect.Method;
import java.lang.reflect.Modifier; import java.lang.reflect.Modifier;
import java.util.Locale;
import javax.annotation.Resource; import javax.annotation.Resource;
import javax.naming.InitialContext; import javax.naming.InitialContext;
import javax.naming.NameNotFoundException; import javax.naming.NameNotFoundException;
@ -261,7 +262,7 @@ public class ResourceAnnotationHandler extends AbstractIntrospectableAnnotationH
//default name is the javabean property name //default name is the javabean property name
String name = method.getName().substring(3); String name = method.getName().substring(3);
name = name.substring(0,1).toLowerCase()+name.substring(1); name = name.substring(0,1).toLowerCase(Locale.ENGLISH)+name.substring(1);
name = clazz.getCanonicalName()+"/"+name; name = clazz.getCanonicalName()+"/"+name;
name = (resource.name()!=null && !resource.name().trim().equals("")? resource.name(): name); name = (resource.name()!=null && !resource.name().trim().equals("")? resource.name(): name);

View File

@ -79,14 +79,14 @@ public class AuthenticationProtocolHandler implements ProtocolHandler
public void onComplete(Result result) public void onComplete(Result result)
{ {
Request request = result.getRequest(); Request request = result.getRequest();
HttpConversation conversation = client.getConversation(request.getConversationID()); HttpConversation conversation = client.getConversation(request.getConversationID(), false);
Response.Listener listener = conversation.getExchanges().peekFirst().getResponseListener(); List<Response.ResponseListener> listeners = conversation.getExchanges().peekFirst().getResponseListeners();
ContentResponse response = new HttpContentResponse(result.getResponse(), getContent(), getEncoding()); ContentResponse response = new HttpContentResponse(result.getResponse(), getContent(), getEncoding());
if (result.isFailed()) if (result.isFailed())
{ {
Throwable failure = result.getFailure(); Throwable failure = result.getFailure();
LOG.debug("Authentication challenge failed {}", failure); LOG.debug("Authentication challenge failed {}", failure);
notifier.forwardFailureComplete(listener, request, result.getRequestFailure(), response, result.getResponseFailure()); notifier.forwardFailureComplete(listeners, request, result.getRequestFailure(), response, result.getResponseFailure());
return; return;
} }
@ -94,7 +94,7 @@ public class AuthenticationProtocolHandler implements ProtocolHandler
if (wwwAuthenticates.isEmpty()) if (wwwAuthenticates.isEmpty())
{ {
LOG.debug("Authentication challenge without WWW-Authenticate header"); LOG.debug("Authentication challenge without WWW-Authenticate header");
notifier.forwardFailureComplete(listener, request, null, response, new HttpResponseException("HTTP protocol violation: 401 without WWW-Authenticate header", response)); notifier.forwardFailureComplete(listeners, request, null, response, new HttpResponseException("HTTP protocol violation: 401 without WWW-Authenticate header", response));
return; return;
} }
@ -113,7 +113,7 @@ public class AuthenticationProtocolHandler implements ProtocolHandler
if (authentication == null) if (authentication == null)
{ {
LOG.debug("No authentication available for {}", request); LOG.debug("No authentication available for {}", request);
notifier.forwardSuccessComplete(listener, request, response); notifier.forwardSuccessComplete(listeners, request, response);
return; return;
} }
@ -121,19 +121,20 @@ public class AuthenticationProtocolHandler implements ProtocolHandler
LOG.debug("Authentication result {}", authnResult); LOG.debug("Authentication result {}", authnResult);
if (authnResult == null) if (authnResult == null)
{ {
notifier.forwardSuccessComplete(listener, request, response); notifier.forwardSuccessComplete(listeners, request, response);
return; return;
} }
authnResult.apply(request); Request newRequest = client.copyRequest(request, request.getURI());
request.send(new Response.Listener.Empty() authnResult.apply(newRequest);
newRequest.onResponseSuccess(new Response.SuccessListener()
{ {
@Override @Override
public void onSuccess(Response response) public void onSuccess(Response response)
{ {
client.getAuthenticationStore().addAuthenticationResult(authnResult); client.getAuthenticationStore().addAuthenticationResult(authnResult);
} }
}); }).send(null);
} }
private List<WWWAuthenticate> parseWWWAuthenticate(Response response) private List<WWWAuthenticate> parseWWWAuthenticate(Response response)

View File

@ -18,8 +18,11 @@
package org.eclipse.jetty.client; package org.eclipse.jetty.client;
import java.util.List;
import org.eclipse.jetty.client.api.Request; import org.eclipse.jetty.client.api.Request;
import org.eclipse.jetty.client.api.Response; import org.eclipse.jetty.client.api.Response;
import org.eclipse.jetty.client.api.Result;
import org.eclipse.jetty.client.util.BufferingResponseListener; import org.eclipse.jetty.client.util.BufferingResponseListener;
import org.eclipse.jetty.http.HttpHeader; import org.eclipse.jetty.http.HttpHeader;
import org.eclipse.jetty.http.HttpHeaderValue; import org.eclipse.jetty.http.HttpHeaderValue;
@ -41,7 +44,8 @@ public class ContinueProtocolHandler implements ProtocolHandler
public boolean accept(Request request, Response response) public boolean accept(Request request, Response response)
{ {
boolean expect100 = request.getHeaders().contains(HttpHeader.EXPECT, HttpHeaderValue.CONTINUE.asString()); boolean expect100 = request.getHeaders().contains(HttpHeader.EXPECT, HttpHeaderValue.CONTINUE.asString());
boolean handled100 = client.getConversation(request.getConversationID()).getAttribute(ATTRIBUTE) != null; HttpConversation conversation = client.getConversation(request.getConversationID(), false);
boolean handled100 = conversation != null && conversation.getAttribute(ATTRIBUTE) != null;
return expect100 && !handled100; return expect100 && !handled100;
} }
@ -60,20 +64,20 @@ public class ContinueProtocolHandler implements ProtocolHandler
// Handling of success must be done here and not from onComplete(), // Handling of success must be done here and not from onComplete(),
// since the onComplete() is not invoked because the request is not completed yet. // since the onComplete() is not invoked because the request is not completed yet.
HttpConversation conversation = client.getConversation(response.getConversationID()); HttpConversation conversation = client.getConversation(response.getConversationID(), false);
// Mark the 100 Continue response as handled // Mark the 100 Continue response as handled
conversation.setAttribute(ATTRIBUTE, Boolean.TRUE); conversation.setAttribute(ATTRIBUTE, Boolean.TRUE);
HttpExchange exchange = conversation.getExchanges().peekLast(); HttpExchange exchange = conversation.getExchanges().peekLast();
assert exchange.getResponse() == response; assert exchange.getResponse() == response;
Response.Listener listener = exchange.getResponseListener(); List<Response.ResponseListener> listeners = exchange.getResponseListeners();
switch (response.getStatus()) switch (response.getStatus())
{ {
case 100: case 100:
{ {
// All good, continue // All good, continue
exchange.resetResponse(true); exchange.resetResponse(true);
conversation.setResponseListener(listener); conversation.setResponseListeners(listeners);
exchange.proceed(true); exchange.proceed(true);
break; break;
} }
@ -81,8 +85,8 @@ public class ContinueProtocolHandler implements ProtocolHandler
{ {
// Server either does not support 100 Continue, or it does and wants to refuse the request content // Server either does not support 100 Continue, or it does and wants to refuse the request content
HttpContentResponse contentResponse = new HttpContentResponse(response, getContent(), getEncoding()); HttpContentResponse contentResponse = new HttpContentResponse(response, getContent(), getEncoding());
notifier.forwardSuccess(listener, contentResponse); notifier.forwardSuccess(listeners, contentResponse);
conversation.setResponseListener(listener); conversation.setResponseListeners(listeners);
exchange.proceed(false); exchange.proceed(false);
break; break;
} }
@ -92,15 +96,20 @@ public class ContinueProtocolHandler implements ProtocolHandler
@Override @Override
public void onFailure(Response response, Throwable failure) public void onFailure(Response response, Throwable failure)
{ {
HttpConversation conversation = client.getConversation(response.getConversationID()); HttpConversation conversation = client.getConversation(response.getConversationID(), false);
// Mark the 100 Continue response as handled // Mark the 100 Continue response as handled
conversation.setAttribute(ATTRIBUTE, Boolean.TRUE); conversation.setAttribute(ATTRIBUTE, Boolean.TRUE);
HttpExchange exchange = conversation.getExchanges().peekLast(); HttpExchange exchange = conversation.getExchanges().peekLast();
assert exchange.getResponse() == response; assert exchange.getResponse() == response;
Response.Listener listener = exchange.getResponseListener(); List<Response.ResponseListener> listeners = exchange.getResponseListeners();
HttpContentResponse contentResponse = new HttpContentResponse(response, getContent(), getEncoding()); HttpContentResponse contentResponse = new HttpContentResponse(response, getContent(), getEncoding());
notifier.forwardFailureComplete(listener, exchange.getRequest(), exchange.getRequestFailure(), contentResponse, failure); notifier.forwardFailureComplete(listeners, exchange.getRequest(), exchange.getRequestFailure(), contentResponse, failure);
}
@Override
public void onComplete(Result result)
{
} }
} }
} }

View File

@ -1,80 +0,0 @@
//
// ========================================================================
// Copyright (c) 1995-2012 Mort Bay Consulting Pty. Ltd.
// ------------------------------------------------------------------------
// All rights reserved. This program and the accompanying materials
// are made available under the terms of the Eclipse Public License v1.0
// and Apache License v2.0 which accompanies this distribution.
//
// The Eclipse Public License is available at
// http://www.eclipse.org/legal/epl-v10.html
//
// The Apache License v2.0 is available at
// http://www.opensource.org/licenses/apache2.0.php
//
// You may elect to redistribute this code under either of these licenses.
// ========================================================================
//
package org.eclipse.jetty.client;
import java.nio.ByteBuffer;
import org.eclipse.jetty.client.api.Response;
import org.eclipse.jetty.client.api.Result;
public class DoubleResponseListener implements Response.Listener
{
private final ResponseNotifier responseNotifier;
private final Response.Listener listener1;
private final Response.Listener listener2;
public DoubleResponseListener(ResponseNotifier responseNotifier, Response.Listener listener1, Response.Listener listener2)
{
this.responseNotifier = responseNotifier;
this.listener1 = listener1;
this.listener2 = listener2;
}
@Override
public void onBegin(Response response)
{
responseNotifier.notifyBegin(listener1, response);
responseNotifier.notifyBegin(listener2, response);
}
@Override
public void onHeaders(Response response)
{
responseNotifier.notifyHeaders(listener1, response);
responseNotifier.notifyHeaders(listener2, response);
}
@Override
public void onContent(Response response, ByteBuffer content)
{
responseNotifier.notifyContent(listener1, response, content);
responseNotifier.notifyContent(listener2, response, content);
}
@Override
public void onSuccess(Response response)
{
responseNotifier.notifySuccess(listener1, response);
responseNotifier.notifySuccess(listener2, response);
}
@Override
public void onFailure(Response response, Throwable failure)
{
responseNotifier.notifyFailure(listener1, response, failure);
responseNotifier.notifyFailure(listener2, response, failure);
}
@Override
public void onComplete(Result result)
{
responseNotifier.notifyComplete(listener1, result);
responseNotifier.notifyComplete(listener2, result);
}
}

View File

@ -30,6 +30,7 @@ import java.util.ArrayList;
import java.util.Arrays; import java.util.Arrays;
import java.util.Collections; import java.util.Collections;
import java.util.List; import java.util.List;
import java.util.Locale;
import java.util.Set; import java.util.Set;
import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap; import java.util.concurrent.ConcurrentMap;
@ -45,6 +46,8 @@ import org.eclipse.jetty.client.api.CookieStore;
import org.eclipse.jetty.client.api.Destination; import org.eclipse.jetty.client.api.Destination;
import org.eclipse.jetty.client.api.Request; import org.eclipse.jetty.client.api.Request;
import org.eclipse.jetty.client.api.Response; import org.eclipse.jetty.client.api.Response;
import org.eclipse.jetty.http.HttpFields;
import org.eclipse.jetty.http.HttpHeader;
import org.eclipse.jetty.http.HttpMethod; import org.eclipse.jetty.http.HttpMethod;
import org.eclipse.jetty.io.ByteBufferPool; import org.eclipse.jetty.io.ByteBufferPool;
import org.eclipse.jetty.io.EndPoint; import org.eclipse.jetty.io.EndPoint;
@ -86,7 +89,7 @@ import org.eclipse.jetty.util.thread.TimerScheduler;
* *
* // Asynchronously * // Asynchronously
* HttpClient client = new HttpClient(); * HttpClient client = new HttpClient();
* client.newRequest("http://localhost:8080").send(new Response.Listener.Adapter() * client.newRequest("http://localhost:8080").send(new Response.Listener.Empty()
* { * {
* &#64;Override * &#64;Override
* public void onSuccess(Response response) * public void onSuccess(Response response)
@ -265,9 +268,21 @@ public class HttpClient extends ContainerLifeCycle
return new HttpRequest(this, uri); return new HttpRequest(this, uri);
} }
protected Request newRequest(long id, String uri) protected Request copyRequest(Request oldRequest, String newURI)
{ {
return new HttpRequest(this, id, URI.create(uri)); Request newRequest = new HttpRequest(this, oldRequest.getConversationID(), URI.create(newURI));
newRequest.method(oldRequest.getMethod())
.version(oldRequest.getVersion())
.content(oldRequest.getContent());
for (HttpFields.Field header : oldRequest.getHeaders())
{
// We have a new URI, so skip the host header if present
if (HttpHeader.HOST == header.getHeader())
continue;
newRequest.header(header.getName(), header.getValue());
}
return newRequest;
} }
private String address(String scheme, String host, int port) private String address(String scheme, String host, int port)
@ -307,9 +322,9 @@ public class HttpClient extends ContainerLifeCycle
return new ArrayList<Destination>(destinations.values()); return new ArrayList<Destination>(destinations.values());
} }
protected void send(final Request request, Response.Listener listener) protected void send(final Request request, List<Response.ResponseListener> listeners)
{ {
String scheme = request.getScheme().toLowerCase(); String scheme = request.getScheme().toLowerCase(Locale.ENGLISH);
if (!Arrays.asList("http", "https").contains(scheme)) if (!Arrays.asList("http", "https").contains(scheme))
throw new IllegalArgumentException("Invalid protocol " + scheme); throw new IllegalArgumentException("Invalid protocol " + scheme);
@ -317,11 +332,12 @@ public class HttpClient extends ContainerLifeCycle
if (port < 0) if (port < 0)
port = "https".equals(scheme) ? 443 : 80; port = "https".equals(scheme) ? 443 : 80;
if (listener instanceof ResponseListener.Timed) for (Response.ResponseListener listener : listeners)
((ResponseListener.Timed)listener).schedule(scheduler); if (listener instanceof Schedulable)
((Schedulable)listener).schedule(scheduler);
HttpDestination destination = provideDestination(scheme, request.getHost(), port); HttpDestination destination = provideDestination(scheme, request.getHost(), port);
destination.send(request, listener); destination.send(request, listeners);
} }
protected void newConnection(HttpDestination destination, Callback<Connection> callback) protected void newConnection(HttpDestination destination, Callback<Connection> callback)
@ -365,10 +381,10 @@ public class HttpClient extends ContainerLifeCycle
} }
} }
protected HttpConversation getConversation(long id) protected HttpConversation getConversation(long id, boolean create)
{ {
HttpConversation conversation = conversations.get(id); HttpConversation conversation = conversations.get(id);
if (conversation == null) if (conversation == null && create)
{ {
conversation = new HttpConversation(this, id); conversation = new HttpConversation(this, id);
HttpConversation existing = conversations.putIfAbsent(id, conversation); HttpConversation existing = conversations.putIfAbsent(id, conversation);
@ -395,7 +411,7 @@ public class HttpClient extends ContainerLifeCycle
{ {
for (ProtocolHandler handler : getProtocolHandlers()) for (ProtocolHandler handler : getProtocolHandlers())
{ {
if (handler.accept(request, response)) if (handler.accept(request, response))
return handler; return handler;
} }
return null; return null;

View File

@ -21,6 +21,7 @@ package org.eclipse.jetty.client;
import java.io.UnsupportedEncodingException; import java.io.UnsupportedEncodingException;
import java.net.URLEncoder; import java.net.URLEncoder;
import java.nio.charset.UnsupportedCharsetException; import java.nio.charset.UnsupportedCharsetException;
import java.util.Collections;
import java.util.Enumeration; import java.util.Enumeration;
import java.util.Iterator; import java.util.Iterator;
import java.util.List; import java.util.List;
@ -102,7 +103,12 @@ public class HttpConnection extends AbstractConnection implements Connection
} }
@Override @Override
public void send(Request request, Response.Listener listener) public void send(Request request, Response.CompleteListener listener)
{
send(request, Collections.<Response.ResponseListener>singletonList(listener));
}
public void send(Request request, List<Response.ResponseListener> listeners)
{ {
normalizeRequest(request); normalizeRequest(request);
@ -111,13 +117,14 @@ public class HttpConnection extends AbstractConnection implements Connection
idleTimeout = endPoint.getIdleTimeout(); idleTimeout = endPoint.getIdleTimeout();
endPoint.setIdleTimeout(request.getIdleTimeout()); endPoint.setIdleTimeout(request.getIdleTimeout());
HttpConversation conversation = client.getConversation(request.getConversationID()); HttpConversation conversation = client.getConversation(request.getConversationID(), true);
HttpExchange exchange = new HttpExchange(conversation, this, request, listener); HttpExchange exchange = new HttpExchange(conversation, this, request, listeners);
setExchange(exchange); setExchange(exchange);
conversation.getExchanges().offer(exchange); conversation.getExchanges().offer(exchange);
if (listener instanceof ResponseListener.Timed) for (Response.ResponseListener listener : listeners)
((ResponseListener.Timed)listener).schedule(client.getScheduler()); if (listener instanceof Schedulable)
((Schedulable)listener).schedule(client.getScheduler());
sender.send(exchange); sender.send(exchange);
} }

View File

@ -20,6 +20,7 @@ package org.eclipse.jetty.client;
import java.io.UnsupportedEncodingException; import java.io.UnsupportedEncodingException;
import java.nio.charset.UnsupportedCharsetException; import java.nio.charset.UnsupportedCharsetException;
import java.util.List;
import org.eclipse.jetty.client.api.ContentResponse; import org.eclipse.jetty.client.api.ContentResponse;
import org.eclipse.jetty.client.api.Response; import org.eclipse.jetty.client.api.Response;
@ -46,9 +47,9 @@ public class HttpContentResponse implements ContentResponse
} }
@Override @Override
public Listener getListener() public <T extends ResponseListener> List<T> getListeners(Class<T> listenerClass)
{ {
return response.getListener(); return response.getListeners(listenerClass);
} }
@Override @Override

View File

@ -21,6 +21,7 @@ package org.eclipse.jetty.client;
import java.util.Collections; import java.util.Collections;
import java.util.Deque; import java.util.Deque;
import java.util.Enumeration; import java.util.Enumeration;
import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentLinkedDeque; import java.util.concurrent.ConcurrentLinkedDeque;
@ -34,8 +35,7 @@ public class HttpConversation implements Attributes
private final Deque<HttpExchange> exchanges = new ConcurrentLinkedDeque<>(); private final Deque<HttpExchange> exchanges = new ConcurrentLinkedDeque<>();
private final HttpClient client; private final HttpClient client;
private final long id; private final long id;
private volatile Response.Listener listener; private volatile List<Response.ResponseListener> listeners;
private volatile HttpExchange last;
public HttpConversation(HttpClient client, long id) public HttpConversation(HttpClient client, long id)
{ {
@ -53,35 +53,14 @@ public class HttpConversation implements Attributes
return exchanges; return exchanges;
} }
public Response.Listener getResponseListener() public List<Response.ResponseListener> getResponseListeners()
{ {
return listener; return listeners;
} }
public void setResponseListener(Response.Listener listener) public void setResponseListeners(List<Response.ResponseListener> listeners)
{ {
this.listener = listener; this.listeners = listeners;
}
/**
* @return the exchange that has been identified as the last of this conversation
* @see #last
*/
public HttpExchange getLastExchange()
{
return last;
}
/**
* Remembers the given {@code exchange} as the last of this conversation.
*
* @param exchange the exchange that is the last of this conversation
* @see #last
*/
public void setLastExchange(HttpExchange exchange)
{
if (last == null)
last = exchange;
} }
public void complete() public void complete()

View File

@ -44,7 +44,7 @@ public class HttpCookieParser
public static List<HttpCookie> parseCookies(String headerValue) public static List<HttpCookie> parseCookies(String headerValue)
{ {
if (headerValue.toLowerCase().contains("expires=")) if (headerValue.toLowerCase(Locale.ENGLISH).contains("expires="))
{ {
HttpCookie cookie = parseCookie(headerValue, 0); HttpCookie cookie = parseCookie(headerValue, 0);
if (cookie != null) if (cookie != null)
@ -111,7 +111,7 @@ public class HttpCookieParser
try try
{ {
String[] attributeParts = cookieParts[i].split("=", 2); String[] attributeParts = cookieParts[i].split("=", 2);
String attributeName = attributeParts[0].trim().toLowerCase(); String attributeName = attributeParts[0].trim().toLowerCase(Locale.ENGLISH);
String attributeValue = attributeParts.length < 2 ? "" : attributeParts[1].trim(); String attributeValue = attributeParts.length < 2 ? "" : attributeParts[1].trim();
switch (attributeName) switch (attributeName)
{ {

View File

@ -50,7 +50,7 @@ public class HttpDestination implements Destination, AutoCloseable, Dumpable
private final String scheme; private final String scheme;
private final String host; private final String host;
private final int port; private final int port;
private final Queue<RequestPair> requests; private final Queue<RequestContext> requests;
private final BlockingQueue<Connection> idleConnections; private final BlockingQueue<Connection> idleConnections;
private final BlockingQueue<Connection> activeConnections; private final BlockingQueue<Connection> activeConnections;
private final RequestNotifier requestNotifier; private final RequestNotifier requestNotifier;
@ -97,7 +97,7 @@ public class HttpDestination implements Destination, AutoCloseable, Dumpable
return port; return port;
} }
public void send(Request request, Response.Listener listener) public void send(Request request, List<Response.ResponseListener> listeners)
{ {
if (!scheme.equals(request.getScheme())) if (!scheme.equals(request.getScheme()))
throw new IllegalArgumentException("Invalid request scheme " + request.getScheme() + " for destination " + this); throw new IllegalArgumentException("Invalid request scheme " + request.getScheme() + " for destination " + this);
@ -107,12 +107,12 @@ public class HttpDestination implements Destination, AutoCloseable, Dumpable
if (port >= 0 && this.port != port) if (port >= 0 && this.port != port)
throw new IllegalArgumentException("Invalid request port " + port + " for destination " + this); throw new IllegalArgumentException("Invalid request port " + port + " for destination " + this);
RequestPair requestPair = new RequestPair(request, listener); RequestContext requestContext = new RequestContext(request, listeners);
if (client.isRunning()) if (client.isRunning())
{ {
if (requests.offer(requestPair)) if (requests.offer(requestContext))
{ {
if (!client.isRunning() && requests.remove(requestPair)) if (!client.isRunning() && requests.remove(requestContext))
{ {
throw new RejectedExecutionException(client + " is stopping"); throw new RejectedExecutionException(client + " is stopping");
} }
@ -202,15 +202,15 @@ public class HttpDestination implements Destination, AutoCloseable, Dumpable
private void drain(Throwable x) private void drain(Throwable x)
{ {
RequestPair pair; RequestContext requestContext;
while ((pair = requests.poll()) != null) while ((requestContext = requests.poll()) != null)
{ {
Request request = pair.request; Request request = requestContext.request;
requestNotifier.notifyFailure(request, x); requestNotifier.notifyFailure(request, x);
Response.Listener listener = pair.listener; List<Response.ResponseListener> listeners = requestContext.listeners;
HttpResponse response = new HttpResponse(request, listener); HttpResponse response = new HttpResponse(request, listeners);
responseNotifier.notifyFailure(listener, response, x); responseNotifier.notifyFailure(listeners, response, x);
responseNotifier.notifyComplete(listener, new Result(request, x, response, x)); responseNotifier.notifyComplete(listeners, new Result(request, x, response, x));
} }
} }
@ -223,37 +223,40 @@ public class HttpDestination implements Destination, AutoCloseable, Dumpable
* *
* @param connection the new connection * @param connection the new connection
*/ */
protected void process(final Connection connection, boolean dispatch) protected void process(Connection connection, boolean dispatch)
{ {
RequestPair requestPair = requests.poll(); // Ugly cast, but lack of generic reification forces it
if (requestPair == null) final HttpConnection httpConnection = (HttpConnection)connection;
RequestContext requestContext = requests.poll();
if (requestContext == null)
{ {
LOG.debug("{} idle", connection); LOG.debug("{} idle", httpConnection);
if (!idleConnections.offer(connection)) if (!idleConnections.offer(httpConnection))
{ {
LOG.debug("{} idle overflow"); LOG.debug("{} idle overflow");
connection.close(); httpConnection.close();
} }
if (!client.isRunning()) if (!client.isRunning())
{ {
LOG.debug("{} is stopping", client); LOG.debug("{} is stopping", client);
remove(connection); remove(httpConnection);
connection.close(); httpConnection.close();
} }
} }
else else
{ {
final Request request = requestPair.request; final Request request = requestContext.request;
final Response.Listener listener = requestPair.listener; final List<Response.ResponseListener> listeners = requestContext.listeners;
if (request.aborted()) if (request.isAborted())
{ {
abort(request, listener, "Aborted"); abort(request, listeners, "Aborted");
LOG.debug("Aborted {} before processing", request); LOG.debug("Aborted {} before processing", request);
} }
else else
{ {
LOG.debug("{} active", connection); LOG.debug("{} active", httpConnection);
if (!activeConnections.offer(connection)) if (!activeConnections.offer(httpConnection))
{ {
LOG.warn("{} active overflow"); LOG.warn("{} active overflow");
} }
@ -264,13 +267,13 @@ public class HttpDestination implements Destination, AutoCloseable, Dumpable
@Override @Override
public void run() public void run()
{ {
connection.send(request, listener); httpConnection.send(request, listeners);
} }
}); });
} }
else else
{ {
connection.send(request, listener); httpConnection.send(request, listeners);
} }
} }
} }
@ -333,14 +336,14 @@ public class HttpDestination implements Destination, AutoCloseable, Dumpable
public boolean abort(Request request, String reason) public boolean abort(Request request, String reason)
{ {
for (RequestPair pair : requests) for (RequestContext requestContext : requests)
{ {
if (pair.request == request) if (requestContext.request == request)
{ {
if (requests.remove(pair)) if (requests.remove(requestContext))
{ {
// We were able to remove the pair, so it won't be processed // We were able to remove the pair, so it won't be processed
abort(request, pair.listener, reason); abort(request, requestContext.listeners, reason);
LOG.debug("Aborted {} while queued", request); LOG.debug("Aborted {} while queued", request);
return true; return true;
} }
@ -349,13 +352,13 @@ public class HttpDestination implements Destination, AutoCloseable, Dumpable
return false; return false;
} }
private void abort(Request request, Response.Listener listener, String reason) private void abort(Request request, List<Response.ResponseListener> listeners, String reason)
{ {
HttpResponse response = new HttpResponse(request, listener); HttpResponse response = new HttpResponse(request, listeners);
HttpResponseException responseFailure = new HttpResponseException(reason, response); HttpResponseException responseFailure = new HttpResponseException(reason, response);
responseNotifier.notifyFailure(listener, response, responseFailure); responseNotifier.notifyFailure(listeners, response, responseFailure);
HttpRequestException requestFailure = new HttpRequestException(reason, request); HttpRequestException requestFailure = new HttpRequestException(reason, request);
responseNotifier.notifyComplete(listener, new Result(request, requestFailure, response, responseFailure)); responseNotifier.notifyComplete(listeners, new Result(request, requestFailure, response, responseFailure));
} }
@Override @Override
@ -382,15 +385,15 @@ public class HttpDestination implements Destination, AutoCloseable, Dumpable
return String.format("%s(%s://%s:%d)", HttpDestination.class.getSimpleName(), getScheme(), getHost(), getPort()); return String.format("%s(%s://%s:%d)", HttpDestination.class.getSimpleName(), getScheme(), getHost(), getPort());
} }
private static class RequestPair private static class RequestContext
{ {
private final Request request; private final Request request;
private final Response.Listener listener; private final List<Response.ResponseListener> listeners;
private RequestPair(Request request, Response.Listener listener) private RequestContext(Request request, List<Response.ResponseListener> listeners)
{ {
this.request = request; this.request = request;
this.listener = listener; this.listeners = listeners;
} }
} }
} }

View File

@ -18,6 +18,7 @@
package org.eclipse.jetty.client; package org.eclipse.jetty.client;
import java.util.List;
import java.util.concurrent.CountDownLatch; import java.util.concurrent.CountDownLatch;
import java.util.concurrent.atomic.AtomicInteger; import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.atomic.AtomicMarkableReference; import java.util.concurrent.atomic.AtomicMarkableReference;
@ -37,18 +38,19 @@ public class HttpExchange
private final HttpConversation conversation; private final HttpConversation conversation;
private final HttpConnection connection; private final HttpConnection connection;
private final Request request; private final Request request;
private final Response.Listener listener; private final List<Response.ResponseListener> listeners;
private final HttpResponse response; private final HttpResponse response;
private volatile boolean last;
private volatile Throwable requestFailure; private volatile Throwable requestFailure;
private volatile Throwable responseFailure; private volatile Throwable responseFailure;
public HttpExchange(HttpConversation conversation, HttpConnection connection, Request request, Response.Listener listener) public HttpExchange(HttpConversation conversation, HttpConnection connection, Request request, List<Response.ResponseListener> listeners)
{ {
this.conversation = conversation; this.conversation = conversation;
this.connection = connection; this.connection = connection;
this.request = request; this.request = request;
this.listener = listener; this.listeners = listeners;
this.response = new HttpResponse(request, listener); this.response = new HttpResponse(request, listeners);
} }
public HttpConversation getConversation() public HttpConversation getConversation()
@ -66,9 +68,9 @@ public class HttpExchange
return requestFailure; return requestFailure;
} }
public Response.Listener getResponseListener() public List<Response.ResponseListener> getResponseListeners()
{ {
return listener; return listeners;
} }
public HttpResponse getResponse() public HttpResponse getResponse()
@ -81,6 +83,22 @@ public class HttpExchange
return responseFailure; return responseFailure;
} }
/**
* @return whether this exchange is the last in the conversation
*/
public boolean isLast()
{
return last;
}
/**
* @param last whether this exchange is the last in the conversation
*/
public void setLast(boolean last)
{
this.last = last;
}
public void receive() public void receive()
{ {
connection.receive(); connection.receive();
@ -159,12 +177,13 @@ public class HttpExchange
{ {
// Request and response completed // Request and response completed
LOG.debug("{} complete", this); LOG.debug("{} complete", this);
if (conversation.getLastExchange() == this) if (isLast())
{ {
HttpExchange first = conversation.getExchanges().peekFirst(); HttpExchange first = conversation.getExchanges().peekFirst();
Response.Listener listener = first.getResponseListener(); List<Response.ResponseListener> listeners = first.getResponseListeners();
if (listener instanceof ResponseListener.Timed) for (Response.ResponseListener listener : listeners)
((ResponseListener.Timed)listener).cancel(); if (listener instanceof Schedulable)
((Schedulable)listener).cancel();
conversation.complete(); conversation.complete();
} }
} }

View File

@ -20,8 +20,11 @@ package org.eclipse.jetty.client;
import java.io.EOFException; import java.io.EOFException;
import java.nio.ByteBuffer; import java.nio.ByteBuffer;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Enumeration; import java.util.Enumeration;
import java.util.List; import java.util.List;
import java.util.Locale;
import java.util.concurrent.TimeoutException; import java.util.concurrent.TimeoutException;
import java.util.concurrent.atomic.AtomicMarkableReference; import java.util.concurrent.atomic.AtomicMarkableReference;
import java.util.concurrent.atomic.AtomicReference; import java.util.concurrent.atomic.AtomicReference;
@ -139,30 +142,41 @@ public class HttpReceiver implements HttpParser.ResponseHandler<ByteBuffer>
response.version(version).status(status).reason(reason); response.version(version).status(status).reason(reason);
// Probe the protocol handlers // Probe the protocol handlers
Response.Listener currentListener = exchange.getResponseListener(); HttpExchange initialExchange = conversation.getExchanges().peekFirst();
Response.Listener initialListener = conversation.getExchanges().peekFirst().getResponseListener();
HttpClient client = connection.getHttpClient(); HttpClient client = connection.getHttpClient();
ProtocolHandler protocolHandler = client.findProtocolHandler(exchange.getRequest(), response); ProtocolHandler protocolHandler = client.findProtocolHandler(exchange.getRequest(), response);
Response.Listener handlerListener = protocolHandler == null ? null : protocolHandler.getResponseListener(); Response.Listener handlerListener = protocolHandler == null ? null : protocolHandler.getResponseListener();
if (handlerListener == null) if (handlerListener == null)
{ {
conversation.setLastExchange(exchange); exchange.setLast(true);
if (currentListener == initialListener) if (initialExchange == exchange)
conversation.setResponseListener(initialListener); {
conversation.setResponseListeners(exchange.getResponseListeners());
}
else else
conversation.setResponseListener(new DoubleResponseListener(responseNotifier, currentListener, initialListener)); {
List<Response.ResponseListener> listeners = new ArrayList<>(exchange.getResponseListeners());
listeners.addAll(initialExchange.getResponseListeners());
conversation.setResponseListeners(listeners);
}
} }
else else
{ {
LOG.debug("Found protocol handler {}", protocolHandler); LOG.debug("Found protocol handler {}", protocolHandler);
if (currentListener == initialListener) if (initialExchange == exchange)
conversation.setResponseListener(handlerListener); {
conversation.setResponseListeners(Collections.<Response.ResponseListener>singletonList(handlerListener));
}
else else
conversation.setResponseListener(new DoubleResponseListener(responseNotifier, currentListener, handlerListener)); {
List<Response.ResponseListener> listeners = new ArrayList<>(exchange.getResponseListeners());
listeners.add(handlerListener);
conversation.setResponseListeners(listeners);
}
} }
LOG.debug("Receiving {}", response); LOG.debug("Receiving {}", response);
responseNotifier.notifyBegin(conversation.getResponseListener(), response); responseNotifier.notifyBegin(conversation.getResponseListeners(), response);
} }
} }
return false; return false;
@ -178,7 +192,7 @@ public class HttpReceiver implements HttpParser.ResponseHandler<ByteBuffer>
if (exchange != null) if (exchange != null)
{ {
exchange.getResponse().getHeaders().add(name, value); exchange.getResponse().getHeaders().add(name, value);
switch (name.toLowerCase()) switch (name.toLowerCase(Locale.ENGLISH))
{ {
case "set-cookie": case "set-cookie":
case "set-cookie2": case "set-cookie2":
@ -212,7 +226,7 @@ public class HttpReceiver implements HttpParser.ResponseHandler<ByteBuffer>
HttpConversation conversation = exchange.getConversation(); HttpConversation conversation = exchange.getConversation();
HttpResponse response = exchange.getResponse(); HttpResponse response = exchange.getResponse();
LOG.debug("Headers {}", response); LOG.debug("Headers {}", response);
responseNotifier.notifyHeaders(conversation.getResponseListener(), response); responseNotifier.notifyHeaders(conversation.getResponseListeners(), response);
Enumeration<String> contentEncodings = response.getHeaders().getValues(HttpHeader.CONTENT_ENCODING.asString(), ","); Enumeration<String> contentEncodings = response.getHeaders().getValues(HttpHeader.CONTENT_ENCODING.asString(), ",");
if (contentEncodings != null) if (contentEncodings != null)
@ -254,7 +268,7 @@ public class HttpReceiver implements HttpParser.ResponseHandler<ByteBuffer>
LOG.debug("{} {}: {} bytes", decoder, response, buffer.remaining()); LOG.debug("{} {}: {} bytes", decoder, response, buffer.remaining());
} }
responseNotifier.notifyContent(conversation.getResponseListener(), response, buffer); responseNotifier.notifyContent(conversation.getResponseListeners(), response, buffer);
} }
} }
return false; return false;
@ -287,8 +301,8 @@ public class HttpReceiver implements HttpParser.ResponseHandler<ByteBuffer>
exchange.terminateResponse(); exchange.terminateResponse();
HttpResponse response = exchange.getResponse(); HttpResponse response = exchange.getResponse();
Response.Listener listener = exchange.getConversation().getResponseListener(); List<Response.ResponseListener> listeners = exchange.getConversation().getResponseListeners();
responseNotifier.notifySuccess(listener, response); responseNotifier.notifySuccess(listeners, response);
LOG.debug("Received {}", response); LOG.debug("Received {}", response);
Result result = completion.getReference(); Result result = completion.getReference();
@ -296,7 +310,7 @@ public class HttpReceiver implements HttpParser.ResponseHandler<ByteBuffer>
{ {
connection.complete(exchange, !result.isFailed()); connection.complete(exchange, !result.isFailed());
responseNotifier.notifyComplete(listener, result); responseNotifier.notifyComplete(listeners, result);
} }
return true; return true;
@ -330,7 +344,7 @@ public class HttpReceiver implements HttpParser.ResponseHandler<ByteBuffer>
HttpResponse response = exchange.getResponse(); HttpResponse response = exchange.getResponse();
HttpConversation conversation = exchange.getConversation(); HttpConversation conversation = exchange.getConversation();
responseNotifier.notifyFailure(conversation.getResponseListener(), response, failure); responseNotifier.notifyFailure(conversation.getResponseListeners(), response, failure);
LOG.debug("Failed {} {}", response, failure); LOG.debug("Failed {} {}", response, failure);
Result result = completion.getReference(); Result result = completion.getReference();
@ -338,7 +352,7 @@ public class HttpReceiver implements HttpParser.ResponseHandler<ByteBuffer>
{ {
connection.complete(exchange, false); connection.complete(exchange, false);
responseNotifier.notifyComplete(conversation.getResponseListener(), result); responseNotifier.notifyComplete(conversation.getResponseListeners(), result);
} }
return true; return true;

View File

@ -50,7 +50,8 @@ public class HttpRequest implements Request
private final HttpFields headers = new HttpFields(); private final HttpFields headers = new HttpFields();
private final Fields params = new Fields(); private final Fields params = new Fields();
private final Map<String, Object> attributes = new HashMap<>(); private final Map<String, Object> attributes = new HashMap<>();
private final List<Listener> listeners = new ArrayList<>(); private final List<RequestListener> requestListeners = new ArrayList<>();
private final List<Response.ResponseListener> responseListeners = new ArrayList<>();
private final HttpClient client; private final HttpClient client;
private final long conversation; private final long conversation;
private final String host; private final String host;
@ -240,15 +241,89 @@ public class HttpRequest implements Request
} }
@Override @Override
public List<Listener> getListeners() public <T extends RequestListener> List<T> getRequestListeners(Class<T> type)
{ {
return listeners; ArrayList<T> result = new ArrayList<>();
for (RequestListener listener : requestListeners)
if (type == null || type.isInstance(listener))
result.add((T)listener);
return result;
} }
@Override @Override
public Request listener(Request.Listener listener) public Request listener(Request.Listener listener)
{ {
this.listeners.add(listener); this.requestListeners.add(listener);
return this;
}
@Override
public Request onRequestQueued(QueuedListener listener)
{
this.requestListeners.add(listener);
return this;
}
@Override
public Request onRequestBegin(BeginListener listener)
{
this.requestListeners.add(listener);
return this;
}
@Override
public Request onRequestHeaders(HeadersListener listener)
{
this.requestListeners.add(listener);
return this;
}
@Override
public Request onRequestSuccess(SuccessListener listener)
{
this.requestListeners.add(listener);
return this;
}
@Override
public Request onRequestFailure(FailureListener listener)
{
this.requestListeners.add(listener);
return this;
}
@Override
public Request onResponseBegin(Response.BeginListener listener)
{
this.responseListeners.add(listener);
return this;
}
@Override
public Request onResponseHeaders(Response.HeadersListener listener)
{
this.responseListeners.add(listener);
return this;
}
@Override
public Request onResponseContent(Response.ContentListener listener)
{
this.responseListeners.add(listener);
return this;
}
@Override
public Request onResponseSuccess(Response.SuccessListener listener)
{
this.responseListeners.add(listener);
return this;
}
@Override
public Request onResponseFailure(Response.FailureListener listener)
{
this.responseListeners.add(listener);
return this; return this;
} }
@ -320,9 +395,11 @@ public class HttpRequest implements Request
} }
@Override @Override
public void send(final Response.Listener listener) public void send(Response.CompleteListener listener)
{ {
client.send(this, listener); if (listener != null)
responseListeners.add(listener);
client.send(this, responseListeners);
} }
@Override @Override
@ -331,12 +408,12 @@ public class HttpRequest implements Request
aborted = true; aborted = true;
if (client.provideDestination(getScheme(), getHost(), getPort()).abort(this, reason)) if (client.provideDestination(getScheme(), getHost(), getPort()).abort(this, reason))
return true; return true;
HttpConversation conversation = client.getConversation(getConversationID()); HttpConversation conversation = client.getConversation(getConversationID(), false);
return conversation.abort(reason); return conversation != null && conversation.abort(reason);
} }
@Override @Override
public boolean aborted() public boolean isAborted()
{ {
return aborted; return aborted;
} }

View File

@ -18,6 +18,9 @@
package org.eclipse.jetty.client; package org.eclipse.jetty.client;
import java.util.ArrayList;
import java.util.List;
import org.eclipse.jetty.client.api.Request; import org.eclipse.jetty.client.api.Request;
import org.eclipse.jetty.client.api.Response; import org.eclipse.jetty.client.api.Response;
import org.eclipse.jetty.http.HttpFields; import org.eclipse.jetty.http.HttpFields;
@ -27,15 +30,15 @@ public class HttpResponse implements Response
{ {
private final HttpFields headers = new HttpFields(); private final HttpFields headers = new HttpFields();
private final Request request; private final Request request;
private final Listener listener; private final List<ResponseListener> listeners;
private HttpVersion version; private HttpVersion version;
private int status; private int status;
private String reason; private String reason;
public HttpResponse(Request request, Listener listener) public HttpResponse(Request request, List<ResponseListener> listeners)
{ {
this.request = request; this.request = request;
this.listener = listener; this.listeners = listeners;
} }
public HttpVersion getVersion() public HttpVersion getVersion()
@ -85,9 +88,13 @@ public class HttpResponse implements Response
} }
@Override @Override
public Listener getListener() public <T extends ResponseListener> List<T> getListeners(Class<T> type)
{ {
return listener; ArrayList<T> result = new ArrayList<>();
for (ResponseListener listener : listeners)
if (type == null || type.isInstance(listener))
result.add((T)listener);
return result;
} }
@Override @Override

View File

@ -19,8 +19,10 @@
package org.eclipse.jetty.client; package org.eclipse.jetty.client;
import java.nio.ByteBuffer; import java.nio.ByteBuffer;
import java.util.ArrayList;
import java.util.Collections; import java.util.Collections;
import java.util.Iterator; import java.util.Iterator;
import java.util.List;
import java.util.concurrent.CountDownLatch; import java.util.concurrent.CountDownLatch;
import java.util.concurrent.Executor; import java.util.concurrent.Executor;
import java.util.concurrent.atomic.AtomicMarkableReference; import java.util.concurrent.atomic.AtomicMarkableReference;
@ -67,15 +69,20 @@ public class HttpSender
// Arrange the listeners, so that if there is a request failure the proper listeners are notified // Arrange the listeners, so that if there is a request failure the proper listeners are notified
HttpConversation conversation = exchange.getConversation(); HttpConversation conversation = exchange.getConversation();
Response.Listener currentListener = exchange.getResponseListener(); HttpExchange initialExchange = conversation.getExchanges().peekFirst();
Response.Listener initialListener = conversation.getExchanges().peekFirst().getResponseListener(); if (initialExchange == exchange)
if (initialListener == currentListener) {
conversation.setResponseListener(initialListener); conversation.setResponseListeners(exchange.getResponseListeners());
}
else else
conversation.setResponseListener(new DoubleResponseListener(responseNotifier, currentListener, initialListener)); {
List<Response.ResponseListener> listeners = new ArrayList<>(exchange.getResponseListeners());
listeners.addAll(initialExchange.getResponseListeners());
conversation.setResponseListeners(listeners);
}
Request request = exchange.getRequest(); Request request = exchange.getRequest();
if (request.aborted()) if (request.isAborted())
{ {
exchange.abort(null); exchange.abort(null);
} }
@ -123,7 +130,7 @@ public class HttpSender
return; return;
final Request request = exchange.getRequest(); final Request request = exchange.getRequest();
HttpConversation conversation = client.getConversation(request.getConversationID()); HttpConversation conversation = exchange.getConversation();
HttpGenerator.RequestInfo requestInfo = null; HttpGenerator.RequestInfo requestInfo = null;
boolean expect100 = request.getHeaders().contains(HttpHeader.EXPECT, HttpHeaderValue.CONTINUE.asString()); boolean expect100 = request.getHeaders().contains(HttpHeader.EXPECT, HttpHeaderValue.CONTINUE.asString());
@ -359,7 +366,7 @@ public class HttpSender
connection.complete(exchange, !result.isFailed()); connection.complete(exchange, !result.isFailed());
HttpConversation conversation = exchange.getConversation(); HttpConversation conversation = exchange.getConversation();
responseNotifier.notifyComplete(conversation.getResponseListener(), result); responseNotifier.notifyComplete(conversation.getResponseListeners(), result);
} }
return true; return true;
@ -393,7 +400,7 @@ public class HttpSender
Result result = completion.getReference(); Result result = completion.getReference();
boolean notCommitted = current == State.IDLE || current == State.SEND; boolean notCommitted = current == State.IDLE || current == State.SEND;
if (result == null && notCommitted && !request.aborted()) if (result == null && notCommitted && !request.isAborted())
{ {
result = exchange.responseComplete(failure).getReference(); result = exchange.responseComplete(failure).getReference();
exchange.terminateResponse(); exchange.terminateResponse();
@ -405,7 +412,7 @@ public class HttpSender
connection.complete(exchange, false); connection.complete(exchange, false);
HttpConversation conversation = exchange.getConversation(); HttpConversation conversation = exchange.getConversation();
responseNotifier.notifyComplete(conversation.getResponseListener(), result); responseNotifier.notifyComplete(conversation.getResponseListeners(), result);
} }
return true; return true;

View File

@ -18,10 +18,11 @@
package org.eclipse.jetty.client; package org.eclipse.jetty.client;
import java.util.List;
import org.eclipse.jetty.client.api.Request; import org.eclipse.jetty.client.api.Request;
import org.eclipse.jetty.client.api.Response; import org.eclipse.jetty.client.api.Response;
import org.eclipse.jetty.client.api.Result; import org.eclipse.jetty.client.api.Result;
import org.eclipse.jetty.http.HttpFields;
import org.eclipse.jetty.http.HttpMethod; import org.eclipse.jetty.http.HttpMethod;
public class RedirectProtocolHandler extends Response.Listener.Empty implements ProtocolHandler public class RedirectProtocolHandler extends Response.Listener.Empty implements ProtocolHandler
@ -105,7 +106,7 @@ public class RedirectProtocolHandler extends Response.Listener.Empty implements
private void redirect(Result result, HttpMethod method, String location) private void redirect(Result result, HttpMethod method, String location)
{ {
final Request request = result.getRequest(); final Request request = result.getRequest();
HttpConversation conversation = client.getConversation(request.getConversationID()); HttpConversation conversation = client.getConversation(request.getConversationID(), false);
Integer redirects = (Integer)conversation.getAttribute(ATTRIBUTE); Integer redirects = (Integer)conversation.getAttribute(ATTRIBUTE);
if (redirects == null) if (redirects == null)
redirects = 0; redirects = 0;
@ -115,31 +116,22 @@ public class RedirectProtocolHandler extends Response.Listener.Empty implements
++redirects; ++redirects;
conversation.setAttribute(ATTRIBUTE, redirects); conversation.setAttribute(ATTRIBUTE, redirects);
Request redirect = client.newRequest(request.getConversationID(), location); Request redirect = client.copyRequest(request, location);
// Use given method // Use given method
redirect.method(method); redirect.method(method);
redirect.version(request.getVersion()); redirect.onRequestBegin(new Request.BeginListener()
// Copy headers
for (HttpFields.Field header : request.getHeaders())
redirect.header(header.getName(), header.getValue());
// Copy content
redirect.content(request.getContent());
redirect.listener(new Request.Listener.Empty()
{ {
@Override @Override
public void onBegin(Request redirect) public void onBegin(Request redirect)
{ {
if (request.aborted()) if (request.isAborted())
redirect.abort(null); redirect.abort(null);
} }
}); });
redirect.send(new Response.Listener.Empty()); redirect.send(null);
} }
else else
{ {
@ -151,10 +143,10 @@ public class RedirectProtocolHandler extends Response.Listener.Empty implements
{ {
Request request = result.getRequest(); Request request = result.getRequest();
Response response = result.getResponse(); Response response = result.getResponse();
HttpConversation conversation = client.getConversation(request.getConversationID()); HttpConversation conversation = client.getConversation(request.getConversationID(), false);
Response.Listener listener = conversation.getExchanges().peekFirst().getResponseListener(); List<Response.ResponseListener> listeners = conversation.getExchanges().peekFirst().getResponseListeners();
// TODO: should we replay all events, or just the failure ? // TODO: should we replay all events, or just the failure ?
notifier.notifyFailure(listener, response, failure); notifier.notifyFailure(listeners, response, failure);
notifier.notifyComplete(listener, new Result(request, response, failure)); notifier.notifyComplete(listeners, new Result(request, response, failure));
} }
} }

View File

@ -35,13 +35,13 @@ public class RequestNotifier
public void notifyQueued(Request request) public void notifyQueued(Request request)
{ {
for (Request.Listener listener : request.getListeners()) for (Request.QueuedListener listener : request.getRequestListeners(Request.QueuedListener.class))
notifyQueued(listener, request); notifyQueued(listener, request);
for (Request.Listener listener : client.getRequestListeners()) for (Request.Listener listener : client.getRequestListeners())
notifyQueued(listener, request); notifyQueued(listener, request);
} }
private void notifyQueued(Request.Listener listener, Request request) private void notifyQueued(Request.QueuedListener listener, Request request)
{ {
try try
{ {
@ -56,13 +56,13 @@ public class RequestNotifier
public void notifyBegin(Request request) public void notifyBegin(Request request)
{ {
for (Request.Listener listener : request.getListeners()) for (Request.BeginListener listener : request.getRequestListeners(Request.BeginListener.class))
notifyBegin(listener, request); notifyBegin(listener, request);
for (Request.Listener listener : client.getRequestListeners()) for (Request.Listener listener : client.getRequestListeners())
notifyBegin(listener, request); notifyBegin(listener, request);
} }
private void notifyBegin(Request.Listener listener, Request request) private void notifyBegin(Request.BeginListener listener, Request request)
{ {
try try
{ {
@ -77,13 +77,13 @@ public class RequestNotifier
public void notifyHeaders(Request request) public void notifyHeaders(Request request)
{ {
for (Request.Listener listener : request.getListeners()) for (Request.HeadersListener listener : request.getRequestListeners(Request.HeadersListener.class))
notifyHeaders(listener, request); notifyHeaders(listener, request);
for (Request.Listener listener : client.getRequestListeners()) for (Request.Listener listener : client.getRequestListeners())
notifyHeaders(listener, request); notifyHeaders(listener, request);
} }
private void notifyHeaders(Request.Listener listener, Request request) private void notifyHeaders(Request.HeadersListener listener, Request request)
{ {
try try
{ {
@ -98,13 +98,13 @@ public class RequestNotifier
public void notifySuccess(Request request) public void notifySuccess(Request request)
{ {
for (Request.Listener listener : request.getListeners()) for (Request.SuccessListener listener : request.getRequestListeners(Request.SuccessListener.class))
notifySuccess(listener, request); notifySuccess(listener, request);
for (Request.Listener listener : client.getRequestListeners()) for (Request.Listener listener : client.getRequestListeners())
notifySuccess(listener, request); notifySuccess(listener, request);
} }
private void notifySuccess(Request.Listener listener, Request request) private void notifySuccess(Request.SuccessListener listener, Request request)
{ {
try try
{ {
@ -119,13 +119,13 @@ public class RequestNotifier
public void notifyFailure(Request request, Throwable failure) public void notifyFailure(Request request, Throwable failure)
{ {
for (Request.Listener listener : request.getListeners()) for (Request.FailureListener listener : request.getRequestListeners(Request.FailureListener.class))
notifyFailure(listener, request, failure); notifyFailure(listener, request, failure);
for (Request.Listener listener : client.getRequestListeners()) for (Request.Listener listener : client.getRequestListeners())
notifyFailure(listener, request, failure); notifyFailure(listener, request, failure);
} }
private void notifyFailure(Request.Listener listener, Request request, Throwable failure) private void notifyFailure(Request.FailureListener listener, Request request, Throwable failure)
{ {
try try
{ {

View File

@ -19,6 +19,7 @@
package org.eclipse.jetty.client; package org.eclipse.jetty.client;
import java.nio.ByteBuffer; import java.nio.ByteBuffer;
import java.util.List;
import org.eclipse.jetty.client.api.ContentResponse; import org.eclipse.jetty.client.api.ContentResponse;
import org.eclipse.jetty.client.api.Request; import org.eclipse.jetty.client.api.Request;
@ -37,12 +38,18 @@ public class ResponseNotifier
this.client = client; this.client = client;
} }
public void notifyBegin(Response.Listener listener, Response response) public void notifyBegin(List<Response.ResponseListener> listeners, Response response)
{
for (Response.ResponseListener listener : listeners)
if (listener instanceof Response.BeginListener)
notifyBegin((Response.BeginListener)listener, response);
}
private void notifyBegin(Response.BeginListener listener, Response response)
{ {
try try
{ {
if (listener != null) listener.onBegin(response);
listener.onBegin(response);
} }
catch (Exception x) catch (Exception x)
{ {
@ -50,12 +57,18 @@ public class ResponseNotifier
} }
} }
public void notifyHeaders(Response.Listener listener, Response response) public void notifyHeaders(List<Response.ResponseListener> listeners, Response response)
{
for (Response.ResponseListener listener : listeners)
if (listener instanceof Response.HeadersListener)
notifyHeaders((Response.HeadersListener)listener, response);
}
private void notifyHeaders(Response.HeadersListener listener, Response response)
{ {
try try
{ {
if (listener != null) listener.onHeaders(response);
listener.onHeaders(response);
} }
catch (Exception x) catch (Exception x)
{ {
@ -63,12 +76,19 @@ public class ResponseNotifier
} }
} }
public void notifyContent(Response.Listener listener, Response response, ByteBuffer buffer) public void notifyContent(List<Response.ResponseListener> listeners, Response response, ByteBuffer buffer)
{
for (Response.ResponseListener listener : listeners)
if (listener instanceof Response.ContentListener)
notifyContent((Response.ContentListener)listener, response, buffer);
}
private void notifyContent(Response.ContentListener listener, Response response, ByteBuffer buffer)
{ {
try try
{ {
if (listener != null) listener.onContent(response, buffer);
listener.onContent(response, buffer);
} }
catch (Exception x) catch (Exception x)
{ {
@ -76,12 +96,18 @@ public class ResponseNotifier
} }
} }
public void notifySuccess(Response.Listener listener, Response response) public void notifySuccess(List<Response.ResponseListener> listeners, Response response)
{
for (Response.ResponseListener listener : listeners)
if (listener instanceof Response.SuccessListener)
notifySuccess((Response.SuccessListener)listener, response);
}
private void notifySuccess(Response.SuccessListener listener, Response response)
{ {
try try
{ {
if (listener != null) listener.onSuccess(response);
listener.onSuccess(response);
} }
catch (Exception x) catch (Exception x)
{ {
@ -89,12 +115,18 @@ public class ResponseNotifier
} }
} }
public void notifyFailure(Response.Listener listener, Response response, Throwable failure) public void notifyFailure(List<Response.ResponseListener> listeners, Response response, Throwable failure)
{
for (Response.ResponseListener listener : listeners)
if (listener instanceof Response.FailureListener)
notifyFailure((Response.FailureListener)listener, response, failure);
}
private void notifyFailure(Response.FailureListener listener, Response response, Throwable failure)
{ {
try try
{ {
if (listener != null) listener.onFailure(response, failure);
listener.onFailure(response, failure);
} }
catch (Exception x) catch (Exception x)
{ {
@ -102,12 +134,18 @@ public class ResponseNotifier
} }
} }
public void notifyComplete(Response.Listener listener, Result result) public void notifyComplete(List<Response.ResponseListener> listeners, Result result)
{
for (Response.ResponseListener listener : listeners)
if (listener instanceof Response.CompleteListener)
notifyComplete((Response.CompleteListener)listener, result);
}
private void notifyComplete(Response.CompleteListener listener, Result result)
{ {
try try
{ {
if (listener != null) listener.onComplete(result);
listener.onComplete(result);
} }
catch (Exception x) catch (Exception x)
{ {
@ -115,37 +153,37 @@ public class ResponseNotifier
} }
} }
public void forwardSuccess(Response.Listener listener, Response response) public void forwardSuccess(List<Response.ResponseListener> listeners, Response response)
{ {
notifyBegin(listener, response); notifyBegin(listeners, response);
notifyHeaders(listener, response); notifyHeaders(listeners, response);
if (response instanceof ContentResponse) if (response instanceof ContentResponse)
notifyContent(listener, response, ByteBuffer.wrap(((ContentResponse)response).getContent())); notifyContent(listeners, response, ByteBuffer.wrap(((ContentResponse)response).getContent()));
notifySuccess(listener, response); notifySuccess(listeners, response);
} }
public void forwardSuccessComplete(Response.Listener listener, Request request, Response response) public void forwardSuccessComplete(List<Response.ResponseListener> listeners, Request request, Response response)
{ {
HttpConversation conversation = client.getConversation(request.getConversationID()); HttpConversation conversation = client.getConversation(request.getConversationID(), false);
forwardSuccess(listener, response); forwardSuccess(listeners, response);
conversation.complete(); conversation.complete();
notifyComplete(listener, new Result(request, response)); notifyComplete(listeners, new Result(request, response));
} }
public void forwardFailure(Response.Listener listener, Response response, Throwable failure) public void forwardFailure(List<Response.ResponseListener> listeners, Response response, Throwable failure)
{ {
notifyBegin(listener, response); notifyBegin(listeners, response);
notifyHeaders(listener, response); notifyHeaders(listeners, response);
if (response instanceof ContentResponse) if (response instanceof ContentResponse)
notifyContent(listener, response, ByteBuffer.wrap(((ContentResponse)response).getContent())); notifyContent(listeners, response, ByteBuffer.wrap(((ContentResponse)response).getContent()));
notifyFailure(listener, response, failure); notifyFailure(listeners, response, failure);
} }
public void forwardFailureComplete(Response.Listener listener, Request request, Throwable requestFailure, Response response, Throwable responseFailure) public void forwardFailureComplete(List<Response.ResponseListener> listeners, Request request, Throwable requestFailure, Response response, Throwable responseFailure)
{ {
HttpConversation conversation = client.getConversation(request.getConversationID()); HttpConversation conversation = client.getConversation(request.getConversationID(), false);
forwardFailure(listener, response, responseFailure); forwardFailure(listeners, response, responseFailure);
conversation.complete(); conversation.complete();
notifyComplete(listener, new Result(request, requestFailure, response, responseFailure)); notifyComplete(listeners, new Result(request, requestFailure, response, responseFailure));
} }
} }

View File

@ -18,15 +18,11 @@
package org.eclipse.jetty.client; package org.eclipse.jetty.client;
import org.eclipse.jetty.client.api.Response;
import org.eclipse.jetty.util.thread.Scheduler; import org.eclipse.jetty.util.thread.Scheduler;
public interface ResponseListener extends Response.Listener public interface Schedulable
{ {
public interface Timed extends Response.Listener public boolean schedule(Scheduler scheduler);
{
public boolean schedule(Scheduler scheduler);
public boolean cancel(); public boolean cancel();
}
} }

View File

@ -37,7 +37,7 @@ public interface Connection extends AutoCloseable
* @param request the request to send * @param request the request to send
* @param listener the response listener * @param listener the response listener
*/ */
void send(Request request, Response.Listener listener); void send(Request request, Response.CompleteListener listener);
@Override @Override
void close(); void close();

View File

@ -20,12 +20,12 @@ package org.eclipse.jetty.client.api;
import java.io.IOException; import java.io.IOException;
import java.nio.file.Path; import java.nio.file.Path;
import java.util.EventListener;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.concurrent.Future; import java.util.concurrent.Future;
import org.eclipse.jetty.client.HttpClient; import org.eclipse.jetty.client.HttpClient;
import org.eclipse.jetty.client.util.InputStreamResponseListener;
import org.eclipse.jetty.http.HttpFields; import org.eclipse.jetty.http.HttpFields;
import org.eclipse.jetty.http.HttpMethod; import org.eclipse.jetty.http.HttpMethod;
import org.eclipse.jetty.http.HttpVersion; import org.eclipse.jetty.http.HttpVersion;
@ -207,16 +207,77 @@ public interface Request
Request followRedirects(boolean follow); Request followRedirects(boolean follow);
/** /**
* @return the listener for request events * @param listenerClass the class of the listener, or null for all listeners classes
* @return the listeners for request events of the given class
*/ */
List<Listener> getListeners(); <T extends RequestListener> List<T> getRequestListeners(Class<T> listenerClass);
/** /**
* @param listener the listener for request events * @param listener a listener for request events
* @return this request object * @return this request object
*/ */
Request listener(Listener listener); Request listener(Listener listener);
/**
* @param listener a listener for request queued event
* @return this request object
*/
Request onRequestQueued(QueuedListener listener);
/**
* @param listener a listener for request begin event
* @return this request object
*/
Request onRequestBegin(BeginListener listener);
/**
* @param listener a listener for request headers event
* @return this request object
*/
Request onRequestHeaders(HeadersListener listener);
/**
* @param listener a listener for request success event
* @return this request object
*/
Request onRequestSuccess(SuccessListener listener);
/**
* @param listener a listener for request failure event
* @return this request object
*/
Request onRequestFailure(FailureListener listener);
/**
* @param listener a listener for response begin event
* @return this request object
*/
Request onResponseBegin(Response.BeginListener listener);
/**
* @param listener a listener for response headers event
* @return this request object
*/
Request onResponseHeaders(Response.HeadersListener listener);
/**
* @param listener a listener for response content events
* @return this request object
*/
Request onResponseContent(Response.ContentListener listener);
/**
* @param listener a listener for response success event
* @return this request object
*/
Request onResponseSuccess(Response.SuccessListener listener);
/**
* @param listener a listener for response failure event
* @return this request object
*/
Request onResponseFailure(Response.FailureListener listener);
/** /**
* Sends this request and returns a {@link Future} that can be used to wait for the * Sends this request and returns a {@link Future} that can be used to wait for the
* request and the response to be completed (either with a success or a failure). * request and the response to be completed (either with a success or a failure).
@ -242,7 +303,7 @@ public interface Request
* *
* @param listener the listener that receives response events * @param listener the listener that receives response events
*/ */
void send(Response.Listener listener); void send(Response.CompleteListener listener);
/** /**
* Attempts to abort the send of this request. * Attempts to abort the send of this request.
@ -255,12 +316,13 @@ public interface Request
/** /**
* @return whether {@link #abort(String)} was called * @return whether {@link #abort(String)} was called
*/ */
boolean aborted(); boolean isAborted();
/** public interface RequestListener extends EventListener
* Listener for request events {
*/ }
public interface Listener
public interface QueuedListener extends RequestListener
{ {
/** /**
* Callback method invoked when the request is queued, waiting to be sent * Callback method invoked when the request is queued, waiting to be sent
@ -268,7 +330,10 @@ public interface Request
* @param request the request being queued * @param request the request being queued
*/ */
public void onQueued(Request request); public void onQueued(Request request);
}
public interface BeginListener extends RequestListener
{
/** /**
* Callback method invoked when the request begins being processed in order to be sent. * Callback method invoked when the request begins being processed in order to be sent.
* This is the last opportunity to modify the request. * This is the last opportunity to modify the request.
@ -276,7 +341,10 @@ public interface Request
* @param request the request that begins being processed * @param request the request that begins being processed
*/ */
public void onBegin(Request request); public void onBegin(Request request);
}
public interface HeadersListener extends RequestListener
{
/** /**
* Callback method invoked when the request headers (and perhaps small content) have been sent. * Callback method invoked when the request headers (and perhaps small content) have been sent.
* The request is now committed, and in transit to the server, and further modifications to the * The request is now committed, and in transit to the server, and further modifications to the
@ -284,21 +352,33 @@ public interface Request
* @param request the request that has been committed * @param request the request that has been committed
*/ */
public void onHeaders(Request request); public void onHeaders(Request request);
}
public interface SuccessListener extends RequestListener
{
/** /**
* Callback method invoked when the request has been successfully sent. * Callback method invoked when the request has been successfully sent.
* *
* @param request the request sent * @param request the request sent
*/ */
public void onSuccess(Request request); public void onSuccess(Request request);
}
public interface FailureListener extends RequestListener
{
/** /**
* Callback method invoked when the request has failed to be sent * Callback method invoked when the request has failed to be sent
* @param request the request that failed * @param request the request that failed
* @param failure the failure * @param failure the failure
*/ */
public void onFailure(Request request, Throwable failure); public void onFailure(Request request, Throwable failure);
}
/**
* Listener for all request events
*/
public interface Listener extends QueuedListener, BeginListener, HeadersListener, SuccessListener, FailureListener
{
/** /**
* An empty implementation of {@link Listener} * An empty implementation of {@link Listener}
*/ */

View File

@ -19,6 +19,8 @@
package org.eclipse.jetty.client.api; package org.eclipse.jetty.client.api;
import java.nio.ByteBuffer; import java.nio.ByteBuffer;
import java.util.EventListener;
import java.util.List;
import org.eclipse.jetty.client.util.BufferingResponseListener; import org.eclipse.jetty.client.util.BufferingResponseListener;
import org.eclipse.jetty.http.HttpFields; import org.eclipse.jetty.http.HttpFields;
@ -42,9 +44,9 @@ public interface Response
long getConversationID(); long getConversationID();
/** /**
* @return the response listener passed to {@link Request#send(Listener)} * @return the response listener passed to {@link Request#send(CompleteListener)}
*/ */
Listener getListener(); <T extends ResponseListener> List<T> getListeners(Class<T> listenerClass);
/** /**
* @return the HTTP version of this response, such as "HTTP/1.1" * @return the HTTP version of this response, such as "HTTP/1.1"
@ -74,10 +76,11 @@ public interface Response
*/ */
boolean abort(String reason); boolean abort(String reason);
/** public interface ResponseListener extends EventListener
* Listener for response events {
*/ }
public interface Listener
public interface BeginListener extends ResponseListener
{ {
/** /**
* Callback method invoked when the response line containing HTTP version, * Callback method invoked when the response line containing HTTP version,
@ -88,14 +91,20 @@ public interface Response
* @param response the response containing the response line data * @param response the response containing the response line data
*/ */
public void onBegin(Response response); public void onBegin(Response response);
}
public interface HeadersListener extends ResponseListener
{
/** /**
* Callback method invoked when the response headers have been received and parsed. * Callback method invoked when the response headers have been received and parsed.
* *
* @param response the response containing the response line data and the headers * @param response the response containing the response line data and the headers
*/ */
public void onHeaders(Response response); public void onHeaders(Response response);
}
public interface ContentListener extends ResponseListener
{
/** /**
* Callback method invoked when the response content has been received. * Callback method invoked when the response content has been received.
* This method may be invoked multiple times, and the {@code content} buffer must be consumed * This method may be invoked multiple times, and the {@code content} buffer must be consumed
@ -105,14 +114,20 @@ public interface Response
* @param content the content bytes received * @param content the content bytes received
*/ */
public void onContent(Response response, ByteBuffer content); public void onContent(Response response, ByteBuffer content);
}
public interface SuccessListener extends ResponseListener
{
/** /**
* Callback method invoked when the whole response has been successfully received. * Callback method invoked when the whole response has been successfully received.
* *
* @param response the response containing the response line data and the headers * @param response the response containing the response line data and the headers
*/ */
public void onSuccess(Response response); public void onSuccess(Response response);
}
public interface FailureListener extends ResponseListener
{
/** /**
* Callback method invoked when the response has failed in the process of being received * Callback method invoked when the response has failed in the process of being received
* *
@ -120,7 +135,10 @@ public interface Response
* @param failure the failure happened * @param failure the failure happened
*/ */
public void onFailure(Response response, Throwable failure); public void onFailure(Response response, Throwable failure);
}
public interface CompleteListener extends ResponseListener
{
/** /**
* Callback method invoked when the request <em><b>and</b></em> the response have been processed, * Callback method invoked when the request <em><b>and</b></em> the response have been processed,
* either successfully or not. * either successfully or not.
@ -129,13 +147,20 @@ public interface Response
* <p/> * <p/>
* Requests may complete <em>after</em> response, for example in case of big uploads that are * Requests may complete <em>after</em> response, for example in case of big uploads that are
* discarded or read asynchronously by the server. * discarded or read asynchronously by the server.
* This method is always invoked <em>after</em> {@link #onSuccess(Response)} or * This method is always invoked <em>after</em> {@link SuccessListener#onSuccess(Response)} or
* {@link #onFailure(Response, Throwable)}, and only when request indicates that it is completed. * {@link FailureListener#onFailure(Response, Throwable)}, and only when request indicates that
* it is completed.
* *
* @param result the result of the request / response exchange * @param result the result of the request / response exchange
*/ */
public void onComplete(Result result); public void onComplete(Result result);
}
/**
* Listener for response events
*/
public interface Listener extends BeginListener, HeadersListener, ContentListener, SuccessListener, FailureListener, CompleteListener
{
/** /**
* An empty implementation of {@link Listener} * An empty implementation of {@link Listener}
*/ */

View File

@ -46,7 +46,6 @@ public class BlockingResponseListener extends BufferingResponseListener implemen
@Override @Override
public void onComplete(Result result) public void onComplete(Result result)
{ {
super.onComplete(result);
response = new HttpContentResponse(result.getResponse(), getContent(), getEncoding()); response = new HttpContentResponse(result.getResponse(), getContent(), getEncoding());
failure = result.getFailure(); failure = result.getFailure();
latch.countDown(); latch.countDown();

View File

@ -21,6 +21,7 @@ package org.eclipse.jetty.client.util;
import java.io.UnsupportedEncodingException; import java.io.UnsupportedEncodingException;
import java.nio.ByteBuffer; import java.nio.ByteBuffer;
import java.nio.charset.UnsupportedCharsetException; import java.nio.charset.UnsupportedCharsetException;
import java.util.Locale;
import org.eclipse.jetty.client.api.Response; import org.eclipse.jetty.client.api.Response;
import org.eclipse.jetty.client.api.Result; import org.eclipse.jetty.client.api.Result;
@ -33,7 +34,7 @@ import org.eclipse.jetty.http.HttpHeader;
* <p>The content may be retrieved from {@link #onSuccess(Response)} or {@link #onComplete(Result)} * <p>The content may be retrieved from {@link #onSuccess(Response)} or {@link #onComplete(Result)}
* via {@link #getContent()} or {@link #getContentAsString()}.</p> * via {@link #getContent()} or {@link #getContentAsString()}.</p>
*/ */
public class BufferingResponseListener extends Response.Listener.Empty public abstract class BufferingResponseListener extends Response.Listener.Empty
{ {
private final int maxLength; private final int maxLength;
private volatile byte[] buffer = new byte[0]; private volatile byte[] buffer = new byte[0];
@ -69,7 +70,7 @@ public class BufferingResponseListener extends Response.Listener.Empty
if (contentType != null) if (contentType != null)
{ {
String charset = "charset="; String charset = "charset=";
int index = contentType.toLowerCase().indexOf(charset); int index = contentType.toLowerCase(Locale.ENGLISH).indexOf(charset);
if (index > 0) if (index > 0)
{ {
String encoding = contentType.substring(index + charset.length()); String encoding = contentType.substring(index + charset.length());
@ -95,6 +96,9 @@ public class BufferingResponseListener extends Response.Listener.Empty
buffer = newBuffer; buffer = newBuffer;
} }
@Override
public abstract void onComplete(Result result);
public String getEncoding() public String getEncoding()
{ {
return encoding; return encoding;

View File

@ -25,6 +25,7 @@ import java.util.ArrayList;
import java.util.Arrays; import java.util.Arrays;
import java.util.HashMap; import java.util.HashMap;
import java.util.List; import java.util.List;
import java.util.Locale;
import java.util.Map; import java.util.Map;
import java.util.Random; import java.util.Random;
import java.util.concurrent.atomic.AtomicInteger; import java.util.concurrent.atomic.AtomicInteger;
@ -108,7 +109,7 @@ public class DigestAuthentication implements Authentication
Matcher matcher = PARAM_PATTERN.matcher(part); Matcher matcher = PARAM_PATTERN.matcher(part);
if (matcher.matches()) if (matcher.matches())
{ {
String name = matcher.group(1).trim().toLowerCase(); String name = matcher.group(1).trim().toLowerCase(Locale.ENGLISH);
String value = matcher.group(2).trim(); String value = matcher.group(2).trim();
if (value.startsWith("\"") && value.endsWith("\"")) if (value.startsWith("\"") && value.endsWith("\""))
value = value.substring(1, value.length() - 1); value = value.substring(1, value.length() - 1);
@ -251,7 +252,7 @@ public class DigestAuthentication implements Authentication
private String nextNonceCount() private String nextNonceCount()
{ {
String padding = "00000000"; String padding = "00000000";
String next = Integer.toHexString(nonceCount.incrementAndGet()).toLowerCase(); String next = Integer.toHexString(nonceCount.incrementAndGet()).toLowerCase(Locale.ENGLISH);
return padding.substring(0, padding.length() - next.length()) + next; return padding.substring(0, padding.length() - next.length()) + next;
} }
@ -265,7 +266,7 @@ public class DigestAuthentication implements Authentication
private String toHexString(byte[] bytes) private String toHexString(byte[] bytes)
{ {
return TypeUtil.toHexString(bytes).toLowerCase(); return TypeUtil.toHexString(bytes).toLowerCase(Locale.ENGLISH);
} }
} }
} }

View File

@ -22,7 +22,7 @@ import java.nio.ByteBuffer;
import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicReference; import java.util.concurrent.atomic.AtomicReference;
import org.eclipse.jetty.client.ResponseListener; import org.eclipse.jetty.client.Schedulable;
import org.eclipse.jetty.client.api.Request; import org.eclipse.jetty.client.api.Request;
import org.eclipse.jetty.client.api.Response; import org.eclipse.jetty.client.api.Response;
import org.eclipse.jetty.client.api.Result; import org.eclipse.jetty.client.api.Result;
@ -30,7 +30,7 @@ import org.eclipse.jetty.util.log.Log;
import org.eclipse.jetty.util.log.Logger; import org.eclipse.jetty.util.log.Logger;
import org.eclipse.jetty.util.thread.Scheduler; import org.eclipse.jetty.util.thread.Scheduler;
public class TimedResponseListener implements ResponseListener.Timed, Runnable public class TimedResponseListener implements Response.Listener, Schedulable, Runnable
{ {
private static final Logger LOG = Log.getLogger(TimedResponseListener.class); private static final Logger LOG = Log.getLogger(TimedResponseListener.class);

View File

@ -0,0 +1,85 @@
//
// ========================================================================
// Copyright (c) 1995-2012 Mort Bay Consulting Pty. Ltd.
// ------------------------------------------------------------------------
// All rights reserved. This program and the accompanying materials
// are made available under the terms of the Eclipse Public License v1.0
// and Apache License v2.0 which accompanies this distribution.
//
// The Eclipse Public License is available at
// http://www.eclipse.org/legal/epl-v10.html
//
// The Apache License v2.0 is available at
// http://www.opensource.org/licenses/apache2.0.php
//
// You may elect to redistribute this code under either of these licenses.
// ========================================================================
//
package org.eclipse.jetty.client;
import java.io.IOException;
import java.net.Socket;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;
import org.eclipse.jetty.client.api.Response;
import org.eclipse.jetty.client.api.Result;
import org.eclipse.jetty.toolchain.test.TestTracker;
import org.junit.After;
import org.junit.Assert;
import org.junit.Assume;
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
public class ExternalSiteTest
{
@Rule
public final TestTracker tracker = new TestTracker();
private HttpClient client;
@Before
public void prepare() throws Exception
{
client = new HttpClient();
client.start();
}
@After
public void dispose() throws Exception
{
client.stop();
}
@Test
public void testExternalSite() throws Exception
{
String host = "wikipedia.org";
int port = 80;
// Verify that we have connectivity
try
{
new Socket(host, port);
}
catch (IOException x)
{
Assume.assumeNoException(x);
}
final CountDownLatch latch = new CountDownLatch(1);
client.newRequest(host, port).send(new Response.CompleteListener()
{
@Override
public void onComplete(Result result)
{
if (!result.isFailed() && result.getResponse().getStatus() == 200)
latch.countDown();
}
});
Assert.assertTrue(latch.await(10, TimeUnit.SECONDS));
}
}

View File

@ -25,6 +25,8 @@ import java.nio.charset.Charset;
import java.util.zip.GZIPInputStream; import java.util.zip.GZIPInputStream;
import java.util.zip.GZIPOutputStream; import java.util.zip.GZIPOutputStream;
import org.eclipse.jetty.toolchain.test.TestTracker;
import org.junit.Rule;
import org.junit.Test; import org.junit.Test;
import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertEquals;
@ -33,6 +35,9 @@ import static org.junit.Assert.assertTrue;
public class GZIPContentDecoderTest public class GZIPContentDecoderTest
{ {
@Rule
public final TestTracker tracker = new TestTracker();
@Test @Test
public void testStreamNoBlocks() throws Exception public void testStreamNoBlocks() throws Exception
{ {

View File

@ -99,14 +99,16 @@ public class HttpClientAuthenticationTest extends AbstractHttpClientServerTest
public void test_BasicAuthentication() throws Exception public void test_BasicAuthentication() throws Exception
{ {
startBasic(new EmptyServerHandler()); startBasic(new EmptyServerHandler());
test_Authentication(new BasicAuthentication(scheme + "://localhost:" + connector.getLocalPort(), realm, "basic", "basic")); String uri = scheme + "://localhost:" + connector.getLocalPort();
test_Authentication(new BasicAuthentication(uri, realm, "basic", "basic"));
} }
@Test @Test
public void test_DigestAuthentication() throws Exception public void test_DigestAuthentication() throws Exception
{ {
startDigest(new EmptyServerHandler()); startDigest(new EmptyServerHandler());
test_Authentication(new DigestAuthentication(scheme + "://localhost:" + connector.getLocalPort(), realm, "digest", "digest")); String uri = scheme + "://localhost:" + connector.getLocalPort();
test_Authentication(new DigestAuthentication(uri, realm, "digest", "digest"));
} }
private void test_Authentication(Authentication authentication) throws Exception private void test_Authentication(Authentication authentication) throws Exception
@ -189,7 +191,8 @@ public class HttpClientAuthenticationTest extends AbstractHttpClientServerTest
} }
}); });
client.getAuthenticationStore().addAuthentication(new BasicAuthentication(scheme + "://localhost:" + connector.getLocalPort(), realm, "basic", "basic")); String uri = scheme + "://localhost:" + connector.getLocalPort();
client.getAuthenticationStore().addAuthentication(new BasicAuthentication(uri, realm, "basic", "basic"));
final CountDownLatch requests = new CountDownLatch(3); final CountDownLatch requests = new CountDownLatch(3);
Request.Listener.Empty requestListener = new Request.Listener.Empty() Request.Listener.Empty requestListener = new Request.Listener.Empty()
@ -227,7 +230,8 @@ public class HttpClientAuthenticationTest extends AbstractHttpClientServerTest
} }
}); });
client.getAuthenticationStore().addAuthentication(new BasicAuthentication(scheme + "://localhost:" + connector.getLocalPort(), realm, "basic", "basic")); String uri = scheme + "://localhost:" + connector.getLocalPort();
client.getAuthenticationStore().addAuthentication(new BasicAuthentication(uri, realm, "basic", "basic"));
final CountDownLatch requests = new CountDownLatch(3); final CountDownLatch requests = new CountDownLatch(3);
Request.Listener.Empty requestListener = new Request.Listener.Empty() Request.Listener.Empty requestListener = new Request.Listener.Empty()
@ -268,7 +272,8 @@ public class HttpClientAuthenticationTest extends AbstractHttpClientServerTest
client.getRequestListeners().add(requestListener); client.getRequestListeners().add(requestListener);
AuthenticationStore authenticationStore = client.getAuthenticationStore(); AuthenticationStore authenticationStore = client.getAuthenticationStore();
BasicAuthentication authentication = new BasicAuthentication(scheme + "://localhost:" + connector.getLocalPort(), realm, "basic", "basic"); String uri = scheme + "://localhost:" + connector.getLocalPort();
BasicAuthentication authentication = new BasicAuthentication(uri, realm, "basic", "basic");
authenticationStore.addAuthentication(authentication); authenticationStore.addAuthentication(authentication);
Request request = client.newRequest("localhost", connector.getLocalPort()).scheme(scheme).path("/secure"); Request request = client.newRequest("localhost", connector.getLocalPort()).scheme(scheme).path("/secure");

View File

@ -23,6 +23,7 @@ import java.nio.ByteBuffer;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Arrays; import java.util.Arrays;
import java.util.List; import java.util.List;
import java.util.Locale;
import java.util.Random; import java.util.Random;
import java.util.concurrent.CountDownLatch; import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeUnit;
@ -67,7 +68,7 @@ public class HttpClientLoadTest extends AbstractHttpClientServerTest
client.setMaxQueueSizePerAddress(1024 * 1024); client.setMaxQueueSizePerAddress(1024 * 1024);
client.setDispatchIO(false); client.setDispatchIO(false);
Random random = new Random(1000L); Random random = new Random();
int iterations = 500; int iterations = 500;
CountDownLatch latch = new CountDownLatch(iterations); CountDownLatch latch = new CountDownLatch(iterations);
List<String> failures = new ArrayList<>(); List<String> failures = new ArrayList<>();
@ -132,15 +133,15 @@ public class HttpClientLoadTest extends AbstractHttpClientServerTest
else if (!ssl && random.nextBoolean()) else if (!ssl && random.nextBoolean())
request.header("X-Close", "true"); request.header("X-Close", "true");
int contentLength = random.nextInt(maxContentLength) + 1;
switch (method) switch (method)
{ {
case GET: case GET:
// Randomly ask the server to download data upon this GET request // Randomly ask the server to download data upon this GET request
if (random.nextBoolean()) if (random.nextBoolean())
request.header("X-Download", String.valueOf(random.nextInt(maxContentLength) + 1)); request.header("X-Download", String.valueOf(contentLength));
break; break;
case POST: case POST:
int contentLength = random.nextInt(maxContentLength) + 1;
request.header("X-Upload", String.valueOf(contentLength)); request.header("X-Upload", String.valueOf(contentLength));
request.content(new BytesContentProvider(new byte[contentLength])); request.content(new BytesContentProvider(new byte[contentLength]));
break; break;
@ -184,7 +185,7 @@ public class HttpClientLoadTest extends AbstractHttpClientServerTest
@Override @Override
public void handle(String target, org.eclipse.jetty.server.Request baseRequest, HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException public void handle(String target, org.eclipse.jetty.server.Request baseRequest, HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException
{ {
String method = request.getMethod().toUpperCase(); String method = request.getMethod().toUpperCase(Locale.ENGLISH);
switch (method) switch (method)
{ {
case "GET": case "GET":

View File

@ -72,7 +72,7 @@ public class HttpClientStreamTest extends AbstractHttpClientServerTest
ContentResponse response = client.newRequest("localhost", connector.getLocalPort()) ContentResponse response = client.newRequest("localhost", connector.getLocalPort())
.scheme(scheme) .scheme(scheme)
.file(upload) .file(upload)
.listener(new Request.Listener.Empty() .onRequestSuccess(new Request.SuccessListener()
{ {
@Override @Override
public void onSuccess(Request request) public void onSuccess(Request request)

View File

@ -289,7 +289,7 @@ public class HttpClientTest extends AbstractHttpClientServerTest
final CountDownLatch successLatch = new CountDownLatch(2); final CountDownLatch successLatch = new CountDownLatch(2);
client.newRequest("localhost", connector.getLocalPort()) client.newRequest("localhost", connector.getLocalPort())
.scheme(scheme) .scheme(scheme)
.listener(new Request.Listener.Empty() .onRequestBegin(new Request.BeginListener()
{ {
@Override @Override
public void onBegin(Request request) public void onBegin(Request request)
@ -316,7 +316,7 @@ public class HttpClientTest extends AbstractHttpClientServerTest
client.newRequest("localhost", connector.getLocalPort()) client.newRequest("localhost", connector.getLocalPort())
.scheme(scheme) .scheme(scheme)
.listener(new Request.Listener.Empty() .onRequestQueued(new Request.QueuedListener()
{ {
@Override @Override
public void onQueued(Request request) public void onQueued(Request request)
@ -371,18 +371,19 @@ public class HttpClientTest extends AbstractHttpClientServerTest
latch.countDown(); latch.countDown();
} }
}) })
.send(new Response.Listener.Empty() .onResponseFailure(new Response.FailureListener()
{ {
@Override @Override
public void onFailure(Response response, Throwable failure) public void onFailure(Response response, Throwable failure)
{ {
latch.countDown(); latch.countDown();
} }
}); })
.send(null);
client.newRequest("localhost", connector.getLocalPort()) client.newRequest("localhost", connector.getLocalPort())
.scheme(scheme) .scheme(scheme)
.send(new Response.Listener.Empty() .onResponseSuccess(new Response.SuccessListener()
{ {
@Override @Override
public void onSuccess(Response response) public void onSuccess(Response response)
@ -390,7 +391,8 @@ public class HttpClientTest extends AbstractHttpClientServerTest
Assert.assertEquals(200, response.getStatus()); Assert.assertEquals(200, response.getStatus());
latch.countDown(); latch.countDown();
} }
}); })
.send(null);
Assert.assertTrue(latch.await(5 * idleTimeout, TimeUnit.MILLISECONDS)); Assert.assertTrue(latch.await(5 * idleTimeout, TimeUnit.MILLISECONDS));
} }
@ -419,7 +421,7 @@ public class HttpClientTest extends AbstractHttpClientServerTest
client.newRequest("localhost", connector.getLocalPort()) client.newRequest("localhost", connector.getLocalPort())
.scheme(scheme) .scheme(scheme)
.file(file) .file(file)
.listener(new Request.Listener.Empty() .onRequestSuccess(new Request.SuccessListener()
{ {
@Override @Override
public void onSuccess(Request request) public void onSuccess(Request request)
@ -529,7 +531,7 @@ public class HttpClientTest extends AbstractHttpClientServerTest
final int port = connector.getLocalPort(); final int port = connector.getLocalPort();
client.newRequest(host, port) client.newRequest(host, port)
.scheme(scheme) .scheme(scheme)
.listener(new Request.Listener.Empty() .onRequestBegin(new Request.BeginListener()
{ {
@Override @Override
public void onBegin(Request request) public void onBegin(Request request)
@ -621,8 +623,4 @@ public class HttpClientTest extends AbstractHttpClientServerTest
Assert.assertNotNull(response); Assert.assertNotNull(response);
Assert.assertEquals(200, response.getStatus()); Assert.assertEquals(200, response.getStatus());
} }
// TODO: add a test to idle timeout a request that is in the queue...
// TODO: even though "idle timeout" only applies to connections
// TODO: so do we still need a "global" timeout that takes in count queue time + send time + receive time ?
} }

View File

@ -151,7 +151,7 @@ public class HttpClientTimeoutTest extends AbstractHttpClientServerTest
TimeUnit.MILLISECONDS.sleep(2 * timeout); TimeUnit.MILLISECONDS.sleep(2 * timeout);
Assert.assertFalse(request.aborted()); Assert.assertFalse(request.isAborted());
} }
@Slow @Slow
@ -208,7 +208,7 @@ public class HttpClientTimeoutTest extends AbstractHttpClientServerTest
TimeUnit.MILLISECONDS.sleep(2 * timeout); TimeUnit.MILLISECONDS.sleep(2 * timeout);
Assert.assertFalse(request.aborted()); Assert.assertFalse(request.isAborted());
} }
} }

View File

@ -68,7 +68,7 @@ public class HttpConnectionLifecycleTest extends AbstractHttpClientServerTest
final CountDownLatch successLatch = new CountDownLatch(3); final CountDownLatch successLatch = new CountDownLatch(3);
client.newRequest(host, port) client.newRequest(host, port)
.scheme(scheme) .scheme(scheme)
.listener(new Request.Listener.Empty() .onRequestSuccess(new Request.SuccessListener()
{ {
@Override @Override
public void onSuccess(Request request) public void onSuccess(Request request)
@ -76,7 +76,7 @@ public class HttpConnectionLifecycleTest extends AbstractHttpClientServerTest
successLatch.countDown(); successLatch.countDown();
} }
}) })
.send(new Response.Listener.Empty() .onResponseHeaders(new Response.HeadersListener()
{ {
@Override @Override
public void onHeaders(Response response) public void onHeaders(Response response)
@ -85,7 +85,9 @@ public class HttpConnectionLifecycleTest extends AbstractHttpClientServerTest
Assert.assertEquals(1, activeConnections.size()); Assert.assertEquals(1, activeConnections.size());
headersLatch.countDown(); headersLatch.countDown();
} }
})
.send(new Response.Listener.Empty()
{
@Override @Override
public void onSuccess(Response response) public void onSuccess(Response response)
{ {
@ -308,7 +310,7 @@ public class HttpConnectionLifecycleTest extends AbstractHttpClientServerTest
final CountDownLatch failureLatch = new CountDownLatch(2); final CountDownLatch failureLatch = new CountDownLatch(2);
client.newRequest(host, port) client.newRequest(host, port)
.scheme(scheme) .scheme(scheme)
.listener(new Request.Listener.Empty() .onRequestFailure(new Request.FailureListener()
{ {
@Override @Override
public void onFailure(Request request, Throwable failure) public void onFailure(Request request, Throwable failure)

View File

@ -21,11 +21,16 @@ package org.eclipse.jetty.client;
import java.util.List; import java.util.List;
import org.eclipse.jetty.http.HttpCookie; import org.eclipse.jetty.http.HttpCookie;
import org.eclipse.jetty.toolchain.test.TestTracker;
import org.junit.Assert; import org.junit.Assert;
import org.junit.Rule;
import org.junit.Test; import org.junit.Test;
public class HttpCookieParserTest public class HttpCookieParserTest
{ {
@Rule
public final TestTracker tracker = new TestTracker();
@Test @Test
public void testParseCookie1() throws Exception public void testParseCookie1() throws Exception
{ {

View File

@ -23,11 +23,16 @@ import java.util.List;
import org.eclipse.jetty.client.api.CookieStore; import org.eclipse.jetty.client.api.CookieStore;
import org.eclipse.jetty.client.api.Destination; import org.eclipse.jetty.client.api.Destination;
import org.eclipse.jetty.http.HttpCookie; import org.eclipse.jetty.http.HttpCookie;
import org.eclipse.jetty.toolchain.test.TestTracker;
import org.junit.Assert; import org.junit.Assert;
import org.junit.Rule;
import org.junit.Test; import org.junit.Test;
public class HttpCookieStoreTest public class HttpCookieStoreTest
{ {
@Rule
public final TestTracker tracker = new TestTracker();
private HttpClient client = new HttpClient(); private HttpClient client = new HttpClient();
@Test @Test

View File

@ -22,6 +22,7 @@ import java.io.ByteArrayOutputStream;
import java.io.EOFException; import java.io.EOFException;
import java.net.URI; import java.net.URI;
import java.nio.ByteBuffer; import java.nio.ByteBuffer;
import java.util.Collections;
import java.util.concurrent.ExecutionException; import java.util.concurrent.ExecutionException;
import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException; import java.util.concurrent.TimeoutException;
@ -34,13 +35,18 @@ import org.eclipse.jetty.http.HttpFields;
import org.eclipse.jetty.http.HttpHeader; import org.eclipse.jetty.http.HttpHeader;
import org.eclipse.jetty.http.HttpVersion; import org.eclipse.jetty.http.HttpVersion;
import org.eclipse.jetty.io.ByteArrayEndPoint; import org.eclipse.jetty.io.ByteArrayEndPoint;
import org.eclipse.jetty.toolchain.test.TestTracker;
import org.junit.After; import org.junit.After;
import org.junit.Assert; import org.junit.Assert;
import org.junit.Before; import org.junit.Before;
import org.junit.Rule;
import org.junit.Test; import org.junit.Test;
public class HttpReceiverTest public class HttpReceiverTest
{ {
@Rule
public final TestTracker tracker = new TestTracker();
private HttpClient client; private HttpClient client;
private HttpDestination destination; private HttpDestination destination;
private ByteArrayEndPoint endPoint; private ByteArrayEndPoint endPoint;
@ -68,7 +74,7 @@ public class HttpReceiverTest
{ {
HttpRequest request = new HttpRequest(client, URI.create("http://localhost")); HttpRequest request = new HttpRequest(client, URI.create("http://localhost"));
BlockingResponseListener listener = new BlockingResponseListener(request); BlockingResponseListener listener = new BlockingResponseListener(request);
HttpExchange exchange = new HttpExchange(conversation, connection, request, listener); HttpExchange exchange = new HttpExchange(conversation, connection, request, Collections.<Response.ResponseListener>singletonList(listener));
conversation.getExchanges().offer(exchange); conversation.getExchanges().offer(exchange);
connection.setExchange(exchange); connection.setExchange(exchange);
exchange.requestComplete(null); exchange.requestComplete(null);
@ -84,7 +90,7 @@ public class HttpReceiverTest
"Content-length: 0\r\n" + "Content-length: 0\r\n" +
"\r\n"); "\r\n");
HttpExchange exchange = newExchange(); HttpExchange exchange = newExchange();
BlockingResponseListener listener = (BlockingResponseListener)exchange.getResponseListener(); BlockingResponseListener listener = (BlockingResponseListener)exchange.getResponseListeners().get(0);
exchange.receive(); exchange.receive();
Response response = listener.get(5, TimeUnit.SECONDS); Response response = listener.get(5, TimeUnit.SECONDS);
@ -108,7 +114,7 @@ public class HttpReceiverTest
"\r\n" + "\r\n" +
content); content);
HttpExchange exchange = newExchange(); HttpExchange exchange = newExchange();
BlockingResponseListener listener = (BlockingResponseListener)exchange.getResponseListener(); BlockingResponseListener listener = (BlockingResponseListener)exchange.getResponseListeners().get(0);
exchange.receive(); exchange.receive();
Response response = listener.get(5, TimeUnit.SECONDS); Response response = listener.get(5, TimeUnit.SECONDS);
@ -135,7 +141,7 @@ public class HttpReceiverTest
"\r\n" + "\r\n" +
content1); content1);
HttpExchange exchange = newExchange(); HttpExchange exchange = newExchange();
BlockingResponseListener listener = (BlockingResponseListener)exchange.getResponseListener(); BlockingResponseListener listener = (BlockingResponseListener)exchange.getResponseListeners().get(0);
exchange.receive(); exchange.receive();
endPoint.setInputEOF(); endPoint.setInputEOF();
exchange.receive(); exchange.receive();
@ -159,7 +165,7 @@ public class HttpReceiverTest
"Content-length: 1\r\n" + "Content-length: 1\r\n" +
"\r\n"); "\r\n");
HttpExchange exchange = newExchange(); HttpExchange exchange = newExchange();
BlockingResponseListener listener = (BlockingResponseListener)exchange.getResponseListener(); BlockingResponseListener listener = (BlockingResponseListener)exchange.getResponseListeners().get(0);
exchange.receive(); exchange.receive();
// Simulate an idle timeout // Simulate an idle timeout
connection.idleTimeout(); connection.idleTimeout();
@ -183,7 +189,7 @@ public class HttpReceiverTest
"Content-length: A\r\n" + "Content-length: A\r\n" +
"\r\n"); "\r\n");
HttpExchange exchange = newExchange(); HttpExchange exchange = newExchange();
BlockingResponseListener listener = (BlockingResponseListener)exchange.getResponseListener(); BlockingResponseListener listener = (BlockingResponseListener)exchange.getResponseListeners().get(0);
exchange.receive(); exchange.receive();
try try
@ -214,7 +220,7 @@ public class HttpReceiverTest
"Content-Encoding: gzip\r\n" + "Content-Encoding: gzip\r\n" +
"\r\n"); "\r\n");
HttpExchange exchange = newExchange(); HttpExchange exchange = newExchange();
BlockingResponseListener listener = (BlockingResponseListener)exchange.getResponseListener(); BlockingResponseListener listener = (BlockingResponseListener)exchange.getResponseListeners().get(0);
exchange.receive(); exchange.receive();
endPoint.reset(); endPoint.reset();

View File

@ -139,7 +139,7 @@ public class HttpRequestAbortTest extends AbstractHttpClientServerTest
{ {
ContentResponse response = client.newRequest("localhost", connector.getLocalPort()) ContentResponse response = client.newRequest("localhost", connector.getLocalPort())
.scheme(scheme) .scheme(scheme)
.listener(new Request.Listener.Empty() .onRequestHeaders(new Request.HeadersListener()
{ {
@Override @Override
public void onHeaders(Request request) public void onHeaders(Request request)
@ -191,7 +191,7 @@ public class HttpRequestAbortTest extends AbstractHttpClientServerTest
{ {
client.newRequest("localhost", connector.getLocalPort()) client.newRequest("localhost", connector.getLocalPort())
.scheme(scheme) .scheme(scheme)
.listener(new Request.Listener.Empty() .onRequestHeaders(new Request.HeadersListener()
{ {
@Override @Override
public void onHeaders(Request request) public void onHeaders(Request request)

View File

@ -55,14 +55,16 @@ public class HttpResponseAbortTest extends AbstractHttpClientServerTest
final CountDownLatch latch = new CountDownLatch(1); final CountDownLatch latch = new CountDownLatch(1);
client.newRequest("localhost", connector.getLocalPort()) client.newRequest("localhost", connector.getLocalPort())
.scheme(scheme) .scheme(scheme)
.send(new Response.Listener.Empty() .onResponseBegin(new Response.BeginListener()
{ {
@Override @Override
public void onBegin(Response response) public void onBegin(Response response)
{ {
response.abort(null); response.abort(null);
} }
})
.send(new Response.CompleteListener()
{
@Override @Override
public void onComplete(Result result) public void onComplete(Result result)
{ {
@ -81,13 +83,16 @@ public class HttpResponseAbortTest extends AbstractHttpClientServerTest
final CountDownLatch latch = new CountDownLatch(1); final CountDownLatch latch = new CountDownLatch(1);
client.newRequest("localhost", connector.getLocalPort()) client.newRequest("localhost", connector.getLocalPort())
.scheme(scheme) .scheme(scheme)
.send(new Response.Listener.Empty() .onResponseHeaders(new Response.HeadersListener()
{ {
@Override @Override
public void onHeaders(Response response) public void onHeaders(Response response)
{ {
response.abort(null); response.abort(null);
} }
})
.send(new Response.CompleteListener()
{
@Override @Override
public void onComplete(Result result) public void onComplete(Result result)
@ -126,14 +131,16 @@ public class HttpResponseAbortTest extends AbstractHttpClientServerTest
final CountDownLatch latch = new CountDownLatch(1); final CountDownLatch latch = new CountDownLatch(1);
client.newRequest("localhost", connector.getLocalPort()) client.newRequest("localhost", connector.getLocalPort())
.scheme(scheme) .scheme(scheme)
.send(new Response.Listener.Empty() .onResponseContent(new Response.ContentListener()
{ {
@Override @Override
public void onContent(Response response, ByteBuffer content) public void onContent(Response response, ByteBuffer content)
{ {
response.abort(null); response.abort(null);
} }
})
.send(new Response.CompleteListener()
{
@Override @Override
public void onComplete(Result result) public void onComplete(Result result)
{ {

View File

@ -20,6 +20,7 @@ package org.eclipse.jetty.client;
import java.net.URI; import java.net.URI;
import java.nio.ByteBuffer; import java.nio.ByteBuffer;
import java.util.Locale;
import java.util.concurrent.CountDownLatch; import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeUnit;
@ -28,14 +29,19 @@ import org.eclipse.jetty.client.api.Response;
import org.eclipse.jetty.client.api.Result; import org.eclipse.jetty.client.api.Result;
import org.eclipse.jetty.client.util.ByteBufferContentProvider; import org.eclipse.jetty.client.util.ByteBufferContentProvider;
import org.eclipse.jetty.io.ByteArrayEndPoint; import org.eclipse.jetty.io.ByteArrayEndPoint;
import org.eclipse.jetty.toolchain.test.TestTracker;
import org.eclipse.jetty.toolchain.test.annotation.Slow; import org.eclipse.jetty.toolchain.test.annotation.Slow;
import org.junit.After; import org.junit.After;
import org.junit.Assert; import org.junit.Assert;
import org.junit.Before; import org.junit.Before;
import org.junit.Rule;
import org.junit.Test; import org.junit.Test;
public class HttpSenderTest public class HttpSenderTest
{ {
@Rule
public final TestTracker tracker = new TestTracker();
private HttpClient client; private HttpClient client;
@Before @Before
@ -74,7 +80,7 @@ public class HttpSenderTest
successLatch.countDown(); successLatch.countDown();
} }
}); });
connection.send(request, null); connection.send(request, (Response.CompleteListener)null);
String requestString = endPoint.takeOutputString(); String requestString = endPoint.takeOutputString();
Assert.assertTrue(requestString.startsWith("GET ")); Assert.assertTrue(requestString.startsWith("GET "));
@ -91,7 +97,7 @@ public class HttpSenderTest
HttpDestination destination = new HttpDestination(client, "http", "localhost", 8080); HttpDestination destination = new HttpDestination(client, "http", "localhost", 8080);
HttpConnection connection = new HttpConnection(client, endPoint, destination); HttpConnection connection = new HttpConnection(client, endPoint, destination);
Request request = client.newRequest(URI.create("http://localhost/")); Request request = client.newRequest(URI.create("http://localhost/"));
connection.send(request, null); connection.send(request, (Response.CompleteListener)null);
// This take will free space in the buffer and allow for the write to complete // This take will free space in the buffer and allow for the write to complete
StringBuilder builder = new StringBuilder(endPoint.takeOutputString()); StringBuilder builder = new StringBuilder(endPoint.takeOutputString());
@ -202,7 +208,7 @@ public class HttpSenderTest
successLatch.countDown(); successLatch.countDown();
} }
}); });
connection.send(request, null); connection.send(request, (Response.CompleteListener)null);
String requestString = endPoint.takeOutputString(); String requestString = endPoint.takeOutputString();
Assert.assertTrue(requestString.startsWith("GET ")); Assert.assertTrue(requestString.startsWith("GET "));
@ -237,7 +243,7 @@ public class HttpSenderTest
successLatch.countDown(); successLatch.countDown();
} }
}); });
connection.send(request, null); connection.send(request, (Response.CompleteListener)null);
String requestString = endPoint.takeOutputString(); String requestString = endPoint.takeOutputString();
Assert.assertTrue(requestString.startsWith("GET ")); Assert.assertTrue(requestString.startsWith("GET "));
@ -279,12 +285,12 @@ public class HttpSenderTest
successLatch.countDown(); successLatch.countDown();
} }
}); });
connection.send(request, null); connection.send(request, (Response.CompleteListener)null);
String requestString = endPoint.takeOutputString(); String requestString = endPoint.takeOutputString();
Assert.assertTrue(requestString.startsWith("GET ")); Assert.assertTrue(requestString.startsWith("GET "));
String content = Integer.toHexString(content1.length()).toUpperCase() + "\r\n" + content1 + "\r\n"; String content = Integer.toHexString(content1.length()).toUpperCase(Locale.ENGLISH) + "\r\n" + content1 + "\r\n";
content += Integer.toHexString(content2.length()).toUpperCase() + "\r\n" + content2 + "\r\n"; content += Integer.toHexString(content2.length()).toUpperCase(Locale.ENGLISH) + "\r\n" + content2 + "\r\n";
content += "0\r\n\r\n"; content += "0\r\n\r\n";
Assert.assertTrue(requestString.endsWith("\r\n\r\n" + content)); Assert.assertTrue(requestString.endsWith("\r\n\r\n" + content));
Assert.assertTrue(headersLatch.await(5, TimeUnit.SECONDS)); Assert.assertTrue(headersLatch.await(5, TimeUnit.SECONDS));

View File

@ -43,6 +43,16 @@
<Set name="defaultsDescriptor"><Property name="jetty.home" default="." />/etc/webdefault.xml</Set> <Set name="defaultsDescriptor"><Property name="jetty.home" default="." />/etc/webdefault.xml</Set>
<Set name="scanInterval">1</Set> <Set name="scanInterval">1</Set>
<Set name="extractWars">true</Set> <Set name="extractWars">true</Set>
<Set name="configurationManager">
<New class="org.eclipse.jetty.deploy.PropertiesConfigurationManager">
<!-- file of context configuration properties
<Set name="file"><SystemProperty name="jetty.home"/>/etc/some.properties</Set>
-->
<!-- set a context configuration property
<Call name="put"><Arg>name</Arg><Arg>value</Arg></Call>
-->
</New>
</Set>
</New> </New>
</Arg> </Arg>
</Call> </Call>

View File

@ -21,10 +21,15 @@ package org.eclipse.jetty.deploy;
import java.io.FileNotFoundException; import java.io.FileNotFoundException;
import java.io.IOException; import java.io.IOException;
import java.net.MalformedURLException; import java.net.MalformedURLException;
import java.util.Collections;
import java.util.HashMap; import java.util.HashMap;
import java.util.Map; import java.util.Map;
import java.util.Properties; import java.util.Properties;
import org.eclipse.jetty.util.annotation.ManagedAttribute;
import org.eclipse.jetty.util.annotation.ManagedObject;
import org.eclipse.jetty.util.annotation.ManagedOperation;
import org.eclipse.jetty.util.annotation.Name;
import org.eclipse.jetty.util.resource.Resource; import org.eclipse.jetty.util.resource.Resource;
/** /**
@ -32,42 +37,55 @@ import org.eclipse.jetty.util.resource.Resource;
* *
* Supplies properties defined in a file. * Supplies properties defined in a file.
*/ */
public class FileConfigurationManager implements ConfigurationManager @ManagedObject("Configure deployed webapps via properties")
public class PropertiesConfigurationManager implements ConfigurationManager
{ {
private Resource _file; private String _properties;
private Map<String,String> _map = new HashMap<String,String>(); private final Map<String,String> _map = new HashMap<String,String>();
public FileConfigurationManager() public PropertiesConfigurationManager(String properties)
{
}
public PropertiesConfigurationManager()
{ {
} }
public void setFile(String filename) throws MalformedURLException, IOException @ManagedAttribute("A file or URL of properties")
public void setFile(String resource) throws MalformedURLException, IOException
{ {
_file = Resource.newResource(filename); _properties=resource;
_map.clear();
loadProperties(_properties);
} }
public String getFile()
{
return _properties;
}
@ManagedOperation("Set a property")
public void put(@Name("name")String name, @Name("value")String value)
{
_map.put(name,value);
}
/** /**
* @see org.eclipse.jetty.deploy.ConfigurationManager#getProperties() * @see org.eclipse.jetty.deploy.ConfigurationManager#getProperties()
*/ */
@Override
public Map<String, String> getProperties() public Map<String, String> getProperties()
{ {
try return new HashMap<>(_map);
{
loadProperties();
return _map;
}
catch (Exception e)
{
throw new RuntimeException(e);
}
} }
private void loadProperties() throws FileNotFoundException, IOException private void loadProperties(String resource) throws FileNotFoundException, IOException
{ {
if (_map.isEmpty() && _file!=null) Resource file=Resource.newResource(resource);
if (file!=null && file.exists())
{ {
Properties properties = new Properties(); Properties properties = new Properties();
properties.load(_file.getInputStream()); properties.load(file.getInputStream());
for (Map.Entry<Object, Object> entry : properties.entrySet()) for (Map.Entry<Object, Object> entry : properties.entrySet())
_map.put(entry.getKey().toString(),String.valueOf(entry.getValue())); _map.put(entry.getKey().toString(),String.valueOf(entry.getValue()));
} }

View File

@ -22,6 +22,7 @@ import java.io.File;
import java.io.FilenameFilter; import java.io.FilenameFilter;
import java.io.IOException; import java.io.IOException;
import java.net.MalformedURLException; import java.net.MalformedURLException;
import java.util.Locale;
import org.eclipse.jetty.deploy.App; import org.eclipse.jetty.deploy.App;
import org.eclipse.jetty.deploy.ConfigurationManager; import org.eclipse.jetty.deploy.ConfigurationManager;
@ -77,7 +78,7 @@ public class WebAppProvider extends ScanningAppProvider
{ {
return false; return false;
} }
String lowername = name.toLowerCase(); String lowername = name.toLowerCase(Locale.ENGLISH);
File file = new File(dir,name); File file = new File(dir,name);
@ -299,9 +300,9 @@ public class WebAppProvider extends ScanningAppProvider
{ {
context = URIUtil.SLASH; context = URIUtil.SLASH;
} }
else if (context.toLowerCase().startsWith("root-")) else if (context.toLowerCase(Locale.ENGLISH).startsWith("root-"))
{ {
int dash=context.toLowerCase().indexOf('-'); int dash=context.toLowerCase(Locale.ENGLISH).indexOf('-');
String virtual = context.substring(dash+1); String virtual = context.substring(dash+1);
wah.setVirtualHosts(new String[]{virtual}); wah.setVirtualHosts(new String[]{virtual});
context = URIUtil.SLASH; context = URIUtil.SLASH;

View File

@ -19,6 +19,7 @@
package org.eclipse.jetty.deploy.util; package org.eclipse.jetty.deploy.util;
import java.io.File; import java.io.File;
import java.util.Locale;
/** /**
* Simple, yet surprisingly common utility methods for identifying various file types commonly seen and worked with in a * Simple, yet surprisingly common utility methods for identifying various file types commonly seen and worked with in a
@ -38,7 +39,7 @@ public class FileID
{ {
if (path.isFile()) if (path.isFile())
{ {
String name = path.getName().toLowerCase(); String name = path.getName().toLowerCase(Locale.ENGLISH);
return (name.endsWith(".war") || name.endsWith(".jar")); return (name.endsWith(".war") || name.endsWith(".jar"));
} }
@ -62,7 +63,7 @@ public class FileID
return false; return false;
} }
String name = path.getName().toLowerCase(); String name = path.getName().toLowerCase(Locale.ENGLISH);
return (name.endsWith(".war") || name.endsWith(".jar")); return (name.endsWith(".war") || name.endsWith(".jar"));
} }
@ -73,7 +74,7 @@ public class FileID
return false; return false;
} }
String name = path.getName().toLowerCase(); String name = path.getName().toLowerCase(Locale.ENGLISH);
return name.endsWith(".xml"); return name.endsWith(".xml");
} }
} }

View File

@ -50,7 +50,7 @@
<Set name="monitoredDirName"><SystemProperty name="jetty.home" />/webapps</Set> <Set name="monitoredDirName"><SystemProperty name="jetty.home" />/webapps</Set>
<Set name="scanInterval">1</Set> <Set name="scanInterval">1</Set>
<Set name="configurationManager"> <Set name="configurationManager">
<New class="org.eclipse.jetty.deploy.FileConfigurationManager"> <New class="org.eclipse.jetty.deploy.PropertiesConfigurationManager">
<Set name="file"> <Set name="file">
<SystemProperty name="jetty.home"/>/xml-configured-jetty.properties <SystemProperty name="jetty.home"/>/xml-configured-jetty.properties
</Set> </Set>

View File

@ -17,7 +17,7 @@
<Set name="monitoredDirName"><SystemProperty name="jetty.home" />/webapps</Set> <Set name="monitoredDirName"><SystemProperty name="jetty.home" />/webapps</Set>
<Set name="scanInterval">1</Set> <Set name="scanInterval">1</Set>
<Set name="configurationManager"> <Set name="configurationManager">
<New class="org.eclipse.jetty.deploy.FileConfigurationManager"> <New class="org.eclipse.jetty.deploy.PropertiesConfigurationManager">
<Set name="file"> <Set name="file">
<SystemProperty name="jetty.home"/>/xml-configured-jetty.properties <SystemProperty name="jetty.home"/>/xml-configured-jetty.properties
</Set> </Set>

View File

@ -364,6 +364,12 @@
<version>${project.version}</version> <version>${project.version}</version>
</dependency> </dependency>
<dependency>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-jaas</artifactId>
<version>${project.version}</version>
</dependency>
<dependency> <dependency>
<groupId>org.eclipse.jetty</groupId> <groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-annotations</artifactId> <artifactId>jetty-annotations</artifactId>
@ -381,11 +387,6 @@
<artifactId>jetty-jndi</artifactId> <artifactId>jetty-jndi</artifactId>
<version>${project.version}</version> <version>${project.version}</version>
</dependency> </dependency>
<dependency>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-plus</artifactId>
<version>${project.version}</version>
</dependency>
<dependency> <dependency>
<groupId>org.eclipse.jetty</groupId> <groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-client</artifactId> <artifactId>jetty-client</artifactId>

View File

@ -1,13 +1,7 @@
<?xml version="1.0" encoding="ISO-8859-1"?> <?xml version="1.0" encoding="ISO-8859-1"?>
<!DOCTYPE Configure PUBLIC "-//Jetty//Configure//EN" "http://www.eclipse.org/jetty/configure.dtd"> <!DOCTYPE Configure PUBLIC "-//Jetty//Configure//EN" "http://www.eclipse.org/jetty/configure.dtd">
<!-- <!--Configure a context for the javadoc -->
Configure a custom context for the javadoc.
This context contains only a ServletHandler with a default servlet
to serve static html files and images.
-->
<Configure class="org.eclipse.jetty.server.handler.ContextHandler"> <Configure class="org.eclipse.jetty.server.handler.ContextHandler">
<Set name="contextPath">/javadoc</Set> <Set name="contextPath">/javadoc</Set>
<Set name="resourceBase"><SystemProperty name="jetty.home" default="."/>/javadoc/</Set> <Set name="resourceBase"><SystemProperty name="jetty.home" default="."/>/javadoc/</Set>
@ -21,6 +15,5 @@ to serve static html files and images.
<Set name="cacheControl">max-age=3600,public</Set> <Set name="cacheControl">max-age=3600,public</Set>
</New> </New>
</Set> </Set>
</Configure> </Configure>

View File

@ -810,7 +810,7 @@ public class HttpFields implements Iterable<HttpFields.Field>
{ {
hasDomain = true; hasDomain = true;
buf.append(";Domain="); buf.append(";Domain=");
QuotedStringTokenizer.quoteIfNeeded(buf,domain.toLowerCase(),delim); QuotedStringTokenizer.quoteIfNeeded(buf,domain.toLowerCase(Locale.ENGLISH),delim);
} }
if (maxAge >= 0) if (maxAge >= 0)

View File

@ -22,6 +22,7 @@ import java.nio.ByteBuffer;
import java.nio.charset.Charset; import java.nio.charset.Charset;
import java.util.Enumeration; import java.util.Enumeration;
import java.util.HashMap; import java.util.HashMap;
import java.util.Locale;
import java.util.Map; import java.util.Map;
import java.util.MissingResourceException; import java.util.MissingResourceException;
import java.util.ResourceBundle; import java.util.ResourceBundle;
@ -70,7 +71,7 @@ public class MimeTypes
_string=s; _string=s;
_buffer=BufferUtil.toBuffer(s); _buffer=BufferUtil.toBuffer(s);
int i=s.toLowerCase().indexOf("charset="); int i=s.toLowerCase(Locale.ENGLISH).indexOf("charset=");
_charset=(i>0)?Charset.forName(s.substring(i+8)):null; _charset=(i>0)?Charset.forName(s.substring(i+8)):null;
} }

View File

@ -171,6 +171,7 @@ xhtml=application/xhtml+xml
xls=application/vnd.ms-excel xls=application/vnd.ms-excel
xml=application/xml xml=application/xml
xpm=image/x-xpixmap xpm=image/x-xpixmap
xsd=application/xml
xsl=application/xml xsl=application/xml
xslt=application/xslt+xml xslt=application/xslt+xml
xul=application/vnd.mozilla.xul+xml xul=application/vnd.mozilla.xul+xml

View File

@ -21,6 +21,7 @@ package org.eclipse.jetty.http;
import java.nio.ByteBuffer; import java.nio.ByteBuffer;
import java.util.Enumeration; import java.util.Enumeration;
import java.util.HashSet; import java.util.HashSet;
import java.util.Locale;
import java.util.Set; import java.util.Set;
import org.eclipse.jetty.util.BufferUtil; import org.eclipse.jetty.util.BufferUtil;
@ -385,7 +386,7 @@ public class HttpFieldsTest
{ {
Set<String> s=new HashSet<String>(); Set<String> s=new HashSet<String>();
while(e.hasMoreElements()) while(e.hasMoreElements())
s.add(e.nextElement().toLowerCase()); s.add(e.nextElement().toLowerCase(Locale.ENGLISH));
return s; return s;
} }

View File

@ -45,7 +45,6 @@
</archive> </archive>
</configuration> </configuration>
</plugin> </plugin>
<!--
<plugin> <plugin>
<groupId>org.apache.maven.plugins</groupId> <groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-assembly-plugin</artifactId> <artifactId>maven-assembly-plugin</artifactId>
@ -63,7 +62,6 @@
</execution> </execution>
</executions> </executions>
</plugin> </plugin>
-->
<!-- always include the sources to be able to prepare the eclipse-jetty-SDK feature <!-- always include the sources to be able to prepare the eclipse-jetty-SDK feature
with a snapshot. --> with a snapshot. -->
<plugin> <plugin>

View File

@ -14,17 +14,4 @@
<Arg><SystemProperty name="jetty.home" default="." />/etc/login.conf</Arg> <Arg><SystemProperty name="jetty.home" default="." />/etc/login.conf</Arg>
</Call> </Call>
<!-- ======================================================== -->
<!-- An example JAAS realm setup -->
<!-- ======================================================== -->
<Call name="addBean">
<Arg>
<New class="org.eclipse.jetty.jaas.JAASLoginService">
<Set name="Name">Test JAAS Realm</Set>
<Set name="LoginModuleName">xyz</Set>
</New>
</Arg>
</Call>
</Configure> </Configure>

View File

@ -22,6 +22,7 @@ import java.io.IOException;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Hashtable; import java.util.Hashtable;
import java.util.List; import java.util.List;
import java.util.Locale;
import java.util.Map; import java.util.Map;
import java.util.Properties; import java.util.Properties;
import javax.naming.Context; import javax.naming.Context;
@ -652,12 +653,12 @@ public class LdapLoginModule extends AbstractLoginModule
public static String convertCredentialJettyToLdap(String encryptedPassword) public static String convertCredentialJettyToLdap(String encryptedPassword)
{ {
if ("MD5:".startsWith(encryptedPassword.toUpperCase())) if ("MD5:".startsWith(encryptedPassword.toUpperCase(Locale.ENGLISH)))
{ {
return "{MD5}" + encryptedPassword.substring("MD5:".length(), encryptedPassword.length()); return "{MD5}" + encryptedPassword.substring("MD5:".length(), encryptedPassword.length());
} }
if ("CRYPT:".startsWith(encryptedPassword.toUpperCase())) if ("CRYPT:".startsWith(encryptedPassword.toUpperCase(Locale.ENGLISH)))
{ {
return "{CRYPT}" + encryptedPassword.substring("CRYPT:".length(), encryptedPassword.length()); return "{CRYPT}" + encryptedPassword.substring("CRYPT:".length(), encryptedPassword.length());
} }
@ -672,12 +673,12 @@ public class LdapLoginModule extends AbstractLoginModule
return encryptedPassword; return encryptedPassword;
} }
if ("{MD5}".startsWith(encryptedPassword.toUpperCase())) if ("{MD5}".startsWith(encryptedPassword.toUpperCase(Locale.ENGLISH)))
{ {
return "MD5:" + encryptedPassword.substring("{MD5}".length(), encryptedPassword.length()); return "MD5:" + encryptedPassword.substring("{MD5}".length(), encryptedPassword.length());
} }
if ("{CRYPT}".startsWith(encryptedPassword.toUpperCase())) if ("{CRYPT}".startsWith(encryptedPassword.toUpperCase(Locale.ENGLISH)))
{ {
return "CRYPT:" + encryptedPassword.substring("{CRYPT}".length(), encryptedPassword.length()); return "CRYPT:" + encryptedPassword.substring("{CRYPT}".length(), encryptedPassword.length());
} }

View File

@ -20,6 +20,7 @@ package org.eclipse.jetty.jmx;
import java.io.IOException; import java.io.IOException;
import java.util.HashMap; import java.util.HashMap;
import java.util.Locale;
import java.util.Map; import java.util.Map;
import java.util.WeakHashMap; import java.util.WeakHashMap;
@ -164,7 +165,7 @@ public class MBeanContainer implements Container.InheritedListener, Dumpable
domain = obj.getClass().getPackage().getName(); domain = obj.getClass().getPackage().getName();
String type = obj.getClass().getName().toLowerCase(); String type = obj.getClass().getName().toLowerCase(Locale.ENGLISH);
int dot = type.lastIndexOf('.'); int dot = type.lastIndexOf('.');
if (dot >= 0) if (dot >= 0)
type = type.substring(dot + 1); type = type.substring(dot + 1);

View File

@ -30,6 +30,7 @@ import java.util.HashMap;
import java.util.HashSet; import java.util.HashSet;
import java.util.Iterator; import java.util.Iterator;
import java.util.List; import java.util.List;
import java.util.Locale;
import java.util.Map; import java.util.Map;
import java.util.Set; import java.util.Set;
import javax.management.Attribute; import javax.management.Attribute;
@ -622,7 +623,7 @@ public class ObjectMBean implements DynamicMBean
convert = true; convert = true;
} }
String uName = name.substring(0, 1).toUpperCase() + name.substring(1); String uName = name.substring(0, 1).toUpperCase(Locale.ENGLISH) + name.substring(1);
Class<?> oClass = onMBean ? this.getClass() : _managed.getClass(); Class<?> oClass = onMBean ? this.getClass() : _managed.getClass();
LOG.debug("defineAttribute {} {}:{}:{}:{}",name,onMBean,readonly,oClass,description); LOG.debug("defineAttribute {} {}:{}:{}:{}",name,onMBean,readonly,oClass,description);
@ -862,7 +863,7 @@ public class ObjectMBean implements DynamicMBean
variableName = variableName.substring(2); variableName = variableName.substring(2);
} }
variableName = variableName.substring(0,1).toLowerCase() + variableName.substring(1); variableName = variableName.substring(0,1).toLowerCase(Locale.ENGLISH) + variableName.substring(1);
return variableName; return variableName;
} }

View File

@ -483,7 +483,7 @@ public abstract class AbstractJettyMojo extends AbstractMojo
if (connectors == null || connectors.length == 0) if (connectors == null || connectors.length == 0)
{ {
//if a SystemProperty -Djetty.port=<portnum> has been supplied, use that as the default port //if a SystemProperty -Djetty.port=<portnum> has been supplied, use that as the default port
this.connectors = new Connector[] { this.server.createDefaultConnector(server, System.getProperty(PORT_SYSPROPERTY, null)) }; this.connectors = new Connector[] { this.server.createDefaultConnector(System.getProperty(PORT_SYSPROPERTY, null)) };
this.server.setConnectors(this.connectors); this.server.setConnectors(this.connectors);
} }
} }

View File

@ -16,58 +16,55 @@
// ======================================================================== // ========================================================================
// //
/**
*
*/
package org.eclipse.jetty.maven.plugin; package org.eclipse.jetty.maven.plugin;
import java.io.IOException; import java.io.IOException;
public class ConsoleScanner extends Thread public class ConsoleScanner extends Thread
{ {
private final AbstractJettyMojo mojo; private final AbstractJettyMojo mojo;
public ConsoleScanner(AbstractJettyMojo mojo) public ConsoleScanner(AbstractJettyMojo mojo)
{ {
this.mojo = mojo; this.mojo = mojo;
setName("Console scanner"); setName("Console scanner");
setDaemon(true); setDaemon(true);
} }
public void run() public void run()
{ {
try try
{ {
while (true) while (true)
{ {
checkSystemInput(); checkSystemInput();
getSomeSleep(); getSomeSleep();
} }
} }
catch (IOException e) catch (IOException e)
{ {
mojo.getLog().warn(e); mojo.getLog().warn(e);
} }
} }
private void getSomeSleep() private void getSomeSleep()
{ {
try try
{ {
Thread.sleep(500); Thread.sleep(500);
} }
catch (InterruptedException e) catch (InterruptedException e)
{ {
mojo.getLog().debug(e); mojo.getLog().debug(e);
} }
} }
private void checkSystemInput() throws IOException private void checkSystemInput() throws IOException
{ {
while (System.in.available() > 0) { while (System.in.available() > 0) {
int inputByte = System.in.read(); int inputByte = System.in.read();
if (inputByte >= 0) if (inputByte >= 0)
{ {
char c = (char)inputByte; char c = (char)inputByte;
if (c == '\n') { if (c == '\n') {
@ -76,12 +73,12 @@ public class ConsoleScanner extends Thread
} }
} }
} }
/** /**
* Skip buffered bytes of system console. * Skip buffered bytes of system console.
*/ */
private void clearInputBuffer() private void clearInputBuffer()
{ {
try try
{ {
@ -101,9 +98,9 @@ public class ConsoleScanner extends Thread
catch (IOException e) catch (IOException e)
{ {
mojo.getLog().warn("Error discarding console input buffer", e); mojo.getLog().warn("Error discarding console input buffer", e);
} }
} }
private void restartWebApp() private void restartWebApp()
{ {
try try

View File

@ -1,46 +1,45 @@
// //
// ======================================================================== // ========================================================================
// Copyright (c) 1995-2012 Mort Bay Consulting Pty. Ltd. // Copyright (c) 1995-2012 Mort Bay Consulting Pty. Ltd.
// ------------------------------------------------------------------------ // ------------------------------------------------------------------------
// All rights reserved. This program and the accompanying materials // All rights reserved. This program and the accompanying materials
// are made available under the terms of the Eclipse Public License v1.0 // are made available under the terms of the Eclipse Public License v1.0
// and Apache License v2.0 which accompanies this distribution. // and Apache License v2.0 which accompanies this distribution.
// //
// The Eclipse Public License is available at // The Eclipse Public License is available at
// http://www.eclipse.org/legal/epl-v10.html // http://www.eclipse.org/legal/epl-v10.html
// //
// The Apache License v2.0 is available at // The Apache License v2.0 is available at
// http://www.opensource.org/licenses/apache2.0.php // http://www.opensource.org/licenses/apache2.0.php
// //
// You may elect to redistribute this code under either of these licenses. // You may elect to redistribute this code under either of these licenses.
// ======================================================================== // ========================================================================
// //
package org.eclipse.jetty.maven.plugin; package org.eclipse.jetty.maven.plugin;
/**
/** * <p>
* <p> * This goal is used to run Jetty with a pre-assembled war.
* This goal is used to run Jetty with a pre-assembled war. * </p>
* </p> * <p>
* <p> * It accepts exactly the same options as the <a href="run-war-mojo.html">run-war</a> goal.
* It accepts exactly the same options as the <a href="run-war-mojo.html">run-war</a> goal. * However, it doesn't assume that the current artifact is a
* However, it doesn't assume that the current artifact is a * webapp and doesn't try to assemble it into a war before its execution.
* webapp and doesn't try to assemble it into a war before its execution. * So using it makes sense only when used in conjunction with the
* So using it makes sense only when used in conjunction with the * <a href="run-war-mojo.html#webApp">webApp</a> configuration parameter pointing to a pre-built WAR.
* <a href="run-war-mojo.html#webApp">webApp</a> configuration parameter pointing to a pre-built WAR. * </p>
* </p> * <p>
* <p> * This goal is useful e.g. for launching a web app in Jetty as a target for unit-tested
* This goal is useful e.g. for launching a web app in Jetty as a target for unit-tested * HTTP client components.
* HTTP client components. * </p>
* </p> *
* * @goal deploy-war
* @goal deploy-war * @requiresDependencyResolution runtime
* @requiresDependencyResolution runtime * @execute phase="validate"
* @execute phase="validate" * @description Deploy a pre-assembled war
* @description Deploy a pre-assembled war *
* */
*/ public class JettyDeployWar extends JettyRunWarMojo
public class JettyDeployWar extends JettyRunWarMojo {
{ }
}

View File

@ -18,23 +18,33 @@
package org.eclipse.jetty.maven.plugin; package org.eclipse.jetty.maven.plugin;
import java.io.BufferedInputStream;
import java.io.BufferedOutputStream; import java.io.BufferedOutputStream;
import java.io.BufferedReader; import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.File; import java.io.File;
import java.io.FileOutputStream; import java.io.FileOutputStream;
import java.io.FileWriter;
import java.io.IOException; import java.io.IOException;
import java.io.InputStream; import java.io.InputStream;
import java.io.InputStreamReader; import java.io.InputStreamReader;
import java.io.LineNumberReader; import java.io.LineNumberReader;
import java.net.MalformedURLException; import java.net.MalformedURLException;
import java.net.URL;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Arrays; import java.util.Arrays;
import java.util.HashSet; import java.util.HashSet;
import java.util.Iterator; import java.util.Iterator;
import java.util.List; import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.Properties; import java.util.Properties;
import java.util.Random; import java.util.Random;
import java.util.Set; import java.util.Set;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import org.apache.maven.artifact.Artifact; import org.apache.maven.artifact.Artifact;
import org.apache.maven.plugin.AbstractMojo; import org.apache.maven.plugin.AbstractMojo;
@ -42,7 +52,10 @@ import org.apache.maven.plugin.MojoExecutionException;
import org.apache.maven.plugin.MojoFailureException; import org.apache.maven.plugin.MojoFailureException;
import org.apache.maven.plugin.descriptor.PluginDescriptor; import org.apache.maven.plugin.descriptor.PluginDescriptor;
import org.apache.maven.project.MavenProject; import org.apache.maven.project.MavenProject;
import org.codehaus.plexus.component.repository.ComponentDependency;
import org.eclipse.jetty.server.RequestLog;
import org.eclipse.jetty.util.IO; import org.eclipse.jetty.util.IO;
import org.eclipse.jetty.util.resource.Resource;
/** /**
@ -64,7 +77,7 @@ import org.eclipse.jetty.util.IO;
* There is a <a href="run-war-mojo.html">reference guide</a> to the configuration parameters for this plugin, and more detailed information * There is a <a href="run-war-mojo.html">reference guide</a> to the configuration parameters for this plugin, and more detailed information
* with examples in the <a href="http://docs.codehaus.org/display/JETTY/Maven+Jetty+Plugin/">Configuration Guide</a>. * with examples in the <a href="http://docs.codehaus.org/display/JETTY/Maven+Jetty+Plugin/">Configuration Guide</a>.
* </p> * </p>
* *
* @goal run-forked * @goal run-forked
* @requiresDependencyResolution compile+runtime * @requiresDependencyResolution compile+runtime
* @execute phase="test-compile" * @execute phase="test-compile"
@ -72,17 +85,17 @@ import org.eclipse.jetty.util.IO;
* *
*/ */
public class JettyRunForkedMojo extends AbstractMojo public class JettyRunForkedMojo extends AbstractMojo
{ {
public String PORT_SYSPROPERTY = "jetty.port"; public String PORT_SYSPROPERTY = "jetty.port";
/** /**
* Whether or not to include dependencies on the plugin's classpath with &lt;scope&gt;provided&lt;/scope&gt; * Whether or not to include dependencies on the plugin's classpath with &lt;scope&gt;provided&lt;/scope&gt;
* Use WITH CAUTION as you may wind up with duplicate jars/classes. * Use WITH CAUTION as you may wind up with duplicate jars/classes.
* @parameter default-value="false" * @parameter default-value="false"
*/ */
protected boolean useProvidedScope; protected boolean useProvidedScope;
/** /**
* The maven project. * The maven project.
* *
@ -91,9 +104,9 @@ public class JettyRunForkedMojo extends AbstractMojo
* @readonly * @readonly
*/ */
private MavenProject project; private MavenProject project;
/** /**
* If true, the &lt;testOutputDirectory&gt; * If true, the &lt;testOutputDirectory&gt;
* and the dependencies of &lt;scope&gt;test&lt;scope&gt; * and the dependencies of &lt;scope&gt;test&lt;scope&gt;
@ -101,27 +114,27 @@ public class JettyRunForkedMojo extends AbstractMojo
* @parameter alias="useTestClasspath" default-value="false" * @parameter alias="useTestClasspath" default-value="false"
*/ */
private boolean useTestScope; private boolean useTestScope;
/** /**
* The default location of the web.xml file. Will be used * The default location of the web.xml file. Will be used
* if &lt;webAppConfig&gt;&lt;descriptor&gt; is not set. * if &lt;webAppConfig&gt;&lt;descriptor&gt; is not set.
* *
* @parameter expression="${basedir}/src/main/webapp/WEB-INF/web.xml" * @parameter expression="${basedir}/src/main/webapp/WEB-INF/web.xml"
* @readonly * @readonly
*/ */
private String webXml; private String webXml;
/** /**
* The target directory * The target directory
* *
* @parameter expression="${project.build.directory}" * @parameter expression="${project.build.directory}"
* @required * @required
* @readonly * @readonly
*/ */
protected File target; protected File target;
/** /**
* The temporary directory to use for the webapp. * The temporary directory to use for the webapp.
* Defaults to target/tmp * Defaults to target/tmp
@ -132,26 +145,26 @@ public class JettyRunForkedMojo extends AbstractMojo
*/ */
protected File tmpDirectory; protected File tmpDirectory;
/** /**
* The directory containing generated classes. * The directory containing generated classes.
* *
* @parameter expression="${project.build.outputDirectory}" * @parameter expression="${project.build.outputDirectory}"
* @required * @required
* *
*/ */
private File classesDirectory; private File classesDirectory;
/** /**
* The directory containing generated test classes. * The directory containing generated test classes.
* *
* @parameter expression="${project.build.testOutputDirectory}" * @parameter expression="${project.build.testOutputDirectory}"
* @required * @required
*/ */
private File testClassesDirectory; private File testClassesDirectory;
/** /**
* Root directory for all html/jsp etc files * Root directory for all html/jsp etc files
* *
@ -159,34 +172,34 @@ public class JettyRunForkedMojo extends AbstractMojo
* *
*/ */
private File webAppSourceDirectory; private File webAppSourceDirectory;
/** /**
* Directories that contain static resources * Directories that contain static resources
* for the webapp. Optional. * for the webapp. Optional.
* *
* @parameter * @parameter
*/ */
private File[] resourceBases; private File[] resourceBases;
/** /**
* If true, the webAppSourceDirectory will be first on the list of * If true, the webAppSourceDirectory will be first on the list of
* resources that form the resource base for the webapp. If false, * resources that form the resource base for the webapp. If false,
* it will be last. * it will be last.
* *
* @parameter default-value="true" * @parameter default-value="true"
*/ */
private boolean baseAppFirst; private boolean baseAppFirst;
/** /**
* Location of jetty xml configuration files whose contents * Location of jetty xml configuration files whose contents
* will be applied before any plugin configuration. Optional. * will be applied before any plugin configuration. Optional.
* @parameter * @parameter
*/ */
private String jettyXml; private String jettyXml;
/** /**
* The context path for the webapp. Defaults to the * The context path for the webapp. Defaults to the
* name of the webapp's artifact. * name of the webapp's artifact.
@ -205,71 +218,71 @@ public class JettyRunForkedMojo extends AbstractMojo
*/ */
private String contextXml; private String contextXml;
/** /**
* @parameter expression="${jetty.skip}" default-value="false" * @parameter expression="${jetty.skip}" default-value="false"
*/ */
private boolean skip; private boolean skip;
/** /**
* Port to listen to stop jetty on executing -DSTOP.PORT=&lt;stopPort&gt; * Port to listen to stop jetty on executing -DSTOP.PORT=&lt;stopPort&gt;
* -DSTOP.KEY=&lt;stopKey&gt; -jar start.jar --stop * -DSTOP.KEY=&lt;stopKey&gt; -jar start.jar --stop
* @parameter * @parameter
* @required * @required
*/ */
protected int stopPort; protected int stopPort;
/** /**
* Key to provide when stopping jetty on executing java -DSTOP.KEY=&lt;stopKey&gt; * Key to provide when stopping jetty on executing java -DSTOP.KEY=&lt;stopKey&gt;
* -DSTOP.PORT=&lt;stopPort&gt; -jar start.jar --stop * -DSTOP.PORT=&lt;stopPort&gt; -jar start.jar --stop
* @parameter * @parameter
* @required * @required
*/ */
protected String stopKey; protected String stopKey;
/** /**
* Arbitrary jvm args to pass to the forked process * Arbitrary jvm args to pass to the forked process
* @parameter * @parameter
*/ */
private String jvmArgs; private String jvmArgs;
/** /**
* @parameter expression="${plugin.artifacts}" * @parameter expression="${plugin.artifacts}"
* @readonly * @readonly
*/ */
private List pluginArtifacts; private List pluginArtifacts;
/** /**
* @parameter expression="${plugin}" * @parameter expression="${plugin}"
* @readonly * @readonly
*/ */
private PluginDescriptor plugin; private PluginDescriptor plugin;
/** /**
* @parameter expression="true" default-value="true" * @parameter expression="true" default-value="true"
*/ */
private boolean waitForChild; private boolean waitForChild;
private Process forkedProcess; private Process forkedProcess;
private Random random; private Random random;
public class ShutdownThread extends Thread public class ShutdownThread extends Thread
{ {
public ShutdownThread() public ShutdownThread()
{ {
super("RunForkedShutdown"); super("RunForkedShutdown");
} }
public void run () public void run ()
{ {
if (forkedProcess != null && waitForChild) if (forkedProcess != null && waitForChild)
@ -278,7 +291,7 @@ public class JettyRunForkedMojo extends AbstractMojo
} }
} }
} }
/** /**
* @see org.apache.maven.plugin.Mojo#execute() * @see org.apache.maven.plugin.Mojo#execute()
*/ */
@ -295,20 +308,20 @@ public class JettyRunForkedMojo extends AbstractMojo
random = new Random(); random = new Random();
startJettyRunner(); startJettyRunner();
} }
public List<String> getProvidedJars() throws MojoExecutionException public List<String> getProvidedJars() throws MojoExecutionException
{ {
//if we are configured to include the provided dependencies on the plugin's classpath //if we are configured to include the provided dependencies on the plugin's classpath
//(which mimics being on jetty's classpath vs being on the webapp's classpath), we first //(which mimics being on jetty's classpath vs being on the webapp's classpath), we first
//try and filter out ones that will clash with jars that are plugin dependencies, then //try and filter out ones that will clash with jars that are plugin dependencies, then
//create a new classloader that we setup in the parent chain. //create a new classloader that we setup in the parent chain.
if (useProvidedScope) if (useProvidedScope)
{ {
List<String> provided = new ArrayList<String>(); List<String> provided = new ArrayList<String>();
for ( Iterator<Artifact> iter = project.getArtifacts().iterator(); iter.hasNext(); ) for ( Iterator<Artifact> iter = project.getArtifacts().iterator(); iter.hasNext(); )
{ {
Artifact artifact = iter.next(); Artifact artifact = iter.next();
if (Artifact.SCOPE_PROVIDED.equals(artifact.getScope()) && !isPluginArtifact(artifact)) if (Artifact.SCOPE_PROVIDED.equals(artifact.getScope()) && !isPluginArtifact(artifact))
{ {
@ -322,16 +335,16 @@ public class JettyRunForkedMojo extends AbstractMojo
else else
return null; return null;
} }
/* ------------------------------------------------------------ */ /* ------------------------------------------------------------ */
public File prepareConfiguration() throws MojoExecutionException public File prepareConfiguration() throws MojoExecutionException
{ {
try try
{ {
//work out the configuration based on what is configured in the pom //work out the configuration based on what is configured in the pom
File propsFile = new File (target, "fork.props"); File propsFile = new File (target, "fork.props");
if (propsFile.exists()) if (propsFile.exists())
propsFile.delete(); propsFile.delete();
propsFile.createNewFile(); propsFile.createNewFile();
//propsFile.deleteOnExit(); //propsFile.deleteOnExit();
@ -358,9 +371,9 @@ public class JettyRunForkedMojo extends AbstractMojo
//sort out base dir of webapp //sort out base dir of webapp
if (webAppSourceDirectory != null) if (webAppSourceDirectory != null)
props.put("base.dir", webAppSourceDirectory.getAbsolutePath()); props.put("base.dir", webAppSourceDirectory.getAbsolutePath());
//sort out the resource base directories of the webapp //sort out the resource base directories of the webapp
StringBuilder builder = new StringBuilder(); StringBuilder builder = new StringBuilder();
if (baseAppFirst) if (baseAppFirst)
{ {
add((webAppSourceDirectory==null?null:webAppSourceDirectory.getAbsolutePath()), builder); add((webAppSourceDirectory==null?null:webAppSourceDirectory.getAbsolutePath()), builder);
@ -371,7 +384,7 @@ public class JettyRunForkedMojo extends AbstractMojo
} }
} }
else else
{ {
if (resourceBases != null) if (resourceBases != null)
{ {
for (File resDir:resourceBases) for (File resDir:resourceBases)
@ -380,7 +393,7 @@ public class JettyRunForkedMojo extends AbstractMojo
add((webAppSourceDirectory==null?null:webAppSourceDirectory.getAbsolutePath()), builder); add((webAppSourceDirectory==null?null:webAppSourceDirectory.getAbsolutePath()), builder);
} }
props.put("res.dirs", builder.toString()); props.put("res.dirs", builder.toString());
//web-inf classes //web-inf classes
List<File> classDirs = getClassesDirs(); List<File> classDirs = getClassesDirs();
@ -397,7 +410,7 @@ public class JettyRunForkedMojo extends AbstractMojo
{ {
props.put("classes.dir", classesDirectory.getAbsolutePath()); props.put("classes.dir", classesDirectory.getAbsolutePath());
} }
if (useTestScope && testClassesDirectory != null) if (useTestScope && testClassesDirectory != null)
{ {
props.put("testClasses.dir", testClassesDirectory.getAbsolutePath()); props.put("testClasses.dir", testClassesDirectory.getAbsolutePath());
@ -435,7 +448,7 @@ public class JettyRunForkedMojo extends AbstractMojo
throw new MojoExecutionException("Prepare webapp configuration", e); throw new MojoExecutionException("Prepare webapp configuration", e);
} }
} }
private void add (String string, StringBuilder builder) private void add (String string, StringBuilder builder)
{ {
if (string == null) if (string == null)
@ -448,62 +461,62 @@ public class JettyRunForkedMojo extends AbstractMojo
private List<File> getClassesDirs () private List<File> getClassesDirs ()
{ {
List<File> classesDirs = new ArrayList<File>(); List<File> classesDirs = new ArrayList<File>();
//if using the test classes, make sure they are first //if using the test classes, make sure they are first
//on the list //on the list
if (useTestScope && (testClassesDirectory != null)) if (useTestScope && (testClassesDirectory != null))
classesDirs.add(testClassesDirectory); classesDirs.add(testClassesDirectory);
if (classesDirectory != null) if (classesDirectory != null)
classesDirs.add(classesDirectory); classesDirs.add(classesDirectory);
return classesDirs; return classesDirs;
} }
private List<File> getOverlays() private List<File> getOverlays()
throws MalformedURLException, IOException throws MalformedURLException, IOException
{ {
List<File> overlays = new ArrayList<File>(); List<File> overlays = new ArrayList<File>();
for ( Iterator<Artifact> iter = project.getArtifacts().iterator(); iter.hasNext(); ) for ( Iterator<Artifact> iter = project.getArtifacts().iterator(); iter.hasNext(); )
{ {
Artifact artifact = (Artifact) iter.next(); Artifact artifact = (Artifact) iter.next();
if (artifact.getType().equals("war")) if (artifact.getType().equals("war"))
overlays.add(artifact.getFile()); overlays.add(artifact.getFile());
} }
return overlays; return overlays;
} }
private List<File> getDependencyFiles () private List<File> getDependencyFiles ()
{ {
List<File> dependencyFiles = new ArrayList<File>(); List<File> dependencyFiles = new ArrayList<File>();
for ( Iterator<Artifact> iter = project.getArtifacts().iterator(); iter.hasNext(); ) for ( Iterator<Artifact> iter = project.getArtifacts().iterator(); iter.hasNext(); )
{ {
Artifact artifact = (Artifact) iter.next(); Artifact artifact = (Artifact) iter.next();
if (((!Artifact.SCOPE_PROVIDED.equals(artifact.getScope())) && (!Artifact.SCOPE_TEST.equals( artifact.getScope()))) if (((!Artifact.SCOPE_PROVIDED.equals(artifact.getScope())) && (!Artifact.SCOPE_TEST.equals( artifact.getScope())))
|| ||
(useTestScope && Artifact.SCOPE_TEST.equals( artifact.getScope()))) (useTestScope && Artifact.SCOPE_TEST.equals( artifact.getScope())))
{ {
dependencyFiles.add(artifact.getFile()); dependencyFiles.add(artifact.getFile());
getLog().debug( "Adding artifact " + artifact.getFile().getName() + " for WEB-INF/lib " ); getLog().debug( "Adding artifact " + artifact.getFile().getName() + " for WEB-INF/lib " );
} }
} }
return dependencyFiles; return dependencyFiles;
} }
public boolean isPluginArtifact(Artifact artifact) public boolean isPluginArtifact(Artifact artifact)
{ {
if (pluginArtifacts == null || pluginArtifacts.isEmpty()) if (pluginArtifacts == null || pluginArtifacts.isEmpty())
return false; return false;
boolean isPluginArtifact = false; boolean isPluginArtifact = false;
for (Iterator<Artifact> iter = pluginArtifacts.iterator(); iter.hasNext() && !isPluginArtifact; ) for (Iterator<Artifact> iter = pluginArtifacts.iterator(); iter.hasNext() && !isPluginArtifact; )
{ {
@ -512,18 +525,18 @@ public class JettyRunForkedMojo extends AbstractMojo
if (pluginArtifact.getGroupId().equals(artifact.getGroupId()) && pluginArtifact.getArtifactId().equals(artifact.getArtifactId())) if (pluginArtifact.getGroupId().equals(artifact.getGroupId()) && pluginArtifact.getArtifactId().equals(artifact.getArtifactId()))
isPluginArtifact = true; isPluginArtifact = true;
} }
return isPluginArtifact; return isPluginArtifact;
} }
private Set<Artifact> getExtraJars() private Set<Artifact> getExtraJars()
throws Exception throws Exception
{ {
Set<Artifact> extraJars = new HashSet<Artifact>(); Set<Artifact> extraJars = new HashSet<Artifact>();
List l = pluginArtifacts; List l = pluginArtifacts;
Artifact pluginArtifact = null; Artifact pluginArtifact = null;
@ -531,7 +544,7 @@ public class JettyRunForkedMojo extends AbstractMojo
{ {
Iterator itor = l.iterator(); Iterator itor = l.iterator();
while (itor.hasNext() && pluginArtifact == null) while (itor.hasNext() && pluginArtifact == null)
{ {
Artifact a = (Artifact)itor.next(); Artifact a = (Artifact)itor.next();
if (a.getArtifactId().equals(plugin.getArtifactId())) //get the jetty-maven-plugin jar if (a.getArtifactId().equals(plugin.getArtifactId())) //get the jetty-maven-plugin jar
{ {
@ -543,18 +556,18 @@ public class JettyRunForkedMojo extends AbstractMojo
return extraJars; return extraJars;
} }
/* ------------------------------------------------------------ */ /* ------------------------------------------------------------ */
public void startJettyRunner() throws MojoExecutionException public void startJettyRunner() throws MojoExecutionException
{ {
try try
{ {
File props = prepareConfiguration(); File props = prepareConfiguration();
List<String> cmd = new ArrayList<String>(); List<String> cmd = new ArrayList<String>();
cmd.add(getJavaBin()); cmd.add(getJavaBin());
if (jvmArgs != null) if (jvmArgs != null)
{ {
String[] args = jvmArgs.split(" "); String[] args = jvmArgs.split(" ");
@ -564,7 +577,7 @@ public class JettyRunForkedMojo extends AbstractMojo
cmd.add(args[i].trim()); cmd.add(args[i].trim());
} }
} }
String classPath = getClassPath(); String classPath = getClassPath();
if (classPath != null && classPath.length() > 0) if (classPath != null && classPath.length() > 0)
{ {
@ -572,7 +585,7 @@ public class JettyRunForkedMojo extends AbstractMojo
cmd.add(classPath); cmd.add(classPath);
} }
cmd.add(Starter.class.getCanonicalName()); cmd.add(Starter.class.getCanonicalName());
if (stopPort > 0 && stopKey != null) if (stopPort > 0 && stopKey != null)
{ {
cmd.add("--stop-port"); cmd.add("--stop-port");
@ -585,26 +598,26 @@ public class JettyRunForkedMojo extends AbstractMojo
cmd.add("--jetty-xml"); cmd.add("--jetty-xml");
cmd.add(jettyXml); cmd.add(jettyXml);
} }
if (contextXml != null) if (contextXml != null)
{ {
cmd.add("--context-xml"); cmd.add("--context-xml");
cmd.add(contextXml); cmd.add(contextXml);
} }
cmd.add("--props"); cmd.add("--props");
cmd.add(props.getAbsolutePath()); cmd.add(props.getAbsolutePath());
String token = createToken(); String token = createToken();
cmd.add("--token"); cmd.add("--token");
cmd.add(token); cmd.add(token);
ProcessBuilder builder = new ProcessBuilder(cmd); ProcessBuilder builder = new ProcessBuilder(cmd);
builder.directory(project.getBasedir()); builder.directory(project.getBasedir());
if (PluginLog.getLog().isDebugEnabled()) if (PluginLog.getLog().isDebugEnabled())
PluginLog.getLog().debug(Arrays.toString(cmd.toArray())); PluginLog.getLog().debug(Arrays.toString(cmd.toArray()));
forkedProcess = builder.start(); forkedProcess = builder.start();
PluginLog.getLog().info("Forked process starting"); PluginLog.getLog().info("Forked process starting");
@ -612,7 +625,7 @@ public class JettyRunForkedMojo extends AbstractMojo
{ {
startPump("STDOUT",forkedProcess.getInputStream()); startPump("STDOUT",forkedProcess.getInputStream());
startPump("STDERR",forkedProcess.getErrorStream()); startPump("STDERR",forkedProcess.getErrorStream());
int exitcode = forkedProcess.waitFor(); int exitcode = forkedProcess.waitFor();
PluginLog.getLog().info("Forked execution exit: "+exitcode); PluginLog.getLog().info("Forked execution exit: "+exitcode);
} }
else else
@ -652,20 +665,20 @@ public class JettyRunForkedMojo extends AbstractMojo
{ {
if (forkedProcess != null && waitForChild) if (forkedProcess != null && waitForChild)
forkedProcess.destroy(); forkedProcess.destroy();
throw new MojoExecutionException("Failed to start Jetty within time limit"); throw new MojoExecutionException("Failed to start Jetty within time limit");
} }
catch (Exception ex) catch (Exception ex)
{ {
if (forkedProcess != null && waitForChild) if (forkedProcess != null && waitForChild)
forkedProcess.destroy(); forkedProcess.destroy();
throw new MojoExecutionException("Failed to create Jetty process", ex); throw new MojoExecutionException("Failed to create Jetty process", ex);
} }
} }
public String getClassPath() throws Exception public String getClassPath() throws Exception
{ {
StringBuilder classPath = new StringBuilder(); StringBuilder classPath = new StringBuilder();
@ -682,16 +695,16 @@ public class JettyRunForkedMojo extends AbstractMojo
} }
} }
//Any jars that we need from the plugin environment (like the ones containing Starter class) //Any jars that we need from the plugin environment (like the ones containing Starter class)
Set<Artifact> extraJars = getExtraJars(); Set<Artifact> extraJars = getExtraJars();
for (Artifact a:extraJars) for (Artifact a:extraJars)
{ {
classPath.append(File.pathSeparator); classPath.append(File.pathSeparator);
classPath.append(a.getFile().getAbsolutePath()); classPath.append(a.getFile().getAbsolutePath());
} }
//Any jars that we need from the project's dependencies because we're useProvided //Any jars that we need from the project's dependencies because we're useProvided
List<String> providedJars = getProvidedJars(); List<String> providedJars = getProvidedJars();
if (providedJars != null && !providedJars.isEmpty()) if (providedJars != null && !providedJars.isEmpty())
@ -703,7 +716,7 @@ public class JettyRunForkedMojo extends AbstractMojo
if (getLog().isDebugEnabled()) getLog().debug("Adding provided jar: "+jar); if (getLog().isDebugEnabled()) getLog().debug("Adding provided jar: "+jar);
} }
} }
return classPath.toString(); return classPath.toString();
} }
@ -724,7 +737,7 @@ public class JettyRunForkedMojo extends AbstractMojo
return "java"; return "java";
} }
public static String fileSeparators(String path) public static String fileSeparators(String path)
{ {
StringBuilder ret = new StringBuilder(); StringBuilder ret = new StringBuilder();
@ -759,13 +772,13 @@ public class JettyRunForkedMojo extends AbstractMojo
return ret.toString(); return ret.toString();
} }
private String createToken () private String createToken ()
{ {
return Long.toString(random.nextLong()^System.currentTimeMillis(), 36).toUpperCase(); return Long.toString(random.nextLong()^System.currentTimeMillis(), 36).toUpperCase(Locale.ENGLISH);
} }
private void startPump(String mode, InputStream inputStream) private void startPump(String mode, InputStream inputStream)
{ {
ConsoleStreamer pump = new ConsoleStreamer(mode,inputStream); ConsoleStreamer pump = new ConsoleStreamer(mode,inputStream);
@ -774,7 +787,7 @@ public class JettyRunForkedMojo extends AbstractMojo
thread.start(); thread.start();
} }
/** /**

View File

@ -63,6 +63,9 @@ import org.eclipse.jetty.webapp.WebAppContext;
*/ */
public class JettyRunMojo extends AbstractJettyMojo public class JettyRunMojo extends AbstractJettyMojo
{ {
public static final String DEFAULT_WEBAPP_SRC = "src"+File.separator+"main"+File.separator+"webapp";
/** /**
* If true, the &lt;testOutputDirectory&gt; * If true, the &lt;testOutputDirectory&gt;
* and the dependencies of &lt;scope&gt;test&lt;scope&gt; * and the dependencies of &lt;scope&gt;test&lt;scope&gt;
@ -134,12 +137,13 @@ public class JettyRunMojo extends AbstractJettyMojo
*/ */
private List<File> extraScanTargets; private List<File> extraScanTargets;
/** /**
* Verify the configuration given in the pom. * Verify the configuration given in the pom.
* *
* @see org.eclipse.jetty.maven.plugin.AbstractJettyMojo#checkPomConfiguration() * @see org.mortbay.jetty.plugin.AbstractJettyMojo#checkPomConfiguration()
*/ */
public void checkPomConfiguration () throws MojoExecutionException public void checkPomConfiguration () throws MojoExecutionException
{ {
@ -147,9 +151,10 @@ public class JettyRunMojo extends AbstractJettyMojo
try try
{ {
if ((getWebAppSourceDirectory() == null) || !getWebAppSourceDirectory().exists()) if ((getWebAppSourceDirectory() == null) || !getWebAppSourceDirectory().exists())
{ {
webAppSourceDirectory = new File (project.getBasedir(), "src"+File.separator+"main"+File.separator+"webapp"); File defaultWebAppSrcDir = new File (project.getBasedir(), DEFAULT_WEBAPP_SRC);
getLog().info("webAppSourceDirectory "+getWebAppSourceDirectory() +" does not exist. Defaulting to "+webAppSourceDirectory.getAbsolutePath()); getLog().info("webAppSourceDirectory"+(getWebAppSourceDirectory()==null?" not set.":" does not exist.")+" Defaulting to "+defaultWebAppSrcDir.getAbsolutePath());
webAppSourceDirectory = defaultWebAppSrcDir;
} }
else else
getLog().info( "Webapp source directory = " + getWebAppSourceDirectory().getCanonicalPath()); getLog().info( "Webapp source directory = " + getWebAppSourceDirectory().getCanonicalPath());
@ -441,6 +446,7 @@ public class JettyRunMojo extends AbstractJettyMojo
for ( Iterator<Artifact> iter = projectArtifacts.iterator(); iter.hasNext(); ) for ( Iterator<Artifact> iter = projectArtifacts.iterator(); iter.hasNext(); )
{ {
Artifact artifact = (Artifact) iter.next(); Artifact artifact = (Artifact) iter.next();
// Include runtime and compile time libraries, and possibly test libs too // Include runtime and compile time libraries, and possibly test libs too
if(artifact.getType().equals("war")) if(artifact.getType().equals("war"))
{ {
@ -448,6 +454,7 @@ public class JettyRunMojo extends AbstractJettyMojo
{ {
Resource r=Resource.newResource("jar:"+Resource.toURL(artifact.getFile()).toString()+"!/"); Resource r=Resource.newResource("jar:"+Resource.toURL(artifact.getFile()).toString()+"!/");
overlays.add(r); overlays.add(r);
getLog().info("Adding overlay for war project artifact "+artifact.getId());
getExtraScanTargets().add(artifact.getFile()); getExtraScanTargets().add(artifact.getFile());
} }
catch(Exception e) catch(Exception e)

View File

@ -25,19 +25,21 @@ import java.util.List;
import org.apache.maven.plugin.MojoExecutionException; import org.apache.maven.plugin.MojoExecutionException;
import org.apache.maven.plugin.MojoFailureException; import org.apache.maven.plugin.MojoFailureException;
import org.eclipse.jetty.util.Scanner; import org.eclipse.jetty.util.Scanner;
import org.eclipse.jetty.util.resource.Resource;
import org.eclipse.jetty.xml.XmlConfiguration;
/** /**
* *
* <p> * <p>
* This goal is used to assemble your webapp into an exploded war and automatically deploy it to Jetty. * This goal is used to assemble your webapp into an exploded war and automatically deploy it to Jetty.
* </p> * </p>
* <p> * <p>
* Once invoked, the plugin can be configured to run continuously, scanning for changes in the pom.xml and * Once invoked, the plugin can be configured to run continuously, scanning for changes in the pom.xml and
* to WEB-INF/web.xml, WEB-INF/classes or WEB-INF/lib and hot redeploy when a change is detected. * to WEB-INF/web.xml, WEB-INF/classes or WEB-INF/lib and hot redeploy when a change is detected.
* </p> * </p>
* <p> * <p>
* You may also specify the location of a jetty.xml file whose contents will be applied before any plugin configuration. * You may also specify the location of a jetty.xml file whose contents will be applied before any plugin configuration.
* This can be used, for example, to deploy a static webapp that is not part of your maven build. * This can be used, for example, to deploy a static webapp that is not part of your maven build.
* </p> * </p>
* <p> * <p>
* There is a <a href="run-exploded-mojo.html">reference guide</a> to the configuration parameters for this plugin, and more detailed information * There is a <a href="run-exploded-mojo.html">reference guide</a> to the configuration parameters for this plugin, and more detailed information
@ -51,24 +53,24 @@ import org.eclipse.jetty.util.Scanner;
public class JettyRunWarExplodedMojo extends AbstractJettyMojo public class JettyRunWarExplodedMojo extends AbstractJettyMojo
{ {
/** /**
* The location of the war file. * The location of the war file.
* *
* @parameter alias="webApp" expression="${project.build.directory}/${project.build.finalName}" * @parameter alias="webApp" expression="${project.build.directory}/${project.build.finalName}"
* @required * @required
*/ */
private File war; private File war;
/** /**
* *
* @see org.eclipse.jetty.maven.plugin.AbstractJettyMojo#checkPomConfiguration() * @see org.mortbay.jetty.plugin.AbstractJettyMojo#checkPomConfiguration()
*/ */
public void checkPomConfiguration() throws MojoExecutionException public void checkPomConfiguration() throws MojoExecutionException
{ {
@ -76,7 +78,7 @@ public class JettyRunWarExplodedMojo extends AbstractJettyMojo
} }
/** /**
* @see org.eclipse.jetty.maven.plugin.AbstractJettyMojo#configureScanner() * @see org.mortbay.jetty.plugin.AbstractJettyMojo#configureScanner()
*/ */
public void configureScanner() throws MojoExecutionException public void configureScanner() throws MojoExecutionException
{ {
@ -93,7 +95,7 @@ public class JettyRunWarExplodedMojo extends AbstractJettyMojo
scanList.add(new File(webInfDir, "classes")); scanList.add(new File(webInfDir, "classes"));
scanList.add(new File(webInfDir, "lib")); scanList.add(new File(webInfDir, "lib"));
setScanList(scanList); setScanList(scanList);
ArrayList<Scanner.BulkListener> listeners = new ArrayList<Scanner.BulkListener>(); ArrayList<Scanner.BulkListener> listeners = new ArrayList<Scanner.BulkListener>();
listeners.add(new Scanner.BulkListener() listeners.add(new Scanner.BulkListener()
{ {
@ -113,10 +115,10 @@ public class JettyRunWarExplodedMojo extends AbstractJettyMojo
setScannerListeners(listeners); setScannerListeners(listeners);
} }
public void restartWebApp(boolean reconfigureScanner) throws Exception public void restartWebApp(boolean reconfigureScanner) throws Exception
{ {
getLog().info("Restarting webapp"); getLog().info("Restarting webapp");
getLog().debug("Stopping webapp ..."); getLog().debug("Stopping webapp ...");
@ -152,20 +154,20 @@ public class JettyRunWarExplodedMojo extends AbstractJettyMojo
getLog().info("Restart completed."); getLog().info("Restart completed.");
} }
public void configureWebApplication () throws Exception public void configureWebApplication () throws Exception
{ {
super.configureWebApplication(); super.configureWebApplication();
webApp.setWar(war.getCanonicalPath()); webApp.setWar(war.getCanonicalPath());
} }
public void execute () throws MojoExecutionException, MojoFailureException public void execute () throws MojoExecutionException, MojoFailureException
{ {
super.execute(); super.execute();
} }
} }

View File

@ -21,10 +21,14 @@ package org.eclipse.jetty.maven.plugin;
import java.io.File; import java.io.File;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
import java.util.Set;
import org.apache.maven.artifact.Artifact;
import org.apache.maven.plugin.MojoExecutionException; import org.apache.maven.plugin.MojoExecutionException;
import org.apache.maven.plugin.MojoFailureException; import org.apache.maven.plugin.MojoFailureException;
import org.eclipse.jetty.util.Scanner; import org.eclipse.jetty.util.Scanner;
import org.eclipse.jetty.util.resource.Resource;
import org.eclipse.jetty.xml.XmlConfiguration;
/** /**
* <p> * <p>
@ -32,18 +36,18 @@ import org.eclipse.jetty.util.Scanner;
* </p> * </p>
* <p> * <p>
* Once invoked, the plugin can be configured to run continuously, scanning for changes in the project and to the * Once invoked, the plugin can be configured to run continuously, scanning for changes in the project and to the
* war file and automatically performing a * war file and automatically performing a
* hot redeploy when necessary. * hot redeploy when necessary.
* </p> * </p>
* <p> * <p>
* You may also specify the location of a jetty.xml file whose contents will be applied before any plugin configuration. * You may also specify the location of a jetty.xml file whose contents will be applied before any plugin configuration.
* This can be used, for example, to deploy a static webapp that is not part of your maven build. * This can be used, for example, to deploy a static webapp that is not part of your maven build.
* </p> * </p>
* <p> * <p>
* There is a <a href="run-war-mojo.html">reference guide</a> to the configuration parameters for this plugin, and more detailed information * There is a <a href="run-war-mojo.html">reference guide</a> to the configuration parameters for this plugin, and more detailed information
* with examples in the <a href="http://docs.codehaus.org/display/JETTY/Maven+Jetty+Plugin/">Configuration Guide</a>. * with examples in the <a href="http://docs.codehaus.org/display/JETTY/Maven+Jetty+Plugin/">Configuration Guide</a>.
* </p> * </p>
* *
* @goal run-war * @goal run-war
* @requiresDependencyResolution compile+runtime * @requiresDependencyResolution compile+runtime
* @execute phase="package" * @execute phase="package"
@ -61,13 +65,13 @@ public class JettyRunWarMojo extends AbstractJettyMojo
private File war; private File war;
/** /**
* @see org.apache.maven.plugin.Mojo#execute() * @see org.apache.maven.plugin.Mojo#execute()
*/ */
public void execute() throws MojoExecutionException, MojoFailureException public void execute() throws MojoExecutionException, MojoFailureException
{ {
super.execute(); super.execute();
} }
@ -75,18 +79,18 @@ public class JettyRunWarMojo extends AbstractJettyMojo
public void configureWebApplication () throws Exception public void configureWebApplication () throws Exception
{ {
super.configureWebApplication(); super.configureWebApplication();
webApp.setWar(war.getCanonicalPath()); webApp.setWar(war.getCanonicalPath());
} }
/** /**
* @see org.eclipse.jetty.maven.plugin.AbstractJettyMojo#checkPomConfiguration() * @see org.mortbay.jetty.plugin.AbstractJettyMojo#checkPomConfiguration()
*/ */
public void checkPomConfiguration() throws MojoExecutionException public void checkPomConfiguration() throws MojoExecutionException
{ {
return; return;
} }
@ -100,7 +104,7 @@ public class JettyRunWarMojo extends AbstractJettyMojo
scanList.add(getProject().getFile()); scanList.add(getProject().getFile());
scanList.add(war); scanList.add(war);
setScanList(scanList); setScanList(scanList);
ArrayList listeners = new ArrayList(); ArrayList listeners = new ArrayList();
listeners.add(new Scanner.BulkListener() listeners.add(new Scanner.BulkListener()
{ {
@ -117,11 +121,11 @@ public class JettyRunWarMojo extends AbstractJettyMojo
} }
} }
}); });
setScannerListeners(listeners); setScannerListeners(listeners);
} }
public void restartWebApp(boolean reconfigureScanner) throws Exception public void restartWebApp(boolean reconfigureScanner) throws Exception
{ {
getLog().info("Restarting webapp ..."); getLog().info("Restarting webapp ...");
getLog().debug("Stopping webapp ..."); getLog().debug("Stopping webapp ...");

View File

@ -23,7 +23,6 @@ import org.eclipse.jetty.server.Connector;
import org.eclipse.jetty.server.Handler; import org.eclipse.jetty.server.Handler;
import org.eclipse.jetty.server.RequestLog; import org.eclipse.jetty.server.RequestLog;
import org.eclipse.jetty.server.ServerConnector; import org.eclipse.jetty.server.ServerConnector;
import org.eclipse.jetty.server.Server;
import org.eclipse.jetty.server.handler.ContextHandlerCollection; import org.eclipse.jetty.server.handler.ContextHandlerCollection;
import org.eclipse.jetty.server.handler.DefaultHandler; import org.eclipse.jetty.server.handler.DefaultHandler;
import org.eclipse.jetty.server.handler.HandlerCollection; import org.eclipse.jetty.server.handler.HandlerCollection;
@ -33,20 +32,20 @@ import org.eclipse.jetty.webapp.WebAppContext;
/** /**
* JettyServer * JettyServer
* *
* Maven jetty plugin version of a wrapper for the Server class. * Maven jetty plugin version of a wrapper for the Server class.
* *
*/ */
public class JettyServer extends org.eclipse.jetty.server.Server public class JettyServer extends org.eclipse.jetty.server.Server
{ {
public static int DEFAULT_PORT = 8080; public static int DEFAULT_PORT = 8080;
public static int DEFAULT_MAX_IDLE_TIME = 30000; public static int DEFAULT_MAX_IDLE_TIME = 30000;
private RequestLog requestLog; private RequestLog requestLog;
private ContextHandlerCollection contexts; private ContextHandlerCollection contexts;
public JettyServer() public JettyServer()
{ {
super(); super();
@ -55,7 +54,7 @@ public class JettyServer extends org.eclipse.jetty.server.Server
Resource.setDefaultUseCaches(false); Resource.setDefaultUseCaches(false);
} }
public void setRequestLog (RequestLog requestLog) public void setRequestLog (RequestLog requestLog)
{ {
this.requestLog = requestLog; this.requestLog = requestLog;
@ -69,16 +68,16 @@ public class JettyServer extends org.eclipse.jetty.server.Server
super.doStart(); super.doStart();
} }
/** /**
* @see org.eclipse.jetty.server.handler.HandlerCollection#addHandler(org.eclipse.jetty.server.Handler) * @see org.eclipse.jetty.server.handler.HandlerCollection#addHandler(org.eclipse.jetty.server.Handler)
*/ */
public void addWebApplication(WebAppContext webapp) throws Exception public void addWebApplication(WebAppContext webapp) throws Exception
{ {
contexts.addHandler (webapp); contexts.addHandler (webapp);
} }
/** /**
* Set up the handler structure to receive a webapp. * Set up the handler structure to receive a webapp.
* Also put in a DefaultHandler so we get a nice page * Also put in a DefaultHandler so we get a nice page
@ -86,43 +85,43 @@ public class JettyServer extends org.eclipse.jetty.server.Server
* context isn't at root. * context isn't at root.
* @throws Exception * @throws Exception
*/ */
public void configureHandlers () throws Exception public void configureHandlers () throws Exception
{ {
DefaultHandler defaultHandler = new DefaultHandler(); DefaultHandler defaultHandler = new DefaultHandler();
RequestLogHandler requestLogHandler = new RequestLogHandler(); RequestLogHandler requestLogHandler = new RequestLogHandler();
if (this.requestLog != null) if (this.requestLog != null)
requestLogHandler.setRequestLog(this.requestLog); requestLogHandler.setRequestLog(this.requestLog);
contexts = (ContextHandlerCollection)super.getChildHandlerByClass(ContextHandlerCollection.class); contexts = (ContextHandlerCollection)super.getChildHandlerByClass(ContextHandlerCollection.class);
if (contexts==null) if (contexts==null)
{ {
contexts = new ContextHandlerCollection(); contexts = new ContextHandlerCollection();
HandlerCollection handlers = (HandlerCollection)super.getChildHandlerByClass(HandlerCollection.class); HandlerCollection handlers = (HandlerCollection)super.getChildHandlerByClass(HandlerCollection.class);
if (handlers==null) if (handlers==null)
{ {
handlers = new HandlerCollection(); handlers = new HandlerCollection();
super.setHandler(handlers); super.setHandler(handlers);
handlers.setHandlers(new Handler[]{contexts, defaultHandler, requestLogHandler}); handlers.setHandlers(new Handler[]{contexts, defaultHandler, requestLogHandler});
} }
else else
{ {
handlers.addHandler(contexts); handlers.addHandler(contexts);
} }
} }
} }
public Connector createDefaultConnector(Server server, String portnum) throws Exception public Connector createDefaultConnector(String portnum) throws Exception
{ {
ServerConnector connector = new ServerConnector(server); ServerConnector connector = new ServerConnector(this);
int port = ((portnum==null||portnum.equals(""))?DEFAULT_PORT:Integer.parseInt(portnum.trim())); int port = ((portnum==null||portnum.equals(""))?DEFAULT_PORT:Integer.parseInt(portnum.trim()));
connector.setPort(port); connector.setPort(port);
connector.setIdleTimeout(DEFAULT_MAX_IDLE_TIME); // connector.setMaxIdleTime(DEFAULT_MAX_IDLE_TIME);
return connector; return connector;
} }
} }

View File

@ -28,7 +28,6 @@ import java.util.Map;
import java.util.Set; import java.util.Set;
import java.util.TreeSet; import java.util.TreeSet;
import org.eclipse.jetty.annotations.AnnotationConfiguration;
import org.eclipse.jetty.plus.webapp.EnvConfiguration; import org.eclipse.jetty.plus.webapp.EnvConfiguration;
import org.eclipse.jetty.util.URIUtil; import org.eclipse.jetty.util.URIUtil;
import org.eclipse.jetty.util.log.Log; import org.eclipse.jetty.util.log.Log;
@ -39,8 +38,8 @@ import org.eclipse.jetty.webapp.Configuration;
import org.eclipse.jetty.webapp.FragmentConfiguration; import org.eclipse.jetty.webapp.FragmentConfiguration;
import org.eclipse.jetty.webapp.JettyWebXmlConfiguration; import org.eclipse.jetty.webapp.JettyWebXmlConfiguration;
import org.eclipse.jetty.webapp.MetaInfConfiguration; import org.eclipse.jetty.webapp.MetaInfConfiguration;
import org.eclipse.jetty.webapp.TagLibConfiguration;
import org.eclipse.jetty.webapp.WebAppContext; import org.eclipse.jetty.webapp.WebAppContext;
import org.eclipse.jetty.webapp.WebInfConfiguration;
import org.eclipse.jetty.webapp.WebXmlConfiguration; import org.eclipse.jetty.webapp.WebXmlConfiguration;
/** /**
@ -56,6 +55,7 @@ public class JettyWebAppContext extends WebAppContext
{ {
private static final Logger LOG = Log.getLogger(JettyWebAppContext.class); 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 WEB_INF_CLASSES_PREFIX = "/WEB-INF/classes"; private static final String WEB_INF_CLASSES_PREFIX = "/WEB-INF/classes";
private static final String WEB_INF_LIB_PREFIX = "/WEB-INF/lib"; private static final String WEB_INF_LIB_PREFIX = "/WEB-INF/lib";
@ -73,6 +73,19 @@ public class JettyWebAppContext extends WebAppContext
* @deprecated The value of this parameter will be ignored by the plugin. Overlays will always be unpacked. * @deprecated The value of this parameter will be ignored by the plugin. Overlays will always be unpacked.
*/ */
private boolean unpackOverlays; private boolean unpackOverlays;
/**
* Set the "org.eclipse.jetty.server.webapp.ContainerIncludeJarPattern" with a pattern for matching jars on
* container classpath to scan. This is analogous to the WebAppContext.setAttribute() call.
*/
private String containerIncludeJarPattern = null;
/**
* Set the "org.eclipse.jetty.server.webapp.WebInfIncludeJarPattern" with a pattern for matching jars on
* webapp's classpath to scan. This is analogous to the WebAppContext.setAttribute() call.
*/
private String webInfIncludeJarPattern = null;
/** /**
* @deprecated The value of this parameter will be ignored by the plugin. This option will be always disabled. * @deprecated The value of this parameter will be ignored by the plugin. This option will be always disabled.
@ -91,14 +104,34 @@ public class JettyWebAppContext extends WebAppContext
new MetaInfConfiguration(), new MetaInfConfiguration(),
new FragmentConfiguration(), new FragmentConfiguration(),
envConfig = new EnvConfiguration(), envConfig = new EnvConfiguration(),
new AnnotationConfiguration(),
new org.eclipse.jetty.plus.webapp.PlusConfiguration(), new org.eclipse.jetty.plus.webapp.PlusConfiguration(),
new JettyWebXmlConfiguration(), new MavenAnnotationConfiguration(),
new TagLibConfiguration() new JettyWebXmlConfiguration()
}); });
// Turn off copyWebInf option as it is not applicable for plugin. // Turn off copyWebInf option as it is not applicable for plugin.
super.setCopyWebInf(false); super.setCopyWebInf(false);
} }
public void setContainerIncludeJarPattern(String pattern)
{
containerIncludeJarPattern = pattern;
}
public String getContainerIncludeJarPattern()
{
return containerIncludeJarPattern;
}
public String getWebInfIncludeJarPattern()
{
return webInfIncludeJarPattern;
}
public void setWebInfIncludeJarPattern(String pattern)
{
webInfIncludeJarPattern = pattern;
}
public boolean getUnpackOverlays() public boolean getUnpackOverlays()
{ {
@ -218,17 +251,21 @@ public class JettyWebAppContext extends WebAppContext
{ {
//Set up the pattern that tells us where the jars are that need scanning for //Set up the pattern that tells us where the jars are that need scanning for
//stuff like taglibs so we can tell jasper about it (see TagLibConfiguration) //stuff like taglibs so we can tell jasper about it (see TagLibConfiguration)
String tmp = (String)getAttribute("org.eclipse.jetty.server.webapp.ContainerIncludeJarPattern");
tmp = addPattern(tmp, ".*/.*jsp-api-[^/]*\\.jar$");
tmp = addPattern(tmp, ".*/.*jsp-[^/]*\\.jar$");
tmp = addPattern(tmp, ".*/.*taglibs[^/]*\\.jar$");
tmp = addPattern(tmp, ".*/.*jstl[^/]*\\.jar$");
tmp = addPattern(tmp, ".*/.*jsf-impl-[^/]*\\.jar$"); // add in 2 most popular jsf impls
tmp = addPattern(tmp, ".*/.*javax.faces-[^/]*\\.jar$");
tmp = addPattern(tmp, ".*/.*myfaces-impl-[^/]*\\.jar$");
setAttribute("org.eclipse.jetty.server.webapp.ContainerIncludeJarPattern", tmp); //Allow user to set up pattern for names of jars from the container classpath
//that will be scanned - note that by default NO jars are scanned
String tmp = containerIncludeJarPattern;
if (tmp==null || "".equals(tmp))
tmp = (String)getAttribute(WebInfConfiguration.CONTAINER_JAR_PATTERN);
tmp = addPattern(tmp, DEFAULT_CONTAINER_INCLUDE_JAR_PATTERN);
setAttribute(WebInfConfiguration.CONTAINER_JAR_PATTERN, tmp);
//Allow user to set up pattern of jar names from WEB-INF that will be scanned.
//Note that by default ALL jars considered to be in WEB-INF will be scanned - setting
//a pattern restricts scanning
if (webInfIncludeJarPattern != null)
setAttribute(WebInfConfiguration.WEBINF_JAR_PATTERN, webInfIncludeJarPattern);
//Set up the classes dirs that comprises the equivalent of WEB-INF/classes //Set up the classes dirs that comprises the equivalent of WEB-INF/classes
if (testClasses != null) if (testClasses != null)
@ -241,7 +278,6 @@ public class JettyWebAppContext extends WebAppContext
classpathFiles.addAll(webInfClasses); classpathFiles.addAll(webInfClasses);
classpathFiles.addAll(webInfJars); classpathFiles.addAll(webInfJars);
// Initialize map containing all jars in /WEB-INF/lib // Initialize map containing all jars in /WEB-INF/lib
webInfJarMap.clear(); webInfJarMap.clear();
for (File file : webInfJars) for (File file : webInfJars)
@ -255,13 +291,28 @@ public class JettyWebAppContext extends WebAppContext
if (this.jettyEnvXml != null) if (this.jettyEnvXml != null)
envConfig.setJettyEnvXml(Resource.toURL(new File(this.jettyEnvXml))); envConfig.setJettyEnvXml(Resource.toURL(new File(this.jettyEnvXml)));
//setShutdown(false); // CHECK setShutdown(false);
super.doStart(); super.doStart();
} }
public void doStop () throws Exception public void doStop () throws Exception
{ {
//setShutdown(true); if (classpathFiles != null)
classpathFiles.clear();
classpathFiles = null;
classes = null;
testClasses = null;
if (webInfJarMap != null)
webInfJarMap.clear();
webInfClasses.clear();
webInfJars.clear();
// CHECK setShutdown(true);
//just wait a little while to ensure no requests are still being processed //just wait a little while to ensure no requests are still being processed
Thread.currentThread().sleep(500L); Thread.currentThread().sleep(500L);
super.doStop(); super.doStop();
@ -344,37 +395,40 @@ public class JettyWebAppContext extends WebAppContext
@Override @Override
public Set<String> getResourcePaths(String path) public Set<String> getResourcePaths(String path)
{ {
// Try to get regular resource paths // Try to get regular resource paths - this will get appropriate paths from any overlaid wars etc
Set<String> paths = super.getResourcePaths(path); Set<String> paths = super.getResourcePaths(path);
// If no paths are returned check for virtual paths /WEB-INF/classes and /WEB-INF/lib if (path != null)
if (paths.isEmpty() && path != null)
{ {
path = URIUtil.canonicalPath(path); TreeSet<String> allPaths = new TreeSet<String>();
allPaths.addAll(paths);
//add in the dependency jars as a virtual WEB-INF/lib entry
if (path.startsWith(WEB_INF_LIB_PREFIX)) if (path.startsWith(WEB_INF_LIB_PREFIX))
{ {
paths = new TreeSet<String>();
for (String fileName : webInfJarMap.keySet()) for (String fileName : webInfJarMap.keySet())
{ {
// Return all jar files from class path // Return all jar files from class path
paths.add(WEB_INF_LIB_PREFIX + "/" + fileName); allPaths.add(WEB_INF_LIB_PREFIX + "/" + fileName);
} }
} }
else if (path.startsWith(WEB_INF_CLASSES_PREFIX)) else if (path.startsWith(WEB_INF_CLASSES_PREFIX))
{ {
int i=0; int i=0;
while (paths.isEmpty() && (i < webInfClasses.size())) while (i < webInfClasses.size())
{ {
String newPath = path.replace(WEB_INF_CLASSES_PREFIX, webInfClasses.get(i).getPath()); String newPath = path.replace(WEB_INF_CLASSES_PREFIX, webInfClasses.get(i).getPath());
paths = super.getResourcePaths(newPath); allPaths.addAll(super.getResourcePaths(newPath));
i++; i++;
} }
} }
return allPaths;
} }
return paths; return paths;
} }
public String addPattern (String s, String pattern) public String addPattern (String s, String pattern)
{ {
if (s == null) if (s == null)

View File

@ -0,0 +1,109 @@
//
// ========================================================================
// Copyright (c) 1995-2012 Mort Bay Consulting Pty. Ltd.
// ------------------------------------------------------------------------
// All rights reserved. This program and the accompanying materials
// are made available under the terms of the Eclipse Public License v1.0
// and Apache License v2.0 which accompanies this distribution.
//
// The Eclipse Public License is available at
// http://www.eclipse.org/legal/epl-v10.html
//
// The Apache License v2.0 is available at
// http://www.opensource.org/licenses/apache2.0.php
//
// You may elect to redistribute this code under either of these licenses.
// ========================================================================
//
package org.eclipse.jetty.maven.plugin;
import java.io.File;
import org.eclipse.jetty.annotations.AbstractDiscoverableAnnotationHandler;
import org.eclipse.jetty.annotations.AnnotationConfiguration;
import org.eclipse.jetty.annotations.AnnotationParser;
import org.eclipse.jetty.annotations.AnnotationParser.DiscoverableAnnotationHandler;
import org.eclipse.jetty.annotations.ClassNameResolver;
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.MetaData;
import org.eclipse.jetty.webapp.WebAppContext;
public class MavenAnnotationConfiguration extends AnnotationConfiguration
{
private static final Logger LOG = Log.getLogger(MavenAnnotationConfiguration.class);
/* ------------------------------------------------------------ */
@Override
public void parseWebInfClasses(final WebAppContext context, final AnnotationParser parser) throws Exception
{
JettyWebAppContext jwac = (JettyWebAppContext)context;
if (jwac.getClassPathFiles() == null || jwac.getClassPathFiles().size() == 0)
super.parseWebInfClasses (context, parser);
else
{
LOG.debug("Scanning classes ");
//Look for directories on the classpath and process each one of those
MetaData metaData = context.getMetaData();
if (metaData == null)
throw new IllegalStateException ("No metadata");
parser.clearHandlers();
for (DiscoverableAnnotationHandler h:_discoverableAnnotationHandlers)
{
if (h instanceof AbstractDiscoverableAnnotationHandler)
((AbstractDiscoverableAnnotationHandler)h).setResource(null); //
}
parser.registerHandlers(_discoverableAnnotationHandlers);
parser.registerHandler(_classInheritanceHandler);
parser.registerHandlers(_containerInitializerAnnotationHandlers);
for (File f:jwac.getClassPathFiles())
{
//scan the equivalent of the WEB-INF/classes directory that has been synthesised by the plugin
if (f.isDirectory() && f.exists())
{
doParse(context, parser, Resource.newResource(f.toURL()));
}
}
//if an actual WEB-INF/classes directory also exists (eg because of overlayed wars) then scan that
//too
if (context.getWebInf() != null && context.getWebInf().exists())
{
Resource classesDir = context.getWebInf().addPath("classes/");
if (classesDir.exists())
{
doParse(context, parser, classesDir);
}
}
}
}
public void doParse (final WebAppContext context, final AnnotationParser parser, Resource resource)
throws Exception
{
parser.parse(resource, new ClassNameResolver()
{
public boolean isExcluded (String name)
{
if (context.isSystemClass(name)) return true;
if (context.isServerClass(name)) return false;
return false;
}
public boolean shouldOverride (String name)
{
//looking at webapp classpath, found already-parsed class of same name - did it come from system or duplicate in webapp?
if (context.isParentLoaderPriority())
return false;
return true;
}
});
}
}

View File

@ -24,8 +24,10 @@ import java.net.URLClassLoader;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Iterator; import java.util.Iterator;
import java.util.List; import java.util.List;
import java.util.Locale;
import org.eclipse.jetty.util.IO; import org.eclipse.jetty.util.IO;
import org.eclipse.jetty.util.LazyList;
import org.eclipse.jetty.util.log.Log; import org.eclipse.jetty.util.log.Log;
import org.eclipse.jetty.util.log.Logger; import org.eclipse.jetty.util.log.Logger;
import org.eclipse.jetty.util.resource.Resource; import org.eclipse.jetty.util.resource.Resource;
@ -40,8 +42,8 @@ public class MavenWebInfConfiguration extends WebInfConfiguration
protected Resource _originalResourceBase; protected Resource _originalResourceBase;
protected Resource[] _unpackedOverlays; protected Resource[] _unpackedOverlays;
public void configure(WebAppContext context) throws Exception public void configure(WebAppContext context) throws Exception
{ {
JettyWebAppContext jwac = (JettyWebAppContext)context; JettyWebAppContext jwac = (JettyWebAppContext)context;
@ -54,11 +56,11 @@ public class MavenWebInfConfiguration extends WebInfConfiguration
while (itor.hasNext()) while (itor.hasNext())
((WebAppClassLoader)context.getClassLoader()).addClassPath(((File)itor.next()).getCanonicalPath()); ((WebAppClassLoader)context.getClassLoader()).addClassPath(((File)itor.next()).getCanonicalPath());
if (LOG.isDebugEnabled()) //if (LOG.isDebugEnabled())
LOG.debug("Classpath = "+((URLClassLoader)context.getClassLoader()).getURLs()); //LOG.debug("Classpath = "+LazyList.array2List(((URLClassLoader)context.getClassLoader()).getURLs()));
} }
super.configure(context); super.configure(context);
// knock out environmental maven and plexus classes from webAppContext // knock out environmental maven and plexus classes from webAppContext
String[] existingServerClasses = context.getServerClasses(); String[] existingServerClasses = context.getServerClasses();
String[] newServerClasses = new String[2+(existingServerClasses==null?0:existingServerClasses.length)]; String[] newServerClasses = new String[2+(existingServerClasses==null?0:existingServerClasses.length)];
@ -71,7 +73,7 @@ public class MavenWebInfConfiguration extends WebInfConfiguration
for (int i=0;i<newServerClasses.length;i++) for (int i=0;i<newServerClasses.length;i++)
LOG.debug(newServerClasses[i]); LOG.debug(newServerClasses[i]);
} }
context.setServerClasses( newServerClasses ); context.setServerClasses( newServerClasses );
} }
@ -79,6 +81,53 @@ public class MavenWebInfConfiguration extends WebInfConfiguration
{ {
super.preConfigure(context); super.preConfigure(context);
}
public void postConfigure(WebAppContext context) throws Exception
{
super.postConfigure(context);
}
public void deconfigure(WebAppContext context) throws Exception
{
JettyWebAppContext jwac = (JettyWebAppContext)context;
//remove the unpacked wars
if (_unpackedOverlays != null && _unpackedOverlays.length>0)
{
try
{
for (int i=0; i<_unpackedOverlays.length; i++)
{
IO.delete(_unpackedOverlays[i].getFile());
}
}
catch (IOException e)
{
LOG.ignore(e);
}
}
super.deconfigure(context);
//restore whatever the base resource was before we might have included overlaid wars
context.setBaseResource(_originalResourceBase);
}
/**
* @see org.eclipse.jetty.webapp.WebInfConfiguration#unpack(org.eclipse.jetty.webapp.WebAppContext)
*/
@Override
public void unpack(WebAppContext context) throws IOException
{
//Unpack and find base resource as normal
super.unpack(context);
//Add in any overlays as a resource collection for the base
_originalResourceBase = context.getBaseResource(); _originalResourceBase = context.getBaseResource();
JettyWebAppContext jwac = (JettyWebAppContext)context; JettyWebAppContext jwac = (JettyWebAppContext)context;
@ -102,7 +151,7 @@ public class MavenWebInfConfiguration extends WebInfConfiguration
origSize = 1; origSize = 1;
} }
} }
int overlaySize = jwac.getOverlays().size(); int overlaySize = jwac.getOverlays().size();
Resource[] newResources = new Resource[origSize + overlaySize]; Resource[] newResources = new Resource[origSize + overlaySize];
@ -112,7 +161,6 @@ public class MavenWebInfConfiguration extends WebInfConfiguration
if (jwac.getBaseAppFirst()) if (jwac.getBaseAppFirst())
{ {
System.arraycopy(origResources,0,newResources,0,origSize); System.arraycopy(origResources,0,newResources,0,origSize);
offset = origSize; offset = origSize;
} }
else else
@ -120,53 +168,23 @@ public class MavenWebInfConfiguration extends WebInfConfiguration
System.arraycopy(origResources,0,newResources,overlaySize,origSize); System.arraycopy(origResources,0,newResources,overlaySize,origSize);
} }
} }
// Overlays are always unpacked // Overlays are always unpacked
_unpackedOverlays = new Resource[overlaySize]; _unpackedOverlays = new Resource[overlaySize];
List<Resource> overlays = jwac.getOverlays(); List<Resource> overlays = jwac.getOverlays();
for (int idx=0; idx<overlaySize; idx++) for (int idx=0; idx<overlaySize; idx++)
{ {
LOG.info("Unpacking overlay: " + overlays.get(idx));
_unpackedOverlays[idx] = unpackOverlay(context, overlays.get(idx)); _unpackedOverlays[idx] = unpackOverlay(context, overlays.get(idx));
newResources[idx+offset] = _unpackedOverlays[idx]; newResources[idx+offset] = _unpackedOverlays[idx];
LOG.info("Adding overlay: " + _unpackedOverlays[idx]); LOG.info("Adding overlay: " + _unpackedOverlays[idx]);
} }
jwac.setBaseResource(new ResourceCollection(newResources)); jwac.setBaseResource(new ResourceCollection(newResources));
} }
} }
public void postConfigure(WebAppContext context) throws Exception
{
super.postConfigure(context);
}
public void deconfigure(WebAppContext context) throws Exception
{
JettyWebAppContext jwac = (JettyWebAppContext)context;
//remove the unpacked wars
if (_unpackedOverlays != null && _unpackedOverlays.length>0)
{
try
{
for (int i=0; i<_unpackedOverlays.length; i++)
{
IO.delete(_unpackedOverlays[i].getFile());
}
}
catch (IOException e)
{
LOG.ignore(e);
}
}
super.deconfigure(context);
//restore whatever the base resource was before we might have included overlaid wars
context.setBaseResource(_originalResourceBase);
}
/** /**
* Get the jars to examine from the files from which we have * Get the jars to examine from the files from which we have
@ -175,6 +193,7 @@ public class MavenWebInfConfiguration extends WebInfConfiguration
* @param context * @param context
* @return the list of jars found * @return the list of jars found
*/ */
@Override
protected List<Resource> findJars (WebAppContext context) protected List<Resource> findJars (WebAppContext context)
throws Exception throws Exception
{ {
@ -184,7 +203,7 @@ public class MavenWebInfConfiguration extends WebInfConfiguration
{ {
for (File f: jwac.getClassPathFiles()) for (File f: jwac.getClassPathFiles())
{ {
if (f.getName().toLowerCase().endsWith(".jar")) if (f.getName().toLowerCase(Locale.ENGLISH).endsWith(".jar"))
{ {
try try
{ {
@ -203,14 +222,16 @@ public class MavenWebInfConfiguration extends WebInfConfiguration
list.addAll(superList); list.addAll(superList);
return list; return list;
} }
protected Resource unpackOverlay (WebAppContext context, Resource overlay) protected Resource unpackOverlay (WebAppContext context, Resource overlay)
throws IOException throws IOException
{ {
//resolve if not already resolved //resolve if not already resolved
resolveTempDirectory(context); resolveTempDirectory(context);
//Get the name of the overlayed war and unpack it to a dir of the //Get the name of the overlayed war and unpack it to a dir of the
//same name in the temporary directory //same name in the temporary directory
String name = overlay.getName(); String name = overlay.getName();
@ -225,6 +246,4 @@ public class MavenWebInfConfiguration extends WebInfConfiguration
Resource unpackedOverlay = Resource.newResource(dir.getCanonicalPath()); Resource unpackedOverlay = Resource.newResource(dir.getCanonicalPath());
return unpackedOverlay; return unpackedOverlay;
} }
} }

View File

@ -16,12 +16,12 @@
// ======================================================================== // ========================================================================
// //
package org.eclipse.jetty.maven.plugin; package org.eclipse.jetty.maven.plugin;
import java.io.IOException; import java.io.IOException;
import java.io.InputStreamReader; import java.io.InputStreamReader;
import java.io.LineNumberReader; import java.io.LineNumberReader;
import java.net.InetAddress;
import java.net.InetSocketAddress; import java.net.InetSocketAddress;
import java.net.ServerSocket; import java.net.ServerSocket;
import java.net.Socket; import java.net.Socket;
@ -41,7 +41,7 @@ import org.eclipse.jetty.server.Server;
* by stopping the Server instances. The choice of * by stopping the Server instances. The choice of
* behaviour is controlled by either passing true * behaviour is controlled by either passing true
* (exit jvm) or false (stop Servers) in the constructor. * (exit jvm) or false (stop Servers) in the constructor.
* *
*/ */
public class Monitor extends Thread public class Monitor extends Thread
{ {
@ -51,7 +51,7 @@ public class Monitor extends Thread
ServerSocket _serverSocket; ServerSocket _serverSocket;
boolean _kill; boolean _kill;
public Monitor(int port, String key, Server[] servers, boolean kill) public Monitor(int port, String key, Server[] servers, boolean kill)
throws UnknownHostException, IOException throws UnknownHostException, IOException
{ {
if (port <= 0) if (port <= 0)
@ -64,7 +64,7 @@ public class Monitor extends Thread
_kill = kill; _kill = kill;
setDaemon(true); setDaemon(true);
setName("StopJettyPluginMonitor"); setName("StopJettyPluginMonitor");
InetSocketAddress address = new InetSocketAddress("127.0.0.1", port); InetSocketAddress address = new InetSocketAddress("127.0.0.1", port);
_serverSocket=new ServerSocket(); _serverSocket=new ServerSocket();
_serverSocket.setReuseAddress(true); _serverSocket.setReuseAddress(true);
try try
@ -77,7 +77,7 @@ public class Monitor extends Thread
throw x; throw x;
} }
} }
public void run() public void run()
{ {
while (_serverSocket != null) while (_serverSocket != null)
@ -88,7 +88,7 @@ public class Monitor extends Thread
socket = _serverSocket.accept(); socket = _serverSocket.accept();
socket.setSoLinger(false, 0); socket.setSoLinger(false, 0);
LineNumberReader lin = new LineNumberReader(new InputStreamReader(socket.getInputStream())); LineNumberReader lin = new LineNumberReader(new InputStreamReader(socket.getInputStream()));
String key = lin.readLine(); String key = lin.readLine();
if (!_key.equals(key)) continue; if (!_key.equals(key)) continue;
String cmd = lin.readLine(); String cmd = lin.readLine();
@ -97,13 +97,13 @@ public class Monitor extends Thread
try{socket.close();}catch (Exception e){e.printStackTrace();} try{socket.close();}catch (Exception e){e.printStackTrace();}
try{socket.close();}catch (Exception e){e.printStackTrace();} try{socket.close();}catch (Exception e){e.printStackTrace();}
try{_serverSocket.close();}catch (Exception e){e.printStackTrace();} try{_serverSocket.close();}catch (Exception e){e.printStackTrace();}
_serverSocket = null; _serverSocket = null;
if (_kill) if (_kill)
{ {
System.out.println("Killing Jetty"); System.out.println("Killing Jetty");
System.exit(0); System.exit(0);
} }
else else
{ {
@ -111,7 +111,7 @@ public class Monitor extends Thread
{ {
try try
{ {
System.out.println("Stopping server "+i); System.out.println("Stopping server "+i);
_servers[i].stop(); _servers[i].stop();
} }
catch (Exception e) catch (Exception e)

View File

@ -23,19 +23,23 @@ import java.io.FileInputStream;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
import java.util.Properties; import java.util.Properties;
import java.util.StringTokenizer;
import org.eclipse.jetty.server.Connector; import org.eclipse.jetty.server.Connector;
import org.eclipse.jetty.server.Handler; import org.eclipse.jetty.server.Handler;
import org.eclipse.jetty.server.Server; import org.eclipse.jetty.server.Server;
import org.eclipse.jetty.server.handler.ContextHandler;
import org.eclipse.jetty.server.handler.ContextHandlerCollection;
import org.eclipse.jetty.server.handler.HandlerCollection; import org.eclipse.jetty.server.handler.HandlerCollection;
import org.eclipse.jetty.util.log.Log; import org.eclipse.jetty.util.log.Log;
import org.eclipse.jetty.util.log.Logger; import org.eclipse.jetty.util.log.Logger;
import org.eclipse.jetty.util.resource.Resource; import org.eclipse.jetty.util.resource.Resource;
import org.eclipse.jetty.util.resource.ResourceCollection; import org.eclipse.jetty.util.resource.ResourceCollection;
import org.eclipse.jetty.webapp.WebAppContext;
import org.eclipse.jetty.xml.XmlConfiguration; import org.eclipse.jetty.xml.XmlConfiguration;
public class Starter public class Starter
{ {
public static final String PORT_SYSPROPERTY = "jetty.port"; public static final String PORT_SYSPROPERTY = "jetty.port";
private static final Logger LOG = Log.getLogger(Starter.class); private static final Logger LOG = Log.getLogger(Starter.class);
@ -45,21 +49,21 @@ public class Starter
private JettyServer server; private JettyServer server;
private JettyWebAppContext webApp; private JettyWebAppContext webApp;
private Monitor monitor; private Monitor monitor;
private int stopPort=0; private int stopPort=0;
private String stopKey=null; private String stopKey=null;
private Properties props; private Properties props;
private String token; private String token;
public void configureJetty () throws Exception public void configureJetty () throws Exception
{ {
LOG.debug("Starting Jetty Server ..."); LOG.debug("Starting Jetty Server ...");
this.server = new JettyServer(); this.server = new JettyServer();
//apply any configs from jetty.xml files first //apply any configs from jetty.xml files first
applyJettyXml (); applyJettyXml ();
// if the user hasn't configured a connector in the jetty.xml // if the user hasn't configured a connector in the jetty.xml
@ -68,7 +72,7 @@ public class Starter
if (connectors == null|| connectors.length == 0) if (connectors == null|| connectors.length == 0)
{ {
//if a SystemProperty -Djetty.port=<portnum> has been supplied, use that as the default port //if a SystemProperty -Djetty.port=<portnum> has been supplied, use that as the default port
connectors = new Connector[] { this.server.createDefaultConnector(server, System.getProperty(PORT_SYSPROPERTY, null)) }; connectors = new Connector[] { this.server.createDefaultConnector(System.getProperty(PORT_SYSPROPERTY, null)) };
this.server.setConnectors(connectors); this.server.setConnectors(connectors);
} }
@ -84,15 +88,15 @@ public class Starter
this.server.configureHandlers(); this.server.configureHandlers();
webApp = new JettyWebAppContext(); webApp = new JettyWebAppContext();
//configure webapp from properties file describing unassembled webapp //configure webapp from properties file describing unassembled webapp
configureWebApp(); configureWebApp();
//set up the webapp from the context xml file provided //set up the webapp from the context xml file provided
//NOTE: just like jetty:run mojo this means that the context file can //NOTE: just like jetty:run mojo this means that the context file can
//potentially override settings made in the pom. Ideally, we'd like //potentially override settings made in the pom. Ideally, we'd like
//the pom to override the context xml file, but as the other mojos all //the pom to override the context xml file, but as the other mojos all
//configure a WebAppContext in the pom (the <webApp> element), it is //configure a WebAppContext in the pom (the <webApp> element), it is
//already configured by the time the context xml file is applied. //already configured by the time the context xml file is applied.
if (contextXml != null) if (contextXml != null)
{ {
@ -109,30 +113,30 @@ public class Starter
monitor = new Monitor(stopPort, stopKey, new Server[]{server}, true); monitor = new Monitor(stopPort, stopKey, new Server[]{server}, true);
} }
} }
public void configureWebApp () public void configureWebApp ()
throws Exception throws Exception
{ {
if (props == null) if (props == null)
return; return;
//apply a properties file that defines the things that we configure in the jetty:run plugin: //apply a properties file that defines the things that we configure in the jetty:run plugin:
// - the context path // - the context path
String str = (String)props.get("context.path"); String str = (String)props.get("context.path");
if (str != null) if (str != null)
webApp.setContextPath(str); webApp.setContextPath(str);
// - web.xml // - web.xml
str = (String)props.get("web.xml"); str = (String)props.get("web.xml");
if (str != null) if (str != null)
webApp.setDescriptor(str); webApp.setDescriptor(str);
// - the tmp directory // - the tmp directory
str = (String)props.getProperty("tmp.dir"); str = (String)props.getProperty("tmp.dir");
if (str != null) if (str != null)
webApp.setTempDirectory(new File(str.trim())); webApp.setTempDirectory(new File(str.trim()));
// - the base directory // - the base directory
str = (String)props.getProperty("base.dir"); str = (String)props.getProperty("base.dir");
if (str != null && !"".equals(str.trim())) if (str != null && !"".equals(str.trim()))
@ -145,7 +149,7 @@ public class Starter
ResourceCollection resources = new ResourceCollection(str); ResourceCollection resources = new ResourceCollection(str);
webApp.setBaseResource(resources); webApp.setBaseResource(resources);
} }
// - overlays // - overlays
str = (String)props.getProperty("overlay.files"); str = (String)props.getProperty("overlay.files");
if (str != null && !"".equals(str.trim())) if (str != null && !"".equals(str.trim()))
@ -163,8 +167,8 @@ public class Starter
{ {
webApp.setClasses(new File(str)); webApp.setClasses(new File(str));
} }
str = (String)props.getProperty("testClasses.dir"); str = (String)props.getProperty("testClasses.dir");
if (str != null && !"".equals(str.trim())) if (str != null && !"".equals(str.trim()))
{ {
webApp.setTestClasses(new File(str)); webApp.setTestClasses(new File(str));
@ -181,7 +185,7 @@ public class Starter
jars.add(new File(names[j].trim())); jars.add(new File(names[j].trim()));
webApp.setWebInfLib(jars); webApp.setWebInfLib(jars);
} }
} }
public void getConfiguration (String[] args) public void getConfiguration (String[] args)
@ -205,7 +209,7 @@ public class Starter
for (int j=0; names!= null && j < names.length; j++) for (int j=0; names!= null && j < names.length; j++)
{ {
jettyXmls.add(new File(names[j].trim())); jettyXmls.add(new File(names[j].trim()));
} }
} }
//--context-xml //--context-xml
@ -221,7 +225,7 @@ public class Starter
props = new Properties(); props = new Properties();
props.load(new FileInputStream(f)); props.load(new FileInputStream(f));
} }
//--token //--token
if ("--token".equals(args[i])) if ("--token".equals(args[i]))
{ {
@ -237,16 +241,16 @@ public class Starter
monitor.start(); monitor.start();
LOG.info("Started Jetty Server"); LOG.info("Started Jetty Server");
server.start(); server.start();
} }
public void join () throws Exception public void join () throws Exception
{ {
server.join(); server.join();
} }
public void communicateStartupResult (Exception e) public void communicateStartupResult (Exception e)
{ {
if (token != null) if (token != null)
@ -257,16 +261,16 @@ public class Starter
System.out.println(token+"\t"+e.getMessage()); System.out.println(token+"\t"+e.getMessage());
} }
} }
public void applyJettyXml() throws Exception public void applyJettyXml() throws Exception
{ {
if (jettyXmls == null) if (jettyXmls == null)
return; return;
for ( File xmlFile : jettyXmls ) for ( File xmlFile : jettyXmls )
{ {
LOG.info( "Configuring Jetty from xml configuration file = " + xmlFile.getCanonicalPath() ); LOG.info( "Configuring Jetty from xml configuration file = " + xmlFile.getCanonicalPath() );
XmlConfiguration xmlConfiguration = new XmlConfiguration(Resource.toURL(xmlFile)); XmlConfiguration xmlConfiguration = new XmlConfiguration(Resource.toURL(xmlFile));
xmlConfiguration.configure(this.server); xmlConfiguration.configure(this.server);
} }
@ -286,8 +290,8 @@ public class Starter
System.arraycopy(existing, 0, children, 1, existing.length); System.arraycopy(existing, 0, children, 1, existing.length);
handlers.setHandlers(children); handlers.setHandlers(children);
} }
public static final void main(String[] args) public static final void main(String[] args)
{ {
if (args == null) if (args == null)

View File

@ -23,6 +23,7 @@ import java.io.FilenameFilter;
import java.io.IOException; import java.io.IOException;
import java.util.HashSet; import java.util.HashSet;
import java.util.Iterator; import java.util.Iterator;
import java.util.Locale;
import java.util.Map.Entry; import java.util.Map.Entry;
import java.util.Set; import java.util.Set;
@ -116,7 +117,7 @@ public class OSGiAppProvider extends ScanningAppProvider implements AppProvider
*/ */
private static String getDeployedAppName(String contextFileName) private static String getDeployedAppName(String contextFileName)
{ {
String lowername = contextFileName.toLowerCase(); String lowername = contextFileName.toLowerCase(Locale.ENGLISH);
if (lowername.endsWith(".xml")) if (lowername.endsWith(".xml"))
{ {
String contextName = contextFileName.substring(0, lowername.length() - ".xml".length()); String contextName = contextFileName.substring(0, lowername.length() - ".xml".length());

View File

@ -26,6 +26,7 @@ import java.util.ArrayList;
import java.util.HashMap; import java.util.HashMap;
import java.util.HashSet; import java.util.HashSet;
import java.util.List; import java.util.List;
import java.util.Locale;
import java.util.Map; import java.util.Map;
import java.util.Set; import java.util.Set;
@ -109,7 +110,7 @@ public class LibExtClassLoaderHelper
for (File f : jettyResources.listFiles()) for (File f : jettyResources.listFiles())
{ {
jettyResFiles.put(f.getName(), f); jettyResFiles.put(f.getName(), f);
if (f.getName().toLowerCase().startsWith("readme")) if (f.getName().toLowerCase(Locale.ENGLISH).startsWith("readme"))
{ {
continue; continue;
} }

View File

@ -21,6 +21,7 @@ package org.eclipse.jetty.plus.annotation;
import java.lang.reflect.Field; import java.lang.reflect.Field;
import java.lang.reflect.Member; import java.lang.reflect.Member;
import java.lang.reflect.Method; import java.lang.reflect.Method;
import java.util.Locale;
import javax.naming.InitialContext; import javax.naming.InitialContext;
import javax.naming.NamingException; import javax.naming.NamingException;
@ -140,7 +141,7 @@ public class Injection
_resourceClass = resourceType; _resourceClass = resourceType;
//first look for a javabeans style setter matching the targetName //first look for a javabeans style setter matching the targetName
String setter = "set"+target.substring(0,1).toUpperCase()+target.substring(1); String setter = "set"+target.substring(0,1).toUpperCase(Locale.ENGLISH)+target.substring(1);
try try
{ {
LOG.debug("Looking for method for setter: "+setter+" with arg "+_resourceClass); LOG.debug("Looking for method for setter: "+setter+" with arg "+_resourceClass);

View File

@ -26,6 +26,7 @@ import java.sql.ResultSet;
import java.sql.SQLException; import java.sql.SQLException;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
import java.util.Locale;
import javax.naming.InitialContext; import javax.naming.InitialContext;
import javax.naming.NameNotFoundException; import javax.naming.NameNotFoundException;
import javax.naming.NamingException; import javax.naming.NamingException;
@ -413,7 +414,7 @@ public class DataSourceLoginService extends MappedLoginService
DatabaseMetaData metaData = connection.getMetaData(); DatabaseMetaData metaData = connection.getMetaData();
//check if tables exist //check if tables exist
String tableName = (metaData.storesLowerCaseIdentifiers()? _userTableName.toLowerCase(): (metaData.storesUpperCaseIdentifiers()?_userTableName.toUpperCase(): _userTableName)); String tableName = (metaData.storesLowerCaseIdentifiers()? _userTableName.toLowerCase(Locale.ENGLISH): (metaData.storesUpperCaseIdentifiers()?_userTableName.toUpperCase(Locale.ENGLISH): _userTableName));
ResultSet result = metaData.getTables(null, null, tableName, null); ResultSet result = metaData.getTables(null, null, tableName, null);
if (!result.next()) if (!result.next())
{ {
@ -431,7 +432,7 @@ public class DataSourceLoginService extends MappedLoginService
result.close(); result.close();
tableName = (metaData.storesLowerCaseIdentifiers()? _roleTableName.toLowerCase(): (metaData.storesUpperCaseIdentifiers()?_roleTableName.toUpperCase(): _roleTableName)); tableName = (metaData.storesLowerCaseIdentifiers()? _roleTableName.toLowerCase(Locale.ENGLISH): (metaData.storesUpperCaseIdentifiers()?_roleTableName.toUpperCase(Locale.ENGLISH): _roleTableName));
result = metaData.getTables(null, null, tableName, null); result = metaData.getTables(null, null, tableName, null);
if (!result.next()) if (!result.next())
{ {
@ -448,7 +449,7 @@ public class DataSourceLoginService extends MappedLoginService
result.close(); result.close();
tableName = (metaData.storesLowerCaseIdentifiers()? _userRoleTableName.toLowerCase(): (metaData.storesUpperCaseIdentifiers()?_userRoleTableName.toUpperCase(): _userRoleTableName)); tableName = (metaData.storesLowerCaseIdentifiers()? _userRoleTableName.toLowerCase(Locale.ENGLISH): (metaData.storesUpperCaseIdentifiers()?_userRoleTableName.toUpperCase(Locale.ENGLISH): _userRoleTableName));
result = metaData.getTables(null, null, tableName, null); result = metaData.getTables(null, null, tableName, null);
if (!result.next()) if (!result.next())
{ {

View File

@ -30,6 +30,7 @@ import java.util.Collections;
import java.util.Enumeration; import java.util.Enumeration;
import java.util.HashSet; import java.util.HashSet;
import java.util.List; import java.util.List;
import java.util.Locale;
import java.util.Map; import java.util.Map;
import java.util.StringTokenizer; import java.util.StringTokenizer;
@ -489,7 +490,7 @@ public class ProxyServlet implements Servlet
protected void onResponseHeader(Buffer name, Buffer value) throws IOException protected void onResponseHeader(Buffer name, Buffer value) throws IOException
{ {
String nameString = name.toString(); String nameString = name.toString();
String s = nameString.toLowerCase(); String s = nameString.toLowerCase(Locale.ENGLISH);
if (!_DontProxyHeaders.contains(s) || (HttpHeader.CONNECTION.is(name) && HttpHeaderValue.CLOSE.is(value))) if (!_DontProxyHeaders.contains(s) || (HttpHeader.CONNECTION.is(name) && HttpHeaderValue.CLOSE.is(value)))
{ {
if (debug != 0) if (debug != 0)
@ -560,7 +561,7 @@ public class ProxyServlet implements Servlet
String connectionHdr = request.getHeader("Connection"); String connectionHdr = request.getHeader("Connection");
if (connectionHdr != null) if (connectionHdr != null)
{ {
connectionHdr = connectionHdr.toLowerCase(); connectionHdr = connectionHdr.toLowerCase(Locale.ENGLISH);
if (connectionHdr.indexOf("keep-alive") < 0 && connectionHdr.indexOf("close") < 0) if (connectionHdr.indexOf("keep-alive") < 0 && connectionHdr.indexOf("close") < 0)
connectionHdr = null; connectionHdr = null;
} }
@ -578,7 +579,7 @@ public class ProxyServlet implements Servlet
{ {
// TODO could be better than this! // TODO could be better than this!
String hdr = (String)enm.nextElement(); String hdr = (String)enm.nextElement();
String lhdr = hdr.toLowerCase(); String lhdr = hdr.toLowerCase(Locale.ENGLISH);
if (_DontProxyHeaders.contains(lhdr)) if (_DontProxyHeaders.contains(lhdr))
continue; continue;

View File

@ -27,6 +27,7 @@ import java.io.IOException;
import java.net.Socket; import java.net.Socket;
import java.net.SocketTimeoutException; import java.net.SocketTimeoutException;
import java.util.LinkedHashMap; import java.util.LinkedHashMap;
import java.util.Locale;
import java.util.Map; import java.util.Map;
import java.util.regex.Matcher; import java.util.regex.Matcher;
import java.util.regex.Pattern; import java.util.regex.Pattern;
@ -105,7 +106,7 @@ public abstract class AbstractConnectHandlerTest
assertTrue(header.lookingAt()); assertTrue(header.lookingAt());
String headerName = header.group(1); String headerName = header.group(1);
String headerValue = header.group(2); String headerValue = header.group(2);
headers.put(headerName.toLowerCase(), headerValue.toLowerCase()); headers.put(headerName.toLowerCase(Locale.ENGLISH), headerValue.toLowerCase(Locale.ENGLISH));
} }
StringBuilder body; StringBuilder body;

View File

@ -79,6 +79,20 @@ public class RewriteHandlerTest extends AbstractRuleTestCase
@Test @Test
public void test() throws Exception public void test() throws Exception
{ {
_response.setStatus(200);
_request.setHandled(false);
_handler.setOriginalPathAttribute("/before");
_handler.setRewriteRequestURI(true);
_handler.setRewritePathInfo(true);
_request.setRequestURI("/xxx/bar");
_request.setPathInfo("/xxx/bar");
_handler.handle("/xxx/bar",_request,_request, _response);
assertEquals(201,_response.getStatus());
assertEquals("/bar/zzz",_request.getAttribute("target"));
assertEquals("/bar/zzz",_request.getAttribute("URI"));
assertEquals("/bar/zzz",_request.getAttribute("info"));
assertEquals(null,_request.getAttribute("before"));
_response.setStatus(200); _response.setStatus(200);
_request.setHandled(false); _request.setHandled(false);
_handler.setOriginalPathAttribute("/before"); _handler.setOriginalPathAttribute("/before");

View File

@ -21,6 +21,7 @@ package org.eclipse.jetty.security.authentication;
import java.io.IOException; import java.io.IOException;
import java.util.Collections; import java.util.Collections;
import java.util.Enumeration; import java.util.Enumeration;
import java.util.Locale;
import javax.servlet.RequestDispatcher; import javax.servlet.RequestDispatcher;
import javax.servlet.ServletException; import javax.servlet.ServletException;
import javax.servlet.ServletRequest; import javax.servlet.ServletRequest;
@ -413,7 +414,7 @@ public class FormAuthenticator extends LoginAuthenticator
@Override @Override
public long getDateHeader(String name) public long getDateHeader(String name)
{ {
if (name.toLowerCase().startsWith("if-")) if (name.toLowerCase(Locale.ENGLISH).startsWith("if-"))
return -1; return -1;
return super.getDateHeader(name); return super.getDateHeader(name);
} }
@ -421,7 +422,7 @@ public class FormAuthenticator extends LoginAuthenticator
@Override @Override
public String getHeader(String name) public String getHeader(String name)
{ {
if (name.toLowerCase().startsWith("if-")) if (name.toLowerCase(Locale.ENGLISH).startsWith("if-"))
return null; return null;
return super.getHeader(name); return super.getHeader(name);
} }
@ -435,7 +436,7 @@ public class FormAuthenticator extends LoginAuthenticator
@Override @Override
public Enumeration<String> getHeaders(String name) public Enumeration<String> getHeaders(String name)
{ {
if (name.toLowerCase().startsWith("if-")) if (name.toLowerCase(Locale.ENGLISH).startsWith("if-"))
return Collections.<String>enumeration(Collections.<String>emptyList()); return Collections.<String>enumeration(Collections.<String>emptyList());
return super.getHeaders(name); return super.getHeaders(name);
} }

View File

@ -25,6 +25,7 @@ import java.util.ArrayList;
import java.util.Collection; import java.util.Collection;
import java.util.LinkedHashMap; import java.util.LinkedHashMap;
import java.util.List; import java.util.List;
import java.util.Locale;
import java.util.Map; import java.util.Map;
import java.util.concurrent.CountDownLatch; import java.util.concurrent.CountDownLatch;
import java.util.concurrent.Executor; import java.util.concurrent.Executor;
@ -314,7 +315,7 @@ public abstract class AbstractConnector extends ContainerLifeCycle implements Co
{ {
synchronized (_factories) synchronized (_factories)
{ {
return _factories.get(protocol.toLowerCase()); return _factories.get(protocol.toLowerCase(Locale.ENGLISH));
} }
} }
@ -337,7 +338,7 @@ public abstract class AbstractConnector extends ContainerLifeCycle implements Co
ConnectionFactory old=_factories.remove(factory.getProtocol()); ConnectionFactory old=_factories.remove(factory.getProtocol());
if (old!=null) if (old!=null)
removeBean(old); removeBean(old);
_factories.put(factory.getProtocol().toLowerCase(), factory); _factories.put(factory.getProtocol().toLowerCase(Locale.ENGLISH), factory);
addBean(factory); addBean(factory);
if (_defaultProtocol==null) if (_defaultProtocol==null)
_defaultProtocol=factory.getProtocol(); _defaultProtocol=factory.getProtocol();
@ -348,7 +349,7 @@ public abstract class AbstractConnector extends ContainerLifeCycle implements Co
{ {
synchronized (_factories) synchronized (_factories)
{ {
ConnectionFactory factory= _factories.remove(protocol.toLowerCase()); ConnectionFactory factory= _factories.remove(protocol.toLowerCase(Locale.ENGLISH));
removeBean(factory); removeBean(factory);
return factory; return factory;
} }
@ -403,7 +404,7 @@ public abstract class AbstractConnector extends ContainerLifeCycle implements Co
public void setDefaultProtocol(String defaultProtocol) public void setDefaultProtocol(String defaultProtocol)
{ {
_defaultProtocol = defaultProtocol.toLowerCase(); _defaultProtocol = defaultProtocol.toLowerCase(Locale.ENGLISH);
if (isRunning()) if (isRunning())
_defaultConnectionFactory=getConnectionFactory(_defaultProtocol); _defaultConnectionFactory=getConnectionFactory(_defaultProtocol);
} }

View File

@ -17,6 +17,8 @@
// //
package org.eclipse.jetty.server; package org.eclipse.jetty.server;
import java.util.Locale;
import javax.servlet.http.Cookie; import javax.servlet.http.Cookie;
import org.eclipse.jetty.util.LazyList; import org.eclipse.jetty.util.LazyList;
@ -283,7 +285,7 @@ public class CookieCutter
{ {
if (name.startsWith("$")) if (name.startsWith("$"))
{ {
String lowercaseName = name.toLowerCase(); String lowercaseName = name.toLowerCase(Locale.ENGLISH);
if ("$path".equals(lowercaseName)) if ("$path".equals(lowercaseName))
{ {
if (cookie!=null) if (cookie!=null)

View File

@ -34,6 +34,7 @@ import java.util.Collection;
import java.util.HashSet; import java.util.HashSet;
import java.util.Iterator; import java.util.Iterator;
import java.util.List; import java.util.List;
import java.util.Locale;
import java.util.Random; import java.util.Random;
import java.util.Timer; import java.util.Timer;
import java.util.TimerTask; import java.util.TimerTask;
@ -124,7 +125,7 @@ public class JDBCSessionIdManager extends AbstractSessionIdManager
public DatabaseAdaptor (DatabaseMetaData dbMeta) public DatabaseAdaptor (DatabaseMetaData dbMeta)
throws SQLException throws SQLException
{ {
_dbName = dbMeta.getDatabaseProductName().toLowerCase(); _dbName = dbMeta.getDatabaseProductName().toLowerCase(Locale.ENGLISH);
LOG.debug ("Using database {}",_dbName); LOG.debug ("Using database {}",_dbName);
_isLower = dbMeta.storesLowerCaseIdentifiers(); _isLower = dbMeta.storesLowerCaseIdentifiers();
_isUpper = dbMeta.storesUpperCaseIdentifiers(); _isUpper = dbMeta.storesUpperCaseIdentifiers();
@ -140,9 +141,9 @@ public class JDBCSessionIdManager extends AbstractSessionIdManager
public String convertIdentifier (String identifier) public String convertIdentifier (String identifier)
{ {
if (_isLower) if (_isLower)
return identifier.toLowerCase(); return identifier.toLowerCase(Locale.ENGLISH);
if (_isUpper) if (_isUpper)
return identifier.toUpperCase(); return identifier.toUpperCase(Locale.ENGLISH);
return identifier; return identifier;
} }

View File

@ -24,6 +24,7 @@ import java.io.IOException;
import java.io.InputStream; import java.io.InputStream;
import java.io.UnsupportedEncodingException; import java.io.UnsupportedEncodingException;
import java.net.Socket; import java.net.Socket;
import java.util.Locale;
import org.eclipse.jetty.server.session.SessionHandler; import org.eclipse.jetty.server.session.SessionHandler;
import org.eclipse.jetty.util.IO; import org.eclipse.jetty.util.IO;
@ -52,7 +53,7 @@ public class SelectChannelTimeoutTest extends ConnectorTimeoutTest
_handler.setSuspendFor(100); _handler.setSuspendFor(100);
_handler.setResumeAfter(25); _handler.setResumeAfter(25);
assertTrue(process(null).toUpperCase().contains("RESUMED")); assertTrue(process(null).toUpperCase(Locale.ENGLISH).contains("RESUMED"));
} }
@Test @Test
@ -66,7 +67,7 @@ public class SelectChannelTimeoutTest extends ConnectorTimeoutTest
_server.start(); _server.start();
_handler.setSuspendFor(50); _handler.setSuspendFor(50);
assertTrue(process(null).toUpperCase().contains("TIMEOUT")); assertTrue(process(null).toUpperCase(Locale.ENGLISH).contains("TIMEOUT"));
} }
@Test @Test
@ -81,7 +82,7 @@ public class SelectChannelTimeoutTest extends ConnectorTimeoutTest
_handler.setSuspendFor(100); _handler.setSuspendFor(100);
_handler.setCompleteAfter(25); _handler.setCompleteAfter(25);
assertTrue(process(null).toUpperCase().contains("COMPLETED")); assertTrue(process(null).toUpperCase(Locale.ENGLISH).contains("COMPLETED"));
} }
private synchronized String process(String content) throws UnsupportedEncodingException, IOException, InterruptedException private synchronized String process(String content) throws UnsupportedEncodingException, IOException, InterruptedException

View File

@ -30,6 +30,7 @@ import java.net.Socket;
import java.util.Arrays; import java.util.Arrays;
import java.util.Collection; import java.util.Collection;
import java.util.LinkedHashMap; import java.util.LinkedHashMap;
import java.util.Locale;
import java.util.Map; import java.util.Map;
import java.util.regex.Matcher; import java.util.regex.Matcher;
import java.util.regex.Pattern; import java.util.regex.Pattern;
@ -153,7 +154,7 @@ public class IPAccessHandlerTest
assertTrue(header.lookingAt()); assertTrue(header.lookingAt());
String headerName = header.group(1); String headerName = header.group(1);
String headerValue = header.group(2); String headerValue = header.group(2);
headers.put(headerName.toLowerCase(), headerValue.toLowerCase()); headers.put(headerName.toLowerCase(Locale.ENGLISH), headerValue.toLowerCase(Locale.ENGLISH));
} }
StringBuilder body = new StringBuilder(); StringBuilder body = new StringBuilder();

View File

@ -21,6 +21,7 @@ package org.eclipse.jetty.servlet;
import java.io.IOException; import java.io.IOException;
import java.util.Enumeration; import java.util.Enumeration;
import java.util.HashMap; import java.util.HashMap;
import java.util.Locale;
import java.util.Map; import java.util.Map;
import javax.servlet.ServletContext; import javax.servlet.ServletContext;
import javax.servlet.ServletException; import javax.servlet.ServletException;
@ -90,7 +91,7 @@ public class Invoker extends HttpServlet
{ {
String param=(String)e.nextElement(); String param=(String)e.nextElement();
String value=getInitParameter(param); String value=getInitParameter(param);
String lvalue=value.toLowerCase(); String lvalue=value.toLowerCase(Locale.ENGLISH);
if ("nonContextServlets".equals(param)) if ("nonContextServlets".equals(param))
{ {
_nonContextServlets=value.length()>0 && lvalue.startsWith("t"); _nonContextServlets=value.length()>0 && lvalue.startsWith("t");

View File

@ -24,6 +24,7 @@ import java.io.InputStream;
import java.io.OutputStream; import java.io.OutputStream;
import java.util.Enumeration; import java.util.Enumeration;
import java.util.HashMap; import java.util.HashMap;
import java.util.Locale;
import java.util.Map; import java.util.Map;
import javax.servlet.ServletException; import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServlet;
@ -138,7 +139,7 @@ public class CGI extends HttpServlet
if (!_env.envMap.containsKey("SystemRoot")) if (!_env.envMap.containsKey("SystemRoot"))
{ {
String os = System.getProperty("os.name"); String os = System.getProperty("os.name");
if (os != null && os.toLowerCase().indexOf("windows") != -1) if (os != null && os.toLowerCase(Locale.ENGLISH).indexOf("windows") != -1)
{ {
_env.set("SystemRoot","C:\\WINDOWS"); _env.set("SystemRoot","C:\\WINDOWS");
} }
@ -255,7 +256,7 @@ public class CGI extends HttpServlet
{ {
String name = (String)enm.nextElement(); String name = (String)enm.nextElement();
String value = req.getHeader(name); String value = req.getHeader(name);
env.set("HTTP_" + name.toUpperCase().replace('-','_'),value); env.set("HTTP_" + name.toUpperCase(Locale.ENGLISH).replace('-','_'),value);
} }
// these extra ones were from printenv on www.dev.nomura.co.uk // these extra ones were from printenv on www.dev.nomura.co.uk

View File

@ -20,6 +20,7 @@ package org.eclipse.jetty.servlets;
import java.io.IOException; import java.io.IOException;
import java.util.HashSet; import java.util.HashSet;
import java.util.Locale;
import java.util.Set; import java.util.Set;
import java.util.StringTokenizer; import java.util.StringTokenizer;
import java.util.regex.Pattern; import java.util.regex.Pattern;
@ -277,7 +278,7 @@ public class GzipFilter extends UserAgentFilter
{ {
for (int i=0; i< encodings.length; i++) for (int i=0; i< encodings.length; i++)
{ {
if (encodings[i].toLowerCase().contains(GZIP)) if (encodings[i].toLowerCase(Locale.ENGLISH).contains(GZIP))
{ {
if (isEncodingAcceptable(encodings[i])) if (isEncodingAcceptable(encodings[i]))
{ {
@ -286,7 +287,7 @@ public class GzipFilter extends UserAgentFilter
} }
} }
if (encodings[i].toLowerCase().contains(DEFLATE)) if (encodings[i].toLowerCase(Locale.ENGLISH).contains(DEFLATE))
{ {
if (isEncodingAcceptable(encodings[i])) if (isEncodingAcceptable(encodings[i]))
{ {

View File

@ -31,6 +31,7 @@ import java.util.Enumeration;
import java.util.HashMap; import java.util.HashMap;
import java.util.Iterator; import java.util.Iterator;
import java.util.List; import java.util.List;
import java.util.Locale;
import java.util.Map; import java.util.Map;
import javax.servlet.Filter; import javax.servlet.Filter;
import javax.servlet.FilterChain; import javax.servlet.FilterChain;

View File

@ -26,6 +26,7 @@ import java.net.URL;
import java.util.Arrays; import java.util.Arrays;
import java.util.EnumSet; import java.util.EnumSet;
import java.util.HashSet; import java.util.HashSet;
import java.util.Locale;
import java.util.Set; import java.util.Set;
import javax.servlet.DispatcherType; import javax.servlet.DispatcherType;
import javax.servlet.http.HttpServletResponse; import javax.servlet.http.HttpServletResponse;
@ -62,7 +63,7 @@ public class PutFilterTest
FilterHolder holder = tester.addFilter(PutFilter.class,"/*",EnumSet.of(DispatcherType.REQUEST)); FilterHolder holder = tester.addFilter(PutFilter.class,"/*",EnumSet.of(DispatcherType.REQUEST));
holder.setInitParameter("delAllowed","true"); holder.setInitParameter("delAllowed","true");
// Bloody Windows does not allow file renaming // Bloody Windows does not allow file renaming
if (!System.getProperty("os.name").toLowerCase().contains("windows")) if (!System.getProperty("os.name").toLowerCase(Locale.ENGLISH).contains("windows"))
holder.setInitParameter("putAtomic","true"); holder.setInitParameter("putAtomic","true");
tester.start(); tester.start();
} }

View File

@ -95,6 +95,7 @@ public class NextProtoNegoClientConnection extends AbstractConnection implements
catch (IOException x) catch (IOException x)
{ {
LOG.debug(x); LOG.debug(x);
NextProtoNego.remove(engine);
getEndPoint().close(); getEndPoint().close();
return -1; return -1;
} }

View File

@ -21,6 +21,7 @@ package org.eclipse.jetty.spdy.generator;
import java.io.ByteArrayOutputStream; import java.io.ByteArrayOutputStream;
import java.nio.ByteBuffer; import java.nio.ByteBuffer;
import java.nio.charset.Charset; import java.nio.charset.Charset;
import java.util.Locale;
import org.eclipse.jetty.spdy.CompressionDictionary; import org.eclipse.jetty.spdy.CompressionDictionary;
import org.eclipse.jetty.spdy.CompressionFactory; import org.eclipse.jetty.spdy.CompressionFactory;
@ -45,7 +46,7 @@ public class HeadersBlockGenerator
writeCount(version, buffer, headers.size()); writeCount(version, buffer, headers.size());
for (Fields.Field header : headers) for (Fields.Field header : headers)
{ {
String name = header.name().toLowerCase(); String name = header.name().toLowerCase(Locale.ENGLISH);
byte[] nameBytes = name.getBytes(iso1); byte[] nameBytes = name.getBytes(iso1);
writeNameLength(version, buffer, nameBytes.length); writeNameLength(version, buffer, nameBytes.length);
buffer.write(nameBytes, 0, nameBytes.length); buffer.write(nameBytes, 0, nameBytes.length);

View File

@ -23,6 +23,7 @@ import java.util.Arrays;
import java.util.Collections; import java.util.Collections;
import java.util.HashSet; import java.util.HashSet;
import java.util.List; import java.util.List;
import java.util.Locale;
import java.util.Set; import java.util.Set;
import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap; import java.util.concurrent.ConcurrentMap;
@ -206,7 +207,7 @@ public class ReferrerPushStrategy implements PushStrategy
if (header == null) if (header == null)
return true; return true;
String contentType = header.value().toLowerCase(); String contentType = header.value().toLowerCase(Locale.ENGLISH);
for (String pushContentType : pushContentTypes) for (String pushContentType : pushContentTypes)
if (contentType.startsWith(pushContentType)) if (contentType.startsWith(pushContentType))
return true; return true;

View File

@ -20,6 +20,7 @@ package org.eclipse.jetty.spdy.server.proxy;
import java.io.IOException; import java.io.IOException;
import java.nio.ByteBuffer; import java.nio.ByteBuffer;
import java.util.Locale;
import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeUnit;
import java.util.regex.Matcher; import java.util.regex.Matcher;
import java.util.regex.Pattern; import java.util.regex.Pattern;
@ -92,7 +93,7 @@ public class ProxyHTTPSPDYConnection extends HttpConnection implements HttpParse
@Override @Override
public boolean parsedHeader(HttpHeader header, String headerName, String headerValue) public boolean parsedHeader(HttpHeader header, String headerName, String headerValue)
{ {
switch (headerName.toLowerCase()) switch (headerName.toLowerCase(Locale.ENGLISH))
{ {
case "host": case "host":
headers.put(HTTPSPDYHeader.HOST.name(version), headerValue); headers.put(HTTPSPDYHeader.HOST.name(version), headerValue);

View File

@ -25,7 +25,6 @@ import javax.net.ssl.SSLEngine;
import org.eclipse.jetty.io.AbstractConnection; import org.eclipse.jetty.io.AbstractConnection;
import org.eclipse.jetty.io.Connection; import org.eclipse.jetty.io.Connection;
import org.eclipse.jetty.io.EndPoint; import org.eclipse.jetty.io.EndPoint;
import org.eclipse.jetty.io.ssl.SslConnection.DecryptedEndPoint;
import org.eclipse.jetty.npn.NextProtoNego; import org.eclipse.jetty.npn.NextProtoNego;
import org.eclipse.jetty.server.ConnectionFactory; import org.eclipse.jetty.server.ConnectionFactory;
import org.eclipse.jetty.server.Connector; import org.eclipse.jetty.server.Connector;
@ -93,6 +92,7 @@ public class NextProtoNegoServerConnection extends AbstractConnection implements
catch (IOException x) catch (IOException x)
{ {
LOG.debug(x); LOG.debug(x);
NextProtoNego.remove(engine);
getEndPoint().close(); getEndPoint().close();
return -1; return -1;
} }

View File

@ -38,6 +38,7 @@ import java.util.Enumeration;
import java.util.HashMap; import java.util.HashMap;
import java.util.Iterator; import java.util.Iterator;
import java.util.List; import java.util.List;
import java.util.Locale;
import java.util.Map; import java.util.Map;
import java.util.Properties; import java.util.Properties;
import java.util.Set; import java.util.Set;
@ -269,7 +270,7 @@ public class Config
} }
else else
{ {
String name = entry.getName().toLowerCase(); String name = entry.getName().toLowerCase(Locale.ENGLISH);
if (name.endsWith(".jar") || name.endsWith(".zip")) if (name.endsWith(".jar") || name.endsWith(".zip"))
{ {
String jar = entry.getCanonicalPath(); String jar = entry.getCanonicalPath();
@ -796,7 +797,7 @@ public class Config
} }
// Add XML configuration // Add XML configuration
if (subject.toLowerCase().endsWith(".xml")) if (subject.toLowerCase(Locale.ENGLISH).endsWith(".xml"))
{ {
// Config file // Config file
File f = new File(fixPath(file)); File f = new File(fixPath(file));
@ -807,7 +808,7 @@ public class Config
} }
// Set the main class to execute (overrides any previously set) // Set the main class to execute (overrides any previously set)
if (subject.toLowerCase().endsWith(".class")) if (subject.toLowerCase(Locale.ENGLISH).endsWith(".class"))
{ {
// Class // Class
String cn = expand(subject.substring(0,subject.length() - 6)); String cn = expand(subject.substring(0,subject.length() - 6));
@ -820,7 +821,7 @@ public class Config
} }
// Add raw classpath entry // Add raw classpath entry
if (subject.toLowerCase().endsWith(".path")) if (subject.toLowerCase(Locale.ENGLISH).endsWith(".path"))
{ {
// classpath (jetty.class.path?) to add to runtime classpath // classpath (jetty.class.path?) to add to runtime classpath
String cn = expand(subject.substring(0,subject.length() - 5)); String cn = expand(subject.substring(0,subject.length() - 5));

View File

@ -46,6 +46,7 @@ import java.util.Collections;
import java.util.Date; import java.util.Date;
import java.util.HashSet; import java.util.HashSet;
import java.util.List; import java.util.List;
import java.util.Locale;
import java.util.Properties; import java.util.Properties;
import java.util.Set; import java.util.Set;
@ -365,7 +366,7 @@ public class Main
return false; return false;
} }
String name = path.getName().toLowerCase(); String name = path.getName().toLowerCase(Locale.ENGLISH);
return (name.startsWith("jetty") && name.endsWith(".xml")); return (name.startsWith("jetty") && name.endsWith(".xml"));
} }
}); });
@ -639,7 +640,7 @@ public class Main
private String resolveXmlConfig(String xmlFilename) throws FileNotFoundException private String resolveXmlConfig(String xmlFilename) throws FileNotFoundException
{ {
if (!xmlFilename.toLowerCase().endsWith(".xml")) if (!xmlFilename.toLowerCase(Locale.ENGLISH).endsWith(".xml"))
{ {
// Nothing to resolve. // Nothing to resolve.
return xmlFilename; return xmlFilename;
@ -853,7 +854,7 @@ public class Main
if (element.isFile()) if (element.isFile())
{ {
String name = element.getName().toLowerCase(); String name = element.getName().toLowerCase(Locale.ENGLISH);
if (name.endsWith(".jar")) if (name.endsWith(".jar"))
{ {
return JarVersion.getVersion(element); return JarVersion.getVersion(element);
@ -1105,7 +1106,7 @@ public class Main
@Override @Override
public boolean accept(File dir, String name) public boolean accept(File dir, String name)
{ {
return name.toLowerCase().endsWith(".ini"); return name.toLowerCase(Locale.ENGLISH).endsWith(".ini");
} }
}); });
Arrays.sort(inis); Arrays.sort(inis);

View File

@ -22,6 +22,7 @@ import java.lang.reflect.Method;
import java.lang.reflect.Modifier; import java.lang.reflect.Modifier;
import java.util.Arrays; import java.util.Arrays;
import java.util.HashSet; import java.util.HashSet;
import java.util.Locale;
import java.util.Map; import java.util.Map;
import java.util.Set; import java.util.Set;
@ -89,9 +90,9 @@ public class JSONObjectConvertor implements JSON.Convertor
{ {
String name=m.getName(); String name=m.getName();
if (name.startsWith("is")) if (name.startsWith("is"))
name=name.substring(2,3).toLowerCase()+name.substring(3); name=name.substring(2,3).toLowerCase(Locale.ENGLISH)+name.substring(3);
else if (name.startsWith("get")) else if (name.startsWith("get"))
name=name.substring(3,4).toLowerCase()+name.substring(4); name=name.substring(3,4).toLowerCase(Locale.ENGLISH)+name.substring(4);
else else
continue; continue;

View File

@ -26,6 +26,7 @@ import java.util.Arrays;
import java.util.HashMap; import java.util.HashMap;
import java.util.HashSet; import java.util.HashSet;
import java.util.Iterator; import java.util.Iterator;
import java.util.Locale;
import java.util.Map; import java.util.Map;
import java.util.Set; import java.util.Set;
@ -122,9 +123,9 @@ public class JSONPojoConvertor implements JSON.Convertor
if(m.getReturnType()!=null) if(m.getReturnType()!=null)
{ {
if (name.startsWith("is") && name.length()>2) if (name.startsWith("is") && name.length()>2)
name=name.substring(2,3).toLowerCase()+name.substring(3); name=name.substring(2,3).toLowerCase(Locale.ENGLISH)+name.substring(3);
else if (name.startsWith("get") && name.length()>3) else if (name.startsWith("get") && name.length()>3)
name=name.substring(3,4).toLowerCase()+name.substring(4); name=name.substring(3,4).toLowerCase(Locale.ENGLISH)+name.substring(4);
else else
break; break;
if(includeField(name, m)) if(includeField(name, m))
@ -134,7 +135,7 @@ public class JSONPojoConvertor implements JSON.Convertor
case 1: case 1:
if (name.startsWith("set") && name.length()>3) if (name.startsWith("set") && name.length()>3)
{ {
name=name.substring(3,4).toLowerCase()+name.substring(4); name=name.substring(3,4).toLowerCase(Locale.ENGLISH)+name.substring(4);
if(includeField(name, m)) if(includeField(name, m))
addSetter(name, m); addSetter(name, m);
} }

View File

@ -23,6 +23,7 @@ import java.util.Collections;
import java.util.Iterator; import java.util.Iterator;
import java.util.LinkedHashMap; import java.util.LinkedHashMap;
import java.util.LinkedHashSet; import java.util.LinkedHashSet;
import java.util.Locale;
import java.util.Map; import java.util.Map;
import java.util.Set; import java.util.Set;
@ -93,7 +94,7 @@ public class Fields implements Iterable<Fields.Field>
*/ */
public Field get(String name) public Field get(String name)
{ {
return fields.get(name.trim().toLowerCase()); return fields.get(name.trim().toLowerCase(Locale.ENGLISH));
} }
/** /**
@ -107,7 +108,7 @@ public class Fields implements Iterable<Fields.Field>
name = name.trim(); name = name.trim();
// Preserve the case for the field name // Preserve the case for the field name
Field field = new Field(name, value); Field field = new Field(name, value);
fields.put(name.toLowerCase(), field); fields.put(name.toLowerCase(Locale.ENGLISH), field);
} }
/** /**
@ -118,7 +119,7 @@ public class Fields implements Iterable<Fields.Field>
public void put(Field field) public void put(Field field)
{ {
if (field != null) if (field != null)
fields.put(field.name().toLowerCase(), field); fields.put(field.name().toLowerCase(Locale.ENGLISH), field);
} }
/** /**
@ -131,16 +132,16 @@ public class Fields implements Iterable<Fields.Field>
public void add(String name, String value) public void add(String name, String value)
{ {
name = name.trim(); name = name.trim();
Field field = fields.get(name.toLowerCase()); Field field = fields.get(name.toLowerCase(Locale.ENGLISH));
if (field == null) if (field == null)
{ {
field = new Field(name, value); field = new Field(name, value);
fields.put(name.toLowerCase(), field); fields.put(name.toLowerCase(Locale.ENGLISH), field);
} }
else else
{ {
field = new Field(field.name(), field.values(), value); field = new Field(field.name(), field.values(), value);
fields.put(name.toLowerCase(), field); fields.put(name.toLowerCase(Locale.ENGLISH), field);
} }
} }
@ -153,7 +154,7 @@ public class Fields implements Iterable<Fields.Field>
public Field remove(String name) public Field remove(String name)
{ {
name = name.trim(); name = name.trim();
return fields.remove(name.toLowerCase()); return fields.remove(name.toLowerCase(Locale.ENGLISH));
} }
/** /**
@ -234,7 +235,7 @@ public class Fields implements Iterable<Fields.Field>
@Override @Override
public int hashCode() public int hashCode()
{ {
int result = name.toLowerCase().hashCode(); int result = name.toLowerCase(Locale.ENGLISH).hashCode();
result = 31 * result + Arrays.hashCode(values); result = 31 * result + Arrays.hashCode(values);
return result; return result;
} }

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