diff --git a/jetty-documentation/src/main/asciidoc/development/maven/jetty-maven-plugin.adoc b/jetty-documentation/src/main/asciidoc/development/maven/jetty-maven-plugin.adoc index 24b7bba4ee1..ac5514b2b4f 100644 --- a/jetty-documentation/src/main/asciidoc/development/maven/jetty-maven-plugin.adoc +++ b/jetty-documentation/src/main/asciidoc/development/maven/jetty-maven-plugin.adoc @@ -597,6 +597,9 @@ The available configuration parameters - in addition to those for the `jetty:run jvmArgs:: Optional. A string representing arbitrary arguments to pass to the forked JVM. +env:: +Optional. +Map of key/value pairs to pass as environment to the forked JVM. waitForChild:: Default is `true`. This causes the parent process to wait for the forked process to exit. diff --git a/jetty-security/src/main/java/org/eclipse/jetty/security/AbstractLoginService.java b/jetty-security/src/main/java/org/eclipse/jetty/security/AbstractLoginService.java index fd652bb479a..fb15581c9c6 100644 --- a/jetty-security/src/main/java/org/eclipse/jetty/security/AbstractLoginService.java +++ b/jetty-security/src/main/java/org/eclipse/jetty/security/AbstractLoginService.java @@ -25,7 +25,6 @@ import java.security.Principal; import javax.security.auth.Subject; import javax.servlet.ServletRequest; - import org.eclipse.jetty.server.UserIdentity; import org.eclipse.jetty.util.component.AbstractLifeCycle; import org.eclipse.jetty.util.log.Log; @@ -203,7 +202,6 @@ public abstract class AbstractLoginService extends AbstractLifeCycle implements if (user.getUserPrincipal() instanceof UserPrincipal) { - System.err.println("VALIDATING user "+fresh.getName()); return fresh.authenticate(((UserPrincipal)user.getUserPrincipal())._credential); } diff --git a/jetty-security/src/main/java/org/eclipse/jetty/security/PropertyUserStore.java b/jetty-security/src/main/java/org/eclipse/jetty/security/PropertyUserStore.java index 0c418ea65a6..ba795608f44 100644 --- a/jetty-security/src/main/java/org/eclipse/jetty/security/PropertyUserStore.java +++ b/jetty-security/src/main/java/org/eclipse/jetty/security/PropertyUserStore.java @@ -18,17 +18,8 @@ package org.eclipse.jetty.security; -import org.eclipse.jetty.util.PathWatcher; -import org.eclipse.jetty.util.PathWatcher.PathWatchEvent; -import org.eclipse.jetty.util.StringUtil; -import org.eclipse.jetty.util.log.Log; -import org.eclipse.jetty.util.log.Logger; -import org.eclipse.jetty.util.resource.JarResource; -import org.eclipse.jetty.util.resource.PathResource; -import org.eclipse.jetty.util.resource.Resource; -import org.eclipse.jetty.util.security.Credential; - import java.io.File; +import java.io.FileOutputStream; import java.io.IOException; import java.nio.file.Files; import java.nio.file.Path; @@ -41,6 +32,17 @@ import java.util.Map; import java.util.Properties; import java.util.Set; +import org.eclipse.jetty.util.IO; +import org.eclipse.jetty.util.PathWatcher; +import org.eclipse.jetty.util.PathWatcher.PathWatchEvent; +import org.eclipse.jetty.util.StringUtil; +import org.eclipse.jetty.util.log.Log; +import org.eclipse.jetty.util.log.Logger; +import org.eclipse.jetty.util.resource.JarFileResource; +import org.eclipse.jetty.util.resource.PathResource; +import org.eclipse.jetty.util.resource.Resource; +import org.eclipse.jetty.util.security.Credential; + /** * PropertyUserStore *

@@ -59,13 +61,10 @@ public class PropertyUserStore extends UserStore implements PathWatcher.Listener { private static final Logger LOG = Log.getLogger(PropertyUserStore.class); - private static final String JAR_FILE = "jar:file:"; - protected Path _configPath; - protected Resource _configResource; - protected PathWatcher pathWatcher; - protected boolean hotReload = false; // default is not to reload + protected PathWatcher _pathWatcher; + protected boolean _hotReload = false; // default is not to reload protected boolean _firstLoad = true; // true if first load, false from that point on protected List _listeners; @@ -73,9 +72,7 @@ public class PropertyUserStore extends UserStore implements PathWatcher.Listener /** * Get the config (as a string) * @return the config path as a string - * @deprecated use {@link #getConfigPath()} instead */ - @Deprecated public String getConfig() { if (_configPath != null) @@ -89,16 +86,28 @@ public class PropertyUserStore extends UserStore implements PathWatcher.Listener */ public void setConfig(String config) { + if (config == null) + { + _configPath = null; + return; + } + try { Resource configResource = Resource.newResource(config); - if (configResource.getFile() != null) - setConfigPath(configResource.getFile()); + + if (configResource instanceof JarFileResource) + _configPath = extractPackedFile((JarFileResource)configResource); + else if (configResource instanceof PathResource) + _configPath = ((PathResource)configResource).getPath(); + else if (configResource.getFile() != null) + setConfigFile(configResource.getFile()); else - throw new IllegalArgumentException(config+" is not a file"); + throw new IllegalArgumentException(config); } catch (Exception e) { + _configPath = null; throw new IllegalStateException(e); } @@ -117,44 +126,33 @@ public class PropertyUserStore extends UserStore implements PathWatcher.Listener * Set the Config Path from a String reference to a file * @param configFile the config file can a be a file path or a reference to a file within a jar file jar:file: */ + @Deprecated public void setConfigPath(String configFile) { - if (configFile == null) - { - _configPath = null; - } - else if (new File( configFile ).exists()) - { - _configPath = new File(configFile).toPath(); - } - if ( !new File( configFile ).exists() && configFile.startsWith( JAR_FILE )) - { - // format of the url is jar:file:/foo/bar/beer.jar!/mountain_goat/pale_ale.txt - // ideally we'd like to extract this to Resource class? - try - { - _configPath = extractPackedFile( configFile ); - } - catch ( IOException e ) - { - throw new RuntimeException( "cannot extract file from url:" + configFile, e ); - } - } + setConfig(configFile); } - private Path extractPackedFile( String configFile ) + private Path extractPackedFile( JarFileResource configResource ) throws IOException { - int fileIndex = configFile.indexOf( "!" ); - String entryPath = configFile.substring( fileIndex + 1, configFile.length() ); + String uri = configResource.getURI().toASCIIString(); + int colon = uri.lastIndexOf(":"); + int bang_slash = uri.indexOf("!/"); + if (colon<0 || bang_slash<0 || colon>bang_slash) + throw new IllegalArgumentException("Not resolved JarFile resource: "+uri); + String entry_path = uri.substring(colon+2).replace("!/","__").replace('/','_').replace('.','_'); Path tmpDirectory = Files.createTempDirectory( "users_store" ); - Path extractedPath = Paths.get(tmpDirectory.toString(), entryPath); - // delete if exists as copyTo do not overwrite + tmpDirectory.toFile().deleteOnExit(); + Path extractedPath = Paths.get(tmpDirectory.toString(), entry_path); Files.deleteIfExists( extractedPath ); - // delete on shutdown extractedPath.toFile().deleteOnExit(); - JarResource.newResource( configFile ).copyTo( tmpDirectory.toFile() ); + IO.copy(configResource.getInputStream(),new FileOutputStream(extractedPath.toFile())); + if (isHotReload()) + { + LOG.warn("Cannot hot reload from packed configuration: {}",configResource); + setHotReload(false); + } return extractedPath; } @@ -162,7 +160,17 @@ public class PropertyUserStore extends UserStore implements PathWatcher.Listener * Set the Config Path from a {@link File} reference * @param configFile the config file */ + @Deprecated public void setConfigPath(File configFile) + { + setConfigFile(configFile); + } + + /** + * Set the Config Path from a {@link File} reference + * @param configFile the config file + */ + public void setConfigFile(File configFile) { if(configFile == null) { @@ -182,19 +190,15 @@ public class PropertyUserStore extends UserStore implements PathWatcher.Listener _configPath = configPath; } - /* ------------------------------------------------------------ */ /** * @return the resource associated with the configured properties file, creating it if necessary * @throws IOException if unable to get the resource */ public Resource getConfigResource() throws IOException { - if (_configResource == null) - { - _configResource = new PathResource(_configPath); - } - - return _configResource; + if (_configPath==null) + return null; + return new PathResource(_configPath); } /** @@ -204,7 +208,7 @@ public class PropertyUserStore extends UserStore implements PathWatcher.Listener */ public boolean isHotReload() { - return hotReload; + return _hotReload; } /** @@ -218,7 +222,7 @@ public class PropertyUserStore extends UserStore implements PathWatcher.Listener { throw new IllegalStateException("Cannot set hot reload while user store is running"); } - this.hotReload = enable; + this._hotReload = enable; } @@ -247,8 +251,9 @@ public class PropertyUserStore extends UserStore implements PathWatcher.Listener } Properties properties = new Properties(); - if (getConfigResource().exists()) - properties.load(getConfigResource().getInputStream()); + Resource config = getConfigResource(); + if (config!=null && config.exists()) + properties.load(config.getInputStream()); Set known = new HashSet<>(); @@ -297,7 +302,6 @@ public class PropertyUserStore extends UserStore implements PathWatcher.Listener } } - /* * set initial load to false as there should be no more initial loads */ @@ -324,11 +328,11 @@ public class PropertyUserStore extends UserStore implements PathWatcher.Listener loadUsers(); if ( isHotReload() && (_configPath != null) ) { - this.pathWatcher = new PathWatcher(); - this.pathWatcher.watch(_configPath); - this.pathWatcher.addListener(this); - this.pathWatcher.setNotifyExistingOnStart(false); - this.pathWatcher.start(); + this._pathWatcher = new PathWatcher(); + this._pathWatcher.watch(_configPath); + this._pathWatcher.addListener(this); + this._pathWatcher.setNotifyExistingOnStart(false); + this._pathWatcher.start(); } } @@ -357,9 +361,9 @@ public class PropertyUserStore extends UserStore implements PathWatcher.Listener protected void doStop() throws Exception { super.doStop(); - if (this.pathWatcher != null) - this.pathWatcher.stop(); - this.pathWatcher = null; + if (this._pathWatcher != null) + this._pathWatcher.stop(); + this._pathWatcher = null; } /** diff --git a/jetty-security/src/test/java/org/eclipse/jetty/security/PropertyUserStoreTest.java b/jetty-security/src/test/java/org/eclipse/jetty/security/PropertyUserStoreTest.java index 2f24ebb6d56..84e8c764b75 100644 --- a/jetty-security/src/test/java/org/eclipse/jetty/security/PropertyUserStoreTest.java +++ b/jetty-security/src/test/java/org/eclipse/jetty/security/PropertyUserStoreTest.java @@ -169,7 +169,7 @@ public class PropertyUserStoreTest final File usersFile = initUsersText(); PropertyUserStore store = new PropertyUserStore(); - store.setConfigPath(usersFile); + store.setConfigFile(usersFile); store.registerUserListener(userCount); @@ -189,7 +189,7 @@ public class PropertyUserStoreTest final String usersFile = initUsersPackedFileText(); PropertyUserStore store = new PropertyUserStore(); - store.setConfigPath(usersFile); + store.setConfig(usersFile); store.registerUserListener(userCount); @@ -215,7 +215,7 @@ public class PropertyUserStoreTest PropertyUserStore store = new PropertyUserStore(); store.setHotReload(true); - store.setConfigPath(usersFile); + store.setConfigFile(usersFile); store.registerUserListener(userCount); @@ -246,7 +246,7 @@ public class PropertyUserStoreTest PropertyUserStore store = new PropertyUserStore(); store.setHotReload(true); - store.setConfigPath(usersFile); + store.setConfigFile(usersFile); store.registerUserListener(userCount); diff --git a/jetty-util/src/main/java/org/eclipse/jetty/util/resource/JarFileResource.java b/jetty-util/src/main/java/org/eclipse/jetty/util/resource/JarFileResource.java index dc95ab451fc..c57cb35476d 100644 --- a/jetty-util/src/main/java/org/eclipse/jetty/util/resource/JarFileResource.java +++ b/jetty-util/src/main/java/org/eclipse/jetty/util/resource/JarFileResource.java @@ -34,7 +34,7 @@ import org.eclipse.jetty.util.log.Log; import org.eclipse.jetty.util.log.Logger; /* ------------------------------------------------------------ */ -class JarFileResource extends JarResource +public class JarFileResource extends JarResource { private static final Logger LOG = Log.getLogger(JarFileResource.class); private JarFile _jarFile; diff --git a/jetty-websocket/javax-websocket-client-impl/src/main/java/org/eclipse/jetty/websocket/jsr356/JettyClientContainerProvider.java b/jetty-websocket/javax-websocket-client-impl/src/main/java/org/eclipse/jetty/websocket/jsr356/JettyClientContainerProvider.java index 481450f25a4..dff12b4b11f 100644 --- a/jetty-websocket/javax-websocket-client-impl/src/main/java/org/eclipse/jetty/websocket/jsr356/JettyClientContainerProvider.java +++ b/jetty-websocket/javax-websocket-client-impl/src/main/java/org/eclipse/jetty/websocket/jsr356/JettyClientContainerProvider.java @@ -19,18 +19,14 @@ package org.eclipse.jetty.websocket.jsr356; import java.lang.reflect.Method; -import java.util.concurrent.Executor; import javax.websocket.ContainerProvider; import javax.websocket.WebSocketContainer; -import org.eclipse.jetty.io.ByteBufferPool; -import org.eclipse.jetty.io.MappedByteBufferPool; import org.eclipse.jetty.util.component.ContainerLifeCycle; import org.eclipse.jetty.util.component.LifeCycle; import org.eclipse.jetty.util.log.Log; import org.eclipse.jetty.util.log.Logger; -import org.eclipse.jetty.util.thread.QueuedThreadPool; import org.eclipse.jetty.util.thread.ShutdownThread; import org.eclipse.jetty.websocket.api.WebSocketPolicy; import org.eclipse.jetty.websocket.common.scopes.SimpleContainerScope; @@ -48,10 +44,8 @@ public class JettyClientContainerProvider extends ContainerProvider private static final Logger LOG = Log.getLogger(JettyClientContainerProvider.class); private static boolean useSingleton = false; - private static WebSocketContainer INSTANCE; private static boolean useServerContainer = false; - private static Executor commonExecutor; - private static ByteBufferPool commonBufferPool; + private static WebSocketContainer INSTANCE; private static Object lock = new Object(); @@ -83,7 +77,7 @@ public class JettyClientContainerProvider extends ContainerProvider /** * Add ability of calls to {@link ContainerProvider#getWebSocketContainer()} to - * find and return the {@link javax.websocket.server.ServerContainer} from the + * find and return the {@code javax.websocket.server.ServerContainer} from the * active {@code javax.servlet.ServletContext}. *

*

@@ -91,7 +85,7 @@ public class JettyClientContainerProvider extends ContainerProvider * occurs within a thread being processed by the Servlet container. *

* - * @param flag true to to use return the {@link javax.websocket.server.ServerContainer} + * @param flag true to to use return the {@code javax.websocket.server.ServerContainer} * from the active {@code javax.servlet.ServletContext} for all calls to * {@link ContainerProvider#getWebSocketContainer()} from within a Servlet thread. */ @@ -103,13 +97,13 @@ public class JettyClientContainerProvider extends ContainerProvider /** * Test if {@link ContainerProvider#getWebSocketContainer()} has the ability to - * find and return the {@link javax.websocket.server.ServerContainer} from the + * find and return the {@code javax.websocket.server.ServerContainer} from the * active {@code javax.servlet.ServletContext}, before creating a new client based * {@link WebSocketContainer}. * * @return true if {@link WebSocketContainer} returned from * calls to {@link ContainerProvider#getWebSocketContainer()} could be the - * {@link javax.websocket.server.ServerContainer} + * {@code javax.websocket.server.ServerContainer} * from the active {@code javax.servlet.ServletContext} */ @SuppressWarnings("unused") @@ -194,28 +188,14 @@ public class JettyClientContainerProvider extends ContainerProvider // Still no instance? if (webSocketContainer == null) { - if (commonExecutor == null) - { - QueuedThreadPool threadPool = new QueuedThreadPool(); - String name = "Jsr356Client@" + hashCode(); - threadPool.setName(name); - threadPool.setDaemon(true); - commonExecutor = threadPool; - } - - if (commonBufferPool == null) - { - commonBufferPool = new MappedByteBufferPool(); - } - - SimpleContainerScope containerScope = new SimpleContainerScope(WebSocketPolicy.newClientPolicy(), commonBufferPool, commonExecutor, null); + SimpleContainerScope containerScope = new SimpleContainerScope(WebSocketPolicy.newClientPolicy()); ClientContainer clientContainer = new ClientContainer(containerScope); if (contextHandler != null && contextHandler instanceof ContainerLifeCycle) { // Add as bean to contextHandler // Allow startup to follow Jetty lifecycle - ((ContainerLifeCycle) contextHandler).addBean(clientContainer); + ((ContainerLifeCycle) contextHandler).addManaged(clientContainer); } else { diff --git a/jetty-websocket/websocket-client/src/main/java/org/eclipse/jetty/websocket/client/WebSocketClient.java b/jetty-websocket/websocket-client/src/main/java/org/eclipse/jetty/websocket/client/WebSocketClient.java index 30464349810..11d4ef71a46 100644 --- a/jetty-websocket/websocket-client/src/main/java/org/eclipse/jetty/websocket/client/WebSocketClient.java +++ b/jetty-websocket/websocket-client/src/main/java/org/eclipse/jetty/websocket/client/WebSocketClient.java @@ -66,16 +66,16 @@ import org.eclipse.jetty.websocket.common.scopes.WebSocketContainerScope; public class WebSocketClient extends ContainerLifeCycle implements WebSocketContainerScope { private static final Logger LOG = Log.getLogger(WebSocketClient.class); - + // From HttpClient private final HttpClient httpClient; - + // The container private final WebSocketContainerScope containerScope; private final WebSocketExtensionFactory extensionRegistry; private SessionFactory sessionFactory; private final List listeners = new CopyOnWriteArrayList<>(); - + private final int id = ThreadLocalRandom.current().nextInt(); /** @@ -125,7 +125,7 @@ public class WebSocketClient extends ContainerLifeCycle implements WebSocketCont { this(new HttpClient()); this.httpClient.setExecutor(executor); - + } /** @@ -237,7 +237,7 @@ public class WebSocketClient extends ContainerLifeCycle implements WebSocketCont this.sessionFactory = new WebSocketSessionFactory(containerScope); } - + /** * Create WebSocketClient based on pre-existing Container Scope, to allow sharing of * internal features like Executor, ByteBufferPool, SSLContextFactory, etc. @@ -388,10 +388,7 @@ public class WebSocketClient extends ContainerLifeCycle implements WebSocketCont if (LOG.isDebugEnabled()) LOG.debug("Stopping {}",this); - if (ShutdownThread.isRegistered(this)) - { - ShutdownThread.deregister(this); - } + ShutdownThread.deregister(this); super.doStop(); @@ -434,7 +431,7 @@ public class WebSocketClient extends ContainerLifeCycle implements WebSocketCont { return httpClient.getCookieStore(); } - + public Executor getExecutor() { return httpClient.getExecutor(); @@ -451,10 +448,10 @@ public class WebSocketClient extends ContainerLifeCycle implements WebSocketCont threadPool.setDaemon(true); return threadPool; } - + return executor; } - + public ExtensionFactory getExtensionFactory() { return extensionRegistry; @@ -698,7 +695,7 @@ public class WebSocketClient extends ContainerLifeCycle implements WebSocketCont getPolicy().setIdleTimeout(ms); httpClient.setIdleTimeout(ms); } - + /** * @deprecated see {@link WebSocketPolicy#setMaxTextMessageBufferSize(int)} */ diff --git a/jetty-websocket/websocket-tests/src/test/java/org/eclipse/jetty/websocket/tests/server/jsr356/DelayedStartClientOnServerTest.java b/jetty-websocket/websocket-tests/src/test/java/org/eclipse/jetty/websocket/tests/server/jsr356/DelayedStartClientOnServerTest.java index c63575f0e42..70232069a48 100644 --- a/jetty-websocket/websocket-tests/src/test/java/org/eclipse/jetty/websocket/tests/server/jsr356/DelayedStartClientOnServerTest.java +++ b/jetty-websocket/websocket-tests/src/test/java/org/eclipse/jetty/websocket/tests/server/jsr356/DelayedStartClientOnServerTest.java @@ -250,7 +250,7 @@ public class DelayedStartClientOnServerTest List threadNames = getThreadNames(server, (ContainerLifeCycle)container); assertNoHttpClientPoolThreads(threadNames); - assertThat("Threads", threadNames, hasItem(containsString("Jsr356Client@"))); + assertThat("Threads", threadNames, hasItem(containsString("WebSocketContainer@"))); } finally { diff --git a/pom.xml b/pom.xml index 8defcf427ff..067fc3c4a41 100644 --- a/pom.xml +++ b/pom.xml @@ -933,7 +933,7 @@ org.eclipse.jetty.toolchain jetty-test-helper - 4.1 + 4.2 org.eclipse.jetty.toolchain