001/** 002 * Logback: the reliable, generic, fast and flexible logging framework. 003 * Copyright (C) 1999-2015, QOS.ch. All rights reserved. 004 * 005 * This program and the accompanying materials are dual-licensed under 006 * either the terms of the Eclipse Public License v1.0 as published by 007 * the Eclipse Foundation 008 * 009 * or (per the licensee's choosing) 010 * 011 * under the terms of the GNU Lesser General Public License version 2.1 012 * as published by the Free Software Foundation. 013 */ 014package ch.qos.logback.core.status; 015 016import java.util.ArrayList; 017import java.util.Iterator; 018import java.util.List; 019import java.util.Objects; 020 021abstract public class StatusBase implements Status { 022 023 static private final List<Status> EMPTY_LIST = new ArrayList<Status>(0); 024 025 int level; 026 final String message; 027 final Object origin; 028 List<Status> childrenList; 029 Throwable throwable; 030 long timestamp; 031 032 StatusBase(int level, String msg, Object origin) { 033 this(level, msg, origin, null); 034 } 035 036 StatusBase(int level, String msg, Object origin, Throwable t) { 037 this.level = level; 038 this.message = msg; 039 this.origin = origin; 040 this.throwable = t; 041 this.timestamp = System.currentTimeMillis(); 042 } 043 044 public synchronized void add(Status child) { 045 if (child == null) { 046 throw new NullPointerException("Null values are not valid Status."); 047 } 048 if (childrenList == null) { 049 childrenList = new ArrayList<Status>(); 050 } 051 childrenList.add(child); 052 } 053 054 public synchronized boolean hasChildren() { 055 return ((childrenList != null) && (childrenList.size() > 0)); 056 } 057 058 public synchronized Iterator<Status> iterator() { 059 if (childrenList != null) { 060 return childrenList.iterator(); 061 } else { 062 return EMPTY_LIST.iterator(); 063 } 064 } 065 066 public synchronized boolean remove(Status statusToRemove) { 067 if (childrenList == null) { 068 return false; 069 } 070 // TODO also search in childrens' children 071 return childrenList.remove(statusToRemove); 072 } 073 074 public int getLevel() { 075 return level; 076 } 077 078 // status messages are not supposed to contain cycles. 079 // cyclic status arrangements are like to cause deadlocks 080 // when this method is called from different thread on 081 // different status objects lying on the same cycle 082 public synchronized int getEffectiveLevel() { 083 int result = level; 084 int effLevel; 085 086 Iterator<Status> it = iterator(); 087 Status s; 088 while (it.hasNext()) { 089 s = (Status) it.next(); 090 effLevel = s.getEffectiveLevel(); 091 if (effLevel > result) { 092 result = effLevel; 093 } 094 } 095 return result; 096 } 097 098 public String getMessage() { 099 return message; 100 } 101 102 public Object getOrigin() { 103 return origin; 104 } 105 106 public Throwable getThrowable() { 107 return throwable; 108 } 109 110 public long getTimestamp() { 111 return timestamp; 112 } 113 114 @Override 115 public String toString() { 116 StringBuilder buf = new StringBuilder(); 117 switch (getEffectiveLevel()) { 118 case INFO: 119 buf.append("INFO"); 120 break; 121 case WARN: 122 buf.append("WARN"); 123 break; 124 case ERROR: 125 buf.append("ERROR"); 126 break; 127 } 128 if (origin != null) { 129 buf.append(" in "); 130 buf.append(origin); 131 buf.append(" -"); 132 } 133 134 buf.append(" "); 135 buf.append(message); 136 137 if (throwable != null) { 138 buf.append(" "); 139 buf.append(throwable); 140 } 141 142 return buf.toString(); 143 } 144 145 @Override 146 public boolean equals(Object o) { 147 if (this == o) 148 return true; 149 if (o == null || getClass() != o.getClass()) 150 return false; 151 StatusBase that = (StatusBase) o; 152 return level == that.level && timestamp == that.timestamp && Objects.equals(message, that.message); 153 } 154 155 156 157 @Override 158 public int hashCode() { 159 return Objects.hash(level, message, timestamp); 160 } 161 162}