package freenet.support; import java.util.ArrayList; import java.util.StringTokenizer; import java.util.concurrent.CopyOnWriteArrayList; public abstract class LoggerHook extends Logger { protected LogLevel threshold; public static final class DetailedThreshold { final String section; final LogLevel dThreshold; public DetailedThreshold(String section, LogLevel thresh) { this.section = section; this.dThreshold = thresh; } } protected LoggerHook(LogLevel thresh){ this.threshold = thresh; } LoggerHook(String thresh) throws InvalidThresholdException{ this.threshold = parseThreshold(thresh.toUpperCase()); } public DetailedThreshold[] detailedThresholds = new DetailedThreshold[0]; private CopyOnWriteArrayList<LogThresholdCallback> thresholdsCallbacks = new CopyOnWriteArrayList<LogThresholdCallback>(); /** * Log a message * * @param o * The object where this message was generated. * @param source * The class where this message was generated. * @param message * A clear and verbose message describing the event * @param e * Logs this exception with the message. * @param priority * The priority of the mesage, one of LogLevel.ERROR, * LogLevel.NORMAL, LogLevel.MINOR, or LogLevel.DEBUG. */ @Override public abstract void log( Object o, Class<?> source, String message, Throwable e, LogLevel priority); /** * Log a message. * @param source The source object where this message was generated * @param message A clear and verbose message describing the event * @param priority The priority of the mesage, one of LogLevel.ERROR, * LogLevel.NORMAL, LogLevel.MINOR, or LogLevel.DEBUG. **/ @Override public void log(Object source, String message, LogLevel priority) { if (!instanceShouldLog(priority,source)) return; log(source, source == null ? null : source.getClass(), message, null, priority); } /** * Log a message with an exception. * @param o The source object where this message was generated. * @param message A clear and verbose message describing the event. * @param e Logs this exception with the message. * @param priority The priority of the mesage, one of LogLevel.ERROR, * LogLevel.NORMAL, LogLevel.MINOR, or LogLevel.DEBUG. * @see #log(Object o, String message, int priority) */ @Override public void log(Object o, String message, Throwable e, LogLevel priority) { if (!instanceShouldLog(priority,o)) return; log(o, o == null ? null : o.getClass(), message, e, priority); } /** * Log a message from static code. * @param c The class where this message was generated. * @param message A clear and verbose message describing the event * @param priority The priority of the mesage, one of LogLevel.ERROR, * LogLevel.NORMAL, LogLevel.MINOR, or LogLevel.DEBUG. */ @Override public void log(Class<?> c, String message, LogLevel priority) { if (!instanceShouldLog(priority,c)) return; log(null, c, message, null, priority); } @Override public void log(Class<?> c, String message, Throwable e, LogLevel priority) { if (!instanceShouldLog(priority, c)) return; log(null, c, message, e, priority); } public boolean acceptPriority(LogLevel prio) { return prio.matchesThreshold(threshold); } @Override public void setThreshold(LogLevel thresh) { this.threshold = thresh; notifyLogThresholdCallbacks(); } @Override public LogLevel getThresholdNew() { return threshold; } private LogLevel parseThreshold(String threshold) throws InvalidThresholdException { if(threshold == null) throw new InvalidThresholdException(threshold); try { return LogLevel.valueOf(threshold.toUpperCase()); } catch (IllegalArgumentException e) { throw new InvalidThresholdException(threshold); } } @Override public void setThreshold(String symbolicThreshold) throws InvalidThresholdException { setThreshold(parseThreshold(symbolicThreshold)); } @Override public void setDetailedThresholds(String details) throws InvalidThresholdException { if (details == null) return; StringTokenizer st = new StringTokenizer(details, ",", false); ArrayList<DetailedThreshold> stuff = new ArrayList<DetailedThreshold>(); while (st.hasMoreTokens()) { String token = st.nextToken(); if (token.length() == 0) continue; int x = token.indexOf(':'); if (x < 0) continue; if (x == token.length() - 1) continue; String section = token.substring(0, x); String value = token.substring(x + 1, token.length()); stuff.add(new DetailedThreshold(section, parseThreshold(value.toUpperCase()))); } DetailedThreshold[] newThresholds = new DetailedThreshold[stuff.size()]; stuff.toArray(newThresholds); synchronized(this) { detailedThresholds = newThresholds; } notifyLogThresholdCallbacks(); } public String getDetailedThresholds() { DetailedThreshold[] thresh = null; synchronized(this) { thresh = detailedThresholds; } if (thresh.length == 0) return ""; StringBuilder sb = new StringBuilder(); for(DetailedThreshold t: thresh) { sb.append(t.section); sb.append(':'); sb.append(t.dThreshold); sb.append(','); } // assert(sb.length() > 0); -- always true as thresh.length != 0 // remove last ',' sb.deleteCharAt(sb.length() - 1); return sb.toString(); } public static class InvalidThresholdException extends Exception { private static final long serialVersionUID = -1; InvalidThresholdException(String msg) { super(msg); } } @Override public boolean instanceShouldLog(LogLevel priority, Class<?> c) { DetailedThreshold[] thresholds; LogLevel thresh; synchronized(this) { thresholds = detailedThresholds; thresh = threshold; } if ((c != null) && (thresholds.length > 0)) { String cname = c.getName(); for(DetailedThreshold dt : thresholds) { if(cname.startsWith(dt.section)) thresh = dt.dThreshold; } } return priority.matchesThreshold(thresh); } @Override public final boolean instanceShouldLog(LogLevel prio, Object o) { return instanceShouldLog(prio, o == null ? null : o.getClass()); } @Override public final void instanceRegisterLogThresholdCallback(LogThresholdCallback ltc) { thresholdsCallbacks.add(ltc); // Call the new callback to avoid code duplication ltc.shouldUpdate(); } @Override public final void instanceUnregisterLogThresholdCallback(LogThresholdCallback ltc) { thresholdsCallbacks.remove(ltc); } private void notifyLogThresholdCallbacks() { for(LogThresholdCallback ltc : thresholdsCallbacks) ltc.shouldUpdate(); } }