From 275f83c1d0503b12e2b308fead5f18ded4d4e952 Mon Sep 17 00:00:00 2001 From: Lachlan Date: Tue, 18 Jun 2019 16:01:09 +1000 Subject: [PATCH 1/3] Issue #3785 - fix failures in QTP testLifeCycleStop (#3788) make sure the jobs are actually run before calling QTP.stop() Signed-off-by: Lachlan Roberts --- .../util/thread/QueuedThreadPoolTest.java | 29 ++++++++++--------- 1 file changed, 15 insertions(+), 14 deletions(-) diff --git a/jetty-util/src/test/java/org/eclipse/jetty/util/thread/QueuedThreadPoolTest.java b/jetty-util/src/test/java/org/eclipse/jetty/util/thread/QueuedThreadPoolTest.java index e03322d7b74..0c11f81163c 100644 --- a/jetty-util/src/test/java/org/eclipse/jetty/util/thread/QueuedThreadPoolTest.java +++ b/jetty-util/src/test/java/org/eclipse/jetty/util/thread/QueuedThreadPoolTest.java @@ -48,11 +48,12 @@ public class QueuedThreadPoolTest extends AbstractThreadPoolTest private class RunningJob implements Runnable { - private final CountDownLatch _run = new CountDownLatch(1); - private final CountDownLatch _stopping = new CountDownLatch(1); - private final CountDownLatch _stopped = new CountDownLatch(1); - private final String _name; - private final boolean _fail; + final CountDownLatch _run = new CountDownLatch(1); + final CountDownLatch _stopping = new CountDownLatch(1); + final CountDownLatch _stopped = new CountDownLatch(1); + final String _name; + final boolean _fail; + RunningJob() { this(null, false); @@ -118,7 +119,7 @@ public class QueuedThreadPoolTest extends AbstractThreadPoolTest private class CloseableJob extends RunningJob implements Closeable { - private final CountDownLatch _closed = new CountDownLatch(1); + final CountDownLatch _closed = new CountDownLatch(1); @Override public void close() throws IOException @@ -382,24 +383,24 @@ public class QueuedThreadPoolTest extends AbstractThreadPoolTest // Wait until the first 2 start running waitForThreads(tp,2); waitForIdle(tp,0); + assertTrue(job0._run.await(200, TimeUnit.MILLISECONDS)); + assertTrue(job1._run.await(200, TimeUnit.MILLISECONDS)); // Queue should be empty after thread pool is stopped tp.stop(); assertThat(tp.getQueue().size(), is(0)); // First 2 jobs closed by InterruptedException - assertThat(job0._stopped.await(200, TimeUnit.MILLISECONDS), is(true)); - assertThat(job1._stopped.await(200, TimeUnit.MILLISECONDS), is(true)); + assertTrue(job0._stopped.await(200, TimeUnit.MILLISECONDS)); + assertTrue(job1._stopped.await(200, TimeUnit.MILLISECONDS)); // Verify RunningJobs in the queue have not been run - assertThat(job2._run.await(200, TimeUnit.MILLISECONDS), is(false)); - assertThat(job4._run.await(200, TimeUnit.MILLISECONDS), is(false)); + assertFalse(job2._run.await(200, TimeUnit.MILLISECONDS)); + assertFalse(job4._run.await(200, TimeUnit.MILLISECONDS)); // Verify ClosableJobs have not been run but have been closed - assertThat(job4._run.await(200, TimeUnit.MILLISECONDS), is(false)); - assertThat(job3._closed.await(200, TimeUnit.MILLISECONDS), is(true)); - - tp.stop(); + assertFalse(job3._run.await(200, TimeUnit.MILLISECONDS)); + assertTrue(job3._closed.await(200, TimeUnit.MILLISECONDS)); } From 862e6d008e99223ad048860dd69c19914732a4f7 Mon Sep 17 00:00:00 2001 From: Greg Wilkins Date: Tue, 18 Jun 2019 09:50:18 +0200 Subject: [PATCH 2/3] Jetty 9.4.x 3755 annotation/jndi example cleanup (#3763) * Issue #3755 Annotation example cleanup + Created JettyDistribution class as common utility to locate a jetty distribution for examples. + Fixed ServerWithAnnotations to correctly use the test-spec-webapp + Added AttributeContainerMap as a better way to treat attribute values as beans. This avoids them appearing twice in a dump and always associates them with their key. + Added NamingDump and use it in EnvConfiguration and jetty-plus.xml so that a server dump will contain dumps of the server local tree and each contexts java:comp/env tree + Improved the dump format of NamingContext and WebAppContext + Improved the toString format of several associated classes Signed-off-by: Greg Wilkins --- .../jetty/embedded/JettyDistribution.java | 109 +++++++++++ .../eclipse/jetty/embedded/LikeJettyXml.java | 20 +- .../org/eclipse/jetty/embedded/OneWebApp.java | 3 +- .../jetty/embedded/ServerWithAnnotations.java | 18 +- .../org/eclipse/jetty/jndi/NamingContext.java | 27 ++- .../jetty/jndi/local/localContextRoot.java | 4 +- .../org/eclipse/jetty/plus/jndi/EnvEntry.java | 6 + .../org/eclipse/jetty/plus/jndi/Link.java | 6 + .../eclipse/jetty/plus/jndi/NamingDump.java | 71 +++++++ .../eclipse/jetty/plus/jndi/NamingEntry.java | 32 ++-- .../jetty/plus/jndi/NamingEntryUtil.java | 4 +- .../jetty/plus/webapp/EnvConfiguration.java | 47 ++--- .../src/main/plus-config/etc/jetty-plus.xml | 4 + .../jetty/plus/jndi/TestNamingEntryUtil.java | 21 +-- .../jetty/server/LowResourceMonitor.java | 20 +- .../java/org/eclipse/jetty/server/Server.java | 20 +- .../util/component/AttributeContainerMap.java | 82 +++++++++ .../jetty/util/component/Container.java | 2 +- .../util/component/ContainerLifeCycle.java | 12 +- .../jetty/util/component/Dumpable.java | 174 ++++++++++-------- .../jetty/webapp/WebAppClassLoader.java | 2 +- .../eclipse/jetty/webapp/WebAppContext.java | 48 +++-- 22 files changed, 520 insertions(+), 212 deletions(-) create mode 100644 examples/embedded/src/main/java/org/eclipse/jetty/embedded/JettyDistribution.java create mode 100644 jetty-plus/src/main/java/org/eclipse/jetty/plus/jndi/NamingDump.java create mode 100644 jetty-util/src/main/java/org/eclipse/jetty/util/component/AttributeContainerMap.java diff --git a/examples/embedded/src/main/java/org/eclipse/jetty/embedded/JettyDistribution.java b/examples/embedded/src/main/java/org/eclipse/jetty/embedded/JettyDistribution.java new file mode 100644 index 00000000000..0d3c3810606 --- /dev/null +++ b/examples/embedded/src/main/java/org/eclipse/jetty/embedded/JettyDistribution.java @@ -0,0 +1,109 @@ +// +// ======================================================================== +// Copyright (c) 1995-2019 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.embedded; + +import java.io.File; +import java.nio.file.Path; + +import org.eclipse.jetty.util.StringUtil; +import org.eclipse.jetty.util.log.Log; +import org.eclipse.jetty.util.log.Logger; + +/** + * A utility test class to locate a Jetty Distribution for testing purposes by searching: + *
    + *
  • The jetty.home system property
  • + *
  • The JETTY_HOME environment variable
  • + *
  • The working directory hierarchy with subdirectory jetty-distribution/target/home
  • + *
+ */ +public class JettyDistribution +{ + private final static Logger LOG = Log.getLogger(JettyDistribution.class); + public final static Path DISTRIBUTION; + + static + { + Path distro = asJettyDistribution(System.getProperty("jetty.home")); + if (distro==null) + distro = asJettyDistribution(System.getenv().get("JETTY_HOME")); + + if (distro==null) + { + try + { + Path working = new File(".").getAbsoluteFile().getCanonicalFile().toPath(); + while(distro == null && working !=null ) + { + distro = asJettyDistribution(working.resolve("jetty-distribution/target/distribution").toString()); + working = working.getParent(); + } + } + catch(Throwable th) + { + LOG.warn(th); + } + } + DISTRIBUTION = distro; + } + + private static Path asJettyDistribution(String test) + { + try + { + if (StringUtil.isBlank(test)) + { + LOG.info("asJettyDistribution {} is blank", test); + return null; + } + + File dir = new File(test); + if (!dir.exists() || !dir.isDirectory()) + { + LOG.info("asJettyDistribution {} is not a directory", test); + return null; + } + + File demoBase = new File(dir,"demo-base"); + if (!demoBase.exists() || !demoBase.isDirectory()) + { + LOG.info("asJettyDistribution {} has no demo-base", test); + return null; + } + + LOG.info("asJettyDistribution {}", dir); + return dir.getAbsoluteFile().getCanonicalFile().toPath(); + } + catch(Exception e) + { + LOG.ignore(e); + } + return null; + } + + public static Path resolve(String path) + { + return DISTRIBUTION.resolve(path); + } + + public static void main(String... arg) + { + System.err.println("Jetty Distribution is " + DISTRIBUTION); + } +} diff --git a/examples/embedded/src/main/java/org/eclipse/jetty/embedded/LikeJettyXml.java b/examples/embedded/src/main/java/org/eclipse/jetty/embedded/LikeJettyXml.java index 3a56eff6da9..1ad9f45f664 100644 --- a/examples/embedded/src/main/java/org/eclipse/jetty/embedded/LikeJettyXml.java +++ b/examples/embedded/src/main/java/org/eclipse/jetty/embedded/LikeJettyXml.java @@ -19,7 +19,6 @@ package org.eclipse.jetty.embedded; import java.io.File; -import java.io.FileNotFoundException; import java.lang.management.ManagementFactory; import org.eclipse.jetty.deploy.DeploymentManager; @@ -60,27 +59,14 @@ public class LikeJettyXml public static void main( String[] args ) throws Exception { // Path to as-built jetty-distribution directory - String jettyHomeBuild = "jetty-distribution/target/distribution"; - + String jettyHomeBuild = JettyDistribution.DISTRIBUTION.toString(); + // Find jetty home and base directories String homePath = System.getProperty("jetty.home", jettyHomeBuild); - File start_jar = new File(homePath,"start.jar"); - if (!start_jar.exists()) - { - homePath = jettyHomeBuild = "jetty-distribution/target/distribution"; - start_jar = new File(homePath,"start.jar"); - if (!start_jar.exists()) - throw new FileNotFoundException(start_jar.toString()); - } - File homeDir = new File(homePath); String basePath = System.getProperty("jetty.base", homeDir + "/demo-base"); File baseDir = new File(basePath); - if(!baseDir.exists()) - { - throw new FileNotFoundException(baseDir.getAbsolutePath()); - } // Configure jetty.home and jetty.base system properties String jetty_home = homeDir.getAbsolutePath(); @@ -88,7 +74,6 @@ public class LikeJettyXml System.setProperty("jetty.home", jetty_home); System.setProperty("jetty.base", jetty_base); - // === jetty.xml === // Setup Threadpool QueuedThreadPool threadPool = new QueuedThreadPool(); @@ -219,7 +204,6 @@ public class LikeJettyXml lowResourcesMonitor.setPeriod(1000); lowResourcesMonitor.setLowResourcesIdleTimeout(200); lowResourcesMonitor.setMonitorThreads(true); - lowResourcesMonitor.setMaxConnections(0); lowResourcesMonitor.setMaxMemory(0); lowResourcesMonitor.setMaxLowResourcesTime(5000); server.addBean(lowResourcesMonitor); diff --git a/examples/embedded/src/main/java/org/eclipse/jetty/embedded/OneWebApp.java b/examples/embedded/src/main/java/org/eclipse/jetty/embedded/OneWebApp.java index e6457c784c0..454d0555b4c 100644 --- a/examples/embedded/src/main/java/org/eclipse/jetty/embedded/OneWebApp.java +++ b/examples/embedded/src/main/java/org/eclipse/jetty/embedded/OneWebApp.java @@ -49,8 +49,7 @@ public class OneWebApp // PlusConfiguration) to choosing where the webapp will unpack itself. WebAppContext webapp = new WebAppContext(); webapp.setContextPath("/"); - File warFile = new File( - "../../tests/test-jmx/jmx-webapp/target/jmx-webapp"); + File warFile = JettyDistribution.resolve("demo-base/webapps/async-rest.war").toFile(); webapp.setWar(warFile.getAbsolutePath()); // A WebAppContext is a ContextHandler as well so it needs to be set to diff --git a/examples/embedded/src/main/java/org/eclipse/jetty/embedded/ServerWithAnnotations.java b/examples/embedded/src/main/java/org/eclipse/jetty/embedded/ServerWithAnnotations.java index d5ed0c922ca..41b611d2543 100644 --- a/examples/embedded/src/main/java/org/eclipse/jetty/embedded/ServerWithAnnotations.java +++ b/examples/embedded/src/main/java/org/eclipse/jetty/embedded/ServerWithAnnotations.java @@ -21,6 +21,7 @@ package org.eclipse.jetty.embedded; import java.io.File; import org.eclipse.jetty.plus.jndi.EnvEntry; +import org.eclipse.jetty.plus.jndi.NamingDump; import org.eclipse.jetty.plus.jndi.Resource; import org.eclipse.jetty.plus.jndi.Transaction; import org.eclipse.jetty.security.HashLoginService; @@ -47,16 +48,14 @@ public class ServerWithAnnotations classlist.addBefore( "org.eclipse.jetty.webapp.JettyWebXmlConfiguration", "org.eclipse.jetty.annotations.AnnotationConfiguration"); - // Create a WebApp WebAppContext webapp = new WebAppContext(); webapp.setContextPath("/"); - File warFile = new File( - "jetty-distribution/target/distribution/demo-base/webapps/test.war"); + File warFile = JettyDistribution.resolve("demo-base/webapps/test-spec.war").toFile(); webapp.setWar(warFile.getAbsolutePath()); webapp.setAttribute( - "org.eclipse.jetty.server.webapp.ContainerIncludeJarPattern", - ".*/javax.servlet-[^/]*\\.jar$|.*/servlet-api-[^/]*\\.jar$"); + "org.eclipse.jetty.server.webapp.ContainerIncludeJarPattern", + ".*/javax.servlet-[^/]*\\.jar$|.*/servlet-api-[^/]*\\.jar$"); server.setHandler(webapp); // Register new transaction manager in JNDI @@ -64,10 +63,14 @@ public class ServerWithAnnotations new Transaction(new com.acme.MockUserTransaction()); // Define an env entry with webapp scope. - new EnvEntry(webapp, "maxAmount", new Double(100), true); + // THIS ENTRY IS OVERRIDEN BY THE ENTRY IN jetty-env.xml + new EnvEntry(webapp, "maxAmount", 100d, true); // Register a mock DataSource scoped to the webapp - new Resource(webapp, "jdbc/mydatasource", new com.acme.MockDataSource()); + new Resource(server, "jdbc/mydatasource", new com.acme.MockDataSource()); + + // Add JNDI context to server for dump + server.addBean(new NamingDump()); // Configure a LoginService HashLoginService loginService = new HashLoginService(); @@ -75,6 +78,7 @@ public class ServerWithAnnotations loginService.setConfig("examples/embedded/src/test/resources/realm.properties"); server.addBean(loginService); + server.start(); server.dumpStdErr(); server.join(); diff --git a/jetty-jndi/src/main/java/org/eclipse/jetty/jndi/NamingContext.java b/jetty-jndi/src/main/java/org/eclipse/jetty/jndi/NamingContext.java index 1d147752c12..d0f7271f297 100644 --- a/jetty-jndi/src/main/java/org/eclipse/jetty/jndi/NamingContext.java +++ b/jetty-jndi/src/main/java/org/eclipse/jetty/jndi/NamingContext.java @@ -22,8 +22,10 @@ import java.io.IOException; import java.util.ArrayList; import java.util.Collection; import java.util.Collections; +import java.util.HashMap; import java.util.Hashtable; import java.util.List; +import java.util.Map; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentMap; import javax.naming.Binding; @@ -126,7 +128,7 @@ public class NamingContext implements Context, Dumpable this(env, name, parent, parser, null); } - private NamingContext(Hashtable env, + protected NamingContext(Hashtable env, String name, NamingContext parent, NameParser parser, @@ -143,14 +145,13 @@ public class NamingContext implements Context, Dumpable } /** - * @return A shallow copy of the Context with the same bindings, but a copy of the Env + * @return A shallow copy of the Context with the same bindings, but with the passed environment */ - public NamingContext shallowCopy() + public Context shallowCopy(Hashtable env) { - return new NamingContext(_env, _name, _parent, _parser, _bindings); + return new NamingContext(env, _name, _parent, _parser, _bindings); } - public boolean isDeepBindingSupported() { // look for deep binding support in _env @@ -457,7 +458,7 @@ public class NamingContext implements Context, Dumpable { if(LOG.isDebugEnabled()) LOG.debug("Null or empty name, returning shallowCopy of this context"); - return shallowCopy(); + return shallowCopy(_env); } if (cname.size() == 1) @@ -541,7 +542,7 @@ public class NamingContext implements Context, Dumpable if (cname == null || name.isEmpty()) { - return shallowCopy(); + return shallowCopy(_env); } if (cname.size() == 0) @@ -1118,7 +1119,17 @@ public class NamingContext implements Context, Dumpable @Override public void dump(Appendable out,String indent) throws IOException { - Dumpable.dumpObjects(out,indent,this, _bindings); + Map bindings = new HashMap<>(); + for (Map.Entry binding : _bindings.entrySet()) + bindings.put(binding.getKey(), binding.getValue().getObject()); + + Dumpable.dumpObject(out, this); + Dumpable.dumpMapEntries(out, indent, bindings, _env.isEmpty()); + if (!_env.isEmpty()) + { + out.append(indent).append("+> environment\n"); + Dumpable.dumpMapEntries(out, indent + " ", _env, true); + } } private Collection findListeners() diff --git a/jetty-jndi/src/main/java/org/eclipse/jetty/jndi/local/localContextRoot.java b/jetty-jndi/src/main/java/org/eclipse/jetty/jndi/local/localContextRoot.java index f712d329be6..3ad31582062 100644 --- a/jetty-jndi/src/main/java/org/eclipse/jetty/jndi/local/localContextRoot.java +++ b/jetty-jndi/src/main/java/org/eclipse/jetty/jndi/local/localContextRoot.java @@ -270,7 +270,7 @@ public class localContextRoot implements Context if (cname == null || cname.isEmpty()) { //If no name create copy of this context with same bindings, but with copy of the environment so it can be modified - return __root.shallowCopy(); + return __root.shallowCopy(_env); } if (cname.size() == 0) @@ -339,7 +339,7 @@ public class localContextRoot implements Context if ((cname == null) || cname.isEmpty()) { - return __root.shallowCopy(); + return __root.shallowCopy(_env); } if (cname.size() == 1) diff --git a/jetty-plus/src/main/java/org/eclipse/jetty/plus/jndi/EnvEntry.java b/jetty-plus/src/main/java/org/eclipse/jetty/plus/jndi/EnvEntry.java index 8a08ae902e4..a6881343ea2 100644 --- a/jetty-plus/src/main/java/org/eclipse/jetty/plus/jndi/EnvEntry.java +++ b/jetty-plus/src/main/java/org/eclipse/jetty/plus/jndi/EnvEntry.java @@ -56,4 +56,10 @@ public class EnvEntry extends NamingEntry { return this.overrideWebXml; } + + @Override + protected String toStringMetaData() + { + return "OverrideWebXml=" + overrideWebXml; + } } diff --git a/jetty-plus/src/main/java/org/eclipse/jetty/plus/jndi/Link.java b/jetty-plus/src/main/java/org/eclipse/jetty/plus/jndi/Link.java index aeb96e096e3..c0ee8a68563 100644 --- a/jetty-plus/src/main/java/org/eclipse/jetty/plus/jndi/Link.java +++ b/jetty-plus/src/main/java/org/eclipse/jetty/plus/jndi/Link.java @@ -52,4 +52,10 @@ public class Link extends NamingEntry { return _link; } + + @Override + protected String toStringMetaData() + { + return _link; + } } diff --git a/jetty-plus/src/main/java/org/eclipse/jetty/plus/jndi/NamingDump.java b/jetty-plus/src/main/java/org/eclipse/jetty/plus/jndi/NamingDump.java new file mode 100644 index 00000000000..7be17835011 --- /dev/null +++ b/jetty-plus/src/main/java/org/eclipse/jetty/plus/jndi/NamingDump.java @@ -0,0 +1,71 @@ +// +// ======================================================================== +// Copyright (c) 1995-2019 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.plus.jndi; + +import javax.naming.InitialContext; + +import org.eclipse.jetty.util.StringUtil; +import org.eclipse.jetty.util.component.Dumpable; + +/** + * A utility Dumpable to dump a JNDI naming context tree. + */ +public class NamingDump implements Dumpable +{ + private final ClassLoader _loader; + private final String _name; + + public NamingDump() + { + this(null,""); + } + + public NamingDump(ClassLoader loader, String name) + { + _loader = loader; + _name = name; + } + + @Override + public void dump(Appendable out, String indent) + { + ClassLoader loader = Thread.currentThread().getContextClassLoader(); + try + { + if (!StringUtil.isBlank(_name)) + out.append(_name).append(" "); + if (_loader!=null) + Thread.currentThread().setContextClassLoader(_loader); + Object context = new InitialContext().lookup(_name); + if (context instanceof Dumpable) + ((Dumpable)context).dump(out, indent); + else + Dumpable.dumpObjects(out, indent, context); + } + catch(Throwable th) + { + throw new RuntimeException(th); + } + finally + { + if (_loader!=null) + Thread.currentThread().setContextClassLoader(loader); + } + } +} diff --git a/jetty-plus/src/main/java/org/eclipse/jetty/plus/jndi/NamingEntry.java b/jetty-plus/src/main/java/org/eclipse/jetty/plus/jndi/NamingEntry.java index 765064524cd..92a3ff0c216 100644 --- a/jetty-plus/src/main/java/org/eclipse/jetty/plus/jndi/NamingEntry.java +++ b/jetty-plus/src/main/java/org/eclipse/jetty/plus/jndi/NamingEntry.java @@ -49,14 +49,7 @@ public abstract class NamingEntry protected String _namingEntryNameString; //the name of the NamingEntry relative to the context it is stored in protected String _objectNameString; //the name of the object relative to the context it is stored in - - @Override - public String toString() - { - return _jndiName; - } - - + /** * Create a naming entry. * @@ -173,21 +166,21 @@ public abstract class NamingEntry /** * Save the NamingEntry for later use. *

- * Saving is done by binding the NamingEntry + * Saving is done by binding both the NamingEntry * itself, and the value it represents into * JNDI. In this way, we can link to the * value it represents later, but also * still retrieve the NamingEntry itself too. *

- * The object is bound at the jndiName passed in. - * This NamingEntry is bound at __/jndiName. + * The object is bound at scope/jndiName and + * the NamingEntry is bound at scope/__/jndiName. *

* eg *

      * jdbc/foo    : DataSource
      * __/jdbc/foo : NamingEntry
      * 
- * + * @see NamingEntryUtil#getNameForScope(Object) * @param object the object to save * @throws NamingException if unable to save */ @@ -212,5 +205,18 @@ public abstract class NamingEntry _objectNameString = objectName.toString(); NamingUtil.bind(ic, _objectNameString, object); } - + + protected String toStringMetaData() + { + return null; + } + + @Override + public String toString() + { + String metadata = toStringMetaData(); + if (metadata == null) + return String.format("%s@%x{name=%s}", this.getClass().getName(), hashCode(), getJndiName()); + return String.format("%s@%x{name=%s,%s}", this.getClass().getName(), hashCode(), getJndiName(), metadata); + } } diff --git a/jetty-plus/src/main/java/org/eclipse/jetty/plus/jndi/NamingEntryUtil.java b/jetty-plus/src/main/java/org/eclipse/jetty/plus/jndi/NamingEntryUtil.java index e005d4337b2..b6050350dfe 100644 --- a/jetty-plus/src/main/java/org/eclipse/jetty/plus/jndi/NamingEntryUtil.java +++ b/jetty-plus/src/main/java/org/eclipse/jetty/plus/jndi/NamingEntryUtil.java @@ -118,7 +118,7 @@ public class NamingEntryUtil * @return all NameEntries of a certain type in the given naming environment scope (server-wide names or context-specific names) * @throws NamingException if unable to lookup the naming entries */ - public static List lookupNamingEntries (Object scope, Class clazz) + public static List lookupNamingEntries (Object scope, Class clazz) throws NamingException { try @@ -127,7 +127,7 @@ public class NamingEntryUtil Context namingEntriesContext = (Context)scopeContext.lookup(NamingEntry.__contextName); ArrayList list = new ArrayList(); lookupNamingEntries(list, namingEntriesContext, clazz); - return list; + return (List)list; } catch (NameNotFoundException e) { diff --git a/jetty-plus/src/main/java/org/eclipse/jetty/plus/webapp/EnvConfiguration.java b/jetty-plus/src/main/java/org/eclipse/jetty/plus/webapp/EnvConfiguration.java index 869d2d605d0..6441478bc17 100644 --- a/jetty-plus/src/main/java/org/eclipse/jetty/plus/webapp/EnvConfiguration.java +++ b/jetty-plus/src/main/java/org/eclipse/jetty/plus/webapp/EnvConfiguration.java @@ -21,9 +21,7 @@ package org.eclipse.jetty.plus.webapp; import java.net.URL; import java.util.ArrayList; import java.util.Collections; -import java.util.Iterator; import java.util.List; - import javax.naming.Binding; import javax.naming.Context; import javax.naming.InitialContext; @@ -36,6 +34,7 @@ import org.eclipse.jetty.jndi.NamingContext; import org.eclipse.jetty.jndi.NamingUtil; import org.eclipse.jetty.jndi.local.localContextRoot; import org.eclipse.jetty.plus.jndi.EnvEntry; +import org.eclipse.jetty.plus.jndi.NamingDump; import org.eclipse.jetty.plus.jndi.NamingEntryUtil; import org.eclipse.jetty.util.log.Log; import org.eclipse.jetty.util.log.Logger; @@ -54,6 +53,7 @@ public class EnvConfiguration extends AbstractConfiguration private static final String JETTY_ENV_BINDINGS = "org.eclipse.jetty.jndi.EnvConfiguration"; private URL jettyEnvXmlUrl; + private NamingDump _dumper; public void setJettyEnvXml (URL url) { @@ -128,6 +128,9 @@ public class EnvConfiguration extends AbstractConfiguration //add java:comp/env entries for any EnvEntries that have been defined so far bindEnvEntries(context); + + _dumper = new NamingDump(context.getClassLoader(),"java:comp"); + context.addBean(_dumper); } @@ -138,6 +141,9 @@ public class EnvConfiguration extends AbstractConfiguration @Override public void deconfigure (WebAppContext context) throws Exception { + context.removeBean(_dumper); + _dumper = null; + //get rid of any bindings for comp/env for webapp ClassLoader oldLoader = Thread.currentThread().getContextClassLoader(); Thread.currentThread().setContextClassLoader(context.getClassLoader()); @@ -206,40 +212,23 @@ public class EnvConfiguration extends AbstractConfiguration public void bindEnvEntries (WebAppContext context) throws NamingException { - LOG.debug("Binding env entries from the jvm scope"); InitialContext ic = new InitialContext(); Context envCtx = (Context)ic.lookup("java:comp/env"); - Object scope = null; - List list = NamingEntryUtil.lookupNamingEntries(scope, EnvEntry.class); - Iterator itor = list.iterator(); - while (itor.hasNext()) - { - EnvEntry ee = (EnvEntry)itor.next(); - ee.bindToENC(ee.getJndiName()); - Name namingEntryName = NamingEntryUtil.makeNamingEntryName(null, ee); - NamingUtil.bind(envCtx, namingEntryName.toString(), ee);//also save the EnvEntry in the context so we can check it later - } + + LOG.debug("Binding env entries from the jvm scope"); + doBindings(envCtx, null); LOG.debug("Binding env entries from the server scope"); - - scope = context.getServer(); - list = NamingEntryUtil.lookupNamingEntries(scope, EnvEntry.class); - itor = list.iterator(); - while (itor.hasNext()) - { - EnvEntry ee = (EnvEntry)itor.next(); - ee.bindToENC(ee.getJndiName()); - Name namingEntryName = NamingEntryUtil.makeNamingEntryName(null, ee); - NamingUtil.bind(envCtx, namingEntryName.toString(), ee);//also save the EnvEntry in the context so we can check it later - } + doBindings(envCtx, context.getServer()); LOG.debug("Binding env entries from the context scope"); - scope = context; - list = NamingEntryUtil.lookupNamingEntries(scope, EnvEntry.class); - itor = list.iterator(); - while (itor.hasNext()) + doBindings(envCtx, context); + } + + private void doBindings(Context envCtx, Object scope) throws NamingException + { + for (EnvEntry ee : NamingEntryUtil.lookupNamingEntries(scope, EnvEntry.class)) { - EnvEntry ee = (EnvEntry)itor.next(); ee.bindToENC(ee.getJndiName()); Name namingEntryName = NamingEntryUtil.makeNamingEntryName(null, ee); NamingUtil.bind(envCtx, namingEntryName.toString(), ee);//also save the EnvEntry in the context so we can check it later diff --git a/jetty-plus/src/main/plus-config/etc/jetty-plus.xml b/jetty-plus/src/main/plus-config/etc/jetty-plus.xml index ed3082408a4..fd869e72aa4 100644 --- a/jetty-plus/src/main/plus-config/etc/jetty-plus.xml +++ b/jetty-plus/src/main/plus-config/etc/jetty-plus.xml @@ -22,5 +22,9 @@ + + + + diff --git a/jetty-plus/src/test/java/org/eclipse/jetty/plus/jndi/TestNamingEntryUtil.java b/jetty-plus/src/test/java/org/eclipse/jetty/plus/jndi/TestNamingEntryUtil.java index b861ef308a9..d4a22cabe25 100644 --- a/jetty-plus/src/test/java/org/eclipse/jetty/plus/jndi/TestNamingEntryUtil.java +++ b/jetty-plus/src/test/java/org/eclipse/jetty/plus/jndi/TestNamingEntryUtil.java @@ -18,6 +18,15 @@ package org.eclipse.jetty.plus.jndi; +import java.util.List; +import javax.naming.Context; +import javax.naming.InitialContext; +import javax.naming.Name; +import javax.naming.NameNotFoundException; +import javax.naming.NamingException; + +import org.junit.jupiter.api.Test; + import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.Matchers.containsInAnyOrder; import static org.hamcrest.Matchers.empty; @@ -27,16 +36,6 @@ import static org.junit.jupiter.api.Assertions.assertNotNull; import static org.junit.jupiter.api.Assertions.assertNull; import static org.junit.jupiter.api.Assertions.fail; -import java.util.List; - -import javax.naming.Context; -import javax.naming.InitialContext; -import javax.naming.Name; -import javax.naming.NameNotFoundException; -import javax.naming.NamingException; - -import org.junit.jupiter.api.Test; - public class TestNamingEntryUtil { public class MyNamingEntry extends NamingEntry @@ -122,7 +121,7 @@ public class TestNamingEntryUtil public void testLookupNamingEntries() throws Exception { ScopeA scope = new ScopeA(); - List list = NamingEntryUtil.lookupNamingEntries(scope, MyNamingEntry.class); + List list = NamingEntryUtil.lookupNamingEntries(scope, MyNamingEntry.class); assertThat(list, is(empty())); MyNamingEntry mne1 = new MyNamingEntry(scope, "a/b", 1); diff --git a/jetty-server/src/main/java/org/eclipse/jetty/server/LowResourceMonitor.java b/jetty-server/src/main/java/org/eclipse/jetty/server/LowResourceMonitor.java index 811c547307a..65994fced8d 100644 --- a/jetty-server/src/main/java/org/eclipse/jetty/server/LowResourceMonitor.java +++ b/jetty-server/src/main/java/org/eclipse/jetty/server/LowResourceMonitor.java @@ -18,6 +18,15 @@ package org.eclipse.jetty.server; +import java.util.Arrays; +import java.util.Collection; +import java.util.Collections; +import java.util.HashSet; +import java.util.Set; +import java.util.concurrent.Executor; +import java.util.concurrent.TimeUnit; +import java.util.concurrent.atomic.AtomicBoolean; + import org.eclipse.jetty.io.EndPoint; import org.eclipse.jetty.util.annotation.ManagedAttribute; import org.eclipse.jetty.util.annotation.ManagedObject; @@ -29,15 +38,6 @@ import org.eclipse.jetty.util.thread.ScheduledExecutorScheduler; import org.eclipse.jetty.util.thread.Scheduler; import org.eclipse.jetty.util.thread.ThreadPool; -import java.util.Arrays; -import java.util.Collection; -import java.util.Collections; -import java.util.HashSet; -import java.util.Set; -import java.util.concurrent.Executor; -import java.util.concurrent.TimeUnit; -import java.util.concurrent.atomic.AtomicBoolean; - /** * @@ -135,7 +135,7 @@ public class LowResourceMonitor extends ContainerLifeCycle /** * @param maxConnections The maximum connections before low resources state is triggered - * @deprecated Replaced by ConnectionLimit + * @deprecated Replaced by {@link ConnectionLimit} */ @Deprecated public void setMaxConnections(int maxConnections) diff --git a/jetty-server/src/main/java/org/eclipse/jetty/server/Server.java b/jetty-server/src/main/java/org/eclipse/jetty/server/Server.java index 808882a8576..b04ee643cf6 100644 --- a/jetty-server/src/main/java/org/eclipse/jetty/server/Server.java +++ b/jetty-server/src/main/java/org/eclipse/jetty/server/Server.java @@ -28,7 +28,6 @@ import java.util.Enumeration; import java.util.List; import java.util.concurrent.CopyOnWriteArrayList; import java.util.concurrent.Future; - import javax.servlet.ServletContext; import javax.servlet.ServletException; import javax.servlet.http.HttpServletRequest; @@ -47,7 +46,6 @@ import org.eclipse.jetty.server.handler.ErrorHandler; import org.eclipse.jetty.server.handler.HandlerWrapper; import org.eclipse.jetty.server.handler.StatisticsHandler; import org.eclipse.jetty.util.Attributes; -import org.eclipse.jetty.util.AttributesMap; import org.eclipse.jetty.util.Jetty; import org.eclipse.jetty.util.MultiException; import org.eclipse.jetty.util.URIUtil; @@ -55,6 +53,7 @@ import org.eclipse.jetty.util.Uptime; import org.eclipse.jetty.util.annotation.ManagedAttribute; import org.eclipse.jetty.util.annotation.ManagedObject; import org.eclipse.jetty.util.annotation.Name; +import org.eclipse.jetty.util.component.AttributeContainerMap; import org.eclipse.jetty.util.component.LifeCycle; import org.eclipse.jetty.util.log.Log; import org.eclipse.jetty.util.log.Logger; @@ -75,7 +74,7 @@ public class Server extends HandlerWrapper implements Attributes { private static final Logger LOG = Log.getLogger(Server.class); - private final AttributesMap _attributes = new AttributesMap(); + private final AttributeContainerMap _attributes = new AttributeContainerMap(); private final ThreadPool _threadPool; private final List _connectors = new CopyOnWriteArrayList<>(); private SessionIdManager _sessionIdManager; @@ -107,6 +106,7 @@ public class Server extends HandlerWrapper implements Attributes ServerConnector connector=new ServerConnector(this); connector.setPort(port); setConnectors(new Connector[]{connector}); + addBean(_attributes); } /* ------------------------------------------------------------ */ @@ -584,9 +584,6 @@ public class Server extends HandlerWrapper implements Attributes @Override public void clearAttributes() { - Enumeration names = _attributes.getAttributeNames(); - while (names.hasMoreElements()) - removeBean(_attributes.getAttribute(names.nextElement())); _attributes.clearAttributes(); } @@ -607,7 +604,7 @@ public class Server extends HandlerWrapper implements Attributes @Override public Enumeration getAttributeNames() { - return AttributesMap.getAttributeNamesCopy(_attributes); + return _attributes.getAttributeNames(); } /* ------------------------------------------------------------ */ @@ -617,9 +614,6 @@ public class Server extends HandlerWrapper implements Attributes @Override public void removeAttribute(String name) { - Object bean=_attributes.getAttribute(name); - if (bean!=null) - removeBean(bean); _attributes.removeAttribute(name); } @@ -630,9 +624,6 @@ public class Server extends HandlerWrapper implements Attributes @Override public void setAttribute(String name, Object attribute) { - // TODO this is a crude way to get attribute values managed by JMX. - Object old=_attributes.getAttribute(name); - updateBean(old,attribute); _attributes.setAttribute(name, attribute); } @@ -693,7 +684,7 @@ public class Server extends HandlerWrapper implements Attributes @Override public void dump(Appendable out,String indent) throws IOException { - dumpObjects(out,indent,new ClassLoaderDump(this.getClass().getClassLoader()),_attributes); + dumpObjects(out,indent,new ClassLoaderDump(this.getClass().getClassLoader())); } /* ------------------------------------------------------------ */ @@ -714,6 +705,5 @@ public class Server extends HandlerWrapper implements Attributes _seconds = seconds; _dateField = dateField; } - } } diff --git a/jetty-util/src/main/java/org/eclipse/jetty/util/component/AttributeContainerMap.java b/jetty-util/src/main/java/org/eclipse/jetty/util/component/AttributeContainerMap.java new file mode 100644 index 00000000000..109af9e163f --- /dev/null +++ b/jetty-util/src/main/java/org/eclipse/jetty/util/component/AttributeContainerMap.java @@ -0,0 +1,82 @@ +// +// ======================================================================== +// Copyright (c) 1995-2019 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.util.component; + +import java.io.IOException; +import java.util.Collections; +import java.util.Enumeration; +import java.util.HashMap; +import java.util.Map; + +import org.eclipse.jetty.util.Attributes; + +/** + * An Attributes implementation that holds it's values in an immutable {@link ContainerLifeCycle} + */ +public class AttributeContainerMap extends ContainerLifeCycle implements Attributes +{ + private final Map _map = new HashMap<>(); + + @Override + public synchronized void setAttribute(String name, Object attribute) + { + Object old = _map.put(name, attribute); + updateBean(old, attribute); + } + + @Override + public synchronized void removeAttribute(String name) + { + Object removed = _map.remove(name); + if (removed != null) + removeBean(removed); + } + + @Override + public synchronized Object getAttribute(String name) + { + return _map.get(name); + } + + @Override + public synchronized Enumeration getAttributeNames() + { + return Collections.enumeration(_map.keySet()); + } + + @Override + public synchronized void clearAttributes() + { + _map.clear(); + this.removeBeans(); + } + + @Override + public void dump(Appendable out, String indent) throws IOException + { + Dumpable.dumpObject(out, this); + Dumpable.dumpMapEntries(out, indent, _map, true); + } + + @Override + public String toString() + { + return String.format("%s@%x{size=%d}",this.getClass().getSimpleName(),hashCode(),_map.size()); + } +} diff --git a/jetty-util/src/main/java/org/eclipse/jetty/util/component/Container.java b/jetty-util/src/main/java/org/eclipse/jetty/util/component/Container.java index 7ead27df1c5..805b0814215 100644 --- a/jetty-util/src/main/java/org/eclipse/jetty/util/component/Container.java +++ b/jetty-util/src/main/java/org/eclipse/jetty/util/component/Container.java @@ -132,7 +132,7 @@ public interface Container /** * @param clazz the class of the beans - * @return the list of beans of the given class from the entire managed hierarchy + * @return the list of beans of the given class from the entire Container hierarchy * @param the Bean type */ public Collection getContainedBeans(Class clazz); diff --git a/jetty-util/src/main/java/org/eclipse/jetty/util/component/ContainerLifeCycle.java b/jetty-util/src/main/java/org/eclipse/jetty/util/component/ContainerLifeCycle.java index 9f5483eac8a..8f3bcff06dd 100644 --- a/jetty-util/src/main/java/org/eclipse/jetty/util/component/ContainerLifeCycle.java +++ b/jetty-util/src/main/java/org/eclipse/jetty/util/component/ContainerLifeCycle.java @@ -550,13 +550,17 @@ public class ContainerLifeCycle extends AbstractLifeCycle implements Container, @Override public Collection getBeans(Class clazz) { - ArrayList beans = new ArrayList<>(); + ArrayList beans = null; for (Bean b : _beans) { if (clazz.isInstance(b._bean)) + { + if (beans == null) + beans = new ArrayList<>(); beans.add(clazz.cast(b._bean)); + } } - return beans; + return beans == null ? Collections.emptyList() : beans; } @Override @@ -879,7 +883,7 @@ public class ContainerLifeCycle extends AbstractLifeCycle implements Container, /** * @param clazz the class of the beans - * @return the list of beans of the given class from the entire managed hierarchy + * @return the list of beans of the given class from the entire Container hierarchy * @param the Bean type */ @Override @@ -893,7 +897,7 @@ public class ContainerLifeCycle extends AbstractLifeCycle implements Container, /** * @param clazz the class of the beans * @param the Bean type - * @param beans the collection to add beans of the given class from the entire managed hierarchy + * @param beans the collection to add beans of the given class from the entire Container hierarchy */ protected void getContainedBeans(Class clazz, Collection beans) { diff --git a/jetty-util/src/main/java/org/eclipse/jetty/util/component/Dumpable.java b/jetty-util/src/main/java/org/eclipse/jetty/util/component/Dumpable.java index 1e973f3f5c6..7908bf48adf 100644 --- a/jetty-util/src/main/java/org/eclipse/jetty/util/component/Dumpable.java +++ b/jetty-util/src/main/java/org/eclipse/jetty/util/component/Dumpable.java @@ -93,18 +93,19 @@ public interface Dumpable String s; if (o==null) s = "null"; - else if (o instanceof Collection) - s = String.format("%s@%x(size=%d)",o.getClass().getName(),o.hashCode(),((Collection)o).size()); - else if (o.getClass().isArray()) - s = String.format("%s@%x[size=%d]",o.getClass().getComponentType(),o.hashCode(), Array.getLength(o)); - else if (o instanceof Map) - s = String.format("%s@%x{size=%d}",o.getClass().getName(),o.hashCode(),((Map)o).size()); else if (o instanceof Dumpable) { s = ((Dumpable)o).dumpSelf(); s = StringUtil.replace(s, "\r\n", "|"); s = StringUtil.replace(s, '\n', '|'); } + else if (o instanceof Collection) + s = String.format("%s@%x(size=%d)",o.getClass().getName(),o.hashCode(),((Collection)o).size()); + else if (o.getClass().isArray()) + s = String.format("%s@%x[size=%d]",o.getClass().getComponentType(),o.hashCode(), Array.getLength(o)); + else if (o instanceof Map) + s = String.format("%s@%x{size=%d}",o.getClass().getName(),o.hashCode(),((Map)o).size()); + else { s = String.valueOf(o); @@ -139,7 +140,7 @@ public interface Dumpable { dumpObject(out,object); - int size = extraChildren==null?0:extraChildren.length; + int extras = extraChildren==null?0:extraChildren.length; if (object instanceof Stream) object = ((Stream)object).toArray(); @@ -148,87 +149,25 @@ public interface Dumpable if (object instanceof Container) { - Container container = (Container)object; - ContainerLifeCycle containerLifeCycle = container instanceof ContainerLifeCycle ? (ContainerLifeCycle)container : null; - for (Iterator i = container.getBeans().iterator(); i.hasNext();) - { - Object bean = i.next(); - String nextIndent = indent + ((i.hasNext() || size>0) ? "| " : " "); - if (bean instanceof LifeCycle) - { - if (container.isManaged(bean)) - { - out.append(indent).append("+= "); - if (bean instanceof Dumpable) - ((Dumpable)bean).dump(out,nextIndent); - else - dumpObjects(out, nextIndent, bean); - } - else if (containerLifeCycle != null && containerLifeCycle.isAuto(bean)) - { - out.append(indent).append("+? "); - if (bean instanceof Dumpable) - ((Dumpable)bean).dump(out,nextIndent); - else - dumpObjects(out, nextIndent, bean); - } - else - { - out.append(indent).append("+~ "); - dumpObject(out, bean); - } - } - else if (containerLifeCycle != null && containerLifeCycle.isUnmanaged(bean)) - { - out.append(indent).append("+~ "); - dumpObject(out, bean); - } - else - { - out.append(indent).append("+- "); - if (bean instanceof Dumpable) - ((Dumpable)bean).dump(out,nextIndent); - else - dumpObjects(out, nextIndent, bean); - } - } + dumpContainer(out, indent, (Container)object, extras==0); } if (object instanceof Iterable) { - for (Iterator i = ((Iterable)object).iterator(); i.hasNext();) - { - Object item = i.next(); - String nextIndent = indent + ((i.hasNext() || size>0) ? "| " : " "); - out.append(indent).append("+: "); - if (item instanceof Dumpable) - ((Dumpable)item).dump(out,nextIndent); - else - dumpObjects(out,nextIndent, item); - } + dumpIterable(out, indent, (Iterable)object, extras==0); } else if (object instanceof Map) { - for (Iterator> i = ((Map)object).entrySet().iterator(); i.hasNext();) - { - Map.Entry entry = i.next(); - String nextIndent = indent + ((i.hasNext() || size>0) ? "| " : " "); - out.append(indent).append("+@ ").append(String.valueOf(entry.getKey())).append('='); - Object item = entry.getValue(); - if (item instanceof Dumpable) - ((Dumpable)item).dump(out,nextIndent); - else - dumpObjects(out,nextIndent, item); - } + dumpMapEntries(out, indent, (Map)object, extras==0); } - if (size==0) + if (extras==0) return; int i = 0; for (Object item : extraChildren) { i++; - String nextIndent = indent + (i "); if (item instanceof Dumpable) ((Dumpable)item).dump(out,nextIndent); @@ -236,4 +175,91 @@ public interface Dumpable dumpObjects(out, nextIndent, item); } } + + static void dumpContainer(Appendable out, String indent, Container object, boolean last) throws IOException + { + Container container = object; + ContainerLifeCycle containerLifeCycle = container instanceof ContainerLifeCycle ? (ContainerLifeCycle)container : null; + for (Iterator i = container.getBeans().iterator(); i.hasNext();) + { + Object bean = i.next(); + String nextIndent = indent + ((i.hasNext() || !last) ? "| " : " "); + if (bean instanceof LifeCycle) + { + if (container.isManaged(bean)) + { + out.append(indent).append("+= "); + if (bean instanceof Dumpable) + ((Dumpable)bean).dump(out,nextIndent); + else + dumpObjects(out, nextIndent, bean); + } + else if (containerLifeCycle != null && containerLifeCycle.isAuto(bean)) + { + out.append(indent).append("+? "); + if (bean instanceof Dumpable) + ((Dumpable)bean).dump(out,nextIndent); + else + dumpObjects(out, nextIndent, bean); + } + else + { + out.append(indent).append("+~ "); + dumpObject(out, bean); + } + } + else if (containerLifeCycle != null && containerLifeCycle.isUnmanaged(bean)) + { + out.append(indent).append("+~ "); + dumpObject(out, bean); + } + else + { + out.append(indent).append("+- "); + if (bean instanceof Dumpable) + ((Dumpable)bean).dump(out,nextIndent); + else + dumpObjects(out, nextIndent, bean); + } + } + } + + static void dumpIterable(Appendable out, String indent, Iterable iterable, boolean last) throws IOException + { + for (Iterator i = iterable.iterator(); i.hasNext();) + { + Object item = i.next(); + String nextIndent = indent + ((i.hasNext() || !last) ? "| " : " "); + out.append(indent).append("+: "); + if (item instanceof Dumpable) + ((Dumpable)item).dump(out,nextIndent); + else + dumpObjects(out,nextIndent, item); + } + + } + + static void dumpMapEntries(Appendable out, String indent, Map map, boolean last) throws IOException + { + for (Iterator> i = map.entrySet().iterator(); i.hasNext();) + { + Map.Entry entry = i.next(); + String nextIndent = indent + ((i.hasNext() || !last) ? "| " : " "); + out.append(indent).append("+@ ").append(String.valueOf(entry.getKey())).append(" = "); + Object item = entry.getValue(); + if (item instanceof Dumpable) + ((Dumpable)item).dump(out,nextIndent); + else + dumpObjects(out,nextIndent, item); + } + } + + static Dumpable named(String name, Object object) + { + return (out, indent) -> + { + out.append(name).append(": "); + Dumpable.dumpObjects(out, indent, object); + }; + } } diff --git a/jetty-webapp/src/main/java/org/eclipse/jetty/webapp/WebAppClassLoader.java b/jetty-webapp/src/main/java/org/eclipse/jetty/webapp/WebAppClassLoader.java index a96bc416363..a6bfc75eaf8 100644 --- a/jetty-webapp/src/main/java/org/eclipse/jetty/webapp/WebAppClassLoader.java +++ b/jetty-webapp/src/main/java/org/eclipse/jetty/webapp/WebAppClassLoader.java @@ -724,7 +724,7 @@ public class WebAppClassLoader extends URLClassLoader implements ClassVisibility @Override public String toString() { - return "WebAppClassLoader=" + _name+"@"+Long.toHexString(hashCode()); + return String.format("%s{%s}@%x", this.getClass().getSimpleName(), _name, hashCode()); } @Override diff --git a/jetty-webapp/src/main/java/org/eclipse/jetty/webapp/WebAppContext.java b/jetty-webapp/src/main/java/org/eclipse/jetty/webapp/WebAppContext.java index b38334fd0ff..6c15f207c75 100644 --- a/jetty-webapp/src/main/java/org/eclipse/jetty/webapp/WebAppContext.java +++ b/jetty-webapp/src/main/java/org/eclipse/jetty/webapp/WebAppContext.java @@ -34,7 +34,6 @@ import java.util.HashSet; import java.util.List; import java.util.Map; import java.util.Set; - import javax.servlet.ServletContext; import javax.servlet.ServletRegistration.Dynamic; import javax.servlet.ServletSecurityElement; @@ -1040,15 +1039,10 @@ public class WebAppContext extends ServletContextHandler implements WebAppClassL public String toString() { if (_war!=null) - { - String war=_war; - if (war.indexOf("/webapps/")>=0) - war=war.substring(war.indexOf("/webapps/")+8); - return super.toString()+"{"+war+"}"; - } + return super.toString()+"{"+_war+"}"; return super.toString(); } - + /* ------------------------------------------------------------ */ @Override public void dump(Appendable out, String indent) throws IOException @@ -1066,15 +1060,39 @@ public class WebAppContext extends ServletContextHandler implements WebAppClassL server_classes=new ArrayList<>(_serverClasses); Collections.sort(server_classes); } - + + String name = getDisplayName(); + if (name == null) + { + if (_war != null) + { + if (_war.indexOf("/webapps/") >= 0) + name = _war.substring(_war.indexOf("/webapps/") + 8); + else + name = _war; + } + else if (getResourceBase() != null) + { + name = getResourceBase(); + if (name.indexOf("/webapps/") >= 0) + name = name.substring(name.indexOf("/webapps/") + 8); + } + else + { + name = this.getClass().getSimpleName(); + } + } + + name = String.format("%s@%x", name, hashCode()); + dumpObjects(out,indent, new ClassLoaderDump(getClassLoader()), - new DumpableCollection("Systemclasses "+this,system_classes), - new DumpableCollection("Serverclasses "+this,server_classes), - new DumpableCollection("Configurations "+this,_configurations), - new DumpableCollection("Handler attributes "+this,((AttributesMap)getAttributes()).getAttributeEntrySet()), - new DumpableCollection("Context attributes "+this,((Context)getServletContext()).getAttributeEntrySet()), - new DumpableCollection("Initparams "+this,getInitParams().entrySet()) + new DumpableCollection("Systemclasses " + name, system_classes), + new DumpableCollection("Serverclasses " + name, server_classes), + new DumpableCollection("Configurations " + name, _configurations), + new DumpableCollection("Handler attributes " + name, ((AttributesMap)getAttributes()).getAttributeEntrySet()), + new DumpableCollection("Context attributes " + name, ((Context)getServletContext()).getAttributeEntrySet()), + new DumpableCollection("Initparams " + name, getInitParams().entrySet()) ); } From cd38756ef5ace34610d3dcfd2fafc4a8eb87b660 Mon Sep 17 00:00:00 2001 From: Greg Wilkins Date: Tue, 18 Jun 2019 09:51:54 +0200 Subject: [PATCH 3/3] fixed formatting from merge Signed-off-by: Greg Wilkins --- .../src/main/java/org/eclipse/jetty/util/component/Dumpable.java | 1 - 1 file changed, 1 deletion(-) diff --git a/jetty-util/src/main/java/org/eclipse/jetty/util/component/Dumpable.java b/jetty-util/src/main/java/org/eclipse/jetty/util/component/Dumpable.java index 7908bf48adf..f1819cbb8de 100644 --- a/jetty-util/src/main/java/org/eclipse/jetty/util/component/Dumpable.java +++ b/jetty-util/src/main/java/org/eclipse/jetty/util/component/Dumpable.java @@ -105,7 +105,6 @@ public interface Dumpable s = String.format("%s@%x[size=%d]",o.getClass().getComponentType(),o.hashCode(), Array.getLength(o)); else if (o instanceof Map) s = String.format("%s@%x{size=%d}",o.getClass().getName(),o.hashCode(),((Map)o).size()); - else { s = String.valueOf(o);