package com.redhat.gss.formatters;
/*
* JBoss, Home of Professional Open Source.
* Copyright 2009, Red Hat Inc., and individual contributors
* as indicated by the @author tags. See the copyright.txt file in the
* distribution for a full listing of individual contributors.
*
* This is free software; you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as
* published by the Free Software Foundation; either version 2.1 of
* the License, or (at your option) any later version.
*
* This software is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this software; if not, write to the Free
* Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
* 02110-1301 USA, or see the FSF site: http://www.fsf.org.
*/
import java.util.Collections;
import java.util.HashMap;
import java.util.Locale;
import java.util.Map;
import java.util.NavigableMap;
import java.util.TreeMap;
import org.jboss.logmanager.Level;
/**
* @author Jason T. Greene
*/
public class ColorMap {
private static final String DARK_BLACK = "\033[30m";
private static final String DARK_RED = "\033[31m";
private static final String DARK_GREEN = "\033[32m";
private static final String DARK_YELLOW = "\033[33m";
private static final String DARK_BLUE = "\033[34m";
private static final String DARK_MAGENTA = "\033[35m";
private static final String DARK_CYAN = "\033[36m";
private static final String DARK_WHITE = "\033[37m";
private static final String BRIGHT_BLACK = "\033[1;30m";
private static final String BRIGHT_RED = "\033[1;31m";
private static final String BRIGHT_GREEN = "\033[1;32m";
private static final String BRIGHT_YELLOW = "\033[1;33m";
private static final String BRIGHT_BLUE = "\033[1;34m";
private static final String BRIGHT_MAGENTA = "\033[1;35m";
private static final String BRIGHT_CYAN = "\033[1;36m";
private static final String BRIGHT_WHITE = "\033[1;37m";
private static final String CLEAR = "\033[0m";
static final boolean SUPPORTS_COLOR;
private static final Map<String, String> codes;
private static final Map<String, String> reverseCodes;
private static final Map<String, Integer> levels = new HashMap<String, Integer>();
private static final Map<Integer, String> reverseLevels = new HashMap<Integer, String>();
private static final NavigableMap<Integer, String> defaultLevelMap = new TreeMap<Integer, String>();
static final ColorMap DEFAULT_COLOR_MAP = new ColorMap(defaultLevelMap);
private final NavigableMap<Integer, String> levelMap;
private ColorMap(NavigableMap<Integer,String> levelMap) {
this.levelMap = levelMap;
}
private static final int SEVERE_NUM = Level.SEVERE.intValue();
private static final int FATAL_NUM = Level.FATAL.intValue();
private static final int ERROR_NUM = Level.ERROR.intValue();
private static final int WARN_NUM = Level.WARN.intValue();
private static final int INFO_NUM = Level.INFO.intValue();
private static final int CONFIG_NUM = Level.CONFIG.intValue();
private static final int DEBUG_NUM = Level.DEBUG.intValue();
private static final int TRACE_NUM = Level.TRACE.intValue();
private static final int FINE_NUM = Level.FINE.intValue();
private static final int FINER_NUM = Level.FINER.intValue();
private static final int FINEST_NUM = Level.FINEST.intValue();
static final String LEVEL_NAME = "level";
static final String SEVERE_NAME = "severe";
static final String FATAL_NAME = "fatal";
static final String ERROR_NAME = "error";
static final String WARN_NAME = "warn";
static final String WARNING_NAME = "warning";
static final String INFO_NAME = "info";
static final String DEBUG_NAME = "debug";
static final String TRACE_NAME = "trace";
static final String CONFIG_NAME = "config";
static final String FINE_NAME = "fine";
static final String FINER_NAME = "finer";
static final String FINEST_NAME = "finest";
static final String BLACK_NAME = "black";
static final String GREEN_NAME = "green";
static final String RED_NAME = "red";
static final String YELLOW_NAME = "yellow";
static final String BLUE_NAME = "blue";
static final String MAGENTA_NAME = "magenta";
static final String CYAN_NAME = "cyan";
static final String WHITE_NAME = "white";
static final String BRIGHT_BLACK_NAME = "brightblack";
static final String BRIGHT_RED_NAME = "brightred";
static final String BRIGHT_GREEN_NAME = "brightgreen";
static final String BRIGHT_BLUE_NAME = "brightblue";
static final String BRIGHT_YELLOW_NAME = "brightyellow";
static final String BRIGHT_MAGENTA_NAME = "brightmagenta";
static final String BRIGHT_CYAN_NAME = "brightcyan";
static final String BRIGHT_WHITE_NAME = "brightwhite";
static final String CLEAR_NAME = "clear";
static {
// Turn color on by default for everything but Windows, unless ansicon is used
String os = System.getProperty("os.name");
final boolean dft = os != null && (!os.toLowerCase(Locale.ROOT).contains("win") || System.getenv("ANSICON") != null);
final String nocolor = System.getProperty("org.jboss.logmanager.nocolor");
SUPPORTS_COLOR = (nocolor == null ? dft : "false".equalsIgnoreCase(nocolor));
levels.put(SEVERE_NAME, SEVERE_NUM);
levels.put(FATAL_NAME, FATAL_NUM);
levels.put(ERROR_NAME, ERROR_NUM);
levels.put(WARN_NAME, WARN_NUM);
levels.put(WARNING_NAME, WARN_NUM);
levels.put(INFO_NAME, INFO_NUM);
levels.put(CONFIG_NAME, CONFIG_NUM);
levels.put(DEBUG_NAME, DEBUG_NUM);
levels.put(TRACE_NAME, TRACE_NUM);
levels.put(FINE_NAME, FINE_NUM);
levels.put(FINER_NAME, FINER_NUM);
levels.put(FINEST_NAME, FINEST_NUM);
reverseLevels.put(SEVERE_NUM, SEVERE_NAME);
reverseLevels.put(CONFIG_NUM, CONFIG_NAME);
reverseLevels.put(FINE_NUM, FINE_NAME);
reverseLevels.put(FINER_NUM, FINER_NAME);
reverseLevels.put(FINEST_NUM, FINEST_NAME);
reverseLevels.put(FATAL_NUM, FATAL_NAME);
reverseLevels.put(ERROR_NUM, ERROR_NAME);
reverseLevels.put(WARN_NUM, WARN_NAME);
reverseLevels.put(INFO_NUM, INFO_NAME);
reverseLevels.put(DEBUG_NUM, DEBUG_NAME);
reverseLevels.put(TRACE_NUM, TRACE_NAME);
if (SUPPORTS_COLOR) {
codes = new HashMap<String, String>();
codes.put(BLACK_NAME, DARK_BLACK);
codes.put(RED_NAME, DARK_RED);
codes.put(GREEN_NAME, DARK_GREEN);
codes.put(YELLOW_NAME, DARK_YELLOW);
codes.put(BLUE_NAME, DARK_BLUE);
codes.put(MAGENTA_NAME, DARK_MAGENTA);
codes.put(CYAN_NAME, DARK_CYAN);
codes.put(WHITE_NAME, DARK_WHITE);
codes.put(BRIGHT_BLACK_NAME, BRIGHT_BLACK);
codes.put(BRIGHT_RED_NAME, BRIGHT_RED);
codes.put(BRIGHT_GREEN_NAME, BRIGHT_GREEN);
codes.put(BRIGHT_YELLOW_NAME, BRIGHT_YELLOW);
codes.put(BRIGHT_BLUE_NAME, BRIGHT_BLUE);
codes.put(BRIGHT_MAGENTA_NAME, BRIGHT_MAGENTA);
codes.put(BRIGHT_CYAN_NAME, BRIGHT_CYAN);
codes.put(BRIGHT_WHITE_NAME, BRIGHT_WHITE);
codes.put(CLEAR_NAME, CLEAR);
reverseCodes = new HashMap<String, String>();
reverseCodes.put(DARK_BLACK, BLACK_NAME);
reverseCodes.put(DARK_RED, RED_NAME);
reverseCodes.put(DARK_GREEN, GREEN_NAME);
reverseCodes.put(DARK_YELLOW, YELLOW_NAME);
reverseCodes.put(DARK_BLUE, BLUE_NAME);
reverseCodes.put(DARK_MAGENTA, MAGENTA_NAME);
reverseCodes.put(DARK_CYAN, CYAN_NAME);
reverseCodes.put(DARK_WHITE, WHITE_NAME);
reverseCodes.put(BRIGHT_BLACK, BRIGHT_BLACK_NAME);
reverseCodes.put(BRIGHT_RED, BRIGHT_RED_NAME);
reverseCodes.put(BRIGHT_GREEN, BRIGHT_GREEN_NAME);
reverseCodes.put(BRIGHT_YELLOW, BRIGHT_YELLOW_NAME);
reverseCodes.put(BRIGHT_BLUE, BRIGHT_BLUE_NAME);
reverseCodes.put(BRIGHT_MAGENTA, BRIGHT_MAGENTA_NAME);
reverseCodes.put(BRIGHT_CYAN, BRIGHT_CYAN_NAME);
reverseCodes.put(BRIGHT_WHITE, BRIGHT_WHITE_NAME);
reverseCodes.put(CLEAR, CLEAR);
defaultLevelMap.put(Level.ERROR.intValue(), DARK_RED);
defaultLevelMap.put(Level.WARN.intValue(), DARK_YELLOW);
defaultLevelMap.put(Level.INFO.intValue(), CLEAR);
defaultLevelMap.put(Level.DEBUG.intValue(), DARK_GREEN);
} else {
reverseCodes = codes = Collections.emptyMap();
}
}
static ColorMap create(String expression) {
if (expression == null || expression.length() < 3) {
return DEFAULT_COLOR_MAP;
}
NavigableMap<Integer, String> levelMap = new TreeMap<Integer, String>();
for (String pair : expression.split(",")) {
String[] parts = pair.split(":");
if (parts.length != 2) {
continue;
}
String color = codes.get(parts[1].toLowerCase(Locale.ROOT));
if (color == null) {
continue;
}
try {
int i = Integer.parseInt(parts[0]);
levelMap.put(i, color);
continue;
} catch (NumberFormatException e) {
// eat
}
Integer i = levels.get(parts[0].toLowerCase(Locale.ROOT));
if (i == null) {
continue;
}
levelMap.put(i, color);
}
return new ColorMap(levelMap);
}
String getCode(String name, java.util.logging.Level level) {
if (name == null || !SUPPORTS_COLOR) {
return null;
}
String lower = name.toLowerCase(Locale.ROOT);
if (lower.equals(LEVEL_NAME)) {
Map.Entry<Integer,String> entry = levelMap.floorEntry(level.intValue());
return entry != null ? entry.getValue() : null;
}
return codes.get(lower);
}
public String toString() {
StringBuilder builder = new StringBuilder();
for (Map.Entry<Integer, String> entry : levelMap.descendingMap().entrySet()) {
Integer num = entry.getKey();
String level = reverseLevels.get(num);
builder.append(level == null ? num : level).append(":").append(reverseCodes.get(entry.getValue()))
.append(",");
}
if (builder.length() > 0) {
builder.setLength(builder.length() - 1);
}
return builder.toString();
}
}