1 /* 2 * Copyright (C) 2017 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package com.android.libcore.timezone.util; 18 19 import java.io.IOException; 20 import java.io.PrintWriter; 21 import java.io.StringWriter; 22 import java.util.ArrayList; 23 import java.util.LinkedList; 24 import java.util.List; 25 26 /** 27 * Stores context, errors and error severity for logging and flow control. This class distinguishes 28 * between warnings (just info), errors (may not be immediately fatal) and fatal (immediately 29 * fatal). 30 */ 31 public final class Errors { 32 33 private final static int LEVEL_WARNING = 1; 34 private final static int LEVEL_ERROR = 2; 35 private final static int LEVEL_FATAL = 3; 36 37 private int level = 0; 38 39 private final LinkedList<String> scopes = new LinkedList<>(); 40 private final List<String> messages = new ArrayList<>(); 41 Errors()42 public Errors() { 43 } 44 pushScope(String name)45 public void pushScope(String name) { 46 scopes.add(name); 47 } 48 popScope()49 public String popScope() { 50 return scopes.removeLast(); 51 } 52 53 /** Adds a fatal error, and immediately throws {@link HaltExecutionException}. */ addFatalAndHalt(String msg)54 public HaltExecutionException addFatalAndHalt(String msg) throws HaltExecutionException { 55 addInternal(msg, null, LEVEL_FATAL); 56 throw new HaltExecutionException("Fatal error"); 57 } 58 59 /** Adds a fatal error, and immediately throws {@link HaltExecutionException}. */ addFatalAndHalt(String msg, Throwable t)60 public HaltExecutionException addFatalAndHalt(String msg, Throwable t) 61 throws HaltExecutionException { 62 addInternal(msg, t, LEVEL_FATAL); 63 throw new HaltExecutionException("Fatal error"); 64 } 65 addError(String msg)66 public void addError(String msg) { 67 addInternal(msg, null, LEVEL_ERROR); 68 } 69 addError(String msg, Throwable t)70 public void addError(String msg, Throwable t) { 71 addInternal(msg, t, LEVEL_ERROR); 72 } 73 addWarning(String msg)74 public void addWarning(String msg) { 75 addInternal(msg, null, LEVEL_WARNING); 76 } 77 asString()78 public String asString() { 79 StringBuilder sb = new StringBuilder(); 80 for (String message : messages) { 81 sb.append(message); 82 sb.append("\n"); 83 } 84 return sb.toString(); 85 } 86 isEmpty()87 public boolean isEmpty() { 88 return messages.isEmpty(); 89 } 90 91 /** True if there are error or fatal messages. */ hasError()92 public boolean hasError() { 93 return level >= LEVEL_ERROR; 94 } 95 96 /** True if there are fatal messages. */ hasFatal()97 public boolean hasFatal() { 98 return level >= LEVEL_FATAL; 99 } 100 addInternal(String msg, Throwable t, int level)101 private void addInternal(String msg, Throwable t, int level) { 102 this.level = Math.max(this.level, level); 103 addMessage(msg); 104 if (t != null) { 105 try (StringWriter out = new StringWriter(); 106 PrintWriter printWriter = new PrintWriter(out)) { 107 t.printStackTrace(printWriter); 108 addMessage(out.toString()); 109 } catch (IOException e) { 110 // Impossible - this is actually a compiler bug. Nothing throws IOException above. 111 throw new AssertionError("Impossible exception thrown", e); 112 } 113 } 114 } 115 addMessage(String msg)116 private void addMessage(String msg) { 117 messages.add(scopes.toString() + ": " + msg); 118 } 119 120 /** Throws a {@link HaltExecutionException} if there are any error or fatal messages. */ throwIfError(String why)121 public void throwIfError(String why) throws HaltExecutionException { 122 if (hasError()) { 123 throw new HaltExecutionException(why); 124 } 125 } 126 127 /** Thrown to halt execution. */ 128 public static class HaltExecutionException extends Exception { HaltExecutionException(String why)129 HaltExecutionException(String why) { 130 super(why); 131 } 132 } 133 } 134