Skip to main content
aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorEike Stepper2020-06-09 08:59:51 +0000
committerEike Stepper2020-06-09 08:59:51 +0000
commit51cce8a6e95333921535374b2934659d852c8f19 (patch)
treec6d684fd6734efc7f7fa4dbd723f138104674879
parentd62e181f7b4001dfe47e682c49bdfd5e818ee08b (diff)
downloadcdo-51cce8a6e95333921535374b2934659d852c8f19.tar.gz
cdo-51cce8a6e95333921535374b2934659d852c8f19.tar.xz
cdo-51cce8a6e95333921535374b2934659d852c8f19.zip
[Releng] Add schema access tracking option
-rw-r--r--features/org.eclipse.net4j.util-feature/feature.xml2
-rw-r--r--features/org.eclipse.net4j.util-feature/pom.xml2
-rw-r--r--plugins/org.eclipse.net4j.db/src/org/eclipse/net4j/internal/db/DBConnection.java61
-rw-r--r--plugins/org.eclipse.net4j.db/src/org/eclipse/net4j/internal/db/DBDatabase.java165
-rw-r--r--plugins/org.eclipse.net4j.db/src/org/eclipse/net4j/internal/db/DBPreparedStatement.java9
-rw-r--r--plugins/org.eclipse.net4j.tests/src/org/eclipse/net4j/util/tests/AbstractOMTest.java2
-rw-r--r--plugins/org.eclipse.net4j.util/META-INF/MANIFEST.MF62
-rw-r--r--plugins/org.eclipse.net4j.util/pom.xml2
-rw-r--r--plugins/org.eclipse.net4j.util/src/org/eclipse/net4j/internal/util/test/CurrentTestName.java33
-rw-r--r--plugins/org.eclipse.net4j.util/src/org/eclipse/net4j/util/ReflectUtil.java11
10 files changed, 267 insertions, 82 deletions
diff --git a/features/org.eclipse.net4j.util-feature/feature.xml b/features/org.eclipse.net4j.util-feature/feature.xml
index 5df13cda42..66c0912b84 100644
--- a/features/org.eclipse.net4j.util-feature/feature.xml
+++ b/features/org.eclipse.net4j.util-feature/feature.xml
@@ -12,7 +12,7 @@
<feature
id="org.eclipse.net4j.util"
label="%featureName"
- version="4.9.1.qualifier"
+ version="4.10.0.qualifier"
provider-name="%providerName"
image="eclipse_update_120.jpg"
license-feature="org.eclipse.emf.cdo.license"
diff --git a/features/org.eclipse.net4j.util-feature/pom.xml b/features/org.eclipse.net4j.util-feature/pom.xml
index fb5d77f1c7..894e0591e1 100644
--- a/features/org.eclipse.net4j.util-feature/pom.xml
+++ b/features/org.eclipse.net4j.util-feature/pom.xml
@@ -25,7 +25,7 @@
<groupId>org.eclipse.emf.cdo.features</groupId>
<artifactId>org.eclipse.net4j.util</artifactId>
- <version>4.9.1-SNAPSHOT</version>
+ <version>4.10.0-SNAPSHOT</version>
<packaging>eclipse-feature</packaging>
</project>
diff --git a/plugins/org.eclipse.net4j.db/src/org/eclipse/net4j/internal/db/DBConnection.java b/plugins/org.eclipse.net4j.db/src/org/eclipse/net4j/internal/db/DBConnection.java
index 1564cdcabc..a7f1f82f56 100644
--- a/plugins/org.eclipse.net4j.db/src/org/eclipse/net4j/internal/db/DBConnection.java
+++ b/plugins/org.eclipse.net4j.db/src/org/eclipse/net4j/internal/db/DBConnection.java
@@ -137,43 +137,53 @@ public final class DBConnection extends DelegatingConnection implements IDBConne
@Override
public IDBPreparedStatement prepareStatement(String sql, int resultSetType, int resultSetConcurrency, ReuseProbability reuseProbability)
{
- database.beginSchemaAccess(false);
+ Object schemaAccessToken = database.beginSchemaAccess(false);
- DBPreparedStatement preparedStatement;
- synchronized (this)
+ try
{
- preparedStatement = cache.remove(sql);
- if (preparedStatement == null)
+ DBPreparedStatement preparedStatement;
+ synchronized (this)
{
- try
+ preparedStatement = cache.remove(sql);
+ if (preparedStatement == null)
{
- PreparedStatement delegate = getDelegate().prepareStatement(sql, resultSetType, resultSetConcurrency);
- preparedStatement = new DBPreparedStatement(this, sql, reuseProbability, delegate);
+ try
+ {
+ PreparedStatement delegate = getDelegate().prepareStatement(sql, resultSetType, resultSetConcurrency);
+ preparedStatement = new DBPreparedStatement(this, sql, reuseProbability, delegate);
+ }
+ catch (SQLException ex)
+ {
+ throw new DBException(ex);
+ }
}
- catch (SQLException ex)
+ else
{
- throw new DBException(ex);
+ --cacheSize;
+
+ DBPreparedStatement nextCached = preparedStatement.getNextCached();
+ if (nextCached != null)
+ {
+ cache.put(sql, nextCached);
+ preparedStatement.setNextCached(null);
+ }
}
- }
- else
- {
- --cacheSize;
- DBPreparedStatement nextCached = preparedStatement.getNextCached();
- if (nextCached != null)
+ if (VALIDATE_CHECKOUTS)
{
- cache.put(sql, nextCached);
- preparedStatement.setNextCached(null);
+ checkOuts.add(preparedStatement);
}
}
- if (VALIDATE_CHECKOUTS)
- {
- checkOuts.add(preparedStatement);
- }
- }
+ preparedStatement.setSchemaAccessToken(schemaAccessToken);
- return preparedStatement;
+ return preparedStatement;
+ }
+ catch (RuntimeException | Error ex)
+ {
+ database.endSchemaAccess(schemaAccessToken);
+ throw ex;
+ }
}
@Override
@@ -232,7 +242,8 @@ public final class DBConnection extends DelegatingConnection implements IDBConne
}
finally
{
- database.endSchemaAccess();
+ Object schemaAccessToken = preparedStatement.setSchemaAccessToken(null);
+ database.endSchemaAccess(schemaAccessToken);
}
}
diff --git a/plugins/org.eclipse.net4j.db/src/org/eclipse/net4j/internal/db/DBDatabase.java b/plugins/org.eclipse.net4j.db/src/org/eclipse/net4j/internal/db/DBDatabase.java
index e7a41861f7..b16e5509e0 100644
--- a/plugins/org.eclipse.net4j.db/src/org/eclipse/net4j/internal/db/DBDatabase.java
+++ b/plugins/org.eclipse.net4j.db/src/org/eclipse/net4j/internal/db/DBDatabase.java
@@ -21,6 +21,8 @@ import org.eclipse.net4j.db.ddl.delta.IDBSchemaDelta;
import org.eclipse.net4j.internal.db.ddl.delta.DBSchemaDelta;
import org.eclipse.net4j.spi.db.DBAdapter;
import org.eclipse.net4j.spi.db.ddl.InternalDBSchema;
+import org.eclipse.net4j.util.ReflectUtil;
+import org.eclipse.net4j.util.StringUtil;
import org.eclipse.net4j.util.WrappedException;
import org.eclipse.net4j.util.concurrent.TimeoutRuntimeException;
import org.eclipse.net4j.util.container.SetContainer;
@@ -31,7 +33,9 @@ import org.eclipse.net4j.util.security.IUserAware;
import java.sql.Connection;
import java.sql.SQLException;
+import java.util.LinkedHashMap;
import java.util.LinkedList;
+import java.util.Map;
/**
* @author Eike Stepper
@@ -42,6 +46,8 @@ public final class DBDatabase extends SetContainer<IDBConnection> implements IDB
private static final boolean DEBUG_SCHEMA_ACCESS = OMPlatform.INSTANCE.isProperty("org.eclipse.net4j.internal.db.DBDatabase.DEBUG_SCHEMA_ACCESS");
+ private static final boolean TRACK_SCHEMA_ACCESS = true || OMPlatform.INSTANCE.isProperty("org.eclipse.net4j.internal.db.DBDatabase.TRACK_SCHEMA_ACCESS");
+
private DBAdapter adapter;
private IDBConnectionProvider connectionProvider;
@@ -52,7 +58,7 @@ public final class DBDatabase extends SetContainer<IDBConnection> implements IDB
private final LinkedList<SchemaAccess> schemaAccessQueue = new LinkedList<>();
- private int schemaWriters;
+ private int waitingSchemaWriters;
public DBDatabase(final DBAdapter adapter, IDBConnectionProvider connectionProvider, final String schemaName, final boolean fixNullableIndexColumns)
{
@@ -117,9 +123,11 @@ public final class DBDatabase extends SetContainer<IDBConnection> implements IDB
return;
}
+ Object schemaAccessToken = null;
+
try
{
- beginSchemaAccess(true);
+ schemaAccessToken = beginSchemaAccess(true);
for (IDBConnection transaction : getConnections())
{
@@ -130,7 +138,7 @@ public final class DBDatabase extends SetContainer<IDBConnection> implements IDB
}
finally
{
- endSchemaAccess();
+ endSchemaAccess(schemaAccessToken);
}
}
@@ -220,7 +228,7 @@ public final class DBDatabase extends SetContainer<IDBConnection> implements IDB
super.doDeactivate();
}
- public void beginSchemaAccess(boolean write)
+ public Object beginSchemaAccess(boolean write)
{
if (DEBUG_SCHEMA_ACCESS)
{
@@ -234,24 +242,26 @@ public final class DBDatabase extends SetContainer<IDBConnection> implements IDB
}
}
+ Object token = null;
SchemaAccess schemaAccess = null;
synchronized (schemaAccessQueue)
{
if (write)
{
- schemaAccess = new WriteSchemaAccess();
+ schemaAccess = createWriteSchemaAccess();
+ token = schemaAccess;
schemaAccessQueue.addLast(schemaAccess);
- ++schemaWriters;
+ ++waitingSchemaWriters;
}
else
{
- if (schemaWriters == 0 && !schemaAccessQueue.isEmpty())
+ if (waitingSchemaWriters == 0 && !schemaAccessQueue.isEmpty())
{
schemaAccess = schemaAccessQueue.getFirst();
if (schemaAccess instanceof ReadSchemaAccess)
{
ReadSchemaAccess readSchemaAccess = (ReadSchemaAccess)schemaAccess;
- readSchemaAccess.incrementReaders();
+ token = readSchemaAccess.addReader();
}
else
{
@@ -261,7 +271,10 @@ public final class DBDatabase extends SetContainer<IDBConnection> implements IDB
if (schemaAccess == null)
{
- schemaAccess = new ReadSchemaAccess();
+ ReadSchemaAccess readSchemaAccess = createReadSchemaAccess();
+ token = readSchemaAccess.addReader();
+
+ schemaAccess = readSchemaAccess;
schemaAccessQueue.addLast(schemaAccess);
}
}
@@ -279,10 +292,10 @@ public final class DBDatabase extends SetContainer<IDBConnection> implements IDB
{
if (write)
{
- --schemaWriters;
+ --waitingSchemaWriters;
}
- return;
+ return token;
}
try
@@ -301,7 +314,7 @@ public final class DBDatabase extends SetContainer<IDBConnection> implements IDB
+ TIMEOUT_SCHEMA_ACCESS + " milliseconds. Active access: " + activeSchemaAccess);
}
- public void endSchemaAccess()
+ public void endSchemaAccess(Object token)
{
if (DEBUG_SCHEMA_ACCESS)
{
@@ -317,11 +330,11 @@ public final class DBDatabase extends SetContainer<IDBConnection> implements IDB
synchronized (schemaAccessQueue)
{
- SchemaAccess schemaAccess = schemaAccessQueue.getFirst();
- if (schemaAccess instanceof ReadSchemaAccess)
+ SchemaAccess activeSchemaAccess = schemaAccessQueue.getFirst();
+ if (activeSchemaAccess instanceof ReadSchemaAccess)
{
- ReadSchemaAccess readSchemaAccess = (ReadSchemaAccess)schemaAccess;
- if (readSchemaAccess.decrementReaders())
+ ReadSchemaAccess readSchemaAccess = (ReadSchemaAccess)activeSchemaAccess;
+ if (readSchemaAccess.removeReader(token))
{
return;
}
@@ -347,6 +360,26 @@ public final class DBDatabase extends SetContainer<IDBConnection> implements IDB
return adapter.convertString(resultSet, columnLabel, value);
}
+ private ReadSchemaAccess createReadSchemaAccess()
+ {
+ if (TRACK_SCHEMA_ACCESS)
+ {
+ return new ReadSchemaAccess.Tracked();
+ }
+
+ return new ReadSchemaAccess();
+ }
+
+ private WriteSchemaAccess createWriteSchemaAccess()
+ {
+ if (TRACK_SCHEMA_ACCESS)
+ {
+ return new WriteSchemaAccess.Tracked();
+ }
+
+ return new WriteSchemaAccess();
+ }
+
/**
* @author Eike Stepper
*/
@@ -357,16 +390,20 @@ public final class DBDatabase extends SetContainer<IDBConnection> implements IDB
/**
* @author Eike Stepper
*/
- private static final class ReadSchemaAccess implements SchemaAccess
+ private static class ReadSchemaAccess implements SchemaAccess
{
- private int readers = 1;
+ private int readers;
- public void incrementReaders()
+ public Object addReader()
{
++readers;
+ return this;
}
- public boolean decrementReaders()
+ /**
+ * @return <code>true</code> if at least one reader remains, <code>false</code> otherwise.
+ */
+ public boolean removeReader(Object token)
{
return --readers > 0;
}
@@ -376,18 +413,104 @@ public final class DBDatabase extends SetContainer<IDBConnection> implements IDB
{
return "READERS[" + readers + "]";
}
+
+ /**
+ * @author Eike Stepper
+ */
+ private static final class Tracked extends ReadSchemaAccess
+ {
+ private final Map<Object, Exception> stackTraces = new LinkedHashMap<>();
+
+ public Tracked()
+ {
+ }
+
+ @Override
+ public Object addReader()
+ {
+ Object token = new Object();
+ Exception stackTrace;
+
+ try
+ {
+ throw new Exception();
+ }
+ catch (Exception ex)
+ {
+ stackTrace = ex;
+ }
+
+ stackTraces.put(token, stackTrace);
+ super.addReader();
+ return token;
+ }
+
+ @Override
+ public boolean removeReader(Object token)
+ {
+ stackTraces.remove(token);
+ return super.removeReader(token);
+ }
+
+ @Override
+ public String toString()
+ {
+ StringBuilder builder = new StringBuilder(super.toString());
+ builder.append(" --> Read access(es) started here:");
+ builder.append(StringUtil.NL);
+
+ for (Exception stackTrace : stackTraces.values())
+ {
+ ReflectUtil.appendStackTrace(builder, stackTrace.getStackTrace());
+ builder.append(StringUtil.NL);
+ }
+
+ return builder.toString();
+ }
+ }
}
/**
* @author Eike Stepper
*/
- private static final class WriteSchemaAccess implements SchemaAccess
+ private static class WriteSchemaAccess implements SchemaAccess
{
@Override
public String toString()
{
return "WRITER";
}
+
+ /**
+ * @author Eike Stepper
+ */
+ private static final class Tracked extends WriteSchemaAccess
+ {
+ private final Exception stackTrace;
+
+ public Tracked()
+ {
+ try
+ {
+ throw new Exception();
+ }
+ catch (Exception ex)
+ {
+ stackTrace = ex;
+ }
+ }
+
+ @Override
+ public String toString()
+ {
+ StringBuilder builder = new StringBuilder(super.toString());
+ builder.append(" --> Write access started here:");
+ builder.append(StringUtil.NL);
+ ReflectUtil.appendStackTrace(builder, stackTrace.getStackTrace());
+ builder.append(StringUtil.NL);
+ return builder.toString();
+ }
+ }
}
/**
diff --git a/plugins/org.eclipse.net4j.db/src/org/eclipse/net4j/internal/db/DBPreparedStatement.java b/plugins/org.eclipse.net4j.db/src/org/eclipse/net4j/internal/db/DBPreparedStatement.java
index 84195474e7..c99305947e 100644
--- a/plugins/org.eclipse.net4j.db/src/org/eclipse/net4j/internal/db/DBPreparedStatement.java
+++ b/plugins/org.eclipse.net4j.db/src/org/eclipse/net4j/internal/db/DBPreparedStatement.java
@@ -32,6 +32,8 @@ public class DBPreparedStatement extends DelegatingPreparedStatement implements
private DBPreparedStatement nextCached;
+ private Object schemaAccessToken;
+
public DBPreparedStatement(DBConnection transaction, String sql, ReuseProbability reuseProbability, PreparedStatement delegate)
{
super(delegate, transaction);
@@ -151,4 +153,11 @@ public class DBPreparedStatement extends DelegatingPreparedStatement implements
{
return getConnection().convertString(resultSet, columnLabel, value);
}
+
+ Object setSchemaAccessToken(Object schemaAccessToken)
+ {
+ Object oldSchemaAccessToken = this.schemaAccessToken;
+ this.schemaAccessToken = schemaAccessToken;
+ return oldSchemaAccessToken;
+ }
}
diff --git a/plugins/org.eclipse.net4j.tests/src/org/eclipse/net4j/util/tests/AbstractOMTest.java b/plugins/org.eclipse.net4j.tests/src/org/eclipse/net4j/util/tests/AbstractOMTest.java
index 51df3f79e0..84bb30d21b 100644
--- a/plugins/org.eclipse.net4j.tests/src/org/eclipse/net4j/util/tests/AbstractOMTest.java
+++ b/plugins/org.eclipse.net4j.tests/src/org/eclipse/net4j/util/tests/AbstractOMTest.java
@@ -10,6 +10,7 @@
*/
package org.eclipse.net4j.util.tests;
+import org.eclipse.net4j.internal.util.test.CurrentTestName;
import org.eclipse.net4j.internal.util.test.TestExecuter;
import org.eclipse.net4j.tests.bundle.OM;
import org.eclipse.net4j.util.ReflectUtil;
@@ -177,6 +178,7 @@ public abstract class AbstractOMTest extends TestCase
public void setUp() throws Exception
{
testName = getClass().getName() + "." + getName() + "()";
+ CurrentTestName.set(testName);
codeLink = null;
PrintTraceHandler.CONSOLE.setShortContext(true);
diff --git a/plugins/org.eclipse.net4j.util/META-INF/MANIFEST.MF b/plugins/org.eclipse.net4j.util/META-INF/MANIFEST.MF
index a119efdeb3..519798df43 100644
--- a/plugins/org.eclipse.net4j.util/META-INF/MANIFEST.MF
+++ b/plugins/org.eclipse.net4j.util/META-INF/MANIFEST.MF
@@ -1,7 +1,7 @@
Manifest-Version: 1.0
Bundle-ManifestVersion: 2
Bundle-SymbolicName: org.eclipse.net4j.util;singleton:=true
-Bundle-Version: 3.10.1.qualifier
+Bundle-Version: 3.11.0.qualifier
Bundle-Name: %pluginName
Bundle-Vendor: %providerName
Bundle-Localization: plugin
@@ -15,35 +15,35 @@ Import-Package: org.eclipse.osgi.service.debug;version="[1.0.0,2.0.0)";resolutio
org.osgi.framework;version="[1.3.0,2.0.0)";resolution:=optional,
org.osgi.service.log;version="[1.3.0,2.0.0)";resolution:=optional,
org.osgi.util.tracker;version="[1.3.0,2.0.0)";resolution:=optional
-Export-Package: org.eclipse.net4j.internal.util.bundle;version="3.10.1";x-friends:="org.eclipse.net4j.util.ui,org.eclipse.net4j.tests",
- org.eclipse.net4j.internal.util.container;version="3.10.1";x-internal:=true,
- org.eclipse.net4j.internal.util.factory;version="3.10.1";x-internal:=true,
- org.eclipse.net4j.internal.util.om;version="3.10.1";x-internal:=true,
- org.eclipse.net4j.internal.util.om.pref;version="3.10.1";x-internal:=true,
- org.eclipse.net4j.internal.util.table;version="3.10.1";x-internal:=true,
- org.eclipse.net4j.internal.util.test;version="3.10.1";x-friends:="org.eclipse.net4j.tests",
- org.eclipse.net4j.util;version="3.10.1",
- org.eclipse.net4j.util.cache;version="3.10.1",
- org.eclipse.net4j.util.collection;version="3.10.1",
- org.eclipse.net4j.util.concurrent;version="3.10.1",
- org.eclipse.net4j.util.confirmation;version="3.10.1",
- org.eclipse.net4j.util.container;version="3.10.1",
- org.eclipse.net4j.util.container.delegate;version="3.10.1",
- org.eclipse.net4j.util.event;version="3.10.1",
- org.eclipse.net4j.util.factory;version="3.10.1",
- org.eclipse.net4j.util.fsm;version="3.10.1",
- org.eclipse.net4j.util.io;version="3.10.1",
- org.eclipse.net4j.util.lifecycle;version="3.10.1",
- org.eclipse.net4j.util.om;version="3.10.1",
- org.eclipse.net4j.util.om.log;version="3.10.1",
- org.eclipse.net4j.util.om.monitor;version="3.10.1",
- org.eclipse.net4j.util.om.pref;version="3.10.1",
- org.eclipse.net4j.util.om.trace;version="3.10.1",
- org.eclipse.net4j.util.options;version="3.10.1",
- org.eclipse.net4j.util.properties;version="3.10.1",
- org.eclipse.net4j.util.ref;version="3.10.1",
- org.eclipse.net4j.util.registry;version="3.10.1",
- org.eclipse.net4j.util.security;version="3.10.1",
- org.eclipse.net4j.util.transaction;version="3.10.1"
+Export-Package: org.eclipse.net4j.internal.util.bundle;version="3.11.0";x-friends:="org.eclipse.net4j.util.ui,org.eclipse.net4j.tests",
+ org.eclipse.net4j.internal.util.container;version="3.11.0";x-internal:=true,
+ org.eclipse.net4j.internal.util.factory;version="3.11.0";x-internal:=true,
+ org.eclipse.net4j.internal.util.om;version="3.11.0";x-internal:=true,
+ org.eclipse.net4j.internal.util.om.pref;version="3.11.0";x-internal:=true,
+ org.eclipse.net4j.internal.util.table;version="3.11.0";x-internal:=true,
+ org.eclipse.net4j.internal.util.test;version="3.11.0";x-friends:="org.eclipse.net4j.tests",
+ org.eclipse.net4j.util;version="3.11.0",
+ org.eclipse.net4j.util.cache;version="3.11.0",
+ org.eclipse.net4j.util.collection;version="3.11.0",
+ org.eclipse.net4j.util.concurrent;version="3.11.0",
+ org.eclipse.net4j.util.confirmation;version="3.11.0",
+ org.eclipse.net4j.util.container;version="3.11.0",
+ org.eclipse.net4j.util.container.delegate;version="3.11.0",
+ org.eclipse.net4j.util.event;version="3.11.0",
+ org.eclipse.net4j.util.factory;version="3.11.0",
+ org.eclipse.net4j.util.fsm;version="3.11.0",
+ org.eclipse.net4j.util.io;version="3.11.0",
+ org.eclipse.net4j.util.lifecycle;version="3.11.0",
+ org.eclipse.net4j.util.om;version="3.11.0",
+ org.eclipse.net4j.util.om.log;version="3.11.0",
+ org.eclipse.net4j.util.om.monitor;version="3.11.0",
+ org.eclipse.net4j.util.om.pref;version="3.11.0",
+ org.eclipse.net4j.util.om.trace;version="3.11.0",
+ org.eclipse.net4j.util.options;version="3.11.0",
+ org.eclipse.net4j.util.properties;version="3.11.0",
+ org.eclipse.net4j.util.ref;version="3.11.0",
+ org.eclipse.net4j.util.registry;version="3.11.0",
+ org.eclipse.net4j.util.security;version="3.11.0",
+ org.eclipse.net4j.util.transaction;version="3.11.0"
Eclipse-BuddyPolicy: registered
Automatic-Module-Name: org.eclipse.net4j.util
diff --git a/plugins/org.eclipse.net4j.util/pom.xml b/plugins/org.eclipse.net4j.util/pom.xml
index 141841c262..379473e572 100644
--- a/plugins/org.eclipse.net4j.util/pom.xml
+++ b/plugins/org.eclipse.net4j.util/pom.xml
@@ -25,7 +25,7 @@
<groupId>org.eclipse.emf.cdo</groupId>
<artifactId>org.eclipse.net4j.util</artifactId>
- <version>3.10.1-SNAPSHOT</version>
+ <version>3.11.0-SNAPSHOT</version>
<packaging>eclipse-plugin</packaging>
</project>
diff --git a/plugins/org.eclipse.net4j.util/src/org/eclipse/net4j/internal/util/test/CurrentTestName.java b/plugins/org.eclipse.net4j.util/src/org/eclipse/net4j/internal/util/test/CurrentTestName.java
new file mode 100644
index 0000000000..c5e0d15b4e
--- /dev/null
+++ b/plugins/org.eclipse.net4j.util/src/org/eclipse/net4j/internal/util/test/CurrentTestName.java
@@ -0,0 +1,33 @@
+/*
+ * Copyright (c) 2020 Eike Stepper (Loehne, Germany) and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Eike Stepper - initial API and implementation
+ */
+package org.eclipse.net4j.internal.util.test;
+
+/**
+ * @author Eike Stepper
+ */
+public final class CurrentTestName
+{
+ private static String name;
+
+ public static String get()
+ {
+ return name;
+ }
+
+ public static void set(String name)
+ {
+ CurrentTestName.name = name;
+ }
+
+ private CurrentTestName()
+ {
+ }
+}
diff --git a/plugins/org.eclipse.net4j.util/src/org/eclipse/net4j/util/ReflectUtil.java b/plugins/org.eclipse.net4j.util/src/org/eclipse/net4j/util/ReflectUtil.java
index 8c6d91ef1b..fa91c30a0f 100644
--- a/plugins/org.eclipse.net4j.util/src/org/eclipse/net4j/util/ReflectUtil.java
+++ b/plugins/org.eclipse.net4j.util/src/org/eclipse/net4j/util/ReflectUtil.java
@@ -238,14 +238,21 @@ public final class ReflectUtil
builder.append(StringUtil.NL);
StackTraceElement[] stackTrace = thread.getStackTrace();
+ appendStackTrace(builder, stackTrace);
+ return builder.toString();
+ }
+
+ /**
+ * @since 3.11
+ */
+ public static void appendStackTrace(StringBuilder builder, StackTraceElement[] stackTrace)
+ {
for (int i = 2; i < stackTrace.length; i++)
{
StackTraceElement stackTraceElement = stackTrace[i];
builder.append("\tat " + stackTraceElement); //$NON-NLS-1$
builder.append(StringUtil.NL);
}
-
- return builder.toString();
}
public static void printStackTrace(PrintStream out, StackTraceElement[] stackTrace)

Back to the top