/*
* 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
*
* http://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.math3.exception.util;
import java.util.List;
import java.util.ArrayList;
import java.util.Set;
import java.util.Map;
import java.io.IOException;
import java.io.Serializable;
import java.io.ObjectOutputStream;
import java.io.ObjectInputStream;
import java.util.HashMap;
import java.text.MessageFormat;
import java.util.Locale;
Class that contains the actual implementation of the functionality mandated by the ExceptionContext
interface. All Commons Math exceptions delegate the interface's methods to this class. Since: 3.0
/**
* Class that contains the actual implementation of the functionality mandated
* by the {@link ExceptionContext} interface.
* All Commons Math exceptions delegate the interface's methods to this class.
*
* @since 3.0
*/
public class ExceptionContext implements Serializable {
Serializable version Id. /** Serializable version Id. */
private static final long serialVersionUID = -6024911025449780478L;
The throwable to which this context refers to.
/**
* The throwable to which this context refers to.
*/
private Throwable throwable;
Various informations that enrich the informative message.
/**
* Various informations that enrich the informative message.
*/
private List<Localizable> msgPatterns;
Various informations that enrich the informative message. The arguments will replace the corresponding place-holders in msgPatterns
. /**
* Various informations that enrich the informative message.
* The arguments will replace the corresponding place-holders in
* {@link #msgPatterns}.
*/
private List<Object[]> msgArguments;
Arbitrary context information.
/**
* Arbitrary context information.
*/
private Map<String, Object> context;
Simple constructor.
Params: - throwable – the exception this context refers too
/** Simple constructor.
* @param throwable the exception this context refers too
*/
public ExceptionContext(final Throwable throwable) {
this.throwable = throwable;
msgPatterns = new ArrayList<Localizable>();
msgArguments = new ArrayList<Object[]>();
context = new HashMap<String, Object>();
}
Get a reference to the exception to which the context relates.
Returns: a reference to the exception to which the context relates
/** Get a reference to the exception to which the context relates.
* @return a reference to the exception to which the context relates
*/
public Throwable getThrowable() {
return throwable;
}
Adds a message.
Params: - pattern – Message pattern.
- arguments – Values for replacing the placeholders in the message
pattern.
/**
* Adds a message.
*
* @param pattern Message pattern.
* @param arguments Values for replacing the placeholders in the message
* pattern.
*/
public void addMessage(Localizable pattern,
Object ... arguments) {
msgPatterns.add(pattern);
msgArguments.add(ArgUtils.flatten(arguments));
}
Sets the context (key, value) pair.
Keys are assumed to be unique within an instance. If the same key is
assigned a new value, the previous one will be lost.
Params: - key – Context key (not null).
- value – Context value.
/**
* Sets the context (key, value) pair.
* Keys are assumed to be unique within an instance. If the same key is
* assigned a new value, the previous one will be lost.
*
* @param key Context key (not null).
* @param value Context value.
*/
public void setValue(String key, Object value) {
context.put(key, value);
}
Gets the value associated to the given context key.
Params: - key – Context key.
Returns: the context value or null
if the key does not exist.
/**
* Gets the value associated to the given context key.
*
* @param key Context key.
* @return the context value or {@code null} if the key does not exist.
*/
public Object getValue(String key) {
return context.get(key);
}
Gets all the keys stored in the exception
Returns: the set of keys.
/**
* Gets all the keys stored in the exception
*
* @return the set of keys.
*/
public Set<String> getKeys() {
return context.keySet();
}
Gets the default message.
Returns: the message.
/**
* Gets the default message.
*
* @return the message.
*/
public String getMessage() {
return getMessage(Locale.US);
}
Gets the message in the default locale.
Returns: the localized message.
/**
* Gets the message in the default locale.
*
* @return the localized message.
*/
public String getLocalizedMessage() {
return getMessage(Locale.getDefault());
}
Gets the message in a specified locale.
Params: - locale – Locale in which the message should be translated.
Returns: the localized message.
/**
* Gets the message in a specified locale.
*
* @param locale Locale in which the message should be translated.
* @return the localized message.
*/
public String getMessage(final Locale locale) {
return buildMessage(locale, ": ");
}
Gets the message in a specified locale.
Params: - locale – Locale in which the message should be translated.
- separator – Separator inserted between the message parts.
Returns: the localized message.
/**
* Gets the message in a specified locale.
*
* @param locale Locale in which the message should be translated.
* @param separator Separator inserted between the message parts.
* @return the localized message.
*/
public String getMessage(final Locale locale,
final String separator) {
return buildMessage(locale, separator);
}
Builds a message string.
Params: - locale – Locale in which the message should be translated.
- separator – Message separator.
Returns: a localized message string.
/**
* Builds a message string.
*
* @param locale Locale in which the message should be translated.
* @param separator Message separator.
* @return a localized message string.
*/
private String buildMessage(Locale locale,
String separator) {
final StringBuilder sb = new StringBuilder();
int count = 0;
final int len = msgPatterns.size();
for (int i = 0; i < len; i++) {
final Localizable pat = msgPatterns.get(i);
final Object[] args = msgArguments.get(i);
final MessageFormat fmt = new MessageFormat(pat.getLocalizedString(locale),
locale);
sb.append(fmt.format(args));
if (++count < len) {
// Add a separator if there are other messages.
sb.append(separator);
}
}
return sb.toString();
}
Serialize this object to the given stream.
Params: - out – Stream.
Throws: - IOException – This should never happen.
/**
* Serialize this object to the given stream.
*
* @param out Stream.
* @throws IOException This should never happen.
*/
private void writeObject(ObjectOutputStream out)
throws IOException {
out.writeObject(throwable);
serializeMessages(out);
serializeContext(out);
}
Deserialize this object from the given stream.
Params: - in – Stream.
Throws: - IOException – This should never happen.
- ClassNotFoundException – This should never happen.
/**
* Deserialize this object from the given stream.
*
* @param in Stream.
* @throws IOException This should never happen.
* @throws ClassNotFoundException This should never happen.
*/
private void readObject(ObjectInputStream in)
throws IOException,
ClassNotFoundException {
throwable = (Throwable) in.readObject();
deSerializeMessages(in);
deSerializeContext(in);
}
Serialize msgPatterns
and msgArguments
. Params: - out – Stream.
Throws: - IOException – This should never happen.
/**
* Serialize {@link #msgPatterns} and {@link #msgArguments}.
*
* @param out Stream.
* @throws IOException This should never happen.
*/
private void serializeMessages(ObjectOutputStream out)
throws IOException {
// Step 1.
final int len = msgPatterns.size();
out.writeInt(len);
// Step 2.
for (int i = 0; i < len; i++) {
final Localizable pat = msgPatterns.get(i);
// Step 3.
out.writeObject(pat);
final Object[] args = msgArguments.get(i);
final int aLen = args.length;
// Step 4.
out.writeInt(aLen);
for (int j = 0; j < aLen; j++) {
if (args[j] instanceof Serializable) {
// Step 5a.
out.writeObject(args[j]);
} else {
// Step 5b.
out.writeObject(nonSerializableReplacement(args[j]));
}
}
}
}
Deserialize msgPatterns
and msgArguments
. Params: - in – Stream.
Throws: - IOException – This should never happen.
- ClassNotFoundException – This should never happen.
/**
* Deserialize {@link #msgPatterns} and {@link #msgArguments}.
*
* @param in Stream.
* @throws IOException This should never happen.
* @throws ClassNotFoundException This should never happen.
*/
private void deSerializeMessages(ObjectInputStream in)
throws IOException,
ClassNotFoundException {
// Step 1.
final int len = in.readInt();
msgPatterns = new ArrayList<Localizable>(len);
msgArguments = new ArrayList<Object[]>(len);
// Step 2.
for (int i = 0; i < len; i++) {
// Step 3.
final Localizable pat = (Localizable) in.readObject();
msgPatterns.add(pat);
// Step 4.
final int aLen = in.readInt();
final Object[] args = new Object[aLen];
for (int j = 0; j < aLen; j++) {
// Step 5.
args[j] = in.readObject();
}
msgArguments.add(args);
}
}
Serialize context
. Params: - out – Stream.
Throws: - IOException – This should never happen.
/**
* Serialize {@link #context}.
*
* @param out Stream.
* @throws IOException This should never happen.
*/
private void serializeContext(ObjectOutputStream out)
throws IOException {
// Step 1.
final int len = context.size();
out.writeInt(len);
for (Map.Entry<String, Object> entry : context.entrySet()) {
// Step 2.
out.writeObject(entry.getKey());
final Object value = entry.getValue();
if (value instanceof Serializable) {
// Step 3a.
out.writeObject(value);
} else {
// Step 3b.
out.writeObject(nonSerializableReplacement(value));
}
}
}
Deserialize context
. Params: - in – Stream.
Throws: - IOException – This should never happen.
- ClassNotFoundException – This should never happen.
/**
* Deserialize {@link #context}.
*
* @param in Stream.
* @throws IOException This should never happen.
* @throws ClassNotFoundException This should never happen.
*/
private void deSerializeContext(ObjectInputStream in)
throws IOException,
ClassNotFoundException {
// Step 1.
final int len = in.readInt();
context = new HashMap<String, Object>();
for (int i = 0; i < len; i++) {
// Step 2.
final String key = (String) in.readObject();
// Step 3.
final Object value = in.readObject();
context.put(key, value);
}
}
Replaces a non-serializable object with an error message string.
Params: - obj – Object that does not implement the
Serializable
interface.
Returns: a string that mentions which class could not be serialized.
/**
* Replaces a non-serializable object with an error message string.
*
* @param obj Object that does not implement the {@code Serializable}
* interface.
* @return a string that mentions which class could not be serialized.
*/
private String nonSerializableReplacement(Object obj) {
return "[Object could not be serialized: " + obj.getClass().getName() + "]";
}
}