Merge branch 'jetty-9.4.x'

This commit is contained in:
Joakim Erdfelt 2016-10-20 09:58:13 -07:00
commit d70a20c00e
43 changed files with 5036 additions and 3942 deletions

File diff suppressed because it is too large Load Diff

View File

@ -8,68 +8,67 @@ gcloud
[depends] [depends]
gcloud gcloud
jcl-slf4j jcl-slf4j
jul-slf4j jul-impl
[files] [files]
maven://com.google.cloud/google-cloud-datastore/0.4.0|lib/gcloud/google-cloud-datastore-0.4.0.jar maven://aopalliance/aopalliance/1.0|lib/gcloud/aopalliance-1.0.jar
maven://com.google.cloud/google-cloud-core/0.4.0|lib/gcloud/google-cloud-core-0.4.0.jar maven://com.fasterxml.jackson.core/jackson-core/2.1.3|lib/gcloud/jackson-core-2.1.3.jar
maven://com.google.api-client/google-api-client-appengine/1.21.0|lib/gcloud/google-api-client-appengine-1.21.0.jar
maven://com.google.api-client/google-api-client-servlet/1.21.0|lib/gcloud/google-api-client-servlet-1.21.0.jar
maven://com.google.api-client/google-api-client/1.20.0|lib/gcloud/google-api-client-1.20.0.jar
maven://com.google.api.grpc/grpc-google-common-protos/0.1.0|lib/gcloud/grpc-google-common-protos-0.1.0.jar
maven://com.google.api.grpc/grpc-google-iam-v1/0.1.0|lib/gcloud/grpc-google-iam-v1-0.1.0.jar
maven://com.google.api/gax/0.0.18|lib/gcloud/gax-0.0.18.jar
maven://com.google.auth/google-auth-library-credentials/0.3.1|lib/gcloud/google-auth-library-credentials-0.3.1.jar maven://com.google.auth/google-auth-library-credentials/0.3.1|lib/gcloud/google-auth-library-credentials-0.3.1.jar
maven://com.google.auth/google-auth-library-oauth2-http/0.3.1|lib/gcloud/google-auth-library-oauth2-http-0.3.1.jar maven://com.google.auth/google-auth-library-oauth2-http/0.3.1|lib/gcloud/google-auth-library-oauth2-http-0.3.1.jar
maven://com.google.http-client/google-http-client-jackson2/1.19.0|lib/gcloud/google-http-client-jackson2-1.19.0.jar maven://com.google.auto.value/auto-value/1.1|lib/gcloud/auto-value-1.1.jar
maven://com.fasterxml.jackson.core/jackson-core/2.1.3|lib/gcloud/jackson-core-2.1.3.jar maven://com.google.cloud.datastore/datastore-v1-proto-client/1.2.0|lib/gcloud/datastore-v1-proto-client-1.2.0.jar
maven://com.google.http-client/google-http-client/1.21.0|lib/gcloud/google-http-client-1.21.0.jar maven://com.google.cloud.datastore/datastore-v1-protos/1.2.0|lib/gcloud/datastore-v1-protos-1.2.0.jar
maven://com.google.cloud/google-cloud-core/0.4.0|lib/gcloud/google-cloud-core-0.4.0.jar
maven://com.google.cloud/google-cloud-datastore/0.4.0|lib/gcloud/google-cloud-datastore-0.4.0.jar
maven://com.google.code.findbugs/jsr305/1.3.9|lib/gcloud/jsr305-1.3.9.jar maven://com.google.code.findbugs/jsr305/1.3.9|lib/gcloud/jsr305-1.3.9.jar
maven://org.apache.httpcomponents/httpclient/4.0.1|lib/gcloud/httpclient-4.0.1.jar maven://com.google.code.gson/gson/2.3|lib/gcloud/gson-2.3.jar
maven://org.apache.httpcomponents/httpcore/4.0.1|lib/gcloud/httpcore-4.0.1.jar
maven://commons-codec/commons-codec/1.3|lib/gcloud/commons-codec-1.3.jar
maven://com.google.oauth-client/google-oauth-client/1.21.0|lib/gcloud/google-oauth-client-1.21.0.jar
maven://com.google.guava/guava/19.0|lib/gcloud/guava-19.0.jar maven://com.google.guava/guava/19.0|lib/gcloud/guava-19.0.jar
maven://com.google.api-client/google-api-client-appengine/1.21.0|lib/gcloud/google-api-client-appengine-1.21.0.jar
maven://com.google.oauth-client/google-oauth-client-appengine/1.21.0|lib/gcloud/google-oauth-client-appengine-1.21.0.jar
maven://com.google.oauth-client/google-oauth-client-servlet/1.21.0|lib/gcloud/google-oauth-client-servlet-1.21.0.jar
maven://com.google.http-client/google-http-client-jdo/1.21.0|lib/gcloud/google-http-client-jdo-1.21.0.jar
maven://com.google.api-client/google-api-client-servlet/1.21.0|lib/gcloud/google-api-client-servlet-1.21.0.jar
maven://javax.jdo/jdo2-api/2.3-eb|lib/gcloud/jdo2-api-2.3-eb.jar
maven://javax.transaction/transaction-api/1.1|lib/gcloud/transaction-api-1.1.jar
maven://com.google.http-client/google-http-client-appengine/1.21.0|lib/gcloud/google-http-client-appengine-1.21.0.jar maven://com.google.http-client/google-http-client-appengine/1.21.0|lib/gcloud/google-http-client-appengine-1.21.0.jar
maven://com.google.http-client/google-http-client-jackson/1.21.0|lib/gcloud/google-http-client-jackson-1.21.0.jar maven://com.google.http-client/google-http-client-jackson/1.21.0|lib/gcloud/google-http-client-jackson-1.21.0.jar
maven://org.codehaus.jackson/jackson-core-asl/1.9.11|lib/gcloud/jackson-core-asl-1.9.11.jar maven://com.google.http-client/google-http-client-jackson2/1.19.0|lib/gcloud/google-http-client-jackson2-1.19.0.jar
maven://joda-time/joda-time/2.9.2|lib/gcloud/joda-time-2.9.2.jar maven://com.google.http-client/google-http-client-jdo/1.21.0|lib/gcloud/google-http-client-jdo-1.21.0.jar
maven://org.json/json/20151123|lib/gcloud/json-20151123.jar maven://com.google.http-client/google-http-client-protobuf/1.20.0|lib/gcloud/google-http-client-protobuf-1.20.0.jar
maven://com.google.http-client/google-http-client/1.21.0|lib/gcloud/google-http-client-1.21.0.jar
maven://com.google.inject/guice/4.0|lib/gcloud/guice-4.0.jar
maven://com.google.oauth-client/google-oauth-client-appengine/1.21.0|lib/gcloud/google-oauth-client-appengine-1.21.0.jar
maven://com.google.oauth-client/google-oauth-client-servlet/1.21.0|lib/gcloud/google-oauth-client-servlet-1.21.0.jar
maven://com.google.oauth-client/google-oauth-client/1.21.0|lib/gcloud/google-oauth-client-1.21.0.jar
maven://com.google.protobuf.nano/protobuf-javanano/3.0.0-alpha-5|lib/gcloud/protobuf-javanano-3.0.0-alpha-5.jar
maven://com.google.protobuf/protobuf-java-util/3.0.0|lib/gcloud/protobuf-java-util-3.0.0.jar
maven://com.google.protobuf/protobuf-java/3.0.0|lib/gcloud/protobuf-java-3.0.0.jar maven://com.google.protobuf/protobuf-java/3.0.0|lib/gcloud/protobuf-java-3.0.0.jar
maven://com.google.api/gax/0.0.18|lib/gcloud/gax-0.0.18.jar maven://com.google.protobuf/protobuf-lite/3.0.1|lib/gcloud/protobuf-lite-3.0.1.jar
maven://com.google.auto.value/auto-value/1.1|lib/gcloud/auto-value-1.1.jar maven://com.squareup.okhttp/okhttp/2.5.0|lib/gcloud/okhttp-2.5.0.jar
maven://com.squareup.okio/okio/1.6.0|lib/gcloud/okio-1.6.0.jar
maven://commons-codec/commons-codec/1.3|lib/gcloud/commons-codec-1.3.jar
maven://io.grpc/grpc-all/1.0.1|lib/gcloud/grpc-all-1.0.1.jar maven://io.grpc/grpc-all/1.0.1|lib/gcloud/grpc-all-1.0.1.jar
maven://io.grpc/grpc-auth/1.0.1|lib/gcloud/grpc-auth-1.0.1.jar maven://io.grpc/grpc-auth/1.0.1|lib/gcloud/grpc-auth-1.0.1.jar
maven://io.grpc/grpc-context/1.0.1|lib/gcloud/grpc-context-1.0.1.jar maven://io.grpc/grpc-context/1.0.1|lib/gcloud/grpc-context-1.0.1.jar
maven://io.grpc/grpc-protobuf/1.0.1|lib/gcloud/grpc-protobuf-1.0.1.jar
maven://com.google.protobuf/protobuf-java-util/3.0.0|lib/gcloud/protobuf-java-util-3.0.0.jar
maven://com.google.code.gson/gson/2.3|lib/gcloud/gson-2.3.jar
maven://io.grpc/grpc-netty/1.0.1|lib/gcloud/grpc-netty-1.0.1.jar
maven://io.netty/netty-codec-http2/4.1.3.Final|lib/gcloud/netty-codec-http2-4.1.3.jar
maven://io.netty/netty-codec-http/4.1.3.Final|lib/gcloud/netty-codec-http-4.1.3.Final.jar
maven://io.netty/netty-codec/4.1.3.Final|lib/gcloud/netty-codec-4.1.3.Final.jar
maven://io.netty/netty-handler/4.1.3.Final|lib/gcloud/netty-handler-4.1.3.Final.jar
maven://io.netty/netty-buffer/4.1.3.Final|lib/gcloud/netty-buffer-4.1.3.Final.jar
maven://io.netty/netty-common/4.1.3.Final|lib/gcloud/netty-common-4.1.3.Final.jar
maven://io.netty/netty-transport/4.1.3.Final|lib/gcloud/netty-transport-4.1.3.Final.jar
maven://io.netty/netty-resolver/4.1.3.Final|lib/gcloud/netty-resolver-4.1.3.Final.jar
maven://io.grpc/grpc-stub/1.0.1|lib/gcloud/grpc-stub-1.0.1.jar
maven://io.grpc/grpc-protobuf-nano/1.0.1|lib/gcloud/grpc-protobuf-nano-1.0.1.jar
maven://com.google.protobuf.nano/protobuf-javanano/3.0.0-alpha-5|lib/gcloud/protobuf-javanano/3.0.0-alpha-5.jar
maven://io.grpc/grpc-core/1.0.1|lib/gcloud/grpc-core-1.0.1.jar maven://io.grpc/grpc-core/1.0.1|lib/gcloud/grpc-core-1.0.1.jar
maven://io.grpc/grpc-netty/1.0.1|lib/gcloud/grpc-netty-1.0.1.jar
maven://io.grpc/grpc-okhttp/1.0.1|lib/gcloud/grpc-okhttp-1.0.1.jar maven://io.grpc/grpc-okhttp/1.0.1|lib/gcloud/grpc-okhttp-1.0.1.jar
maven://com.squareup.okio/okio/1.6.0|lib/gcloud/okio-1.6.0.jar
maven://com.squareup.okhttp/okhttp/2.5.0|lib/gcloud/okhttp-2.5.0.jar
maven://io.grpc/grpc-protobuf-lite/1.0.1|lib/gcloud/grpc-protobuf-lite-1.0.1.jar maven://io.grpc/grpc-protobuf-lite/1.0.1|lib/gcloud/grpc-protobuf-lite-1.0.1.jar
maven://com.google.protobuf/protobuf-lite/3.0.1|lib/gcloud/protobuf-lite-3.0.1.jar maven://io.grpc/grpc-protobuf-nano/1.0.1|lib/gcloud/grpc-protobuf-nano-1.0.1.jar
maven://com.google.inject/guice/4.0|lib/gcloud/guice-4.0.jar maven://io.grpc/grpc-protobuf/1.0.1|lib/gcloud/grpc-protobuf-1.0.1.jar
maven://io.grpc/grpc-stub/1.0.1|lib/gcloud/grpc-stub-1.0.1.jar
maven://io.netty/netty-buffer/4.1.3.Final|lib/gcloud/netty-buffer-4.1.3.Final.jar
maven://io.netty/netty-codec-http/4.1.3.Final|lib/gcloud/netty-codec-http-4.1.3.Final.jar
maven://io.netty/netty-codec-http2/4.1.3.Final|lib/gcloud/netty-codec-http2-4.1.3.jar
maven://io.netty/netty-codec/4.1.3.Final|lib/gcloud/netty-codec-4.1.3.Final.jar
maven://io.netty/netty-common/4.1.3.Final|lib/gcloud/netty-common-4.1.3.Final.jar
maven://io.netty/netty-handler/4.1.3.Final|lib/gcloud/netty-handler-4.1.3.Final.jar
maven://io.netty/netty-resolver/4.1.3.Final|lib/gcloud/netty-resolver-4.1.3.Final.jar
maven://io.netty/netty-transport/4.1.3.Final|lib/gcloud/netty-transport-4.1.3.Final.jar
maven://javax.inject/javax.inject/1|lib/gcloud/javax.inject-1.jar maven://javax.inject/javax.inject/1|lib/gcloud/javax.inject-1.jar
maven://aopalliance/aopalliance/1.0|lib/gcloud/aopalliance-1.0.jar maven://javax.jdo/jdo2-api/2.3-eb|lib/gcloud/jdo2-api-2.3-eb.jar
maven://com.google.api.grpc/grpc-google-common-protos/0.1.0|lib/gcloud/grpc-google-common-protos-0.1.0.jar maven://javax.transaction/transaction-api/1.1|lib/gcloud/transaction-api-1.1.jar
maven://com.google.api.grpc/grpc-google-iam-v1/0.1.0|lib/gcloud/grpc-google-iam-v1-0.1.0.jar maven://joda-time/joda-time/2.9.2|lib/gcloud/joda-time-2.9.2.jar
maven://com.google.cloud.datastore/datastore-v1-protos/1.2.0|lib/gcloud/datastore-v1-protos-1.2.0.jar maven://org.apache.httpcomponents/httpclient/4.0.1|lib/gcloud/httpclient-4.0.1.jar
maven://com.google.cloud.datastore/datastore-v1-proto-client/1.2.0|lib/gcloud/datastore-v1-proto-client-1.2.0.jar maven://org.apache.httpcomponents/httpcore/4.0.1|lib/gcloud/httpcore-4.0.1.jar
maven://com.google.http-client/google-http-client-protobuf/1.20.0|lib/gcloud/google-http-client-protobuf-1.20.0.jar maven://org.codehaus.jackson/jackson-core-asl/1.9.11|lib/gcloud/jackson-core-asl-1.9.11.jar
maven://com.google.api-client/google-api-client/1.20.0|lib/gcloud/google-api-client/1.20.0 maven://org.json/json/20151123|lib/gcloud/json-20151123.jar

View File

@ -9,11 +9,13 @@ session-store
[depend] [depend]
sessions sessions
sessions/infinispan/default
[files] [files]
maven://org.infinispan/infinispan-embedded/7.1.1.Final|lib/infinispan/infinispan-embedded-7.1.1.Final.jar maven://org.infinispan/infinispan-embedded/7.1.1.Final|lib/infinispan/infinispan-embedded-7.1.1.Final.jar
[xml]
etc/sessions/infinispan/default.xml
[lib] [lib]
lib/jetty-infinispan-${jetty.version}.jar lib/jetty-infinispan-${jetty.version}.jar
lib/infinispan/*.jar lib/infinispan/*.jar
@ -22,3 +24,4 @@ lib/infinispan/*.jar
Infinispan is an open source project hosted on Github and released under the Apache 2.0 license. Infinispan is an open source project hosted on Github and released under the Apache 2.0 license.
http://infinispan.org/ http://infinispan.org/
http://www.apache.org/licenses/LICENSE-2.0.html http://www.apache.org/licenses/LICENSE-2.0.html

View File

@ -9,10 +9,13 @@ session-store
[depend] [depend]
sessions sessions
sessions/infinispan/remote
[files] [files]
maven://org.infinispan/infinispan-remote/7.1.1.Final|lib/infinispan/infinispan-remote-7.1.1.Final.jar maven://org.infinispan/infinispan-remote/7.1.1.Final|lib/infinispan/infinispan-remote-7.1.1.Final.jar
basehome:modules/session-store-infinispan-remote/
[xml]
etc/sessions/infinispan/remote.xml
[lib] [lib]
lib/jetty-infinispan-${jetty.version}.jar lib/jetty-infinispan-${jetty.version}.jar
@ -28,3 +31,8 @@ http://www.apache.org/licenses/LICENSE-2.0.html
#jetty.session.infinispan.remoteCacheName=sessions #jetty.session.infinispan.remoteCacheName=sessions
#jetty.session.infinispan.idleTimeout.seconds=0 #jetty.session.infinispan.idleTimeout.seconds=0
#jetty.session.gracePeriod.seconds=3600 #jetty.session.gracePeriod.seconds=3600

View File

@ -1,6 +0,0 @@
[description]
Enable use of DefaultCache for session data storage
[xml]
etc/sessions/infinispan/default.xml

View File

@ -1,9 +0,0 @@
[description]
Enable use of HotRod remote cache for session data storage
[files]
https://raw.githubusercontent.com/eclipse/jetty.project/master/jetty-infinispan/src/main/infinispan-resources/hotrod-client.properties?id=${jetty.tag.version}|resources/hotrod-client.properties
[xml]
etc/sessions/infinispan/remote.xml

View File

@ -29,6 +29,7 @@ import java.util.Date;
import java.util.Enumeration; import java.util.Enumeration;
import java.util.List; import java.util.List;
import java.util.concurrent.CopyOnWriteArrayList; import java.util.concurrent.CopyOnWriteArrayList;
import java.util.concurrent.Executor;
import java.util.concurrent.Future; import java.util.concurrent.Future;
import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeUnit;
@ -376,29 +377,39 @@ public class Server extends HandlerWrapper implements Attributes
} }
HttpGenerator.setJettyVersion(HttpConfiguration.SERVER_VERSION); HttpGenerator.setJettyVersion(HttpConfiguration.SERVER_VERSION);
MultiException mex=new MultiException();
// check size of thread pool // check size of thread pool
SizedThreadPool pool = getBean(SizedThreadPool.class); SizedThreadPool pool = getBean(SizedThreadPool.class);
int max=pool==null?-1:pool.getMaxThreads(); int max=pool==null?-1:pool.getMaxThreads();
int selectors=0; int selectors=0;
int acceptors=0; int acceptors=0;
if (mex.size()==0)
{
for (Connector connector : _connectors)
{
if (connector instanceof AbstractConnector)
acceptors+=((AbstractConnector)connector).getAcceptors();
if (connector instanceof ServerConnector) for (Connector connector : _connectors)
selectors+=((ServerConnector)connector).getSelectorManager().getSelectorCount(); {
} if (!(connector instanceof AbstractConnector))
continue;
AbstractConnector abstractConnector = (AbstractConnector) connector;
Executor connectorExecutor = connector.getExecutor();
if (connectorExecutor != pool)
// Do not count the selectors and acceptors from this connector at server level, because connector uses dedicated executor.
continue;
acceptors += abstractConnector.getAcceptors();
if (connector instanceof ServerConnector)
selectors+=((ServerConnector)connector).getSelectorManager().getSelectorCount();
} }
int needed=1+selectors+acceptors; int needed=1+selectors+acceptors;
if (max>0 && needed>max) if (max>0 && needed>max)
throw new IllegalStateException(String.format("Insufficient threads: max=%d < needed(acceptors=%d + selectors=%d + request=1)",max,acceptors,selectors)); throw new IllegalStateException(String.format("Insufficient threads: max=%d < needed(acceptors=%d + selectors=%d + request=1)",max,acceptors,selectors));
MultiException mex=new MultiException();
try try
{ {
super.doStart(); super.doStart();

View File

@ -0,0 +1,86 @@
//
// ========================================================================
// Copyright (c) 1995-2016 Mort Bay Consulting Pty. Ltd.
// ------------------------------------------------------------------------
// All rights reserved. This program and the accompanying materials
// are made available under the terms of the Eclipse Public License v1.0
// and Apache License v2.0 which accompanies this distribution.
//
// The Eclipse Public License is available at
// http://www.eclipse.org/legal/epl-v10.html
//
// The Apache License v2.0 is available at
// http://www.opensource.org/licenses/apache2.0.php
//
// You may elect to redistribute this code under either of these licenses.
// ========================================================================
//
package org.eclipse.jetty.server;
import org.eclipse.jetty.util.thread.QueuedThreadPool;
import org.eclipse.jetty.util.thread.ThreadPool;
import org.junit.After;
import org.junit.Test;
public class InsufficientThreadsDetectionTest {
private Server _server;
@After
public void dispose() throws Exception
{
_server.stop();
}
@Test(expected = IllegalStateException.class)
public void testConnectorUsesServerExecutorWithNotEnoughThreads() throws Exception
{
// server has 3 threads in the executor
_server = new Server(new QueuedThreadPool(3));
// connector will use executor from server because connectorPool is null
ThreadPool connectorPool = null;
// connector requires 7 threads(2 + 4 + 1)
ServerConnector connector = new ServerConnector(_server, connectorPool, null, null, 2, 4, new HttpConnectionFactory());
connector.setPort(0);
_server.addConnector(connector);
// should throw IllegalStateException because there are no required threads in server pool
_server.start();
}
@Test
public void testConnectorWithDedicatedExecutor() throws Exception
{
// server has 3 threads in the executor
_server = new Server(new QueuedThreadPool(3));
// connector pool has 100 threads
ThreadPool connectorPool = new QueuedThreadPool(100);
// connector requires 7 threads(2 + 4 + 1)
ServerConnector connector = new ServerConnector(_server, connectorPool, null, null, 2, 4, new HttpConnectionFactory());
connector.setPort(0);
_server.addConnector(connector);
// should not throw exception because connector uses own executor, so its threads should not be counted
_server.start();
}
@Test // Github issue #586
public void testCaseForMultipleConnectors() throws Exception {
// server has 3 threads in the executor
_server = new Server(new QueuedThreadPool(3));
// first connector consumes all 3 threads from server pool
_server.addConnector(new ServerConnector(_server, null, null, null, 1, 1, new HttpConnectionFactory()));
// second connect also require 3 threads but uses own executor, so its threads should not be counted
final QueuedThreadPool connectorPool = new QueuedThreadPool(3, 3);
_server.addConnector(new ServerConnector(_server, connectorPool, null, null, 1, 1, new HttpConnectionFactory()));
// should not throw exception because limit was not overflown
_server.start();
}
}

View File

@ -34,6 +34,7 @@ import org.eclipse.jetty.start.builders.StartDirBuilder;
import org.eclipse.jetty.start.builders.StartIniBuilder; import org.eclipse.jetty.start.builders.StartIniBuilder;
import org.eclipse.jetty.start.fileinits.BaseHomeFileInitializer; import org.eclipse.jetty.start.fileinits.BaseHomeFileInitializer;
import org.eclipse.jetty.start.fileinits.MavenLocalRepoFileInitializer; import org.eclipse.jetty.start.fileinits.MavenLocalRepoFileInitializer;
import org.eclipse.jetty.start.fileinits.LocalFileInitializer;
import org.eclipse.jetty.start.fileinits.TestFileInitializer; import org.eclipse.jetty.start.fileinits.TestFileInitializer;
import org.eclipse.jetty.start.fileinits.UriFileInitializer; import org.eclipse.jetty.start.fileinits.UriFileInitializer;
@ -74,18 +75,24 @@ public class BaseBuilder
// Copy from basehome // Copy from basehome
fileInitializers.add(new BaseHomeFileInitializer(baseHome)); fileInitializers.add(new BaseHomeFileInitializer(baseHome));
// Handle local directories
fileInitializers.add(new LocalFileInitializer(baseHome));
// No downloads performed // No downloads performed
fileInitializers.add(new TestFileInitializer()); fileInitializers.add(new TestFileInitializer(baseHome));
} }
else if (args.isDownload()) else if (args.isCreateFiles())
{ {
// Handle local directories
fileInitializers.add(new LocalFileInitializer(baseHome));
// Downloads are allowed to be performed // Downloads are allowed to be performed
// Setup Maven Local Repo // Setup Maven Local Repo
Path localRepoDir = args.getMavenLocalRepoDir(); Path localRepoDir = args.findMavenLocalRepoDir();
if (localRepoDir != null) if (localRepoDir != null)
{ {
// Use provided local repo directory // Use provided local repo directory
fileInitializers.add(new MavenLocalRepoFileInitializer(baseHome,localRepoDir)); fileInitializers.add(new MavenLocalRepoFileInitializer(baseHome,localRepoDir,args.getMavenLocalRepoDir()==null));
} }
else else
{ {
@ -258,105 +265,36 @@ public class BaseBuilder
/** /**
* Process a specific file resource * Process a specific file resource
* *
* @param arg * @param arg the fileArg to work with
* the fileArg to work with
* @param file
* the resolved file reference to work with
* @return true if change was made as a result of the file, false if no change made. * @return true if change was made as a result of the file, false if no change made.
* @throws IOException * @throws IOException
* if there was an issue in processing this file * if there was an issue in processing this file
*/ */
private boolean processFileResource(FileArg arg, Path file) throws IOException private boolean processFileResource(FileArg arg) throws IOException
{ {
// now on copy/download paths (be safe above all else) URI uri = arg.uri==null?null:URI.create(arg.uri);
if (!file.startsWith(baseHome.getBasePath()))
throw new IOException("For security reasons, Jetty start is unable to process maven file resource not in ${jetty.base} - " + file);
if (startArgs.isDownload() && (arg.uri != null)) if (startArgs.isCreateFiles())
{ {
// make the directories in ${jetty.base} that we need
boolean modified = FS.ensureDirectoryExists(file.getParent());
if (modified)
StartLog.log("MKDIR",baseHome.toShortForm(file.getParent()));
URI uri = URI.create(arg.uri);
// Process via initializers
for (FileInitializer finit : fileInitializers) for (FileInitializer finit : fileInitializers)
{ {
if (finit.init(uri,file,arg.location)) if (finit.isApplicable(uri))
{ return finit.create(uri,arg.location);
// Completed successfully
return true;
}
} }
if (!FS.exists(file)) throw new IOException(String.format("Unable to create %s",arg));
System.err.println("Failed to initialize: "+arg.uri+"|"+arg.location);
return modified;
} }
else
for (FileInitializer finit : fileInitializers)
{ {
// Process directly if (finit.isApplicable(uri))
boolean isDir = arg.location.endsWith("/"); if (!finit.check(uri,arg.location))
startArgs.setRun(false);
if (FS.exists(file))
{
// Validate existence
if (isDir)
{
if (!Files.isDirectory(file))
{
throw new IOException("Invalid: path should be a directory (but isn't): " + file);
}
if (!FS.canReadDirectory(file))
{
throw new IOException("Unable to read directory: " + file);
}
}
else
{
if (!FS.canReadFile(file))
{
throw new IOException("Unable to read file: " + file);
}
}
return false;
}
if (isDir)
{
// Create directory
boolean mkdir = FS.ensureDirectoryExists(file);
if (mkdir)
StartLog.log("MKDIR",baseHome.toShortForm(file));
return mkdir;
}
else
{
// Warn on missing file (this has to be resolved manually by user)
String shortRef = baseHome.toShortForm(file);
if (startArgs.isTestingModeEnabled())
{
StartLog.log("TESTING MODE","Skipping required file check on: %s",shortRef);
return false;
}
StartLog.warn("Missing Required File: %s",baseHome.toShortForm(file));
startArgs.setRun(false);
if (arg.uri != null)
{
StartLog.warn(" Can be downloaded From: %s",arg.uri);
StartLog.warn(" Run start.jar --create-files to download");
}
return false;
}
} }
return false;
} }
/** /**
* Process the {@link FileArg} for startup, assume that all licenses have * Process the {@link FileArg} for startup, assume that all licenses have
* been acknowledged at this stage. * been acknowledged at this stage.
@ -378,16 +316,15 @@ public class BaseBuilder
for (FileArg arg : files) for (FileArg arg : files)
{ {
Path file = baseHome.getBasePath(arg.location);
try try
{ {
boolean processed = processFileResource(arg,file); boolean processed = processFileResource(arg);
dirty |= processed; dirty |= processed;
} }
catch (Throwable t) catch (Throwable t)
{ {
StartLog.warn(t); StartLog.warn(t);
failures.add(String.format("[%s] %s - %s",t.getClass().getSimpleName(),t.getMessage(),file.toAbsolutePath().toString())); failures.add(String.format("[%s] %s - %s",t.getClass().getSimpleName(),t.getMessage(),arg.location));
} }
} }

View File

@ -71,6 +71,10 @@ public class FS
{ {
if (exists(dir)) if (exists(dir))
{ {
// Is it a directory?
if (!Files.isDirectory(dir))
throw new IOException("Path is not directory: " + dir.toAbsolutePath());
// exists already, nothing to do // exists already, nothing to do
return false; return false;
} }

View File

@ -46,6 +46,7 @@ public class FileArg
err.append(LN).append("Valid Syntaxes: "); err.append(LN).append("Valid Syntaxes: ");
err.append(LN).append(" <relative-path> - eg: resources/"); err.append(LN).append(" <relative-path> - eg: resources/");
err.append(LN).append(" or <absolute-path> - eg: /var/run/jetty.pid"); err.append(LN).append(" or <absolute-path> - eg: /var/run/jetty.pid");
err.append(LN).append(" or <uri> - eg: basehome:some/path");
err.append(LN).append(" or <uri>|<rel-path> - eg: http://machine/my.conf|resources/my.conf"); err.append(LN).append(" or <uri>|<rel-path> - eg: http://machine/my.conf|resources/my.conf");
err.append(LN).append(" or <uri>|<abs-path> - eg: http://machine/glob.dat|/opt/run/glob.dat"); err.append(LN).append(" or <uri>|<abs-path> - eg: http://machine/glob.dat|/opt/run/glob.dat");
err.append(LN).append("Known uri schemes: http, maven, home"); err.append(LN).append("Known uri schemes: http, maven, home");
@ -56,6 +57,11 @@ public class FileArg
this.uri = parts[0]; this.uri = parts[0];
this.location = parts[1]; this.location = parts[1];
} }
else if (uriLocation.contains(":"))
{
this.uri = uriLocation;
this.location = null;
}
else else
{ {
this.uri = null; this.uri = null;
@ -118,11 +124,7 @@ public class FileArg
public String toString() public String toString()
{ {
StringBuilder builder = new StringBuilder(); StringBuilder builder = new StringBuilder();
builder.append("DownloadArg [uri="); builder.append("DownloadArg [uri=").append(uri).append(", location=").append(location).append("]");
builder.append(uri);
builder.append(", location=");
builder.append(location);
builder.append("]");
return builder.toString(); return builder.toString();
} }
} }

View File

@ -19,28 +19,216 @@
package org.eclipse.jetty.start; package org.eclipse.jetty.start;
import java.io.IOException; import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.HttpURLConnection;
import java.net.URI; import java.net.URI;
import java.nio.file.DirectoryStream;
import java.nio.file.Files;
import java.nio.file.Path; import java.nio.file.Path;
import java.nio.file.StandardOpenOption;
import java.util.HashSet;
import java.util.Set;
import java.util.stream.Stream;
/** /**
* Interface for initializing a file resource. * Interface for initializing a file resource.
*/ */
public interface FileInitializer public abstract class FileInitializer
{ {
protected final Set<String> _scheme = new HashSet<>();
protected final BaseHome _basehome;
protected FileInitializer(BaseHome basehome, String... scheme)
{
_basehome = basehome;
if (scheme!=null)
for (String s:scheme)
_scheme.add(s.toLowerCase());
}
public boolean isApplicable(URI uri)
{
if (_scheme.isEmpty())
return uri==null;
return uri!=null && _scheme.contains(uri.getScheme().toLowerCase());
}
/** /**
* Initialize a file resource * Initialize a file resource
* *
* @param uri * @param uri
* the remote URI of the resource acting as its source * the URI of the resource acting as its source
* @param file * @param location
* the local file resource to initialize. (often in ${jetty.base} directory)
* @param fileRef
* the simple string reference to the output file, suitable for searching * the simple string reference to the output file, suitable for searching
* for the file in other locations (like ${jetty.home} or ${jetty.dir}) * for the file in other locations (like ${jetty.home} or ${jetty.dir}) *
* @return true if local file is initialized (resulted in a change on disk), false if this * @return true if local file system is modified.
* {@link FileInitializer} did nothing.
* @throws IOException * @throws IOException
* if there was an attempt to initialize, but an error occurred. * if there was an attempt to initialize, but an error occurred.
*/ */
public boolean init(URI uri, Path file, String fileRef) throws IOException;
public abstract boolean create(URI uri, String location) throws IOException;
public boolean check(URI uri, String location) throws IOException
{
if (location!=null)
{
// Process directly
boolean isDir = location.endsWith("/");
Path destination = getDestination(uri,location);
if (FS.exists(destination))
{
// Validate existence
if (isDir)
{
if (!Files.isDirectory(destination))
{
throw new IOException("Invalid: path should be a directory (but isn't): " + location);
}
if (!FS.canReadDirectory(destination))
{
throw new IOException("Unable to read directory: " + location);
}
}
else
{
if (!FS.canReadFile(destination))
{
throw new IOException("Unable to read file: " + location);
}
}
return true;
}
StartLog.error("Missing Required File: %s",_basehome.toShortForm(location));
return false;
}
return true;
}
protected Path getDestination(URI uri, String location) throws IOException
{
if (location==null)
return null;
Path destination = _basehome.getBasePath(location);
// now on copy/download paths (be safe above all else)
if (destination!=null && !destination.startsWith(_basehome.getBasePath()))
throw new IOException("For security reasons, Jetty start is unable to process file resource not in ${jetty.base} - " + location);
boolean isDestDir = Files.isDirectory(destination) || !Files.exists(destination) && location.endsWith("/");
if (isDestDir && uri!=null && uri.getSchemeSpecificPart().contains("/") && !uri.getSchemeSpecificPart().endsWith("/"))
destination = destination.resolve(uri.getSchemeSpecificPart().substring(uri.getSchemeSpecificPart().lastIndexOf('/')+1));
return destination;
}
protected void download(URI uri, Path destination) throws IOException
{
if (FS.ensureDirectoryExists(destination.getParent()))
StartLog.log("MKDIR",_basehome.toShortForm(destination.getParent()));
StartLog.log("DOWNLD","%s to %s",uri,_basehome.toShortForm(destination));
HttpURLConnection http = (HttpURLConnection)uri.toURL().openConnection();
http.setInstanceFollowRedirects(true);
http.setAllowUserInteraction(false);
int status = http.getResponseCode();
if(status != HttpURLConnection.HTTP_OK)
{
throw new IOException("URL GET Failure [" + status + "/" + http.getResponseMessage() + "] on " + uri);
}
byte[] buf = new byte[8192];
try (InputStream in = http.getInputStream(); OutputStream out = Files.newOutputStream(destination,StandardOpenOption.CREATE_NEW,StandardOpenOption.WRITE))
{
while (true)
{
int len = in.read(buf);
if (len > 0)
{
out.write(buf,0,len);
}
if (len < 0)
{
break;
}
}
}
}
/**
* Test if any of the Paths exist (as files)
*
* @param paths
* the list of paths to check
* @return true if the path exist (as a file), false if it doesn't exist
* @throws IOException
* if the path points to a non-file, or is not readable.
*/
protected boolean isFilePresent(Path... paths) throws IOException
{
for (Path file : paths)
{
if (Files.exists(file))
{
if (Files.isDirectory(file))
{
throw new IOException("Directory in the way: " + file.toAbsolutePath());
}
if (!Files.isReadable(file))
{
throw new IOException("File not readable: " + file.toAbsolutePath());
}
return true;
}
}
return false;
}
public boolean copyDirectory(Path source, Path destination) throws IOException
{
boolean modified=false;
try(DirectoryStream<Path> stream = Files.newDirectoryStream(source))
{
for (Path from : stream)
{
Path to = destination.resolve(from.getFileName());
if (Files.isDirectory(from))
{
if (FS.ensureDirectoryExists(to))
{
StartLog.log("MKDIR",_basehome.toShortForm(to));
modified = true;
}
if (copyDirectory(from,to))
modified = true;
}
else if (!Files.exists(to))
{
StartLog.log("COPY ","%s to %s",_basehome.toShortForm(from),_basehome.toShortForm(to));
Files.copy(from,to);
modified = true;
}
}
}
return modified;
}
} }

View File

@ -404,7 +404,7 @@ public class Main
BaseBuilder baseBuilder = new BaseBuilder(baseHome,args); BaseBuilder baseBuilder = new BaseBuilder(baseHome,args);
if(baseBuilder.build()) if(baseBuilder.build())
StartLog.info("Base directory was modified"); StartLog.info("Base directory was modified");
else if (args.isDownload() || !args.getStartModules().isEmpty()) else if (args.isCreateFiles() || !args.getStartModules().isEmpty())
StartLog.info("Base directory was not modified"); StartLog.info("Base directory was not modified");
// Check module dependencies // Check module dependencies

View File

@ -474,9 +474,9 @@ public class Module implements Comparable<Module>
} }
/** /**
* @param source * @param source String describing where the module was enabled from
* @param transitive * @param transitive True if the enable is transitive
* @return True if the module was not previously enabled * @return true if the module was not previously enabled
*/ */
public boolean enable(String source,boolean transitive) public boolean enable(String source,boolean transitive)
{ {

View File

@ -163,8 +163,8 @@ public class StartArgs
/** Should the server be run? */ /** Should the server be run? */
private boolean run = true; private boolean run = true;
/** Download related args */ /** Files related args */
private boolean download = false; private boolean createFiles = false;
private boolean licenseCheckRequired = false; private boolean licenseCheckRequired = false;
private boolean testingMode = false; private boolean testingMode = false;
@ -620,24 +620,33 @@ public class StartArgs
return System.getProperty("main.class",mainclass); return System.getProperty("main.class",mainclass);
} }
public Path getMavenLocalRepoDir() public String getMavenLocalRepoDir()
{ {
// Try property first
String localRepo = getProperties().getString("maven.local.repo"); String localRepo = getProperties().getString("maven.local.repo");
if (Utils.isBlank(localRepo)) if (Utils.isBlank(localRepo))
{
// Try jetty specific env variable
localRepo = System.getenv("JETTY_MAVEN_LOCAL_REPO"); localRepo = System.getenv("JETTY_MAVEN_LOCAL_REPO");
}
if (Utils.isBlank(localRepo))
localRepo = System.getenv("MAVEN_LOCAL_REPO");
return localRepo;
}
public Path findMavenLocalRepoDir()
{
// Try property first
String localRepo = getMavenLocalRepoDir();
if (Utils.isBlank(localRepo)) if (Utils.isBlank(localRepo))
{ {
// Try generic env variable // Try generic env variable
localRepo = System.getenv("MAVEN_LOCAL_REPO"); String home = System.getenv("HOME");
Path home_m2_repository = new File(new File(home,".m2"),"repository").toPath();
if (Files.exists(home_m2_repository))
localRepo = home_m2_repository.toString();
} }
// TODO: load & use $HOME/.m2/settings.xml ?
// TODO: possibly use Eclipse Aether to manage it ? // TODO: possibly use Eclipse Aether to manage it ?
// TODO: see https://bugs.eclipse.org/bugs/show_bug.cgi?id=449511 // TODO: see https://bugs.eclipse.org/bugs/show_bug.cgi?id=449511
@ -710,9 +719,9 @@ public class StartArgs
return approveAllLicenses; return approveAllLicenses;
} }
public boolean isDownload() public boolean isCreateFiles()
{ {
return download; return createFiles;
} }
public boolean isDryRun() public boolean isDryRun()
@ -859,14 +868,14 @@ public class StartArgs
{ {
addFile(null,Props.getValue(arg)); addFile(null,Props.getValue(arg));
run = false; run = false;
download = true; createFiles = true;
return; return;
} }
if (arg.equals("--create-files")) if (arg.equals("--create-files"))
{ {
run = false; run = false;
download = true; createFiles = true;
licenseCheckRequired = true; licenseCheckRequired = true;
return; return;
} }
@ -959,7 +968,7 @@ public class StartArgs
{ {
createStartd=true; createStartd=true;
run = false; run = false;
download = true; createFiles = true;
licenseCheckRequired = true; licenseCheckRequired = true;
return; return;
} }
@ -970,7 +979,7 @@ public class StartArgs
createStartd=true; createStartd=true;
startModules.addAll(Props.getValues(arg)); startModules.addAll(Props.getValues(arg));
run = false; run = false;
download = true; createFiles = true;
licenseCheckRequired = true; licenseCheckRequired = true;
return; return;
} }
@ -978,7 +987,7 @@ public class StartArgs
{ {
startModules.addAll(Props.getValues(arg)); startModules.addAll(Props.getValues(arg));
run = false; run = false;
download = true; createFiles = true;
licenseCheckRequired = true; licenseCheckRequired = true;
return; return;
} }

View File

@ -33,33 +33,66 @@ import org.eclipse.jetty.start.StartLog;
* "basehome:some/path" * "basehome:some/path"
* {@link FileInitializer} * {@link FileInitializer}
*/ */
public class BaseHomeFileInitializer implements FileInitializer public class BaseHomeFileInitializer extends FileInitializer
{ {
private final BaseHome _basehome;
public BaseHomeFileInitializer(BaseHome basehome) public BaseHomeFileInitializer(BaseHome basehome)
{ {
_basehome=basehome; super(basehome,"basehome");
} }
@Override @Override
public boolean init(URI uri, Path file, String fileRef) throws IOException public boolean create(URI uri, String location) throws IOException
{ {
if (!"basehome".equalsIgnoreCase(uri.getScheme()) || uri.getSchemeSpecificPart().startsWith("/")) if (uri.getSchemeSpecificPart().startsWith("/"))
return false; throw new IllegalArgumentException(String.format("Bad file arg: %s",uri));
Path source = _basehome.getPath(uri.getSchemeSpecificPart()); Path source = _basehome.getPath(uri.getSchemeSpecificPart());
if (FS.exists(source) && !FS.exists(file)) if (!FS.exists(source))
{ throw new IllegalArgumentException(String.format("File does not exist: %s",uri));
if (FS.ensureDirectoryExists(file.getParent()))
StartLog.log("MKDIR",_basehome.toShortForm(file.getParent()));
StartLog.log("COPY ","%s to %s",_basehome.toShortForm(source),_basehome.toShortForm(file)); Path destination = location==null?_basehome.getBasePath():getDestination(uri,location);
Files.copy(source,file);
return true; boolean modified=false;
if (Files.isDirectory(source))
{
// Check destination
if (destination!=null && Files.exists(destination))
{
if (!Files.isDirectory(destination))
{
StartLog.error("Cannot copy directory %s to file %s",source,destination);
return false;
}
}
else if (FS.ensureDirectoryExists(destination))
{
modified = true;
StartLog.log("MKDIR",_basehome.toShortForm(destination));
}
copyDirectory(source,destination);
}
else
{
if (FS.ensureDirectoryExists(destination.getParent()))
{
modified = true;
StartLog.log("MKDIR",_basehome.toShortForm(destination.getParent()));
}
if (!FS.exists(destination))
{
StartLog.log("COPY ","%s to %s",_basehome.toShortForm(source),_basehome.toShortForm(destination));
Files.copy(source,destination);
modified = true;
}
} }
return false; return modified;
} }
} }

View File

@ -0,0 +1,87 @@
//
// ========================================================================
// Copyright (c) 1995-2016 Mort Bay Consulting Pty. Ltd.
// ------------------------------------------------------------------------
// All rights reserved. This program and the accompanying materials
// are made available under the terms of the Eclipse Public License v1.0
// and Apache License v2.0 which accompanies this distribution.
//
// The Eclipse Public License is available at
// http://www.eclipse.org/legal/epl-v10.html
//
// The Apache License v2.0 is available at
// http://www.opensource.org/licenses/apache2.0.php
//
// You may elect to redistribute this code under either of these licenses.
// ========================================================================
//
package org.eclipse.jetty.start.fileinits;
import java.io.IOException;
import java.net.URI;
import java.nio.file.Files;
import java.nio.file.Path;
import org.eclipse.jetty.start.BaseHome;
import org.eclipse.jetty.start.FS;
import org.eclipse.jetty.start.FileInitializer;
import org.eclipse.jetty.start.StartLog;
public class LocalFileInitializer extends FileInitializer
{
public LocalFileInitializer(BaseHome basehome)
{
super(basehome);
}
@Override
public boolean create(URI uri, String location) throws IOException
{
Path destination = getDestination(uri,location);
if (destination == null)
{
StartLog.error("Bad file arg %s",uri);
return false;
}
boolean isDir = location.endsWith("/");
if (FS.exists(destination))
{
// Validate existence
if (isDir)
{
if (!Files.isDirectory(destination))
{
throw new IOException("Invalid: path should be a directory (but isn't): " + location);
}
if (!FS.canReadDirectory(destination))
{
throw new IOException("Unable to read directory: " + location);
}
}
else
{
if (!FS.canReadFile(destination))
{
throw new IOException("Unable to read file: " + location);
}
}
return false;
}
if (isDir)
{
// Create directory
boolean mkdir = FS.ensureDirectoryExists(destination);
if (mkdir)
StartLog.log("MKDIR",_basehome.toShortForm(destination));
return mkdir;
}
throw new IOException("Unable to create "+_basehome.toShortForm(destination));
}
}

View File

@ -25,6 +25,7 @@ import java.nio.file.Path;
import org.eclipse.jetty.start.BaseHome; import org.eclipse.jetty.start.BaseHome;
import org.eclipse.jetty.start.FS; import org.eclipse.jetty.start.FS;
import org.eclipse.jetty.start.FileInitializer;
import org.eclipse.jetty.start.StartLog; import org.eclipse.jetty.start.StartLog;
import org.eclipse.jetty.start.Utils; import org.eclipse.jetty.start.Utils;
@ -46,7 +47,7 @@ import org.eclipse.jetty.start.Utils;
* <dd>optional type and classifier requirement</dd> * <dd>optional type and classifier requirement</dd>
* </dl> * </dl>
*/ */
public class MavenLocalRepoFileInitializer extends UriFileInitializer public class MavenLocalRepoFileInitializer extends FileInitializer
{ {
public static class Coordinates public static class Coordinates
{ {
@ -79,20 +80,22 @@ public class MavenLocalRepoFileInitializer extends UriFileInitializer
} }
private Path localRepositoryDir; private Path localRepositoryDir;
private final boolean readonly;
public MavenLocalRepoFileInitializer(BaseHome baseHome) public MavenLocalRepoFileInitializer(BaseHome baseHome)
{ {
this(baseHome,null); this(baseHome,null,true);
} }
public MavenLocalRepoFileInitializer(BaseHome baseHome, Path localRepoDir) public MavenLocalRepoFileInitializer(BaseHome baseHome, Path localRepoDir, boolean readonly)
{ {
super(baseHome); super(baseHome,"maven");
this.localRepositoryDir = localRepoDir; this.localRepositoryDir = localRepoDir;
this.readonly = readonly;
} }
@Override @Override
public boolean init(URI uri, Path file, String fileRef) throws IOException public boolean create(URI uri, String location) throws IOException
{ {
Coordinates coords = getCoordinates(uri); Coordinates coords = getCoordinates(uri);
if (coords == null) if (coords == null)
@ -101,11 +104,11 @@ public class MavenLocalRepoFileInitializer extends UriFileInitializer
return false; return false;
} }
if (isFilePresent(file, baseHome.getPath(fileRef))) Path destination = getDestination(uri,location);
{
// All done if (isFilePresent(destination))
return false; return false;
}
// If using local repository // If using local repository
if (this.localRepositoryDir != null) if (this.localRepositoryDir != null)
@ -113,14 +116,19 @@ public class MavenLocalRepoFileInitializer extends UriFileInitializer
// Grab copy from local repository (download if needed to local // Grab copy from local repository (download if needed to local
// repository) // repository)
Path localRepoFile = getLocalRepoFile(coords); Path localRepoFile = getLocalRepoFile(coords);
StartLog.log("COPY ","%s to %s",localRepoFile,baseHome.toShortForm(file));
Files.copy(localRepoFile,file); if (localRepoFile!=null)
} {
else if (FS.ensureDirectoryExists(destination.getParent()))
{ StartLog.log("MKDIR",_basehome.toShortForm(destination.getParent()));
// normal non-local repo version StartLog.log("COPY ","%s to %s",localRepoFile,_basehome.toShortForm(destination));
download(coords.toCentralURI(),file); Files.copy(localRepoFile,destination);
return true;
}
} }
// normal non-local repo version
download(coords.toCentralURI(),destination);
return true; return true;
} }
@ -128,13 +136,16 @@ public class MavenLocalRepoFileInitializer extends UriFileInitializer
{ {
Path localFile = localRepositoryDir.resolve(coords.toPath()); Path localFile = localRepositoryDir.resolve(coords.toPath());
if (FS.canReadFile(localFile)) if (FS.canReadFile(localFile))
return localFile;
// Download, if needed
if (!readonly)
{ {
download(coords.toCentralURI(),localFile);
return localFile; return localFile;
} }
// Download, if needed return null;
download(coords.toCentralURI(),localFile);
return localFile;
} }
public Coordinates getCoordinates(URI uri) public Coordinates getCoordinates(URI uri)

View File

@ -22,6 +22,7 @@ import java.io.IOException;
import java.net.URI; import java.net.URI;
import java.nio.file.Path; import java.nio.file.Path;
import org.eclipse.jetty.start.BaseHome;
import org.eclipse.jetty.start.FS; import org.eclipse.jetty.start.FS;
import org.eclipse.jetty.start.FileInitializer; import org.eclipse.jetty.start.FileInitializer;
import org.eclipse.jetty.start.StartLog; import org.eclipse.jetty.start.StartLog;
@ -31,14 +32,33 @@ import org.eclipse.jetty.start.StartLog;
* or initialize a file, this implementation is merely a no-op for the * or initialize a file, this implementation is merely a no-op for the
* {@link FileInitializer} * {@link FileInitializer}
*/ */
public class TestFileInitializer implements FileInitializer public class TestFileInitializer extends FileInitializer
{ {
@Override public TestFileInitializer(BaseHome basehome)
public boolean init(URI uri, Path file, String fileRef) throws IOException
{ {
FS.ensureDirectoryExists(file.getParent()); super(basehome);
}
StartLog.log("TESTING MODE","Skipping download of " + uri); @Override
public boolean isApplicable(URI uri)
{
return true; return true;
} }
@Override
public boolean create(URI uri, String location) throws IOException
{
Path destination = getDestination(uri,location);
if (destination!=null)
{
if (location.endsWith("/"))
FS.ensureDirectoryExists(destination);
else
FS.ensureDirectoryExists(destination.getParent());
}
StartLog.log("TESTING MODE","Skipping download of " + uri);
return Boolean.TRUE;
}
} }

View File

@ -32,119 +32,26 @@ import org.eclipse.jetty.start.FS;
import org.eclipse.jetty.start.FileInitializer; import org.eclipse.jetty.start.FileInitializer;
import org.eclipse.jetty.start.StartLog; import org.eclipse.jetty.start.StartLog;
public class UriFileInitializer implements FileInitializer public class UriFileInitializer extends FileInitializer
{ {
private final static String[] SUPPORTED_SCHEMES = { "http", "https" };
protected final BaseHome baseHome;
public UriFileInitializer(BaseHome baseHome) public UriFileInitializer(BaseHome baseHome)
{ {
this.baseHome = baseHome; super(baseHome,"http", "https");
} }
@Override @Override
public boolean init(URI uri, Path file, String fileRef) throws IOException public boolean create(URI uri, String location) throws IOException
{ {
if (!isSupportedScheme(uri)) Path destination = getDestination(uri,location);
{
// Not a supported scheme.
return false;
}
if(isFilePresent(file, baseHome.getPath(fileRef))) if (Files.isDirectory(destination))
{ destination = destination.resolve(uri.getSchemeSpecificPart().substring(uri.getRawSchemeSpecificPart().lastIndexOf('/')+1));
// All done
return false;
}
download(uri,file); if(isFilePresent(destination))
return false;
download(uri,destination);
return true; return true;
} }
protected void download(URI uri, Path file) throws IOException
{
StartLog.log("DOWNLOAD","%s to %s",uri,baseHome.toShortForm(file));
if (FS.ensureDirectoryExists(file.getParent()))
StartLog.log("MKDIR",baseHome.toShortForm(file.getParent()));
HttpURLConnection http = (HttpURLConnection)uri.toURL().openConnection();
http.setInstanceFollowRedirects(true);
http.setAllowUserInteraction(false);
int status = http.getResponseCode();
if(status != HttpURLConnection.HTTP_OK)
{
throw new IOException("URL GET Failure [" + status + "/" + http.getResponseMessage() + "] on " + uri);
}
byte[] buf = new byte[8192];
try (InputStream in = http.getInputStream(); OutputStream out = Files.newOutputStream(file,StandardOpenOption.CREATE_NEW,StandardOpenOption.WRITE))
{
while (true)
{
int len = in.read(buf);
if (len > 0)
{
out.write(buf,0,len);
}
if (len < 0)
{
break;
}
}
}
}
/**
* Test if any of the Paths exist (as files)
*
* @param paths
* the list of paths to check
* @return true if the path exist (as a file), false if it doesn't exist
* @throws IOException
* if the path points to a non-file, or is not readable.
*/
protected boolean isFilePresent(Path... paths) throws IOException
{
for (Path file : paths)
{
if (Files.exists(file))
{
if (Files.isDirectory(file))
{
throw new IOException("Directory in the way: " + file.toAbsolutePath());
}
if (!Files.isReadable(file))
{
throw new IOException("File not readable: " + file.toAbsolutePath());
}
return true;
}
}
return false;
}
private boolean isSupportedScheme(URI uri)
{
String scheme = uri.getScheme();
if (scheme == null)
{
return false;
}
for (String supported : SUPPORTED_SCHEMES)
{
if (supported.equalsIgnoreCase(scheme))
{
return true;
}
}
return false;
}
} }

View File

@ -0,0 +1,15 @@
DOWNLOAD|basehome:modules/withfiles/test.txt|one/renamed.txt
DOWNLOAD|basehome:modules/withfiles/test.txt|two/
DOWNLOAD|basehome:modules/withfiles/test.txt|three
DOWNLOAD|basehome:modules/withfiles|null
DOWNLOAD|basehome:modules/withfiles/four/|five/
DOWNLOAD|basehome:modules/withfiles/four/sub|six
EXISTS|test.txt
EXISTS|one/renamed.txt
EXISTS|two/test.txt
EXISTS|three/test.txt
EXISTS|four/sub/dir/test.txt
EXISTS|five/sub/dir/test.txt
EXISTS|six/sub/dir/test.txt

View File

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

View File

@ -0,0 +1,12 @@
[files]
basehome:modules/withfiles/test.txt|one/renamed.txt
basehome:modules/withfiles/test.txt|two/
three/
basehome:modules/withfiles/test.txt|three
basehome:modules/withfiles
basehome:modules/withfiles/four/|five/
six/
basehome:modules/withfiles/four/sub|six

View File

@ -1 +0,0 @@
org.apache.commons.logging.Log=org.apache.commons.logging.impl.SimpleLog

View File

@ -14,8 +14,7 @@ jul-api
jul-impl jul-impl
[files] [files]
basehome:modules/jul-impl/java-util-logging.properties|etc/java-util-logging.properties basehome:modules/jul-impl
logs/
[exec] [exec]
-Djava.util.logging.config.file=etc/java-util-logging.properties -Djava.util.logging.config.file=etc/java-util-logging.properties

View File

@ -11,12 +11,13 @@ slf4j-api
slf4j-impl slf4j-impl
[provides] [provides]
jul-api
jul-impl jul-impl
slf4j+jul slf4j+jul
[files] [files]
maven://org.slf4j/jul-to-slf4j/${slf4j.version}|lib/slf4j/jul-to-slf4j-${slf4j.version}.jar maven://org.slf4j/jul-to-slf4j/${slf4j.version}|lib/slf4j/jul-to-slf4j-${slf4j.version}.jar
basehome:modules/jul-slf4j/java-util-logging.properties|etc/java-util-logging.properties basehome:modules/jul-slf4j
[lib] [lib]
lib/slf4j/jul-to-slf4j-${slf4j.version}.jar lib/slf4j/jul-to-slf4j-${slf4j.version}.jar

View File

@ -15,9 +15,8 @@ log4j-api
log4j-impl log4j-impl
[files] [files]
basehome:modules/log4j/log4j.xml|resources/log4j.xml
maven://log4j/log4j/${log4j.version}|lib/log4j/log4j-${log4j.version}.jar maven://log4j/log4j/${log4j.version}|lib/log4j/log4j-${log4j.version}.jar
logs/ basehome:modules/log4j-impl
[lib] [lib]
lib/log4j/log4j-${log4j.version}.jar lib/log4j/log4j-${log4j.version}.jar

View File

@ -17,8 +17,7 @@ log4j2-impl
[files] [files]
maven://org.apache.logging.log4j/log4j-core/${log4j2.version}|lib/log4j2/log4j-core-${log4j2.version}.jar maven://org.apache.logging.log4j/log4j-core/${log4j2.version}|lib/log4j2/log4j-core-${log4j2.version}.jar
basehome:modules/log4j2/log4j2.xml|resources/log4j2.xml basehome:modules/log4j2-impl
logs/
[lib] [lib]
lib/log4j2/*.jar lib/log4j2/*.jar

View File

@ -11,7 +11,9 @@
<Appenders> <Appenders>
<Console name="console" target="SYSTEM_ERR"> <Console name="console" target="SYSTEM_ERR">
<PatternLayout pattern="%m%n"/> <PatternLayout>
<Pattern>%d{yyyy-MM-dd HH:mm:ss} %-5p %c{1}:%L - %m%n</Pattern>
</PatternLayout>
</Console> </Console>
<!-- <!--

View File

@ -11,8 +11,7 @@ resources
[files] [files]
maven://ch.qos.logback/logback-core/${logback.version}|lib/logback/logback-core-${logback.version}.jar maven://ch.qos.logback/logback-core/${logback.version}|lib/logback/logback-core-${logback.version}.jar
basehome:modules/logback/logback.xml|resources/logback.xml basehome:modules/logback-impl
logs/
[lib] [lib]
lib/logback/logback-core-${logback.version}.jar lib/logback/logback-core-${logback.version}.jar

View File

@ -12,4 +12,4 @@ resources
logging logging
[files] [files]
basehome:modules/logging-jetty/jetty-logging.properties|resources/jetty-logging.properties basehome:modules/logging-jetty

View File

@ -16,7 +16,6 @@ slf4j-impl
[files] [files]
maven://ch.qos.logback/logback-classic/${logback.version}|lib/logback/logback-classic-${logback.version}.jar maven://ch.qos.logback/logback-classic/${logback.version}|lib/logback/logback-classic-${logback.version}.jar
basehome:modules/logback/logback.xml|resources/logback.xml
[lib] [lib]
lib/logback/logback-classic-${logback.version}.jar lib/logback/logback-classic-${logback.version}.jar

View File

@ -16,8 +16,7 @@ slf4j-impl
[files] [files]
maven://org.slf4j/slf4j-simple/${slf4j.version}|lib/slf4j/slf4j-simple-${slf4j.version}.jar maven://org.slf4j/slf4j-simple/${slf4j.version}|lib/slf4j/slf4j-simple-${slf4j.version}.jar
basehome:modules/slf4j/simplelogger.properties|resources/simplelogger.properties basehome:modules/slf4j-impl
logs/
[lib] [lib]
lib/slf4j/slf4j-simple-${slf4j.version}.jar lib/slf4j/slf4j-simple-${slf4j.version}.jar