Sort members
This commit is contained in:
@@ -1002,18 +1002,6 @@ public abstract class LogFactory {
|
||||
return factory;
|
||||
}
|
||||
|
||||
private static boolean isClassAvailable(final String className, final ClassLoader classLoader) {
|
||||
final ClassLoader loader = LogFactory.class.getClassLoader();
|
||||
logDiagnostic("Checking if class '" + className + "' is available in class loader " + objectId(loader));
|
||||
try {
|
||||
Class.forName(className, true, classLoader);
|
||||
return true;
|
||||
} catch (final ClassNotFoundException | LinkageError e) {
|
||||
logDiagnostic("Failed to load class '" + className + "' from class loader " + objectId(loader) + ": " + e.getMessage());
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Convenience method to return a named logger, without the application having to care about factories.
|
||||
*
|
||||
@@ -1139,8 +1127,6 @@ public abstract class LogFactory {
|
||||
return (Enumeration) result;
|
||||
}
|
||||
|
||||
// ------------------------------------------------------ Protected Methods
|
||||
|
||||
/**
|
||||
* Read the specified system property, using an AccessController so that
|
||||
* the property can be read if JCL has been granted the appropriate
|
||||
@@ -1156,6 +1142,8 @@ public abstract class LogFactory {
|
||||
(PrivilegedAction) () -> System.getProperty(key, def));
|
||||
}
|
||||
|
||||
// ------------------------------------------------------ Protected Methods
|
||||
|
||||
/**
|
||||
* Checks whether the supplied Throwable is one that needs to be
|
||||
* re-thrown and ignores all others.
|
||||
@@ -1277,6 +1265,18 @@ public abstract class LogFactory {
|
||||
}
|
||||
}
|
||||
|
||||
private static boolean isClassAvailable(final String className, final ClassLoader classLoader) {
|
||||
final ClassLoader loader = LogFactory.class.getClassLoader();
|
||||
logDiagnostic("Checking if class '" + className + "' is available in class loader " + objectId(loader));
|
||||
try {
|
||||
Class.forName(className, true, classLoader);
|
||||
return true;
|
||||
} catch (final ClassNotFoundException | LinkageError e) {
|
||||
logDiagnostic("Failed to load class '" + className + "' from class loader " + objectId(loader) + ": " + e.getMessage());
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Indicates true if the user has enabled internal logging.
|
||||
* <p>
|
||||
|
||||
@@ -42,80 +42,6 @@ import org.apache.logging.log4j.util.StackLocatorUtil;
|
||||
*/
|
||||
public final class Log4jApiLogFactory extends LogFactory {
|
||||
|
||||
private static final String[] EMPTY_ARRAY = new String[0];
|
||||
/**
|
||||
* Marker used by all messages coming from Apache Commons Logging.
|
||||
*/
|
||||
private static final Marker MARKER = MarkerManager.getMarker("COMMONS-LOGGING");
|
||||
|
||||
/**
|
||||
* Caches Log instances
|
||||
*/
|
||||
private final LoggerAdapter<Log> adapter = new LogAdapter();
|
||||
|
||||
private final ConcurrentMap<String, Object> attributes = new ConcurrentHashMap<>();
|
||||
|
||||
@Override
|
||||
public Log getInstance(final String name) {
|
||||
return adapter.getLogger(name);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object getAttribute(final String name) {
|
||||
return attributes.get(name);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String[] getAttributeNames() {
|
||||
return attributes.keySet().toArray(EMPTY_ARRAY);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Log getInstance(final Class clazz) {
|
||||
return getInstance(clazz.getName());
|
||||
}
|
||||
|
||||
/**
|
||||
* This method is supposed to clear all loggers. In this implementation it will clear all the logger
|
||||
* wrappers but the loggers managed by the underlying logger context will not be.
|
||||
*/
|
||||
@Override
|
||||
public void release() {
|
||||
try {
|
||||
adapter.close();
|
||||
} catch (final IOException ignored) {
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void removeAttribute(final String name) {
|
||||
attributes.remove(name);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setAttribute(final String name, final Object value) {
|
||||
if (value != null) {
|
||||
attributes.put(name, value);
|
||||
} else {
|
||||
removeAttribute(name);
|
||||
}
|
||||
}
|
||||
|
||||
private static final class LogAdapter extends AbstractLoggerAdapter<Log> {
|
||||
|
||||
@Override
|
||||
protected Log newLogger(final String name, final LoggerContext context) {
|
||||
return new Log4j2Log(context.getLogger(name));
|
||||
}
|
||||
|
||||
@Override
|
||||
protected LoggerContext getContext() {
|
||||
return getContext(LogManager.getFactory().isClassLoaderDependent() ? StackLocatorUtil.getCallerClass(
|
||||
LogFactory.class) : null);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private static final class Log4j2Log implements Log {
|
||||
|
||||
private static final String FQCN = Log4j2Log.class.getName();
|
||||
@@ -126,11 +52,55 @@ public final class Log4jApiLogFactory extends LogFactory {
|
||||
this.logger = logger;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void debug(final Object message) {
|
||||
logIfEnabled(Level.DEBUG, message, null);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void debug(final Object message, final Throwable t) {
|
||||
logIfEnabled(Level.DEBUG, message, t);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void error(final Object message) {
|
||||
logIfEnabled(Level.ERROR, message, null);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void error(final Object message, final Throwable t) {
|
||||
logIfEnabled(Level.ERROR, message, t);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void fatal(final Object message) {
|
||||
logIfEnabled(Level.FATAL, message, null);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void fatal(final Object message, final Throwable t) {
|
||||
logIfEnabled(Level.FATAL, message, t);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void info(final Object message) {
|
||||
logIfEnabled(Level.INFO, message, null);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void info(final Object message, final Throwable t) {
|
||||
logIfEnabled(Level.INFO, message, t);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isDebugEnabled() {
|
||||
return isEnabled(Level.DEBUG);
|
||||
}
|
||||
|
||||
private boolean isEnabled(final Level level) {
|
||||
return logger.isEnabled(level, MARKER, null);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isErrorEnabled() {
|
||||
return isEnabled(Level.ERROR);
|
||||
@@ -156,6 +126,14 @@ public final class Log4jApiLogFactory extends LogFactory {
|
||||
return isEnabled(Level.WARN);
|
||||
}
|
||||
|
||||
private void logIfEnabled(final Level level, final Object message, final Throwable t) {
|
||||
if (message instanceof CharSequence) {
|
||||
logger.logIfEnabled(FQCN, level, MARKER, (CharSequence) message, t);
|
||||
} else {
|
||||
logger.logIfEnabled(FQCN, level, MARKER, message, t);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void trace(final Object message) {
|
||||
logIfEnabled(Level.TRACE, message, null);
|
||||
@@ -166,26 +144,6 @@ public final class Log4jApiLogFactory extends LogFactory {
|
||||
logIfEnabled(Level.TRACE, message, t);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void debug(final Object message) {
|
||||
logIfEnabled(Level.DEBUG, message, null);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void debug(final Object message, final Throwable t) {
|
||||
logIfEnabled(Level.DEBUG, message, t);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void info(final Object message) {
|
||||
logIfEnabled(Level.INFO, message, null);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void info(final Object message, final Throwable t) {
|
||||
logIfEnabled(Level.INFO, message, t);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void warn(final Object message) {
|
||||
logIfEnabled(Level.WARN, message, null);
|
||||
@@ -195,37 +153,79 @@ public final class Log4jApiLogFactory extends LogFactory {
|
||||
public void warn(final Object message, final Throwable t) {
|
||||
logIfEnabled(Level.WARN, message, t);
|
||||
}
|
||||
}
|
||||
private static final class LogAdapter extends AbstractLoggerAdapter<Log> {
|
||||
|
||||
@Override
|
||||
public void error(final Object message) {
|
||||
logIfEnabled(Level.ERROR, message, null);
|
||||
protected LoggerContext getContext() {
|
||||
return getContext(LogManager.getFactory().isClassLoaderDependent() ? StackLocatorUtil.getCallerClass(
|
||||
LogFactory.class) : null);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void error(final Object message, final Throwable t) {
|
||||
logIfEnabled(Level.ERROR, message, t);
|
||||
protected Log newLogger(final String name, final LoggerContext context) {
|
||||
return new Log4j2Log(context.getLogger(name));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void fatal(final Object message) {
|
||||
logIfEnabled(Level.FATAL, message, null);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void fatal(final Object message, final Throwable t) {
|
||||
logIfEnabled(Level.FATAL, message, t);
|
||||
}
|
||||
private static final String[] EMPTY_ARRAY = new String[0];
|
||||
|
||||
private boolean isEnabled(final Level level) {
|
||||
return logger.isEnabled(level, MARKER, null);
|
||||
}
|
||||
/**
|
||||
* Marker used by all messages coming from Apache Commons Logging.
|
||||
*/
|
||||
private static final Marker MARKER = MarkerManager.getMarker("COMMONS-LOGGING");
|
||||
|
||||
private void logIfEnabled(final Level level, final Object message, final Throwable t) {
|
||||
if (message instanceof CharSequence) {
|
||||
logger.logIfEnabled(FQCN, level, MARKER, (CharSequence) message, t);
|
||||
} else {
|
||||
logger.logIfEnabled(FQCN, level, MARKER, message, t);
|
||||
}
|
||||
/**
|
||||
* Caches Log instances
|
||||
*/
|
||||
private final LoggerAdapter<Log> adapter = new LogAdapter();
|
||||
|
||||
private final ConcurrentMap<String, Object> attributes = new ConcurrentHashMap<>();
|
||||
|
||||
@Override
|
||||
public Object getAttribute(final String name) {
|
||||
return attributes.get(name);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String[] getAttributeNames() {
|
||||
return attributes.keySet().toArray(EMPTY_ARRAY);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Log getInstance(final Class clazz) {
|
||||
return getInstance(clazz.getName());
|
||||
}
|
||||
|
||||
@Override
|
||||
public Log getInstance(final String name) {
|
||||
return adapter.getLogger(name);
|
||||
}
|
||||
|
||||
/**
|
||||
* This method is supposed to clear all loggers. In this implementation it will clear all the logger
|
||||
* wrappers but the loggers managed by the underlying logger context will not be.
|
||||
*/
|
||||
@Override
|
||||
public void release() {
|
||||
try {
|
||||
adapter.close();
|
||||
} catch (final IOException ignored) {
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void removeAttribute(final String name) {
|
||||
attributes.remove(name);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setAttribute(final String name, final Object value) {
|
||||
if (value != null) {
|
||||
attributes.put(name, value);
|
||||
} else {
|
||||
removeAttribute(name);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -42,80 +42,111 @@ import org.slf4j.spi.LocationAwareLogger;
|
||||
*/
|
||||
public final class Slf4jLogFactory extends LogFactory {
|
||||
|
||||
private static final Object[] EMPTY_OBJECT_ARRAY = new Object[0];
|
||||
private static final String[] EMPTY_STRING_ARRAY = new String[0];
|
||||
private static final class Slf4jLocationAwareLog implements Log {
|
||||
|
||||
/**
|
||||
* Marker used by all messages coming from Apache Commons Logging.
|
||||
*/
|
||||
private static final Marker MARKER = MarkerFactory.getMarker("COMMONS-LOGGING");
|
||||
private static final String FQCN = Slf4jLocationAwareLog.class.getName();
|
||||
|
||||
/**
|
||||
* Caches Log instances.
|
||||
* <p>
|
||||
* The SLF4J reference implementation (Logback) has a single logger context, so each call to
|
||||
* {@link #getInstance(String)}
|
||||
* should give the same result.
|
||||
* </p>
|
||||
*/
|
||||
private final ConcurrentMap<String, Log> loggers = new ConcurrentHashMap<>();
|
||||
private final LocationAwareLogger logger;
|
||||
|
||||
private final ConcurrentMap<String, Object> attributes = new ConcurrentHashMap<>();
|
||||
public Slf4jLocationAwareLog(final LocationAwareLogger logger) {
|
||||
this.logger = logger;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Log getInstance(final String name) {
|
||||
return loggers.computeIfAbsent(name, n -> {
|
||||
final Logger logger = LoggerFactory.getLogger(n);
|
||||
return logger instanceof LocationAwareLogger ? new Slf4jLocationAwareLog((LocationAwareLogger) logger) : new Slf4jLog(
|
||||
logger);
|
||||
});
|
||||
}
|
||||
@Override
|
||||
public void debug(Object message) {
|
||||
log(DEBUG_INT, message, null);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object getAttribute(final String name) {
|
||||
return attributes.get(name);
|
||||
}
|
||||
@Override
|
||||
public void debug(Object message, Throwable t) {
|
||||
log(DEBUG_INT, message, t);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String[] getAttributeNames() {
|
||||
return attributes.keySet().toArray(EMPTY_STRING_ARRAY);
|
||||
}
|
||||
@Override
|
||||
public void error(Object message) {
|
||||
log(ERROR_INT, message, null);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Log getInstance(final Class clazz) throws LogConfigurationException {
|
||||
return getInstance(clazz.getName());
|
||||
}
|
||||
@Override
|
||||
public void error(Object message, Throwable t) {
|
||||
log(ERROR_INT, message, t);
|
||||
}
|
||||
|
||||
/**
|
||||
* This method is supposed to clear all loggers.
|
||||
* <p>
|
||||
* In this implementation it calls a "stop" method if the logger factory supports it. This is the case of
|
||||
* Logback.
|
||||
* </p>
|
||||
*/
|
||||
@Override
|
||||
public void release() {
|
||||
final ILoggerFactory factory = LoggerFactory.getILoggerFactory();
|
||||
try {
|
||||
factory.getClass().getMethod("stop").invoke(factory);
|
||||
} catch (final ReflectiveOperationException ignored) {
|
||||
@Override
|
||||
public void fatal(Object message) {
|
||||
error(message);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void fatal(Object message, Throwable t) {
|
||||
error(message, t);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void info(Object message) {
|
||||
log(INFO_INT, message, null);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void info(Object message, Throwable t) {
|
||||
log(INFO_INT, message, t);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public boolean isDebugEnabled() {
|
||||
return logger.isDebugEnabled(MARKER);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isErrorEnabled() {
|
||||
return logger.isErrorEnabled(MARKER);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isFatalEnabled() {
|
||||
return isErrorEnabled();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isInfoEnabled() {
|
||||
return logger.isInfoEnabled(MARKER);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isTraceEnabled() {
|
||||
return logger.isTraceEnabled(MARKER);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isWarnEnabled() {
|
||||
return logger.isWarnEnabled(MARKER);
|
||||
}
|
||||
|
||||
private void log(final int level, final Object message, final Throwable t) {
|
||||
logger.log(MARKER, FQCN, level, String.valueOf(message), EMPTY_OBJECT_ARRAY, t);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void trace(Object message) {
|
||||
log(TRACE_INT, message, null);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void trace(Object message, Throwable t) {
|
||||
log(TRACE_INT, message, t);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void warn(Object message) {
|
||||
log(WARN_INT, message, null);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void warn(Object message, Throwable t) {
|
||||
log(WARN_INT, message, t);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void removeAttribute(final String name) {
|
||||
attributes.remove(name);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setAttribute(final String name, final Object value) {
|
||||
if (value != null) {
|
||||
attributes.put(name, value);
|
||||
} else {
|
||||
removeAttribute(name);
|
||||
}
|
||||
}
|
||||
|
||||
private static class Slf4jLog implements Log {
|
||||
|
||||
private final Logger logger;
|
||||
@@ -215,109 +246,78 @@ public final class Slf4jLogFactory extends LogFactory {
|
||||
}
|
||||
}
|
||||
|
||||
private static final class Slf4jLocationAwareLog implements Log {
|
||||
private static final Object[] EMPTY_OBJECT_ARRAY = new Object[0];
|
||||
|
||||
private static final String FQCN = Slf4jLocationAwareLog.class.getName();
|
||||
private static final String[] EMPTY_STRING_ARRAY = new String[0];
|
||||
|
||||
private final LocationAwareLogger logger;
|
||||
/**
|
||||
* Marker used by all messages coming from Apache Commons Logging.
|
||||
*/
|
||||
private static final Marker MARKER = MarkerFactory.getMarker("COMMONS-LOGGING");
|
||||
|
||||
public Slf4jLocationAwareLog(final LocationAwareLogger logger) {
|
||||
this.logger = logger;
|
||||
/**
|
||||
* Caches Log instances.
|
||||
* <p>
|
||||
* The SLF4J reference implementation (Logback) has a single logger context, so each call to
|
||||
* {@link #getInstance(String)}
|
||||
* should give the same result.
|
||||
* </p>
|
||||
*/
|
||||
private final ConcurrentMap<String, Log> loggers = new ConcurrentHashMap<>();
|
||||
|
||||
private final ConcurrentMap<String, Object> attributes = new ConcurrentHashMap<>();
|
||||
|
||||
@Override
|
||||
public Object getAttribute(final String name) {
|
||||
return attributes.get(name);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String[] getAttributeNames() {
|
||||
return attributes.keySet().toArray(EMPTY_STRING_ARRAY);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Log getInstance(final Class clazz) throws LogConfigurationException {
|
||||
return getInstance(clazz.getName());
|
||||
}
|
||||
|
||||
@Override
|
||||
public Log getInstance(final String name) {
|
||||
return loggers.computeIfAbsent(name, n -> {
|
||||
final Logger logger = LoggerFactory.getLogger(n);
|
||||
return logger instanceof LocationAwareLogger ? new Slf4jLocationAwareLog((LocationAwareLogger) logger) : new Slf4jLog(
|
||||
logger);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* This method is supposed to clear all loggers.
|
||||
* <p>
|
||||
* In this implementation it calls a "stop" method if the logger factory supports it. This is the case of
|
||||
* Logback.
|
||||
* </p>
|
||||
*/
|
||||
@Override
|
||||
public void release() {
|
||||
final ILoggerFactory factory = LoggerFactory.getILoggerFactory();
|
||||
try {
|
||||
factory.getClass().getMethod("stop").invoke(factory);
|
||||
} catch (final ReflectiveOperationException ignored) {
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void debug(Object message) {
|
||||
log(DEBUG_INT, message, null);
|
||||
}
|
||||
@Override
|
||||
public void removeAttribute(final String name) {
|
||||
attributes.remove(name);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void debug(Object message, Throwable t) {
|
||||
log(DEBUG_INT, message, t);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void error(Object message) {
|
||||
log(ERROR_INT, message, null);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void error(Object message, Throwable t) {
|
||||
log(ERROR_INT, message, t);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void fatal(Object message) {
|
||||
error(message);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void fatal(Object message, Throwable t) {
|
||||
error(message, t);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void info(Object message) {
|
||||
log(INFO_INT, message, null);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void info(Object message, Throwable t) {
|
||||
log(INFO_INT, message, t);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public boolean isDebugEnabled() {
|
||||
return logger.isDebugEnabled(MARKER);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isErrorEnabled() {
|
||||
return logger.isErrorEnabled(MARKER);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isFatalEnabled() {
|
||||
return isErrorEnabled();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isInfoEnabled() {
|
||||
return logger.isInfoEnabled(MARKER);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isTraceEnabled() {
|
||||
return logger.isTraceEnabled(MARKER);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isWarnEnabled() {
|
||||
return logger.isWarnEnabled(MARKER);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void trace(Object message) {
|
||||
log(TRACE_INT, message, null);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void trace(Object message, Throwable t) {
|
||||
log(TRACE_INT, message, t);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void warn(Object message) {
|
||||
log(WARN_INT, message, null);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void warn(Object message, Throwable t) {
|
||||
log(WARN_INT, message, t);
|
||||
}
|
||||
|
||||
private void log(final int level, final Object message, final Throwable t) {
|
||||
logger.log(MARKER, FQCN, level, String.valueOf(message), EMPTY_OBJECT_ARRAY, t);
|
||||
@Override
|
||||
public void setAttribute(final String name, final Object value) {
|
||||
if (value != null) {
|
||||
attributes.put(name, value);
|
||||
} else {
|
||||
removeAttribute(name);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user