001 /*
002 * Licensed to the Apache Software Foundation (ASF) under one or more
003 * contributor license agreements. See the NOTICE file distributed with
004 * this work for additional information regarding copyright ownership.
005 * The ASF licenses this file to You under the Apache License, Version 2.0
006 * (the "License"); you may not use this file except in compliance with
007 * the License. You may obtain a copy of the License at
008 *
009 * http://www.apache.org/licenses/LICENSE-2.0
010 *
011 * Unless required by applicable law or agreed to in writing, software
012 * distributed under the License is distributed on an "AS IS" BASIS,
013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014 * See the License for the specific language governing permissions and
015 * limitations under the License.
016 */
017 package org.apache.commons.lang3.exception;
018
019 import java.io.Serializable;
020 import java.util.ArrayList;
021 import java.util.HashSet;
022 import java.util.Iterator;
023 import java.util.List;
024 import java.util.Set;
025
026 import org.apache.commons.lang3.StringUtils;
027 import org.apache.commons.lang3.tuple.ImmutablePair;
028 import org.apache.commons.lang3.tuple.Pair;
029
030 /**
031 * Default implementation of the context storing the label-value pairs for contexted exceptions.
032 * <p>
033 * This implementation is serializable, however this is dependent on the values that
034 * are added also being serializable.
035 * </p>
036 *
037 * @see ContextedException
038 * @see ContextedRuntimeException
039 * @since 3.0
040 */
041 public class DefaultExceptionContext implements ExceptionContext, Serializable {
042
043 /** The serialization version. */
044 private static final long serialVersionUID = 20110706L;
045
046 /** The list storing the label-data pairs. */
047 private final List<Pair<String, Object>> contextValues = new ArrayList<Pair<String,Object>>();
048
049 /**
050 * {@inheritDoc}
051 */
052 public DefaultExceptionContext addContextValue(String label, Object value) {
053 contextValues.add(new ImmutablePair<String, Object>(label, value));
054 return this;
055 }
056
057 /**
058 * {@inheritDoc}
059 */
060 public DefaultExceptionContext setContextValue(String label, Object value) {
061 for (final Iterator<Pair<String, Object>> iter = contextValues.iterator(); iter.hasNext();) {
062 final Pair<String, Object> p = iter.next();
063 if (StringUtils.equals(label, p.getKey())) {
064 iter.remove();
065 }
066 }
067 addContextValue(label, value);
068 return this;
069 }
070
071 /**
072 * {@inheritDoc}
073 */
074 public List<Object> getContextValues(String label) {
075 final List<Object> values = new ArrayList<Object>();
076 for (final Pair<String, Object> pair : contextValues) {
077 if (StringUtils.equals(label, pair.getKey())) {
078 values.add(pair.getValue());
079 }
080 }
081 return values;
082 }
083
084 /**
085 * {@inheritDoc}
086 */
087 public Object getFirstContextValue(String label) {
088 for (final Pair<String, Object> pair : contextValues) {
089 if (StringUtils.equals(label, pair.getKey())) {
090 return pair.getValue();
091 }
092 }
093 return null;
094 }
095
096 /**
097 * {@inheritDoc}
098 */
099 public Set<String> getContextLabels() {
100 final Set<String> labels = new HashSet<String>();
101 for (final Pair<String, Object> pair : contextValues) {
102 labels.add(pair.getKey());
103 }
104 return labels;
105 }
106
107 /**
108 * {@inheritDoc}
109 */
110 public List<Pair<String, Object>> getContextEntries() {
111 return contextValues;
112 }
113
114 /**
115 * Builds the message containing the contextual information.
116 *
117 * @param baseMessage the base exception message <b>without</b> context information appended
118 * @return the exception message <b>with</b> context information appended, never null
119 */
120 public String getFormattedExceptionMessage(String baseMessage){
121 StringBuilder buffer = new StringBuilder(256);
122 if (baseMessage != null) {
123 buffer.append(baseMessage);
124 }
125
126 if (contextValues.size() > 0) {
127 if (buffer.length() > 0) {
128 buffer.append('\n');
129 }
130 buffer.append("Exception Context:\n");
131
132 int i = 0;
133 for (final Pair<String, Object> pair : contextValues) {
134 buffer.append("\t[");
135 buffer.append(++i);
136 buffer.append(':');
137 buffer.append(pair.getKey());
138 buffer.append("=");
139 final Object value = pair.getValue();
140 if (value == null) {
141 buffer.append("null");
142 } else {
143 String valueStr;
144 try {
145 valueStr = value.toString();
146 } catch (Exception e) {
147 valueStr = "Exception thrown on toString(): " + ExceptionUtils.getStackTrace(e);
148 }
149 buffer.append(valueStr);
150 }
151 buffer.append("]\n");
152 }
153 buffer.append("---------------------------------");
154 }
155 return buffer.toString();
156 }
157
158 }