365302: made map of loggers concurrent and shared in abstract
This commit is contained in:
parent
08f4b79a66
commit
564cf7329c
|
@ -5,6 +5,6 @@ contexts:MMBean: Deployed Contexts
|
||||||
appProviders:MMBean: Application Providers
|
appProviders:MMBean: Application Providers
|
||||||
getApps(java.lang.String):MBean:ACTION: List apps that are located at specified App LifeCycle node
|
getApps(java.lang.String):MBean:ACTION: List apps that are located at specified App LifeCycle node
|
||||||
getApps(java.lang.String)[0]:nodeName: Name of the App LifeCycle node
|
getApps(java.lang.String)[0]:nodeName: Name of the App LifeCycle node
|
||||||
requestAppGoal(java.lang.String,java.lang.String) ACTION: Request the app to be moved to the specified App LifeCycle node
|
requestAppGoal(java.lang.String,java.lang.String):ACTION: Request the app to be moved to the specified App LifeCycle node
|
||||||
requestAppGoal(java.lang.String,java.lang.String)[0]:appId:App identifier
|
requestAppGoal(java.lang.String,java.lang.String)[0]:appId:App identifier
|
||||||
requestAppGoal(java.lang.String,java.lang.String)[1]:nodeName:Name of the App LifeCycle node
|
requestAppGoal(java.lang.String,java.lang.String)[1]:nodeName:Name of the App LifeCycle node
|
|
@ -48,11 +48,10 @@
|
||||||
</Call>
|
</Call>
|
||||||
|
|
||||||
<!-- Add the static log -->
|
<!-- Add the static log -->
|
||||||
<Get id="Logger" class="org.eclipse.jetty.util.log.Log" name="log" />
|
|
||||||
<Ref id="MBeanContainer">
|
<Ref id="MBeanContainer">
|
||||||
<Call name="addBean">
|
<Call name="addBean">
|
||||||
<Arg>
|
<Arg>
|
||||||
<Ref id="Logger" />
|
<New class="org.eclipse.jetty.util.log.Log"/>
|
||||||
</Arg>
|
</Arg>
|
||||||
</Call>
|
</Call>
|
||||||
</Ref>
|
</Ref>
|
||||||
|
|
|
@ -0,0 +1,48 @@
|
||||||
|
// ========================================================================
|
||||||
|
// Copyright (c) 2009-2009 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.log.jmx;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import org.eclipse.jetty.jmx.ObjectMBean;
|
||||||
|
import org.eclipse.jetty.util.log.Log;
|
||||||
|
|
||||||
|
/* ------------------------------------------------------------ */
|
||||||
|
/**
|
||||||
|
*/
|
||||||
|
public class LogMBean extends ObjectMBean
|
||||||
|
{
|
||||||
|
|
||||||
|
public LogMBean(Object managedObject)
|
||||||
|
{
|
||||||
|
super(managedObject);
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<String> getLoggers()
|
||||||
|
{
|
||||||
|
List<String> keySet = new ArrayList<String>(Log.getLoggers().keySet());
|
||||||
|
return keySet;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isDebugEnabled(String logger)
|
||||||
|
{
|
||||||
|
return Log.getLogger(logger).isDebugEnabled();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setDebugEnabled(String logger, Boolean enabled)
|
||||||
|
{
|
||||||
|
Log.getLogger(logger).setDebugEnabled(enabled);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,8 @@
|
||||||
|
Log: Jetty Logging implementaton
|
||||||
|
loggers:MBean: List of all instantiated loggers
|
||||||
|
debugEnabled:RW: True if debug enabled for root logger Log.LOG
|
||||||
|
isDebugEnabled(java.lang.String):MBean:INFO: True if debug is enabled for the given logger
|
||||||
|
isDebugEnabled(java.lang.String)[0]:loggerName: Name of the logger to return isDebugEnabled for
|
||||||
|
setDebugEnabled(java.lang.String,java.lang.Boolean):MBean:ACTION: Set debug enabled for the given logger
|
||||||
|
setDebugEnabled(java.lang.String,java.lang.Boolean)[0]:loggerName: Name of the logger to set debug enabled
|
||||||
|
setDebugEnabled(java.lang.String,java.lang.Boolean)[1]:enabled: true to enable debug, false otherwise
|
|
@ -1,3 +0,0 @@
|
||||||
Logger: Jetty Logging implementaton
|
|
||||||
debugEnabled: True if debug enabled
|
|
||||||
name: Logger name
|
|
|
@ -1,2 +1 @@
|
||||||
ThreadMonitor: Detect and report spinning and deadlocked threads
|
ThreadMonitor: Detect and report spinning and deadlocked threads
|
||||||
|
|
||||||
|
|
|
@ -3,4 +3,3 @@ name: RO:Name
|
||||||
displayName: RO:Display Name
|
displayName: RO:Display Name
|
||||||
className: RO:Class Name
|
className: RO:Class Name
|
||||||
initParameters: RO:Initial parameters
|
initParameters: RO:Initial parameters
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,59 @@
|
||||||
|
package org.eclipse.jetty.util.log;
|
||||||
|
|
||||||
|
|
||||||
|
/* ------------------------------------------------------------ */
|
||||||
|
/** Abstract Logger.
|
||||||
|
* Manages the atomic registration of the logger by name.
|
||||||
|
*/
|
||||||
|
public abstract class AbstractLogger implements Logger
|
||||||
|
{
|
||||||
|
public final Logger getLogger(String name)
|
||||||
|
{
|
||||||
|
if (isBlank(name))
|
||||||
|
return this;
|
||||||
|
|
||||||
|
final String basename = getName();
|
||||||
|
final String fullname = (isBlank(basename) || Log.getRootLogger()==this)?name:(basename + "." + name);
|
||||||
|
|
||||||
|
Logger logger = Log.getLoggers().get(fullname);
|
||||||
|
if (logger == null)
|
||||||
|
{
|
||||||
|
Logger newlog = newLogger(fullname);
|
||||||
|
|
||||||
|
logger = Log.getMutableLoggers().putIfAbsent(fullname,newlog);
|
||||||
|
if (logger == null)
|
||||||
|
logger=newlog;
|
||||||
|
}
|
||||||
|
|
||||||
|
return logger;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
protected abstract Logger newLogger(String fullname);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A more robust form of name blank test. Will return true for null names, and names that have only whitespace
|
||||||
|
*
|
||||||
|
* @param name
|
||||||
|
* the name to test
|
||||||
|
* @return true for null or blank name, false if any non-whitespace character is found.
|
||||||
|
*/
|
||||||
|
private static boolean isBlank(String name)
|
||||||
|
{
|
||||||
|
if (name == null)
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
int size = name.length();
|
||||||
|
char c;
|
||||||
|
for (int i = 0; i < size; i++)
|
||||||
|
{
|
||||||
|
c = name.charAt(i);
|
||||||
|
if (!Character.isWhitespace(c))
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
|
@ -28,7 +28,7 @@ import java.util.logging.Level;
|
||||||
* standard java.util.logging configuration</a>.
|
* standard java.util.logging configuration</a>.
|
||||||
* </p>
|
* </p>
|
||||||
*/
|
*/
|
||||||
public class JavaUtilLog implements Logger
|
public class JavaUtilLog extends AbstractLogger
|
||||||
{
|
{
|
||||||
private Level configuredLevel;
|
private Level configuredLevel;
|
||||||
private java.util.logging.Logger _logger;
|
private java.util.logging.Logger _logger;
|
||||||
|
@ -116,9 +116,12 @@ public class JavaUtilLog implements Logger
|
||||||
_logger.log(Level.FINE, msg, thrown);
|
_logger.log(Level.FINE, msg, thrown);
|
||||||
}
|
}
|
||||||
|
|
||||||
public Logger getLogger(String name)
|
/**
|
||||||
|
* Create a Child Logger of this Logger.
|
||||||
|
*/
|
||||||
|
protected Logger newLogger(String fullname)
|
||||||
{
|
{
|
||||||
return new JavaUtilLog(name);
|
return new JavaUtilLog(fullname);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void ignore(Throwable ignored)
|
public void ignore(Throwable ignored)
|
||||||
|
|
|
@ -19,10 +19,14 @@ import java.lang.reflect.Method;
|
||||||
import java.net.URL;
|
import java.net.URL;
|
||||||
import java.security.AccessController;
|
import java.security.AccessController;
|
||||||
import java.security.PrivilegedAction;
|
import java.security.PrivilegedAction;
|
||||||
|
import java.util.Collection;
|
||||||
|
import java.util.Collections;
|
||||||
import java.util.Enumeration;
|
import java.util.Enumeration;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Properties;
|
import java.util.Properties;
|
||||||
|
import java.util.concurrent.ConcurrentHashMap;
|
||||||
|
import java.util.concurrent.ConcurrentMap;
|
||||||
|
|
||||||
import org.eclipse.jetty.util.IO;
|
import org.eclipse.jetty.util.IO;
|
||||||
import org.eclipse.jetty.util.Loader;
|
import org.eclipse.jetty.util.Loader;
|
||||||
|
@ -61,7 +65,11 @@ public class Log
|
||||||
*/
|
*/
|
||||||
public static boolean __ignored;
|
public static boolean __ignored;
|
||||||
|
|
||||||
public static Map<String, Logger> __loggers = new HashMap<String, Logger>();
|
/**
|
||||||
|
* Hold loggers only.
|
||||||
|
*/
|
||||||
|
private final static ConcurrentMap<String, Logger> __loggers = new ConcurrentHashMap<String, Logger>();
|
||||||
|
|
||||||
|
|
||||||
static
|
static
|
||||||
{
|
{
|
||||||
|
@ -427,14 +435,16 @@ public class Log
|
||||||
|
|
||||||
Logger logger = __loggers.get(name);
|
Logger logger = __loggers.get(name);
|
||||||
if(logger==null)
|
if(logger==null)
|
||||||
{
|
|
||||||
logger = LOG.getLogger(name);
|
logger = LOG.getLogger(name);
|
||||||
__loggers.put(name,logger);
|
|
||||||
}
|
|
||||||
|
|
||||||
return logger;
|
return logger;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static ConcurrentMap<String, Logger> getMutableLoggers()
|
||||||
|
{
|
||||||
|
return __loggers;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get a map of all configured {@link Logger} instances.
|
* Get a map of all configured {@link Logger} instances.
|
||||||
*
|
*
|
||||||
|
@ -442,6 +452,6 @@ public class Log
|
||||||
*/
|
*/
|
||||||
public static Map<String, Logger> getLoggers()
|
public static Map<String, Logger> getLoggers()
|
||||||
{
|
{
|
||||||
return __loggers;
|
return Collections.unmodifiableMap(__loggers);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -18,7 +18,7 @@ import java.lang.reflect.Method;
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
public class LoggerLog implements Logger
|
public class LoggerLog extends AbstractLogger
|
||||||
{
|
{
|
||||||
private final Object _logger;
|
private final Object _logger;
|
||||||
private final Method _debugMT;
|
private final Method _debugMT;
|
||||||
|
@ -189,11 +189,14 @@ public class LoggerLog implements Logger
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public Logger getLogger(String name)
|
/**
|
||||||
|
* Create a Child Logger of this Logger.
|
||||||
|
*/
|
||||||
|
protected Logger newLogger(String fullname)
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
Object logger=_getLoggerN.invoke(_logger, name);
|
Object logger=_getLoggerN.invoke(_logger, fullname);
|
||||||
return new LoggerLog(logger);
|
return new LoggerLog(logger);
|
||||||
}
|
}
|
||||||
catch (Exception e)
|
catch (Exception e)
|
||||||
|
|
|
@ -18,7 +18,7 @@ package org.eclipse.jetty.util.log;
|
||||||
/**
|
/**
|
||||||
* Slf4jLog Logger
|
* Slf4jLog Logger
|
||||||
*/
|
*/
|
||||||
public class Slf4jLog implements Logger
|
public class Slf4jLog extends AbstractLogger
|
||||||
{
|
{
|
||||||
private final org.slf4j.Logger _logger;
|
private final org.slf4j.Logger _logger;
|
||||||
|
|
||||||
|
@ -114,9 +114,12 @@ public class Slf4jLog implements Logger
|
||||||
warn("setDebugEnabled not implemented",null,null);
|
warn("setDebugEnabled not implemented",null,null);
|
||||||
}
|
}
|
||||||
|
|
||||||
public Logger getLogger(String name)
|
/**
|
||||||
|
* Create a Child Logger of this Logger.
|
||||||
|
*/
|
||||||
|
protected Logger newLogger(String fullname)
|
||||||
{
|
{
|
||||||
return new Slf4jLog(name);
|
return new Slf4jLog(fullname);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void ignore(Throwable ignored)
|
public void ignore(Throwable ignored)
|
||||||
|
|
|
@ -35,7 +35,7 @@ import org.eclipse.jetty.util.DateCache;
|
||||||
* used for logging. For named debuggers, the system property name+".LONG" is checked. If it is not not set, then
|
* used for logging. For named debuggers, the system property name+".LONG" is checked. If it is not not set, then
|
||||||
* "org.eclipse.jetty.util.log.LONG" is used as the default.
|
* "org.eclipse.jetty.util.log.LONG" is used as the default.
|
||||||
*/
|
*/
|
||||||
public class StdErrLog implements Logger
|
public class StdErrLog extends AbstractLogger
|
||||||
{
|
{
|
||||||
private static final String EOL = System.getProperty("line.separator");
|
private static final String EOL = System.getProperty("line.separator");
|
||||||
private static DateCache _dateCache;
|
private static DateCache _dateCache;
|
||||||
|
@ -45,11 +45,6 @@ public class StdErrLog implements Logger
|
||||||
Log.__props.getProperty("org.eclipse.jetty.util.log.stderr.SOURCE","false")));
|
Log.__props.getProperty("org.eclipse.jetty.util.log.stderr.SOURCE","false")));
|
||||||
private final static boolean __long = Boolean.parseBoolean(Log.__props.getProperty("org.eclipse.jetty.util.log.stderr.LONG","false"));
|
private final static boolean __long = Boolean.parseBoolean(Log.__props.getProperty("org.eclipse.jetty.util.log.stderr.LONG","false"));
|
||||||
|
|
||||||
/**
|
|
||||||
* Tracking for child loggers only.
|
|
||||||
*/
|
|
||||||
private final static ConcurrentMap<String, StdErrLog> __loggers = new ConcurrentHashMap<String, StdErrLog>();
|
|
||||||
|
|
||||||
static
|
static
|
||||||
{
|
{
|
||||||
String deprecatedProperties[] =
|
String deprecatedProperties[] =
|
||||||
|
@ -332,28 +327,22 @@ public class StdErrLog implements Logger
|
||||||
{
|
{
|
||||||
if (enabled)
|
if (enabled)
|
||||||
{
|
{
|
||||||
synchronized (__loggers)
|
this._level = LEVEL_DEBUG;
|
||||||
{
|
|
||||||
this._level = LEVEL_DEBUG;
|
|
||||||
|
|
||||||
// Boot stomp all cached log levels to DEBUG
|
for (Logger log : Log.getLoggers().values())
|
||||||
for(StdErrLog log: __loggers.values())
|
{
|
||||||
{
|
if (log instanceof StdErrLog)
|
||||||
log._level = LEVEL_DEBUG;
|
((StdErrLog)log).setLevel(LEVEL_DEBUG);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
synchronized (__loggers)
|
this._level = this._configuredLevel;
|
||||||
{
|
|
||||||
this._level = this._configuredLevel;
|
|
||||||
|
|
||||||
// restore all cached log configured levels
|
for (Logger log : Log.getLoggers().values())
|
||||||
for(StdErrLog log: __loggers.values())
|
{
|
||||||
{
|
if (log instanceof StdErrLog)
|
||||||
log._level = log._configuredLevel;
|
((StdErrLog)log).setLevel(((StdErrLog)log)._configuredLevel);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -570,67 +559,18 @@ public class StdErrLog implements Logger
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* A more robust form of name blank test. Will return true for null names, and names that have only whitespace
|
|
||||||
*
|
|
||||||
* @param name
|
|
||||||
* the name to test
|
|
||||||
* @return true for null or blank name, false if any non-whitespace character is found.
|
|
||||||
*/
|
|
||||||
private static boolean isBlank(String name)
|
|
||||||
{
|
|
||||||
if (name == null)
|
|
||||||
{
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
int size = name.length();
|
|
||||||
char c;
|
|
||||||
for (int i = 0; i < size; i++)
|
|
||||||
{
|
|
||||||
c = name.charAt(i);
|
|
||||||
if (!Character.isWhitespace(c))
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get a Child Logger relative to this Logger.
|
* Create a Child Logger of this Logger.
|
||||||
*
|
|
||||||
* @param name
|
|
||||||
* the child name
|
|
||||||
* @return the appropriate child logger (if name specified results in a new unique child)
|
|
||||||
*/
|
*/
|
||||||
public Logger getLogger(String name)
|
protected Logger newLogger(String fullname)
|
||||||
{
|
{
|
||||||
if (isBlank(name))
|
StdErrLog logger = new StdErrLog(fullname);
|
||||||
{
|
// Preserve configuration for new loggers configuration
|
||||||
return this;
|
logger.setPrintLongNames(_printLongNames);
|
||||||
}
|
// Let Level come from configured Properties instead - sel.setLevel(_level);
|
||||||
|
logger.setSource(_source);
|
||||||
String fullname = name;
|
logger._stderr = this._stderr;
|
||||||
if (!isBlank(_name))
|
|
||||||
{
|
|
||||||
fullname = _name + "." + name;
|
|
||||||
}
|
|
||||||
|
|
||||||
StdErrLog logger = __loggers.get(fullname);
|
|
||||||
if (logger == null)
|
|
||||||
{
|
|
||||||
StdErrLog sel = new StdErrLog(fullname);
|
|
||||||
// Preserve configuration for new loggers configuration
|
|
||||||
sel.setPrintLongNames(_printLongNames);
|
|
||||||
// Let Level come from configured Properties instead - sel.setLevel(_level);
|
|
||||||
sel.setSource(_source);
|
|
||||||
sel._stderr = this._stderr;
|
|
||||||
logger = __loggers.putIfAbsent(fullname,sel);
|
|
||||||
if (logger == null)
|
|
||||||
{
|
|
||||||
logger = sel;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return logger;
|
return logger;
|
||||||
}
|
}
|
||||||
|
|
|
@ -15,6 +15,9 @@ package org.eclipse.jetty.util.log;
|
||||||
|
|
||||||
import static org.hamcrest.Matchers.is;
|
import static org.hamcrest.Matchers.is;
|
||||||
|
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
import org.junit.AfterClass;
|
import org.junit.AfterClass;
|
||||||
import org.junit.Assert;
|
import org.junit.Assert;
|
||||||
import org.junit.BeforeClass;
|
import org.junit.BeforeClass;
|
||||||
|
@ -23,18 +26,23 @@ import org.junit.Test;
|
||||||
public class LogTest
|
public class LogTest
|
||||||
{
|
{
|
||||||
private static Logger originalLogger;
|
private static Logger originalLogger;
|
||||||
|
private static Map<String,Logger> originalLoggers;
|
||||||
|
|
||||||
@SuppressWarnings("deprecation")
|
@SuppressWarnings("deprecation")
|
||||||
@BeforeClass
|
@BeforeClass
|
||||||
public static void rememberOriginalLogger()
|
public static void rememberOriginalLogger()
|
||||||
{
|
{
|
||||||
originalLogger = Log.getLog();
|
originalLogger = Log.getLog();
|
||||||
|
originalLoggers = new HashMap<String, Logger>(Log.getLoggers());
|
||||||
|
Log.getMutableLoggers().clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
@AfterClass
|
@AfterClass
|
||||||
public static void restoreOriginalLogger()
|
public static void restoreOriginalLogger()
|
||||||
{
|
{
|
||||||
Log.setLog(originalLogger);
|
Log.setLog(originalLogger);
|
||||||
|
Log.getMutableLoggers().clear();
|
||||||
|
Log.getMutableLoggers().putAll(originalLoggers);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
|
|
@ -1,26 +1,9 @@
|
||||||
package org.eclipse.jetty.util.log;
|
package org.eclipse.jetty.util.log;
|
||||||
|
|
||||||
import org.junit.AfterClass;
|
|
||||||
import org.junit.BeforeClass;
|
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
|
|
||||||
public class NamedLogTest
|
public class NamedLogTest
|
||||||
{
|
{
|
||||||
private static Logger originalLogger;
|
|
||||||
|
|
||||||
@SuppressWarnings("deprecation")
|
|
||||||
@BeforeClass
|
|
||||||
public static void rememberOriginalLogger()
|
|
||||||
{
|
|
||||||
originalLogger = Log.getLog();
|
|
||||||
}
|
|
||||||
|
|
||||||
@AfterClass
|
|
||||||
public static void restoreOriginalLogger()
|
|
||||||
{
|
|
||||||
Log.setLog(originalLogger);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testNamedLogging()
|
public void testNamedLogging()
|
||||||
{
|
{
|
||||||
|
|
|
@ -43,4 +43,10 @@ public class StdErrCapture
|
||||||
String output = new String(test.toByteArray());
|
String output = new String(test.toByteArray());
|
||||||
Assert.assertThat(output,not(containsString(unexpectedString)));
|
Assert.assertThat(output,not(containsString(unexpectedString)));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public String toString()
|
||||||
|
{
|
||||||
|
err.flush();
|
||||||
|
return new String(test.toByteArray());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue