UserException.java
// Copyright (c) ZeroC, Inc.
package com.zeroc.Ice;
import java.io.PrintWriter;
import java.io.StringWriter;
import java.util.IdentityHashMap;
import java.util.Iterator;
import java.util.Map;
/** Base class for exceptions defined in Slice. */
public abstract class UserException extends java.lang.Exception {
/**
* Returns the type id of this exception.
*
* @return The type id of this exception.
*/
public abstract String ice_id();
/**
* Returns a string representation of this exception.
*
* @return A string representation of this exception.
*/
@Override
public String toString() {
var sw = new StringWriter();
var pw = new PrintWriter(sw);
var out = new OutputBase(pw);
out.setUseTab(false);
out.print(getClass().getName());
out.inc();
ExceptionWriter.write(this, out);
pw.flush();
return sw.toString();
}
/**
* Marshals this exception into an output stream.
*
* @param os the output stream to marshal into
* @hidden
*/
public void _write(OutputStream os) {
os.startException();
_writeImpl(os);
os.endException();
}
/**
* Unmarshals a {@code UserException} from an input stream into this exception.
*
* @param is the input stream to unmarshal from
* @hidden
*/
public void _read(InputStream is) {
is.startException();
_readImpl(is);
is.endException();
}
/**
* Returns {@code true} if this exception holds classes, {@code false} otherwise.
*
* @return {@code true} if this exception holds classes, {@code false} otherwise
* @hidden
*/
public boolean _usesClasses() {
return false;
}
/**
* Marshal this exception's fields into an output stream.
*
* @param os the output stream to marshal into
* @hidden
*/
protected abstract void _writeImpl(OutputStream os);
/**
* Unmarshal this exception's fields from an input stream.
*
* @param is the input stream to unmarshal from
* @hidden
*/
protected abstract void _readImpl(InputStream is);
private final class ExceptionWriter {
public static void write(java.lang.Object obj, OutputBase out) {
writeValue(null, obj, null, out);
}
private static void writeValue(
String name,
java.lang.Object value,
Map<java.lang.Object, java.lang.Object> objectTable,
OutputBase out) {
if (value == null) {
writeName(name, out);
out.print("(null)");
} else {
Class<?> c = value.getClass();
if (c.equals(Byte.class)
|| c.equals(Short.class)
|| c.equals(Integer.class)
|| c.equals(Long.class)
|| c.equals(Double.class)
|| c.equals(Float.class)
|| c.equals(Boolean.class)) {
writeName(name, out);
out.print(value.toString());
} else if (c.equals(String.class)) {
//
// Indent the lines of a string value.
//
writeName(name, out);
out.print("\"");
out.useCurrentPosAsIndent();
String str = value.toString();
int start = 0, pos;
while (start < str.length() && (pos = str.indexOf('\n', start)) != -1) {
out.print(str.substring(start, pos));
out.nl();
start = pos + 1;
}
if (start < str.length()) {
out.print(str.substring(start));
}
out.print("\"");
out.restoreIndent();
} else if (c.isArray()) {
int n = java.lang.reflect.Array.getLength(value);
for (int i = 0; i < n; i++) {
String elem = name != null ? name : "";
elem += "[" + i + "]";
writeValue(elem, java.lang.reflect.Array.get(value, i), objectTable, out);
}
} else if (value instanceof Map) {
Map<?, ?> map = (Map<?, ?>) value;
Iterator<?> i = map.entrySet().iterator();
while (i.hasNext()) {
Map.Entry<?, ?> entry = (Map.Entry<?, ?>) i.next();
String elem = name != null ? name + "." : "";
writeValue(elem + "key", entry.getKey(), objectTable, out);
writeValue(elem + "value", entry.getValue(), objectTable, out);
}
} else if (value instanceof _ObjectPrxI) {
writeName(name, out);
_ObjectPrxI proxy = (_ObjectPrxI) value;
out.print(proxy._getReference().toString());
} else if (value instanceof Value) {
//
// Check for recursion.
//
if (objectTable != null && objectTable.containsKey(value)) {
writeName(name, out);
out.print("(recursive)");
} else {
if (objectTable == null) {
objectTable = new IdentityHashMap<java.lang.Object, java.lang.Object>();
}
objectTable.put(value, null);
writeFields(name, value, c, objectTable, out);
}
} else if (value instanceof java.lang.Enum) {
writeName(name, out);
out.print(((java.lang.Enum<?>) value).name());
} else {
//
// Must be struct.
//
writeFields(name, value, c, objectTable, out);
}
}
}
private static void writeFields(
String name,
java.lang.Object obj,
Class<?> c,
Map<java.lang.Object, java.lang.Object> objectTable,
OutputBase out) {
if (!c.equals(java.lang.Object.class)) {
//
// Write the superclass first.
//
writeFields(name, obj, c.getSuperclass(), objectTable, out);
//
// Write the declared fields of the given class. We prefer to use the declared
// fields because it includes protected fields that may have been defined using the
// Slice "protected" metadata. However, if a security manager prevents us from
// obtaining the declared fields, we will fall back to using the public ones.
//
java.lang.reflect.Field[] fields = null;
try {
fields = c.getDeclaredFields();
} catch (java.lang.SecurityException ex) {
try {
fields = c.getFields();
} catch (java.lang.SecurityException e) {
return; // Nothing else we can do.
}
}
assert (fields != null);
for (java.lang.reflect.Field field : fields) {
//
// Only write public, non-static fields.
//
int mods = field.getModifiers();
if (java.lang.reflect.Modifier.isPublic(mods)
&& !java.lang.reflect.Modifier.isStatic(mods)) {
String fieldName =
name != null ? name + '.' + field.getName() : field.getName();
try {
java.lang.Object value = field.get(obj);
writeValue(fieldName, value, objectTable, out);
} catch (IllegalAccessException ex) {
assert false;
}
}
}
}
}
private static void writeName(String name, OutputBase out) {
if (name != null) {
out.nl();
out.print(name + " = ");
}
}
private ExceptionWriter() {}
}
private static final long serialVersionUID = 0L;
}