001/** 002 * Copyright (c) 2004-2021 QOS.ch 003 * All rights reserved. 004 * 005 * Permission is hereby granted, free of charge, to any person obtaining 006 * a copy of this software and associated documentation files (the 007 * "Software"), to deal in the Software without restriction, including 008 * without limitation the rights to use, copy, modify, merge, publish, 009 * distribute, sublicense, and/or sell copies of the Software, and to 010 * permit persons to whom the Software is furnished to do so, subject to 011 * the following conditions: 012 * 013 * The above copyright notice and this permission notice shall be 014 * included in all copies or substantial portions of the Software. 015 * 016 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 017 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 018 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 019 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE 020 * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 021 * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 022 * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 023 * 024 */ 025package org.slf4j.simple.multiThreadedExecution; 026 027import java.io.PrintStream; 028import java.util.regex.Pattern; 029 030public class StateCheckingPrintStream extends PrintStream { 031 032 static String PACKAGE_NAME = "org.slf4j.simple.multiThreadedExecution"; 033 034 035 enum State { 036 INITIAL, UNKNOWN, HELLO, THROWABLE, AT1, AT2, OTHER; 037 } 038 039 PrintStream other; 040 041 volatile State currentState = State.INITIAL; 042 043 public StateCheckingPrintStream(PrintStream ps) { 044 super(ps); 045 } 046 047 public void print(String s) { 048 } 049 050 public void println(String s) { 051 052 State next = computeState(s); 053 //System.out.println(next + " " + s); 054 switch (currentState) { 055 case INITIAL: 056 currentState = next; 057 break; 058 059 case UNKNOWN: 060 currentState = next; 061 break; 062 063 case OTHER: 064 if (next == State.UNKNOWN) { 065 currentState = State.UNKNOWN; 066 return; 067 } 068 069 if (next != State.OTHER && next != State.HELLO) { 070 throw badState(s, currentState, next); 071 } 072 currentState = next; 073 break; 074 075 case HELLO: 076 if (next != State.THROWABLE) { 077 throw badState(s, currentState, next); 078 } 079 currentState = next; 080 break; 081 case THROWABLE: 082 if (next != State.AT1) { 083 throw badState(s, currentState, next); 084 } 085 currentState = next; 086 break; 087 088 case AT1: 089 if (next != State.AT2) { 090 throw badState(s, currentState, next); 091 } 092 currentState = next; 093 break; 094 095 case AT2: 096 currentState = next; 097 break; 098 default: 099 throw new IllegalStateException("Unreachable code"); 100 } 101 } 102 103 private IllegalStateException badState(String s, State currentState2, State next) { 104 return new IllegalStateException("Unexpected state " + next + " for current state " + currentState2 + " for " + s); 105 106 } 107 108 String OTHER_PATTERN_STR = ".*Other \\d{1,5}"; 109 String HELLO_PATTERN_STR = ".*Hello \\d{1,5}"; 110 String THROWABLE_PATTERN_STR = "java.lang.Throwable: i=\\d{1,5}"; 111 String AT1_PATTERN_STR = "\\s*at " + PACKAGE_NAME + ".*"; 112 String AT2_PATTERN_STR = "\\s*at " + ".*Thread.java.*"; 113 114 Pattern PATTERN_OTHER = Pattern.compile(OTHER_PATTERN_STR); 115 Pattern PATTERN_HELLO = Pattern.compile(HELLO_PATTERN_STR); 116 Pattern PATTERN_THROWABLE = Pattern.compile(THROWABLE_PATTERN_STR); 117 Pattern PATTERN_AT1 = Pattern.compile(AT1_PATTERN_STR); 118 Pattern PATTERN_AT2 = Pattern.compile(AT2_PATTERN_STR); 119 120 private State computeState(String s) { 121 122 if (PATTERN_OTHER.matcher(s).matches()) { 123 return State.OTHER; 124 } else if (PATTERN_HELLO.matcher(s).matches()) { 125 return State.HELLO; 126 } else if (PATTERN_THROWABLE.matcher(s).matches()) { 127 return State.THROWABLE; 128 } else if (PATTERN_AT1.matcher(s).matches()) { 129 return State.AT1; 130 } else if (PATTERN_AT2.matcher(s).matches()) { 131 return State.AT2; 132 } else { 133 return State.UNKNOWN; 134 } 135 } 136 137 public void println(Object o) { 138 println(o.toString()); 139 } 140}