| /* |
| * Licensed to the Apache Software Foundation (ASF) under one or more |
| * contributor license agreements. See the NOTICE file distributed with |
| * this work for additional information regarding copyright ownership. |
| * The ASF licenses this file to You under the Apache License, Version 2.0 |
| * (the "License"); you may not use this file except in compliance with |
| * the License. You may obtain a copy of the License at |
| * |
| * https://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| */ |
| package org.apache.commons.lang3.exception; |
| |
| import java.io.Serializable; |
| import java.util.ArrayList; |
| import java.util.List; |
| import java.util.Objects; |
| import java.util.Set; |
| import java.util.stream.Collectors; |
| import java.util.stream.Stream; |
| |
| import org.apache.commons.lang3.Strings; |
| import org.apache.commons.lang3.tuple.ImmutablePair; |
| import org.apache.commons.lang3.tuple.Pair; |
| |
| /** |
| * Default implementation of the context storing the label-value pairs for contexted exceptions. |
| * <p> |
| * This implementation is serializable, however this is dependent on the values that |
| * are added also being serializable. |
| * </p> |
| * |
| * @see ContextedException |
| * @see ContextedRuntimeException |
| * @since 3.0 |
| */ |
| public class DefaultExceptionContext implements ExceptionContext, Serializable { |
| |
| /** The serialization version. */ |
| private static final long serialVersionUID = 20110706L; |
| |
| /** The list storing the label-data pairs. */ |
| private final List<Pair<String, Object>> contextValues = new ArrayList<>(); |
| |
| /** |
| * Constructs a new instance. |
| */ |
| public DefaultExceptionContext() { |
| // empty |
| } |
| |
| /** |
| * {@inheritDoc} |
| */ |
| @Override |
| public DefaultExceptionContext addContextValue(final String label, final Object value) { |
| contextValues.add(new ImmutablePair<>(label, value)); |
| return this; |
| } |
| |
| /** |
| * {@inheritDoc} |
| */ |
| @Override |
| public List<Pair<String, Object>> getContextEntries() { |
| return contextValues; |
| } |
| |
| /** |
| * {@inheritDoc} |
| */ |
| @Override |
| public Set<String> getContextLabels() { |
| return stream().map(Pair::getKey).collect(Collectors.toSet()); |
| } |
| |
| /** |
| * {@inheritDoc} |
| */ |
| @Override |
| public List<Object> getContextValues(final String label) { |
| return stream().filter(pair -> Strings.CS.equals(label, pair.getKey())).map(Pair::getValue).collect(Collectors.toList()); |
| } |
| |
| /** |
| * {@inheritDoc} |
| */ |
| @Override |
| public Object getFirstContextValue(final String label) { |
| return stream().filter(pair -> Strings.CS.equals(label, pair.getKey())).findFirst().map(Pair::getValue).orElse(null); |
| } |
| |
| /** |
| * Builds the message containing the contextual information. |
| * |
| * @param baseMessage the base exception message <strong>without</strong> context information appended |
| * @return the exception message <strong>with</strong> context information appended, never null |
| */ |
| @Override |
| public String getFormattedExceptionMessage(final String baseMessage) { |
| final StringBuilder buffer = new StringBuilder(256); |
| if (baseMessage != null) { |
| buffer.append(baseMessage); |
| } |
| if (!contextValues.isEmpty()) { |
| if (buffer.length() > 0) { |
| buffer.append('\n'); |
| } |
| buffer.append("Exception Context:\n"); |
| int i = 0; |
| for (final Pair<String, Object> pair : contextValues) { |
| buffer.append("\t["); |
| buffer.append(++i); |
| buffer.append(':'); |
| buffer.append(pair.getKey()); |
| buffer.append("="); |
| final Object value = pair.getValue(); |
| try { |
| buffer.append(Objects.toString(value)); |
| } catch (final Exception e) { |
| buffer.append("Exception thrown on toString(): "); |
| buffer.append(ExceptionUtils.getStackTrace(e)); |
| } |
| buffer.append("]\n"); |
| } |
| buffer.append("---------------------------------"); |
| } |
| return buffer.toString(); |
| } |
| |
| /** |
| * {@inheritDoc} |
| */ |
| @Override |
| public DefaultExceptionContext setContextValue(final String label, final Object value) { |
| contextValues.removeIf(p -> Strings.CS.equals(label, p.getKey())); |
| addContextValue(label, value); |
| return this; |
| } |
| |
| private Stream<Pair<String, Object>> stream() { |
| return contextValues.stream(); |
| } |
| |
| } |